[Zope-CVS] CVS: Products/PageDesign - PageDesign.py:1.2.2.2 RawFile.py:1.1.1.1.2.1 Slot.py:1.1.2.2 SlotElementTraverser.py:1.1.2.2 SlotProvider.py:1.1.2.2
Shane Hathaway
shane@cvs.zope.org
Mon, 5 Aug 2002 21:28:28 -0400
Update of /cvs-repository/Products/PageDesign
In directory cvs.zope.org:/tmp/cvs-serv22348
Modified Files:
Tag: page-redesign-branch
PageDesign.py RawFile.py Slot.py SlotElementTraverser.py
SlotProvider.py
Log Message:
Fixed up enough to run again, but the Javascript and the palette aren't there
yet.
=== Products/PageDesign/PageDesign.py 1.2.2.1 => 1.2.2.2 ===
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from RawFile import RawFile
+from SlotProvider import SlotProvider
+from ISlotProvider import ISlotProvider
# Permission name
change_page_designs = 'Change Page Designs'
@@ -52,17 +54,12 @@
class PageDesignBase (Persistent):
"""Base class for page designs.
"""
- # The idea is that the contents of this
- # folder is the "palette". _slots defines where the items go.
- # Every item must be callable, accepting the "editable" and
- # "index" keyword arguments.
-
security = ClassSecurityInfo()
_slots = None # { slot_name -> (element_id,) }
manage_options = (
- {'label': 'Design', 'action': 'manage_slots'},
+ {'label': 'Design', 'action': 'manage_main'},
)
security.declareProtected(change_page_designs, 'scripts_js')
@@ -71,32 +68,20 @@
security.declareProtected(change_page_designs, 'pagedesign_css')
pagedesign_css = RawFile('pagedesign.css', 'text/css', _www)
- security.declareProtected(change_page_designs, 'manage_slots')
- manage_slots = PageTemplateFile('slots.pt', _www)
-
- security.declareProtected(change_page_designs, 'manage_designFrames')
- manage_designFrames = PageTemplateFile('designFrames.pt', _www)
-
- security.declareProtected(change_page_designs, 'manage_designTopFrame')
- manage_designTopFrame = PageTemplateFile('designTopFrame.pt', _www)
+ security.declareProtected(change_page_designs, 'manage_main')
+ manage_main = PageTemplateFile('main.pt', _www)
- target_html = '<div class="design-target" id="targets/%s/%s"></div>'
- element_html = '<div class="design-element" id="%s/%s">%s</div>'
-
- palette_element_html = '''
- <td class="design-element" id="/%s" align="center" valign="top">
- <img src="%s" /><br />%s</td>
- '''
+ security.declareProtected(change_page_designs, 'designFrames')
+ designFrames = PageTemplateFile('designFrames.pt', _www)
- palette_elements_block = '''
- <table><tr>%s</tr></table>
- '''
+ security.declareProtected(change_page_designs, 'designTopFrame')
+ designTopFrame = PageTemplateFile('designTopFrame.pt', _www)
head_html = '''
<!-- Page design scripts and styles -->
<link type="text/css" href="%(url)s/pagedesign_css" rel="stylesheet" />
- <script type="text/javascript" src="%(url)s/scripts_js" />
<script type="text/javascript">
+ %(scripts)s
design_url = '%(url)s';
</script>
<!-- End page design scripts -->
@@ -104,19 +89,7 @@
footer_html = '''
<!-- Page design footer -->
- <div id="design-palette-window">
- <div id="design-palette-titlebar" onmousedown="dragWindow(event,
- document.getElementById('design-palette-window'));" align="left">
- Palette
- </div>
- <div id="design-palette-contents-box">
- <div id="design-palette-contents">
- %(palette)s
- </div>
- </div>
- </div>
<div id="design-move-box"></div>
-
<script type="text/javascript"><!--
initPageDesign();
// --></script>
@@ -178,7 +151,7 @@
target.paste([element])
if RESPONSE is not None:
- RESPONSE.redirect(self.absolute_url() + '/manage_editForm')
+ RESPONSE.redirect(self.absolute_url() + '/editForm')
security.declareProtected(change_page_designs, 'getSlotNames')
@@ -198,67 +171,6 @@
return res
-## security.declarePrivate('renderSlot')
-## def renderSlot(self, name, editable=0):
-## """Returns a sequence of rendered items."""
-## element_ids = self._slots.get(name, ())
-## res = []
-## for index in range(len(element_ids)):
-## s = None
-## element_id = element_ids[index]
-## try:
-## item = self.getElement(element_id)
-## # Render the item as a string.
-## if getattr(aq_base(item), 'isDocTemp', 0):
-## # DTML
-## s = item(self, self.REQUEST,
-## editable=editable, index=index)
-## else:
-## # Other kinds of callable objects
-## s = item(editable=editable, index=index)
-## except:
-## if editable:
-## t, v = sys.exc_info()[:2]
-## s = escape('Unable to render "%s". %s: %s' % (
-## element_id, getattr(t, '__name__', t), v))
-## if s is not None:
-## # Make sure it's a string or unicode.
-## s = '%s' % s
-## if editable:
-## s = (self.target_html % (name, index)) + (
-## self.element_html % (name, index, s))
-## res.append(s)
-## if editable:
-## # Add a final insertion point.
-## res.append(self.target_html % (name, len(element_ids)))
-## return res
-
-
-## security.declarePrivate('getPaletteHTML')
-## def getPaletteHTML(self):
-## unplaced = {}
-## for element_id in self.listAvailableElementIds():
-## unplaced[element_id] = 1
-## for slot in self._slots.values():
-## for element_id in slot:
-## if unplaced.has_key(element_id):
-## del unplaced[element_id]
-## ids = unplaced.keys()
-## ids.sort()
-## items_html = []
-## for element_id in ids:
-## element = self.getElement(element_id)
-## if hasattr(element, 'getIcon'):
-## icon = element.getIcon()
-## else:
-## icon = element.icon
-## items_html.append(self.palette_element_html % (
-## element_id, icon, element_id))
-
-## block = self.palette_elements_block % ''.join(items_html)
-## return block
-
-
security.declarePrivate('insertEditScripts')
def insertEditScripts(self, s):
match = start_of_head_search(s)
@@ -266,7 +178,8 @@
raise DesignError, 'The template needs a HEAD element'
index = match.end(0)
url = self.absolute_url()
- head_prefix = self.head_html % {'url': url}
+ head_prefix = self.head_html % {'url': url,
+ 'scripts': self.scripts_js()}
s = '%s%s%s' % (s[:index], head_prefix, s[index:])
match = end_of_body_search(s)
if match is None:
@@ -277,8 +190,8 @@
match = m
m = end_of_body_search(s, match.end(0))
index = match.start(0)
- palette = self.getPaletteHTML()
- footer = self.footer_html % {'palette': palette}
+ #palette = self.getPaletteHTML()
+ footer = self.footer_html #% {'palette': palette}
s = '%s%s%s' % (s[:index], footer, s[index:])
return s
@@ -361,10 +274,14 @@
return getattr(aq_parent(aq_inner(self)), id)
security.declareProtected(change_page_designs, 'manage_propertiesForm')
- def manage_propertiesForm(self, *args, **kw):
+ def manage_propertiesForm(self, client=None, REQUEST=None,
+ manage_tabs_message=None):
"""Object properties form
"""
- return self.manage_slots(*args, **kw)
+ if REQUEST is not None:
+ REQUEST['RESPONSE'].redirect(
+ self.absolute_url() + '/manage_main?manage_tabs_message=' +
+ manage_tabs_message)
Globals.InitializeClass(PageDesign)
=== Products/PageDesign/RawFile.py 1.1.1.1 => 1.1.1.1.2.1 ===
self.lmh = rfc1123_date(self.lmt)
- def index_html(self, REQUEST, RESPONSE):
+ def __call__(self, REQUEST=None, RESPONSE=None):
"""Default rendering"""
# HTTP If-Modified-Since header handling. This is duplicated
# from OFS.Image.Image - it really should be consolidated
# somewhere...
- RESPONSE.setHeader('Content-Type', self.content_type)
- RESPONSE.setHeader('Last-Modified', self.lmh)
- RESPONSE.setHeader('Cache-Control', self.cch)
- header = REQUEST.get_header('If-Modified-Since', None)
- if header is not None:
- header = header.split(';')[0]
- # Some proxies seem to send invalid date strings for this
- # header. If the date string is not valid, we ignore it
- # rather than raise an error to be generally consistent
- # with common servers such as Apache (which can usually
- # understand the screwy date string as a lucky side effect
- # of the way they parse it).
- try:
- mod_since = long(DateTime(header).timeTime())
- except:
- mod_since = None
- if mod_since is not None:
- if getattr(self, 'lmt', None):
- last_mod = long(self.lmt)
- else:
- last_mod = long(0)
- if last_mod > 0 and last_mod <= mod_since:
- RESPONSE.setStatus(304)
- return ''
+ if RESPONSE is not None:
+ RESPONSE.setHeader('Content-Type', self.content_type)
+ RESPONSE.setHeader('Last-Modified', self.lmh)
+ RESPONSE.setHeader('Cache-Control', self.cch)
+ if REQUEST is not None:
+ header = REQUEST.get_header('If-Modified-Since', None)
+ if header is not None:
+ header = header.split(';')[0]
+ # Some proxies seem to send invalid date strings for this
+ # header. If the date string is not valid, we ignore it
+ # rather than raise an error to be generally consistent
+ # with common servers such as Apache (which can usually
+ # understand the screwy date string as a lucky side effect
+ # of the way they parse it).
+ try:
+ mod_since = long(DateTime(header).timeTime())
+ except:
+ mod_since = None
+ if mod_since is not None:
+ if getattr(self, 'lmt', None):
+ last_mod = long(self.lmt)
+ else:
+ last_mod = long(0)
+ if last_mod > 0 and last_mod <= mod_since:
+ RESPONSE.setStatus(304)
+ return ''
f = open(self.path, 'rb')
data = f.read()
f.close()
return data
+ index_html = None # Tells ZPublisher to use __call__
+
HEAD__roles__ = None
def HEAD(self, REQUEST, RESPONSE):
""" """
RESPONSE.setHeader('Content-Type', self.content_type)
RESPONSE.setHeader('Last-Modified', self.lmh)
return ''
-
- def __len__(self):
- # This is bogus and needed because of the way Python tests truth.
- return 1
=== Products/PageDesign/Slot.py 1.1.2.1 => 1.1.2.2 ===
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
+"""Slots containing one or more page elements.
+$Id$
+"""
from Persistence import Persistent
import Acquisition
from Acquisition import aq_inner, aq_parent
+import Globals
+from AccessControl import ClassSecurityInfo
from OFS.Traversable import Traversable
from IIndexedSlot import IIndexedSlot
from IPageElement import IPageElement
+from SlotElementClipboardSource import SlotElementClipboardSource
from SlotElementClipboardTarget \
import SlotElementClipboardTarget, SlotElementClipboardLastTarget
+from SlotElementTraverser import SlotElementTraverser
class Slot (Persistent, Acquisition.Explicit, Traversable):
- """Slot in a page design.
+ """Slot in a page design that can contain either 1 element or a sequence.
+
+ When a template uses the 'single()' method, which returns a string,
+ the slot provides a UI for adding only one page element.
+
+ When a template uses the 'multiple()' method, which returns a list,
+ the slot provides a UI for adding multiple page elements. This allows
+ the template to have some control over the layout of multiple elements.
+
+ Slots designed using multiple() but later rendered with single() will
+ get all elements concatenated together in a string.
"""
__implements__ = IIndexedSlot
- # Traversal helpers.
+ security = ClassSecurityInfo()
+
+ # Traversal helpers for the clipboard.
elementSources = SlotElementTraverser('elementSources',
SlotElementClipboardSource)
elementTargets = SlotElementTraverser('elementTargets',
SlotElementClipboardTarget)
lastElementTarget = SlotElementClipboardLastTarget
+ target_html = '''<div class="design-target"
+ id="%(clipboard_path)s"><a href=""><img src="" /></a></div>'''
+
+ element_html = '''<div class="design-element"
+ id="%(clipboard_path)s">%(text)s</div>'''
+
def __init__(self, id):
self.id = id
@@ -47,6 +72,15 @@
return self.id
+ def renderTargetHTML(self, **kw):
+ return self.target_html % kw
+
+
+ def renderSourceHTML(self, **kw):
+ return self.element_html % kw
+
+
+ security.declarePublic('single')
def single(self):
"""Renders as a single-element slot."""
allow_add = (not self.contents)
@@ -61,6 +95,7 @@
return ''.join(res)
+ security.declarePublic('multiple')
def multiple(self):
"""Renders as a multiple-element slot."""
res = self.renderToList(1)
@@ -83,34 +118,37 @@
res = []
phys_path = '/'.join(self.getPhysicalPath())
- for index in range(len(self.contents)):
+ clen = len(self.contents)
+ for index in range(clen):
e = self.contents[index].__of__(self)
if editable and allow_add:
path = '%s/elementTargets/%d' % (phys_path, index)
- res.append(self.target_html % {
- 'slot_name': self.id,
- 'slot_index': index,
- 'path': path,
- })
+ res.append(self.renderTargetHTML(
+ clipboard_path=path,
+ slot_name=self.id,
+ slot_index=index,
+ ))
text = e.render(design=design, editable=editable, index=index)
if editable:
path = '%s/elementSources/%d' % (phys_path, index)
- text = self.element_html % {
- 'title': e.getTitle(),
- 'path': path,
- 'edit_url': e.getEditURL(),
- 'text': text,
- }
+ text = self.renderSourceHTML(
+ clipboard_path=path,
+ title=e.getTitle(),
+ text=text,
+ edit_url=e.getEditURL(),
+ can_move_down=(index < (clen - 1)),
+ can_move_up=(index > 0),
+ )
res.append(text)
if editable and allow_add:
path = '%s/lastElementTarget' % phys_path
- res.append(self.target_html % {
- 'slot_name': self.id,
- 'slot_index': -1,
- 'path': path,
- })
+ res.append(self.renderTargetHTML(
+ clipboard_path=path,
+ slot_name=self.id,
+ slot_index=-1,
+ ))
return res
@@ -142,3 +180,4 @@
lst.remove(element)
self.contents = tuple(lst)
+Globals.InitializeClass(Slot)
=== Products/PageDesign/SlotElementTraverser.py 1.1.2.1 => 1.1.2.2 ===
#
##############################################################################
+import Acquisition
from OFS.Traversable import Traversable
=== Products/PageDesign/SlotProvider.py 1.1.2.1 => 1.1.2.2 ===
##############################################################################
import Acquisition
+import Globals
from AccessControl import ClassSecurityInfo
from OFS.Traversable import Traversable
+from ISlotProvider import ISlotProvider
+from Slot import Slot
+
class SlotProvider (Acquisition.Explicit, Traversable):
@@ -40,7 +44,7 @@
slots = self.aq_parent._slots
slot = slots.get(name)
if slot is None:
- slot = Slot()
+ slot = Slot(name)
if add:
slots[name] = slot
return slot.__of__(self)
@@ -48,6 +52,7 @@
def _isEditable(self):
return self._editable
- def _getLayeredProvider():
+ def _getLayeredProvider(self):
return self._layered_provider
+Globals.InitializeClass(SlotProvider)