Package pyjamas :: Package ui :: Module TreeItem
[hide private]
[frames] | no frames]

Source Code for Module pyjamas.ui.TreeItem

  1  # Copyright 2006 James Tauber and contributors 
  2  # Copyright (C) 2009 Luke Kenneth Casson Leighton <lkcl@lkcl.net> 
  3  # Copyright (C) 2011 Vsevolod Fedorov <vsevolod.fedorov@gmail.com> 
  4  # 
  5  # Licensed under the Apache License, Version 2.0 (the "License"); 
  6  # you may not use this file except in compliance with the License. 
  7  # You may obtain a copy of the License at 
  8  # 
  9  #     http://www.apache.org/licenses/LICENSE-2.0 
 10  # 
 11  # Unless required by applicable law or agreed to in writing, software 
 12  # distributed under the License is distributed on an "AS IS" BASIS, 
 13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 14  # See the License for the specific language governing permissions and 
 15  # limitations under the License. 
 16  from pyjamas import DOM 
 17  from pyjamas import Factory 
 18  from pyjamas.Canvas.GWTCanvas import GWTCanvas 
 19  from pyjamas.Canvas import Color 
 20   
 21  from pyjamas.ui.UIObject import UIObject 
 22  from pyjamas.ui.TreeContentPanel import TreeContentPanel 
 23   
 24  # http://www.greywyvern.com/code/php/binary2base64 - yaay! 
 25  # http://websemantics.co.uk/online_tools/image_to_data_uri_convertor/ 
 26  # this 2nd one didn't put %3D at the end, you have to back-convert that 
 27  # into "==" characters. 
 28  tree_closed = "data:image/gif;base64,R0lGODlhEAAQAJECAMzMzAAAAP///wAAACH5BAEAAAIALAAAAAAQABAAAAIjlI+py+1vgJxzAYtNOFd1sUVYQJLCh3zhmYFcm1oUBdU2VAAAOw==" 
 29  tree_open = "data:image/gif;base64,R0lGODlhEAAQAJECAAAAAMDAwAAAAP///yH5BAEAAAIALAAAAAAQABAAAAIflI+py+1vgpxzBYvV1TldAILC5nUIeZoHulIUBMdQAQA7" 
 30  tree_white = "data:image/gif;base64,R0lGODlhEAAQAJEAAP///wAAAP///wAAACH5BAEAAAIALAAAAAAQABAAAAIOlI+py+0Po5y02ouzPgUAOw==" 
 31   
32 -class TreeItem(UIObject):
33 34 # also callable as TreeItem(widget)
35 - def __init__(self, html=None, **ka):
36 self.children = [] 37 self.attached = False 38 self.contentPanel = None 39 self.itemTable = None 40 self.contentElem = None 41 self.imgElem = None 42 self.childSpanElem = None 43 self.open = False 44 self.parent = None 45 self.selected = False 46 self.tree = None 47 self.userObject = None 48 49 element = ka.pop('Element', None) or DOM.createDiv() 50 self.setElement(element) 51 52 self.itemTable = DOM.createTable() 53 self.contentElem = DOM.createSpan() 54 self.childSpanElem = DOM.createSpan() 55 self.imgElem = self.createImage() 56 57 tbody = DOM.createTBody() 58 tr = DOM.createTR() 59 tdImg = DOM.createTD() 60 tdContent = DOM.createTD() 61 DOM.appendChild(self.itemTable, tbody) 62 DOM.appendChild(tbody, tr) 63 DOM.appendChild(tr, tdImg) 64 DOM.appendChild(tr, tdContent) 65 DOM.setStyleAttribute(tdImg, "verticalAlign", "middle") 66 DOM.setStyleAttribute(tdContent, "verticalAlign", "middle") 67 DOM.setStyleAttribute(self.getElement(), "cursor", "pointer") 68 69 DOM.appendChild(self.getElement(), self.itemTable) 70 DOM.appendChild(self.getElement(), self.childSpanElem) 71 DOM.appendChild(tdImg, self.imgElem) 72 DOM.appendChild(tdContent, self.contentElem) 73 74 # XXX - can't set pos relative on a div node, 75 # or white_space on an HTML Table.. 76 try: 77 DOM.setAttribute(self.getElement(), "position", "relative") 78 except: 79 pass 80 DOM.setStyleAttribute(self.contentElem, "display", "inline") 81 DOM.setStyleAttribute(self.getElement(), "whiteSpace", "nowrap") 82 try: 83 DOM.setAttribute(self.itemTable, "whiteSpace", "nowrap") 84 except: 85 pass 86 DOM.setStyleAttribute(self.childSpanElem, "whiteSpace", "nowrap") 87 self.setStyleName(self.contentElem, "gwt-TreeItem", True) 88 89 #if not ka.has_key('StyleName'): ka['StyleName']="gwt-TreeItem" 90 91 if html is not None: 92 try: 93 # messy. pyjd can do unicode, pyjs can't 94 if isinstance(html, unicode): 95 ka['HTML'] = html 96 elif isinstance(html, basestring): 97 ka['HTML'] = html 98 else: 99 ka['Widget'] = html 100 except: 101 if isinstance(html, basestring): 102 ka['HTML'] = html 103 else: 104 ka['Widget'] = html 105 106 UIObject.__init__(self, **ka)
107
108 - def __iter__(self):
109 return self.children.__iter__()
110
111 - def createImage(self):
112 return DOM.createImg()
113 114 # also callable as addItem(widget) and addItem(itemText)
115 - def addItem(self, item):
116 return self.insertItem(item)
117 118 # also callable as addItem(widget) and addItem(itemText)
119 - def insertItem(self, item, index=None):
120 if not hasattr(item, "getTree"): 121 #if not item.getTree: 122 item = TreeItem(item) 123 124 if (item.getParentItem() is not None) or (item.getTree() is not None): 125 item.remove() 126 127 item.setTree(self.tree) 128 item.setParentItem(self) 129 if index is None: 130 self.children.append(item) 131 else: 132 self.children.insert(index, item) 133 DOM.setStyleAttribute(item.getElement(), "marginLeft", "16px") 134 if index is None: 135 DOM.appendChild(self.childSpanElem, item.getElement()) 136 else: 137 DOM.insertChild(self.childSpanElem, item.getElement(), index) 138 139 if len(self.children) == 1: 140 self.updateState() 141 142 return item
143
144 - def onAttach(self):
145 if self.attached: 146 return 147 self.attached = True 148 for item in self.children: 149 item.onAttach() 150 w = self.getWidget() 151 if w: 152 w.onAttach()
153
154 - def onDetach(self):
155 self.attached = False 156 for item in self.children: 157 item.onDetach() 158 w = self.getWidget() 159 if w: 160 w.onDetach()
161
162 - def getChild(self, index):
163 if (index < 0) or (index >= len(self.children)): 164 return None 165 166 return self.children[index]
167
168 - def getChildCount(self):
169 return len(self.children)
170
171 - def getChildIndex(self, child):
172 return self.children.index(child)
173
174 - def getHTML(self):
175 return DOM.getInnerHTML(self.contentElem)
176
177 - def getText(self):
178 return DOM.getInnerText(self.contentElem)
179
180 - def getParentItem(self):
181 return self.parent
182
183 - def getState(self):
184 return self.open
185
186 - def getTree(self):
187 return self.tree
188
189 - def getUserObject(self):
190 return self.userObject
191
192 - def getWidget(self):
193 if self.contentPanel is None: 194 return None 195 196 return self.contentPanel.getWidget()
197
198 - def isSelected(self):
199 return self.selected
200
201 - def remove(self):
202 if self.parent is not None: 203 self.parent.removeItem(self) 204 elif self.tree is not None: 205 self.tree.removeItem(self)
206
207 - def removeItem(self, item):
208 if item not in self.children: 209 return 210 211 item.setTree(None) 212 item.setParentItem(None) 213 self.children.remove(item) 214 DOM.removeChild(self.childSpanElem, item.getElement()) 215 if len(self.children) == 0: 216 self.updateState()
217
218 - def removeItems(self):
219 while self.getChildCount() > 0: 220 self.removeItem(self.getChild(0))
221
222 - def setHTML(self, html):
223 self.clearContentPanel() 224 DOM.setInnerHTML(self.contentElem, html)
225
226 - def setText(self, text):
227 self.clearContentPanel() 228 DOM.setInnerText(self.contentElem, text)
229
230 - def setSelected(self, selected):
231 if self.selected == selected: 232 return 233 self.selected = selected 234 self.setStyleName(self.contentElem, "gwt-TreeItem-selected", selected)
235
236 - def setState(self, open, fireEvents=True):
237 238 # lkcl: experiment with allowing event state changed to be 239 # fired even on items with no children. otherwise you never 240 # get to find out if an end-item was selected! 241 if not open or len(self.children) != 0: 242 self.open = open 243 self.updateState() 244 245 if fireEvents: 246 self.tree.fireStateChanged(self)
247
248 - def setUserObject(self, userObj):
249 self.userObject = userObj
250
251 - def setWidget(self, widget):
252 self.ensureContentPanel() 253 self.contentPanel.setWidget(widget)
254
255 - def clearContentPanel(self):
256 if self.contentPanel is not None: 257 child = self.contentPanel.getWidget() 258 if child is not None: 259 self.contentPanel.remove(child) 260 261 if self.tree is not None: 262 self.tree.disown(self.contentPanel) 263 self.contentPanel = None
264
265 - def ensureContentPanel(self):
266 if self.contentPanel is None: 267 DOM.setInnerHTML(self.contentElem, "") 268 self.contentPanel = TreeContentPanel(self.contentElem) 269 self.contentPanel.setTreeItem(self) 270 if self.getTree() is not None: 271 self.tree.adopt(self.contentPanel)
272
273 - def addTreeItems(self, accum):
274 for item in self.children: 275 accum.append(item) 276 item.addTreeItems(accum)
277
278 - def getChildren(self):
279 return self.children
280
281 - def getContentElem(self):
282 return self.contentElem
283
284 - def getContentHeight(self):
285 return DOM.getIntAttribute(self.itemTable, "offsetHeight")
286
287 - def getImageElement(self):
288 return self.imgElem
289
290 - def getTreeTop(self):
291 item = self 292 ret = 0 293 294 while item is not None: 295 ret += DOM.getIntAttribute(item.getElement(), "offsetTop") 296 item = item.getParentItem() 297 298 return ret
299
300 - def getFocusableWidget(self):
301 widget = self.getWidget() 302 if hasattr(widget, "setFocus"): 303 return widget 304 return None
305
306 - def imgSrc(self, img):
307 if self.tree is None: 308 return img 309 src = self.tree.getImageBase() + img 310 return src
311
312 - def setParentItem(self, parent):
313 self.parent = parent
314
315 - def setTree(self, tree):
316 if self.tree == tree: 317 return 318 319 if self.tree is not None: 320 if self.tree.getSelectedItem() == self: 321 self.tree.setSelectedItem(None) 322 323 if self.contentPanel is not None: 324 self.tree.disown(self.contentPanel) 325 326 self.tree = tree 327 for child in self.children: 328 child.setTree(tree) 329 self.updateState() 330 if tree is not None and self.contentPanel is not None: 331 tree.adopt(self.contentPanel)
332
333 - def updateState(self):
334 if len(self.children) == 0: 335 self.setVisible(self.childSpanElem, False) 336 #DOM.setAttribute(self.imgElem, "src", self.imgSrc("tree_white.gif")) 337 self.drawImage("white") 338 return 339 340 if self.open: 341 self.setVisible(self.childSpanElem, True) 342 self.drawImage("open") 343 else: 344 self.setVisible(self.childSpanElem, False) 345 self.drawImage("closed")
346
347 - def updateStateRecursive(self):
348 self.updateState() 349 for i in range(len(self.children)): 350 child = self.children[i] 351 child.updateStateRecursive()
352
353 - def drawImage(self, mode):
354 if mode == "white": 355 src = tree_white 356 elif mode == "open": 357 src = tree_open 358 elif mode == "closed": 359 src = tree_closed 360 361 DOM.setAttribute(self.imgElem, "src", src)
362 363
364 -class RootTreeItem(TreeItem):
365 - def addItem(self, item):
366 self.insertItem(item)
367
368 - def insertItem(self, item, index=None):
369 if (item.getParentItem() is not None) or (item.getTree() is not None): 370 item.remove() 371 item.setTree(self.getTree()) 372 373 item.setParentItem(None) 374 if index is None: 375 self.children.append(item) 376 else: 377 self.children.insert(index, item) 378 379 DOM.setIntStyleAttribute(item.getElement(), "marginLeft", 0)
380
381 - def removeItem(self, item):
382 if item not in self.children: 383 return 384 385 item.setTree(None) 386 item.setParentItem(None) 387 self.children.remove(item)
388 389 Factory.registerClass('pyjamas.ui.TreeItem', 'TreeItem', TreeItem) 390