wxWidgets/wxPython/demo/TreeMixin.py
Robin Dunn 7d36c6a8eb Patch from FN that fixes bug in RefreshItem on an item that has no
corresponding node in the tree yet (because its parent isn't expanded
yet) triggered an exception.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45503 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2007-04-16 18:59:00 +00:00

262 lines
9.6 KiB
Python

import wx, wx.lib.customtreectrl, wx.gizmos
import treemixin
class TreeModel(object):
''' TreeModel holds the domain objects that are shown in the different
tree controls. Each domain object is simply a two-tuple consisting of
a label and a list of child tuples, i.e. (label, [list of child tuples]).
'''
def __init__(self, *args, **kwargs):
self.items = []
self.itemCounter = 0
super(TreeModel, self).__init__(*args, **kwargs)
def GetItem(self, indices):
text, children = 'Hidden root', self.items
for index in indices:
text, children = children[index]
return text, children
def GetText(self, indices):
return self.GetItem(indices)[0]
def GetChildren(self, indices):
return self.GetItem(indices)[1]
def GetChildrenCount(self, indices):
return len(self.GetChildren(indices))
def SetChildrenCount(self, indices, count):
children = self.GetChildren(indices)
while len(children) > count:
children.pop()
while len(children) < count:
children.append(('item %d'%self.itemCounter, []))
self.itemCounter += 1
def MoveItem(self, itemToMoveIndex, newParentIndex):
itemToMove = self.GetItem(itemToMoveIndex)
newParentChildren = self.GetChildren(newParentIndex)
newParentChildren.append(itemToMove)
oldParentChildren = self.GetChildren(itemToMoveIndex[:-1])
oldParentChildren.remove(itemToMove)
class DemoTreeMixin(treemixin.VirtualTree, treemixin.DragAndDrop,
treemixin.ExpansionState):
def __init__(self, *args, **kwargs):
self.model = kwargs.pop('treemodel')
self.log = kwargs.pop('log')
super(DemoTreeMixin, self).__init__(*args, **kwargs)
self.CreateImageList()
def CreateImageList(self):
size = (16, 16)
self.imageList = wx.ImageList(*size)
for art in wx.ART_FOLDER, wx.ART_FILE_OPEN, wx.ART_NORMAL_FILE:
self.imageList.Add(wx.ArtProvider.GetBitmap(art, wx.ART_OTHER,
size))
self.AssignImageList(self.imageList)
def OnGetItemText(self, indices):
return self.model.GetText(indices)
def OnGetChildrenCount(self, indices):
return self.model.GetChildrenCount(indices)
def OnGetItemFont(self, indices):
# Show how to change the item font. Here we use a small font for
# items that have children and the default font otherwise.
if self.model.GetChildrenCount(indices) > 0:
return wx.SMALL_FONT
else:
return super(DemoTreeMixin, self).OnGetItemFont(indices)
def OnGetItemTextColour(self, indices):
# Show how to change the item text colour. In this case second level
# items are coloured red and third level items are blue. All other
# items have the default text colour.
if len(indices) % 2 == 0:
return wx.RED
elif len(indices) % 3 == 0:
return wx.BLUE
else:
return super(DemoTreeMixin, self).OnGetItemTextColour(indices)
def OnGetItemBackgroundColour(self, indices):
# Show how to change the item background colour. In this case the
# background colour of each third item is green.
if indices[-1] == 2:
return wx.GREEN
else:
return super(DemoTreeMixin,
self).OnGetItemBackgroundColour(indices)
def OnGetItemImage(self, indices, which):
# Return the right icon depending on whether the item has children.
if which in [wx.TreeItemIcon_Normal, wx.TreeItemIcon_Selected]:
if self.model.GetChildrenCount(indices):
return 0
else:
return 2
else:
return 1
def OnDrop(self, dropTarget, dragItem):
dropIndex = self.GetIndexOfItem(dropTarget)
dropText = self.model.GetText(dropIndex)
dragIndex = self.GetIndexOfItem(dragItem)
dragText = self.model.GetText(dragIndex)
self.log.write('drop %s %s on %s %s'%(dragText, dragIndex,
dropText, dropIndex))
self.model.MoveItem(dragIndex, dropIndex)
self.GetParent().RefreshItems()
class VirtualTreeCtrl(DemoTreeMixin, wx.TreeCtrl):
pass
class VirtualTreeListCtrl(DemoTreeMixin, wx.gizmos.TreeListCtrl):
def __init__(self, *args, **kwargs):
kwargs['style'] = wx.TR_DEFAULT_STYLE | wx.TR_FULL_ROW_HIGHLIGHT
super(VirtualTreeListCtrl, self).__init__(*args, **kwargs)
self.AddColumn('Column 0')
self.AddColumn('Column 1')
for art in wx.ART_TIP, wx.ART_WARNING:
self.imageList.Add(wx.ArtProvider.GetBitmap(art, wx.ART_OTHER,
(16, 16)))
def OnGetItemText(self, indices, column=0):
# Return a different label depending on column.
return '%s, column %d'%\
(super(VirtualTreeListCtrl, self).OnGetItemText(indices), column)
def OnGetItemImage(self, indices, which, column=0):
# Also change the image of the other columns when the item has
# children.
if column == 0:
return super(VirtualTreeListCtrl, self).OnGetItemImage(indices,
which)
elif self.OnGetChildrenCount(indices):
return 4
else:
return 3
class VirtualCustomTreeCtrl(DemoTreeMixin,
wx.lib.customtreectrl.CustomTreeCtrl):
def __init__(self, *args, **kwargs):
self.checked = {}
kwargs['style'] = wx.TR_HIDE_ROOT | \
wx.TR_HAS_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT
super(VirtualCustomTreeCtrl, self).__init__(*args, **kwargs)
self.Bind(wx.lib.customtreectrl.EVT_TREE_ITEM_CHECKED,
self.OnItemChecked)
def OnGetItemType(self, indices):
if len(indices) == 1:
return 1
elif len(indices) == 2:
return 2
else:
return 0
def OnGetItemChecked(self, indices):
return self.checked.get(indices, False)
def OnItemChecked(self, event):
item = event.GetItem()
itemIndex = self.GetIndexOfItem(item)
if self.GetItemType(item) == 2:
# It's a radio item; reset other items on the same level
for nr in range(self.GetChildrenCount(self.GetItemParent(item))):
self.checked[itemIndex[:-1]+(nr,)] = False
self.checked[itemIndex] = True
class TreeNotebook(wx.Notebook):
def __init__(self, *args, **kwargs):
treemodel = kwargs.pop('treemodel')
log = kwargs.pop('log')
super(TreeNotebook, self).__init__(*args, **kwargs)
self.trees = []
for class_, title in [(VirtualTreeCtrl, 'TreeCtrl'),
(VirtualTreeListCtrl, 'TreeListCtrl'),
(VirtualCustomTreeCtrl, 'CustomTreeCtrl')]:
tree = class_(self, treemodel=treemodel, log=log)
self.trees.append(tree)
self.AddPage(tree, title)
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
def OnPageChanged(self, event):
oldTree = self.GetPage(event.OldSelection)
newTree = self.GetPage(event.Selection)
newTree.RefreshItems()
newTree.SetExpansionState(oldTree.GetExpansionState())
event.Skip()
def GetIndicesOfSelectedItems(self):
tree = self.trees[self.GetSelection()]
if tree.GetSelections():
return [tree.GetIndexOfItem(item) for item in tree.GetSelections()]
else:
return [()]
def RefreshItems(self):
tree = self.trees[self.GetSelection()]
tree.RefreshItems()
tree.UnselectAll()
class TestPanel(wx.Panel):
def __init__(self, parent, log):
self.log = log
super(TestPanel, self).__init__(parent)
self.treemodel = TreeModel()
self.CreateControls()
self.LayoutControls()
def CreateControls(self):
self.notebook = TreeNotebook(self, treemodel=self.treemodel,
log=self.log)
self.label = wx.StaticText(self, label='Number of children: ')
self.childrenCountCtrl = wx.SpinCtrl(self, value='0', max=10000)
self.button = wx.Button(self, label='Update children')
self.button.Bind(wx.EVT_BUTTON, self.OnEnter)
def LayoutControls(self):
hSizer = wx.BoxSizer(wx.HORIZONTAL)
options = dict(flag=wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=2)
hSizer.Add(self.label, **options)
hSizer.Add(self.childrenCountCtrl, 2, **options)
hSizer.Add(self.button, **options)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.notebook, 1, wx.EXPAND)
sizer.Add(hSizer, 0, wx.EXPAND)
self.SetSizer(sizer)
def OnEnter(self, event):
indicesList = self.notebook.GetIndicesOfSelectedItems()
newChildrenCount = self.childrenCountCtrl.GetValue()
for indices in indicesList:
text = self.treemodel.GetText(indices)
oldChildrenCount = self.treemodel.GetChildrenCount(indices)
self.log.write('%s %s now has %d children (was %d)'%(text, indices,
newChildrenCount, oldChildrenCount))
self.treemodel.SetChildrenCount(indices, newChildrenCount)
self.notebook.RefreshItems()
def runTest(frame, nb, log):
win = TestPanel(nb, log)
return win
if __name__ == '__main__':
import sys, os, run
run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])