[Zope-CVS] CVS: Products/PageDesign - IClipboardSource.py:1.1 IClipboardTarget.py:1.1 IIndexedSlot.py:1.1 IPageElement.py:1.1 ISlot.py:1.1 ISlotProvider.py:1.1 Slot.py:1.1 SlotElementClipboardSource.py:1.1 SlotElementClipboardTarget.py:1.1 SlotElementTraverser.py:1.1 SlotNameCollector.py:1.1 SlotProvider.py:1.1 newnotes.txt:1.1 PageDesign.py:1.2.2.1
Shane Hathaway
shane@cvs.zope.org
Sat, 3 Aug 2002 15:46:10 -0400
Update of /cvs-repository/Products/PageDesign
In directory cvs.zope.org:/tmp/cvs-serv4789
Modified Files:
Tag: page-redesign-branch
PageDesign.py
Added Files:
IClipboardSource.py IClipboardTarget.py IIndexedSlot.py
IPageElement.py ISlot.py ISlotProvider.py Slot.py
SlotElementClipboardSource.py SlotElementClipboardTarget.py
SlotElementTraverser.py SlotNameCollector.py SlotProvider.py
newnotes.txt
Log Message:
Designed some interfaces to break up responsibilities.
Made it possible to use both single-item and multiple-item slots.
Started thinking about integrating External Editor.
(Note that this is just a checkpoint.)
=== Added File Products/PageDesign/IClipboardSource.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from Interface import Interface
class IClipboardSource(Interface):
def cut():
"""Removes this item from its container and returns the element."""
#def copy():
# """Belongs here too but I don't need it yet. ;-)"""
=== Added File Products/PageDesign/IClipboardTarget.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from Interface import Interface
class IClipboardTarget(Interface):
def paste(elements):
"""Adds the given elements to the container."""
=== Added File Products/PageDesign/IIndexedSlot.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from ISlot import ISlot
class IIndexedSlot(ISlot):
def getElementCount():
"""
"""
def getElement(index):
"""
"""
def insertBefore(before_element, elements):
"""
"""
def remove(element):
"""Removes an element and returns the element removed.
"""
=== Added File Products/PageDesign/IPageElement.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from Interface import Interface
class IPageElement (Interface):
def render(design, editable, index):
"""Returns a string.
"""
def getTitle():
"""Returns the title of this element.
"""
def getEditURL():
"""Returns the URL for editing this element.
Returns None or a blank string if it is not editable.
"""
=== Added File Products/PageDesign/ISlot.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from Interface import Interface
class ISlot (Interface):
def single():
"""Renders as a single-element slot."""
def multiple():
"""Renders as a multiple-element slot."""
=== Added File Products/PageDesign/ISlotProvider.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from Interface import Interface
class ISlotProvider (Interface):
"""The aq_parent should be the page design object."""
def __getitem__(name):
"""Returns an object that implements ISlot.
The slot might be created on the fly and not stored.
"""
def _makeSlot(name):
"""Creates a slot if it doesn't exist.
Returns the slot object.
"""
def _isEditable():
"""
"""
def _getLayeredProvider():
"""
"""
=== Added File Products/PageDesign/Slot.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from Persistence import Persistent
import Acquisition
from Acquisition import aq_inner, aq_parent
from OFS.Traversable import Traversable
from IIndexedSlot import IIndexedSlot
from IPageElement import IPageElement
from SlotElementClipboardTarget \
import SlotElementClipboardTarget, SlotElementClipboardLastTarget
class Slot (Persistent, Acquisition.Explicit, Traversable):
"""Slot in a page design.
"""
__implements__ = IIndexedSlot
# Traversal helpers.
elementSources = SlotElementTraverser('elementSources',
SlotElementClipboardSource)
elementTargets = SlotElementTraverser('elementTargets',
SlotElementClipboardTarget)
lastElementTarget = SlotElementClipboardLastTarget
def __init__(self, id):
self.id = id
self.contents = ()
def getId(self):
return self.id
def single(self):
"""Renders as a single-element slot."""
allow_add = (not self.contents)
res = self.renderToList(allow_add)
if not res:
layered_provider = aq_parent(aq_inner(self))._getLayeredProvider()
if layered_provider is not None:
# A higher layer is using the design holding this slot
# as a template.
# Since the slot is empty, let the higher layer supply it.
return layered_provider[self.id].single()
return ''.join(res)
def multiple(self):
"""Renders as a multiple-element slot."""
res = self.renderToList(1)
layered_provider = aq_parent(aq_inner(self))._getLayeredProvider()
if layered_provider is not None:
# A higher layer is using the design holding this slot
# as a template.
# Allow the higher layer to supply text before and after.
before = layered_provider[self.id + '_before'].multiple()
after = layered_provider[self.id + '_after'].multiple()
res = before + res + after
return res
def renderToList(self, allow_add):
"""Renders the items to a list."""
sp = self.aq_parent
design = sp.aq_parent
editable = sp._isEditable()
res = []
phys_path = '/'.join(self.getPhysicalPath())
for index in range(len(self.contents)):
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,
})
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,
}
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,
})
return res
def getElementCount(self):
return len(self.contents)
def getElement(self, index):
return self.contents[index]
def insertBefore(self, before_element, elements):
# Verify none of the elements are already inserted.
# An element can only be in one place at a time.
for e in elements:
if not IPageElement.isImplementedBy(e):
raise ValueError, 'Not a page element'
if e in self.contents:
raise ValueError, 'Already inserted'
if before_element is None:
# append.
self.contents = self.contents + tuple(elements)
else:
index = list(self.contents).index(before_element)
self.contents = (self.contents[:index] + tuple(elements)
+ self.contents[index:])
def remove(self, element):
lst = list(self.contents)
lst.remove(element)
self.contents = tuple(lst)
=== Added File Products/PageDesign/SlotElementClipboardSource.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import Acquisition
from Acquisition import aq_base, aq_inner, aq_parent
from IClipboardSource import IClipboardSource
from IIndexedSlot import IIndexedSlot
class SlotElementClipboardSource (Acquisition.Explicit):
__implements__ = IClipboardSource
def __init__(self, index):
index = int(index)
slot = aq_parent(aq_inner(self))
assert IIndexedSlot.isImplementedBy(slot)
self.element = slot.getElement(index)
def cut(self):
slot = aq_parent(aq_inner(self))
assert IIndexedSlot.isImplementedBy(slot)
element = aq_base(self.element)
slot.remove(element)
return element
=== Added File Products/PageDesign/SlotElementClipboardTarget.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import Acquisition
from Acquisition import aq_base, aq_inner, aq_parent
from IClipboardTarget import IClipboardTarget
class SlotElementClipboardTarget (Acquisition.Explicit):
__implements__ = IClipboardTarget
def __init__(self, index):
index = int(index)
slot = aq_parent(aq_inner(self))
self.before_element = slot.getElement(index)
def paste(self, elements):
slot = aq_parent(aq_inner(self))
slot.insertBefore(aq_base(self.before_element), elements)
class SlotElementClipboardLastTarget (Acquisition.Explicit):
__implements__ = IClipboardTarget
def paste(self, elements):
slot = aq_parent(aq_inner(self))
slot.insertBefore(None, elements)
=== Added File Products/PageDesign/SlotElementTraverser.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from OFS.Traversable import Traversable
class SlotElementTraverser (Acquisition.Explicit, Traversable):
def __init__(self, id, item_factory):
self.id = id
self.item_factory = item_factory
def getId(self):
return self.id
def __getitem__(self, name):
return self.item_factory(name).__of__(self)
=== Added File Products/PageDesign/SlotNameCollector.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import Acquisition
from AccessControl import ClassSecurityInfo
class MockSlot:
__implements__ = ISlot
def single(self):
return ''
def multiple(self):
return ()
mock_slot = MockSlot()
class SlotNameCollector (Acquisition.Explicit):
__implements__ = ISlotProvider
security = ClassSecurityInfo()
security.setDefaultAccess('allow')
def __init__(self):
self._names = {}
def __getitem__(self, name):
self._names[name] = 1
return mock_slot
def _makeSlot(self, name):
return self[name]
def _getNames(self):
return self._names
def _isEditable(self):
return 0
def _getLayeredProvider():
return None
=== Added File Products/PageDesign/SlotProvider.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import Acquisition
from AccessControl import ClassSecurityInfo
from OFS.Traversable import Traversable
class SlotProvider (Acquisition.Explicit, Traversable):
__implements__ = ISlotProvider
security = ClassSecurityInfo()
security.setDefaultAccess('allow')
id = 'slots'
def __init__(self, editable=0, layered_provider=None):
self._editable = editable
self._layered_provider = layered_provider
def getId(self):
return self.id
def _makeSlot(self, name):
self.__getitem__(name, 1)
def __getitem__(self, name, add=0):
slots = self.aq_parent._slots
slot = slots.get(name)
if slot is None:
slot = Slot()
if add:
slots[name] = slot
return slot.__of__(self)
def _isEditable(self):
return self._editable
def _getLayeredProvider():
return self._layered_provider
=== Added File Products/PageDesign/newnotes.txt ===
element id:
/folder/design/slots/top/elementSources/0
/folder/palette/foo
target id:
/folder/design/slots/bottom/elementTargets/2
/folder/design/slots/bottom/elementTargets/3 (last)
Palettes let you add either references to existing items or new items
(storing a reference to the local item).
You can use a page design as a page template macro:
metal:use-macro="here/design/macro"
"macro" returns a tuple (generated on the fly) with pre-rendered content.
The bar above each page element contains:
Title
Pencil (for external editor)
Move up
Move down
Close (X)
Show the "+" sign for empty slots so it works in NS4.
Verify ahead of time:
- Does Konqueror support external JS?
Change UI:
- Don't make outlines when floating over an item.
Default palette lets you browse the tree?
Management Tabs:
Design
Local page elements
(Folder stuff)
=== Products/PageDesign/PageDesign.py 1.2 => 1.2.2.1 ===
# Permission name
change_page_designs = 'Change Page Designs'
-# Constant until the right policy can be chosen.
-INDEPENDENT_TARGETS = 1
-
_www = os.path.join(os.path.dirname(__file__), 'www')
@@ -52,71 +49,20 @@
"""Error in page design"""
-class AreaRenderer:
-
- security = ClassSecurityInfo()
- security.setDefaultAccess('allow')
-
- def __init__(self, design, editable, layered_areas):
- self._design = design
- self._editable = editable
- # layered_areas is not None when a page design uses another page
- # design as its template.
- self._layered_areas = layered_areas
-
- def __getitem__(self, name):
- res = ()
- try:
- res = self._design.renderArea(name, self._editable)
- if not res:
- # If the area is empty, allow it to be filled by the
- # page design that's using this design as a template.
- # This is just one way to use page designs as templates.
- la = self._layered_areas
- if la is not None:
- res = la[name]
- except:
- if self._editable:
- t, v = sys.exc_info()[:2]
- res = [escape('Unable to render area "%s". %s: %s' % (
- name, getattr(t, '__name__', t), v))]
- return res
-
-Globals.InitializeClass(AreaRenderer)
-
-
-class AreaNameCollector:
-
- security = ClassSecurityInfo()
- security.setDefaultAccess('allow')
-
- def __init__(self):
- self._names = {}
-
- def __getitem__(self, name):
- self._names[name] = 1
- return ()
-
- def _getNames(self):
- return self._names
-
-Globals.InitializeClass(AreaNameCollector)
-
-
class PageDesignBase (Persistent):
"""Base class for page designs.
"""
# The idea is that the contents of this
- # folder is the "palette". _placement defines where the items go.
+ # folder is the "palette". _slots defines where the items go.
# Every item must be callable, accepting the "editable" and
# "index" keyword arguments.
security = ClassSecurityInfo()
- _placement = None # { area_name -> (element_id,) }
+ _slots = None # { slot_name -> (element_id,) }
manage_options = (
- {'label': 'Design', 'action': 'manage_areas'},
+ {'label': 'Design', 'action': 'manage_slots'},
)
security.declareProtected(change_page_designs, 'scripts_js')
@@ -125,8 +71,8 @@
security.declareProtected(change_page_designs, 'pagedesign_css')
pagedesign_css = RawFile('pagedesign.css', 'text/css', _www)
- security.declareProtected(change_page_designs, 'manage_areas')
- manage_areas = PageTemplateFile('areas.pt', _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)
@@ -179,175 +125,142 @@
_v_rendering = 0
+ slots = SlotProvider()
def __init__(self, id, title=''):
- self._placement = PersistentMapping()
+ self._slots = PersistentMapping()
self.id = id
if title:
self.title = title
-
- security.declarePrivate('listAvailableElementIds')
- def listAvailableElementIds(self):
- # To be overridden
- raise NotImplementedError
-
-
- security.declarePrivate('getElement')
- def getElement(self, element_id):
- # To be overridden
- raise NotImplementedError
-
-
security.declareProtected(change_page_designs, 'getTemplate')
def getTemplate(self):
# To be overridden
raise NotImplementedError
- security.declareProtected(change_page_designs, 'addArea')
- def addArea(self, name):
- """Creates an area if it doesn't already exist.
+ security.declareProtected(change_page_designs, 'addSlot')
+ def addSlot(self, name):
+ """Creates a slot if it doesn't already exist.
- If the area already exists, does nothing.
+ If the slot already exists, does nothing.
"""
- assert name
- name = str(name)
- if not self._placement.has_key(name):
- self._placement[name] = ()
+ self.slots._makeSlot(name)
- security.declareProtected(change_page_designs, 'delArea')
- def delArea(self, name):
- """Removes an area.
+ security.declareProtected(change_page_designs, 'delSlot')
+ def delSlot(self, name):
+ """Removes a slot.
"""
- del self._placement[name]
+ del self._slots[name]
security.declareProtected(change_page_designs, 'moveElement')
- def moveElement(self, source_info, target_info, RESPONSE=None):
- """Changes an element's placement.
+ def moveElement(self, source_path, target_path, RESPONSE=None):
+ """Adds or moves an element to a slot.
"""
- s_area, s_data = str(source_info).split('/', 1)
- dummy, t_area, t_index = str(target_info).split('/', 2)
- assert dummy == 'targets'
-
- self._placement._p_changed = 1
- if t_area:
- t_index = int(t_index)
- if s_area:
- s_index = int(s_data)
- if t_area == s_area:
- # Adjust index if necessary.
- if s_index <= t_index:
- t_index -= 1
- element_id = self._placement[s_area][s_index]
- del self._placement[s_area][s_index]
- else:
- # The user selected something from the palette.
- element_id = s_data
- if t_area:
- lst = self._placement.get(t_area)
- if not lst:
- lst = []
- self._placement[t_area] = lst
- lst.insert(t_index, element_id)
- # else the user moved the object to the palette.
+ if source_path:
+ source = self.getPhysicalRoot().restrictedTraverse(source_path)
+ if not IClipboardSource.isImplementedBy(source):
+ raise DesignError, 'Not a source'
+ getSecurityManager().validate(source, source,
+ 'cut', source.cut)
+ if target_path:
+ target = self.getPhysicalRoot().restrictedTraverse(target_path)
+ if not IClipboardTarget.isImplementedBy(target):
+ raise DesignError, 'Not a target'
+ getSecurityManager().validate(target, target,
+ 'paste', target.paste)
+
+ if source is not None:
+ element = source.cut()
+ if target is not None:
+ target.paste([element])
+
if RESPONSE is not None:
RESPONSE.redirect(self.absolute_url() + '/manage_editForm')
- security.declareProtected(change_page_designs, 'getAreaNames')
- def getAreaNames(self):
- """Returns the names of all areas filled and declared by the template.
+ security.declareProtected(change_page_designs, 'getSlotNames')
+ def getSlotNames(self):
+ """Returns the names of all slots filled and declared by the template.
"""
names = {}
template = self.getTemplate()
if template is not None:
- areas = AreaNameCollector()
- try:
- template(areas=areas)
- except:
- # Hopefully, this exception gets reported elsewhere.
- pass
- else:
- names = areas._getNames()
- for k in self._placement.keys():
+ slots = SlotNameCollector().__of__(self)
+ template(slots=slots)
+ names = slots._getNames()
+ for k in self._slots.keys():
names[k] = 1
res = names.keys()
res.sort()
return res
- security.declarePrivate('renderArea')
- def renderArea(self, name, editable=0):
- """Returns a sequence of rendered items."""
- element_ids = self._placement.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:
- # Wrap the element.
- s = self.element_html % (name, index, s)
- if INDEPENDENT_TARGETS:
- # Make targets independent blocks.
- res.append(self.target_html % (name, index))
- else:
- # Targets are mixed into elements.
- s = (self.target_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('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('getPaletteHTML')
- def getPaletteHTML(self):
- unplaced = {}
- for element_id in self.listAvailableElementIds():
- unplaced[element_id] = 1
- for area in self._placement.values():
- for element_id in area:
- 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('insertScripts')
- def insertScripts(self, s):
+ security.declarePrivate('insertEditScripts')
+ def insertEditScripts(self, s):
match = start_of_head_search(s)
if match is None:
raise DesignError, 'The template needs a HEAD element'
@@ -371,7 +284,7 @@
security.declareProtected(change_page_designs, 'render')
- def render(self, editable=0, **kw):
+ def render(self, **kw):
"""Renders the design."""
if self._v_rendering:
raise DesignError, "Recursive page design rendering"
@@ -381,34 +294,38 @@
if template is None:
raise DesignError, (
'Template not set or not available')
- if kw.has_key('areas'):
+ ls = kw.get('slots')
+ if ls is not None and ISlotProvider.isImplementedBy(ls):
# This page design is being used as the template for another
- # page design. Use the layered areas.
- layered_areas = kw['areas']
+ # page design. Use the layered slots.
+ layered_slots = ls
else:
- layered_areas = None
- kw['areas'] = AreaRenderer(self, editable, layered_areas)
+ layered_slots = None
+
+ editable = kw.get('editable', 0)
+ sp = SlotProvider(editable, layered_slots).__of__(self)
+ kw['slots'] = sp
res = template(**kw)
if editable:
- res = self.insertScripts(res)
+ res = self.insertEditScripts(res)
return res
finally:
self._v_rendering = 0
- index_html = None # Use __call__
+ index_html = None # Instruct ZPublisher to use __call__
security.declareProtected(view, '__call__')
- def __call__(self, editable=0, **kw):
+ def __call__(self, **kw):
"""Renders the design in non-edit mode."""
- # Note that the editable argument is ignored on purpose.
- return self.render(0, **kw)
+ kw['editable'] = 0
+ return self.render(**kw)
- security.declareProtected(change_page_designs, 'manage_editForm')
- def manage_editForm(self, editable=1, **kw):
+ security.declareProtected(change_page_designs, 'editForm')
+ def editForm(self, **kw):
"""Renders the design in edit mode."""
- # Note that the editable argument is ignored on purpose.
- return self.render(1, **kw)
+ kw['editable'] = 1
+ return self.render(**kw)
Globals.InitializeClass(PageDesignBase)
@@ -447,8 +364,8 @@
def manage_propertiesForm(self, *args, **kw):
"""Object properties form
"""
- return self.manage_areas(*args, **kw)
-
+ return self.manage_slots(*args, **kw)
+
Globals.InitializeClass(PageDesign)