[Checkins] SVN: z3c.form/trunk/ Fixed badness related to button actions. The API is much cleaner now.

Stephan Richter srichter at cosmos.phy.tufts.edu
Fri Jul 6 11:11:11 EDT 2007


Log message for revision 77519:
  Fixed badness related to button actions. The API is much cleaner now.
   
  

Changed:
  U   z3c.form/trunk/CHANGES.txt
  U   z3c.form/trunk/src/z3c/form/adding.txt
  U   z3c.form/trunk/src/z3c/form/browser/button.py
  U   z3c.form/trunk/src/z3c/form/browser/submit.py
  U   z3c.form/trunk/src/z3c/form/button.py
  U   z3c.form/trunk/src/z3c/form/button.txt
  U   z3c.form/trunk/src/z3c/form/configure.zcml
  U   z3c.form/trunk/src/z3c/form/form.txt
  U   z3c.form/trunk/src/z3c/form/group.txt
  U   z3c.form/trunk/src/z3c/form/interfaces.py
  U   z3c.form/trunk/src/z3c/form/subform.txt
  U   z3c.form/trunk/src/z3c/form/testing.py

-=-
Modified: z3c.form/trunk/CHANGES.txt
===================================================================
--- z3c.form/trunk/CHANGES.txt	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/CHANGES.txt	2007-07-06 15:11:10 UTC (rev 77519)
@@ -5,6 +5,11 @@
 Version 1.5.0 (??/??/2007)
 -------------------------
 
+- Feature: Restructured the approach to customize button actions, by requiring
+  the adapter to provide a new interface ``IButtonAction``. Also, an adapter
+  is now provided by default, still allowing cusotmization using the usual
+  methods though.
+
 - Feature: Added button widget. While it is not very useful without
   Javascript, it still belongs into this package for completion.
 
@@ -28,6 +33,8 @@
 
 - Bug/Feature: Correctly create labels for radio button choices.
 
+- Bug: Button actions were never updated in the actions manager.
+
 - Bug: Added tests for textarea widget.
 
 

Modified: z3c.form/trunk/src/z3c/form/adding.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/adding.txt	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/adding.txt	2007-07-06 15:11:10 UTC (rev 77519)
@@ -85,7 +85,8 @@
         </div>
         <div class="action">
           <input type="submit" id="form-buttons-add"
-                 name="form.buttons.add" class="submitWidget" value="Add" />
+                 name="form.buttons.add" class="submitWidget button-field"
+                 value="Add" />
         </div>
       </form>
     </body>

Modified: z3c.form/trunk/src/z3c/form/browser/button.py
===================================================================
--- z3c.form/trunk/src/z3c/form/browser/button.py	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/browser/button.py	2007-07-06 15:11:10 UTC (rev 77519)
@@ -31,7 +31,8 @@
     klass = u'buttonWidget'
 
     def update(self):
-        super(ButtonWidget, self).update()
+        # We do not need to use the widget's update method, because it is
+        # mostly about ectracting the value, which we do not need to do.
         widget.addFieldClass(self)
 
 

Modified: z3c.form/trunk/src/z3c/form/browser/submit.py
===================================================================
--- z3c.form/trunk/src/z3c/form/browser/submit.py	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/browser/submit.py	2007-07-06 15:11:10 UTC (rev 77519)
@@ -19,22 +19,17 @@
 import zope.component
 import zope.interface
 
-from z3c.form import interfaces, widget
-from z3c.form.widget import Widget, FieldWidget
-from z3c.form.browser import widget
+from z3c.form import interfaces
+from z3c.form.widget import FieldWidget
+from z3c.form.browser import button
 
 
-class SubmitWidget(widget.HTMLInputWidget, Widget):
+class SubmitWidget(button.ButtonWidget):
     """A submit button of a form."""
     zope.interface.implementsOnly(interfaces.ISubmitWidget)
-
     klass = u'submitWidget'
 
-    def update(self):
-        super(SubmitWidget, self).update()
-        widget.addFieldClass(self)
 
-
 @zope.component.adapter(interfaces.IButton, interfaces.IFormLayer)
 @zope.interface.implementer(interfaces.IFieldWidget)
 def SubmitFieldWidget(field, request):

Modified: z3c.form/trunk/src/z3c/form/button.py
===================================================================
--- z3c.form/trunk/src/z3c/form/button.py	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/button.py	2007-07-06 15:11:10 UTC (rev 77519)
@@ -185,10 +185,11 @@
 
 
 class ButtonAction(action.Action, submit.SubmitWidget, zope.location.Location):
-    zope.interface.implements(interfaces.IFieldWidget)
+    zope.interface.implements(interfaces.IButtonAction)
+    zope.component.adapts(interfaces.IFormLayer, interfaces.IButton)
 
-    def __init__(self, request, field, name):
-        action.Action.__init__(self, request, field.title, name)
+    def __init__(self, request, field):
+        action.Action.__init__(self, request, field.title)
         submit.SubmitWidget.__init__(self, request)
         self.field = field
 
@@ -213,33 +214,36 @@
 
     def update(self):
         """See z3c.form.interfaces.IActions."""
-        # Create a unique prefix
+        # Create a unique prefix.
         prefix = util.expandPrefix(self.form.prefix)
         prefix += util.expandPrefix(self.form.buttons.prefix)
+        # Walk through each field, making an action out of it.
         for name, button in self.form.buttons.items():
-            # Only create an action for the button, if the condition is
-            # fulfilled
+            # Step 1: Only create an action for the button, if the condition is
+            #         fulfilled.
             if button.condition is not None and not button.condition(self.form):
                 continue
-            fullName = prefix + name
-            # Look up a button action factory
+            # Step 2: Get the action for the given button.
             if button.actionFactory is not None:
                 buttonAction = button.actionFactory(self.request, button)
-                buttonAction.name = fullName
             else:
-                buttonAction = zope.component.queryMultiAdapter(
-                    (self.request, button), interfaces.IFieldWidget)
-                if buttonAction is not None:
-                    buttonAction.name = fullName
-                    # if one is not found, use the default
-                else:
-                    buttonAction = ButtonAction(self.request, button, fullName)
-            # Look up a potential custom title for the action.
+                buttonAction = zope.component.getMultiAdapter(
+                    (self.request, button), interfaces.IButtonAction)
+            # Step 3: Set the name on the button
+            fullName = prefix + name
+            buttonAction.name = fullName
+            # Step 4: Set any custom attribute values.
             title = zope.component.queryMultiAdapter(
                 (self.form, self.request, self.content, button, self),
                 interfaces.IValue, name='title')
             if title is not None:
                 buttonAction.title = title.get()
+            # Step 5: Set the form
+            buttonAction.form = self.form
+            zope.interface.alsoProvides(buttonAction, interfaces.IFormAware)
+            # Step 6: Update the new action
+            buttonAction.update()
+            # Step 7: Add the widget to the manager
             self._data_keys.append(name)
             self._data_values.append(buttonAction)
             self._data[name] = buttonAction

Modified: z3c.form/trunk/src/z3c/form/button.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/button.txt	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/button.txt	2007-07-06 15:11:10 UTC (rev 77519)
@@ -48,8 +48,13 @@
   >>> request = TestRequest()
   >>> form = Form()
 
+We also have to register a button action factory for the buttons:
+
+  >>> zope.component.provideAdapter(
+  ...     button.ButtonAction, provides=interfaces.IButtonAction)
+
 Action managers are instantiated using the form, request, and
-context/content. A special button-action-manager implementation is avaialble
+context/content. A special button-action-manager implementation is available
 in the ``button`` package:
 
   >>> actions = button.ButtonActions(form, request, None)
@@ -65,21 +70,15 @@
 
 It is possible to customize how a button is transformed into an action
 by registering an adapter for the request and the button that provides
-IFieldWidget.
+``IButtonAction``.
 
   >>> import zope.component
   >>> from zope.publisher.interfaces.browser import IBrowserRequest
   >>> class CustomButtonAction(button.ButtonAction):
   ...     """Custom Button Action Class."""
-  ...     zope.interface.implements(interfaces.IFieldWidget)
-  ...     zope.component.adapts(IBrowserRequest, interfaces.IButton)
-  ...
-  ...     def __init__(self, request, field):
-  ...         super(CustomButtonAction, self).__init__(request, field, None)
 
-  >>> zope.component.provideAdapter(CustomButtonAction,
-  ...                    (IBrowserRequest,interfaces.IButton),
-  ...                    interfaces.IFieldWidget)
+  >>> zope.component.provideAdapter(
+  ...     CustomButtonAction, provides=interfaces.IButtonAction)
 
 Now if we rerun update we will get this other ButtonAction
 implementation.
@@ -144,7 +143,7 @@
 
   >>> print actions['apply'].render()
   <input type="submit" id="form-buttons-apply"
-         name="form.buttons.apply" class="submitWidget"
+         name="form.buttons.apply" class="submitWidget button-field"
          value="Apply" />
 
 So displaying is nice, but how do button handlers get executed? The action

Modified: z3c.form/trunk/src/z3c/form/configure.zcml
===================================================================
--- z3c.form/trunk/src/z3c/form/configure.zcml	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/configure.zcml	2007-07-06 15:11:10 UTC (rev 77519)
@@ -78,8 +78,12 @@
       factory=".term.BoolTerms"
       />
 
-  <!-- Action Managers and Handlers -->
+  <!-- Actions, Action Managers and Handlers -->
   <adapter
+      factory=".button.ButtonAction"
+      provides=".interfaces.IButtonAction"
+      />
+  <adapter
       factory=".button.ButtonActions"
       />
   <adapter

Modified: z3c.form/trunk/src/z3c/form/form.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/form.txt	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/form.txt	2007-07-06 15:11:10 UTC (rev 77519)
@@ -321,7 +321,7 @@
         </div>
         <div class="action">
           <input type="submit" id="form-buttons-add" name="form.buttons.add"
-                 class="submitWidget" value="Add" />
+                 class="submitWidget button-field" value="Add" />
         </div>
       </form>
     </body>
@@ -429,7 +429,7 @@
         </div>
         <div class="action">
           <input type="submit" id="form-buttons-add" name="form.buttons.add"
-                 class="submitWidget" value="Add" />
+                 class="submitWidget button-field" value="Add" />
         </div>
       </form>
     </body>
@@ -617,11 +617,11 @@
   ...
   <div class="action">
     <input type="submit" id="form-buttons-add" name="form.buttons.add"
-           class="submitWidget" value="Add" />
+           class="submitWidget button-field" value="Add" />
   </div>
   <div class="action">
     <input type="submit" id="form-buttons-cancel" name="form.buttons.cancel"
-           class="submitWidget" value="Cancel" />
+           class="submitWidget button-field" value="Cancel" />
   </div>
   ...
 
@@ -717,7 +717,7 @@
         </div>
         <div class="action">
           <input type="submit" id="form-buttons-apply" name="form.buttons.apply"
-                 class="submitWidget" value="Apply" />
+                 class="submitWidget button-field" value="Apply" />
         </div>
       </form>
     </body>
@@ -782,7 +782,7 @@
         </div>
         <div class="action">
           <input type="submit" id="form-buttons-apply" name="form.buttons.apply"
-                 class="submitWidget" value="Apply" />
+                 class="submitWidget button-field" value="Apply" />
         </div>
       </form>
     </body>
@@ -932,7 +932,7 @@
         </div>
         <div class="action">
           <input type="submit" id="form-buttons-apply"
-                 name="form.buttons.apply" class="submitWidget"
+                 name="form.buttons.apply" class="submitWidget button-field"
                  value="Apply" />
         </div>
       </form>

Modified: z3c.form/trunk/src/z3c/form/group.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/group.txt	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/group.txt	2007-07-06 15:11:10 UTC (rev 77519)
@@ -152,7 +152,7 @@
         </fieldgroup>
         <div class="action">
           <input type="submit" id="form-buttons-add"
-                 name="form.buttons.add" class="submitWidget"
+                 name="form.buttons.add" class="submitWidget button-field"
                  value="Add" />
         </div>
       </form>
@@ -341,7 +341,7 @@
         </fieldgroup>
         <div class="action">
           <input type="submit" id="form-buttons-apply"
-                 name="form.buttons.apply" class="submitWidget"
+                 name="form.buttons.apply" class="submitWidget button-field"
                  value="Apply" />
         </div>
       </form>

Modified: z3c.form/trunk/src/z3c/form/interfaces.py
===================================================================
--- z3c.form/trunk/src/z3c/form/interfaces.py	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/interfaces.py	2007-07-06 15:11:10 UTC (rev 77519)
@@ -450,7 +450,6 @@
         default=False,
         required=False)
 
-
     def update():
         """Setup widgets."""
 
@@ -459,6 +458,18 @@
         """
 
 
+class IFieldWidget(zope.interface.Interface):
+    """Offers a field attribute.
+
+    For advanced uses the widget will make decisions based on the field
+    it is rendered for.
+    """
+
+    field = zope.schema.Field(
+        title=_('Field'),
+        description=_('The schema field which the widget is representing.'),
+        required=True)
+
 # ----[ Actions ]------------------------------------------------------------
 
 class IAction(zope.interface.Interface):
@@ -518,6 +529,10 @@
     """Button manager."""
 
 
+class IButtonAction(IAction, IWidget, IFieldWidget):
+    """Button action."""
+
+
 class IButtonHandlers(zope.interface.Interface):
     """A collection of handlers for buttons."""
 
@@ -588,19 +603,6 @@
     form = zope.schema.Field()
 
 
-class IFieldWidget(zope.interface.Interface):
-    """Offers a field attribute.
-
-    For advanced uses the widget will make decisions based on the field
-    it is rendered for.
-    """
-
-    field = zope.schema.Field(
-        title=_('Field'),
-        description=_('The schema field which the widget is representing.'),
-        required=True)
-
-
 class IForm(zope.interface.Interface):
     """Form"""
 

Modified: z3c.form/trunk/src/z3c/form/subform.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/subform.txt	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/subform.txt	2007-07-06 15:11:10 UTC (rev 77519)
@@ -131,13 +131,13 @@
           </div>
           <div class="action">
             <input type="submit" id="owner-buttons-apply"
-                   name="owner.buttons.apply" class="submitWidget"
+                   name="owner.buttons.apply" class="submitWidget button-field"
                    value="Apply" />
           </div>
         </fieldset>
         <div class="action">
           <input type="submit" id="car-buttons-apply"
-                 name="car.buttons.apply" class="submitWidget"
+                 name="car.buttons.apply" class="submitWidget button-field"
                  value="Apply" />
         </div>
       </form>
@@ -203,13 +203,13 @@
           </div>
           <div class="action">
             <input type="submit" id="owner-buttons-apply"
-                   name="owner.buttons.apply" class="submitWidget"
+                   name="owner.buttons.apply" class="submitWidget button-field"
                    value="Apply" />
           </div>
         </fieldset>
         <div class="action">
           <input type="submit" id="car-buttons-apply"
-                 name="car.buttons.apply" class="submitWidget"
+                 name="car.buttons.apply" class="submitWidget button-field"
                  value="Apply" />
         </div>
       </form>
@@ -311,7 +311,7 @@
         </fieldset>
         <div class="action">
           <input type="submit" id="car-buttons-apply"
-                 name="car.buttons.apply" class="submitWidget"
+                 name="car.buttons.apply" class="submitWidget button-field"
                  value="Apply" />
         </div>
       </form>
@@ -407,7 +407,7 @@
         </fieldset>
         <div class="action">
           <input type="submit" id="car-buttons-apply"
-                 name="car.buttons.apply" class="submitWidget"
+                 name="car.buttons.apply" class="submitWidget button-field"
                  value="Apply" />
         </div>
       </form>
@@ -578,13 +578,13 @@
     </div>
     <div class="action">
       <input type="submit" id="owner-buttons-apply"
-           name="owner.buttons.apply" class="submitWidget"
+           name="owner.buttons.apply" class="submitWidget button-field"
            value="Apply" />
     </div>
     </fieldset>
     <div class="action">
       <input type="submit" id="car-buttons-apply"
-           name="car.buttons.apply" class="submitWidget"
+           name="car.buttons.apply" class="submitWidget button-field"
            value="Apply" />
     </div>
   </form>

Modified: z3c.form/trunk/src/z3c/form/testing.py
===================================================================
--- z3c.form/trunk/src/z3c/form/testing.py	2007-07-06 14:58:10 UTC (rev 77518)
+++ z3c.form/trunk/src/z3c/form/testing.py	2007-07-06 15:11:10 UTC (rev 77519)
@@ -136,6 +136,9 @@
     # Adapter for providing terms to radio list and other widgets
     zope.component.provideAdapter(term.ChoiceTerms)
     zope.component.provideAdapter(term.BoolTerms)
+    # Adapter to create an action from a button
+    zope.component.provideAdapter(
+        button.ButtonAction, provides=interfaces.IButtonAction)
     # Adapter to use form.buttons to generate actions
     zope.component.provideAdapter(button.ButtonActions)
     # Adapter to use form.handlers to generate handle actions



More information about the Checkins mailing list