Update to 0.8 from Frank
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@44936 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import wx, wx.lib.customtreectrl, wx.gizmos
|
import wx, wx.lib.customtreectrl, wx.gizmos
|
||||||
import wx.lib.mixins.treemixin as treemixin
|
import treemixin
|
||||||
|
|
||||||
|
|
||||||
class TreeModel(object):
|
class TreeModel(object):
|
||||||
@@ -35,11 +35,11 @@ class TreeModel(object):
|
|||||||
children.append(('item %d'%self.itemCounter, []))
|
children.append(('item %d'%self.itemCounter, []))
|
||||||
self.itemCounter += 1
|
self.itemCounter += 1
|
||||||
|
|
||||||
def MoveItem(self, itemToMoveIndices, newParentIndices):
|
def MoveItem(self, itemToMoveIndex, newParentIndex):
|
||||||
itemToMove = self.GetItem(itemToMoveIndices)
|
itemToMove = self.GetItem(itemToMoveIndex)
|
||||||
newParentChildren = self.GetChildren(newParentIndices)
|
newParentChildren = self.GetChildren(newParentIndex)
|
||||||
newParentChildren.append(itemToMove)
|
newParentChildren.append(itemToMove)
|
||||||
oldParentChildren = self.GetChildren(itemToMoveIndices[:-1])
|
oldParentChildren = self.GetChildren(itemToMoveIndex[:-1])
|
||||||
oldParentChildren.remove(itemToMove)
|
oldParentChildren.remove(itemToMove)
|
||||||
|
|
||||||
|
|
||||||
@@ -104,13 +104,13 @@ class DemoTreeMixin(treemixin.VirtualTree, treemixin.DragAndDrop,
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
def OnDrop(self, dropTarget, dragItem):
|
def OnDrop(self, dropTarget, dragItem):
|
||||||
dropIndices = self.ItemIndices(dropTarget)
|
dropIndex = self.ItemIndex(dropTarget)
|
||||||
dropText = self.model.GetText(dropIndices)
|
dropText = self.model.GetText(dropIndex)
|
||||||
dragIndices = self.ItemIndices(dragItem)
|
dragIndex = self.ItemIndex(dragItem)
|
||||||
dragText = self.model.GetText(dragIndices)
|
dragText = self.model.GetText(dragIndex)
|
||||||
self.log.write('drop %s %s on %s %s'%(dragText, dragIndices,
|
self.log.write('drop %s %s on %s %s'%(dragText, dragIndex,
|
||||||
dropText, dropIndices))
|
dropText, dropIndex))
|
||||||
self.model.MoveItem(dragIndices, dropIndices)
|
self.model.MoveItem(dragIndex, dropIndex)
|
||||||
self.GetParent().RefreshItems()
|
self.GetParent().RefreshItems()
|
||||||
|
|
||||||
|
|
||||||
@@ -164,16 +164,16 @@ class VirtualCustomTreeCtrl(DemoTreeMixin,
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def OnGetItemChecked(self, indices):
|
def OnGetItemChecked(self, indices):
|
||||||
return self.checked.get(tuple(indices), False)
|
return self.checked.get(indices, False)
|
||||||
|
|
||||||
def OnItemChecked(self, event):
|
def OnItemChecked(self, event):
|
||||||
item = event.GetItem()
|
item = event.GetItem()
|
||||||
indices = tuple(self.ItemIndices(item))
|
itemIndex = self.ItemIndex(item)
|
||||||
if self.GetItemType(item) == 2:
|
if self.GetItemType(item) == 2:
|
||||||
# It's a radio item; reset other items on the same level
|
# It's a radio item; reset other items on the same level
|
||||||
for index in range(self.GetChildrenCount(self.GetItemParent(item))):
|
for nr in range(self.GetChildrenCount(self.GetItemParent(item))):
|
||||||
self.checked[indices[:-1]+(index,)] = False
|
self.checked[itemIndex[:-1]+(nr,)] = False
|
||||||
self.checked[indices] = True
|
self.checked[itemIndex] = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -194,14 +194,14 @@ class TreeNotebook(wx.Notebook):
|
|||||||
def OnPageChanged(self, event):
|
def OnPageChanged(self, event):
|
||||||
oldTree = self.GetPage(event.OldSelection)
|
oldTree = self.GetPage(event.OldSelection)
|
||||||
newTree = self.GetPage(event.Selection)
|
newTree = self.GetPage(event.Selection)
|
||||||
newTree.SetExpansionState(oldTree.GetExpansionState())
|
|
||||||
newTree.RefreshItems()
|
newTree.RefreshItems()
|
||||||
|
newTree.SetExpansionState(oldTree.GetExpansionState())
|
||||||
event.Skip()
|
event.Skip()
|
||||||
|
|
||||||
def GetIndicesOfSelectedItems(self):
|
def GetIndicesOfSelectedItems(self):
|
||||||
tree = self.trees[self.GetSelection()]
|
tree = self.trees[self.GetSelection()]
|
||||||
if tree.GetSelections():
|
if tree.GetSelections():
|
||||||
return [tree.ItemIndices(item) for item in tree.GetSelections()]
|
return [tree.ItemIndex(item) for item in tree.GetSelections()]
|
||||||
else:
|
else:
|
||||||
return [()]
|
return [()]
|
||||||
|
|
||||||
|
@@ -1,81 +1,266 @@
|
|||||||
import wx, wx.gizmos, wx.lib.customtreectrl, unittest
|
import wx, wx.gizmos, wx.lib.customtreectrl, unittest, treemixin
|
||||||
from wx.lib.mixins import treemixin
|
|
||||||
|
|
||||||
|
|
||||||
# VirtualTree tests
|
# VirtualTree tests
|
||||||
|
|
||||||
class VirtualTreeCtrl(treemixin.VirtualTree, wx.TreeCtrl):
|
class TreeCtrl(object):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.children = {}
|
self.children = {}
|
||||||
super(VirtualTreeCtrl, self).__init__(*args, **kwargs)
|
self.font = {}
|
||||||
|
self.colour = {}
|
||||||
|
self.bgcolour = {}
|
||||||
|
self.image = {}
|
||||||
|
self.type = {}
|
||||||
|
self.checked = {}
|
||||||
|
super(TreeCtrl, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def OnGetItemFont(self, index):
|
||||||
|
return self.font.get(index, wx.NullFont)
|
||||||
|
|
||||||
|
def PrepareItemFont(self, index, font):
|
||||||
|
self.font[index] = font
|
||||||
|
|
||||||
|
def OnGetItemTextColour(self, index):
|
||||||
|
return self.colour.get(index, wx.NullColour)
|
||||||
|
|
||||||
|
def PrepareItemColour(self, index, colour):
|
||||||
|
self.colour[index] = colour
|
||||||
|
|
||||||
|
def OnGetItemBackgroundColour(self, index):
|
||||||
|
return self.bgcolour.get(index, wx.NullColour)
|
||||||
|
|
||||||
|
def PrepareItemBackgroundColour(self, index, colour):
|
||||||
|
self.bgcolour[index] = colour
|
||||||
|
|
||||||
|
def OnGetItemImage(self, index, which):
|
||||||
|
return self.image.get(index, -1)
|
||||||
|
|
||||||
|
def PrepareImage(self, index, imageIndex):
|
||||||
|
self.image[index] = imageIndex
|
||||||
|
|
||||||
|
def OnGetItemType(self, index):
|
||||||
|
return self.type.get(index, 0)
|
||||||
|
|
||||||
|
def PrepareType(self, index, itemType):
|
||||||
|
self.type[index] = itemType
|
||||||
|
|
||||||
|
def OnGetItemChecked(self, index):
|
||||||
|
return self.checked.get(index, False)
|
||||||
|
|
||||||
|
def PrepareChecked(self, index, checked):
|
||||||
|
self.checked[index] = checked
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualTreeCtrlWithTreeIndices(TreeCtrl, treemixin.VirtualTree,
|
||||||
|
wx.lib.customtreectrl.CustomTreeCtrl):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['tupleIndex'] = True
|
||||||
|
super(VirtualTreeCtrlWithTreeIndices, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def OnGetItemText(self, indices):
|
def OnGetItemText(self, indices):
|
||||||
return 'item %s'%'.'.join([str(index) for index in indices])
|
return 'item %s'%'.'.join([str(index) for index in indices])
|
||||||
|
|
||||||
def OnGetChildrenCount(self, indices=None):
|
def OnGetChildrenCount(self, index=None):
|
||||||
indices = indices or ()
|
index = index or ()
|
||||||
return self.children.get(indices, 0)
|
return self.children.get(index, 0)
|
||||||
|
|
||||||
def SetChildrenCount(self, indices, childrenCount):
|
def PrepareChildrenCount(self, index, childrenCount):
|
||||||
self.children[tuple(indices)] = childrenCount
|
self.children[index] = childrenCount
|
||||||
|
|
||||||
|
|
||||||
class VirtualTreeCtrlTest_NoRootItems(unittest.TestCase):
|
class VirtualTreeCtrlWithListIndices(TreeCtrl, treemixin.VirtualTree,
|
||||||
|
wx.lib.customtreectrl.CustomTreeCtrl):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['tupleIndex'] = False
|
||||||
|
super(VirtualTreeCtrlWithListIndices, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def OnGetItemText(self, index):
|
||||||
|
return 'item %d'%index
|
||||||
|
|
||||||
|
def OnGetChildrenIndices(self, index=None):
|
||||||
|
return self.children.get(index, [])
|
||||||
|
|
||||||
|
def PrepareChildrenIndices(self, index, indices):
|
||||||
|
self.children[index] = indices
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualTreeCtrlTestWithTreeIndices_NoRootItems(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.frame = wx.Frame(None)
|
self.frame = wx.Frame(None)
|
||||||
self.tree = VirtualTreeCtrl(self.frame)
|
self.tree = VirtualTreeCtrlWithTreeIndices(self.frame)
|
||||||
self.tree.RefreshItems()
|
self.tree.RefreshItems()
|
||||||
|
|
||||||
def testNoRootItems(self):
|
def testNoRootItems(self):
|
||||||
self.assertEqual(0, self.tree.GetCount())
|
self.assertEqual(0, self.tree.GetCount())
|
||||||
|
|
||||||
def testAddTwoRootItems(self):
|
def testAddTwoRootItems(self):
|
||||||
self.tree.SetChildrenCount((), 2)
|
self.tree.PrepareChildrenCount((), 2)
|
||||||
self.tree.RefreshItems()
|
self.tree.RefreshItems()
|
||||||
self.assertEqual(2, self.tree.GetCount())
|
self.assertEqual(2, self.tree.GetCount())
|
||||||
|
|
||||||
def testAddOneRootItemAndOneChild(self):
|
def testAddOneRootItemAndOneChild(self):
|
||||||
self.tree.SetChildrenCount((), 1)
|
self.tree.PrepareChildrenCount((), 1)
|
||||||
self.tree.SetChildrenCount((0,), 1)
|
self.tree.PrepareChildrenCount((0,), 1)
|
||||||
self.tree.RefreshItems()
|
self.tree.RefreshItems()
|
||||||
self.tree.ExpandAll()
|
self.tree.ExpandAll()
|
||||||
self.assertEqual(2, self.tree.GetCount())
|
self.assertEqual(2, self.tree.GetCount())
|
||||||
|
|
||||||
def testAddOneRootItemAndTwoChildren(self):
|
def testAddOneRootItemAndTwoChildren(self):
|
||||||
self.tree.SetChildrenCount((), 1)
|
self.tree.PrepareChildrenCount((), 1)
|
||||||
self.tree.SetChildrenCount((0,), 2)
|
self.tree.PrepareChildrenCount((0,), 2)
|
||||||
self.tree.RefreshItems()
|
self.tree.RefreshItems()
|
||||||
self.tree.ExpandAll()
|
self.tree.ExpandAll()
|
||||||
self.assertEqual(3, self.tree.GetCount())
|
self.assertEqual(3, self.tree.GetCount())
|
||||||
|
|
||||||
|
|
||||||
class VirtualTreeCtrlTest_OneRoot(unittest.TestCase):
|
class VirtualTreeCtrlWithListIndicesTest_NoRootItems(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.frame = wx.Frame(None)
|
self.frame = wx.Frame(None)
|
||||||
self.tree = VirtualTreeCtrl(self.frame)
|
self.tree = VirtualTreeCtrlWithListIndices(self.frame)
|
||||||
self.tree.SetChildrenCount((), 1)
|
self.tree.RefreshItems()
|
||||||
|
|
||||||
|
def testNoRootItems(self):
|
||||||
|
self.assertEqual(0, self.tree.GetCount())
|
||||||
|
|
||||||
|
def testAddTwoRootItems(self):
|
||||||
|
self.tree.PrepareChildrenIndices(None, [0,1])
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
self.assertEqual(2, self.tree.GetCount())
|
||||||
|
|
||||||
|
def testAddOneRootItemAndOneChild(self):
|
||||||
|
self.tree.PrepareChildrenIndices(None, [0])
|
||||||
|
self.tree.PrepareChildrenIndices(0, [1])
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
self.tree.ExpandAll()
|
||||||
|
self.assertEqual(2, self.tree.GetCount())
|
||||||
|
|
||||||
|
def testAddOneRootItemAndTwoChildren(self):
|
||||||
|
self.tree.PrepareChildrenIndices(None, [0])
|
||||||
|
self.tree.PrepareChildrenIndices(0, [1,2])
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
self.tree.ExpandAll()
|
||||||
|
self.assertEqual(3, self.tree.GetCount())
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualTreeCtrlTestWithTreeIndices_OneRoot(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.frame = wx.Frame(None)
|
||||||
|
self.tree = VirtualTreeCtrlWithTreeIndices(self.frame)
|
||||||
|
self.tree.PrepareChildrenCount((), 1)
|
||||||
self.tree.RefreshItems()
|
self.tree.RefreshItems()
|
||||||
|
|
||||||
def testOneRoot(self):
|
def testOneRoot(self):
|
||||||
self.assertEqual(1, self.tree.GetCount())
|
self.assertEqual(1, self.tree.GetCount())
|
||||||
|
|
||||||
def testDeleteRootItem(self):
|
def testDeleteRootItem(self):
|
||||||
self.tree.SetChildrenCount((), 0)
|
self.tree.PrepareChildrenCount((), 0)
|
||||||
self.tree.RefreshItems()
|
self.tree.RefreshItems()
|
||||||
self.assertEqual(0, self.tree.GetCount())
|
self.assertEqual(0, self.tree.GetCount())
|
||||||
|
|
||||||
def testAddOneChild(self):
|
def testAddOneChild(self):
|
||||||
self.tree.SetChildrenCount((0,), 1)
|
self.tree.PrepareChildrenCount((0,), 1)
|
||||||
self.tree.RefreshItems()
|
self.tree.RefreshItems()
|
||||||
self.tree.ExpandAll()
|
self.tree.ExpandAll()
|
||||||
self.assertEqual(2, self.tree.GetCount())
|
self.assertEqual(2, self.tree.GetCount())
|
||||||
|
|
||||||
def testAddTwoChildren(self):
|
def testAddTwoChildren(self):
|
||||||
self.tree.SetChildrenCount((0,), 2)
|
self.tree.PrepareChildrenCount((0,), 2)
|
||||||
self.tree.RefreshItems()
|
self.tree.RefreshItems()
|
||||||
self.tree.ExpandAll()
|
self.tree.ExpandAll()
|
||||||
self.assertEqual(3, self.tree.GetCount())
|
self.assertEqual(3, self.tree.GetCount())
|
||||||
|
|
||||||
|
def testChangeFont(self):
|
||||||
|
self.tree.PrepareItemFont((0,), wx.SMALL_FONT)
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.assertEqual(wx.SMALL_FONT, self.tree.GetItemFont(item))
|
||||||
|
|
||||||
|
def testChangeColour(self):
|
||||||
|
self.tree.PrepareItemColour((0,), wx.RED)
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.assertEqual(wx.RED, self.tree.GetItemTextColour(item))
|
||||||
|
|
||||||
|
def testChangeBackgroundColour(self):
|
||||||
|
self.tree.PrepareItemBackgroundColour((0,), wx.RED)
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.assertEqual(wx.RED, self.tree.GetItemBackgroundColour(item))
|
||||||
|
|
||||||
|
def testChangeImage(self):
|
||||||
|
self.tree.PrepareImage((0,), 0)
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.assertEqual(0, self.tree.GetItemImage(item))
|
||||||
|
|
||||||
|
def testChangeType(self):
|
||||||
|
self.tree.PrepareType((0,), 2)
|
||||||
|
self.tree.PrepareChecked((0,), True)
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.failUnless(self.tree.IsItemChecked(item))
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualTreeCtrlWithListIndicesTest_OneRoot(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.frame = wx.Frame(None)
|
||||||
|
self.tree = VirtualTreeCtrlWithListIndices(self.frame)
|
||||||
|
self.tree.PrepareChildrenIndices(None, [0])
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
|
||||||
|
def testOneRoot(self):
|
||||||
|
self.assertEqual(1, self.tree.GetCount())
|
||||||
|
|
||||||
|
def testDeleteRootItem(self):
|
||||||
|
self.tree.PrepareChildrenIndices(None, [])
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
self.assertEqual(0, self.tree.GetCount())
|
||||||
|
|
||||||
|
def testAddOneChild(self):
|
||||||
|
self.tree.PrepareChildrenIndices(0, [1])
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
self.tree.ExpandAll()
|
||||||
|
self.assertEqual(2, self.tree.GetCount())
|
||||||
|
|
||||||
|
def testAddTwoChildren(self):
|
||||||
|
self.tree.PrepareChildrenIndices(0, [1,2])
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
self.tree.ExpandAll()
|
||||||
|
self.assertEqual(3, self.tree.GetCount())
|
||||||
|
|
||||||
|
def testChangeFont(self):
|
||||||
|
self.tree.PrepareItemFont(0, wx.SMALL_FONT)
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.assertEqual(wx.SMALL_FONT, self.tree.GetItemFont(item))
|
||||||
|
|
||||||
|
def testChangeColour(self):
|
||||||
|
self.tree.PrepareItemColour(0, wx.RED)
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.assertEqual(wx.RED, self.tree.GetItemTextColour(item))
|
||||||
|
|
||||||
|
def testChangeBackgroundColour(self):
|
||||||
|
self.tree.PrepareItemBackgroundColour(0, wx.RED)
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.assertEqual(wx.RED, self.tree.GetItemBackgroundColour(item))
|
||||||
|
|
||||||
|
def testChangeImage(self):
|
||||||
|
self.tree.PrepareImage(0, 0)
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.assertEqual(0, self.tree.GetItemImage(item))
|
||||||
|
|
||||||
|
def testChangeType(self):
|
||||||
|
self.tree.PrepareType(0, 2)
|
||||||
|
self.tree.PrepareChecked(0, True)
|
||||||
|
self.tree.RefreshItems()
|
||||||
|
item, cookie = self.tree.GetFirstChild(self.tree.GetRootItem())
|
||||||
|
self.failUnless(self.tree.IsItemChecked(item))
|
||||||
|
|
||||||
|
|
||||||
# TreeAPIHarmonizer tests
|
# TreeAPIHarmonizer tests
|
||||||
|
|
||||||
@@ -91,26 +276,64 @@ class TreeAPIHarmonizerTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
def populateTree(self):
|
def populateTree(self):
|
||||||
self.root = self.tree.AddRoot('Root')
|
self.root = self.tree.AddRoot('Root')
|
||||||
self.item = self.tree.AppendItem(self.root, 'item')
|
self.item = self.tree.AppendItem(self.root, 'Item')
|
||||||
|
self.items = [self.root, self.item]
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerCommonTests(object):
|
class TreeAPIHarmonizerCommonTests(object):
|
||||||
def testSetItemImage(self):
|
''' Tests that should succeed for all tree controls and all styles. '''
|
||||||
self.tree.SetItemImage(self.item, -1, wx.TreeItemIcon_Normal)
|
|
||||||
self.assertEqual(-1,
|
|
||||||
self.tree.GetItemImage(self.item, wx.TreeItemIcon_Normal))
|
|
||||||
|
|
||||||
def testGetColumnCount(self):
|
|
||||||
self.assertEqual(0, self.tree.GetColumnCount())
|
|
||||||
|
|
||||||
def testGetItemType(self):
|
def testGetItemType(self):
|
||||||
self.assertEqual(0, self.tree.GetItemType(self.item))
|
self.assertEqual(0, self.tree.GetItemType(self.item))
|
||||||
|
|
||||||
|
def testGetItemImage_DefaultIcon(self):
|
||||||
|
self.assertEqual(-1, self.tree.GetItemImage(self.item))
|
||||||
|
|
||||||
|
def testGetItemImage_SelectedIcon(self):
|
||||||
|
self.assertEqual(-1,
|
||||||
|
self.tree.GetItemImage(self.item, wx.TreeItemIcon_Selected))
|
||||||
|
|
||||||
|
def testGetItemImage_DefaultIcon_OtherColumn(self):
|
||||||
|
self.assertEqual(-1, self.tree.GetItemImage(self.item, column=1))
|
||||||
|
|
||||||
|
def testGetItemImage_SelectedIcon_OtherColumn(self):
|
||||||
|
self.assertEqual(-1,
|
||||||
|
self.tree.GetItemImage(self.item, wx.TreeItemIcon_Selected, 1))
|
||||||
|
|
||||||
|
def testSetItemImage_DefaultIcon(self):
|
||||||
|
self.tree.SetItemImage(self.item, -1)
|
||||||
|
self.assertEqual(-1, self.tree.GetItemImage(self.item))
|
||||||
|
|
||||||
|
def testSetItemImage_SelectedIcon(self):
|
||||||
|
self.tree.SetItemImage(self.item, -1, wx.TreeItemIcon_Selected)
|
||||||
|
self.assertEqual(-1,
|
||||||
|
self.tree.GetItemImage(self.item, wx.TreeItemIcon_Selected))
|
||||||
|
|
||||||
|
def testSetItemImage_DefaultIcon_OtherColumn(self):
|
||||||
|
self.tree.SetItemImage(self.item, -1, column=1)
|
||||||
|
self.assertEqual(-1, self.tree.GetItemImage(self.item, column=1))
|
||||||
|
|
||||||
|
def testSetItemImage_SelectedIcon_OtherColumn(self):
|
||||||
|
self.tree.SetItemImage(self.item, -1, wx.TreeItemIcon_Selected, 1)
|
||||||
|
self.assertEqual(-1,
|
||||||
|
self.tree.GetItemImage(self.item, wx.TreeItemIcon_Selected, 1))
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerNoTreeListCtrlCommonTests(object):
|
||||||
|
''' Tests that should succeed for all tree controls, except the
|
||||||
|
TreeListCtrl, and all styles. '''
|
||||||
|
|
||||||
def testGetMainWindow(self):
|
def testGetMainWindow(self):
|
||||||
self.assertEqual(self.tree, self.tree.GetMainWindow())
|
self.assertEqual(self.tree, self.tree.GetMainWindow())
|
||||||
|
|
||||||
|
def testGetColumnCount(self):
|
||||||
|
self.assertEqual(0, self.tree.GetColumnCount())
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerSingleSelectionTests(object):
|
class TreeAPIHarmonizerSingleSelectionTests(object):
|
||||||
|
''' Tests that should succeed for all tree controls when in single
|
||||||
|
selection mode (which is the default selection mode). '''
|
||||||
|
|
||||||
def testUnselectAll(self):
|
def testUnselectAll(self):
|
||||||
self.tree.SelectItem(self.item)
|
self.tree.SelectItem(self.item)
|
||||||
self.tree.UnselectAll()
|
self.tree.UnselectAll()
|
||||||
@@ -127,6 +350,9 @@ class TreeAPIHarmonizerSingleSelectionTests(object):
|
|||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerMultipleSelectionTests(object):
|
class TreeAPIHarmonizerMultipleSelectionTests(object):
|
||||||
|
''' Tests that should succeed for all tree controls when in multiple
|
||||||
|
selection mode. '''
|
||||||
|
|
||||||
style = wx.TR_DEFAULT_STYLE | wx.TR_MULTIPLE
|
style = wx.TR_DEFAULT_STYLE | wx.TR_MULTIPLE
|
||||||
|
|
||||||
def testUnselectAll(self):
|
def testUnselectAll(self):
|
||||||
@@ -152,18 +378,68 @@ class TreeAPIHarmonizerMultipleSelectionTests(object):
|
|||||||
self.assertEqual([self.item, item2], self.tree.GetSelections())
|
self.assertEqual([self.item, item2], self.tree.GetSelections())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerVisibleRootTests(object):
|
||||||
|
''' Tests that should succeed for all tree controls when the root item
|
||||||
|
is not hidden. '''
|
||||||
|
|
||||||
|
def testGetCount(self):
|
||||||
|
self.assertEqual(len(self.items), self.tree.GetCount())
|
||||||
|
|
||||||
|
def testSelectRoot(self):
|
||||||
|
self.tree.SelectItem(self.root)
|
||||||
|
self.assertEqual([self.root], self.tree.GetSelections())
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerHiddenRootTests(object):
|
||||||
|
''' Tests that should succeed for all tree controls when the root item
|
||||||
|
is hidden. '''
|
||||||
|
|
||||||
|
style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT
|
||||||
|
|
||||||
|
def testGetCount(self):
|
||||||
|
self.assertEqual(len(self.items) - 1, self.tree.GetCount())
|
||||||
|
|
||||||
|
def testSelectRoot(self):
|
||||||
|
self.tree.SelectItem(self.root)
|
||||||
|
self.assertEqual([], self.tree.GetSelections())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerWithTreeCtrlTestCase(TreeAPIHarmonizerTestCase):
|
class TreeAPIHarmonizerWithTreeCtrlTestCase(TreeAPIHarmonizerTestCase):
|
||||||
TreeClass = wx.TreeCtrl
|
TreeClass = wx.TreeCtrl
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerWithTreeCtrlCommonTests( \
|
||||||
|
TreeAPIHarmonizerCommonTests,
|
||||||
|
TreeAPIHarmonizerNoTreeListCtrlCommonTests):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerWithTreeCtrl_SingleSelection( \
|
class TreeAPIHarmonizerWithTreeCtrl_SingleSelection( \
|
||||||
TreeAPIHarmonizerCommonTests, TreeAPIHarmonizerSingleSelectionTests,
|
TreeAPIHarmonizerWithTreeCtrlCommonTests,
|
||||||
|
TreeAPIHarmonizerSingleSelectionTests,
|
||||||
TreeAPIHarmonizerWithTreeCtrlTestCase):
|
TreeAPIHarmonizerWithTreeCtrlTestCase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerWithTreeCtrl_MultipleSelection( \
|
class TreeAPIHarmonizerWithTreeCtrl_MultipleSelection( \
|
||||||
TreeAPIHarmonizerCommonTests, TreeAPIHarmonizerMultipleSelectionTests,
|
TreeAPIHarmonizerWithTreeCtrlCommonTests,
|
||||||
|
TreeAPIHarmonizerMultipleSelectionTests,
|
||||||
|
TreeAPIHarmonizerWithTreeCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerWithTreeCtrl_VisibleRoot( \
|
||||||
|
TreeAPIHarmonizerWithTreeCtrlCommonTests,
|
||||||
|
TreeAPIHarmonizerVisibleRootTests,
|
||||||
|
TreeAPIHarmonizerWithTreeCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerWithTreeCtrl_HiddenRoot( \
|
||||||
|
TreeAPIHarmonizerWithTreeCtrlCommonTests,
|
||||||
|
TreeAPIHarmonizerHiddenRootTests,
|
||||||
TreeAPIHarmonizerWithTreeCtrlTestCase):
|
TreeAPIHarmonizerWithTreeCtrlTestCase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -176,9 +452,8 @@ class TreeAPIHarmonizerWithTreeListCtrlTestCase(TreeAPIHarmonizerTestCase):
|
|||||||
super(TreeAPIHarmonizerWithTreeListCtrlTestCase, self).populateTree()
|
super(TreeAPIHarmonizerWithTreeListCtrlTestCase, self).populateTree()
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerWithTreeListCtrl_SingleSelection( \
|
class TreeAPIHarmonizerWithTreeListCtrlCommonTests( \
|
||||||
TreeAPIHarmonizerCommonTests, TreeAPIHarmonizerSingleSelectionTests,
|
TreeAPIHarmonizerCommonTests):
|
||||||
TreeAPIHarmonizerWithTreeListCtrlTestCase):
|
|
||||||
|
|
||||||
def testGetColumnCount(self):
|
def testGetColumnCount(self):
|
||||||
self.assertEqual(1, self.tree.GetColumnCount())
|
self.assertEqual(1, self.tree.GetColumnCount())
|
||||||
@@ -187,16 +462,18 @@ class TreeAPIHarmonizerWithTreeListCtrl_SingleSelection( \
|
|||||||
self.assertNotEqual(self.tree, self.tree.GetMainWindow())
|
self.assertNotEqual(self.tree, self.tree.GetMainWindow())
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerWithTreeListCtrl_SingleSelection( \
|
||||||
|
TreeAPIHarmonizerWithTreeListCtrlCommonTests,
|
||||||
|
TreeAPIHarmonizerSingleSelectionTests,
|
||||||
|
TreeAPIHarmonizerWithTreeListCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerWithTreeListCtrl_MultipleSelection( \
|
class TreeAPIHarmonizerWithTreeListCtrl_MultipleSelection( \
|
||||||
TreeAPIHarmonizerCommonTests, TreeAPIHarmonizerMultipleSelectionTests,
|
TreeAPIHarmonizerWithTreeListCtrlCommonTests,
|
||||||
|
TreeAPIHarmonizerMultipleSelectionTests,
|
||||||
TreeAPIHarmonizerWithTreeListCtrlTestCase):
|
TreeAPIHarmonizerWithTreeListCtrlTestCase):
|
||||||
|
|
||||||
def testGetColumnCount(self):
|
|
||||||
self.assertEqual(1, self.tree.GetColumnCount())
|
|
||||||
|
|
||||||
def testGetMainWindow(self):
|
|
||||||
self.assertNotEqual(self.tree, self.tree.GetMainWindow())
|
|
||||||
|
|
||||||
def testGetSelections_TwoSelectedItems(self):
|
def testGetSelections_TwoSelectedItems(self):
|
||||||
''' Override TreeAPIHarmonizerMultipleSelectionTests.-
|
''' Override TreeAPIHarmonizerMultipleSelectionTests.-
|
||||||
testGetSelections_TwoSelectedItems, because
|
testGetSelections_TwoSelectedItems, because
|
||||||
@@ -208,11 +485,28 @@ class TreeAPIHarmonizerWithTreeListCtrl_MultipleSelection( \
|
|||||||
self.assertEqual([self.item, item2], self.tree.GetSelections())
|
self.assertEqual([self.item, item2], self.tree.GetSelections())
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerWithTreeListCtrl_VisibleRoot( \
|
||||||
|
TreeAPIHarmonizerWithTreeListCtrlCommonTests,
|
||||||
|
TreeAPIHarmonizerVisibleRootTests,
|
||||||
|
TreeAPIHarmonizerWithTreeListCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerWithTreeListCtrl_HiddenRoot( \
|
||||||
|
TreeAPIHarmonizerWithTreeListCtrlCommonTests,
|
||||||
|
TreeAPIHarmonizerHiddenRootTests,
|
||||||
|
TreeAPIHarmonizerWithTreeListCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerWithCustomTreeCtrlTestCase(TreeAPIHarmonizerTestCase):
|
class TreeAPIHarmonizerWithCustomTreeCtrlTestCase(TreeAPIHarmonizerTestCase):
|
||||||
TreeClass = wx.lib.customtreectrl.CustomTreeCtrl
|
TreeClass = wx.lib.customtreectrl.CustomTreeCtrl
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerCustomTreeCtrlTests(object):
|
class TreeAPIHarmonizerWithCustomTreeCtrlCommonTests( \
|
||||||
|
TreeAPIHarmonizerCommonTests,
|
||||||
|
TreeAPIHarmonizerNoTreeListCtrlCommonTests):
|
||||||
|
|
||||||
def testGetCheckItemType(self):
|
def testGetCheckItemType(self):
|
||||||
item = self.tree.AppendItem(self.root, 'item', ct_type=1)
|
item = self.tree.AppendItem(self.root, 'item', ct_type=1)
|
||||||
self.assertEqual(1, self.tree.GetItemType(item))
|
self.assertEqual(1, self.tree.GetItemType(item))
|
||||||
@@ -224,17 +518,136 @@ class TreeAPIHarmonizerCustomTreeCtrlTests(object):
|
|||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerWithCustomTreeCtrl_SingleSelection( \
|
class TreeAPIHarmonizerWithCustomTreeCtrl_SingleSelection( \
|
||||||
TreeAPIHarmonizerCommonTests, TreeAPIHarmonizerSingleSelectionTests,
|
TreeAPIHarmonizerWithCustomTreeCtrlCommonTests,
|
||||||
TreeAPIHarmonizerCustomTreeCtrlTests,
|
TreeAPIHarmonizerSingleSelectionTests,
|
||||||
TreeAPIHarmonizerWithCustomTreeCtrlTestCase):
|
TreeAPIHarmonizerWithCustomTreeCtrlTestCase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TreeAPIHarmonizerWithCustomTreeCtrl_MultipleSelection( \
|
class TreeAPIHarmonizerWithCustomTreeCtrl_MultipleSelection( \
|
||||||
TreeAPIHarmonizerCommonTests, TreeAPIHarmonizerMultipleSelectionTests,
|
TreeAPIHarmonizerWithCustomTreeCtrlCommonTests,
|
||||||
TreeAPIHarmonizerCustomTreeCtrlTests,
|
TreeAPIHarmonizerMultipleSelectionTests,
|
||||||
TreeAPIHarmonizerWithCustomTreeCtrlTestCase):
|
TreeAPIHarmonizerWithCustomTreeCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerWithCustomTreeCtrl_VisibleRoot( \
|
||||||
|
TreeAPIHarmonizerWithCustomTreeCtrlCommonTests,
|
||||||
|
TreeAPIHarmonizerVisibleRootTests,
|
||||||
|
TreeAPIHarmonizerWithCustomTreeCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TreeAPIHarmonizerWithCustomTreeCtrl_HiddenRoot( \
|
||||||
|
TreeAPIHarmonizerWithCustomTreeCtrlCommonTests,
|
||||||
|
TreeAPIHarmonizerHiddenRootTests,
|
||||||
|
TreeAPIHarmonizerWithCustomTreeCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# TreeHelper tests
|
||||||
|
|
||||||
|
class TreeHelperTestCase(unittest.TestCase):
|
||||||
|
style = wx.TR_DEFAULT_STYLE
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.frame = wx.Frame(None)
|
||||||
|
class HelperTreeCtrl(treemixin.TreeHelper,
|
||||||
|
treemixin.TreeAPIHarmonizer, self.TreeClass):
|
||||||
|
pass
|
||||||
|
self.tree = HelperTreeCtrl(self.frame, style=self.style)
|
||||||
|
self.populateTree()
|
||||||
|
|
||||||
|
def populateTree(self):
|
||||||
|
self.root = self.tree.AddRoot('Root')
|
||||||
|
self.item = self.tree.AppendItem(self.root, 'Item')
|
||||||
|
self.child = self.tree.AppendItem(self.item, 'Child')
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelperVisibleRootTests(object):
|
||||||
|
def testIntegerIndexRootItem(self):
|
||||||
|
self.assertEqual(0, self.tree.ItemIndex(self.root, tupleIndex=False))
|
||||||
|
|
||||||
|
def testIntegerIndexRegularItem(self):
|
||||||
|
self.assertEqual(1, self.tree.ItemIndex(self.item, tupleIndex=False))
|
||||||
|
|
||||||
|
def testIntegerIndexChild(self):
|
||||||
|
self.assertEqual(2, self.tree.ItemIndex(self.child, tupleIndex=False))
|
||||||
|
|
||||||
|
def testTupleIndexRootItem(self):
|
||||||
|
self.assertEqual((), self.tree.ItemIndex(self.root))
|
||||||
|
|
||||||
|
def testTupleIndexRegularItem(self):
|
||||||
|
self.assertEqual((0,), self.tree.ItemIndex(self.item))
|
||||||
|
|
||||||
|
def testTupleIndexChild(self):
|
||||||
|
self.assertEqual((0,0), self.tree.ItemIndex(self.child))
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelperHiddenRootTests(object):
|
||||||
|
style = wx.TR_HIDE_ROOT
|
||||||
|
|
||||||
|
def testIntegerIndexRootItem(self):
|
||||||
|
self.assertEqual(None, self.tree.ItemIndex(self.root, tupleIndex=False))
|
||||||
|
|
||||||
|
def testIntegerIndexRegularItem(self):
|
||||||
|
self.assertEqual(0, self.tree.ItemIndex(self.item, tupleIndex=False))
|
||||||
|
|
||||||
|
def testIntegerIndexChild(self):
|
||||||
|
self.assertEqual(1, self.tree.ItemIndex(self.child, tupleIndex=False))
|
||||||
|
|
||||||
|
def testTupleIndexRootItem(self):
|
||||||
|
self.assertEqual((), self.tree.ItemIndex(self.root))
|
||||||
|
|
||||||
|
def testTupleIndexRegularItem(self):
|
||||||
|
self.assertEqual((0,), self.tree.ItemIndex(self.item))
|
||||||
|
|
||||||
|
def testTupleIndexChild(self):
|
||||||
|
self.assertEqual((0,0), self.tree.ItemIndex(self.child))
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelperWithTreeCtrlTestCase(TreeHelperTestCase):
|
||||||
|
TreeClass = wx.TreeCtrl
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelperWithTreeCtrl_VisibleRoot(TreeHelperVisibleRootTests,
|
||||||
|
TreeHelperWithTreeCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelperWithTreeCtrl_HiddenRoot(TreeHelperHiddenRootTests,
|
||||||
|
TreeHelperWithTreeCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelperWithTreeListCtrlTestCase(TreeHelperTestCase):
|
||||||
|
TreeClass = wx.gizmos.TreeListCtrl
|
||||||
|
|
||||||
|
def populateTree(self):
|
||||||
|
self.tree.AddColumn('Column')
|
||||||
|
super(TreeHelperWithTreeListCtrlTestCase, self).populateTree()
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelperWithTreeListCtrl_VisibleRoot(TreeHelperVisibleRootTests,
|
||||||
|
TreeHelperWithTreeListCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelperWithTreeListCtrl_HiddenRoot(TreeHelperHiddenRootTests,
|
||||||
|
TreeHelperWithTreeListCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class TreeHelperWithCustomTreeCtrlTestCase(TreeHelperTestCase):
|
||||||
|
TreeClass = wx.lib.customtreectrl.CustomTreeCtrl
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelperWithCustomTreeCtrl_VisibleRoot(TreeHelperVisibleRootTests,
|
||||||
|
TreeHelperWithCustomTreeCtrlTestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelperWithCustomTreeCtrl_HiddenRoot(TreeHelperHiddenRootTests,
|
||||||
|
TreeHelperWithCustomTreeCtrlTestCase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@@ -25,8 +25,8 @@ The VirtualTree and DragAndDrop mixins force the wx.TR_HIDE_ROOT style.
|
|||||||
|
|
||||||
Author: Frank Niessink <frank@niessink.com>
|
Author: Frank Niessink <frank@niessink.com>
|
||||||
License: wxWidgets license
|
License: wxWidgets license
|
||||||
Version: 0.7
|
Version: 0.8
|
||||||
Date: 22 February 2007
|
Date: 13 March 2007
|
||||||
|
|
||||||
ExpansionState is based on code and ideas from Karsten Hilbert.
|
ExpansionState is based on code and ideas from Karsten Hilbert.
|
||||||
Andrea Gavana provided help with the CustomTreeCtrl integration.
|
Andrea Gavana provided help with the CustomTreeCtrl integration.
|
||||||
@@ -67,17 +67,48 @@ class TreeAPIHarmonizer(object):
|
|||||||
# default item type if we are mixed in with another tree control.
|
# default item type if we are mixed in with another tree control.
|
||||||
return self.__callSuper('GetItemType', 0, *args, **kwargs)
|
return self.__callSuper('GetItemType', 0, *args, **kwargs)
|
||||||
|
|
||||||
|
def SetItemType(self, item, newType):
|
||||||
|
# CustomTreeCtrl doesn't support changing the item type on the fly,
|
||||||
|
# so we create a new item and delete the old one. We currently only
|
||||||
|
# keep the item text, would be nicer to also retain other attributes.
|
||||||
|
text = self.GetItemText(item)
|
||||||
|
newItem = self.InsertItem(self.GetItemParent(item), item, text,
|
||||||
|
ct_type=newType)
|
||||||
|
self.Delete(item)
|
||||||
|
return newItem
|
||||||
|
|
||||||
def IsItemChecked(self, *args, **kwargs):
|
def IsItemChecked(self, *args, **kwargs):
|
||||||
# Only CustomTreeCtrl supports checkable items, return False if
|
# Only CustomTreeCtrl supports checkable items, return False if
|
||||||
# we are mixed in with another tree control.
|
# we are mixed in with another tree control.
|
||||||
return self.__callSuper('IsItemChecked', False, *args, **kwargs)
|
return self.__callSuper('IsItemChecked', False, *args, **kwargs)
|
||||||
|
|
||||||
|
def GetItemChecked(self, *args, **kwargs):
|
||||||
|
# For consistency's sake, provide a 'Get' and 'Set' method for
|
||||||
|
# checkable items.
|
||||||
|
return self.IsItemChecked(*args, **kwargs)
|
||||||
|
|
||||||
|
def SetItemChecked(self, *args, **kwargs):
|
||||||
|
# For consistency's sake, provide a 'Get' and 'Set' method for
|
||||||
|
# checkable items.
|
||||||
|
return self.CheckItem(*args, **kwargs)
|
||||||
|
|
||||||
def GetMainWindow(self, *args, **kwargs):
|
def GetMainWindow(self, *args, **kwargs):
|
||||||
# Only TreeListCtrl has a separate main window, return self if we are
|
# Only TreeListCtrl has a separate main window, return self if we are
|
||||||
# mixed in with another tree control.
|
# mixed in with another tree control.
|
||||||
return self.__callSuper('GetMainWindow', self, *args, **kwargs)
|
return self.__callSuper('GetMainWindow', self, *args, **kwargs)
|
||||||
|
|
||||||
def SetItemImage(self, item, imageIndex, which, column=0):
|
def GetItemImage(self, item, which=wx.TreeItemIcon_Normal, column=-1):
|
||||||
|
# CustomTreeCtrl always wants the which argument, so provide it
|
||||||
|
# TreeListCtr.GetItemImage has a different order of arguments than
|
||||||
|
# the other tree controls. Hide the differenes.
|
||||||
|
if self.GetColumnCount():
|
||||||
|
args = (item, column, which)
|
||||||
|
else:
|
||||||
|
args = (item, which)
|
||||||
|
return super(TreeAPIHarmonizer, self).GetItemImage(*args)
|
||||||
|
|
||||||
|
def SetItemImage(self, item, imageIndex, which=wx.TreeItemIcon_Normal,
|
||||||
|
column=-1):
|
||||||
# The SetItemImage signature is different for TreeListCtrl and
|
# The SetItemImage signature is different for TreeListCtrl and
|
||||||
# other tree controls. This adapter method hides the differences.
|
# other tree controls. This adapter method hides the differences.
|
||||||
if self.GetColumnCount():
|
if self.GetColumnCount():
|
||||||
@@ -92,19 +123,46 @@ class TreeAPIHarmonizer(object):
|
|||||||
if self.HasFlag(wx.TR_MULTIPLE):
|
if self.HasFlag(wx.TR_MULTIPLE):
|
||||||
super(TreeAPIHarmonizer, self).UnselectAll()
|
super(TreeAPIHarmonizer, self).UnselectAll()
|
||||||
else:
|
else:
|
||||||
|
# CustomTreeCtrl Unselect() doesn't seem to work in all cases,
|
||||||
|
# also invoke UnselectAll just to be sure.
|
||||||
self.Unselect()
|
self.Unselect()
|
||||||
|
super(TreeAPIHarmonizer, self).UnselectAll()
|
||||||
|
|
||||||
|
def GetCount(self):
|
||||||
|
# TreeListCtrl correctly ignores the root item when it is hidden,
|
||||||
|
# but doesn't count the root item when it is visible
|
||||||
|
itemCount = super(TreeAPIHarmonizer, self).GetCount()
|
||||||
|
if self.GetColumnCount() and not self.HasFlag(wx.TR_HIDE_ROOT):
|
||||||
|
itemCount += 1
|
||||||
|
return itemCount
|
||||||
|
|
||||||
def GetSelections(self):
|
def GetSelections(self):
|
||||||
# Always return a list of selected items, regardless of whether
|
# Always return a list of selected items, regardless of whether
|
||||||
# we are in multiple selection mode or not.
|
# we are in multiple selection mode or not.
|
||||||
if self.HasFlag(wx.TR_MULTIPLE):
|
if self.HasFlag(wx.TR_MULTIPLE):
|
||||||
return super(TreeAPIHarmonizer, self).GetSelections()
|
selections = super(TreeAPIHarmonizer, self).GetSelections()
|
||||||
else:
|
else:
|
||||||
selection = self.GetSelection()
|
selection = self.GetSelection()
|
||||||
if selection:
|
if selection:
|
||||||
return [selection]
|
selections = [selection]
|
||||||
else:
|
else:
|
||||||
return []
|
selections = []
|
||||||
|
# If the root item is hidden, it should never be selected,
|
||||||
|
# unfortunately, CustomTreeCtrl allows it to be selected.
|
||||||
|
if self.HasFlag(wx.TR_HIDE_ROOT):
|
||||||
|
rootItem = self.GetRootItem()
|
||||||
|
if rootItem and rootItem in selections:
|
||||||
|
selections.remove(rootItem)
|
||||||
|
return selections
|
||||||
|
|
||||||
|
def SelectItem(self, item, *args, **kwargs):
|
||||||
|
# Prevent the hidden root from being selected, otherwise TreeCtrl
|
||||||
|
# crashes
|
||||||
|
if self.HasFlag(wx.TR_HIDE_ROOT) and item == self.GetRootItem():
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
return super(TreeAPIHarmonizer, self).SelectItem(item, *args,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
def HitTest(self, *args, **kwargs):
|
def HitTest(self, *args, **kwargs):
|
||||||
''' HitTest returns a two-tuple (item, flags) for tree controls
|
''' HitTest returns a two-tuple (item, flags) for tree controls
|
||||||
@@ -129,10 +187,13 @@ class TreeAPIHarmonizer(object):
|
|||||||
item = self.GetRootItem()
|
item = self.GetRootItem()
|
||||||
super(TreeAPIHarmonizer, self).ExpandAll(item)
|
super(TreeAPIHarmonizer, self).ExpandAll(item)
|
||||||
|
|
||||||
|
|
||||||
|
class TreeHelper(object):
|
||||||
|
''' This class provides methods that are not part of the API of any
|
||||||
|
tree control, but are convenient to have available. '''
|
||||||
|
|
||||||
def GetItemChildren(self, item, recursively=False):
|
def GetItemChildren(self, item, recursively=False):
|
||||||
''' Return the children of item as a list. This method is not
|
''' Return the children of item as a list. '''
|
||||||
part of the API of any tree control, but very convenient to
|
|
||||||
have available. '''
|
|
||||||
children = []
|
children = []
|
||||||
child, cookie = self.GetFirstChild(item)
|
child, cookie = self.GetFirstChild(item)
|
||||||
while child:
|
while child:
|
||||||
@@ -142,22 +203,32 @@ class TreeAPIHarmonizer(object):
|
|||||||
child, cookie = self.GetNextChild(item, cookie)
|
child, cookie = self.GetNextChild(item, cookie)
|
||||||
return children
|
return children
|
||||||
|
|
||||||
def ItemIndices(self, item):
|
def ItemIndex(self, item, tupleIndex=True):
|
||||||
''' Construct an index typle for item. The root item is (), the
|
''' Return the index of item. If tupleIndex is True, return a
|
||||||
first child of the root item is (0,), the second child of the
|
an tuple-based index else return an integer-based index for item. '''
|
||||||
root item is (1,), the first child of the first child of the
|
if tupleIndex:
|
||||||
root item is (0, 0), the second child of the first child of the
|
parent = self.GetItemParent(item)
|
||||||
root item is (0, 1), etc. '''
|
if parent:
|
||||||
parent = self.GetItemParent(item)
|
parentIndices = self.ItemIndex(parent)
|
||||||
if parent:
|
ownIndex = self.GetItemChildren(parent).index(item)
|
||||||
parentIndices = self.ItemIndices(parent)
|
return parentIndices + (ownIndex,)
|
||||||
ownIndex = self.GetItemChildren(parent).index(item)
|
else:
|
||||||
return parentIndices + (ownIndex,)
|
return ()
|
||||||
else:
|
else:
|
||||||
return ()
|
rootItem = self.GetRootItem()
|
||||||
|
if self.HasFlag(wx.TR_HIDE_ROOT):
|
||||||
|
if item == rootItem:
|
||||||
|
return None
|
||||||
|
countRoot = 0
|
||||||
|
else:
|
||||||
|
if item == rootItem:
|
||||||
|
return 0
|
||||||
|
countRoot = 1
|
||||||
|
return self.GetItemChildren(rootItem,
|
||||||
|
recursively=True).index(item) + countRoot
|
||||||
|
|
||||||
|
|
||||||
class VirtualTree(TreeAPIHarmonizer):
|
class VirtualTree(TreeAPIHarmonizer, TreeHelper):
|
||||||
''' This is a mixin class that can be used to allow for virtual tree
|
''' This is a mixin class that can be used to allow for virtual tree
|
||||||
controls. It can be mixed in with wx.TreeCtrl, wx.gizmos.TreeListCtrl,
|
controls. It can be mixed in with wx.TreeCtrl, wx.gizmos.TreeListCtrl,
|
||||||
wx.lib.customtree.CustomTreeCtrl.
|
wx.lib.customtree.CustomTreeCtrl.
|
||||||
@@ -167,79 +238,114 @@ class VirtualTree(TreeAPIHarmonizer):
|
|||||||
class MyTree(VirtualTree, wx.TreeCtrl):
|
class MyTree(VirtualTree, wx.TreeCtrl):
|
||||||
...
|
...
|
||||||
|
|
||||||
You *must* implement OnGetChildrenCount and OnGetItemText so that
|
VirtualTree uses several callbacks (such as OnGetItemText) to
|
||||||
this class knows how many items to draw and what text to use. To
|
retrieve information needed to construct the tree and render the
|
||||||
also draw images, change colours, etc., override one or more of the
|
items. To specify what item the callback needs information about,
|
||||||
other OnGetXXX methods.
|
the callback passes an item index. VirtualTree supports two types of
|
||||||
|
indices: a tuple-based index (the default) and an integer based index.
|
||||||
|
See below for a more detailed explanation of the two index types.
|
||||||
|
|
||||||
About specifying item indices: the VirtualTree uses various item
|
Note that VirtualTree forces the wx.TR_HIDE_ROOT style.
|
||||||
callbacks (such as OnGetItemText) to retrieve information needed
|
|
||||||
to display the items. To specify what item a callback needs
|
In your subclass you *must* override OnGetItemText and either
|
||||||
information about, the callback passes a tuple of indices. The first
|
OnGetChildrenCount if you use the tuple-based index or
|
||||||
index in the tuple is the index of the root item. If no more indices
|
OnGetChildrenIndices if you use the integer-based index. These
|
||||||
are in the tuple (i.e. the length of the tuple of indices is exactly
|
methods are the minimum needed to construct the tree and render
|
||||||
1), the callback should return the information about that root item.
|
the item labels. If you want to add images, change fonts our colours,
|
||||||
If the tuple contains two indices, the first index is the index of
|
etc., you need to override the appropriate OnGetXXX method as well.
|
||||||
the root item, and the second index is the index of the child of
|
|
||||||
that root item. For example, if OnGetItemText is called with
|
About the index types: VirtualTree supports two types of indices that
|
||||||
indices=(0,2), the callback should return information about that the
|
are passed to the several callbacks to retrieve information about
|
||||||
third child of the first root item. OnGetChildrenCount may also be
|
items in the tree. The default index type is tuple-based, the second
|
||||||
called with indices == () to get the number of root items in the
|
type is integer-based.
|
||||||
tree. '''
|
|
||||||
|
If you use tuple-based indices, your callbacks are passed a tuple of
|
||||||
|
integers that identifies the item the VirtualTree wants information
|
||||||
|
about. An empty tuple, i.e. (), represents the hidden root item.
|
||||||
|
A tuple with one integer, e.g. (3,), represents a visible root item,
|
||||||
|
in this case the fourth one. A tuple with two integers, e.g. (3,0),
|
||||||
|
represents a child of a visible root item, in this case the first
|
||||||
|
child of the fourth root item. The tuple-based index is best suited
|
||||||
|
if your underlying data structure is organized as a tree and allows
|
||||||
|
for easy navigation to the right object in your tree data structure.
|
||||||
|
|
||||||
|
If you use integer-based indices, your callbacks are passed a simple
|
||||||
|
integer (or None) that identifies the item the VirtualTree wants
|
||||||
|
information about. None represents the hidden root item. Zero (0)
|
||||||
|
represents the first visible root item. If the first visible root
|
||||||
|
item has children 1 represents the first child of the first visible
|
||||||
|
root item. If that child has children 2 represents the first grand
|
||||||
|
child of the first visible root item. If the first child has no
|
||||||
|
children, 2 would represent the second child of the first visible
|
||||||
|
root item, etc. Basically, the integer is the row number of the item
|
||||||
|
(when the tree is completely expanded). Integer-based indices are
|
||||||
|
more convenient when your underlying data structure is organized as
|
||||||
|
a list that is in the same order as the tree items in the tree need
|
||||||
|
to be.
|
||||||
|
'''
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
self._tupleIndex = kwargs.pop('tupleIndex', True)
|
||||||
kwargs['style'] = kwargs.get('style', wx.TR_DEFAULT_STYLE) | \
|
kwargs['style'] = kwargs.get('style', wx.TR_DEFAULT_STYLE) | \
|
||||||
wx.TR_HIDE_ROOT
|
wx.TR_HIDE_ROOT
|
||||||
super(VirtualTree, self).__init__(*args, **kwargs)
|
super(VirtualTree, self).__init__(*args, **kwargs)
|
||||||
self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding)
|
self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding)
|
||||||
self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed)
|
self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed)
|
||||||
|
|
||||||
def OnGetChildrenCount(self, indices):
|
def OnGetChildrenCount(self, tupleIndex):
|
||||||
''' This function must be overloaded in the derived class. It
|
''' This function must be overloaded in the derived class, if
|
||||||
should return the number of child items of the item with the
|
you use the tuple-based indices. It should return the number
|
||||||
provided indices. If indices == () it should return the number
|
of child items of the item with the provided tupleIndex. If
|
||||||
of root items. '''
|
tupleIndex == () it should return the number of root items. '''
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def OnGetItemText(self, indices, column=0):
|
def OnGetChildrenIndices(self, integerIndex=None):
|
||||||
|
''' This function must be overloaded in the derived class, if
|
||||||
|
you want to use the integer-based index. The overridden method
|
||||||
|
should return a list containing the (integer) indices of the
|
||||||
|
children of the specified item. '''
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def OnGetItemText(self, index, column=0):
|
||||||
''' This function must be overloaded in the derived class. It
|
''' This function must be overloaded in the derived class. It
|
||||||
should return the string containing the text of the specified
|
should return the string containing the text of the specified
|
||||||
item. '''
|
item. '''
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def OnGetItemFont(self, indices):
|
def OnGetItemFont(self, index):
|
||||||
''' This function may be overloaded in the derived class. It
|
''' This function may be overloaded in the derived class. It
|
||||||
should return the wx.Font to be used for the specified item. '''
|
should return the wx.Font to be used for the specified item. '''
|
||||||
return wx.NullFont
|
return wx.NullFont
|
||||||
|
|
||||||
def OnGetItemTextColour(self, indices):
|
def OnGetItemTextColour(self, index):
|
||||||
''' This function may be overloaded in the derived class. It
|
''' This function may be overloaded in the derived class. It
|
||||||
should return the wx.Colour to be used as text colour for the
|
should return the wx.Colour to be used as text colour for the
|
||||||
specified item. '''
|
specified item. '''
|
||||||
return wx.NullColour
|
return wx.NullColour
|
||||||
|
|
||||||
def OnGetItemBackgroundColour(self, indices):
|
def OnGetItemBackgroundColour(self, index):
|
||||||
''' This function may be overloaded in the derived class. It
|
''' This function may be overloaded in the derived class. It
|
||||||
should return the wx.Colour to be used as background colour for
|
should return the wx.Colour to be used as background colour for
|
||||||
the specified item. '''
|
the specified item. '''
|
||||||
return wx.NullColour
|
return wx.NullColour
|
||||||
|
|
||||||
def OnGetItemImage(self, indices, which=wx.TreeItemIcon_Normal, column=0):
|
def OnGetItemImage(self, index, which=wx.TreeItemIcon_Normal, column=0):
|
||||||
''' This function may be overloaded in the derived class. It
|
''' This function may be overloaded in the derived class. It
|
||||||
should return the index of the image to be used. '''
|
should return the index of the image to be used. Don't forget
|
||||||
|
to associate an ImageList with the tree control. '''
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def OnGetItemType(self, indices):
|
def OnGetItemType(self, index):
|
||||||
''' This function may be overloaded in the derived class, but
|
''' This function may be overloaded in the derived class, but
|
||||||
that only makes sense when this class is mixed in with a tree
|
that only makes sense when this class is mixed in with a tree
|
||||||
control that supports checkable items, e.g. CustomTreeCtrl.
|
control that supports checkable items, i.e. CustomTreeCtrl.
|
||||||
This method should return whether the item is to be normal (0,
|
This method should return whether the item is to be normal (0,
|
||||||
the default), a checkbox (1) or a radiobutton (2).
|
the default), a checkbox (1) or a radiobutton (2).
|
||||||
Note that OnGetItemChecked should return whether the item is
|
Note that OnGetItemChecked needs to be implemented as well; it
|
||||||
actually checked. '''
|
should return whether the item is actually checked. '''
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def OnGetItemChecked(self, indices):
|
def OnGetItemChecked(self, index):
|
||||||
''' This function may be overloaded in the derived class, but
|
''' This function may be overloaded in the derived class, but
|
||||||
that only makes sense when this class is mixed in with a tree
|
that only makes sense when this class is mixed in with a tree
|
||||||
control that supports checkable items, i.e. CustomTreeCtrl.
|
control that supports checkable items, i.e. CustomTreeCtrl.
|
||||||
@@ -253,97 +359,71 @@ class VirtualTree(TreeAPIHarmonizer):
|
|||||||
rootItem = self.GetRootItem()
|
rootItem = self.GetRootItem()
|
||||||
if not rootItem:
|
if not rootItem:
|
||||||
rootItem = self.AddRoot('Hidden root')
|
rootItem = self.AddRoot('Hidden root')
|
||||||
self.RefreshChildrenRecursively(rootItem, (),
|
self.RefreshChildrenRecursively(rootItem)
|
||||||
self.OnGetChildrenCount(()))
|
|
||||||
|
|
||||||
def RefreshChildrenRecursively(self, item, indices, childrenCount):
|
def RefreshChildrenRecursively(self, item, itemIndex=None):
|
||||||
''' Refresh the children of item, reusing as much of the
|
''' Refresh the children of item, reusing as much of the
|
||||||
existing items in the tree as possible. '''
|
existing items in the tree as possible. '''
|
||||||
existingChildren = self.GetItemChildren(item)
|
if itemIndex is None:
|
||||||
for childIndex in range(childrenCount):
|
itemIndex = self.ItemIndex(item, tupleIndex=self._tupleIndex)
|
||||||
childIndices = indices + (childIndex,)
|
reusableChildren = self.GetItemChildren(item)
|
||||||
if childIndex < len(existingChildren):
|
for childIndex in self.ChildIndices(itemIndex):
|
||||||
child = existingChildren[childIndex]
|
if reusableChildren:
|
||||||
|
child = reusableChildren.pop(0)
|
||||||
else:
|
else:
|
||||||
child = self.AppendItem(item, '')
|
child = self.AppendItem(item, '')
|
||||||
self.RefreshRecursively(child, childIndices)
|
self.RefreshItemRecursively(child, childIndex)
|
||||||
# Delete left-over items:
|
for child in reusableChildren:
|
||||||
for existingChild in existingChildren[childrenCount:]:
|
self.Delete(child)
|
||||||
self.Delete(existingChild)
|
|
||||||
|
|
||||||
def RefreshRecursively(self, item, indices):
|
def RefreshItemRecursively(self, item, itemIndex):
|
||||||
childrenCount = self.OnGetChildrenCount(indices)
|
''' Refresh the item and its children recursively. '''
|
||||||
self.RefreshItem(item, indices, bool(childrenCount))
|
hasChildren = bool(self.ChildIndices(itemIndex))
|
||||||
|
self.RefreshItem(item, itemIndex, hasChildren)
|
||||||
# We need to refresh the children when the item is expanded and
|
# We need to refresh the children when the item is expanded and
|
||||||
# when the item has no children, because in the latter case we
|
# when the item has no children, because in the latter case we
|
||||||
# might have to delete old children from the tree:
|
# might have to delete old children from the tree:
|
||||||
if self.IsExpanded(item) or not childrenCount:
|
if self.IsExpanded(item) or not hasChildren:
|
||||||
self.RefreshChildrenRecursively(item, indices, childrenCount)
|
self.RefreshChildrenRecursively(item, itemIndex)
|
||||||
self.SetItemHasChildren(item, bool(childrenCount))
|
self.SetItemHasChildren(item, hasChildren)
|
||||||
|
|
||||||
def RefreshItem(self, item, indices, hasChildren):
|
def RefreshItem(self, item, index, hasChildren):
|
||||||
''' Refresh one item. '''
|
''' Refresh one item. '''
|
||||||
item = self.RefreshItemType(item, indices)
|
item = self.RefreshItemType(item, index)
|
||||||
self.RefreshItemText(item, indices)
|
self.RefreshItemText(item, index)
|
||||||
self.RefreshColumns(item, indices)
|
self.RefreshColumns(item, index)
|
||||||
self.RefreshFont(item, indices)
|
self.RefreshItemFont(item, index)
|
||||||
self.RefreshTextColour(item, indices)
|
self.RefreshTextColour(item, index)
|
||||||
self.RefreshBackgroundColour(item, indices)
|
self.RefreshBackgroundColour(item, index)
|
||||||
self.RefreshItemImage(item, indices, hasChildren)
|
self.RefreshItemImage(item, index, hasChildren)
|
||||||
self.RefreshCheckedState(item, indices)
|
self.RefreshCheckedState(item, index)
|
||||||
|
|
||||||
def RefreshItemType(self, item, indices):
|
def RefreshItemText(self, item, index):
|
||||||
currentType = self.GetItemType(item)
|
self.__refreshAttribute(item, index, 'ItemText')
|
||||||
newType = self.OnGetItemType(indices)
|
|
||||||
if newType != currentType:
|
|
||||||
# There's no way to change the type so we create a new item
|
|
||||||
# and delete the old one.
|
|
||||||
oldItem = item
|
|
||||||
item = self.InsertItem(self.GetItemParent(oldItem), item, '',
|
|
||||||
ct_type=newType)
|
|
||||||
self.Delete(oldItem)
|
|
||||||
return item
|
|
||||||
|
|
||||||
def RefreshItemText(self, item, indices):
|
def RefreshColumns(self, item, index):
|
||||||
itemText = self.OnGetItemText(indices)
|
|
||||||
if self.GetItemText(item) != itemText:
|
|
||||||
self.SetItemText(item, itemText)
|
|
||||||
|
|
||||||
def RefreshColumns(self, item, indices):
|
|
||||||
for columnIndex in range(1, self.GetColumnCount()):
|
for columnIndex in range(1, self.GetColumnCount()):
|
||||||
itemText = self.OnGetItemText(indices, columnIndex)
|
self.__refreshAttribute(item, index, 'ItemText', columnIndex)
|
||||||
if self.GetItemText(item, columnIndex) != itemText:
|
|
||||||
self.SetItemText(item, itemText, columnIndex)
|
|
||||||
|
|
||||||
def RefreshFont(self, item, indices):
|
def RefreshItemFont(self, item, index):
|
||||||
font = self.OnGetItemFont(indices)
|
self.__refreshAttribute(item, index, 'ItemFont')
|
||||||
if self.GetItemFont(item) != font:
|
|
||||||
self.SetItemFont(item, font)
|
|
||||||
|
|
||||||
def RefreshTextColour(self, item, indices):
|
def RefreshTextColour(self, item, index):
|
||||||
colour = self.OnGetItemTextColour(indices)
|
self.__refreshAttribute(item, index, 'ItemTextColour')
|
||||||
if self.GetItemTextColour(item) != colour:
|
|
||||||
self.SetItemTextColour(item, colour)
|
|
||||||
|
|
||||||
def RefreshBackgroundColour(self, item, indices):
|
def RefreshBackgroundColour(self, item, index):
|
||||||
# On Mac OSX this one only seems to work for TreeCtrl and not
|
self.__refreshAttribute(item, index, 'ItemBackgroundColour')
|
||||||
# for TreeListCtrl and CustomTreeCtrl.
|
|
||||||
colour = self.OnGetItemBackgroundColour(indices)
|
|
||||||
if self.GetItemBackgroundColour(item) != colour:
|
|
||||||
self.SetItemBackgroundColour(item, colour)
|
|
||||||
|
|
||||||
def RefreshItemImage(self, item, indices, hasChildren):
|
def RefreshItemImage(self, item, index, hasChildren):
|
||||||
regularIcons = [wx.TreeItemIcon_Normal, wx.TreeItemIcon_Selected]
|
regularIcons = [wx.TreeItemIcon_Normal, wx.TreeItemIcon_Selected]
|
||||||
expandedIcons = [wx.TreeItemIcon_Expanded,
|
expandedIcons = [wx.TreeItemIcon_Expanded,
|
||||||
wx.TreeItemIcon_SelectedExpanded]
|
wx.TreeItemIcon_SelectedExpanded]
|
||||||
# Refresh images in first column:
|
# Refresh images in first column:
|
||||||
for icon in regularIcons:
|
for icon in regularIcons:
|
||||||
imageIndex = self.OnGetItemImage(indices, icon)
|
self.__refreshAttribute(item, index, 'ItemImage', icon)
|
||||||
if self.GetItemImage(item, icon) != imageIndex:
|
|
||||||
self.SetItemImage(item, imageIndex, icon)
|
|
||||||
for icon in expandedIcons:
|
for icon in expandedIcons:
|
||||||
if hasChildren:
|
if hasChildren:
|
||||||
imageIndex = self.OnGetItemImage(indices, icon)
|
imageIndex = self.OnGetItemImage(index, icon)
|
||||||
else:
|
else:
|
||||||
imageIndex = -1
|
imageIndex = -1
|
||||||
if self.GetItemImage(item, icon) != imageIndex or imageIndex == -1:
|
if self.GetItemImage(item, icon) != imageIndex or imageIndex == -1:
|
||||||
@@ -351,33 +431,44 @@ class VirtualTree(TreeAPIHarmonizer):
|
|||||||
# Refresh images in remaining columns, if any:
|
# Refresh images in remaining columns, if any:
|
||||||
for columnIndex in range(1, self.GetColumnCount()):
|
for columnIndex in range(1, self.GetColumnCount()):
|
||||||
for icon in regularIcons:
|
for icon in regularIcons:
|
||||||
imageIndex = self.OnGetItemImage(indices, icon, columnIndex)
|
self.__refreshAttribute(item, index, 'ItemImage', icon,
|
||||||
if self.GetItemImage(item, columnIndex, icon) != imageIndex:
|
columnIndex)
|
||||||
self.SetItemImage(item, imageIndex, icon, columnIndex)
|
|
||||||
|
|
||||||
def RefreshCheckedState(self, item, indices):
|
def RefreshItemType(self, item, index):
|
||||||
isChecked = self.IsItemChecked(item)
|
return self.__refreshAttribute(item, index, 'ItemType')
|
||||||
shouldBeChecked = self.OnGetItemChecked(indices)
|
|
||||||
if isChecked != shouldBeChecked:
|
def RefreshCheckedState(self, item, index):
|
||||||
self.CheckItem(item, shouldBeChecked)
|
self.__refreshAttribute(item, index, 'ItemChecked')
|
||||||
|
|
||||||
|
def ChildIndices(self, itemIndex):
|
||||||
|
if self._tupleIndex:
|
||||||
|
childrenCount = self.OnGetChildrenCount(itemIndex)
|
||||||
|
return [itemIndex + (childNumber,) for childNumber \
|
||||||
|
in range(childrenCount)]
|
||||||
|
else:
|
||||||
|
return self.OnGetChildrenIndices(itemIndex)
|
||||||
|
|
||||||
def OnItemExpanding(self, event):
|
def OnItemExpanding(self, event):
|
||||||
indices = self.ItemIndices(event.GetItem())
|
self.RefreshChildrenRecursively(event.GetItem())
|
||||||
childrenCount = self.OnGetChildrenCount(indices)
|
|
||||||
self.RefreshChildrenRecursively(event.GetItem(), indices, childrenCount)
|
|
||||||
event.Skip()
|
event.Skip()
|
||||||
|
|
||||||
def OnItemCollapsed(self, event):
|
def OnItemCollapsed(self, event):
|
||||||
parent = self.GetItemParent(event.GetItem())
|
parent = self.GetItemParent(event.GetItem())
|
||||||
if not parent:
|
if not parent:
|
||||||
parent = self.GetRootItem()
|
parent = self.GetRootItem()
|
||||||
indices = self.ItemIndices(parent)
|
self.RefreshChildrenRecursively(parent)
|
||||||
childrenCount = self.OnGetChildrenCount(indices)
|
|
||||||
self.RefreshChildrenRecursively(parent, indices, childrenCount)
|
|
||||||
event.Skip()
|
event.Skip()
|
||||||
|
|
||||||
|
|
||||||
class DragAndDrop(TreeAPIHarmonizer):
|
def __refreshAttribute(self, item, index, attribute, *args):
|
||||||
|
''' Refresh the specified attribute if necessary. '''
|
||||||
|
value = getattr(self, 'OnGet%s'%attribute)(index, *args)
|
||||||
|
if getattr(self, 'Get%s'%attribute)(item, *args) != value:
|
||||||
|
return getattr(self, 'Set%s'%attribute)(item, value, *args)
|
||||||
|
else:
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
class DragAndDrop(TreeAPIHarmonizer, TreeHelper):
|
||||||
''' This is a mixin class that can be used to easily implement
|
''' This is a mixin class that can be used to easily implement
|
||||||
dragging and dropping of tree items. It can be mixed in with
|
dragging and dropping of tree items. It can be mixed in with
|
||||||
wx.TreeCtrl, wx.gizmos.TreeListCtrl, or wx.lib.customtree.CustomTreeCtrl.
|
wx.TreeCtrl, wx.gizmos.TreeListCtrl, or wx.lib.customtree.CustomTreeCtrl.
|
||||||
@@ -391,7 +482,7 @@ class DragAndDrop(TreeAPIHarmonizer):
|
|||||||
dropped an item on top of another item. It's up to you to decide how
|
dropped an item on top of another item. It's up to you to decide how
|
||||||
to handle the drop. If you are using this mixin together with the
|
to handle the drop. If you are using this mixin together with the
|
||||||
VirtualTree mixin, it makes sense to rearrange your underlying data
|
VirtualTree mixin, it makes sense to rearrange your underlying data
|
||||||
and then call RefreshItems to let de virtual tree refresh itself. '''
|
and then call RefreshItems to let the virtual tree refresh itself. '''
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs['style'] = kwargs.get('style', wx.TR_DEFAULT_STYLE) | \
|
kwargs['style'] = kwargs.get('style', wx.TR_DEFAULT_STYLE) | \
|
||||||
@@ -441,10 +532,9 @@ class DragAndDrop(TreeAPIHarmonizer):
|
|||||||
self.SetCursorToDroppingImpossible()
|
self.SetCursorToDroppingImpossible()
|
||||||
if flags & wx.TREE_HITTEST_ONITEMBUTTON:
|
if flags & wx.TREE_HITTEST_ONITEMBUTTON:
|
||||||
self.Expand(item)
|
self.Expand(item)
|
||||||
selections = self.GetSelections()
|
if self.GetSelections() != [item]:
|
||||||
if selections != [item]:
|
|
||||||
self.UnselectAll()
|
self.UnselectAll()
|
||||||
if item != self.GetRootItem():
|
if item != self.GetRootItem():
|
||||||
self.SelectItem(item)
|
self.SelectItem(item)
|
||||||
event.Skip()
|
event.Skip()
|
||||||
|
|
||||||
@@ -478,7 +568,7 @@ class DragAndDrop(TreeAPIHarmonizer):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class ExpansionState(TreeAPIHarmonizer):
|
class ExpansionState(TreeAPIHarmonizer, TreeHelper):
|
||||||
''' This is a mixin class that can be used to save and restore
|
''' This is a mixin class that can be used to save and restore
|
||||||
the expansion state (i.e. which items are expanded and which items
|
the expansion state (i.e. which items are expanded and which items
|
||||||
are collapsed) of a tree. It can be mixed in with wx.TreeCtrl,
|
are collapsed) of a tree. It can be mixed in with wx.TreeCtrl,
|
||||||
@@ -490,11 +580,11 @@ class ExpansionState(TreeAPIHarmonizer):
|
|||||||
...
|
...
|
||||||
|
|
||||||
By default, ExpansionState uses the position of tree items in the tree
|
By default, ExpansionState uses the position of tree items in the tree
|
||||||
for keeping track of which items are expanded. This should be
|
to keep track of which items are expanded. This should be sufficient
|
||||||
sufficient for the scenario where you save the expansion state of the
|
for the simple scenario where you save the expansion state of the tree
|
||||||
tree when the user closes the application or file so that you can
|
when the user closes the application or file so that you can restore
|
||||||
restore the expansion state when the user start the application or loads
|
the expansion state when the user start the application or loads that
|
||||||
that file for the next session.
|
file for the next session.
|
||||||
|
|
||||||
If you need to add or remove items between the moments of saving and
|
If you need to add or remove items between the moments of saving and
|
||||||
restoring the expansion state (e.g. in case of a multi-user application)
|
restoring the expansion state (e.g. in case of a multi-user application)
|
||||||
@@ -502,17 +592,16 @@ class ExpansionState(TreeAPIHarmonizer):
|
|||||||
expansion doesn't depend on the position of items in the tree, but
|
expansion doesn't depend on the position of items in the tree, but
|
||||||
rather on some more stable characteristic of the underlying domain
|
rather on some more stable characteristic of the underlying domain
|
||||||
object, e.g. a social security number in case of persons or an isbn
|
object, e.g. a social security number in case of persons or an isbn
|
||||||
number in case of books.
|
number in case of books. '''
|
||||||
'''
|
|
||||||
|
|
||||||
def GetItemIdentity(self, item):
|
def GetItemIdentity(self, item):
|
||||||
''' Return a hashable object that represents the identify of the
|
''' Return a hashable object that represents the identity of the
|
||||||
item. By default this returns the position of the item in the
|
item. By default this returns the position of the item in the
|
||||||
tree. You may want to override this to return the item label
|
tree. You may want to override this to return the item label
|
||||||
(if you know that labels are unique and don't change), or return
|
(if you know that labels are unique and don't change), or return
|
||||||
something that represents the underlying domain object, e.g.
|
something that represents the underlying domain object, e.g.
|
||||||
a database key. '''
|
a database key. '''
|
||||||
return self.ItemIndices(item)
|
return self.ItemIndex(item)
|
||||||
|
|
||||||
def GetExpansionState(self):
|
def GetExpansionState(self):
|
||||||
''' GetExpansionState() -> list of expanded items. Expanded items
|
''' GetExpansionState() -> list of expanded items. Expanded items
|
||||||
@@ -527,7 +616,7 @@ class ExpansionState(TreeAPIHarmonizer):
|
|||||||
|
|
||||||
def SetExpansionState(self, listOfExpandedItems):
|
def SetExpansionState(self, listOfExpandedItems):
|
||||||
''' SetExpansionState(listOfExpandedItems). Expands all tree items
|
''' SetExpansionState(listOfExpandedItems). Expands all tree items
|
||||||
whose identify, as determined by GetItemIdentity(item), is present
|
whose identity, as determined by GetItemIdentity(item), is present
|
||||||
in the list and collapses all other tree items. '''
|
in the list and collapses all other tree items. '''
|
||||||
root = self.GetRootItem()
|
root = self.GetRootItem()
|
||||||
if not root:
|
if not root:
|
||||||
|
Reference in New Issue
Block a user