1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Defines a layout component that can be used in browser environment
17 only."""
18
19 from muntjac.ui.abstract_layout import AbstractLayout
20 from muntjac.terminal.gwt.client.event_id import EventId
21
22 from muntjac.event.layout_events import \
23 ILayoutClickNotifier, LayoutClickEvent, ILayoutClickListener
24
25
26 -class CssLayout(AbstractLayout, ILayoutClickNotifier):
27 """CssLayout is a layout component that can be used in browser environment
28 only. It simply renders components and their captions into a same div
29 element. Component layout can then be adjusted with css.
30
31 In comparison to L{HorizontalLayout} and L{VerticalLayout}
32
33 - rather similar server side api
34 - no spacing, alignment or expand ratios
35 - much simpler DOM that can be styled by skilled web developer
36 - no abstraction of browser differences (developer must ensure that
37 the result works properly on each browser)
38 - different kind of handling for relative sizes (that are set from
39 server side) (*)
40 - noticeably faster rendering time in some situations as we rely more
41 on the browser's rendering engine.
42
43 With L{CustomLayout} one can often achieve similar results (good
44 looking layouts with web technologies), but with CustomLayout developer
45 needs to work with fixed templates.
46
47 By extending CssLayout one can also inject some css rules straight to
48 child components using L{getCss}.
49
50 (*) Relative sizes (set from server side) are treated bit differently than
51 in other layouts in Muntjac. In cssLayout the size is calculated relatively
52 to CSS layouts content area which is pretty much as in html and css. In
53 other layouts the size of component is calculated relatively to the "slot"
54 given by layout.
55
56 Also note that client side framework in Muntjac modifies inline style
57 properties width and height. This happens on each update to component. If
58 one wants to set component sizes with CSS, component must have undefined
59 size on server side (which is not the default for all components) and the
60 size must be defined with class styles - not by directly injecting width
61 and height.
62 """
63
64 CLIENT_WIDGET = None
65
66 _CLICK_EVENT = EventId.LAYOUT_CLICK
67
68
74
75
77 """Add a component into this container. The component is added to
78 the right/under the previous component or into indexed position in
79 this container.
80
81 @param c:
82 the component to be added.
83 @param index:
84 the Index of the component position. The components
85 currently in and after the position are shifted forwards.
86 """
87 if index is None:
88 self.components.append(c)
89 try:
90 super(CssLayout, self).addComponent(c)
91 self.requestRepaint()
92 except ValueError, e:
93 self.components.remove(c)
94 raise e
95 else:
96 self.components.insert(index, c)
97 try:
98 super(CssLayout, self).addComponent(c)
99 self.requestRepaint()
100 except ValueError, e:
101 self.components.remove(c)
102 raise e
103
104
106 """Adds a component into this container. The component is added to
107 the left or on top of the other components.
108
109 @param c:
110 the component to be added.
111 """
112 self.components.insert(0, c)
113 try:
114 super(CssLayout, self).addComponent(c)
115 self.requestRepaint()
116 except ValueError, e:
117 self.components.remove(c)
118 raise e
119
120
122 """Removes the component from this container.
123
124 @param c: the component to be removed.
125 """
126 if c in self.components:
127 self.components.remove(c)
128 super(CssLayout, self).removeComponent(c)
129 self.requestRepaint()
130
131
133 """Gets the component container iterator for going trough all the
134 components in the container.
135
136 @return: the iterator of the components inside the container.
137 """
138 return iter(self.components)
139
140
142 """Gets the number of contained components. Consistent with the
143 iterator returned by L{getComponentIterator}.
144
145 @return: the number of contained components
146 """
147 return len(self.components)
148
149
150 - def paintContent(self, target):
151 """Paints the content of this component.
152
153 @param target:
154 the Paint Event.
155 @raise PaintException:
156 if the paint operation failed.
157 """
158 super(CssLayout, self).paintContent(target)
159 componentCss = None
160
161 for c in self.components:
162
163 c.paint(target)
164 componentCssString = self.getCss(c)
165 if componentCssString is not None:
166 if componentCss is None:
167 componentCss = dict()
168 componentCss[c] = componentCssString
169 if componentCss is not None:
170 target.addAttribute('css', componentCss)
171
172
174 """Returns styles to be applied to given component. Override this
175 method to inject custom style rules to components.
176
177 Note that styles are injected over previous styles before actual
178 child rendering. Previous styles are not cleared, but overridden.
179
180 Note that one most often achieves better code style, by separating
181 styling to theme (with custom theme and L{addStyleName}.
182 With own custom styles it is also very easy to break browser
183 compatibility.
184
185 @param c: the component
186 @return: css rules to be applied to component
187 """
188 return None
189
190
192
193 oldLocation = -1
194 newLocation = -1
195 location = 0
196 for component in self.components:
197
198 if component == oldComponent:
199 oldLocation = location
200 if component == newComponent:
201 newLocation = location
202
203 location += 1
204
205 if oldLocation == -1:
206 self.addComponent(newComponent)
207 elif newLocation == -1:
208 self.removeComponent(oldComponent)
209 self.addComponent(newComponent, oldLocation)
210 else:
211 if oldLocation > newLocation:
212 self.components.remove(oldComponent)
213 self.components.append(newLocation, oldComponent)
214 self.components.remove(newComponent)
215 self.components.append(oldLocation, newComponent)
216 else:
217 self.components.remove(newComponent)
218 self.components.append(oldLocation, newComponent)
219 self.components.remove(oldComponent)
220 self.components.append(newLocation, oldComponent)
221 self.requestRepaint()
222
223
232
233
234 - def addCallback(self, callback, eventType=None, *args):
242
243
251
252
262