Package muntjac :: Package ui :: Module popup_view
[hide private]
[frames] | no frames]

Source Code for Module muntjac.ui.popup_view

  1  # Copyright (C) 2012 Vaadin Ltd.  
  2  # Copyright (C) 2012 Richard Lincoln 
  3  #  
  4  # Licensed under the Apache License, Version 2.0 (the "License");  
  5  # you may not use this file except in compliance with the License.  
  6  # You may obtain a copy of the License at  
  7  #  
  8  #     http://www.apache.org/licenses/LICENSE-2.0  
  9  #  
 10  # Unless required by applicable law or agreed to in writing, software  
 11  # distributed under the License is distributed on an "AS IS" BASIS,  
 12  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
 13  # See the License for the specific language governing permissions and  
 14  # limitations under the License. 
 15   
 16  from warnings import warn 
 17   
 18  from muntjac.ui.abstract_component_container import AbstractComponentContainer 
 19  from muntjac.ui.component import Event as ComponentEvent 
 20  from muntjac.ui.abstract_component import AbstractComponent 
 21   
 22   
23 -class IPopupVisibilityListener(object):
24 """Defines a listener that can receive a PopupVisibilityEvent when the 25 visibility of the popup changes. 26 """ 27
28 - def popupVisibilityChange(self, event):
29 """Pass to L{PopupView.PopupVisibilityEvent} to start listening 30 for popup visibility changes. 31 32 @param event: the event 33 34 @see: L{PopupVisibilityEvent} 35 @see: L{PopupView.addListener} 36 """ 37 raise NotImplementedError
38 39 40 _POPUP_VISIBILITY_METHOD = getattr(IPopupVisibilityListener, 41 'popupVisibilityChange') 42 43
44 -class SingleComponentIterator(object):
45 """Iterator for the visible components (zero or one components), used by 46 L{PopupView.getComponentIterator}. 47 """ 48
49 - def __init__(self, component):
50 self._component = component 51 self._first = component is None
52 53
54 - def __iter__(self):
55 return self
56 57
58 - def hasNext(self):
59 return not self._first
60 61
62 - def next(self): #@PydevCodeAnalysisIgnore
63 if not self._first: 64 self._first = True 65 return self._component 66 else: 67 raise StopIteration
68 69
70 - def remove(self):
71 raise NotImplementedError
72 73
74 -class PopupView(AbstractComponentContainer):
75 """A component for displaying a two different views to data. The minimized 76 view is normally used to render the component, and when it is clicked the 77 full view is displayed on a popup. The class L{popup_view.IContent} is 78 used to deliver contents to this component. 79 80 @author: Vaadin Ltd. 81 @author: Richard Lincoln 82 """ 83 84 CLIENT_WIDGET = None #ClientWidget(VPopupView, LoadStyle.EAGER) 85
86 - def __init__(self, *args):
87 """A simple way to create a PopupPanel. Note that the minimal 88 representation may not be dynamically updated. 89 90 Alternatively, creates a PopupView through the IContent interface. 91 This allows the creator to dynamically change the contents of the 92 PopupView. 93 94 @param args: tuple of the form 95 - (small, large) 96 1. the minimal textual representation as HTML 97 2. the full, Component-type representation 98 - (content) 99 1. the IContent that contains the information for this 100 """ 101 self._content = None 102 self._hideOnMouseOut = None 103 self._visibleComponent = None 104 105 nargs = len(args) 106 if nargs == 1: 107 content, = args 108 super(PopupView, self).__init__() 109 self._hideOnMouseOut = True 110 self.setContent(content) 111 elif nargs == 2: 112 small, large = args 113 114 c = InnerContent(small, large) 115 PopupView.__init__(self, c) 116 else: 117 raise ValueError, 'invalid number of arguments'
118 119
120 - def setContent(self, newContent):
121 """This method will replace the current content of the panel with 122 a new one. 123 124 @param newContent: 125 IContent object containing new information 126 for the PopupView 127 @raise ValueError: 128 if the method is passed a null value, or if one of 129 the content methods returns null 130 """ 131 if newContent is None: 132 raise ValueError, 'IContent must not be null' 133 self._content = newContent 134 self.requestRepaint()
135 136
137 - def getContent(self):
138 """Returns the content-package for this PopupView. 139 140 @return: the IContent for this object or null 141 """ 142 return self._content
143 144
145 - def setPopupVisibility(self, visible):
146 """@deprecated: Use L{setPopupVisible} instead.""" 147 warn('use setPopupVisible() instead', DeprecationWarning) 148 self.setPopupVisible(visible)
149
150 - def getPopupVisibility(self):
151 """@deprecated: Use L{isPopupVisible} instead.""" 152 warn('use isPopupVisible() instead', DeprecationWarning) 153 return self.isPopupVisible()
154 155
156 - def setPopupVisible(self, visible):
157 """Set the visibility of the popup. Does not hide the minimal 158 representation. 159 """ 160 if self.isPopupVisible() != visible: 161 if visible: 162 self._visibleComponent = self._content.getPopupComponent() 163 if self._visibleComponent is None: 164 raise ValueError, ('PopupView.IContent did not return ' 165 'Component to set visible') 166 super(PopupView, self).addComponent(self._visibleComponent) 167 else: 168 super(PopupView, self).removeComponent(self._visibleComponent) 169 self._visibleComponent = None 170 self.fireEvent( PopupVisibilityEvent(self) ) 171 self.requestRepaint()
172 173
174 - def isPopupVisible(self):
175 """Return whether the popup is visible. 176 177 @return: true if the popup is showing 178 """ 179 return self._visibleComponent is not None
180 181
182 - def isHideOnMouseOut(self):
183 """Check if this popup will be hidden when the user takes the mouse 184 cursor out of the popup area. 185 186 @return: true if the popup is hidden on mouse out, false otherwise 187 """ 188 return self._hideOnMouseOut
189 190 # Methods inherited from AbstractComponentContainer. These are unnecessary 191 # (but mandatory). Most of them are not supported in this implementation. 192
193 - def setHideOnMouseOut(self, hideOnMouseOut):
194 """Should the popup automatically hide when the user takes the mouse 195 cursor out of the popup area? If this is false, the user must click 196 outside the popup to close it. The default is true. 197 """ 198 self._hideOnMouseOut = hideOnMouseOut
199 200
201 - def getComponentIterator(self):
202 """This class only contains other components when the popup is 203 showing. 204 205 @see: L{ComponentContainer.getComponentIterator} 206 """ 207 return SingleComponentIterator(self._visibleComponent)
208 209
210 - def getComponentCount(self):
211 """Gets the number of contained components. Consistent with the 212 iterator returned by L{getComponentIterator}. 213 214 @return: the number of contained components (zero or one) 215 """ 216 return 1 if self._visibleComponent is not None else 0
217 218
219 - def removeAllComponents(self):
220 """Not supported in this implementation. 221 222 @see: L{AbstractComponentContainer.removeAllComponents} 223 @raise NotImplementedError: 224 """ 225 raise NotImplementedError
226 227
228 - def moveComponentsFrom(self, source):
229 """Not supported in this implementation. 230 231 @see: L{AbstractComponentContainer.moveComponentsFrom} 232 @raise NotImplementedError: 233 """ 234 raise NotImplementedError
235 236
237 - def addComponent(self, c):
238 """Not supported in this implementation. 239 240 @see: L{AbstractComponentContainer.addComponent} 241 @raise NotImplementedError: 242 """ 243 raise NotImplementedError
244 245
246 - def replaceComponent(self, oldComponent, newComponent):
247 """Not supported in this implementation. 248 249 @see: L{ComponentContainer.replaceComponent} 250 @raise NotImplementedError: 251 """ 252 raise NotImplementedError
253 254
255 - def removeComponent(self, c):
256 """Not supported in this implementation 257 258 @see: L{AbstractComponentContainer.removeComponent} 259 """ 260 raise NotImplementedError
261 262 # Methods for server-client communications. 263
264 - def paintContent(self, target):
265 """Paint (serialize) the component for the client. 266 267 @see: L{AbstractComponent.paintContent} 268 """ 269 # Superclass writes any common attributes in the paint target. 270 super(PopupView, self).paintContent(target) 271 272 html = self._content.getMinimizedValueAsHTML() 273 if html is None: 274 html = '' 275 276 target.addAttribute('html', html) 277 target.addAttribute('hideOnMouseOut', self._hideOnMouseOut) 278 279 # Only paint component to client if we know that the popup is showing 280 if self.isPopupVisible(): 281 target.startTag('popupComponent') 282 self._visibleComponent.paint(target) 283 target.endTag('popupComponent') 284 285 target.addVariable(self, 'popupVisibility', self.isPopupVisible())
286 287
288 - def changeVariables(self, source, variables):
289 """Deserialize changes received from client. 290 291 @see: L{AbstractComponent.changeVariables} 292 """ 293 if 'popupVisibility' in variables: 294 self.setPopupVisible( bool(variables.get('popupVisibility')) )
295 296
297 - def addListener(self, listener, iface=None):
298 """Add a listener that is called whenever the visibility of the 299 popup is changed. 300 301 @param listener: the listener to add 302 @see: L{IPopupVisibilityListener} 303 @see: L{PopupVisibilityEvent} 304 @see: L{removeListener} 305 """ 306 if (isinstance(listener, IPopupVisibilityListener) and 307 (iface is None or issubclass(iface, IPopupVisibilityListener))): 308 self.registerListener(PopupVisibilityEvent, 309 listener, _POPUP_VISIBILITY_METHOD) 310 311 super(PopupView, self).addListener(listener, iface)
312 313
314 - def addCallback(self, callback, eventType=None, *args):
315 if eventType is None: 316 eventType = callback._eventType 317 318 if issubclass(eventType, PopupVisibilityEvent): 319 self.registerCallback(ClickEvent, callback, None, *args) 320 else: 321 super(PopupView, self).addCallback(callback, eventType, *args)
322 323
324 - def removeListener(self, listener, iface=None):
325 """Removes a previously added listener, so that it no longer receives 326 events when the visibility of the popup changes. 327 328 @param listener: the listener to remove 329 @see: L{IPopupVisibilityListener} 330 @see: L{addListener} 331 """ 332 if (isinstance(listener, IPopupVisibilityListener) and 333 (iface is None or issubclass(iface, IPopupVisibilityListener))): 334 self.withdrawListener(PopupVisibilityEvent, listener, 335 _POPUP_VISIBILITY_METHOD) 336 337 super(PopupView, self).removeListener(listener, iface)
338 339
340 - def removeCallback(self, callback, eventType=None):
341 if eventType is None: 342 eventType = callback._eventType 343 344 if issubclass(eventType, PopupVisibilityEvent): 345 self.withdrawCallback(PopupVisibilityEvent, callback) 346 else: 347 super(PopupView, self).removeCallback(callback, eventType)
348 349
350 -class PopupVisibilityEvent(ComponentEvent):
351 """This event is received by the PopupVisibilityListeners when the 352 visibility of the popup changes. You can get the new visibility directly 353 with L{isPopupVisible}, or get the PopupView that produced the event with 354 L{getPopupView}. 355 """ 356
357 - def __init__(self, source):
358 super(PopupVisibilityEvent, self).__init__(source)
359 360
361 - def getPopupView(self):
362 """Get the PopupView instance that is the source of this event. 363 364 @return: the source PopupView 365 """ 366 return self.getSource()
367 368
369 - def isPopupVisible(self):
370 """Returns the current visibility of the popup. 371 372 @return: true if the popup is visible 373 """ 374 return self.getPopupView().isPopupVisible()
375 376
377 -class IContent(object):
378 """Used to deliver customized content-packages to the PopupView. These 379 are dynamically loaded when they are redrawn. The user must take care 380 that neither of these methods ever return null. 381 """ 382
383 - def getMinimizedValueAsHTML(self):
384 """This should return a small view of the full data. 385 386 @return: value in HTML format 387 """ 388 raise NotImplementedError
389 390
391 - def getPopupComponent(self):
392 """This should return the full Component representing the data 393 394 @return: a Component for the value 395 """ 396 raise NotImplementedError
397 398
399 -class InnerContent(IContent):
400
401 - def __init__(self, small, large):
402 self._small = small 403 self._large = large
404 405
406 - def getMinimizedValueAsHTML(self):
407 return self._small
408 409
410 - def getPopupComponent(self):
411 return self._large
412