[Checkins] SVN: z3c.multiform/Sandbox/src/z3c/multiform/ - prepare MultiformBase for filter

Stefan Martin s.martin at iwm-kmrc.de
Thu Dec 7 09:53:24 EST 2006


Log message for revision 71478:
  - prepare MultiformBase for filter
  - add MultiformWidgets to handle different widgets for display and input
  - build usable containerviews like contents.html and index.html
  - separate Actions and Fields of containerviews
  - write test of containerviews

Changed:
  _U  z3c.multiform/Sandbox/src/z3c/multiform/
  U   z3c.multiform/Sandbox/src/z3c/multiform/README.txt
  U   z3c.multiform/Sandbox/src/z3c/multiform/TODO.txt
  U   z3c.multiform/Sandbox/src/z3c/multiform/actions.txt
  U   z3c.multiform/Sandbox/src/z3c/multiform/configure.zcml
  U   z3c.multiform/Sandbox/src/z3c/multiform/container/configure.zcml
  U   z3c.multiform/Sandbox/src/z3c/multiform/container/container.txt
  U   z3c.multiform/Sandbox/src/z3c/multiform/container/interfaces.py
  U   z3c.multiform/Sandbox/src/z3c/multiform/container/location.py
  U   z3c.multiform/Sandbox/src/z3c/multiform/container/tests.py
  U   z3c.multiform/Sandbox/src/z3c/multiform/container/views.py
  U   z3c.multiform/Sandbox/src/z3c/multiform/gridform.py
  U   z3c.multiform/Sandbox/src/z3c/multiform/gridform.txt
  U   z3c.multiform/Sandbox/src/z3c/multiform/interfaces.py
  U   z3c.multiform/Sandbox/src/z3c/multiform/multiform.py
  U   z3c.multiform/Sandbox/src/z3c/multiform/selection.py
  A   z3c.multiform/Sandbox/src/z3c/multiform/selection.txt
  D   z3c.multiform/Sandbox/src/z3c/multiform/selections.txt
  U   z3c.multiform/Sandbox/src/z3c/multiform/sort.py
  U   z3c.multiform/Sandbox/src/z3c/multiform/tests.py

-=-

Property changes on: z3c.multiform/Sandbox/src/z3c/multiform
___________________________________________________________________
Name: svn:ignore
   + 
.project


Modified: z3c.multiform/Sandbox/src/z3c/multiform/README.txt
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/README.txt	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/README.txt	2006-12-07 14:53:23 UTC (rev 71478)
@@ -7,12 +7,12 @@
 from the Form class of the formlib package.
 
     >>> from zope import interface, schema
-    >>> from zope.app.location.interfaces import ILocation
+    >>> from zope.location.interfaces import ILocation
 
     >>> class IOrder(interface.Interface):
     ...     identifier = schema.Int(title=u"Identifier", readonly=True)
     ...     name = schema.TextLine(title=u"Name")
-    >>> class Order:
+    >>> class Order(object):
     ...     interface.implements(IOrder,ILocation)
     ...
     ...     def __init__(self, identifier, name=''):
@@ -22,7 +22,6 @@
 
     >>> orderMapping = dict([(str(k),Order(k,name='n%s'%k)) for k in range(5)])
 
-
 Let us create a new multiform class which should display IOrder objects.
 
     >>> from zope.formlib import form
@@ -50,14 +49,13 @@
     ...             res += '<div>%s</div>\n' % self.subForms[name](
     ...             ignore_request=ignore_request)
     ...         return res
-    ...     
-
+    ...
     >>> from zope.publisher.browser import TestRequest
     >>> request = TestRequest()
     >>> view = OrdersForm(orderMapping, request)
     >>> print view()
     <div>
-    <div>0</div><div><input ... name="form.0.name" ... value="n0" ...</div>
+    <div>0</div><div><input ... name="form.sf.0.name" ... value="n0" ...</div>
     </div>
     <div>
     ...
@@ -66,11 +64,11 @@
 If the request contains any form data, that will be reflected in the
 output:
 
-    >>> request.form['form.1.name'] = u'bob'
+    >>> request.form['form.sf.1.name'] = u'bob'
     >>> print OrdersForm(orderMapping,request)()
     <div>
     ...
-    <div>1</div><div><input ... name="form.1.name" ... value="bob" ...</div>
+    <div>1</div><div><input ... name="form.sf.1.name" ... value="bob" ...</div>
     ...
     </div>
 
@@ -82,7 +80,7 @@
     >>> print OrdersForm(orderMapping, request)(ignore_request=True)
     <div>
     ...
-    <div>1</div><div><input ... name="form.1.name" ... value="n1" ...</div>
+    <div>1</div><div><input ... name="form.sf.1.name" ... value="n1" ...</div>
     ...
     </div>
 

Modified: z3c.multiform/Sandbox/src/z3c/multiform/TODO.txt
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/TODO.txt	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/TODO.txt	2006-12-07 14:53:23 UTC (rev 71478)
@@ -7,11 +7,6 @@
 Missing functionalities:
 ------------------------
 
-	- customwidget for container.interfaces.IMovableLocation['__name__']
-
-		Returns an inputwidget if an IInputWidget is needed and returns
-		an displaywidget if an IDisplayWidget is needed.
-	
 	- Size columns
 
 	    Enable to register a size information field (ISized has only IMethods).
@@ -36,5 +31,5 @@
 
 	- sort_down and sort_up gifs from the skin
 	
-		It would be a nice feature of a skin to provides these to icons
+		It would be a nice feature of a skin to provides these two icons
 

Modified: z3c.multiform/Sandbox/src/z3c/multiform/actions.txt
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/actions.txt	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/actions.txt	2006-12-07 14:53:23 UTC (rev 71478)
@@ -15,7 +15,7 @@
     >>> from zope.formlib import form
     >>> from zope.publisher.browser import TestRequest
     >>> from zope.app.form.interfaces import IInputWidget
-    >>> from zope.app.location.interfaces import ILocation
+    >>> from zope.location.interfaces import ILocation
     >>> from z3c.multiform import multiform
     >>> from z3c.multiform.multiform import ItemFormBase,MultiFormBase
     >>> from zope.app.i18n import ZopeMessageFactory as _
@@ -85,10 +85,10 @@
     >>> pf = OrdersForm(orderMapping,request)
     >>> print pf()
     <div>
-    <div>0</div><div>n0</div>...<input...name="form.n0.actions.upper"...
+    <div>0</div><div>n0</div>...<input...name="form.sf.n0.actions.upper"...
     </div>
     <div>
-    <div>1</div><div>n1</div>...<input...name="form.n1.actions.upper"...
+    <div>1</div><div>n1</div>...<input...name="form.sf.n1.actions.upper"...
     </div>
     <div><input...name="form.actions.edit"...</div>
 
@@ -127,8 +127,8 @@
     >>> request = TestRequest()
     >>> request.form['form.actions.save']=u''
     >>> for i in range(2):
-    ...     request.form['form.n%s.name' % i]='newer name %s' % i
-    ...     request.form['form.n%s.identifier' % i]= i
+    ...     request.form['form.sf.n%s.name' % i]='newer name %s' % i
+    ...     request.form['form.sf.n%s.identifier' % i]= i
     >>> pf =  OrdersForm(orderMapping,request)
     >>> result = pf()
 
@@ -161,8 +161,8 @@
     >>> request = TestRequest()
     >>> request.form['form.actions.cancel']=u''
     >>> for i in range(2):
-    ...     request.form['form.n%s.name' % i]='next name %s' % i
-    ...     request.form['form.n%s.identifier' % i]= i
+    ...     request.form['form.sf.n%s.name' % i]='next name %s' % i
+    ...     request.form['form.sf.n%s.identifier' % i]= i
     >>> pf =  OrdersForm(orderMapping,request)
     >>> result = pf()
 
@@ -186,7 +186,7 @@
 mapping.
 
     >>> request = TestRequest()
-    >>> request.form['form.n1.actions.upper']=u''
+    >>> request.form['form.sf.n1.actions.upper']=u''
     >>> pf =  OrdersForm(orderMapping,request)
     >>> result = pf()
     >>> print result

Modified: z3c.multiform/Sandbox/src/z3c/multiform/configure.zcml
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/configure.zcml	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/configure.zcml	2006-12-07 14:53:23 UTC (rev 71478)
@@ -3,24 +3,12 @@
            xmlns:i18n="http://namespaces.zope.org/i18n"
            i18n_domain="zope">
 
-  <adapter for="zope.app.location.interfaces.ILocation
-                zope.formlib.interfaces.IForm"
-           provides=".interfaces.IFormLocation"
-           factory=".selection.FormLocationProxy"
+  <adapter factory=".selection.FormLocationProxy"
            trusted="true"
            />
+  <adapter factory=".selection.FormLocationSelection" />
+  <adapter factory=".sort.SchemaSorter" />
 
-  <adapter for=".interfaces.IFormLocation"
-           provides=".interfaces.ISelection"
-           factory=".selection.FormLocationSelection"
-           />
-
-  <adapter for="zope.interface.Interface
-                zope.schema.interfaces.IField"
-           factory=".sort.SchemaSorter"
-           provides=".interfaces.ISorter"
-           />
-
   <!-- namedtemplate for IParentAction -->
   <adapter factory=".multiform.render_submit_button" name="render" />
  

Modified: z3c.multiform/Sandbox/src/z3c/multiform/container/configure.zcml
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/container/configure.zcml	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/container/configure.zcml	2006-12-07 14:53:23 UTC (rev 71478)
@@ -9,9 +9,7 @@
        permission="zope.View"
        class=".views.ContainerGridForm"/>
 
-  <zope:adapter for="zope.app.location.interfaces.ILocation"
-                factory=".location.MovableLocation"
-                provides=".interfaces.IMovableLocation"/>
+  <zope:adapter factory=".location.MovableLocation" />
  
 </configure>
 

Modified: z3c.multiform/Sandbox/src/z3c/multiform/container/container.txt
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/container/container.txt	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/container/container.txt	2006-12-07 14:53:23 UTC (rev 71478)
@@ -3,44 +3,245 @@
 =====================
 
 A container contents view implementation using multiform. This view
-provides cut, copy, paste, edit and save actions. Additionally the
-__name__ attribute of the items can be transparently changed.
+provides cut, copy, paste, delete, edit and save actions. Additionally
+the __name__ attribute of the items can be transparently changed.
 
-In order to test the behaviour of the ``ContainerGridForm`` we
-subclass it and override the template method.
+In order to test the behaviour of the ``ContainerGridForm`` and
+``ContainerItemForm`` we subclass these and override the template methods.
 
     >>> from zope import interface
     >>> from zope.publisher.browser import TestRequest
     >>> from zope.app.container.sample import SampleContainer
     >>> from zope.app.annotation.interfaces import IAttributeAnnotatable
-    >>> from zope.app.dublincore.interfaces import IZopeDublinCore
-    >>> from zope.app.dublincore.interfaces import IDCDescriptiveProperties
+    >>> from zope.dublincore.interfaces import IZopeDublinCore
+    >>> from zope.dublincore.interfaces import IDCDescriptiveProperties
     >>> from z3c.multiform.container.views import ContainerGridForm
-
+    >>> from z3c.multiform.container.views import ContainerItemForm
+    >>> from z3c.multiform.container import views
+    >>> from z3c.multiform.interfaces import ISelection
+    ...
+    >>> class ContainerItemTest(ContainerItemForm):
+    ...
+    ...     def template(self):
+    ...         return '\n<div>%s</div>\n' % '</div><div>'.join([w() for w in
+    ...     		self.widgets] + [action.render() for action in 
+    ...     		self.availableActions()])
+	
     >>> class ContainerTest(ContainerGridForm):
-    ...     actions = ContainerGridForm.actions.copy()
+    ...
     ...     def template(self):
     ...         res = u''
-    ...         forms = list(self.getForms())
-    ...         forms.sort(lambda x,y: cmp(x.prefix,y.prefix))
-    ...         for form in forms:
-    ...             res += '<div>%s</div>\n' % form.render()
+    ...         for error in self.errors:
+    ...             res += '<div>%s</div>\n' % error
+    ...         names = sorted(self.subForms.keys())
+    ...         for name in names:
+    ...             res += '<div>%s</div>\n' % self.subForms[name].render()
+    ...         for action in self.availableActions():
+    ...             res += '<div>%s</div>\n' % action.render()
+    ...         for action in self.availableSubActions():
+    ...             res += '<div>%s</div>\n' % action.render()
     ...         return res
+    ...
+    ...     def getAllAvailableActionsLabel(self):
+    ...         res = []
+    ...         for action in self.availableActions():
+    ...             res.append(action.label)
+    ...         for action in self.availableSubActions():
+    ...             res.append(action.label)
+    ...         return res
+    ...
+    ...     def getAllAvailableActions(self):
+    ...         res = {}
+    ...         for action in self.availableActions():
+    ...             res[action.label] = action.__name__
+    ...         for action in self.availableSubActions():
+    ...             res[action.label] = action.__name__
+    ...         return res
+    
+    >>> def getAvailableActions(view):
+    ...    return sorted([action.label for action in view.availableActions()])
 
+    >>> def getSelectionInfo(view):
+    ...    return [(n, ISelection(f.context).selected) for n, f in view.subForms.items()]
+    
+We need principals to test the clipboard.
+
+    >>> class DummyPrincipal(object):
+    ...
+    ...     def __init__(self, id):
+    ...        self.id = id
+
+    >>> from zope.app.folder import Folder, rootFolder
+    >>> root = rootFolder()
     >>> c = SampleContainer()
+    >>> root['base'] = c
     >>> for i in range(2):
     ...     o = SampleContainer()
     ...     interface.directlyProvides(o,IAttributeAnnotatable)
-    ...     c[u'name of %s' % i]=o
+    ...     c[u'item%s' % i]=o
 
+    >>> dobe = DummyPrincipal(u'dobe')
+    >>> stmartin = DummyPrincipal(u'stmartin')
+    >>> stmartin.id
+    u'stmartin'
+    
+First of all we get the default view
+
     >>> request = TestRequest()
+    >>> request.setPrincipal(dobe)
     >>> view = ContainerTest(c,request)
-    >>> print view()
-    <div...<td>name of 0</td>...<td>name of 1</td>...             
+    >>> x = view()
+    >>> view.getAllAvailableActionsLabel()
+    [u'container-cut-button', u'container-copy-button', u'container-delete-button', u'Edit']
+    >>> defaultActions = view.getAllAvailableActions()
+    >>> getSelectionInfo(view)
+    [(u'item0', False), (u'item1', False)]
 
+We mark item0 and click on edit
 
+    >>> request = TestRequest()
+    >>> request.setPrincipal(dobe)
+    >>> request.form['form.sf.item0.selected']=u'on'
+    >>> request.form['form.sf.item1.selected.used']=u''
+    >>> request.form['form.actions.edit']=u''
+    >>> view = ContainerTest(c,request)
+    >>> x = view()
+    >>> view.getAllAvailableActionsLabel()
+    [u'Cancel', u'Save']
+    >>> getSelectionInfo(view)
+    [(u'item0', True), (u'item1', False)]
+    >>> print x
+    <div>...<td><input...id="form.sf.item0.__name__"...
+    </div>
+    <div>...<td>...>item1<...</td>...
+    </div>
+    <div><input...value="Cancel".../></div>
+    <div><input...value="Save".../></div>
 
+Sorry, wrong item, cancel.
 
+    >>> request = TestRequest()
+    >>> request.setPrincipal(dobe)
+    >>> request.form['form.sf.item0.selected']=u'on'
+    >>> request.form['form.sf.item1.selected.used']=u''
+    >>> request.form['form.actions.cancel']=u''
+    >>> view = ContainerTest(c,request)
+    >>> x = view()
+    >>> view.getAllAvailableActionsLabel()
+    [u'container-cut-button', u'container-copy-button', u'container-delete-button', u'Edit']
 
+We mark item1, change the title and click on save.
+
+    >>> request = TestRequest()
+    >>> request.setPrincipal(dobe)
+    >>> request.form['form.sf.item0.selected.used']=u''
+    >>> request.form['form.sf.item1.selected']=u'on'
+    >>> request.form['form.actions.save']=u''
+    >>> request.form['form.sf.item1.__name__'] = 'item1'
+    >>> request.form['form.sf.item1.title'] = 'item1newtitle'
+    >>> view = ContainerTest(c,request)
+    >>> x = view()
+    >>> view.getAllAvailableActionsLabel()
+    [u'container-cut-button', u'container-copy-button', u'container-delete-button', u'Edit']
+    >>> getSelectionInfo(view)
+    [(u'item0', False), (u'item1', False)]
+    >>> print x
+    <div>...<td>...>item0<...</td><td></td><td></td>...
+    </div>
+    <div>...<td>...>item1<...</td><td>item1newtitle</td>...
+    </div>
+    <div><input type="submit"...
+    <div><input type="submit"...
+    <div><input type="submit"...
+    <div><input type="submit"...
+
+Next, we mark item0 and click on copy
+
+    >>> request = TestRequest()
+    >>> request.setPrincipal(dobe)
+    >>> request.form['form.sf.item0.selected']=u'on'
+    >>> request.form['form.sf.item1.selected.used']=u''
+    >>> request.form[defaultActions[u'container-copy-button']]=u''
+    >>> view = ContainerTest(c,request)
+    >>> x = view()
+    >>> view.getAllAvailableActionsLabel()
+    [u'container-paste-button', u'container-cut-button', u'container-copy-button', u'container-delete-button', u'Edit']
+    >>> defaultActions = view.getAllAvailableActions() 
+
+and paste it.
     
+    >>> request = TestRequest()
+    >>> request.setPrincipal(dobe)
+    >>> request.form['form.sf.item0.selected']=u'on'
+    >>> request.form['form.sf.item1.selected.used']=u''
+    >>> request.form[defaultActions['container-paste-button']]=u''
+    >>> view = ContainerTest(c,request)
+    >>> x = view()
 
+    >>> getSelectionInfo(view)
+    [(u'item0', True), (u'item1', False), (u'item0-2', False)]
+
+The name of the new item could be better:
+
+    >>> request = TestRequest()
+    >>> request.setPrincipal(dobe)
+    >>> request.form['form.sf.item0.selected']=u'on'
+    >>> request.form['form.sf.item1.selected']=u'on'
+    >>> request.form['form.sf.item0-2.selected.used']=u''
+    >>> request.form['form.sf.item0-2.__name__'] = u'item2'
+    >>> request.form['form.sf.item0-2.title'] = u''
+    >>> request.form['form.actions.save']=u''
+    >>> view = ContainerTest(c,request)
+    >>> x = view()
+    >>> print x
+    <div>...
+    </div>
+    <div>...
+        style:="background: red;"
+        title:="...Required input is missing...id="form.sf.item0-2.title"...
+    </div>
+    ...
+
+Required input in field title is missing, fill in a title and retry
+
+    >>> request = TestRequest()
+    >>> request.setPrincipal(dobe)
+    >>> request.form['form.sf.item0.selected']=u'on'
+    >>> request.form['form.sf.item1.selected']=u'on'
+    >>> request.form['form.sf.item0-2.selected']=u'on'
+    >>> request.form['form.sf.item0-2.__name__'] = u'item2'
+    >>> request.form['form.sf.item0-2.title'] = u'title'
+    >>> request.form['form.actions.save']=u''
+    >>> view = ContainerTest(c,request)
+    >>> x = view()
+    >>> getSelectionInfo(view)
+    [(u'item2', False), (u'item0', False), (u'item1', False)]
+
+We cut item2
+
+    >>> request = TestRequest()
+    >>> request.setPrincipal(dobe)
+    >>> request.form['form.sf.item2.selected']=u'on'
+    >>> request.form[defaultActions['container-cut-button']]=u''
+    >>> view = ContainerTest(c,request)
+    >>> x = view()
+
+And paste in item0
+
+    >>> request = TestRequest()
+    >>> request.setPrincipal(dobe)
+    >>> request.form[defaultActions['container-paste-button']]=u''
+    >>> view = ContainerTest(c['item0'],request)
+    >>> x = view()
+
+    >>> [key for key in c.keys()]
+    [u'item0', u'item1']
+
+    >>> [key for key in c['item0'].keys()]
+    [u'item2']
+
+    
+TODO:
+-----
+- different widgets for display and input mode
+- __name__ as link in displaymode

Modified: z3c.multiform/Sandbox/src/z3c/multiform/container/interfaces.py
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/container/interfaces.py	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/container/interfaces.py	2006-12-07 14:53:23 UTC (rev 71478)
@@ -1,6 +1,6 @@
 from zope import schema
 from zope.interface import Interface, Attribute
-from zope.app.location.interfaces import ILocation
+from zope.location.interfaces import ILocation
 
 
 class IMovableLocation(ILocation):

Modified: z3c.multiform/Sandbox/src/z3c/multiform/container/location.py
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/container/location.py	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/container/location.py	2006-12-07 14:53:23 UTC (rev 71478)
@@ -1,14 +1,17 @@
-from zope.interface import implements
+from zope import interface, component
+
 from zope.security.proxy import removeSecurityProxy
-from zope.app.copypastemove.interfaces import IContainerItemRenamer
+from zope.copypastemove.interfaces import IContainerItemRenamer
+from zope.location.interfaces import ILocation
 
 from z3c.multiform.interfaces import IFormLocation
-from interfaces import IMovableLocation
+from z3c.multiform.container.interfaces import IMovableLocation
 
 
 class MovableLocation(object):
 
-    implements(IMovableLocation)
+    interface.implements(IMovableLocation)
+    component.adapts(ILocation)
 
     def __init__(self,context):
         self.context = context

Modified: z3c.multiform/Sandbox/src/z3c/multiform/container/tests.py
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/container/tests.py	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/container/tests.py	2006-12-07 14:53:23 UTC (rev 71478)
@@ -7,16 +7,21 @@
 from zope.app.testing import setup
 import zope.schema.interfaces
 import zope.app.form.browser
+import zope.app.form.browser.exception
 import zope.publisher.interfaces.browser
 import zope.app.form.interfaces
-from zope.app.dublincore.annotatableadapter import ZDCAnnotatableAdapter
-from zope.app.dublincore.interfaces import IWriteZopeDublinCore
-from zope.app.annotation.interfaces import IAnnotatable
-from zope.app.location.interfaces import ILocation
+from zope.copypastemove import PrincipalClipboard, ObjectCopier, ObjectMover, ContainerItemRenamer
+from zope.app.principalannotation import PrincipalAnnotationUtility
+from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
+from zope.dublincore.annotatableadapter import ZDCAnnotatableAdapter
+from zope.dublincore.interfaces import IWriteZopeDublinCore
+from zope.annotation.interfaces import IAnnotatable
+from zope.annotation.interfaces import IAnnotations
+from zope.location.interfaces import ILocation
 from zope.formlib import form
 
-from z3c.multiform import gridform,multiform,selection
-from z3c.multiform.interfaces import IFormLocation,ISelection
+from z3c.multiform import gridform, multiform, selection
+from z3c.multiform.interfaces import IFormLocation, ISelection
 from interfaces import IMovableLocation
 
 
@@ -24,6 +29,14 @@
     setup.placefulSetUp()
 
     component.provideAdapter(
+        zope.app.form.browser.exception.WidgetInputErrorView,
+        [zope.app.form.interfaces.IWidgetInputError,
+         zope.publisher.interfaces.browser.IBrowserRequest,
+         ],
+        zope.app.form.browser.interfaces.IWidgetInputErrorView,
+        )
+      
+    component.provideAdapter(
         zope.app.form.browser.DatetimeDisplayWidget,
         [zope.schema.interfaces.IDatetime,
          zope.publisher.interfaces.browser.IBrowserRequest,
@@ -74,29 +87,21 @@
          ],
         zope.app.form.interfaces.IInputWidget,
         )
+    component.provideAdapter(selection.FormLocationProxy)
+    component.provideAdapter(selection.FormLocationSelection)
+    component.provideAdapter(location.MovableLocation)
+
     component.provideAdapter(
-        selection.FormLocationProxy,
-        [zope.app.location.interfaces.ILocation,
-         zope.formlib.interfaces.IForm
-         ],
-        IFormLocation
-        )
-    component.provideAdapter(
-        selection.FormLocationSelection,
-        [IFormLocation],
-        ISelection
-        )
-    component.provideAdapter(
-        location.MovableLocation,
-        [ILocation],
-        IMovableLocation
-        )
-    component.provideAdapter(
         ZDCAnnotatableAdapter,
         [IAnnotatable],
         IWriteZopeDublinCore
         )
-
+    component.provideAdapter(PrincipalClipboard)
+    component.provideAdapter(ObjectCopier)
+    component.provideAdapter(ObjectMover)
+    component.provideAdapter(ContainerItemRenamer)
+    component.provideUtility(PrincipalAnnotationUtility(),
+                             IPrincipalAnnotationUtility)
     
     component.provideAdapter(gridform.default_grid_template,
                              name="default")

Modified: z3c.multiform/Sandbox/src/z3c/multiform/container/views.py
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/container/views.py	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/container/views.py	2006-12-07 14:53:23 UTC (rev 71478)
@@ -1,20 +1,26 @@
+
 import datetime
 import pytz
+
+from zope import component
+
 from zope.interface.common import idatetime
 from zope.app.i18n import ZopeMessageFactory as _
 from zope.formlib import form
-from zope.app.dublincore.interfaces import IWriteZopeDublinCore
+from zope.dublincore.interfaces import IWriteZopeDublinCore
 from zope.app.pagetemplate import ViewPageTemplateFile
 from zope.event import notify
-from zope.app.event.objectevent import ObjectModifiedEvent
+from zope.lifecycleevent import ObjectModifiedEvent
 from zope.app import zapi
-from zope.app.copypastemove.interfaces import IPrincipalClipboard
-from zope.app.copypastemove.interfaces import IObjectCopier
-from zope.app.copypastemove.interfaces import IObjectMover
+from zope.copypastemove.interfaces import IPrincipalClipboard
+from zope.copypastemove.interfaces import IObjectCopier
+from zope.copypastemove.interfaces import IObjectMover
 from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
 from zope.app.container.interfaces import DuplicateIDError
+from zope.app.container.browser.contents import getPrincipalClipboard, getDCTitle
+from zope.app.form.browser import TextWidget, DisplayWidget
 from zope.security.interfaces import Unauthorized
-from zope.app.traversing.interfaces import TraversalError
+from zope.traversing.interfaces import TraversalError
 
 from z3c.multiform import multiform, gridform
 from z3c.multiform.interfaces import ISelection
@@ -96,64 +102,33 @@
     return False
 
 
-class ContainerItemForm(multiform.ItemFormBase):
+def condition_paste_action(form, action):
+    return hasClipboardContents(form, action)
+label_paste_action = _("container-paste-button")
 
-    inputMode=False
-    forceInput=['selected']
-    template = ViewPageTemplateFile('griditem.pt')
-    form_fields = form.Fields(ISelection['selected'],
-                              IMovableLocation['__name__'],
-                              IWriteZopeDublinCore['title'],
-                              IWriteZopeDublinCore['created'],
-                              IWriteZopeDublinCore['modified'],
-                        omit_readonly=False,render_context=True)
-    form_fields['created'].for_display=True
-    form_fields['modified'].for_display=True
+def condition_cut_action(form, action):
+    return multiform.allSubFormsDisplayMode(form, action)
+label_cut_action = _("container-cut-button")
 
+def condition_copy_action(form, action):
+    return multiform.allSubFormsDisplayMode(form, action)
+label_copy_action = _("container-copy-button")
+ 
+def condition_delete_action(form, action):
+    return multiform.allSubFormsDisplayMode(form, action)
+label_delete_action = _("container-delete-button")
 
-    @multiform.parentAction(_('Edit'),
-                            condition=multiform.allSubFormsDisplayMode)
-    def handle_edit_action(self, action, data):
-        #print "handle_edit_action",action,data,isSelected(self,action)
-        if isSelected(self,action):
-            self.newInputMode = True
+def condition_cancel_action(form, action):
+    return multiform.anySubFormInputMode(form, action)
+label_cancel_action = _('Cancel')
 
-    @multiform.parentAction(_("Save"), inputMode=True,
-                            condition=multiform.anySubFormInputMode)
-    def handle_save_action(self, action, data):
 
-        if not isSelected(self,action):
-            return
-        if form.applyChanges(self.context, self.form_fields,
-                             data, self.adapters):
-            notify(ObjectModifiedEvent(self.context))
-            formatter = self.request.locale.dates.getFormatter(
-                'dateTime', 'medium')
-            try:
-                time_zone = idatetime.ITZInfo(self.request)
-            except TypeError:
-                time_zone = pytz.UTC
-            m = {'date_time':formatter.format(datetime.datetime.now(time_zone))}
-            self.status = (_("Updated on ${date_time}", mapping=m),)
-        else:
-            self.status = (_('No changes'),)
-        ISelection(self.context).selected=False
-        self.newInputMode = False
-       
-
-class ContainerGridForm(multiform.MultiFormBase):
-
-    itemFormFactory=ContainerItemForm
-
-    template = ViewPageTemplateFile('grid.pt')
-
-    @form.action(_('Cancel'),condition=multiform.anySubFormInputMode)
+class ContainerActions(object):
+    
     def handle_cancel_action(self, action, data):
         for form in self.subForms.values():
             form.newInputMode = False
 
-    @form.action(_("container-paste-button"),
-                 condition=hasClipboardContents)
     def handle_paste_action(self, action, data):
         """Paste ojects in the user clipboard to the container"""
         self.form_reset = True
@@ -201,8 +176,6 @@
                 _("The given name(s) %s is / are already being used" %(
                 str(not_pasteable_ids))),)
 
-    @form.action(_("container-cut-button"),
-                 condition=multiform.allSubFormsDisplayMode)
     def handle_cut_action(self, action, data):
         """move objects specified in a list of object ids"""
 
@@ -242,8 +215,6 @@
             clipboard.clearContents()
             clipboard.addItems('cut', items)
 
-    @form.action(_("container-copy-button"),
-                 condition=multiform.allSubFormsDisplayMode)
     def handle_copy_action(self, action, data):
         """Copy objects specified in a list of object ids"""
 
@@ -284,8 +255,6 @@
             clipboard.clearContents()
             clipboard.addItems('copy', items)
 
-    @form.action(_("container-delete-button"),
-                 condition=multiform.allSubFormsDisplayMode)
     def handle_delete_action(self, action, data):
         """Delete objects specified in a list of object ids"""
         container = self.context
@@ -301,11 +270,146 @@
         else:
             self.errors = (_("You didn't specify any ids to delete."),)            
 
+def condition_edit_action(form, action):
+    return multiform.allSubFormsDisplayMode(form, action)
+label_edit_action = _("Edit")
 
-def getPrincipalClipboard(request):
-    """Return the clipboard based on the request."""
-    user = request.principal
-    annotationutil = zapi.getUtility(IPrincipalAnnotationUtility)
-    annotations = annotationutil.getAnnotations(user)
-    return IPrincipalClipboard(annotations)
+def condition_save_action(form, action):
+    return multiform.anySubFormInputMode(form, action)
+label_save_action = _("Save")
 
+
+class ContainerItemActions(object):
+
+    def handle_edit_action(self, action, data):
+        if isSelected(self,action):
+            self.newInputMode = True
+
+    def handle_save_action(self, action, data):
+
+        if not isSelected(self,action):
+            return
+        if form.applyChanges(self.context, self.form_fields,
+                             data, self.adapters):
+            notify(ObjectModifiedEvent(self.context))
+            formatter = self.request.locale.dates.getFormatter(
+                'dateTime', 'medium')
+            try:
+                time_zone = idatetime.ITZInfo(self.request)
+            except TypeError:
+                time_zone = pytz.UTC
+            m = {'date_time':formatter.format(datetime.datetime.now(time_zone))}
+            self.status = (_("Updated on ${date_time}", mapping=m),)
+        else:
+            self.status = (_('No changes'),)
+        ISelection(self.context).selected=False
+        self.newInputMode = False
+       
+
+class NameTextWidget(TextWidget):
+
+    def __call__(self):
+        content = super(NameTextWidget, self).__call__()
+        # bad!
+        context = self.context.context.context
+        # zmi icon
+        zmi_icon = component.queryMultiAdapter((context, self.request), name='zmi_icon')        
+        if zmi_icon is not None:
+            icon = u'<img class="itemicon" src="%s" />&nbsp;' % zmi_icon.url()
+        else:
+            icon = u''
+        return icon + content
+
+
+class NameDisplayWidget(DisplayWidget):
+    
+    def __call__(self):
+        content = super(NameDisplayWidget, self).__call__()
+        # bad!
+        context = self.context.context.context
+        # zmi icon
+        zmi_icon = component.queryMultiAdapter((context, self.request), name='zmi_icon')        
+        if zmi_icon is not None:
+            icon = u'<img class="itemicon" src="%s" />&nbsp;' % zmi_icon.url()
+        else:
+            icon = u''
+        # link
+        url = zapi.absoluteURL(context, self.request)
+        result = u'<a href="%s/@@SelectedManagementView.html">%s%s</a>' % (url, icon, content)
+        return result
+
+    
+class ContainerItemForm(multiform.ItemFormBase,
+                        ContainerItemActions):
+
+    inputMode=False
+    forceInput=['selected']
+    template = ViewPageTemplateFile('griditem.pt')
+    form_fields = form.Fields(ISelection['selected'],
+                              IMovableLocation['__name__'],
+                              IWriteZopeDublinCore['title'],
+                              IWriteZopeDublinCore['created'],
+                              IWriteZopeDublinCore['modified'],
+                        omit_readonly=False,render_context=True)
+    form_fields['created'].for_display=True
+    form_fields['modified'].for_display=True
+    form_fields['__name__'].custom_widget=multiform.MultiformWidgets(
+                         NameTextWidget, NameDisplayWidget)
+
+    actions = form.Actions(
+           multiform.ParentAction(label_edit_action,
+                                  success='handle_edit_action',
+                                  condition=condition_edit_action),
+           multiform.ParentAction(label_save_action,
+                                  inputMode=True,
+                                  success='handle_save_action',
+                                  condition=condition_save_action)
+           )
+                         
+
+class ContainerGridForm(multiform.MultiFormBase,
+                        ContainerActions):
+
+    itemFormFactory=ContainerItemForm
+
+    template = ViewPageTemplateFile('grid.pt')
+
+    actions = form.Actions(
+       form.Action(label_cancel_action,
+                   success='handle_cancel_action',
+                   condition=condition_cancel_action),
+       form.Action(label_paste_action,
+                   success='handle_paste_action',
+                   condition=condition_paste_action),
+       form.Action(label_cut_action,
+                   success='handle_cut_action',
+                   condition=condition_cut_action),
+       form.Action(label_copy_action,
+                   success='handle_copy_action',
+                   condition=condition_copy_action),
+       form.Action(label_delete_action,
+                   success='handle_delete_action',
+                   condition=condition_delete_action)
+       )
+
+
+class ContainerItemIndexForm(multiform.ItemFormBase):
+
+    inputMode=False
+    template = ViewPageTemplateFile('griditem.pt')
+    form_fields = form.Fields(IMovableLocation['__name__'],
+                              IWriteZopeDublinCore['title'],
+                              IWriteZopeDublinCore['created'],
+                              IWriteZopeDublinCore['modified'],
+                        omit_readonly=False,render_context=True)
+    form_fields['created'].for_display=True
+    form_fields['modified'].for_display=True
+    form_fields['__name__'].custom_widget=NameDisplayWidget
+
+    
+class ContainerIndexForm(multiform.MultiFormBase):
+
+    itemFormFactory=ContainerItemIndexForm
+
+    template = ViewPageTemplateFile('grid.pt')
+

Modified: z3c.multiform/Sandbox/src/z3c/multiform/gridform.py
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/gridform.py	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/gridform.py	2006-12-07 14:53:23 UTC (rev 71478)
@@ -1,8 +1,11 @@
-from zope.component import getMultiAdapter
-from zope.interface import implements
+
+from zope import component, interface
 from zope.formlib import namedtemplate
 from zope.app.pagetemplate import ViewPageTemplateFile
-from zope.app.location.interfaces import ILocation
+from zope.location.interfaces import ILocation
+
+from zc import shortcut
+
 from interfaces import IGridForm, IGridItemForm, ISorter
 import multiform
 
@@ -15,13 +18,15 @@
 
 
 class GridItemFormBase(multiform.ItemFormBase):
-    implements(IGridItemForm)
+
+    interface.implements(IGridItemForm)
+
     template = namedtemplate.NamedTemplate('default')
 
 
 class GridFormBase(multiform.MultiFormBase):
 
-    implements(IGridForm)
+    interface.implements(IGridForm)
 
     default_batch_size = None
     default_sort_on = None
@@ -34,21 +39,19 @@
         super(GridFormBase,self).__init__(context, request)
         
 
-class FilterMapping(object):
+class FilterMapping(shortcut.Shortcut):
     
-    implements(ILocation)
+    def __init__(self, context, request, form):
+        self.__parent__ = None
+        self.__name__ = None
+        self.raw_target = context        
 
-    def __init__(self, context, request, form):
-        self.context = context
-        self.request = request
         if ILocation.providedBy(context):
             self.__parent__ = context.__parent__
             self.__name__ = context.__name__
-            
-        else:
-            self.__parent__ = None
-            self.__name__ = u""
+        self.request = request
         self.form = form
+
         self.batch_start = request.form.get(
                            '%s.handle.batch_start' % form.prefix,0)
         self.batch_size = request.form.get(
@@ -71,17 +74,18 @@
                     sortField = field
                     break
             if sortField:
-                sorter = getMultiAdapter((sortField.field.interface,
-                                          sortField.field),ISorter)
+                sorter = component.getMultiAdapter((sortField.field.interface,
+                                                    sortField.field),
+                                                   ISorter)
         if sorter:
-            items = sorter.sort(self.context.items())
+            items = sorter.sort(self.target.items())
             if self.sort_reverse:
                 items.reverse()
             keys = []
             for key, value in items:
                 yield key
         else:
-            for key in self.context.keys():
+            for key in self.target.keys():
                 yield key
 
     def keys(self):
@@ -104,11 +108,11 @@
 
     def values(self):
         for k in self.keys():
-            yield self.context[k]
+            yield self.target[k]
 
     def items(self):
         for k in self.keys():
-            yield k, self.context[k]
+            yield k, self.target[k]
 
     def __iter__(self):
         return iter(self.keys())
@@ -116,7 +120,7 @@
     def __getitem__(self, key):
         '''See interface `IReadContainer`'''
         if key in self.keys():
-            return self.context[key]
+            return self.target[key]
         else:
             raise KeyError, key
 
@@ -139,11 +143,11 @@
 
     def __setitem__(self, key, object):
         '''See interface `IWriteContainer`'''
-        self.context.__setitem__(key, object)
+        self.target.__setitem__(key, object)
 
     def __delitem__(self, key):
         '''See interface `IWriteContainer`'''
         if key in self.keys():
-            self.context.__delitem__(key)
+            self.target.__delitem__(key)
         else:
             raise KeyError, key

Modified: z3c.multiform/Sandbox/src/z3c/multiform/gridform.txt
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/gridform.txt	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/gridform.txt	2006-12-07 14:53:23 UTC (rev 71478)
@@ -10,7 +10,7 @@
     >>> from zope import interface, schema
     >>> from zope.formlib import form
     >>> from zope.publisher.browser import TestRequest
-    >>> from zope.app.location.interfaces import ILocation
+    >>> from zope.location.interfaces import ILocation
     >>> from z3c.multiform.interfaces import ISelection
     >>> from z3c.multiform import multiform, gridform
 
@@ -108,12 +108,12 @@
     >>> gf.update()
     >>> print gf.render()
     <div>
-    <div><input ... name="form.n0.selected" type="checkbox" ...  /></div>
+    <div><input ... name="form.sf.n0.selected" type="checkbox" ...  /></div>
     <div>0</div>
     <div>n0</div>
     </div>
     <div>
-    <div><input ... name="form.n1.selected" type="checkbox" ...  /></div>
+    <div><input ... name="form.sf.n1.selected" type="checkbox" ...  /></div>
     <div>1</div>
     <div>n1</div>
     ...
@@ -129,18 +129,18 @@
 Now we are going to select some items. And the checkbox of the ``selected``
 
     >>> request = TestRequest()
-    >>> request.form['form.n1.selected']=u'on'
-    >>> request.form['form.n0.selected.used']=u''
+    >>> request.form['form.sf.n1.selected']=u'on'
+    >>> request.form['form.sf.n0.selected.used']=u''
     >>> gf = OrdersForm(orderMapping,request)
     >>> gf.update()
     >>> print gf.render()
     <div>
-    <div><input... name="form.n0.selected" type="checkbox" value="on"  /></div>
+    <div><input... name="form.sf.n0.selected" type="checkbox" value="on"  /></div>
     <div>0</div>
     <div>n0</div>
     </div>
     <div>
-    <div><input... checked="checked" ... name="form.n1.selected" ... /></div>
+    <div><input... checked="checked" ... name="form.sf.n1.selected" ... /></div>
     <div>1</div>
     <div>n1</div>
     ...
@@ -151,24 +151,24 @@
 
     >>> request = TestRequest()
     >>> request.form['form.actions.edit']=u''
-    >>> request.form['form.n0.selected.used']=u''
-    >>> request.form['form.n1.selected']=u'on'
-    >>> request.form['form.n2.selected.used']=u''
-    >>> request.form['form.n3.selected.used']=u''
+    >>> request.form['form.sf.n0.selected.used']=u''
+    >>> request.form['form.sf.n1.selected']=u'on'
+    >>> request.form['form.sf.n2.selected.used']=u''
+    >>> request.form['form.sf.n3.selected.used']=u''
     >>> gf = OrdersForm(orderMapping,request)
     >>> res = gf()
     >>> ISelection(gf.subForms['n1'].context).selected
     True
     >>> print res
     <div>
-    <div><input... name="form.n0.selected" type="checkbox" value="on"  /></div>
+    <div><input... name="form.sf.n0.selected" type="checkbox" value="on"  /></div>
     <div>0</div>
     <div>n0</div>
     </div>
     <div>
-    <div><input... checked="checked" ... name="form.n1.selected" ... /></div>
+    <div><input... checked="checked" ... name="form.sf.n1.selected" ... /></div>
     <div>1</div>
-    <div><input... name="form.n1.name" ...</div>
+    <div><input... name="form.sf.n1.name" ...</div>
     ...
     </div>
 
@@ -181,19 +181,19 @@
 Now we test the actions which are displayed in each row.
 
     >>> request = TestRequest()
-    >>> #request.form['form.n1.actions.singleedit']=u''
+    >>> #request.form['form.sf.n1.actions.singleedit']=u''
     >>> gf = OrdersForm(orderMapping,request)
     >>> res = gf()
     >>> sorted([action.__name__ for action in
     ...     gf.subForms['n1'].availableActions()])
-    [u'form.n1.actions.singleedit']
+    [u'form.sf.n1.actions.singleedit']
 
 We call the singleedit to edit a single row.
     
     >>> request = TestRequest()
-    >>> request.form['form.n0.selected.used']=u''
-    >>> request.form['form.n1.selected.used']=u''
-    >>> request.form['form.n1.actions.singleedit']=u''
+    >>> request.form['form.sf.n0.selected.used']=u''
+    >>> request.form['form.sf.n1.selected.used']=u''
+    >>> request.form['form.sf.n1.actions.singleedit']=u''
     >>> gf = OrdersForm(orderMapping,request)
     >>> res = gf()
 
@@ -209,12 +209,12 @@
     >>> gf.update()
     >>> print gf.render()
     <div>
-    <div><input ... name="form.n1.selected" type="checkbox" ...  /></div>
+    <div><input ... name="form.sf.n1.selected" type="checkbox" ...  /></div>
     <div>1</div>
     <div>n1</div>
     </div>
     <div>
-    <div><input ... name="form.n2.selected" type="checkbox" ...  /></div>
+    <div><input ... name="form.sf.n2.selected" type="checkbox" ...  /></div>
     <div>2</div>
     <div>n2</div>
     </div>    
@@ -243,7 +243,7 @@
     >>> gf.update()
     >>> print gf.render()
     <div>
-    <div><input ... name="form.n0.selected" ...
+    <div><input ... name="form.sf.n0.selected" ...
     <div>1</div>
     <div>n1</div>
     ...

Modified: z3c.multiform/Sandbox/src/z3c/multiform/interfaces.py
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/interfaces.py	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/interfaces.py	2006-12-07 14:53:23 UTC (rev 71478)
@@ -5,21 +5,17 @@
 
 
 class IMultiForm(Interface):
-
     """multiform"""
 
 class IItemForm(Interface):
-
     """a sub form for an item of a multiform"""
 
 
 class IGridItemForm(IItemForm):
-
     """an form for an item of a grid form"""
 
 
 class IGridForm(IMultiForm):
-
     """a special grid multiform"""
 
 
@@ -32,7 +28,6 @@
 
 
 class ISelection(Interface):
-
     """Provides information about the selection state of an object"""
 
     selected = schema.Bool(title=_(u'Selected'),default=False)
@@ -47,3 +42,17 @@
 
     def sort(items):
         """return the items sorted. items are (key,value) tuples"""
+
+
+class IFilter(Interface):
+    """Provides the content of the context."""
+
+    batch_start = schema.Int()
+    
+    batch_size = schema.Int()
+    
+    sort_on = schema.TextLine()
+    
+    sort_reverse = schema.Bool(default=False)
+
+    sort_columns = schema.List()
\ No newline at end of file

Modified: z3c.multiform/Sandbox/src/z3c/multiform/multiform.py
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/multiform.py	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/multiform.py	2006-12-07 14:53:23 UTC (rev 71478)
@@ -1,56 +1,58 @@
+
 import copy
-from zope import interface
-from zope.component import getMultiAdapter
-from zope.interface import implements
+
+from zope import interface, component
 import zope.i18n
-from zope.app.publisher.browser import BrowserView
 from zope.app import zapi
+from zope.app.form.interfaces import IInputWidget, IDisplayWidget
 from zope.app.form.browser.interfaces import IWidgetInputErrorView
-from zope.formlib import form
+from zope import formlib
 from zope.formlib import namedtemplate
 from zope.formlib.interfaces import IBoundAction
 from zope.app.i18n import ZopeMessageFactory as _
-from interfaces import *
-from interfaces import IFormLocation,IItemForm
 
+import interfaces
+from interfaces import IFormLocation, ISelection
+
+
 def isFormDisplayMode(f,action):
     return not f.inputMode
     
 def isFormInputMode(f,action):
     return f.inputMode
 
-def anySubFormInputMode(form,action):
-    if not IMultiForm.providedBy(form):
-        form = form.parentForm
-    for f in form.subForms.values():
-        if f.inputMode:
+def anySubFormInputMode(f,action):
+    if not interfaces.IMultiForm.providedBy(f):
+        f = f.parentForm
+    for sf in f.subForms.values():
+        if sf.inputMode:
             return True
 
-def allSubFormsDisplayMode(form,action):
-    if not IMultiForm.providedBy(form):
-        form = form.parentForm
-    for f in form.subForms.values():
-        if f.inputMode:
+def allSubFormsDisplayMode(f,action):
+    if not interfaces.IMultiForm.providedBy(f):
+        f = f.parentForm
+    for sf in f.subForms.values():
+        if sf.inputMode:
             return False
     return True
 
 
-class ItemAction(form.Action):
-
+class ItemAction(formlib.form.Action):
     """an action that is rendered in the itemform object and can
     handle the toggle between input and display."""
     
-    implements(IItemAction)
+    interface.implements(interfaces.IItemAction)
+
     def __init__(self, label, **options):
         self.inputMode = options.pop('inputMode',None)
         super(ItemAction,self).__init__(label,**options)
 
-class ParentAction(form.Action):
-
+class ParentAction(formlib.form.Action):
     """an action that is rendered in the parent multiform object and
     is applied to all subForms"""
     
-    implements(IParentAction)
+    interface.implements(interfaces.IParentAction)
+
     def __init__(self, label, **options):
         self.inputMode = options.pop('inputMode',None)
         super(ParentAction,self).__init__(label,**options)
@@ -73,7 +75,7 @@
             res =  self.__name__ in self.form.request
         return res
 
- at namedtemplate.implementation(IParentAction)
+ at namedtemplate.implementation(interfaces.IParentAction)
 def render_submit_button(self):
     if IBoundAction.providedBy(self) and not self.available():
         return ''
@@ -86,7 +88,7 @@
             )
 
 
-class itemAction(form.action):
+class itemAction(formlib.form.action):
 
     def __call__(self, success):
         action = ItemAction(self.label, success=success, **self.options)
@@ -94,7 +96,7 @@
         return action
 
 
-class parentAction(form.action):
+class parentAction(formlib.form.action):
     
     def __call__(self, success):
         action = ParentAction(self.label, success=success, **self.options)
@@ -102,9 +104,112 @@
         return action
 
 
-class ItemFormBase(form.FormBase):
+class MultiformWidgets(object):
+    
+    def __init__(self, inputWidget=None, displayWidget=None):
+        self.inputWidget = inputWidget
+        self.displayWidget = displayWidget
 
-    implements(IItemForm)
+    def __call__(self, field, request, iface):
+        if iface == IDisplayWidget:
+            return self.displayWidget(field, request)
+        else:
+            return self.inputWidget(field, request)
+
+
+def _createWidget(form_field, field, request, iface):
+    if form_field.custom_widget is None:
+        return component.getMultiAdapter((field, request), iface)
+    else:
+        if isinstance(form_field.custom_widget, MultiformWidgets):
+            return form_field.custom_widget(field, request, iface)
+        else:
+            return form_field.custom_widget(field, request)
+
+
+def setUpWidgets(form_fields,
+                 form_prefix=None, context=None, request=None, form=None,
+                 data=(), adapters=None, ignore_request=False):
+
+    if request is None:
+        request = form.request
+    if context is None and form is not None:
+        context = form.context
+    if form_prefix is None:
+        form_prefix = form.prefix
+
+    widgets = []
+    adapter = None
+    for form_field in form_fields:
+        field = form_field.field
+        if form_field.render_context:
+            if adapters is None:
+                adapters = {}
+
+            # Adapt context, if necessary
+            interface = field.interface
+            adapter = adapters.get(interface)
+            if adapter is None:
+                if interface is None:
+                    adapter = context
+                else:
+                    adapter = interface(context)
+                adapters[interface] = adapter
+                if interface is not None:
+                    adapters[interface.__name__] = adapter
+            field = field.bind(adapter)
+        else:
+            field = field.bind(context)
+
+        readonly = form_field.for_display
+        readonly = readonly or (field.readonly and not form_field.for_input)
+        readonly = readonly or (
+            (form_field.render_context & formlib.form.interfaces.DISPLAY_UNWRITEABLE)
+            and not formlib.form.canWrite(context, field)
+            )
+
+        if readonly:
+            iface = IDisplayWidget
+        else:
+            iface = IInputWidget
+        widget = _createWidget(form_field, field, request, iface)
+
+#        if form_field.custom_widget is not None:
+#            widget = form_field.custom_widget(field, request)
+#        else:
+#            if readonly:
+#                widget = component.getMultiAdapter((field, request),
+#                                                   IDisplayWidget)
+#            else:
+#                widget = component.getMultiAdapter((field, request),
+#                                                   IInputWidget)
+
+        prefix = form_prefix
+        if form_field.prefix:
+            prefix += '.' + form_field.prefix
+
+        widget.setPrefix(prefix)
+
+        if ignore_request or readonly or not widget.hasInput():
+            # Get the value to render
+            if form_field.__name__ in data:
+                widget.setRenderedValue(data[form_field.__name__])
+            elif form_field.get_rendered is not None:
+                widget.setRenderedValue(form_field.get_rendered(form))
+            elif form_field.render_context:
+                widget.setRenderedValue(field.get(adapter))
+            else:
+                widget.setRenderedValue(field.default)
+
+        widgets.append((not readonly, widget))
+
+    return formlib.form.Widgets(widgets, len(form_prefix)+1)
+
+        
+class ItemFormBase(formlib.form.FormBase):
+
+    interface.implements(interfaces.IItemForm)
+
     forceInput = []
     parentForm = None
     inputMode = None
@@ -112,19 +217,19 @@
     form_fields=[]
     actions = []
     
-    def __init__(self,context,request,parentForm):
+    def __init__(self, context, request, parentForm):
         # we have to copy the default fields, so that we can mutate
         # them in our instance
         self.form_fields = copy.deepcopy(self.__class__.form_fields)
         self.request = request
-        self.context = getMultiAdapter([context,self],IFormLocation)
+        self.context = component.getMultiAdapter((context, self), IFormLocation)
         self.parentForm = parentForm
 
     def update(self):
         self.form_reset = False
 
         data = {}
-        errors, action = form.handleSubmit(self.actions, data, self.validate)
+        errors, action = formlib.form.handleSubmit(self.actions, data, self.validate)
         self.errors = errors
 
         if errors:
@@ -138,29 +243,33 @@
 
         self.form_result = result
 
-    def setUpWidgets(self,ignore_request=False):
-        super(ItemFormBase,self).setUpWidgets(ignore_request)
+    def setUpWidgets(self, ignore_request=False):
+        self.adapters = {}
+        self.widgets = setUpWidgets(
+            self.form_fields, self.prefix, self.context, self.request,
+            form=self, adapters=self.adapters, ignore_request=ignore_request)
         # XXX how to check for the field
         if self.widgets.get('selected'):
             widget = self.widgets['selected']
-            widget.setRenderedValue(ISelection(self.context).selected)
+            widget.setRenderedValue(interfaces.ISelection(self.context).selected)
 
     def availableActions(self):
         # we need to override this, because we should not return the
         # parentActions
-        if not hasattr(self,'actions'):
+        if not hasattr(self, 'actions'):
             return []
         actions = [action for action in self.actions
-                   if not IParentAction.providedBy(action)]
-        return form.availableActions(self, actions)
+                   if not interfaces.IParentAction.providedBy(action)]
+        return formlib.form.availableActions(self, actions)
         
     def availableParentActions(self):
-        if not hasattr(self,'actions'):
+        if not hasattr(self, 'actions'):
             return []
         actions = [action for action in self.actions
-                   if IParentAction.providedBy(action)]
-        return form.availableActions(self, actions)
+                   if interfaces.IParentAction.providedBy(action)]
+        return formlib.form.availableActions(self, actions)
 
+
 # copy from formlib with get
 def availableActions(form, actions):
     result = []
@@ -171,10 +280,10 @@
     return result
 
 
+class MultiFormBase(formlib.form.FormBase):
 
-class MultiFormBase(form.FormBase):
+    interface.implements(interfaces.IMultiForm)
 
-    implements(IMultiForm)
     itemFormFactory = ItemFormBase
     subForms={}
     form_fields = []
@@ -183,34 +292,43 @@
     subFormInputMode = {}
     selection = []
     actions = []
+    forms = []
 
+    def __init__(self, context, request):
+        super(MultiFormBase,self).__init__(context, request)
+        self.filter = self.context
+
     def update(self):
+        self.forms = list(self.filter.keys())
         self.checkInputMode()
         self.updateSelection()
         super(MultiFormBase,self).update()
         preForms = list(self.getForms())
         for form in preForms:
             form.update()
+        self.forms = list(self.filter.keys())            
         postForms = list(self.getForms())
         refresh = postForms != preForms
         for form in postForms:
+            if form.form_reset is True:
+                refresh = True
             if form.newInputMode is not None:
                 newInputMode = form.newInputMode
-                context = self.context[form.context.__name__]
+                context = self.filter[form.context.__name__]
                 name = context.__name__
                 self.setUpForm(name, context, newInputMode,
                                ignore_request=True)
                 self.subFormInputMode[name] = newInputMode
                 refresh = True
-            if refresh:
-                self.refreshSubActionNames()
+        if refresh:
+            self.refreshSubActionNames()
 
     def setUpWidgets(self, *args, **kw):
         super(MultiFormBase,self).setUpWidgets(*args,**kw)
         self.setUpForms(*args, **kw)
 
     def setUpForm(self, name, item, inputMode, *args, **kw):
-        prefix = (self.prefix and self.prefix+'.' or '') + name
+        prefix = self.prefix + '.sf.' + name
         subForm = self.newSubForm(item)
         if inputMode is not None and not inputMode:
             forceInput = self.itemFormFactory.forceInput
@@ -223,31 +341,32 @@
         self.subForms[name] = subForm
 
     def setUpForms(self, *args, **kw):
+        self.forms = list(self.filter.keys())
         self.subForms = {}
-        for name, item in self.context.items():
-            inputMode = self.subFormInputMode.get(name,self.itemFormFactory.inputMode)
-            self.setUpForm(name, item, inputMode)
+        for key in self.forms:
+            item = self.filter[key]
+            inputMode = self.subFormInputMode.get(key, self.itemFormFactory.inputMode)
+            self.setUpForm(key, item, inputMode)
         self.refreshSubActionNames()
 
     def getForms(self):
         # we have to use the keys here to support all actions that
         # modifies the keys of our mapping, e.g. rename, delete
-        keys = list(self.context.keys())
-        deleted = filter(lambda x: x not in keys,self.subForms.keys())
+        keys = self.forms
+        deleted = filter(lambda x: x not in keys, self.subForms.keys())
         for k in deleted:
             del(self.subForms[k])
             try:
                 del(self.subFormInputMode[k])
             except KeyError:
                 pass
-        for name in self.context.keys():
-            if not self.subForms.has_key(name):
-                self.setUpForm(name,self.context[name],
+        for key in self.forms:
+            if not self.subForms.has_key(key):
+                self.setUpForm(key, self.filter[key],
                                self.itemFormFactory.inputMode,
                                ignore_request=True)
-            yield self.subForms[name]
+            yield self.subForms[key]
 
-
     def refreshSubActionNames(self):
         availableActions = set()
         for subForm in self.getForms():
@@ -259,55 +378,78 @@
                 name = '%s.%s' % (self.prefix,action.__name__)
                 if name in availableActions:
                     self.subActionNames.append(name)
-                    
-            
+
+    def checkInputModeAction(self, action):
+        if interfaces.IItemAction.providedBy(action):
+            for key in self.forms:
+                name = self.prefix + '.sf.' + key + action.__name__
+                if name in self.request.form:
+                    return action.inputMode
+        if interfaces.IParentAction.providedBy(action):
+            name = self.prefix + '.' + action.__name__
+            if name in self.request.form:
+               return action.inputMode
+        return None
+   
     def checkInputMode(self):
         self.subFormInputMode = {}
+        # check if any action with inputMode Flag in request
         inputMode = None
-        for action in self.itemFormFactory.actions:
-            name = '%s.%s' % (self.prefix,action.__name__)
-            if name in self.request.form and getattr(action,
-                                'inputMode', None) is not None:
-                inputMode = action.inputMode
-                break
+        # check itemForm actions
+        if hasattr(self.itemFormFactory, 'actions'):
+            for action in self.itemFormFactory.actions:
+                if getattr(action, 'inputMode', None) is not None:
+                    inputMode = self.checkInputModeAction(action)
+                    if inputMode is not None:
+                        break
+        # check form actions
+        if hasattr(self, 'actions'):
+            for action in self.actions:
+                if getattr(action, 'inputMode', None) is not None:
+                    inputMode = self.checkInputModeAction(action)
+                    if inputMode is not None:
+                        break
         if inputMode is None:
             return
-        inputField = None
-        if len(self.context) > 0:
-            for name, item in self.context.items():
-                break
-            tmpForm = self.newSubForm(item)
+        
+        # check which forms in inputMode
+        if len(self.forms) > 0:
+            # get any inputfield
+            tmpForm = self.newSubForm(self.filter[self.forms[0]])
+            inputField = None
             for field in tmpForm.form_fields:
                 if not field.for_display and field.__name__ not in tmpForm.forceInput:
                     inputField = field
                     break
-            for name in self.context.keys():
-                prefix = self.prefix + '.' + name + '.' + field.__name__
-                self.subFormInputMode[name] = (prefix in self.request.form)
-                
+            if inputField is None:
+                # should not be happen
+                return
+            for key in self.forms:
+                name = self.prefix + '.sf.' + key + '.' + inputField.__name__
+                self.subFormInputMode[key] = (name in self.request.form)
+
     def updateSelection(self):
         for field in self.itemFormFactory.form_fields:
-            if issubclass(field.field.interface,ISelection):
-                form_fields = form.Fields(field)
-                for name,item in self.context.items():
+            if issubclass(field.field.interface,interfaces.ISelection):
+                form_fields = formlib.form.Fields(field)
+                for key in self.forms:
+                    item = self.filter[key]
                     sForm = SelectionForm(item, self.request, form_fields)
-                    prefix = (self.prefix and self.prefix+'.' or '') + name
-                    sForm.setPrefix(prefix)
+                    name = self.prefix + '.sf.' + key
+                    sForm.setPrefix(name)
                     sForm.form_fields = form_fields
                     sForm.setUpWidgets()
                     data = {}
                     try:
-                        form.getWidgetsData(sForm.widgets, sForm.prefix, data)
+                        formlib.form.getWidgetsData(sForm.widgets, sForm.prefix, data)
                     except:
                        pass
-                    form.applyChanges(sForm.context, sForm.form_fields, data)
+                    formlib.form.applyChanges(sForm.context, sForm.form_fields, data)
                 return
 
-    def newSubForm(self,item):
-
+    def newSubForm(self, item):
         """creates a new instance from the itemFormFactory for
         temporary usage"""
-        
         return self.itemFormFactory(item,self.request,self)
 
     def availableSubActions(self):
@@ -325,9 +467,10 @@
                 yield action
 
 
-class SelectionForm(form.FormBase):
+class SelectionForm(formlib.form.FormBase):
     
     def __init__(self, context, request, form_fields):
         self.form_fields = form_fields
         self.request = request
-        self.context = getMultiAdapter([context,self],IFormLocation)
+        self.context = component.getMultiAdapter((context,self), IFormLocation)
+

Modified: z3c.multiform/Sandbox/src/z3c/multiform/selection.py
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/selection.py	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/selection.py	2006-12-07 14:53:23 UTC (rev 71478)
@@ -1,12 +1,15 @@
-from zope.interface import implements
+from zope import interface, component
+
 from zope.proxy import ProxyBase, getProxiedObject
 from zope.security.checker import NamesChecker,defineChecker
 from zope.security.proxy import removeSecurityProxy
-from zope.app.decorator import DecoratorSpecificationDescriptor
-from zope.app.decorator import DecoratedSecurityCheckerDescriptor
-from zope.app.location import location
+from zope.decorator import DecoratorSpecificationDescriptor
+from zope.decorator import DecoratedSecurityCheckerDescriptor
+from zope.location import location
+from zope.location.interfaces import ILocation
+from zope.formlib.interfaces import IForm
 
-from interfaces import ISelection,IFormLocation
+from z3c.multiform.interfaces import ISelection, IFormLocation
 
 
 class FormLocationSelection(object):
@@ -37,7 +40,8 @@
     False
     """
 
-    implements(ISelection)
+    interface.implements(ISelection)
+    component.adapts(IFormLocation)
 
     def __init__(self,context):
         self.context = context
@@ -104,7 +108,9 @@
 
     """
 
-    implements(IFormLocation)
+#    interface.implements(IFormLocation)
+    interface.implementsOnly(IFormLocation)
+    component.adapts(ILocation, IForm)
 
     __slots__ = '__form__'
     __safe_for_unpickling__ = True
@@ -134,5 +140,3 @@
 formLocationChecker = NamesChecker(['__form__'])
 defineChecker(FormLocationProxy, formLocationChecker)
 
-
-

Copied: z3c.multiform/Sandbox/src/z3c/multiform/selection.txt (from rev 71090, z3c.multiform/Sandbox/src/z3c/multiform/selections.txt)
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/selections.txt	2006-11-06 15:49:14 UTC (rev 71090)
+++ z3c.multiform/Sandbox/src/z3c/multiform/selection.txt	2006-12-07 14:53:23 UTC (rev 71478)
@@ -0,0 +1,13 @@
+======================
+ Multiform Selections
+======================
+
+Selecting subforms of a multiform is a common task which is supported
+by the multiform package. Selections are implemented by the ISelection
+interface. This interface can be adapted to from objects which
+implement IFormLocation which in turn can be adapted to from ILocation
+and IForm. The IFormLocation adpater is a proxy which provides the
+``__form_name__`` attribute.
+
+The ISelection implementation in this package uses the request to
+store the selection state, by using the ILocationForm interface.

Deleted: z3c.multiform/Sandbox/src/z3c/multiform/selections.txt
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/selections.txt	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/selections.txt	2006-12-07 14:53:23 UTC (rev 71478)
@@ -1,14 +0,0 @@
-======================
- Multiform Selections
-======================
-
-Selecting subforms of a multiform is a common task which is supported
-by the multiform package. Selections are implemented by the ISelection
-interface. This interface can be adapted to from objects which
-implement IFormLocation which in turn can be adapted to from ILocation
-and IForm. The IFormLocation adpater is a proxy which provides the
-``__form_name__`` attribute.
-
-The ISelection implementation in this package uses the request to
-store the selection state, by using the ILocationForm interface.
-

Modified: z3c.multiform/Sandbox/src/z3c/multiform/sort.py
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/sort.py	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/sort.py	2006-12-07 14:53:23 UTC (rev 71478)
@@ -1,11 +1,14 @@
-from zope.interface import implements
+from zope import interface, component
+from zope.interface import Interface
+from zope.schema.interfaces import IField
 
-from interfaces import ISorter
+from z3c.multiform.interfaces import ISorter
 
 
 class SchemaSorter(object):
 
-    implements(ISorter)
+    interface.implements(ISorter)
+    component.adapts(Interface, IField)
 
     def __init__(self,schema,field):
         self.schema = schema
@@ -13,7 +16,6 @@
         self.field = field
 
     def sort(self,seq):
-
         l = []
         def _v(o):
             o = self.schema(o)

Modified: z3c.multiform/Sandbox/src/z3c/multiform/tests.py
===================================================================
--- z3c.multiform/Sandbox/src/z3c/multiform/tests.py	2006-12-07 13:45:16 UTC (rev 71477)
+++ z3c.multiform/Sandbox/src/z3c/multiform/tests.py	2006-12-07 14:53:23 UTC (rev 71478)
@@ -3,7 +3,7 @@
 
 from zope import component
 from zope.testing.doctestunit import DocFileSuite, DocTestSuite
-from zope.app.testing import setup
+from zope.app.testing import setup, ztapi
 import zope.schema.interfaces
 import zope.app.form.browser
 import zope.publisher.interfaces.browser
@@ -15,6 +15,7 @@
 import multiform
 import selection
 import sort
+from interfaces import IFormLocation, ISelection
 
 
 def setUp(test):
@@ -62,24 +63,10 @@
          ],
         zope.app.form.interfaces.IInputWidget,
         )
-    component.provideAdapter(
-        selection.FormLocationProxy,
-        [zope.app.location.interfaces.ILocation,
-         zope.formlib.interfaces.IForm
-         ],
-        interfaces.IFormLocation
-        )
-    component.provideAdapter(
-        selection.FormLocationSelection,
-        [interfaces.IFormLocation],
-        interfaces.ISelection
-        )
-    component.provideAdapter(
-        sort.SchemaSorter,
-        [zope.interface.Interface,
-         zope.schema.interfaces.IField],
-        interfaces.ISorter
-        )    
+    component.provideAdapter(selection.FormLocationProxy)
+    component.provideAdapter(selection.FormLocationSelection)
+    component.provideAdapter(sort.SchemaSorter)
+
     component.provideAdapter(gridform.default_grid_template,
                              name="default")
     component.provideAdapter(gridform.default_griditem_template,
@@ -98,6 +85,10 @@
         DocTestSuite('z3c.multiform.selection',
                      optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
                      ),
+        DocFileSuite('selection.txt',
+                     setUp=setUp, tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),                     
         DocFileSuite('README.txt',
                      setUp=setUp, tearDown=tearDown,
                      optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,



More information about the Checkins mailing list