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

Source Code for Module muntjac.ui.custom_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  """Defines a container component with freely designed layout and style.""" 
 17   
 18  from muntjac.ui.abstract_layout import AbstractLayout 
 19  from muntjac.ui.component import IComponent 
 20   
 21   
22 -class CustomLayout(AbstractLayout):
23 """A container component with freely designed layout and style. The 24 layout consists of items with textually represented locations. Each item 25 contains one sub-component, which can be any Muntjac component, such as a 26 layout. The adapter and theme are responsible for rendering the layout 27 with a given style by placing the items in the defined locations. 28 29 The placement of the locations is not fixed - different themes can define 30 the locations in a way that is suitable for them. One typical example 31 would be to create visual design for a web site as a custom layout: the 32 visual design would define locations for "menu", "body", and "title", for 33 example. The layout would then be implemented as an XHTML template for 34 each theme. 35 36 The default theme handles the styles that are not defined by drawing the 37 subcomponents just as in OrderedLayout. 38 39 @author: Vaadin Ltd. 40 @author: Richard Lincoln 41 @author: Duy B. Vo 42 @version: 1.1.2 43 """ 44 45 CLIENT_WIDGET = None #ClientWidget(VCustomLayout, LoadStyle.EAGER) 46 47 _BUFFER_SIZE = 10000 48
49 - def __init__(self, template=None):
50 """Default constructor only used by subclasses. Subclasses are 51 responsible for setting the appropriate fields. Either 52 L{setTemplateName}, that makes layout fetch the template from theme, 53 or L{setTemplateContents}. 54 55 Template file is fetched from "<theme>/layout/<templateName>". 56 57 @raise IOException: 58 """ 59 super(CustomLayout, self).__init__() 60 61 # Custom layout slots containing the components. 62 self._slots = dict() 63 self._templateContents = None 64 self._templateName = None 65 66 self.setWidth(100, self.UNITS_PERCENTAGE) 67 68 if template is not None: 69 if isinstance(template, basestring): 70 self._templateName = template 71 else: 72 self.initTemplateContentsFromInputStream(template)
73 74
75 - def initTemplateContentsFromInputStream(self, templateStream):
76 self._templateContents = templateStream.getvalue()
77 78
79 - def addComponent(self, c, location=''):
80 """Adds the component into this container to given location. If 81 the location is already populated, the old component is removed. 82 If the component is added without specifying the location (empty 83 string is then used as location). Only one component can be added 84 to the default "" location and adding more components into that 85 location overwrites the old components. 86 87 @param c: the component to be added. 88 @param location: the location of the component. 89 """ 90 old = self._slots.get(location) 91 if old is not None: 92 self.removeComponent(old) 93 self._slots[location] = c 94 c.setParent(self) 95 self.fireComponentAttachEvent(c) 96 self.requestRepaint()
97 98
99 - def removeComponent(self, arg):
100 """Removes the component from this container or the given location. 101 102 @param arg: the component to be removed or the location identifier 103 of the component. 104 """ 105 if isinstance(arg, IComponent): 106 c = arg 107 if c is None: 108 return 109 for k, v in self._slots.iteritems(): 110 if v == c: 111 del self._slots[k] 112 break 113 super(CustomLayout, self).removeComponent(c) 114 self.requestRepaint() 115 else: 116 location = arg 117 self.removeComponent(self._slots.get(location))
118 119
120 - def getComponentIterator(self):
121 """Gets the component container iterator for going trough all 122 the components in the container. 123 124 @return: the iterator of the components inside the container. 125 """ 126 return iter( self._slots.values() )
127 128
129 - def getComponentCount(self):
130 """Gets the number of contained components. Consistent with the 131 iterator returned by L{getComponentIterator}. 132 133 @return: the number of contained components 134 """ 135 return len( self._slots.values() )
136 137
138 - def getComponent(self, location):
139 """Gets the child-component by its location. 140 141 @param location: the name of the location where the requested 142 component resides. 143 @return: the IComponent in the given location or null if not found. 144 """ 145 return self._slots.get(location)
146 147
148 - def paintContent(self, target):
149 """Paints the content of this component. 150 151 @raise PaintException: if the paint operation failed. 152 """ 153 super(CustomLayout, self).paintContent(target) 154 155 if self._templateName is not None: 156 target.addAttribute('template', self._templateName) 157 else: 158 target.addAttribute('templateContents', self._templateContents) 159 160 # Adds all items in all the locations 161 for location, c in self._slots.iteritems(): 162 if c is not None: 163 # Writes the item 164 target.startTag('location') 165 target.addAttribute('name', location) 166 c.paint(target) 167 target.endTag('location')
168 169
170 - def replaceComponent(self, oldComponent, newComponent):
171 # Gets the locations 172 oldLocation = None 173 newLocation = None 174 175 for location, component in self._slots.iteritems(): 176 if component == oldComponent: 177 oldLocation = location 178 if component == newComponent: 179 newLocation = location 180 181 if oldLocation is None: 182 self.addComponent(newComponent) 183 184 elif newLocation is None: 185 self.removeComponent(oldLocation) 186 self.addComponent(newComponent, oldLocation) 187 188 else: 189 self._slots[newLocation] = oldComponent 190 self._slots[oldLocation] = newComponent 191 self.requestRepaint()
192 193
194 - def setStyle(self, name):
195 """CustomLayout's template selecting was previously implemented 196 with setStyle. Overriding to improve backwards compatibility. 197 198 @param name: template name 199 @deprecated: Use L{setTemplateName} instead 200 """ 201 self.setTemplateName(name)
202 203
204 - def getTemplateName(self):
205 """Get the name of the template""" 206 return self._templateName
207 208
209 - def getTemplateContents(self):
210 """Get the contents of the template""" 211 return self._templateContents
212 213
214 - def setTemplateName(self, templateName):
215 """Set the name of the template used to draw custom layout. 216 217 With GWT-adapter, the template with name 'templatename' is loaded 218 from VAADIN/themes/themename/layouts/templatename.html. If the theme 219 has not been set (with Application.setTheme()), themename is 220 'default'. 221 """ 222 self._templateName = templateName 223 self._templateContents = None 224 self.requestRepaint()
225 226
227 - def setTemplateContents(self, templateContents):
228 """Set the contents of the template used to draw the custom layout. 229 """ 230 self._templateContents = templateContents 231 self._templateName = None 232 self.requestRepaint()
233 234
235 - def setMargin(self, *args):
236 """Although most layouts support margins, CustomLayout does not. 237 The behaviour of this layout is determined almost completely by 238 the actual template. 239 240 @raise NotImplementedError: CustomLayout does not support margins 241 """ 242 raise NotImplementedError, 'CustomLayout does not support margins.'
243