1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Defines a simple single component container."""
17
18 from warnings import warn
19
20 from muntjac.terminal.scrollable import IScrollable
21 from muntjac.event.action_manager import ActionManager
22 from muntjac.event import action
23 from muntjac.ui.vertical_layout import VerticalLayout
24 from muntjac.ui.abstract_component_container import AbstractComponentContainer
25
26 from muntjac.ui import component_container
27
28 from muntjac.ui.component import IFocusable
29 from muntjac.ui.layout import ILayout
30 from muntjac.event.mouse_events import ClickEvent, IClickListener
31
32 from muntjac.terminal.gwt.client.mouse_event_details import MouseEventDetails
33 from muntjac.terminal.gwt.client.ui.v_panel import VPanel
34
35
36 -class Panel(AbstractComponentContainer, IScrollable,
37 component_container.IComponentAttachListener,
38 component_container.IComponentDetachListener,
39 action.INotifier, IFocusable):
40 """Panel - a simple single component container.
41
42 @author: Vaadin Ltd.
43 @author: Richard Lincoln
44 @version: 1.1.2
45 """
46
47 CLIENT_WIDGET = None
48
49 _CLICK_EVENT = VPanel.CLICK_EVENT_IDENTIFIER
50
51
52
53
54
55
56
57
58 STYLE_LIGHT = 'light'
59
60
62 """Creates a new panel with caption and or content. A VerticalLayout
63 is used as content by default.
64
65 @param args: tuple of the form
66 - (content)
67 1. the content for the panel (HTML/XHTML).
68 - (caption)
69 1. the caption used in the panel (HTML/XHTML).
70 - (caption, content)
71 1. the caption of the panel.
72 2. the content used in the panel (HTML/XHTML).
73 """
74 super(Panel, self).__init__()
75
76
77 self._content = None
78
79
80 self._scrollOffsetX = 0
81
82
83 self._scrollOffsetY = 0
84
85
86 self._scrollable = False
87
88
89
90 self.actionManager = None
91
92
93
94
95 self._tabIndex = -1
96
97 nargs = len(args)
98 if nargs == 0:
99 Panel.__init__(self, None)
100 elif nargs == 1:
101 if isinstance(args[0], basestring):
102 caption, = args
103 Panel.__init__(self, caption, None)
104 self.setCaption(caption)
105 else:
106 content, = args
107 self.setContent(content)
108 self.setWidth(100, self.UNITS_PERCENTAGE)
109 elif nargs == 2:
110 caption, content = args
111 Panel.__init__(self, content)
112 self.setCaption(caption)
113 else:
114 raise ValueError, 'too many arguments'
115
116
118 """Sets the caption of the panel.
119
120 Note that the caption is interpreted as HTML/XHTML and therefore care
121 should be taken not to enable HTML injection and XSS attacks using
122 panel captions. This behavior may change in future versions.
123
124 @see L{AbstractComponent.setCaption}
125 """
126 super(Panel, self).setCaption(caption)
127
128
130 """Gets the current layout of the panel.
131
132 @return: the Current layout of the panel.
133 @deprecated: A Panel can now contain a IComponentContainer which is not
134 necessarily a ILayout. Use L{getContent} instead.
135 """
136 warn('Use getContent() instead', DeprecationWarning)
137
138 if isinstance(self._content, ILayout):
139 return self._content
140 elif self._content is None:
141 return None
142 raise ValueError, ('Panel does not contain a ILayout. '
143 'Use getContent() instead of getLayout().')
144
145
147 """Sets the layout of the panel.
148
149 If given layout is null, a VerticalLayout with margins set is used
150 as a default.
151
152 Components from old layout are not moved to new layout by default.
153 Use function in ILayout interface manually.
154
155 @param newLayout:
156 the New layout of the panel.
157 @deprecated: A Panel can now contain a IComponentContainer which is
158 not necessarily a ILayout. Use L{setContent} instead.
159 """
160 self.setContent(newLayout)
161
162
163 - def getContent(self):
164 """Returns the content of the Panel.
165 """
166 return self._content
167
168
169 - def setContent(self, newContent):
170 """Set the content of the Panel. If null is given as the new content
171 then a layout is automatically created and set as the content.
172
173 @param newContent: The new content
174 """
175
176 if newContent is None:
177 newContent = self.createDefaultContent()
178
179
180
181
182 if newContent == self._content:
183 return
184
185
186 if self._content is not None:
187 self._content.setParent(None)
188 self._content.removeListener(self,
189 component_container.IComponentAttachListener)
190 self._content.removeListener(self,
191 component_container.IComponentDetachListener)
192
193
194 newContent.setParent(self)
195
196
197 self._content = newContent
198
199
200 newContent.addListener(self,
201 component_container.IComponentAttachListener)
202 newContent.addListener(self,
203 component_container.IComponentDetachListener)
204
205 self._content = newContent
206
207
209 """Create a IComponentContainer which is added by default to
210 the Panel if user does not specify any content.
211 """
212 layout = VerticalLayout()
213
214 layout.setMargin(True)
215 return layout
216
217
218 - def paintContent(self, target):
219 self._content.paint(target)
220
221 target.addVariable(self, 'tabindex', self.getTabIndex())
222
223 if self.isScrollable():
224 target.addVariable(self, 'scrollLeft', self.getScrollLeft())
225 target.addVariable(self, 'scrollTop', self.getScrollTop())
226
227 if self.actionManager is not None:
228 self.actionManager.paintActions(None, target)
229
230
236
237
239 """Adds the component into this container.
240
241 @param c: the component to be added.
242 @see: L{AbstractComponentContainer.addComponent}
243 """
244 self._content.addComponent(c)
245
246
247
248
250 """Removes the component from this container.
251
252 @param c: The component to be removed.
253 @see: L{AbstractComponentContainer.removeComponent}
254 """
255 self._content.removeComponent(c)
256
257
258
259
261 """Gets the component container iterator for going through
262 all the components in the container.
263
264 @return: the iterator of the components inside the container.
265 @see: L{IComponentContainer.getComponentIterator}
266 """
267 return self._content.getComponentIterator()
268
269
271 """Called when one or more variables handled by the implementing
272 class are changed.
273
274 @see: L{muntjac.terminal.VariableOwner.changeVariables}
275 """
276 super(Panel, self).changeVariables(source, variables)
277
278 if self._CLICK_EVENT in variables:
279 self.fireClick(variables[self._CLICK_EVENT])
280
281
282 newWidth = variables.get('width')
283 newHeight = variables.get('height')
284
285 if newWidth is not None and newWidth != self.getWidth():
286 self.setWidth(newWidth, self.UNITS_PIXELS)
287
288 if newHeight is not None and newHeight != self.getHeight():
289 self.setHeight(newHeight, self.UNITS_PIXELS)
290
291
292 newScrollX = variables.get('scrollLeft')
293 newScrollY = variables.get('scrollTop')
294 if newScrollX is not None and newScrollX != self.getScrollLeft():
295
296 self._scrollOffsetX = newScrollX
297
298 if newScrollY is not None and newScrollY != self.getScrollTop():
299
300 self._scrollOffsetY = newScrollY
301
302
303 if self.actionManager is not None:
304 self.actionManager.handleActions(variables, self)
305
306
309
310
315
316
319
320
325
326
329
330
345
346
365
366
371
372
390
391
396
397
400
401
409
410
418
419
421 """Notifies the component that it is connected to an application.
422
423 @see: L{IComponent.attach}
424 """
425
426 self.requestRepaint()
427 if self._content is not None:
428 self._content.attach()
429
430
432 """Notifies the component that it is detached from the application.
433
434 @see: L{IComponent.detach}
435 """
436
437 if self._content is not None:
438 self._content.detach()
439
440
442 """Removes all components from this container.
443
444 @see: L{IComponentContainer.removeAllComponents}
445 """
446 self._content.removeAllComponents()
447
448
450 if self.actionManager is None:
451 self.actionManager = ActionManager(self)
452 return self.actionManager
453
454
457
458
462
463
466
467
469 if self.actionManager is not None:
470 self.actionManager.removeActionHandler(actionHandler)
471
472
474 """Removes all action handlers"""
475 if self.actionManager is not None:
476 self.actionManager.removeAllActionHandlers()
477
478
480 """Add a click listener to the Panel. The listener is called whenever
481 the user clicks inside the Panel. Also when the click targets a
482 component inside the Panel, provided the targeted component does not
483 prevent the click event from propagating.
484
485 Use L{removeListener} to remove the listener.
486
487 @param listener:
488 The listener to add
489 """
490 if (isinstance(listener, IClickListener) and
491 (iface is None or issubclass(iface, IClickListener))):
492 self.registerListener(self._CLICK_EVENT, ClickEvent,
493 listener, IClickListener.clickMethod)
494
495 super(Panel, self).addListener(listener, iface)
496
497
498 - def addCallback(self, callback, eventType=None, *args):
507
508
521
522
531
532
534 """Fire a click event to all click listeners.
535
536 @param parameters:
537 The raw "value" of the variable change from the client side
538 """
539 params = parameters.get('mouseDetails')
540 mouseDetails = MouseEventDetails.deSerialize(params)
541 self.fireEvent( ClickEvent(self, mouseDetails) )
542
543
545 return self._tabIndex
546
547
551
552
554 """Moves keyboard focus to the component.
555
556 @see: L{IFocusable.focus}
557 """
558 super(Panel, self).focus()
559