Package muntjac :: Package addon :: Package weelayout :: Module wee_layout
[hide private]
[frames] | no frames]

Source Code for Module muntjac.addon.weelayout.wee_layout

  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 muntjac.ui.abstract_layout \ 
 17      import AbstractLayout 
 18   
 19  from muntjac.ui.alignment \ 
 20      import Alignment 
 21   
 22  from muntjac.event.layout_events \ 
 23      import ILayoutClickNotifier, LayoutClickEvent, ILayoutClickListener 
 24   
 25  from muntjac.terminal.gwt.client.event_id \ 
 26      import EventId 
 27   
 28   
29 -class Direction(object):
30 VERTICAL = 'VERTICAL' 31 HORIZONTAL = 'HORIZONTAL'
32 33
34 -class WeeLayout(AbstractLayout, ILayoutClickNotifier):
35 """Server side component for the VWeeLayout widget.""" 36 37 CLIENT_WIDGET = None #ClientWidget(VWeeLayout) 38 39 TYPE_MAPPING = 'org.vaadin.weelayout.WeeLayout' 40 41 _CLICK_EVENT = EventId.LAYOUT_CLICK 42
43 - def __init__(self, direction):
44 """Create a new layout. The direction of the child components must be 45 specified. The direction can only be set once. 46 47 @param direction: 48 The direction in which the child components will flow, either 49 L{Direction}.VERTICAL or L{Direction} .HORIZONTAL 50 """ 51 self._direction = direction 52 53 # Custom layout slots containing the components. 54 self.components = list() 55 56 # Mapping from components to alignments (horizontal + vertical). 57 self._componentToAlignment = dict() 58 59 # Should the layout clip any overflowing components outside the layout 60 # dimensions. 61 self._clip = False 62 63 self._smartRelatives = None 64 65 super(WeeLayout, self).__init__()
66 67
68 - def addComponent(self, *args):
69 """Add a component into this container. The component is added after the 70 previous component or into indexed position in this container. 71 72 @param args: 73 tuple of the form: 74 - (c) 75 - the component to be added. 76 - (c, alignment) 77 - the component to be added. 78 - the alignment for the component. 79 - (c, width, height, alignment) 80 - the component to be added. 81 - set the width of the component. Use <code>null</code> 82 to leave untouched. 83 - set the height of the component. Use <code>null</code> 84 to leave untouched. 85 - the alignment for the component. 86 - (c, index) 87 - the component to be added. 88 - the Index of the component position. The components 89 currently in and after the position are shifted forwards. 90 - (c, index, alignment) 91 - the component to be added. 92 - the Index of the component position. The components 93 currently in and after the position are shifted forwards. 94 - the alignment for the component. 95 """ 96 nargs = len(args) 97 if nargs == 1: 98 c, = args 99 self.components.append(c) 100 try: 101 super(WeeLayout, self).addComponent(c) 102 self.requestRepaint() 103 except ValueError, e: 104 self.components.remove(c) 105 raise e 106 elif nargs == 2: 107 if isinstance(args[1], Alignment): 108 c, alignment = args 109 self.addComponent(c) 110 if alignment is not None: 111 self.setComponentAlignment(c, alignment) 112 else: 113 c, index = args 114 self.components.append(index, c) 115 try: 116 super(WeeLayout, self).addComponent(c) 117 self.requestRepaint() 118 except ValueError, e: 119 self.components.remove(c) 120 raise e 121 elif nargs == 3: 122 c, index, alignment = args 123 self.components.append(index, c) 124 try: 125 super(WeeLayout, self).addComponent(c) 126 self.setComponentAlignment(c, alignment) 127 self.requestRepaint() 128 except ValueError, e: 129 self.components.remove(c) 130 self._componentToAlignment.remove(c) 131 raise e 132 elif nargs == 4: 133 c, width, height, alignment = args 134 self.addComponent(c) 135 if width is not None: 136 c.setWidth(width) 137 if height is not None: 138 c.setHeight(height) 139 if alignment is not None: 140 self.setComponentAlignment(c, alignment) 141 else: 142 raise ValueError
143 144
145 - def removeComponent(self, c):
146 """Removes the component from this container. 147 148 @param c: 149 the component to be removed. 150 """ 151 self.components.remove(c) 152 self._componentToAlignment.remove(c) 153 super(WeeLayout, self).removeComponent(c) 154 self.requestRepaint()
155 156
157 - def paintContent(self, target):
158 super(WeeLayout, self).paintContent(target) 159 160 # Specify direction 161 if self._direction == Direction.VERTICAL: 162 target.addAttribute('vertical', True) 163 164 # Specify clipping 165 if self._clip: 166 target.addAttribute('clip', True) 167 168 # Specify smart relative size handling 169 if self._smartRelatives: 170 target.addAttribute('smart', True) 171 172 # Adds all items in all the locations 173 for c in self.components: 174 # Paint child component UIDL 175 c.paint(target) 176 177 # Add child component alignment info to layout tag 178 target.addAttribute('alignments', self._componentToAlignment)
179 180
181 - def getComponentIterator(self):
182 return self.components
183 184
185 - def replaceComponent(self, oldComponent, newComponent):
186 # Gets the locations 187 oldLocation = -1 188 newLocation = -1 189 location = 0 190 191 for component in self.components: 192 if component == oldComponent: 193 oldLocation = location 194 195 if component == newComponent: 196 newLocation = location 197 198 location += 1 199 200 if oldLocation == -1: 201 self.addComponent(newComponent) 202 elif newLocation == -1: 203 self.removeComponent(oldComponent) 204 self.addComponent(newComponent, oldLocation) 205 else: 206 if oldLocation > newLocation: 207 self.components.remove(oldComponent) 208 self.components.append(newLocation, oldComponent) 209 self.components.remove(newComponent) 210 self._componentToAlignment.remove(newComponent) 211 self.components.append(oldLocation, newComponent) 212 else: 213 self.components.remove(newComponent) 214 self.components.append(oldLocation, newComponent) 215 self.components.remove(oldComponent) 216 self._componentToAlignment.remove(oldComponent) 217 self.components.append(newLocation, oldComponent) 218 219 self.requestRepaint()
220 221
222 - def setComponentAlignment(self, childComponent, alignment):
223 """Set the alignment of component in this layout. Only one direction 224 is affected, depending on the layout direction, i.e. only vertical 225 alignment is considered when the direction is horizontal. 226 """ 227 if childComponent in self.components and alignment is not None: 228 self._componentToAlignment[childComponent] = alignment 229 self.requestRepaint() 230 else: 231 raise ValueError('Component must be added to layout before using setComponentAlignment()')
232 233
234 - def getComponentAlignment(self, childComponent):
235 alignment = self._componentToAlignment.get(childComponent) 236 if alignment is None: 237 return Alignment.TOP_LEFT 238 else: 239 return alignment
240 241
242 - def getComponentIndex(self, component):
243 """Returns the index of the given component. 244 245 @param component: 246 The component to look up. 247 @return: The index of the component or -1 if the component is not 248 a child. 249 """ 250 return self.components.index(component)
251 252
253 - def getComponent(self, index):
254 """Returns the component at the given position. 255 256 @param index: 257 The position of the component. 258 @return: The component at the given index. 259 @raise IndexError: 260 If the index is out of range. 261 """ 262 return self.components[index]
263 264
265 - def size(self):
266 """Returns the number of components in the layout. 267 268 @return: Component amount 269 """ 270 return len(self.components)
271 272
273 - def setClipping(self, clip):
274 """Set the clipping value for this layout. If clipping is C{True}, 275 components overflowing outside the layout boundaries will be clipped. 276 Otherwise overflowing components are visible. 277 278 @param clip: 279 the new clipping value. 280 """ 281 self._clip = clip 282 self.requestRepaint()
283 284
285 - def setSmartRelativeSizes(self, smartRelatives):
286 """When the layout size is undefined, relative sizes are calculated as 287 zeros. Set this flag to C{True} if you wish for the layout to 288 calculate relative sizes inside undefined sized layouts as well (the 289 largest component will determine the size). 290 """ 291 self._smartRelatives = smartRelatives
292 293
294 - def addListener(self, listener, iface=None):
295 if (isinstance(listener, ILayoutClickListener) and 296 (iface is None or issubclass(iface, ILayoutClickListener))): 297 self.registerListener(self._CLICK_EVENT, LayoutClickEvent, 298 listener, ILayoutClickListener.clickMethod) 299 300 super(WeeLayout, self).addListener(listener, iface)
301 302
303 - def addCallback(self, callback, eventType=None, *args):
304 if eventType is None: 305 eventType = callback._eventType # set by decorator 306 307 if issubclass(eventType, LayoutClickEvent): 308 self.registerCallback(LayoutClickEvent, callback, 309 self._CLICK_EVENT, *args) 310 else: 311 super(WeeLayout, self).addCallback(callback, eventType, *args)
312 313
314 - def removeListener(self, listener, iface=None):
315 if (isinstance(listener, ILayoutClickListener) and 316 (iface is None or issubclass(iface, ILayoutClickListener))): 317 self.withdrawListener(self._CLICK_EVENT, LayoutClickEvent, 318 listener) 319 320 super(WeeLayout, self).addListener(listener, iface)
321 322
323 - def removeCallback(self, callback, eventType=None):
324 if eventType is None: 325 eventType = callback._eventType 326 327 if issubclass(eventType, LayoutClickEvent): 328 self.withdrawCallback(LayoutClickEvent, callback, 329 self._CLICK_EVENT) 330 else: 331 super(WeeLayout, self).removeCallback(callback, eventType)
332