web/formwidgets.py
changeset 8029 805d4e121b65
parent 7990 a673d1d9a738
child 8193 0c64d6b75303
--- a/web/formwidgets.py	Thu Oct 27 10:38:03 2011 +0200
+++ b/web/formwidgets.py	Thu Oct 27 10:38:16 2011 +0200
@@ -75,6 +75,7 @@
 
 .. autoclass:: cubicweb.web.formwidgets.PasswordInput
 .. autoclass:: cubicweb.web.formwidgets.IntervalWidget
+.. autoclass:: cubicweb.web.formwidgets.BitSelect
 .. autoclass:: cubicweb.web.formwidgets.HorizontalLayoutWidget
 .. autoclass:: cubicweb.web.formwidgets.EditableURLWidget
 
@@ -452,7 +453,7 @@
                 oattrs.setdefault('label', label or '')
                 options.append(u'<optgroup %s>' % uilib.sgml_attributes(oattrs))
                 optgroup_opened = True
-            elif value in curvalues:
+            elif self.value_selected(value, curvalues):
                 options.append(tags.option(label, value=value,
                                            selected='selected', **oattrs))
             else:
@@ -468,6 +469,36 @@
         return tags.select(name=field.input_name(form, self.suffix),
                            multiple=self._multiple, options=options, **attrs)
 
+    def value_selected(self, value, curvalues):
+        return value in curvalues
+
+
+class BitSelect(Select):
+    """Select widget for IntField using a vocabulary with bit masks as values.
+
+    See also :class:`~cubicweb.web.facet.BitFieldFacet`.
+    """
+    def __init__(self, attrs=None, multiple=True, **kwargs):
+        super(BitSelect, self).__init__(attrs, multiple=multiple, **kwargs)
+
+    def value_selected(self, value, curvalues):
+        mask = reduce(lambda x, y: int(x) | int(y), curvalues, 0)
+        return int(value) & mask
+
+    def process_field_data(self, form, field):
+        """Return process posted value(s) for widget and return something
+        understandable by the associated `field`. That value may be correctly
+        typed or a string that the field may parse.
+        """
+        val = super(BitSelect, self).process_field_data(form, field)
+        if isinstance(val, list):
+            val = reduce(lambda x, y: int(x) | int(y), val, 0)
+        elif val:
+            val = int(val)
+        else:
+            val = 0
+        return val
+
 
 class CheckBox(Input):
     """Simple <input type='checkbox'>, for field having a specific