[Zope3-checkins] CVS: Zope3/src/zope/app/browser/form - widget.py:1.29.4.5

Fred L. Drake, Jr. fred@zope.com
Mon, 5 May 2003 16:11:32 -0400


Update of /cvs-repository/Zope3/src/zope/app/browser/form
In directory cvs.zope.org:/tmp/cvs-serv21443

Modified Files:
      Tag: schema-vocabulary-branch
	widget.py 
Log Message:
- add a basic multi-selection widget for vocabularies
- various minor refactorings to support this


=== Zope3/src/zope/app/browser/form/widget.py 1.29.4.4 => 1.29.4.5 ===
--- Zope3/src/zope/app/browser/form/widget.py:1.29.4.4	Mon May  5 15:11:04 2003
+++ Zope3/src/zope/app/browser/form/widget.py	Mon May  5 16:11:32 2003
@@ -769,40 +769,16 @@
         return self.textForValue(term)
 
 
-class VocabularyEditWidget(VocabularyWidgetBase):
-    """Single single-selection edit widget.
-
-    This widget can be used when the number of selections isn't going
-    to be very large.
-    """
-    __implements__ = SingleItemsWidget.__implements__
-    propertyNames = (SingleItemsWidget.propertyNames +
-                     ['firstItem', 'size', 'extra']
-                     )
+class VocabularyEditWidgetBase(VocabularyWidgetBase):
+    propertyNames = (VocabularyWidgetBase.propertyNames
+                     + ['extra', 'size', 'tag'])
     extra = ''
-    firstItem = False
     size = 5
     tag = 'select'
 
-    def render(self, value):
-        rendered_items = self.renderItems(value)
-        return renderElement(self.getValue('tag'),
-                             type = self.getValue('type'),
-                             name = self.name,
-                             id = self.name,
-                             cssClass = self.getValue('cssClass'),
-                             size = self.getValue('size'),
-                             contents = "\n".join(rendered_items),
-                             extra = self.getValue('extra'))
-
-    def renderItems(self, value):
-        vocabulary = self.context
-
-        # check if we want to select first item
-        if (value == self._missing
-            and getattr(self.context, 'firstItem', False)
-            and len(vocabulary) > 0):
-            value = iter(vocabulary).next().value
+    def renderItemsWithValues(self, values):
+        """Render the list of possible values, with those found in
+        'values' being marked as selected."""
 
         cssClass = self.getValue('cssClass')
 
@@ -810,11 +786,11 @@
         # vocabulary, so that need not be considered here
         rendered_items = []
         count = 0
-        for term in vocabulary:
+        for term in self.context:
             item_value = term.value
             item_text = self.textForValue(term)
 
-            if item_value == value:
+            if item_value in values:
                 rendered_item = self.renderSelectedItem(count,
                                                         item_text,
                                                         item_value,
@@ -839,6 +815,70 @@
     def renderSelectedItem(self, index, text, value, name, cssClass):
         return renderElement('option', contents=text, value=value,
                               cssClass=cssClass, selected=None)
+
+
+class VocabularyEditWidget(VocabularyEditWidgetBase):
+    """Vocabulary-backed single-selection edit widget.
+
+    This widget can be used when the number of selections isn't going
+    to be very large.
+    """
+    __implements__ = SingleItemsWidget.__implements__
+    propertyNames = (VocabularyEditWidgetBase.propertyNames
+                     + ['firstItem'])
+    firstItem = False
+
+    def render(self, value):
+        rendered_items = self.renderItems(value)
+        return renderElement(self.getValue('tag'),
+                             type = self.getValue('type'),
+                             name = self.name,
+                             id = self.name,
+                             cssClass = self.getValue('cssClass'),
+                             size = self.getValue('size'),
+                             contents = "\n".join(rendered_items),
+                             extra = self.getValue('extra'))
+
+    def renderItems(self, value):
+        vocabulary = self.context
+
+        # check if we want to select first item
+        if (value == self._missing
+            and getattr(self.context, 'firstItem', False)
+            and len(vocabulary) > 0):
+            # Grab the first item from the iterator:
+            values = [iter(vocabulary).next().value]
+        elif value != self._missing:
+            values = [value]
+        else:
+            values = ()
+
+        return VocabularyEditWidgetBase.renderItemsWithValues(self, values)
+
+
+class VocabularyMultiEditWidget(VocabularyEditWidgetBase):
+    """Vocabulary-backed widget supporting multiple selections."""
+
+    def renderItems(self, value):
+        if value == self._missing:
+            values = ()
+        else:
+            values = list(value)
+        return VocabularyEditWidgetBase.renderItemsWithValues(self, values)
+
+    def render(self, value):
+        # All we really add here is the ':list' in the name argument
+        # to renderElement().
+        rendered_items = self.renderItems(value)
+        return renderElement(self.getValue('tag'),
+                             type = self.getValue('type'),
+                             name = self.name + ':list',
+                             multiple = None,
+                             id = self.name,
+                             cssClass = self.getValue('cssClass'),
+                             size = self.getValue('size'),
+                             contents = "\n".join(rendered_items),
+                             extra = self.getValue('extra'))
 
 
 # XXX Note, some HTML quoting is needed in renderTag and renderElement.