move widget selection's logic on fields
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 28 May 2009 18:32:12 +0200
changeset 1986 96c0e56cb0cf
parent 1985 9c1db4e06095
child 1987 d495e9ce9367
move widget selection's logic on fields
web/formfields.py
--- a/web/formfields.py	Thu May 28 18:31:14 2009 +0200
+++ b/web/formfields.py	Thu May 28 18:32:12 2009 +0200
@@ -20,6 +20,7 @@
     HiddenInput, TextInput, FileInput, PasswordInput, TextArea, FCKEditor,
     Radio, Select, DateTimePicker)
 
+
 class Field(object):
     """field class is introduced to control what's displayed in forms. It makes
     the link between something to edit and its display in the form. Actual
@@ -80,16 +81,13 @@
         self.label = label or name
         self.help = help
         self.required = required
-        if widget is not None:
-            self.widget = widget
-        if isinstance(self.widget, type):
-            self.widget = self.widget()
         self.initial = initial
         self.choices = choices
         self.sort = sort
         self.internationalizable = internationalizable
         self.eidparam = eidparam
         self.role = role
+        self.init_widget(widget)
         # ordering number for this field instance
         self.creation_rank = Field.__creation_rank
         Field.__creation_rank += 1
@@ -102,6 +100,12 @@
     def __repr__(self):
         return self.__unicode__().encode('utf-8')
 
+    def init_widget(self, widget):
+        if widget is not None:
+            self.widget = widget
+        if isinstance(self.widget, type):
+            self.widget = self.widget()
+
     def set_name(self, name):
         """automatically set .id and .label when name is set"""
         assert name
@@ -177,12 +181,25 @@
         """
         pass
 
+
 class StringField(Field):
+    widget = TextArea
+
     def __init__(self, max_length=None, **kwargs):
+        self.max_length = max_length # must be set before super call
         super(StringField, self).__init__(**kwargs)
-        self.max_length = max_length
+
+    def init_widget(self, widget):
+        if widget is None:
+            if self.choices:
+                self.widget = Select()
+            elif self.max_length and self.max_length < 257:
+                self.widget = TextInput()
+        super(StringField, self).init_widget(widget)
         if isinstance(self.widget, TextArea):
             self.init_text_area(self.widget)
+        elif isinstance(self.widget, Select):
+            self.widget.attrs.setdefault('size', 1)
 
     def init_text_area(self, widget):
         if self.max_length < 513:
@@ -342,6 +359,7 @@
             self.widget.attrs.setdefault('size', 5)
             self.widget.attrs.setdefault('maxlength', 15)
 
+
 class BooleanField(Field):
     widget = Radio
 
@@ -381,6 +399,7 @@
     format_prop = 'ui.datetime-format'
     widget = TextInput
 
+
 class HiddenInitialValueField(Field):
     def __init__(self, visible_field):
         name = 'edit%s-%s' % (visible_field.role[0], visible_field.name)
@@ -470,18 +489,11 @@
             # init StringField parameters according to constraints
             for cstr in constraints:
                 if isinstance(cstr, StaticVocabularyConstraint):
-                    kwargs.setdefault('widget', Select())
                     kwargs.setdefault('choices', cstr.vocabulary)
-                    if card in '?1':
-                        if isinstance(kwargs['widget'], type):
-                            kwargs['widget'] = kwargs['widget']()
-                        kwargs['widget'].attrs.setdefault('size', 1)
+                    break
             for cstr in constraints:
                 if isinstance(cstr, SizeConstraint) and cstr.max is not None:
-                    if cstr.max < 257:
-                        kwargs.setdefault('widget', TextInput())
                     kwargs['max_length'] = cstr.max
-            kwargs.setdefault('widget', TextArea())
             return StringField(**kwargs)
         if fieldclass is FileField:
             for metadata in ('format', 'encoding'):
@@ -493,6 +505,7 @@
     kwargs['role'] = role
     return RelationField.fromcardinality(card, **kwargs)
 
+
 FIELDS = {
     'Boolean':  BooleanField,
     'Bytes':    FileField,