|
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 |