# Inspired By And Heavily Based On wxGenericTreeCtrl.
#
# Andrea Gavana, @ 17 May 2006
-# Latest Revision: 01 Apr 2007, 22.30 CET
+# Latest Revision: 16 Apr 2007, 11.00 CET
#
#
# TODO List
* Mac OS (Thanks to John Jackson).
-Latest Revision: Andrea Gavana @ 01 Apr 2007, 22.30 CET
+Latest Revision: Andrea Gavana @ 16 Apr 2007, 11.00 CET
Version 1.0
"""
self._wnd = wnd # are we holding a window?
if wnd:
- if wnd.GetSizer(): # the window is a complex one hold by a sizer
- size = wnd.GetBestSize()
- else: # simple window, without sizers
- size = wnd.GetSize()
-
- # We have to bind the wx.EVT_SET_FOCUS for the associated window
- # No other solution to handle the focus changing from an item in
- # CustomTreeCtrl and the window associated to an item
- # Do better strategies exist?
- self._wnd.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
-
- self._height = size.GetHeight() + 2
- self._width = size.GetWidth()
- self._windowsize = size
-
- # We don't show the window if the item is collapsed
- if self._isCollapsed:
- self._wnd.Show(False)
-
- # The window is enabled only if the item is enabled
- self._wnd.Enable(self._enabled)
- self._windowenabled = self._enabled
+ self.SetWindow(wnd)
def IsOk(self):
self._wnd = wnd
+ if wnd.GetSizer(): # the window is a complex one hold by a sizer
+ size = wnd.GetBestSize()
+ else: # simple window, without sizers
+ size = wnd.GetSize()
+
+ # We have to bind the wx.EVT_SET_FOCUS for the associated window
+ # No other solution to handle the focus changing from an item in
+ # CustomTreeCtrl and the window associated to an item
+ # Do better strategies exist?
+ self._wnd.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+
+ self._height = size.GetHeight() + 2
+ self._width = size.GetWidth()
+ self._windowsize = size
+
+ # We don't show the window if the item is collapsed
+ if self._isCollapsed:
+ self._wnd.Show(False)
+
+ # The window is enabled only if the item is enabled
+ self._wnd.Enable(self._enabled)
+ self._windowenabled = self._enabled
+
def GetWindow(self):
"""Returns the window associated to the item."""
return self._wnd
+ def DeleteWindow(self):
+ """Deletes the window associated to the item (if any)."""
+
+ if self._wnd:
+ self._wnd.Destroy()
+ self._wnd = None
+
+
def GetWindowEnabled(self):
"""Returns whether the associated window is enabled or not."""
TR_NO_LINES # don't draw lines at all
TR_LINES_AT_ROOT # connect top-level nodes
TR_TWIST_BUTTONS # draw mac-like twist buttons
- TR_SINGLE # single selection mode
+ TR_SINGLE # single selection mode
TR_MULTIPLE # can select multiple items
TR_EXTENDED # todo: allow extended selection
TR_HAS_VARIABLE_ROW_HEIGHT # allows rows to have variable height
self._vistaselection = False
# Connection lines style
+ grey = (160,160,160)
if wx.Platform != "__WXMAC__":
- self._dottedPen = wx.Pen("grey", 1, wx.USER_DASH)
+ self._dottedPen = wx.Pen(grey, 1, wx.USER_DASH)
self._dottedPen.SetDashes([1,1])
self._dottedPen.SetCap(wx.CAP_BUTT)
else:
- self._dottedPen = wx.Pen("grey", 1)
+ self._dottedPen = wx.Pen(grey, 1)
# Pen Used To Draw The Border Around Selected Items
self._borderPen = wx.BLACK_PEN
if major < 10:
style |= TR_ROW_LINES
- self._windowStyle = style
-
# Create the default check image list
self.SetImageListCheck(13, 13)
self.RefreshLine(item)
- def IsEnabled(self, item):
+ def IsItemEnabled(self, item):
"""Returns whether an item is enabled or disabled."""
if not item:
dc = wx.ClientDC(self)
self.RefreshLine(item)
- if self._windowStyle & TR_AUTO_CHECK_CHILD:
+ if self.HasFlag(TR_AUTO_CHECK_CHILD):
ischeck = self.IsItemChecked(item)
self.AutoCheckChild(item, ischeck)
- if self._windowStyle & TR_AUTO_CHECK_PARENT:
+ if self.HasFlag(TR_AUTO_CHECK_PARENT):
ischeck = self.IsItemChecked(item)
self.AutoCheckParent(item, ischeck)
- elif self._windowStyle & TR_AUTO_TOGGLE_CHILD:
+ elif self.HasFlag(TR_AUTO_TOGGLE_CHILD):
self.AutoToggleChild(item)
e = TreeEvent(wxEVT_TREE_ITEM_CHECKED, self.GetId())
self._dirty = True
- def HasFlag(self, flag):
- """Returns whether CustomTreeCtrl has a flag."""
-
- return self._windowStyle & flag
-
-
def HasChildren(self, item):
"""Returns whether an item has children or not."""
# want to update the inherited styles, but right now
# none of the parents has updatable styles
- if self._windowStyle & TR_MULTIPLE and not (styles & TR_MULTIPLE):
+ if self.HasFlag(TR_MULTIPLE) and not (styles & TR_MULTIPLE):
selections = self.GetSelections()
for select in selections[0:-1]:
self.SelectItem(select, False)
- self._windowStyle = styles
+ self.SetWindowStyle(styles)
self._dirty = True
def GetTreeStyle(self):
"""Returns the CustomTreeCtrl style."""
- return self._windowStyle
+ return self.GetWindowStyle()
def HasButtons(self):
def DoInsertItem(self, parentId, previous, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
"""Actually inserts an item in the tree."""
- if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if wnd is not None and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
- if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if text.find("\n") >= 0 and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
if ct_type < 0 or ct_type > 2:
if self._anchor:
raise Exception("\nERROR: Tree Can Have Only One Root")
- if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if wnd is not None and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
- if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if text.find("\n") >= 0 and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
if ct_type < 0 or ct_type > 2:
def PrependItem(self, parent, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
"""Appends an item as a first child of parent."""
- if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if wnd is not None and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
- if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if text.find("\n") >= 0 and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
return self.DoInsertItem(parent, 0, text, ct_type, wnd, image, selImage, data)
def InsertItemByItem(self, parentId, idPrevious, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
"""Auxiliary function to cope with the C++ hideous multifunction."""
- if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if wnd is not None and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
- if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if text.find("\n") >= 0 and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
parent = parentId
def InsertItemByIndex(self, parentId, before, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
"""Auxiliary function to cope with the C++ hideous multifunction."""
- if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if wnd is not None and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
- if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if text.find("\n") >= 0 and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
parent = parentId
def InsertItem(self, parentId, input, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
"""Inserts an item after the given previous."""
- if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if wnd is not None and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
- if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if text.find("\n") >= 0 and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
if type(input) == type(1):
def AppendItem(self, parentId, text, ct_type=0, wnd=None, image=-1, selImage=-1, data=None):
"""Appends an item as a last child of its parent."""
- if wnd is not None and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if wnd is not None and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert Controls You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
- if text.find("\n") >= 0 and not (self._windowStyle & TR_HAS_VARIABLE_ROW_HEIGHT):
+ if text.find("\n") >= 0 and not self.HasFlag(TR_HAS_VARIABLE_ROW_HEIGHT):
raise Exception("\nERROR: In Order To Append/Insert A MultiLine Text You Have To Use The Style TR_HAS_VARIABLE_ROW_HEIGHT")
parent = parentId
for child in self._itemWithWindow:
if not self.IsVisible(child):
wnd = child.GetWindow()
- wnd.Hide()
+ if wnd:
+ wnd.Hide()
def Unselect(self):
r2, g2, b2 = int(bottom.Red()), int(bottom.Green()), int(bottom.Blue())
flrect = float(filRect.height)
+ if flrect < 1:
+ flrect = self._lineHeight
rstep = float((r2 - r1)) / flrect
gstep = float((g2 - g1)) / flrect
dc.SetTextForeground(self.GetHyperTextVisitedColour())
else:
dc.SetTextForeground(self.GetHyperTextNewColour())
-
+
text_w, text_h, dummy = dc.GetMultiLineTextExtent(item.GetText())
image = item.GetCurrentImage()
wx.RendererNative.Get().DrawItemSelectionRect(self, dc, itemrect, flags)
else:
dc.DrawRectangleRect(itemrect)
-
+
else:
if item.IsSelected():
wndx = wcheck + image_w + item.GetX() + text_w + 4
xa, ya = self.CalcScrolledPosition((0, item.GetY()))
wndx += xa
+ if item.GetHeight() > item.GetWindowSize()[1]:
+ ya += (item.GetHeight() - item.GetWindowSize()[1])/2
+
if not wnd.IsShown():
wnd.Show()
if wnd.GetPosition() != (wndx, ya):
else: # no custom buttons
- if self._windowStyle & TR_TWIST_BUTTONS:
+ if self.HasFlag(TR_TWIST_BUTTONS):
# We draw something like the Mac twist buttons
dc.SetPen(wx.BLACK_PEN)
keyCode = event.GetKeyCode()
if keyCode in [ord("+"), wx.WXK_ADD]: # "+"
- if self._current.HasPlus() and not self.IsExpanded(self._current) and self.IsEnabled(self._current):
+ if self._current.HasPlus() and not self.IsExpanded(self._current) and self.IsItemEnabled(self._current):
self.Expand(self._current)
elif keyCode in [ord("*"), wx.WXK_MULTIPLY]: # "*"
- if not self.IsExpanded(self._current) and self.IsEnabled(self._current):
+ if not self.IsExpanded(self._current) and self.IsItemEnabled(self._current):
# expand all
self.ExpandAll(self._current)
elif keyCode in [wx.WXK_RETURN, wx.WXK_SPACE]:
- if not self.IsEnabled(self._current):
+ if not self.IsItemEnabled(self._current):
event.Skip()
return
if prev:
current = self._key_current
# TODO: Huh? If we get here, we'd better be the first child of our parent. How else could it be?
- if current == self.GetFirstChild(prev)[0] and self.IsEnabled(prev):
+ if current == self.GetFirstChild(prev)[0] and self.IsItemEnabled(prev):
# otherwise we return to where we came from
self.DoSelectItem(prev, unselect_others, extended_select)
self._key_current = prev
current = prev
# Try to get the previous siblings and see if they are active
- while prev and not self.IsEnabled(prev):
+ while prev and not self.IsItemEnabled(prev):
prev = self.GetPrevSibling(prev)
if not prev:
# No previous siblings active: go to the parent and up
prev = self.GetItemParent(current)
- while prev and not self.IsEnabled(prev):
+ while prev and not self.IsItemEnabled(prev):
prev = self.GetItemParent(prev)
if prev:
if self.IsExpanded(self._current):
self.Collapse(self._current)
else:
- if prev and self.IsEnabled(prev):
+ if prev and self.IsItemEnabled(prev):
self.DoSelectItem(prev, unselect_others, extended_select)
elif keyCode == wx.WXK_RIGHT:
# also expand the item if it wasn't expanded yet
if self.IsExpanded(self._current) and self.HasChildren(self._current):
child, cookie = self.GetFirstChild(self._key_current)
- if self.IsEnabled(child):
+ if self.IsItemEnabled(child):
self.DoSelectItem(child, unselect_others, extended_select)
self._key_current = child
else:
current = self.GetItemParent(current)
if current:
next = self.GetNextSibling(current)
- if not next or not self.IsEnabled(next):
+ if not next or not self.IsItemEnabled(next):
next = None
else:
- while next and not self.IsEnabled(next):
+ while next and not self.IsItemEnabled(next):
next = self.GetNext(next)
if next:
last = lastChild
- if last and self.IsEnabled(last):
+ if last and self.IsItemEnabled(last):
self.DoSelectItem(last, unselect_others, extended_select)
if not prev:
return
- if self.IsEnabled(prev):
+ if self.IsItemEnabled(prev):
self.DoSelectItem(prev, unselect_others, extended_select)
else:
# no such item
return
- if self.IsEnabled(id):
+ if self.IsItemEnabled(id):
self.SelectItem(id)
self._findPrefix += ch
while 1:
child = sibling(item)
- if (child and self.IsEnabled(child)) or not child:
+ if (child and self.IsItemEnabled(child)) or not child:
break
item = child
# Tha's not a radiobutton... but some of its children can be
# inactive
child, cookie = self.GetFirstChild(item)
- while child and not self.IsEnabled(child):
+ while child and not self.IsItemEnabled(child):
child, cookie = self.GetNextChild(item, cookie)
- if child and self.IsEnabled(child):
+ if child and self.IsItemEnabled(child):
return child
return None
flags = TREE_HITTEST_NOWHERE
return None, flags
- if not self.IsEnabled(hit):
+ if not self.IsItemEnabled(hit):
return None, flags
return hit, flags
item.SetHeight(total_h)
else:
item.SetWidth(item.GetWindowSize()[0]+image_w+text_w+wcheck+2)
+ item.SetHeight(max(total_h, item.GetWindowSize()[1]))
def CalculateLevel(self, item, dc, level, y):