[Checkins] SVN: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/ Add group support

Laurent Mignon Laurent.Mignon at softwareag.com
Fri Feb 27 05:38:45 EST 2009


Log message for revision 97339:
  Add group support
  

Changed:
  U   z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.py
  U   z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.txt
  U   z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.zcml
  U   z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/configure.zcml
  A   z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/group.py
  A   z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/group.txt
  U   z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/interfaces.py
  U   z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/testing.py
  U   z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/tests/test_doc.py

-=-
Modified: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.py
===================================================================
--- z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.py	2009-02-27 10:35:04 UTC (rev 97338)
+++ z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.py	2009-02-27 10:38:44 UTC (rev 97339)
@@ -24,6 +24,7 @@
 
 from z3c.form.interfaces import IDataConverter
 from z3c.form.interfaces import IForm, DISPLAY_MODE, HIDDEN_MODE
+from z3c.form.interfaces import IGroup
 from z3c.form.interfaces import IRadioWidget, IButtonAction
 from z3c.form.interfaces import IWidget
 from z3c.form.interfaces import ITextAreaWidget
@@ -330,20 +331,28 @@
     return widgets
 
 
-class FormPanel(Component):
+def getGroupsConfig(form, json=False):
+    items = []
+    if form.groups:
+        for group in form.groups:
+            groupComponent = interfaces.IExtJSComponent(group)
+            groupConfig = groupComponent._getConfig(json)
+            items.append(groupConfig)
+    return items
+
+
+class Panel(Component):
     zope.interface.implements(interfaces.IExtJSComponent)
     zope.component.adapts(IForm)
 
-    xtype = 'formpanel'
+    xtype = 'panel'
 
     def __init__(self, form):
         self.form = form
 
     def _getConfig(self, json=False):
         config = dict(
-            xtype=self.xtype,
-            id=self.form.id,
-            submitURL=self.form.action)
+            xtype=self.xtype)
         if self.form.label:
             config['title'] = self.form.label
         if not self.form.widgets:
@@ -351,13 +360,42 @@
         items = getWidgetsConfig(self.form, asDict=False)
         if items:
             config['items'] = items
+        if hasattr(self.form, 'renderTo'):
+            config['renderTo'] = self.form.renderTo
+        #update config
+        cfg = zope.component.queryMultiAdapter(
+                (self.form.context, self.form.request, self.form),
+                interfaces.IExtJSConfigValue)
+        if cfg:
+            config.update(cfg.get())
+        return config
 
+
+class GroupPanel(Panel):
+    zope.interface.implements(interfaces.IExtJSComponent)
+    zope.component.adapts(IGroup)
+
+    def _getConfig(self, json=False):
+        config = super(GroupPanel, self)._getConfig(json)
+        items = config.get("items", [])
+        items += getGroupsConfig(self.form, json)
+        config['items'] = items
+        return config
+
+
+class FormPanel(Panel):
+    zope.interface.implements(interfaces.IExtJSComponent)
+    zope.component.adapts(interfaces.IBaseForm)
+
+    xtype = 'formpanel'
+
+    def _getConfig(self, json=False):
+        config = super(FormPanel, self)._getConfig(json)
+        config['id'] = self.form.id
+        config['submitURL'] = self.form.action
         buttons = getButtonsConfig(self.form, asDict=False)
         if buttons:
             config['buttons'] = buttons
-        if hasattr(self.form, 'renderTo'):
-            config['renderTo'] = self.form.renderTo
-
         return config
 
 
@@ -413,3 +451,15 @@
         if hasattr(self.form, 'ownerCt'):
             config['ownerCt'] = self.form.ownerCt
         return config
+
+
+class ExtGroupFormPanel(ExtFormPanel):
+    zope.interface.implements(interfaces.IExtJSComponent)
+    zope.component.adapts(interfaces.IExtJSGroupForm)
+
+    def _getConfig(self, json=False):
+        config = super(ExtGroupFormPanel, self)._getConfig()
+        items = config.get("items", [])
+        items += getGroupsConfig(self.form, json)
+        config['items'] = items
+        return config

Modified: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.txt
===================================================================
--- z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.txt	2009-02-27 10:35:04 UTC (rev 97338)
+++ z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.txt	2009-02-27 10:38:44 UTC (rev 97339)
@@ -604,11 +604,9 @@
 Now we can look more closely at what we actually get
 
   >>> config['xtype']
-  'formpanel'
+  'panel'
   >>> config['title']
   u'My Contact Form'
-  >>> config['id']
-  'form'
   >>> config['renderTo']
   'my-dom-id'
 

Modified: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.zcml
===================================================================
--- z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.zcml	2009-02-27 10:35:04 UTC (rev 97338)
+++ z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/component.zcml	2009-02-27 10:38:44 UTC (rev 97339)
@@ -5,12 +5,22 @@
     i18n_domain="z3c.formext">
 
   <adapter
+      factory=".component.Panel"
+      />
+  <adapter
+      factory=".component.GroupPanel"
+      />
+  <adapter
       factory=".component.FormPanel"
       />
   <adapter
       factory=".component.ExtFormPanel"
       />
+  <adapter
+      factory=".component.ExtGroupFormPanel"
+      />
 
+
   <!-- Adapt TextWidget -->
   <adapter
       factory=".component.TextField"

Modified: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/configure.zcml
===================================================================
--- z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/configure.zcml	2009-02-27 10:35:04 UTC (rev 97338)
+++ z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/configure.zcml	2009-02-27 10:38:44 UTC (rev 97339)
@@ -1,3 +1,4 @@
+<?xml version="1.0"?>
 <configure
     xmlns="http://namespaces.zope.org/zope"
     xmlns:browser="http://namespaces.zope.org/browser"
@@ -3,4 +4,9 @@
     xmlns:z3c="http://namespaces.zope.org/z3c">
 
+  <!-- Add marker interface on BaseForm -->
+  <class class="z3c.form.form.BaseForm">
+      <implements
+          interface=".interfaces.IBaseForm"/>
+  </class>
 
   <!-- Data Converters -->

Added: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/group.py
===================================================================
--- z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/group.py	                        (rev 0)
+++ z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/group.py	2009-02-27 10:38:44 UTC (rev 97339)
@@ -0,0 +1,55 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""ExtJS Component representation.
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import zope.interface
+from zope.i18n import translate
+from zope.security.proxy import removeSecurityProxy
+
+from z3c.formext import interfaces
+
+from z3c.form import group
+
+
+class ExtJSGroupForm(group.GroupForm):
+    """A mix-in class for extjs add and edit forms to support groups.
+
+    See z3c.form.group.GroupForm
+    """
+
+    zope.interface.implements(interfaces.IExtJSGroupForm)
+
+    def extractData(self):
+        """See z3c.form.interfaces.IForm
+        """
+        data, errors = super(ExtJSGroupForm, self).extractData()
+        self.jsonResponse = dict(success=True)
+        if errors:
+            self.jsonResponse = dict(
+                success=False,
+                # I shouldn't need the below security proxy
+                errors={},
+                formErrors=[])
+            for error in errors:
+                error = removeSecurityProxy(error)
+                message = translate(error.message, context=self.request)
+                if error.widget:
+                    self.jsonResponse['errors'][error.widget.id] = message
+                else:
+                    self.jsonResponse['formErrors'].append(message)
+        return data, errors


Property changes on: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/group.py
___________________________________________________________________
Added: svn:keywords
   + Date Author Id Revision

Added: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/group.txt
===================================================================
--- z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/group.txt	                        (rev 0)
+++ z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/group.txt	2009-02-27 10:38:44 UTC (rev 97339)
@@ -0,0 +1,352 @@
+ExtJS Group Form Integration
+============================
+
+This package also provides a tight integration between z3c.form.group -
+which allow you to split up a form into selevral logical units (See
+z3c.form.group), and Ext JS forms which provide an advanced client side form
+model.
+
+For the example work, we have to bring a most of the formext framework:
+
+  >>> from z3c.formext import testing
+  >>> testing.setupFormExt()
+  
+  >>> from z3c.formext import form, group, interfaces
+
+So let's first define a complex content component that warrants setting up
+multiple groups:
+
+  >>> from zope.interface import Interface
+  >>> from zope.interface import implements
+  >>> import zope.schema
+
+  >>> class IVehicleRegistration(Interface):
+  ...     firstName = zope.schema.TextLine(title=u'First Name')
+  ...     lastName = zope.schema.TextLine(title=u'Last Name')
+  ...
+  ...     license = zope.schema.TextLine(title=u'License')
+  ...     address = zope.schema.TextLine(title=u'Address')
+  ...
+  ...     model = zope.schema.TextLine(title=u'Model')
+  ...     make = zope.schema.TextLine(title=u'Make')
+  ...     year = zope.schema.TextLine(title=u'Year')
+
+  >>> class VehicleRegistration(object):
+  ...     implements(IVehicleRegistration)
+  ...
+  ...     def __init__(self, **kw):
+  ...         for name, value in kw.items():
+  ...             setattr(self, name, value)
+
+The schema above can be separated into basic, license, and car information,
+where the latter two will be placed into groups. First we create the two
+groups:
+
+  >>> from z3c.form import field
+  >>> from z3c.form.group import Group
+
+  >>> class LicenseGroup(Group):
+  ...     label = u'License'
+  ...     fields = field.Fields(IVehicleRegistration).select(
+  ...         'license', 'address')
+
+  >>> class CarGroup(Group):
+  ...     label = u'Car'
+  ...     fields = field.Fields(IVehicleRegistration).select(
+  ...         'model', 'make', 'year')
+
+Most of the group is setup like any other (sub)form. Additionally, you can
+specify a label, which is a human-readable string that can be used for layout
+purposes.
+
+Let's now create an extjs form for the entire vehicle registration. In
+comparison to a regular form, you only need to add the ``ExtJSGroupForm``
+as one of the base classes. The groups are specified in a simple tuple:
+
+  >>> class RegistrationForm(group.ExtJSGroupForm, testing.TestingForm, form.ExtJSForm):
+  ...     ignoreContext = True
+  ...     fields = field.Fields(IVehicleRegistration).select(
+  ...         'firstName', 'lastName')
+  ...     groups = (LicenseGroup, CarGroup)
+  ...
+  ...     @form.buttonAndHandler(title=u'Save', success='handleSave')
+  ...     def handleSave(self):
+  ...         pass
+
+
+Note: The order of the base classes is very important here. The ``ExtJSGroupForm``
+class must be left of the ``ExtJSForm`` class, because the ``ExtJSGroupForm`` class
+overrides some methods of the ``ExtJSForm`` class.
+
+Now we can instantiate the form:
+
+  >>> request = testing.TestRequest()
+
+  >>> myForm = RegistrationForm(None, request)
+  >>> myForm.update()
+
+After the form is updated the tuple of group classes is converted to group
+instances:
+
+  >>> myForm.groups
+  (<LicenseGroup object at ...>, <CarGroup object at ...>)
+
+If we happen to update the form again, the groups that have
+already been converted to instances ares skipped.
+
+  >>> myForm.update()
+  >>> myForm.groups
+  (<LicenseGroup object at ...>, <CarGroup object at ...>)
+
+So far, everything works as in z3c.form except base classes.
+
+Now we can invoke the form and try to extract the data.
+   
+   >>> data, errors = myForm.extractData()
+
+Since we have not entered in any data, there will be errors.
+
+   >>> len(errors)
+   7
+
+As other ExtJSForm, error are propafated to the client side as a json response.
+
+  >>> from pprint import pprint
+  >>> pprint(myForm.jsonResponse)
+  {'errors': {'form-widgets-address': u'Required input is missing.',
+              'form-widgets-firstName': u'Required input is missing.',
+              'form-widgets-lastName': u'Required input is missing.',
+              'form-widgets-license': u'Required input is missing.',
+              'form-widgets-make': u'Required input is missing.',
+              'form-widgets-model': u'Required input is missing.',
+              'form-widgets-year': u'Required input is missing.'},
+   'formErrors': [],
+   'success': False}
+
+We can now get the form definition
+
+  >>> pprint(interfaces.IExtJSComponent(myForm).getConfig()['items'])
+  [{'allowBlank': False,                                                                                    
+      'fieldLabel': u'First Name',                                                                            
+      'id': 'form-widgets-firstName',                                                                         
+      'itemCls': 'required',                                                                                  
+      'minLength': 0,                                                                                         
+      'name': 'form.widgets.firstName',                                                                       
+      'value': u'',                                                                                           
+      'xtype': 'textfield'},                                                                                  
+     {'allowBlank': False,                                                                                    
+      'fieldLabel': u'Last Name',                                                                             
+      'id': 'form-widgets-lastName',                                                                          
+      'itemCls': 'required',                                                                                  
+      'minLength': 0,                                                                                         
+      'name': 'form.widgets.lastName',
+      'value': u'',
+      'xtype': 'textfield'},
+     {'items': [{'allowBlank': False,
+                 'fieldLabel': u'License',
+                 'id': 'form-widgets-license',
+                 'itemCls': 'required',
+                 'minLength': 0,
+                 'name': 'form.widgets.license',
+                 'value': u'',
+                 'xtype': 'textfield'},
+                {'allowBlank': False,
+                 'fieldLabel': u'Address',
+                 'id': 'form-widgets-address',
+                 'itemCls': 'required',
+                 'minLength': 0,
+                 'name': 'form.widgets.address',
+                 'value': u'',
+                 'xtype': 'textfield'}],
+      'title': u'License',
+      'xtype': 'panel'},
+     {'items': [{'allowBlank': False,
+                 'fieldLabel': u'Model',
+                 'id': 'form-widgets-model',
+                 'itemCls': 'required',
+                 'minLength': 0,
+                 'name': 'form.widgets.model',
+                 'value': u'',
+                 'xtype': 'textfield'},
+                {'allowBlank': False,
+                 'fieldLabel': u'Make',
+                 'id': 'form-widgets-make',
+                 'itemCls': 'required',
+                 'minLength': 0,
+                 'name': 'form.widgets.make',
+                 'value': u'',
+                 'xtype': 'textfield'},
+                {'allowBlank': False,
+                 'fieldLabel': u'Year',
+                 'id': 'form-widgets-year',
+                 'itemCls': 'required',
+                 'minLength': 0,
+                 'name': 'form.widgets.year',
+                 'value': u'',
+                 'xtype': 'textfield'}],
+      'title': u'Car',
+      'xtype': 'panel'}]
+
+
+Ext JS provide a lot of way to support grouping fields.
+
+ * Panel
+ * TabPanel
+ * FieldSet
+
+By default, group are rendered as 'panel'
+
+  >>> interfaces.IExtJSComponent(myForm.groups[0])._getConfig()['xtype']
+  'panel'
+
+You can override this attribute by providing an adapter for IExtJSConfigValue
+
+  >>> class ConfigAdapter(object):
+  ...     zope.component.adapts(zope.interface.Interface,
+  ...           zope.interface.Interface,  LicenseGroup)
+  ...     zope.interface.implements(interfaces.IExtJSConfigValue)
+  ...
+  ...     def __init__(self, context, request, form):
+  ...         pass
+  ...
+  ...     def get(self):
+  ...         return dict(xtype='tabpanel')
+  >>> zope.component.provideAdapter(ConfigAdapter)
+  >>> interfaces.IExtJSComponent(myForm.groups[0])._getConfig()['xtype']
+  'tabpanel'
+
+Only the LicenseGroup class is affected by the adapter
+  >>> interfaces.IExtJSComponent(myForm.groups[1])._getConfig()['xtype']
+  'panel'
+
+  >>> from zope.component import getGlobalSiteManager
+  >>> gsm = getGlobalSiteManager()
+  >>> gsm.unregisterAdapter(ConfigAdapter)
+  True
+
+You can use the same strategy to provide additional attributes for each object
+implementing ``z3c.form.interfaces.IForm``
+
+By mixing Nested group and IExtJSComponent adapters you can build complex Extjs
+form. 
+
+Let's create a FormPanel with 1 fieldset and 2 tabs
+  >>> class PersonFieldset(Group):
+  ...     label = 'Person'
+  ...     fields = field.Fields(IVehicleRegistration).select(
+  ...         'firstName', 'lastName')
+
+  >>> class TabGroup(Group):
+  ...     groups = (LicenseGroup, CarGroup)
+
+  >>> class RegistrationTabForm(group.ExtJSGroupForm, testing.TestingForm, form.ExtJSForm):
+  ...     ignoreContext = True
+  ...     groups = (PersonFieldset, TabGroup)
+  ...
+  ...     @form.buttonAndHandler(title=u'Save', success='handleSave')
+  ...     def handleSave(self):
+  ...         pass
+  
+  >>> class TabAdapter(object):
+  ...     zope.component.adapts(zope.interface.Interface,
+  ...           zope.interface.Interface,  TabGroup)
+  ...     zope.interface.implements(interfaces.IExtJSConfigValue)
+  ...
+  ...     def __init__(self, context, request, form):
+  ...         pass
+  ...
+  ...     def get(self):
+  ...         return dict(xtype='tabpanel')
+  
+  >>> class FieldsetAdapter(object):
+  ...     zope.component.adapts(zope.interface.Interface,
+  ...           zope.interface.Interface,  PersonFieldset)
+  ...     zope.interface.implements(interfaces.IExtJSConfigValue)
+  ...
+  ...     def __init__(self, context, request, form):
+  ...         pass
+  ...
+  ...     def get(self):
+  ...         return dict(xtype='fieldset')
+  
+  >>> zope.component.provideAdapter(FieldsetAdapter)
+  >>> zope.component.provideAdapter(TabAdapter)
+  
+  >>> tabForm = RegistrationTabForm(None, request)
+  >>> tabForm.update()
+  >>> pprint(interfaces.IExtJSComponent(tabForm).getConfig())
+  {'ajaxHandlers': {'form-buttons-save': 'http://127.0.0.1/index.html/@@ajax/save'},                        
+  'buttons': [{'handler': {'success': 'handleSave'},                                                       
+               'id': 'form-buttons-save',                                                                  
+               'name': 'form.buttons.save',                                                                
+               'text': u'Save',                                                                            
+               'title': u'Save',                                                                           
+               'url': 'http://127.0.0.1/index.html/@@ajax/save',                                           
+               'xtype': 'button'}],                                                                        
+  'id': 'form',                                                                                            
+  'items': [{'items': [{'allowBlank': False,                                                               
+                        'fieldLabel': u'First Name',                                                       
+                        'id': 'form-widgets-firstName',                                                    
+                        'itemCls': 'required',                                                             
+                        'minLength': 0,                                                                    
+                        'name': 'form.widgets.firstName',                                                  
+                        'value': u'',                                                                      
+                        'xtype': 'textfield'},                                                             
+                       {'allowBlank': False,                                                               
+                        'fieldLabel': u'Last Name',                                                        
+                        'id': 'form-widgets-lastName',                                                     
+                        'itemCls': 'required',                                                             
+                        'minLength': 0,                                                                    
+                        'name': 'form.widgets.lastName',                                                   
+                        'value': u'',                                                                      
+                        'xtype': 'textfield'}],                                                            
+             'title': 'Person',                                                                            
+             'xtype': 'fieldset'},                                                                         
+            {'items': [{'items': [{'allowBlank': False,
+                                   'fieldLabel': u'License',
+                                   'id': 'form-widgets-license',
+                                   'itemCls': 'required',
+                                   'minLength': 0,
+                                   'name': 'form.widgets.license',
+                                   'value': u'',
+                                   'xtype': 'textfield'},
+                                  {'allowBlank': False,
+                                   'fieldLabel': u'Address',
+                                   'id': 'form-widgets-address',
+                                   'itemCls': 'required',
+                                   'minLength': 0,
+                                   'name': 'form.widgets.address',
+                                   'value': u'',
+                                   'xtype': 'textfield'}],
+                        'title': u'License',
+                        'xtype': 'panel'},
+                       {'items': [{'allowBlank': False,
+                                   'fieldLabel': u'Model',
+                                   'id': 'form-widgets-model',
+                                   'itemCls': 'required',
+                                   'minLength': 0,
+                                   'name': 'form.widgets.model',
+                                   'value': u'',
+                                   'xtype': 'textfield'},
+                                  {'allowBlank': False,
+                                   'fieldLabel': u'Make',
+                                   'id': 'form-widgets-make',
+                                   'itemCls': 'required',
+                                   'minLength': 0,
+                                   'name': 'form.widgets.make',
+                                   'value': u'',
+                                   'xtype': 'textfield'},
+                                  {'allowBlank': False,
+                                   'fieldLabel': u'Year',
+                                   'id': 'form-widgets-year',
+                                   'itemCls': 'required',
+                                   'minLength': 0,
+                                   'name': 'form.widgets.year',
+                                   'value': u'',
+                                   'xtype': 'textfield'}],
+                        'title': u'Car',
+                        'xtype': 'panel'}],
+             'xtype': 'tabpanel'}],
+  'submitURL': 'http://127.0.0.1',
+  'xtype': 'formpanel'}
+


Property changes on: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/group.txt
___________________________________________________________________
Added: svn:keywords
   + Date Author Id Revision

Modified: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/interfaces.py
===================================================================
--- z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/interfaces.py	2009-02-27 10:35:04 UTC (rev 97338)
+++ z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/interfaces.py	2009-02-27 10:38:44 UTC (rev 97339)
@@ -18,13 +18,10 @@
 __docformat__ = "reStructuredText"
 
 import zope.interface
-import zope.schema
 
 from z3c.form.interfaces import ITextWidget
 from z3c.form.interfaces import ISingleCheckBoxWidget
 from z3c.form.interfaces import IForm
-from z3c.form.interfaces import IGroup
-from z3c.form.interfaces import IGroupForm
 from z3c.form.interfaces import IButton
 from z3c.form.interfaces import IButtonAction
 from z3c.form.interfaces import ISelectionManager
@@ -41,6 +38,7 @@
         title=u'Failure function',
         required=False)
 
+
 class IClientButtonAction(IButtonAction):
     success = zope.schema.ASCIILine(
         title=u'Success function',
@@ -75,6 +73,15 @@
     """
 
 
+class IExtJSConfigValue(zope.interface.Interface):
+    """An object providing additional or overriding config
+    attributes as a dict
+    """
+
+    def get():
+        """Returns the value"""
+
+
 class IExtJSComponent(zope.interface.Interface):
     """An object that represents and ExtJS component.
 
@@ -89,18 +96,17 @@
         serialization form.
         """
 
+
 class IJSProperties(ISelectionManager):
     """A Selection Manager for JavaScript Properties"""
 
 
-class IExtJSGroup(IGroup):
-    """The EXTJS translation of a group of fiels/widgets within a form
-
-    see z3c.form.interfaces.IGroup
+class IBaseForm(zope.interface.Interface):
+    """Marker interface for discribing  z3c.form.form.BaseForm
     """
 
 
-class IExtJSGroupForm(IGroupForm):
+class IExtJSGroupForm(zope.interface.Interface):
     """An extjs form that supports groups
 
     see z3c.form.interfaces.IGroupForm

Modified: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/testing.py
===================================================================
--- z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/testing.py	2009-02-27 10:35:04 UTC (rev 97338)
+++ z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/testing.py	2009-02-27 10:38:44 UTC (rev 97339)
@@ -28,6 +28,7 @@
 from z3c.form.interfaces import ISelectWidget
 from z3c.form.interfaces import ISingleCheckBoxWidget
 from z3c.form.interfaces import IRadioWidget
+from z3c.form.form import BaseForm
 
 from z3c.form.testing import setupFormDefaults
 from z3c.formext import component, form, converter, interfaces
@@ -103,8 +104,11 @@
             (None, None, None,
                 ISingleCheckBoxWidget, zope.schema.interfaces.IField),
             interfaces.IExtJSComponent)
+    zope.component.provideAdapter(component.Panel)
+    zope.component.provideAdapter(component.GroupPanel)
     zope.component.provideAdapter(component.FormPanel)
     zope.component.provideAdapter(component.ExtFormPanel)
+    zope.component.provideAdapter(component.ExtGroupFormPanel)
     zope.component.provideAdapter(component.Button)
     zope.component.provideAdapter(component.ClientButton)
     zope.component.provideAdapter(form.ClientButtonAction,
@@ -115,6 +119,7 @@
     setupExtJSComponents()
     setupFormDefaults()
     setupTraversing()
+    zope.interface.classImplements(BaseForm, interfaces.IBaseForm)
     zope.component.provideAdapter(converter.ExtJSDateDataConverter)
     zope.component.provideAdapter(converter.ExtJSSingleCheckBoxDataConverter)
 

Modified: z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/tests/test_doc.py
===================================================================
--- z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/tests/test_doc.py	2009-02-27 10:35:04 UTC (rev 97338)
+++ z3c.formext/branches/sagblmi-morecomponent/src/z3c/formext/tests/test_doc.py	2009-02-27 10:38:44 UTC (rev 97339)
@@ -61,4 +61,11 @@
             optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
             ),
 
+        doctest.DocFileSuite(
+            '../group.txt',
+            setUp=placelesssetup.setUp, tearDown=placelesssetup.tearDown,
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+            ),
+
+
         ))



More information about the Checkins mailing list