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

Source Code for Module muntjac.ui.abstract_split_panel

  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  """Defines a base class for a component container that can contain two 
 17  components.""" 
 18   
 19  from muntjac.ui.vertical_layout import VerticalLayout 
 20  from muntjac.ui.abstract_layout import AbstractLayout 
 21  from muntjac.terminal.gwt.client.mouse_event_details import MouseEventDetails 
 22  from muntjac.event.mouse_events import ClickEvent as MouseClickEvent 
 23  from muntjac.event.component_event_listener import IComponentEventListener 
 24   
 25  from muntjac.terminal.gwt.client.ui.v_split_panel import VSplitPanel 
 26  from muntjac.ui.abstract_component import AbstractComponent 
 27   
 28   
29 -class ComponentIterator(object):
30 """Modifiable and serializable iterator for the components, used by 31 L{AbstractSplitPanel.getComponentIterator}. 32 """ 33
34 - def __init__(self, sp):
35 self.sp = sp 36 self._i = 0
37 38
39 - def __iter__(self):
40 return self
41 42
43 - def hasNext(self):
44 if self._i < self.sp.getComponentCount(): 45 return True 46 return False
47 48
49 - def next(self): #@PydevCodeAnalysisIgnore
50 if not self.hasNext(): 51 raise StopIteration 52 53 self._i += 1 54 55 if self._i == 1: 56 if self.sp._firstComponent is None: 57 return self.sp._secondComponent 58 else: 59 return self.sp._firstComponent 60 elif self._i == 2: 61 return self.sp._secondComponent 62 63 return None
64 65
66 - def remove(self):
67 if self._i == 1: 68 if self.sp._firstComponent is not None: 69 self.sp.setFirstComponent(None) 70 self._i = 0 71 else: 72 self.sp.setSecondComponent(None) 73 elif self._i == 2: 74 self.sp.setSecondComponent(None)
75 76
77 -class AbstractSplitPanel(AbstractLayout):
78 """C{AbstractSplitPanel} is base class for a component container that can 79 contain two components. The comopnents are split by a divider element. 80 81 @author: Vaadin Ltd. 82 @version: 1.1.2 83 """ 84 85 _SPLITTER_CLICK_EVENT = VSplitPanel.SPLITTER_CLICK_EVENT_IDENTIFIER 86
87 - def __init__(self):
88 super(AbstractSplitPanel, self).__init__() 89 90 self._firstComponent = None 91 self._secondComponent = None 92 self._pos = 50 93 self._posUnit = self.UNITS_PERCENTAGE 94 self._posReversed = False 95 self._locked = False
96 97
98 - def addComponent(self, c):
99 """Add a component into this container. The component is added to 100 the right or under the previous component. 101 102 @param c: 103 the component to be added. 104 """ 105 if self._firstComponent is None: 106 self._firstComponent = c 107 elif self._secondComponent is None: 108 self._secondComponent = c 109 else: 110 raise NotImplementedError, \ 111 'Split panel can contain only two components' 112 113 super(AbstractSplitPanel, self).addComponent(c) 114 self.requestRepaint()
115 116
117 - def setFirstComponent(self, c):
118 if self._firstComponent == c: 119 return # Nothing to do 120 121 if self._firstComponent is not None: 122 self.removeComponent(self._firstComponent) # detach old 123 124 self._firstComponent = c 125 super(AbstractSplitPanel, self).addComponent(c) 126 self.requestRepaint()
127 128
129 - def setSecondComponent(self, c):
130 if c == self._secondComponent: 131 return # Nothing to do 132 133 if self._secondComponent is not None: 134 self.removeComponent(self._secondComponent) # detach old 135 136 self._secondComponent = c 137 super(AbstractSplitPanel, self).addComponent(c) 138 self.requestRepaint()
139 140
141 - def getFirstComponent(self):
142 """@return: the first component of this SplitPanel.""" 143 return self._firstComponent
144 145
146 - def getSecondComponent(self):
147 """@return: the second component of this SplitPanel.""" 148 return self._secondComponent
149 150
151 - def removeComponent(self, c):
152 """Removes the component from this container. 153 154 @param c: the component to be removed. 155 """ 156 super(AbstractSplitPanel, self).removeComponent(c) 157 158 if c == self._firstComponent: 159 self._firstComponent = None 160 elif c == self._secondComponent: 161 self._secondComponent = None 162 163 self.requestRepaint()
164 165
166 - def getComponentIterator(self):
167 return ComponentIterator(self)
168 169
170 - def getComponentCount(self):
171 """Gets the number of contained components. Consistent with the 172 iterator returned by L{getComponentIterator}. 173 174 @return: the number of contained components (zero, one or two) 175 """ 176 count = 0 177 if self._firstComponent is not None: 178 count += 1 179 180 if self._secondComponent is not None: 181 count += 1 182 183 return count
184 185
186 - def paintContent(self, target):
187 """Paints the content of this component. 188 189 @param target: 190 the Paint Event. 191 @raise PaintException: 192 if the paint operation failed. 193 """ 194 super(AbstractSplitPanel, self).paintContent(target) 195 196 position = str(self._pos) + self.UNIT_SYMBOLS[self._posUnit] 197 198 target.addAttribute('position', position) 199 200 if self.isLocked(): 201 target.addAttribute('locked', True) 202 203 target.addAttribute('reversed', self._posReversed) 204 205 if self._firstComponent is not None: 206 self._firstComponent.paint(target) 207 else: 208 temporaryComponent = VerticalLayout() 209 temporaryComponent.setParent(self) 210 temporaryComponent.paint(target) 211 if self._secondComponent is not None: 212 self._secondComponent.paint(target) 213 else: 214 temporaryComponent = VerticalLayout() 215 temporaryComponent.setParent(self) 216 temporaryComponent.paint(target)
217 218
219 - def replaceComponent(self, oldComponent, newComponent):
220 221 if oldComponent == self._firstComponent: 222 self.setFirstComponent(newComponent) 223 elif oldComponent == self._secondComponent: 224 self.setSecondComponent(newComponent) 225 226 self.requestRepaint()
227 228
229 - def setSplitPosition(self, *args):
230 """Moves the position of the splitter. 231 232 @param args: tuple of the form 233 - (pos) 234 1. the new size of the region in the unit that was last 235 used (default is percentage) 236 - (pos, reverse) 237 1. size of the first region 238 2. if set to true the split splitter position is measured by 239 the second region else it is measured by the first region 240 - (pos, unit, reverse) 241 1. size of the first region 242 2. the unit (from L{Sizeable}) in which the size is given. 243 3. if set to true the split splitter position is measured by 244 the second region else it is measured by the first region 245 - (pos, unit, repaintNotNeeded) 246 1. size of the first region 247 2. the unit (from L{Sizeable}) in which the size is given. 248 3. true if client side needs to be updated. Use false if 249 the position info has come from the client side, thus it 250 already knows the position. 251 """ 252 nargs = len(args) 253 if nargs == 1: 254 pos, = args 255 self.setSplitPosition(pos, self._posUnit, True, False) 256 elif nargs == 2: 257 if isinstance(args[1], bool): 258 pos, reverse = args 259 self.setSplitPosition(pos, self._posUnit, True, reverse) 260 else: 261 pos, unit = args 262 self.setSplitPosition(pos, unit, True, False) 263 elif nargs == 3: 264 pos, unit, reverse = args 265 self.setSplitPosition(pos, unit, True, reverse) 266 elif nargs == 4: 267 pos, unit, repaintNeeded, reverse = args 268 if unit != self.UNITS_PERCENTAGE and unit != self.UNITS_PIXELS: 269 raise ValueError, \ 270 'Only percentage and pixel units are allowed' 271 self._pos = pos 272 self._posUnit = unit 273 self._posReversed = reverse 274 if repaintNeeded: 275 self.requestRepaint() 276 else: 277 raise ValueError, 'too many arguments'
278 279
280 - def getSplitPosition(self):
281 """Returns the current position of the splitter, in 282 L{getSplitPositionUnit} units. 283 284 @return: position of the splitter 285 """ 286 return self._pos
287 288
289 - def getSplitPositionUnit(self):
290 """Returns the unit of position of the splitter 291 292 @return: unit of position of the splitter 293 """ 294 return self._posUnit
295 296
297 - def setLocked(self, locked):
298 """Lock the SplitPanels position, disabling the user from dragging 299 the split handle. 300 301 @param locked: 302 Set C{True} if locked, C{False} otherwise. 303 """ 304 self._locked = locked 305 self.requestRepaint()
306 307
308 - def isLocked(self):
309 """Is the SplitPanel handle locked (user not allowed to change 310 split position by dragging). 311 312 @return: C{True} if locked, C{False} otherwise. 313 """ 314 return self._locked
315 316
317 - def changeVariables(self, source, variables):
318 # Invoked when a variable of the component changes. 319 super(AbstractSplitPanel, self).changeVariables(source, variables) 320 321 if 'position' in variables and not self.isLocked(): 322 newPos = variables.get('position') 323 self.setSplitPosition(newPos, self._posUnit, self._posReversed) 324 325 if self._SPLITTER_CLICK_EVENT in variables: 326 self.fireClick(variables.get(self._SPLITTER_CLICK_EVENT))
327 328
329 - def fireClick(self, parameters):
330 mouseDetails = \ 331 MouseEventDetails.deSerialize(parameters.get('mouseDetails')) 332 self.fireEvent( SplitterClickEvent(self, mouseDetails) )
333 334
335 - def addListener(self, listener, iface=None):
336 if (isinstance(listener, ISplitterClickListener) and 337 (iface is None or issubclass(iface, ISplitterClickListener))): 338 self.registerListener(self._SPLITTER_CLICK_EVENT, 339 SplitterClickEvent, listener, 340 ISplitterClickListener.clickMethod) 341 342 super(AbstractSplitPanel, self).addListener(listener, iface)
343 344
345 - def addCallback(self, callback, eventType=None, *args):
346 if eventType is None: 347 eventType = callback._eventType 348 349 if issubclass(eventType, SplitterClickEvent): 350 self.registerCallback(SplitterClickEvent, callback, None, *args) 351 352 else: 353 super(AbstractSplitPanel, self).addCallback(callback, eventType, 354 *args)
355 356
357 - def removeListener(self, listener, iface=None):
358 if (isinstance(listener, ISplitterClickListener) and 359 (iface is None or issubclass(iface, ISplitterClickListener))): 360 self.withdrawListener(self._SPLITTER_CLICK_EVENT, 361 SplitterClickEvent, listener) 362 363 super(AbstractSplitPanel, self).removeListener(listener, iface)
364 365
366 - def removeCallback(self, callback, eventType=None):
367 if eventType is None: 368 eventType = callback._eventType 369 370 if issubclass(eventType, SplitterClickEvent): 371 self.withdrawCallback(SplitterClickEvent, callback, 372 self._SPLITTER_CLICK_EVENT) 373 374 else: 375 super(AbstractSplitPanel, self).removeCallback(callback, eventType)
376 377
378 -class ISplitterClickListener(IComponentEventListener):
379 """C{ISplitterClickListener} interface for listening for 380 C{SplitterClickEvent} fired by a C{SplitPanel}. 381 382 @see: SplitterClickEvent 383 """ 384
385 - def splitterClick(self, event):
386 """SplitPanel splitter has been clicked 387 388 @param event: 389 SplitterClickEvent event. 390 """ 391 raise NotImplementedError
392 393 clickMethod = splitterClick
394 395
396 -class SplitterClickEvent(MouseClickEvent):
397
398 - def __init__(self, source, mouseEventDetails):
399 super(SplitterClickEvent, self).__init__(source, mouseEventDetails)
400