📄 mvctree.py
字号:
self.nodemap = {}
self._multiselect = False
self._selections = []
self._assumeChildren = False
self._scrollx = False
self._scrolly = False
self.doubleBuffered = False
self._lastPhysicalSize = self.GetSize()
self._editors = []
if not model:
model = BasicTreeModel()
model.SetRoot("Root")
self.SetModel(model)
if not layout:
layout = TreeLayout(self)
self.layout = layout
if not transform:
transform = NullTransform(self)
self.transform = transform
if not painter:
painter = TreePainter(self)
self.painter = painter
self.SetFont(wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False))
self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
self.doubleBuffered = True
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
self.Bind(wx.EVT_PAINT, self.OnPaint)
def Refresh(self):
if self.doubleBuffered:
self.painter.ClearBuffer()
wx.ScrolledWindow.Refresh(self, False)
def GetPainter(self):
return self.painter
def GetLayoutEngine(self):
return self.layout
def GetTransform(self):
return self.transform
def __repr__(self):
return "<MVCTree instance at %s>" % str(hex(id(self)))
def __str__(self):
return self.__repr__()
def NodeAdded(self, parent, child):
e = MVCTreeEvent(wxEVT_MVCTREE_ADD_ITEM, self.GetId(), node = child, nodes = [parent, child])
self.GetEventHandler().ProcessEvent(e)
self.painter.ClearBuffer()
def NodeInserted(self, parent, child, index):
e = MVCTreeEvent(wxEVT_MVCTREE_ADD_ITEM, self.GetId(), node = child, nodes = [parent, child])
self.GetEventHandler().ProcessEvent(e)
self.painter.ClearBuffer()
def NodeRemoved(self, node):
e = MVCTreeEvent(wxEVT_MVCTREE_DELETE_ITEM, self.GetId(), node = child, nodes = [parent, child])
self.GetEventHandler().ProcessEvent(e)
self.painter.ClearBuffer()
def OnKeyDown(self, evt):
e = MVCTreeEvent(wxEVT_MVCTREE_KEY_DOWN, self.GetId(), keyEvent = evt)
self.GetEventHandler().ProcessEvent(e)
def SetFont(self, font):
self.painter.SetFont(font)
dc = wx.ClientDC(self)
dc.SetFont(font)
self.layout.SetHeight(dc.GetTextExtent("")[1] + 18)
self.painter.ClearBuffer()
def GetFont(self):
return self.painter.GetFont()
def AddEditor(self, editor):
self._editors.append(editor)
def RemoveEditor(self, editor):
self._editors.remove(editor)
def OnMouse(self, evt):
self.painter.OnMouse(evt)
def OnNodeClick(self, node, mouseEvent):
if node.selected and (self.IsMultiSelect() and mouseEvent.ControlDown()):
self.RemoveFromSelection(node.data)
else:
self.AddToSelection(node.data, mouseEvent.ControlDown(), mouseEvent.ShiftDown())
def OnKnobClick(self, node):
self.SetExpanded(node.data, not node.expanded)
def GetDisplayText(self, node):
treenode = self.nodemap[node]
return self.painter.textConverter.Convert(treenode)
def IsDoubleBuffered(self):
return self.doubleBuffered
def SetDoubleBuffered(self, bool):
"""
By default MVCTree is double-buffered.
"""
self.doubleBuffered = bool
def GetModel(self):
return self.model
def SetModel(self, model):
"""
Completely change the data to be displayed.
"""
self.model = model
model.tree = self
self.laidOut = 0
self.transformed = 0
self._selections = []
self.layoutRoot = MVCTreeNode()
self.layoutRoot.data = self.model.GetRoot()
self.layoutRoot.expanded = True
self.LoadChildren(self.layoutRoot)
self.currentRoot = self.layoutRoot
self.offset = [0,0]
self.rotation = 0
self._scrollset = None
self.Refresh()
def GetCurrentRoot(self):
return self.currentRoot
def LoadChildren(self, layoutNode):
if layoutNode.built:
return
else:
self.nodemap[layoutNode.data]=layoutNode
for i in range(self.GetModel().GetChildCount(layoutNode.data)):
p = MVCTreeNode("RAW", layoutNode, [])
layoutNode.Add(p)
p.data = self.GetModel().GetChildAt(layoutNode.data, i)
self.nodemap[p.data]=p
layoutNode.built = True
if not self._assumeChildren:
for kid in layoutNode.kids:
self.LoadChildren(kid)
def OnEraseBackground(self, evt):
pass
def OnSize(self, evt):
size = self.GetSize()
self.center = (size.width/2, size.height/2)
if self._lastPhysicalSize.width < size.width or self._lastPhysicalSize.height < size.height:
self.painter.ClearBuffer()
self._lastPhysicalSize = size
def GetSelection(self):
"Returns a tuple of selected nodes."
return tuple(self._selections)
def SetSelection(self, nodeTuple):
if type(nodeTuple) != type(()):
nodeTuple = (nodeTuple,)
e = MVCTreeNotifyEvent(wxEVT_MVCTREE_SEL_CHANGING, self.GetId(), nodeTuple[0], nodes = nodeTuple)
self.GetEventHandler().ProcessEvent(e)
if not e.notify.IsAllowed():
return
for node in nodeTuple:
treenode = self.nodemap[node]
treenode.selected = True
for node in self._selections:
treenode = self.nodemap[node]
node.selected = False
self._selections = list(nodeTuple)
e = MVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), nodeTuple[0], nodes = nodeTuple)
self.GetEventHandler().ProcessEvent(e)
def IsMultiSelect(self):
return self._multiselect
def SetMultiSelect(self, bool):
self._multiselect = bool
def IsSelected(self, node):
return self.nodemap[node].selected
def Edit(self, node):
if not self.model.IsEditable(node):
return
for ed in self._editors:
if ed.CanEdit(node):
e = MVCTreeNotifyEvent(wxEVT_MVCTREE_BEGIN_EDIT, self.GetId(), node)
self.GetEventHandler().ProcessEvent(e)
if not e.notify.IsAllowed():
return
ed.Edit(node)
self._currentEditor = ed
break
def EndEdit(self):
if self._currentEditor:
self._currentEditor.EndEdit
self._currentEditor = None
def _EditEnding(self, node):
e = MVCTreeNotifyEvent(wxEVT_MVCTREE_END_EDIT, self.GetId(), node)
self.GetEventHandler().ProcessEvent(e)
if not e.notify.IsAllowed():
return False
self._currentEditor = None
return True
def SetExpanded(self, node, bool):
treenode = self.nodemap[node]
if bool:
e = MVCTreeNotifyEvent(wxEVT_MVCTREE_ITEM_EXPANDING, self.GetId(), node)
self.GetEventHandler().ProcessEvent(e)
if not e.notify.IsAllowed():
return
if not treenode.built:
self.LoadChildren(treenode)
else:
e = MVCTreeNotifyEvent(wxEVT_MVCTREE_ITEM_COLLAPSING, self.GetId(), node)
self.GetEventHandler().ProcessEvent(e)
if not e.notify.IsAllowed():
return
treenode.expanded = bool
e = None
if treenode.expanded:
e = MVCTreeEvent(wxEVT_MVCTREE_ITEM_EXPANDED, self.GetId(), node)
else:
e = MVCTreeEvent(wxEVT_MVCTREE_ITEM_COLLAPSED, self.GetId(), node)
self.GetEventHandler().ProcessEvent(e)
self.layout.Layout(self.currentRoot)
self.transform.Transform(self.currentRoot, self.offset, self.rotation)
self.Refresh()
def IsExpanded(self, node):
return self.nodemap[node].expanded
def AddToSelection(self, nodeOrTuple, enableMulti = True, shiftMulti = False):
nodeTuple = nodeOrTuple
if type(nodeOrTuple)!= type(()):
nodeTuple = (nodeOrTuple,)
e = MVCTreeNotifyEvent(wxEVT_MVCTREE_SEL_CHANGING, self.GetId(), nodeTuple[0], nodes = nodeTuple)
self.GetEventHandler().ProcessEvent(e)
if not e.notify.IsAllowed():
return
changeparents = []
if not (self.IsMultiSelect() and (enableMulti or shiftMulti)):
for node in self._selections:
treenode = self.nodemap[node]
treenode.selected = False
changeparents.append(treenode)
node = nodeTuple[0]
self._selections = [node]
treenode = self.nodemap[node]
changeparents.append(treenode)
treenode.selected = True
else:
if shiftMulti:
for node in nodeTuple:
treenode = self.nodemap[node]
oldtreenode = self.nodemap[self._selections[0]]
if treenode.parent == oldtreenode.parent:
found = 0
for kid in oldtreenode.parent.kids:
if kid == treenode or kid == oldtreenode:
found = not found
kid.selected = True
self._selections.append(kid.data)
changeparents.append(kid)
elif found:
kid.selected = True
self._selections.append(kid.data)
changeparents.append(kid)
else:
for node in nodeTuple:
try:
self._selections.index(node)
except ValueError:
self._selections.append(node)
treenode = self.nodemap[node]
treenode.selected = True
changeparents.append(treenode)
e = MVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), nodeTuple[0], nodes = nodeTuple)
self.GetEventHandler().ProcessEvent(e)
dc = wx.ClientDC(self)
self.PrepareDC(dc)
for node in changeparents:
if node:
self.painter.Paint(dc, node, doubleBuffered = 0, paintBackground = 0)
self.painter.ClearBuffer()
def RemoveFromSelection(self, nodeTuple):
if type(nodeTuple) != type(()):
nodeTuple = (nodeTuple,)
changeparents = []
for node in nodeTuple:
self._selections.remove(node)
treenode = self.nodemap[node]
changeparents.append(treenode)
treenode.selected = False
e = MVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), node, nodes = nodeTuple)
self.GetEventHandler().ProcessEvent(e)
dc = wx.ClientDC(self)
self.PrepareDC(dc)
for node in changeparents:
if node:
self.painter.Paint(dc, node, doubleBuffered = 0, paintBackground = 0)
self.painter.ClearBuffer()
def GetBackgroundColour(self):
if hasattr(self, 'painter') and self.painter:
return self.painter.GetBackgroundColour()
else:
return wx.Window.GetBackgroundColour(self)
def SetBackgroundColour(self, color):
if hasattr(self, 'painter') and self.painter:
self.painter.SetBackgroundColour(color)
else:
wx.Window.SetBackgroundColour(self, color)
def GetForegroundColour(self):
if hasattr(self, 'painter') and self.painter:
return self.painter.GetForegroundColour()
else:
return wx.Window.GetBackgroundColour(self)
def SetForegroundColour(self, color):
if hasattr(self, 'painter') and self.painter:
self.painter.SetForegroundColour(color)
else:
wx.Window.SetBackgroundColour(self, color)
def SetAssumeChildren(self, bool):
self._assumeChildren = bool
def GetAssumeChildren(self):
return self._assumeChildren
def OnPaint(self, evt):
"""
Ensures that the tree has been laid out and transformed, then calls the painter
to paint the control.
"""
try:
self.EnableScrolling(False, False)
if not self.laidOut:
self.layout.Layout(self.currentRoot)
self.laidOut = True
self.transformed = False
if not self.transformed:
self.transform.Transform(self.currentRoot, self.offset, self.rotation)
self.transformed = True
tsize = None
tsize = list(self.transform.GetSize())
tsize[0] = tsize[0] + 50
tsize[1] = tsize[1] + 50
w, h = self.GetSize()
if tsize[0] > w or tsize[1] > h:
if not hasattr(self, '_oldsize') or (tsize[0] > self._oldsize[0] or tsize[1] > self._oldsize[1]):
self._oldsize = tsize
oldstart = self.GetViewStart()
self._lastPhysicalSize = self.GetSize()
self.SetScrollbars(10, 10, tsize[0]/10, tsize[1]/10)
self.Scroll(oldstart[0], oldstart[1])
dc = wx.PaintDC(self)
self.PrepareDC(dc)
dc.SetFont(self.GetFont())
self.painter.Paint(dc, self.currentRoot, self.doubleBuffered)
except:
traceback.print_exc()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -