📄 mvctree.py
字号:
# 12/09/2003 - Jeff Grimmett (grimmtooth@softhome.net)
#
# o 2.5 compatability update.
# o I'm a little nervous about some of it though.
#
# 12/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
#
# o wxTreeModel -> TreeModel
# o wxMVCTree -> MVCTree
# o wxMVCTreeEvent -> MVCTreeEvent
# o wxMVCTreeNotifyEvent -> MVCTreeNotifyEvent
#
"""
MVCTree is a control which handles hierarchical data. It is constructed
in model-view-controller architecture, so the display of that data, and
the content of the data can be changed greatly without affecting the other parts.
MVCTree actually is even more configurable than MVC normally implies, because
almost every aspect of it is pluggable:
MVCTree - Overall controller, and the window that actually gets placed
in the GUI.
Painter - Paints the control. The 'view' part of MVC.
NodePainter - Paints just the nodes
LinePainter - Paints just the lines between the nodes
TextConverter - Figures out what text to print for each node
Editor - Edits the contents of a node, if the model is editable.
LayoutEngine - Determines initial placement of nodes
Transform - Adjusts positions of nodes for movement or special effects.
TreeModel - Contains the data which the rest of the control acts
on. The 'model' part of MVC.
Author/Maintainer - Bryn Keller <xoltar@starship.python.net>
NOTE: This module is *not* supported in any way. Use it however you
wish, but be warned that dealing with any consequences is
entirly up to you.
--Robin
"""
#------------------------------------------------------------------------
import os
import sys
import traceback
import warnings
import wx
#------------------------------------------------------------------------
warningmsg = r"""\
################################################\
# This module is not supported in any way! |
# |
# See cource code for wx.lib.mvctree for more |
# information. |
################################################/
"""
warnings.warn(warningmsg, DeprecationWarning, stacklevel=2)
#------------------------------------------------------------------------
class MVCTreeNode:
"""
Used internally by MVCTree to manage its data. Contains information about
screen placement, the actual data associated with it, and more. These are
the nodes passed to all the other helper parts to do their work with.
"""
def __init__(self, data=None, parent = None, kids = None, x = 0, y = 0):
self.x = 0
self.y = 0
self.projx = 0
self.projy = 0
self.parent = parent
self.kids = kids
if self.kids is None:
self.kids = []
self.data = data
self.expanded = False
self.selected = False
self.built = False
self.scale = 0
def GetChildren(self):
return self.kids
def GetParent(self):
return self.parent
def Remove(self, node):
try:
self.kids.remove(node)
except:
pass
def Add(self, node):
self.kids.append(node)
node.SetParent(self)
def SetParent(self, parent):
if self.parent and not (self.parent is parent):
self.parent.Remove(self)
self.parent = parent
def __str__(self):
return "Node: " + str(self.data) + " (" + str(self.x) + ", " + str(self.y) + ")"
def __repr__(self):
return str(self.data)
def GetTreeString(self, tabs=0):
s = tabs * '\t' + str(self) + '\n'
for kid in self.kids:
s = s + kid.GetTreeString(tabs + 1)
return s
class Editor:
def __init__(self, tree):
self.tree = tree
def Edit(self, node):
raise NotImplementedError
def EndEdit(self, node, commit):
raise NotImplementedError
def CanEdit(self, node):
raise NotImplementedError
class LayoutEngine:
"""
Interface for layout engines.
"""
def __init__(self, tree):
self.tree = tree
def Layout(self, node):
raise NotImplementedError
def GetNodeList(self):
raise NotImplementedError
class Transform:
"""
Transform interface.
"""
def __init__(self, tree):
self.tree = tree
def Transform(self, node, offset, rotation):
"""
This method should only change the projx and projy attributes of
the node. These represent the position of the node as it should
be drawn on screen. Adjusting the x and y attributes can and
should cause havoc.
"""
raise NotImplementedError
def GetSize(self):
"""
Returns the size of the entire tree as laid out and transformed
as a tuple
"""
raise NotImplementedError
class Painter:
"""
This is the interface that MVCTree expects from painters. All painters should
be Painter subclasses.
"""
def __init__(self, tree):
self.tree = tree
self.textcolor = wx.NamedColour("BLACK")
self.bgcolor = wx.NamedColour("WHITE")
self.fgcolor = wx.NamedColour("BLUE")
self.linecolor = wx.NamedColour("GREY")
self.font = wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)
self.bmp = None
def GetFont(self):
return self.font
def SetFont(self, font):
self.font = font
self.tree.Refresh()
def GetBuffer(self):
return self.bmp
def ClearBuffer(self):
self.bmp = None
def Paint(self, dc, node, doubleBuffered=1, paintBackground=1):
raise NotImplementedError
def GetTextColour(self):
return self.textcolor
def SetTextColour(self, color):
self.textcolor = color
self.textbrush = wx.Brush(color)
self.textpen = wx.Pen(color, 1, wx.SOLID)
def GetBackgroundColour(self):
return self.bgcolor
def SetBackgroundColour(self, color):
self.bgcolor = color
self.bgbrush = wx.Brush(color)
self.bgpen = wx.Pen(color, 1, wx.SOLID)
def GetForegroundColour(self):
return self.fgcolor
def SetForegroundColour(self, color):
self.fgcolor = color
self.fgbrush = wx.Brush(color)
self.fgpen = wx.Pen(color, 1, wx.SOLID)
def GetLineColour(self):
return self.linecolor
def SetLineColour(self, color):
self.linecolor = color
self.linebrush = wx.Brush(color)
self.linepen = wx.Pen( color, 1, wx.SOLID)
def GetForegroundPen(self):
return self.fgpen
def GetBackgroundPen(self):
return self.bgpen
def GetTextPen(self):
return self.textpen
def GetForegroundBrush(self):
return self.fgbrush
def GetBackgroundBrush(self):
return self.bgbrush
def GetTextBrush(self):
return self.textbrush
def GetLinePen(self):
return self.linepen
def GetLineBrush(self):
return self.linebrush
def OnMouse(self, evt):
if evt.LeftDClick():
x, y = self.tree.CalcUnscrolledPosition(evt.GetX(), evt.GetY())
for item in self.rectangles:
if item[1].Contains((x,y)):
self.tree.Edit(item[0].data)
self.tree.OnNodeClick(item[0], evt)
return
elif evt.ButtonDown():
x, y = self.tree.CalcUnscrolledPosition(evt.GetX(), evt.GetY())
for item in self.rectangles:
if item[1].Contains((x, y)):
self.tree.OnNodeClick(item[0], evt)
return
for item in self.knobs:
if item[1].Contains((x, y)):
self.tree.OnKnobClick(item[0])
return
evt.Skip()
class TreeModel:
"""
Interface for tree models
"""
def GetRoot(self):
raise NotImplementedError
def SetRoot(self, root):
raise NotImplementedError
def GetChildCount(self, node):
raise NotImplementedError
def GetChildAt(self, node, index):
raise NotImplementedError
def GetParent(self, node):
raise NotImplementedError
def AddChild(self, parent, child):
if hasattr(self, 'tree') and self.tree:
self.tree.NodeAdded(parent, child)
def RemoveNode(self, child):
if hasattr(self, 'tree') and self.tree:
self.tree.NodeRemoved(child)
def InsertChild(self, parent, child, index):
if hasattr(self, 'tree') and self.tree:
self.tree.NodeInserted(parent, child, index)
def IsLeaf(self, node):
raise NotImplementedError
def IsEditable(self, node):
return False
def SetEditable(self, node):
return False
class NodePainter:
"""
This is the interface expected of a nodepainter.
"""
def __init__(self, painter):
self.painter = painter
def Paint(self, node, dc, location = None):
"""
location should be provided only to draw in an unusual position
(not the node's normal position), otherwise the node's projected x and y
coordinates will be used.
"""
raise NotImplementedError
class LinePainter:
"""
The linepainter interface.
"""
def __init__(self, painter):
self.painter = painter
def Paint(self, parent, child, dc):
raise NotImplementedError
class TextConverter:
"""
TextConverter interface.
"""
def __init__(self, painter):
self.painter = painter
def Convert(node):
"""
Should return a string. The node argument will be an
MVCTreeNode.
"""
raise NotImplementedError
class BasicTreeModel(TreeModel):
"""
A very simple treemodel implementation, but flexible enough for many needs.
"""
def __init__(self):
self.children = {}
self.parents = {}
self.root = None
def GetRoot(self):
return self.root
def SetRoot(self, root):
self.root = root
def GetChildCount(self, node):
if self.children.has_key(node):
return len(self.children[node])
else:
return 0
def GetChildAt(self, node, index):
return self.children[node][index]
def GetParent(self, node):
return self.parents[node]
def AddChild(self, parent, child):
self.parents[child]=parent
if not self.children.has_key(parent):
self.children[parent]=[]
self.children[parent].append(child)
TreeModel.AddChild(self, parent, child)
return child
def RemoveNode(self, node):
parent = self.parents[node]
del self.parents[node]
self.children[parent].remove(node)
TreeModel.RemoveNode(self, node)
def InsertChild(self, parent, child, index):
self.parents[child]=parent
if not self.children.has_key(parent):
self.children[parent]=[]
self.children[parent].insert(child, index)
TreeModel.InsertChild(self, parent, child, index)
return child
def IsLeaf(self, node):
return not self.children.has_key(node)
def IsEditable(self, node):
return False
def SetEditable(self, node, bool):
return False
class FileEditor(Editor):
def Edit(self, node):
treenode = self.tree.nodemap[node]
self.editcomp = wxTextCtrl(self.tree, -1)
for rect in self.tree.painter.rectangles:
if rect[0] == treenode:
self.editcomp.SetPosition((rect[1][0], rect[1][1]))
break
self.editcomp.SetValue(node.fileName)
self.editcomp.SetSelection(0, len(node.fileName))
self.editcomp.SetFocus()
self.treenode = treenode
# self.editcomp.Bind(wx.EVT_KEY_DOWN, self._key)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -