src/pyams_form/group.py
changeset 0 7a0b409fd4b8
child 2 0f135e3c84b1
equal deleted inserted replaced
-1:000000000000 0:7a0b409fd4b8
       
     1 #
       
     2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
       
     3 # All Rights Reserved.
       
     4 #
       
     5 # This software is subject to the provisions of the Zope Public License,
       
     6 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    10 # FOR A PARTICULAR PURPOSE.
       
    11 #
       
    12 
       
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 
       
    16 # import standard library
       
    17 
       
    18 # import interfaces
       
    19 from pyams_form.interfaces.form import IFormWidgetsGroup, IGroupsBasedForm
       
    20 
       
    21 # import packages
       
    22 from pyramid.decorator import reify
       
    23 from zope.interface import implementer
       
    24 from zope.schema.fieldproperty import FieldProperty
       
    25 
       
    26 
       
    27 @implementer(IFormWidgetsGroup)
       
    28 class FormWidgetsGroup(object):
       
    29     """Form widgets group"""
       
    30 
       
    31     id = FieldProperty(IFormWidgetsGroup['id'])
       
    32     widgets = FieldProperty(IFormWidgetsGroup['widgets'])
       
    33     legend = FieldProperty(IFormWidgetsGroup['legend'])
       
    34     help = FieldProperty(IFormWidgetsGroup['help'])
       
    35     _css_class = FieldProperty(IFormWidgetsGroup['css_class'])
       
    36     switch = FieldProperty(IFormWidgetsGroup['switch'])
       
    37     checkbox_switch = FieldProperty(IFormWidgetsGroup['checkbox_switch'])
       
    38     checkbox_field = FieldProperty(IFormWidgetsGroup['checkbox_field'])
       
    39     checkbox_widget = FieldProperty(IFormWidgetsGroup['checkbox_widget'])
       
    40     hide_if_empty = FieldProperty(IFormWidgetsGroup['hide_if_empty'])
       
    41 
       
    42     def __init__(self, id, widgets=None, legend=None, help=None, css_class='', switch=False,
       
    43                  checkbox_switch=False, checkbox_field=None, hide_if_empty=False):
       
    44         assert (not checkbox_switch) or checkbox_field, "You must define checkbox field when using checkbox switch"
       
    45         self.id = id
       
    46         self.widgets = widgets or []
       
    47         self.legend = id if legend is None else legend
       
    48         self.help = help
       
    49         self._css_class = css_class
       
    50         self.switch = switch
       
    51         self.checkbox_switch = checkbox_switch
       
    52         self.checkbox_field = checkbox_field
       
    53         self.hide_if_empty = hide_if_empty
       
    54 
       
    55     @property
       
    56     def css_class(self):
       
    57         css_class = self._css_class
       
    58         if self.switch:
       
    59             if self.checkbox_switch:
       
    60                 css_class += ' checker'
       
    61             else:
       
    62                 css_class += ' switcher'
       
    63         return css_class
       
    64 
       
    65     @property
       
    66     def checkbox_widget(self):
       
    67         if self.checkbox_field is None:
       
    68             return None
       
    69         for widget in self.widgets:
       
    70             if widget.field is self.checkbox_field.field:
       
    71                 return widget
       
    72 
       
    73     @reify
       
    74     def visible(self):
       
    75         if self.checkbox_switch:
       
    76             widget = self.checkbox_widget
       
    77             context = widget.context
       
    78             name = widget.field.getName()
       
    79             value = getattr(context, name, None)
       
    80             return bool(value)
       
    81         else:
       
    82             if not (self.switch and self.hide_if_empty):
       
    83                 return True
       
    84             for widget in self.widgets:
       
    85                 if not widget.ignoreContext:
       
    86                     field = widget.field
       
    87                     context = widget.context
       
    88                     name = field.getName()
       
    89                     value = getattr(context, name, None)
       
    90                     if value and (value != field.default):
       
    91                         return True
       
    92             return False
       
    93 
       
    94     @property
       
    95     def visible_widgets(self):
       
    96         for widget in self.widgets:
       
    97             if (self.checkbox_field is None) or (widget.field is not self.checkbox_field.field):
       
    98                 yield widget
       
    99 
       
   100     @property
       
   101     def switchable(self):
       
   102         return self.switch or self.checkbox_switch
       
   103 
       
   104     @property
       
   105     def switcher_state(self):
       
   106         return 'on' if self.visible else 'off'
       
   107 
       
   108     @property
       
   109     def checker_state(self):
       
   110         return 'on' if self.visible else 'off'
       
   111 
       
   112 
       
   113 def NamedWidgetsGroup(id, widgets, names=(), legend=None, help=None, css_class='', switch=False,
       
   114                       checkbox_switch=False, checkbox_field=None, hide_if_empty=False):
       
   115     """Create a widgets group based on widgets names"""
       
   116     return FormWidgetsGroup(id, [widgets.get(name) for name in names], legend, help, css_class, switch,
       
   117                             checkbox_switch, checkbox_field, hide_if_empty)
       
   118 
       
   119 
       
   120 @implementer(IGroupsBasedForm)
       
   121 class GroupsBasedForm(object):
       
   122     """Groups based form
       
   123 
       
   124     Should be used as a base class for forms also implementing IForm
       
   125     """
       
   126 
       
   127     def __init__(self):
       
   128         self._groups = []
       
   129 
       
   130     def add_group(self, group):
       
   131         self._groups.append(group)
       
   132 
       
   133     @property
       
   134     def groups(self):
       
   135         result = self._groups[:]
       
   136         others = []
       
   137         for widget in self.widgets.values():
       
   138             found = False
       
   139             for group in result:
       
   140                 if widget in group.widgets:
       
   141                     found = True
       
   142                     break
       
   143             if not found:
       
   144                 others.append(widget)
       
   145         if others:
       
   146             result.insert(0, FormWidgetsGroup(None, others))
       
   147         return result