[Zope3-checkins] CVS: Zope3/src/zope/app/browser/services - field.py:1.4
Steve Alexander
steve@cat-box.net
Sun, 12 Jan 2003 16:22:47 -0500
Update of /cvs-repository/Zope3/src/zope/app/browser/services
In directory cvs.zope.org:/tmp/cvs-serv408/src/zope/app/browser/services
Modified Files:
field.py
Log Message:
added component location field and widget, for specifying a component
either by a dotted module name, or by a path.
=== Zope3/src/zope/app/browser/services/field.py 1.3 => 1.4 ===
--- Zope3/src/zope/app/browser/services/field.py:1.3 Thu Jan 9 12:28:40 2003
+++ Zope3/src/zope/app/browser/services/field.py Sun Jan 12 16:22:15 2003
@@ -18,7 +18,12 @@
__metaclass__ = type
from zope.app.browser.form.widget import BrowserWidget
+from zope.app.interfaces.browser.form import IBrowserWidget
from zope.component import getServiceManager
+from zope.app.form.widget import Widget
+from zope.publisher.browser import BrowserView
+from xml.sax.saxutils import quoteattr
+from zope.app.interfaces.form import WidgetInputError
class ComponentPathWidget(BrowserWidget):
@@ -27,20 +32,171 @@
def __call__(self):
selected = self._showData()
- service_manager = getServiceManager(self.context.context)
- info = service_manager.queryComponent(self.context.type)
- result = []
-
- result.append('<select name="%s">' % self.name)
- result.append('<option></option>')
-
- for item in info:
- item = item['path']
- if item == selected:
- result.append('<option selected>%s</option>' % item)
+ field = self.context
+ return renderPathSelect(field.context, field.type, self.name, selected)
+
+class ComponentLocationWidget(Widget, BrowserView):
+
+ __implements__ = IBrowserWidget
+
+ # Names used:
+ #
+ # name.p the value of the path
+ # name.d the value of the dotted module name
+
+ def haveData(self):
+ # do I have name.p xor name.m ?
+ form = self.request.form
+
+ has_p = self.name+'.p' in form
+ has_d = self.name+'.d' in form
+
+ return bool((has_p or has_d) and not (has_p and has_d))
+
+ def getData(self, optional=0):
+ field = self.context
+ form = self.request.form
+ name_p = self.name+'.p'
+ name_d = self.name+'.d'
+
+ path = form.get(self.name+'.p', '').strip()
+ dottedname = form.get(self.name+'.d', '').strip()
+
+ if path and not path.startswith('/'):
+ raise WidgetInputError(
+ self.context.__name__, self.title,
+ 'The component path must start with a "/"')
+
+ if dottedname and '/' in dottedname:
+ raise WidgetInputError(
+ self.context.__name__, self.title,
+ 'A dotted module name cannot contain a "/"')
+
+ if path and dottedname:
+ location = ''
+ else:
+ location = path or dottedname
+
+ if not location:
+ if path and dottedname:
+ raise WidgetInputError(
+ self.context.__name__, self.title,
+ 'Either give a module or select a component')
+ # No user input
+ if field.required and not optional:
+ raise MissingInputError(field.__name__, field.title,
+ 'the field is required')
+ return field.default
+
+ location = unicode(location)
+
+ if not optional:
+ try:
+ field.validate(location)
+ except ValidationError, v:
+ raise WidgetInputError(self.context.__name__,
+ self.title, str(v))
+ return location
+
+ def __call__(self):
+ 'See IBrowserWidget'
+ field = self.context
+ form = self.request.form
+ name = self.name
+
+ if self._data is None: # no data has been set with Widget.setData(),
+ # so use the data in the form
+
+ path = form.get(name+'.p', '').strip()
+ dottedname = form.get(name+'.d', '').strip()
+
+ if path or dottedname:
+ location = path or dottedname
+ # XXX is validation here really needed?
+ #field.validate(location)
+ else: # otherwise, use the default
+ location = field.default or ''
+ if location.startswith('/'):
+ path = location
+ dottedname = ''
+ else:
+ dottedname = location
+ path = ''
+ else:
+ # data has been set with Widget.setData()
+ location = self._data
+ if location.startswith('/'):
+ path = location
+ dottedname = ''
else:
- result.append('<option>%s</option>' % item)
+ dottedname = location
+ path = ''
+
+ selectmarkup = renderPathSelect(field.context, field.type,
+ name+'.p', path)
+ inputmarkup = '<input type="text" name="%s.d" value="%s">' % (
+ name, dottedname)
+ HTML = 'path: %s<br>dotted name: %s' % (selectmarkup, inputmarkup)
+ return HTML
+
+ def hidden(self):
+ 'See IBrowserWidget'
+ if self._data is None:
+ data = self.getData(1)
+ else:
+ data = self._data
+
+ if not data:
+ return ''
+
+ if data.startswith('/'):
+ name = self.name+'.p'
+ else:
+ name = self.name+'.d'
+
+ return '<input type="hidden" name="%s" value=%s />' % (
+ name, quoteattr(data))
+
+ def label(self):
+ return '<label for="%s">%s</label>' % (self.name, self.title)
+
+ def row(self):
+ return "<td>%s</td><td>%s</td>" % (self.label(), self())
+
+ # --- deprecated methods of IBrowserWidget
+
+ def renderHidden(self, value):
+ 'See IBrowserWidget'
+ raise NotImplementedError
+
+ def render(self, value):
+ 'See IBrowserWidget'
+ raise NotImplementedError
+
+class ComponentLocationDisplayWidget(ComponentLocationWidget):
+ def __call__(self):
+ if self._data is None:
+ data = self.getData(1)
+ else:
+ data = self._data
+ # location = data
+ return data
+
+def renderPathSelect(context, type, name, selected, empty_message=''):
+ service_manager = getServiceManager(context)
+ info = service_manager.queryComponent(type)
+ result = []
+
+ result.append('<select name="%s">' % name)
+ result.append('<option>%s</option>' % empty_message)
+
+ for item in info:
+ item = item['path']
+ if item == selected:
+ result.append('<option selected>%s</option>' % item)
+ else:
+ result.append('<option>%s</option>' % item)
- result.append('</select>')
+ result.append('</select>')
+ return ''.join(result)
- return "\n".join(result)