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

Source Code for Module library.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-2012 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 self.setStyleName(tdImg, "gwt-TreeItemTdImg", True) 75 self.setStyleName(tdContent, "gwt-TreeItemTdContent", True) 76 77 # XXX - can't set pos relative on a div node, 78 # or white_space on an HTML Table.. 79 try: 80 DOM.setAttribute(self.getElement(), "position", "relative") 81 except: 82 pass 83 DOM.setStyleAttribute(self.contentElem, "display", "inline") 84 DOM.setStyleAttribute(self.getElement(), "whiteSpace", "nowrap") 85 try: 86 DOM.setAttribute(self.itemTable, "whiteSpace", "nowrap") 87 except: 88 pass 89 DOM.setStyleAttribute(self.childSpanElem, "whiteSpace", "nowrap") 90 self.setStyleName(self.contentElem, "gwt-TreeItem", True) 91 92 #if not ka.has_key('StyleName'): ka['StyleName']="gwt-TreeItem" 93 94 if html is not None: 95 try: 96 # messy. pyjd can do unicode, pyjs can't 97 if isinstance(html, unicode): 98 ka['HTML'] = html 99 elif isinstance(html, basestring): 100 ka['HTML'] = html 101 else: 102 ka['Widget'] = html 103 except: 104 if isinstance(html, basestring): 105 ka['HTML'] = html 106 else: 107 ka['Widget'] = html 108 109 UIObject.__init__(self, **ka)
110
111 - def __iter__(self):
112 return self.children.__iter__()
113
114 - def createImage(self):
115 return DOM.createImg()
116 117 # also callable as addItem(widget) and addItem(itemText)
118 - def addItem(self, item):
119 return self.insertItem(item)
120 121 # also callable as addItem(widget) and addItem(itemText)
122 - def insertItem(self, item, index=None):
123 if not hasattr(item, "getTree"): 124 #if not item.getTree: 125 item = TreeItem(item) 126 127 if (item.getParentItem() is not None) or (item.getTree() is not None): 128 item.remove() 129 130 item.setTree(self.tree) 131 item.setParentItem(self) 132 if index is None: 133 self.children.append(item) 134 else: 135 self.children.insert(index, item) 136 DOM.setStyleAttribute(item.getElement(), "marginLeft", "16px") 137 if index is None: 138 DOM.appendChild(self.childSpanElem, item.getElement()) 139 else: 140 DOM.insertChild(self.childSpanElem, item.getElement(), index) 141 142 if len(self.children) == 1: 143 self.updateState() 144 145 return item
146
147 - def onAttach(self):
148 if self.attached: 149 return 150 self.attached = True 151 for item in self.children: 152 item.onAttach() 153 w = self.getWidget() 154 if w: 155 w.onAttach()
156
157 - def onDetach(self):
158 self.attached = False 159 for item in self.children: 160 item.onDetach() 161 w = self.getWidget() 162 if w: 163 w.onDetach()
164
165 - def getChild(self, index):
166 if (index < 0) or (index >= len(self.children)): 167 return None 168 169 return self.children[index]
170
171 - def getChildCount(self):
172 return len(self.children)
173
174 - def getChildIndex(self, child):
175 return self.children.index(child)
176
177 - def getHTML(self):
178 return DOM.getInnerHTML(self.contentElem)
179
180 - def getText(self):
181 return DOM.getInnerText(self.contentElem)
182
183 - def getParentItem(self):
184 return self.parent
185
186 - def getState(self):
187 return self.open
188
189 - def getTree(self):
190 return self.tree
191
192 - def getUserObject(self):
193 return self.userObject
194
195 - def getWidget(self):
196 if self.contentPanel is None: 197 return None 198 199 return self.contentPanel.getWidget()
200
201 - def isSelected(self):
202 return self.selected
203
204 - def remove(self):
205 if self.parent is not None: 206 self.parent.removeItem(self) 207 elif self.tree is not None: 208 self.tree.removeItem(self)
209
210 - def removeItem(self, item):
211 if item not in self.children: 212 return 213 214 item.setTree(None) 215 item.setParentItem(None) 216 self.children.remove(item) 217 DOM.removeChild(self.childSpanElem, item.getElement()) 218 if len(self.children) == 0: 219 self.updateState()
220
221 - def removeItems(self):
222 while self.getChildCount() > 0: 223 self.removeItem(self.getChild(0))
224
225 - def setHTML(self, html):
226 self.clearContentPanel() 227 DOM.setInnerHTML(self.contentElem, html)
228
229 - def setText(self, text):
230 self.clearContentPanel() 231 DOM.setInnerText(self.contentElem, text)
232
233 - def setSelected(self, selected):
234 if self.selected == selected: 235 return 236 self.selected = selected 237 self.setStyleName(self.contentElem, "gwt-TreeItem-selected", selected)
238
239 - def setState(self, open, fireEvents=True):
240 241 # lkcl: experiment with allowing event state changed to be 242 # fired even on items with no children. otherwise you never 243 # get to find out if an end-item was selected! 244 if not open or len(self.children) != 0: 245 self.open = open 246 self.updateState() 247 248 if fireEvents: 249 self.tree.fireStateChanged(self)
250
251 - def setUserObject(self, userObj):
252 self.userObject = userObj
253
254 - def setWidget(self, widget):
255 self.ensureContentPanel() 256 self.contentPanel.setWidget(widget)
257
258 - def clearContentPanel(self):
259 if self.contentPanel is not None: 260 child = self.contentPanel.getWidget() 261 if child is not None: 262 self.contentPanel.remove(child) 263 264 if self.tree is not None: 265 self.tree.disown(self.contentPanel) 266 self.contentPanel = None
267
268 - def ensureContentPanel(self):
269 if self.contentPanel is None: 270 DOM.setInnerHTML(self.contentElem, "") 271 self.contentPanel = TreeContentPanel(self.contentElem) 272 self.contentPanel.setTreeItem(self) 273 if self.getTree() is not None: 274 self.tree.adopt(self.contentPanel)
275
276 - def addTreeItems(self, accum):
277 for item in self.children: 278 accum.append(item) 279 item.addTreeItems(accum)
280
281 - def getChildren(self):
282 return self.children
283
284 - def getContentElem(self):
285 return self.contentElem
286
287 - def getContentHeight(self):
288 return DOM.getIntAttribute(self.itemTable, "offsetHeight")
289
290 - def getImageElement(self):
291 return self.imgElem
292
293 - def getTreeTop(self):
294 item = self 295 ret = 0 296 297 while item is not None: 298 ret += DOM.getIntAttribute(item.getElement(), "offsetTop") 299 item = item.getParentItem() 300 301 return ret
302
303 - def getFocusableWidget(self):
304 widget = self.getWidget() 305 if hasattr(widget, "setFocus"): 306 return widget 307 return None
308
309 - def imgSrc(self, img):
310 if self.tree is None: 311 return img 312 src = self.tree.getImageBase() + img 313 return src
314
315 - def setParentItem(self, parent):
316 self.parent = parent
317
318 - def setTree(self, tree):
319 if self.tree == tree: 320 return 321 322 if self.tree is not None: 323 if self.tree.getSelectedItem() == self: 324 self.tree.setSelectedItem(None) 325 326 if self.contentPanel is not None: 327 self.tree.disown(self.contentPanel) 328 329 self.tree = tree 330 for child in self.children: 331 child.setTree(tree) 332 self.updateState() 333 if tree is not None and self.contentPanel is not None: 334 tree.adopt(self.contentPanel)
335
336 - def updateState(self):
337 if len(self.children) == 0: 338 self.setVisible(self.childSpanElem, False) 339 #DOM.setAttribute(self.imgElem, "src", self.imgSrc("tree_white.gif")) 340 self.drawImage("white") 341 return 342 343 if self.open: 344 self.setVisible(self.childSpanElem, True) 345 self.drawImage("open") 346 else: 347 self.setVisible(self.childSpanElem, False) 348 self.drawImage("closed")
349
350 - def updateStateRecursive(self):
351 self.updateState() 352 for i in range(len(self.children)): 353 child = self.children[i] 354 child.updateStateRecursive()
355
356 - def drawImage(self, mode):
357 if mode == "white": 358 src = tree_white 359 elif mode == "open": 360 src = tree_open 361 elif mode == "closed": 362 src = tree_closed 363 364 DOM.setAttribute(self.imgElem, "src", src)
365 366
367 -class RootTreeItem(TreeItem):
368 - def addItem(self, item):
369 self.insertItem(item)
370
371 - def insertItem(self, item, index=None):
372 if (item.getParentItem() is not None) or (item.getTree() is not None): 373 item.remove() 374 item.setTree(self.getTree()) 375 376 item.setParentItem(None) 377 if index is None: 378 self.children.append(item) 379 else: 380 self.children.insert(index, item) 381 382 DOM.setIntStyleAttribute(item.getElement(), "marginLeft", 0)
383
384 - def removeItem(self, item):
385 if item not in self.children: 386 return 387 388 item.setTree(None) 389 item.setParentItem(None) 390 self.children.remove(item)
391 392 Factory.registerClass('pyjamas.ui.TreeItem', 'TreeItem', TreeItem) 393