[Checkins] SVN: z3c.form/trunk/ - Feature: Implemented single checkbox widget that can be used for boolean

Stephan Richter srichter at cosmos.phy.tufts.edu
Tue Sep 4 18:32:36 EDT 2007


Log message for revision 79469:
  - Feature: Implemented single checkbox widget that can be used for boolean
    fields. They are not available by default but can be set using the
    ``widgetFactory`` attribute.
  
  

Changed:
  U   z3c.form/trunk/CHANGES.txt
  U   z3c.form/trunk/src/z3c/form/browser/checkbox.py
  U   z3c.form/trunk/src/z3c/form/browser/checkbox.txt
  U   z3c.form/trunk/src/z3c/form/configure.zcml
  U   z3c.form/trunk/src/z3c/form/converter.py
  U   z3c.form/trunk/src/z3c/form/converter.txt
  U   z3c.form/trunk/src/z3c/form/interfaces.py

-=-
Modified: z3c.form/trunk/CHANGES.txt
===================================================================
--- z3c.form/trunk/CHANGES.txt	2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/CHANGES.txt	2007-09-04 22:32:36 UTC (rev 79469)
@@ -5,6 +5,10 @@
 Version 1.7.0 (9/??/2007)
 -------------------------
 
+- Feature: Implemented single checkbox widget that can be used for boolean
+  fields. They are not available by default but can be set using the
+  ``widgetFactory`` attribute.
+
 - Bug: When rendering a widget the ``style`` attribute was not honored. Thanks
   to Andreas Reuleaux for reporting.
 

Modified: z3c.form/trunk/src/z3c/form/browser/checkbox.py
===================================================================
--- z3c.form/trunk/src/z3c/form/browser/checkbox.py	2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/browser/checkbox.py	2007-09-04 22:32:36 UTC (rev 79469)
@@ -21,9 +21,10 @@
 import zope.interface
 import zope.schema
 import zope.schema.interfaces
+from zope.schema import vocabulary
 from zope.i18n import translate
 
-from z3c.form import interfaces
+from z3c.form import interfaces, term
 from z3c.form.widget import SequenceWidget, FieldWidget
 from z3c.form.browser import widget
 
@@ -60,3 +61,24 @@
 def CheckBoxFieldWidget(field, request):
     """IFieldWidget factory for CheckBoxWidget."""
     return FieldWidget(field, CheckBoxWidget(request))
+
+
+class SingleCheckBoxWidget(CheckBoxWidget):
+    """Single Input type checkbox widget implementation."""
+    zope.interface.implementsOnly(interfaces.ISingleCheckBoxWidget)
+
+    klass = u'single-checkbox-widget'
+
+    def updateTerms(self):
+        if self.terms is None:
+            self.terms = term.Terms()
+            self.terms.terms = vocabulary.SimpleVocabulary((
+                vocabulary.SimpleTerm('selected', 'selected', self.label), ))
+        return self.terms
+
+
+ at zope.component.adapter(zope.schema.interfaces.IBool, interfaces.IFormLayer)
+ at zope.interface.implementer(interfaces.IFieldWidget)
+def SingleCheckBoxFieldWidget(field, request):
+    """IFieldWidget factory for CheckBoxWidget."""
+    return FieldWidget(field, SingleCheckBoxWidget(request))

Modified: z3c.form/trunk/src/z3c/form/browser/checkbox.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/browser/checkbox.txt	2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/browser/checkbox.txt	2007-09-04 22:32:36 UTC (rev 79469)
@@ -3,18 +3,18 @@
 ==============
 
 Note: the checkbox widget isn't registered for a field by default. You can use
-the widgetFactory argument of a IField object if you construct fields or
-set the custom widget factory on selected fields later.
+the ``widgetFactory`` argument of a ``IField`` object if you construct fields
+or set the custom widget factory on selected fields later.
 
-The CheckBoxWidget renders a checkbox input type field e.g.
-<input type="checkbox" />
+The ``CheckBoxWidget`` widget renders a checkbox input type field e.g.  <input
+type="checkbox" />
 
   >>> from zope.interface.verify import verifyClass
   >>> from zope.app.form.interfaces import IInputWidget
   >>> from z3c.form import interfaces
   >>> from z3c.form.browser import checkbox
 
-The TextWidget is a widget:
+The ``CheckboxWidget`` is a widget:
 
   >>> verifyClass(interfaces.IWidget, checkbox.CheckBoxWidget)
   True
@@ -80,7 +80,7 @@
     <label for="widget-id-0">
       <span class="label">yes</span>
     </label>
-  </span><span class="option">
+      </span><span class="option">
     <input type="checkbox" id="widget-id-1" name="widget.name:list"
            class="checkbox-widget" value="false" />
     <label for="widget-id-1">
@@ -110,3 +110,70 @@
     </label>
   </span>
   <input name="widget.name-empty-marker" type="hidden" value="1" />
+
+
+Single Checkbox Widget
+----------------------
+
+Instead of using the checkbox widget as an UI component to allow multiple
+selection from a list of choices, it can be also used by itself to toggle a
+selection, effectively making it a binary selector. So in this case it lends
+itself well as a boolean UI input component.
+
+The ``SingleCheckboxWidget`` is a widget:
+
+  >>> verifyClass(interfaces.IWidget, checkbox.SingleCheckBoxWidget)
+  True
+
+The widget can render a input field only by adapting a request:
+
+  >>> request = TestRequest()
+  >>> widget = checkbox.SingleCheckBoxWidget(request)
+
+Set a name and id for the widget:
+
+  >>> widget.id = 'widget-id'
+  >>> widget.name = 'widget.name'
+
+Such a widget provides the ``IWidget`` interface:
+
+  >>> interfaces.IWidget.providedBy(widget)
+  True
+
+For there to be a sensible output, we need to give the widget a label:
+
+  >>> widget.label = u'Do you want that?'
+
+  >>> widget.update()
+  >>> print widget.render()
+  <span class="option">
+    <input type="checkbox" id="widget-id-0"
+           name="widget.name:list"
+           class="single-checkbox-widget" value="selected" />
+    <label for="widget-id-0">
+      <span class="label">Do you want that?</span>
+    </label>
+  </span>
+  <input name="widget.name-empty-marker" type="hidden"
+         value="1" />
+
+Initially, the box is not checked. Changing the widget value to the selection
+value, ...
+
+  >>> widget.value = ['selected']
+
+will make the box checked:
+
+  >>> widget.update()
+  >>> print widget.render()
+  <span class="option">
+    <input type="checkbox" id="widget-id-0"
+           name="widget.name:list"
+           class="single-checkbox-widget" value="selected"
+           checked="checked" />
+    <label for="widget-id-0">
+      <span class="label">Do you want that?</span>
+    </label>
+  </span>
+  <input name="widget.name-empty-marker" type="hidden"
+         value="1" />

Modified: z3c.form/trunk/src/z3c/form/configure.zcml
===================================================================
--- z3c.form/trunk/src/z3c/form/configure.zcml	2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/configure.zcml	2007-09-04 22:32:36 UTC (rev 79469)
@@ -64,6 +64,9 @@
       factory=".converter.CollectionSequenceDataConverter"
       />
   <adapter
+      factory=".converter.BoolSingleCheckboxDataConverter"
+      />
+  <adapter
       factory=".converter.FieldWidgetDataConverter"
       />
 

Modified: z3c.form/trunk/src/z3c/form/converter.py
===================================================================
--- z3c.form/trunk/src/z3c/form/converter.py	2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/converter.py	2007-09-04 22:32:36 UTC (rev 79469)
@@ -284,3 +284,22 @@
         if isinstance(collectionType, tuple):
             collectionType = collectionType[-1]
         return collectionType([widget.terms.getValue(token) for token in value])
+
+
+class BoolSingleCheckboxDataConverter(BaseDataConverter):
+    "A special converter between boolean fields and single checkbox widgets."
+
+    zope.component.adapts(
+        zope.schema.interfaces.IBool, interfaces.ISingleCheckBoxWidget)
+
+    def toWidgetValue(self, value):
+        """Convert from Python bool to HTML representation."""
+        if value:
+            return ['selected']
+        return []
+
+    def toFieldValue(self, value):
+        """See interfaces.IDataConverter"""
+        if value and value[0] == 'selected':
+            return True
+        return False

Modified: z3c.form/trunk/src/z3c/form/converter.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/converter.txt	2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/converter.txt	2007-09-04 22:32:36 UTC (rev 79469)
@@ -602,3 +602,35 @@
 
   >>> seqWidget.terms
   <z3c.form.term.CollectionTerms object ...>
+
+
+Boolean to Single Checkbox Data Converter
+-----------------------------------------
+
+The conversion from any field to the single checkbox widget value is a special
+case, because it has to be defined what selecting the value means. In the case
+of the boolean field, "selected" means ``True`` and if unselected, ``False``
+is returned:
+
+  >>> boolField = zope.schema.Bool()
+
+  >>> bscbx = converter.BoolSingleCheckboxDataConverter(boolField, seqWidget)
+  >>> bscbx
+  <BoolSingleCheckboxDataConverter converts from Bool to SequenceWidget>
+
+Let's now convert boolean field to widget values:
+
+  >>> bscbx.toWidgetValue(True)
+  ['selected']
+  >>> bscbx.toWidgetValue(False)
+  []
+
+Converting back is equally simple:
+
+  >>> bscbx.toFieldValue(['selected'])
+  True
+  >>> bscbx.toFieldValue([])
+  False
+
+Note that this widget has no concept of missing value, since it can only
+represent two states by desgin.

Modified: z3c.form/trunk/src/z3c/form/interfaces.py
===================================================================
--- z3c.form/trunk/src/z3c/form/interfaces.py	2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/interfaces.py	2007-09-04 22:32:36 UTC (rev 79469)
@@ -438,6 +438,9 @@
 class ICheckBoxWidget(ISequenceWidget):
     """Checbox widget."""
 
+class ISingleCheckBoxWidget(ICheckBoxWidget):
+    """Single Checbox widget."""
+
 class IRadioWidget(ISequenceWidget):
     """Radio widget."""
 



More information about the Checkins mailing list