[Zope3-checkins] CVS: Zope3/src/zope/app/browser/form - vocabularywidget.py:1.1.2.2

Fred L. Drake, Jr. fred@zope.com
Fri, 16 May 2003 15:56:33 -0400


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

Modified Files:
      Tag: schema-vocabulary-branch
	vocabularywidget.py 
Log Message:
- reflect change in IVocabularyQueryView
- revise the VocabularyEditWidgetBase to handle query views and more
  of the composition of the widget components (subclasses can still
  override cleanly for more control)
- re-arrange classes for more logical organization


=== Zope3/src/zope/app/browser/form/vocabularywidget.py 1.1.2.1 => 1.1.2.2 ===
--- Zope3/src/zope/app/browser/form/vocabularywidget.py:1.1.2.1	Fri May 16 12:09:39 2003
+++ Zope3/src/zope/app/browser/form/vocabularywidget.py	Fri May 16 15:56:32 2003
@@ -124,54 +124,46 @@
         return self.textForValue(term)
 
 
-class VocabularyQueryViewBase(ViewSupport, BrowserView):
-    """Vocabulary query support base class."""
-
-    __implements__ = IVocabularyQueryView
-
-    # This specifically isn't a widget in it's own right, but is a
-    # form of BrowserView (conceptually).
-
-    tag = "div"
-
-    def setPrefix(self, prefix):
-        if not prefix.endswith("."):
-            prefix += "."
-        self._prefix = prefix
+class VocabularyMultiDisplayWidget(VocabularyWidgetBase):
 
-    def _render_element(self, cssClass, contents):
-        if contents:
-            return widget.renderElement(self.tag,
-                                        cssClass=cssClass,
-                                        contents="\n%s\n" % contents)
-        else:
-            return ""
+    propertyNames = (VocabularyWidgetBase.propertyNames
+                     + ['itemTag', 'tag'])
 
-    def renderInput(self):
-        return self._render_element("queryinput",
-                                    self.renderQueryInput())
+    itemTag = 'li'
+    tag = 'ol'
 
-    def renderResults(self):
-        results = self.getResults()
-        if results is not None:
-            return self._render_element("queryresults",
-                                        self.renderQueryResults(results))
+    def render(self, value):
+        if value == self._missing:
+            return widget.renderElement('span',
+                                        type=self.getValue('type'),
+                                        name=self.name,
+                                        id=self.name,
+                                        cssClass=self.getValue('cssClass'),
+                                        contents=_("(no values)"),
+                                        extra=self.getValue('extra'))
         else:
-            return ""
-
-    def renderQueryResults(self, results):
-        raise NotImplementedError(
-            "renderQueryResults() must be implemented by a subclass")
-
-    def renderQueryInput(self):
-        raise NotImplementedError(
-            "renderQueryInput() must be implemented by a subclass")
+            rendered_items = self.renderItems(value)
+            return widget.renderElement(self.getValue('tag'),
+                                        type=self.getValue('type'),
+                                        name=self.name,
+                                        id=self.name,
+                                        cssClass=self.getValue('cssClass'),
+                                        contents="\n".join(rendered_items),
+                                        extra=self.getValue('extra'))
 
-    def getResults(self):
-        # This is responsible for running the query against the query
-        # object (self.context), and returning a results object.  If
-        # there isn't a query in the form, returns None.
-        return None
+    def renderItems(self, value):
+        L = []
+        vocabulary = self.context
+        cssClass = self.getValue('cssClass') or ''
+        if cssClass:
+            cssClass += "-item"
+        tag = self.getValue('itemTag')
+        for v in value:
+            term = vocabulary.getTerm(v)
+            L.append(widget.renderElement(tag,
+                                          cssClass=cssClass,
+                                          contents=self.textForValue(term)))
+        return L
 
 
 class VocabularyEditWidgetBase(VocabularyWidgetBase):
@@ -192,15 +184,42 @@
             assert queryview is not None
             self.query = query
             self.queryview = queryview
-            # Use of a hyphen to form the prefix for the query widget
+            # Use of a hyphen to form the name for the query widget
             # ensures that it won't clash with anything else, since
-            # field names are normally Python identifier.
-            queryview.setPrefix(self.name + "-query")
+            # field names are normally Python identifiers.
+            queryview.setName(self.name + "-query")
 
     def setPrefix(self, prefix):
         VocabularyWidgetBase.setPrefix(self, prefix)
         if self.queryview is not None:
-            self.queryview.setPrefix(self.name + "-query")
+            self.queryview.setName(self.name + "-query")
+
+    def render(self, value):
+        contents = []
+        have_results = False
+        if self.queryview:
+            s = self.queryview.renderResults()
+            if s:
+                contents.append(self._div('queryresults', s))
+                s = self.queryview.renderInput()
+                contents.append(self._div('queryinput', s))
+                have_results = True
+        contents.append(self._div('currentvalue', self.renderValue(value)))
+        if self.queryview and not have_results:
+            s = self.queryview.renderInput()
+            if s:
+                contents.append(self._div('queryinput', s))
+        return self._div(self.getValue('cssClass'), "\n".join(contents),
+                         id=self.name,
+                         extra=self.getValue('extra'))
+
+    def _div(self, cssClass, contents, **kw):
+        if contents:
+            return widget.renderElement('div',
+                                        cssClass=cssClass,
+                                        contents="\n%s\n" % contents,
+                                        **kw)
+        return ""
 
     def renderItemsWithValues(self, values):
         """Render the list of possible values, with those found in
@@ -258,16 +277,13 @@
     propertyNames = VocabularyEditWidgetBase.propertyNames + ['firstItem']
     firstItem = False
 
-    def render(self, value):
+    def renderValue(self, value):
         rendered_items = self.renderItems(value)
-        return widget.renderElement(self.getValue('tag'),
-                                    type=self.getValue('type'),
+        contents = "\n%s\n" % "\n".join(rendered_items)
+        return widget.renderElement('select',
                                     name=self.name,
-                                    id=self.name,
-                                    cssClass=self.getValue('cssClass'),
-                                    size=self.getValue('size'),
-                                    contents="\n".join(rendered_items),
-                                    extra=self.getValue('extra'))
+                                    contents=contents,
+                                    size=self.getValue('size'))
 
     def renderItems(self, value):
         vocabulary = self.context
@@ -293,47 +309,6 @@
                                     value=self._showData())
 
 
-class VocabularyMultiDisplayWidget(VocabularyWidgetBase):
-
-    propertyNames = (VocabularyWidgetBase.propertyNames
-                     + ['itemTag', 'tag'])
-
-    itemTag = 'li'
-    tag = 'ol'
-
-    def render(self, value):
-        if value == self._missing:
-            return widget.renderElement('span',
-                                        type=self.getValue('type'),
-                                        name=self.name,
-                                        id=self.name,
-                                        cssClass=self.getValue('cssClass'),
-                                        contents=_("(no values)"),
-                                        extra=self.getValue('extra'))
-        else:
-            rendered_items = self.renderItems(value)
-            return widget.renderElement(self.getValue('tag'),
-                                        type=self.getValue('type'),
-                                        name=self.name,
-                                        id=self.name,
-                                        cssClass=self.getValue('cssClass'),
-                                        contents="\n".join(rendered_items),
-                                        extra=self.getValue('extra'))
-
-    def renderItems(self, value):
-        L = []
-        vocabulary = self.context
-        cssClass = self.getValue('cssClass') or ''
-        if cssClass:
-            cssClass += "-item"
-        tag = self.getValue('itemTag')
-        for v in value:
-            term = vocabulary.getTerm(v)
-            L.append(widget.renderElement(tag,
-                                          cssClass=cssClass,
-                                          contents=self.textForValue(term)))
-        return L
-
 class VocabularyMultiEditWidget(VocabularyEditWidgetBase):
     """Vocabulary-backed widget supporting multiple selections."""
 
@@ -344,7 +319,7 @@
             values = list(value)
         return VocabularyEditWidgetBase.renderItemsWithValues(self, values)
 
-    def render(self, value):
+    def renderValue(self, value):
         # All we really add here is the ':list' in the name argument
         # to widget.renderElement().
         rendered_items = self.renderItems(value)
@@ -353,7 +328,7 @@
                                     name=self.name + ':list',
                                     multiple=None,
                                     id=self.name,
-                                    cssClass=self.getValue('cssClass'),
+                                    cssClass='currentvalue',
                                     size=self.getValue('size'),
                                     contents="\n".join(rendered_items),
                                     extra=self.getValue('extra'))
@@ -369,3 +344,40 @@
             L.append(s[:-1])
             L.append('\n>')
         return ''.join(L)
+
+
+class VocabularyQueryViewBase(ViewSupport, BrowserView):
+    """Vocabulary query support base class."""
+
+    __implements__ = IVocabularyQueryView
+
+    # This specifically isn't a widget in it's own right, but is a
+    # form of BrowserView (at least conceptually).
+
+    def setName(self, name):
+        assert not name.endswith(".")
+        self.name = name
+
+    def renderInput(self):
+        return self.renderQueryInput()
+
+    def renderResults(self):
+        results = self.getResults()
+        if results is not None:
+            return self.renderQueryResults(results)
+        else:
+            return ""
+
+    def renderQueryResults(self, results):
+        raise NotImplementedError(
+            "renderQueryResults() must be implemented by a subclass")
+
+    def renderQueryInput(self):
+        raise NotImplementedError(
+            "renderQueryInput() must be implemented by a subclass")
+
+    def getResults(self):
+        # This is responsible for running the query against the query
+        # object (self.context), and returning a results object.  If
+        # there isn't a query in the form, returns None.
+        return None