[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">
-    &nbsp; 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)