wxMVCTree 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.
-This module contains the wxMVCTree class (the 'controller' of the MVC trio)
-and PathfinderNode, which it uses internally to manage its info.
-Pathfinder actually is even more configurable than MVC normally implies, because
+wxMVCTree actually is even more configurable than MVC normally implies, because
almost every aspect of it is pluggable:
wxMVCTree - Overall controller, and the window that actually gets placed
in the GUI.
#------------------------------------------------------------------------
from wxPython.wx import *
-import os, sys
+import os, sys, traceback
#------------------------------------------------------------------------
class MVCTreeNode:
"""
def __init__(self, tree):
self.tree = tree
- def layout(self, node):
+ def Layout(self, node):
+ raise NotImplementedError
+ def GetNodeList(self):
raise NotImplementedError
class Transform:
"""
def __init__(self, tree):
self.tree = tree
- def transform(self, node, offset, rotation):
+ 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
"""
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 wxMVCTree expects from painters. All painters should
self.fgcolor = wxNamedColour("BLUE")
self.linecolor = wxNamedColour("GREY")
self.font = wxFont(9, wxDEFAULT, wxNORMAL, wxNORMAL, false)
- self.knobs = []
- self.rectangles = []
- self.minx = self.maxx = self.miny = self.maxy = 0
+ self.bmp = None
def GetFont(self):
return self.font
def SetFont(self, font):
self.font = font
self.tree.Refresh()
-
- def paint(self, dc, node):
+ 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
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((evt.GetX(), evt.GetY())):
+ if item[1].Contains((x,y)):
self.tree.Edit(item[0].data)
self.tree.OnNodeClick(item[0], evt)
return
elif evt.ButtonDown():
- #self.oldpos = (evt.GetX(), evt.GetY())
+ x, y = self.tree.CalcUnscrolledPosition(evt.GetX(), evt.GetY())
for item in self.rectangles:
- if item[1].contains((evt.GetX(), evt.GetY())):
+ if item[1].Contains((x, y)):
self.tree.OnNodeClick(item[0], evt)
return
for item in self.knobs:
- if item[1].contains((evt.GetX(), evt.GetY())):
+ if item[1].Contains((x, y)):
self.tree.OnKnobClick(item[0])
return
evt.Skip()
"""
def __init__(self, painter):
self.painter = painter
- def paint(self, node, dc, location = None):
+ 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
"""
def __init__(self, painter):
self.painter = painter
- def paint(self, parent, child, dc):
+ def Paint(self, parent, child, dc):
raise NotImplementedError
class TextConverter:
"""
def __init__(self, painter):
self.painter = painter
- def convert(node):
+ def Convert(node):
"""
Should return a string. The node argument will be an
MVCTreeNode.
self.editcomp.SetSelection(0, len(node.fileName))
self.editcomp.SetFocus()
self.treenode = treenode
- EVT_KEY_DOWN(self.editcomp, self._key)
+# EVT_KEY_DOWN(self.editcomp, self._key)
+ EVT_KEY_UP(self.editcomp, self._key)
EVT_LEFT_DOWN(self.editcomp, self._mdown)
self.editcomp.CaptureMouse()
os.rename(node.path + os.sep + node.fileName, node.path + os.sep + self.editcomp.GetValue())
node.fileName = self.editcomp.GetValue()
except:
- import traceback;traceback.print_exc()
+ traceback.print_exc()
self.editcomp.ReleaseMouse()
self.editcomp.Destroy()
del self.editcomp
+ self.tree.Refresh()
def _key(self, evt):
def _mdown(self, evt):
if evt.IsButton():
pos = evt.GetPosition()
- print pos.x, pos.y
edsize = self.editcomp.GetSize()
if pos.x < 0 or pos.y < 0 or pos.x > edsize.width or pos.y > edsize.height:
self.EndEdit(false)
import string
name = string.split(path, os.sep)[-1]
pathpart = path[:-len(name)]
- print pathpart
fw = FileWrapper(pathpart, name)
self._Build(path, fw)
self.SetRoot(fw)
return not os.path.isdir(node.path + os.sep + node.fileName)
class StrTextConverter(TextConverter):
- def convert(self, node):
+ def Convert(self, node):
return str(node.data)
class NullTransform(Transform):
- def transform(self, node, offset, rotation):
- node.projx = node.x + offset[0]
- node.projy = node.y + offset[1]
- for kid in node.kids:
- self.transform(kid, offset, rotation)
+ def GetSize(self):
+ return tuple(self.size)
+
+ def Transform(self, node, offset, rotation):
+ self.size = [0,0]
+ list = self.tree.GetLayoutEngine().GetNodeList()
+ for node in list:
+ node.projx = node.x + offset[0]
+ node.projy = node.y + offset[1]
+ if node.projx > self.size[0]:
+ self.size[0] = node.projx
+ if node.projy > self.size[1]:
+ self.size[1] = node.projy
class Rect:
def __init__(self, x, y, width, height):
name = ['x', 'y', 'width', 'height'][index]
setattr(self, name, value)
- def contains(self, other):
+ def Contains(self, other):
if type(other) == type(()):
other = Rect(other[0], other[1], 0, 0)
if other.x >= self.x:
LayoutEngine.__init__(self, tree)
self.NODE_STEP = 20
self.NODE_HEIGHT = 20
- def layout(self, node):
+ self.nodelist = []
+
+ def Layout(self, node):
+ self.nodelist = []
+ self.NODE_HEIGHT = self.tree.GetFont().GetPointSize() * 2
+ self.layoutwalk(node)
+
+ def GetNodeList(self):
+ return self.nodelist
+
+ def layoutwalk(self, node):
if node == self.tree.currentRoot:
node.level = 1
self.lastY = (-self.NODE_HEIGHT)
node.x = self.NODE_STEP * node.level
node.y = self.lastY + self.NODE_HEIGHT
self.lastY = node.y
+ self.nodelist.append(node)
if node.expanded:
for kid in node.kids:
kid.level = node.level + 1
- self.layout(kid)
+ self.layoutwalk(kid)
class TreePainter(Painter):
"""
self.textConverter = textConverter
self.charWidths = []
- def paint(self, dc, node):
+ def Paint(self, dc, node, doubleBuffered=1, paintBackground=1):
if not self.charWidths:
self.charWidths = []
for i in range(25):
self.fgbrush = wxBrush(self.GetForegroundColour(), wxSOLID)
self.bgbrush = wxBrush(self.GetBackgroundColour(), wxSOLID)
self.linebrush = wxPen(self.GetLineColour(), 1, wxSOLID)
- self.rectangles = []
- self.knobs = []
+ treesize = self.tree.GetSize()
+ size = self.tree.transform.GetSize()
+ size = (max(treesize.width, size[0]+50), max(treesize.height, size[1]+50))
dc.BeginDrawing()
- dc.SetPen(self.GetBackgroundPen())
- dc.SetBrush(self.GetBackgroundBrush())
- size = self.tree.GetSize()
- dc.DrawRectangle(0, 0, size.width, size.height)
- if node:
- self.paintWalk(node, dc)
+ if doubleBuffered:
+ mem_dc = wxMemoryDC()
+ if not self.GetBuffer():
+ self.knobs = []
+ self.rectangles = []
+ self.bmp = wxEmptyBitmap(size[0], size[1])
+ mem_dc.SelectObject(self.GetBuffer())
+ mem_dc.SetPen(self.GetBackgroundPen())
+ mem_dc.SetBrush(self.GetBackgroundBrush())
+ mem_dc.DrawRectangle(0, 0, size[0], size[1])
+ mem_dc.SetFont(self.tree.GetFont())
+ self.paintWalk(node, mem_dc)
+ else:
+ mem_dc.SelectObject(self.GetBuffer())
+ xstart, ystart = self.tree.CalcUnscrolledPosition(0,0)
+ size = self.tree.GetClientSizeTuple()
+ dc.Blit(xstart, ystart, size[0], size[1], mem_dc, xstart, ystart)
+ else:
+ if node == self.tree.currentRoot:
+ self.knobs = []
+ self.rectangles = []
+ dc.SetPen(self.GetBackgroundPen())
+ dc.SetBrush(self.GetBackgroundBrush())
+ dc.SetFont(self.tree.GetFont())
+ if paintBackground:
+ dc.DrawRectangle(0, 0, size[0], size[1])
+ if node:
+ #Call with not paintBackground because if we are told not to paint the
+ #whole background, we have to paint in parts to undo selection coloring.
+ pb = paintBackground
+ self.paintWalk(node, dc, not pb)
dc.EndDrawing()
def GetDashPen(self):
Painter.SetLinePen(self, pen)
self.dashpen = wxPen(pen.GetColour(), 1, wxDOT)
- def drawBox(self, px, py, node, dc):
- if self.tree.model.IsLeaf(node.data) or ((node.expanded or not self.tree._assumeChildren) and not len(node.kids)):
- return
- dc.SetPen(self.linepen)
- dc.SetBrush(self.bgbrush)
- dc.DrawRectangle(px -4, py-4, 9, 9)
- self.knobs.append(node, Rect(px -4, py -4, 9, 9))
- dc.SetPen(self.textpen)
- if not node.expanded:
- dc.DrawLine(px, py -2, px, py + 3)
- dc.DrawLine(px -2, py, px + 3, py)
-
- def paintWalk(self, node, dc):
- self.linePainter.paint(node.parent, node, dc)
- self.nodePainter.paint(node, dc)
+ def paintWalk(self, node, dc, paintRects=0):
+ self.linePainter.Paint(node.parent, node, dc)
+ self.nodePainter.Paint(node, dc, drawRects = paintRects)
if node.expanded:
for kid in node.kids:
- if not self.paintWalk(kid, dc):
+ if not self.paintWalk(kid, dc, paintRects):
return false
for kid in node.kids:
px = (kid.projx - self.tree.layout.NODE_STEP) + 5
py = kid.projy + kid.height/2
- self.drawBox(px, py, kid, dc)
+ if (not self.tree.model.IsLeaf(kid.data)) or ((kid.expanded or self.tree._assumeChildren) and len(kid.kids)):
+ dc.SetPen(self.linepen)
+ dc.SetBrush(self.bgbrush)
+ dc.DrawRectangle(px -4, py-4, 9, 9)
+ self.knobs.append(kid, Rect(px -4, py -4, 9, 9))
+ dc.SetPen(self.textpen)
+ if not kid.expanded:
+ dc.DrawLine(px, py -2, px, py + 3)
+ dc.DrawLine(px -2, py, px + 3, py)
if node == self.tree.currentRoot:
px = (node.projx - self.tree.layout.NODE_STEP) + 5
py = node.projy + node.height/2
- self.drawBox(px, py, node, dc)
+ dc.SetPen(self.linepen)
+ dc.SetBrush(self.bgbrush)
+ dc.DrawRectangle(px -4, py-4, 9, 9)
+ self.knobs.append(node, Rect(px -4, py -4, 9, 9))
+ dc.SetPen(self.textpen)
+ if not node.expanded:
+ dc.DrawLine(px, py -2, px, py + 3)
+ dc.DrawLine(px -2, py, px + 3, py)
return true
def OnMouse(self, evt):
Painter.OnMouse(self, evt)
class TreeNodePainter(NodePainter):
- def paint(self, node, dc, location = None):
- text = self.painter.textConverter.convert(node)
+ def Paint(self, node, dc, location = None, drawRects = 0):
+ text = self.painter.textConverter.Convert(node)
extent = dc.GetTextExtent(text)
node.width = extent[0]
node.height = extent[1]
- if node == self.painter.tree.currentRoot:
- self.painter.minx = self.painter.maxx = self.painter.miny = self.painter.maxy = 0
- if node.projx < self.painter.minx:
- self.painter.minx = node.projx
- elif node.projx + node.width > self.painter.maxx:
- self.painter.maxx = node.projx + node.width
- if node.projy < self.painter.miny:
- self.painter.miny = node.projy
- elif node.projy + node.height > self.painter.maxy:
- self.painter.maxy = node.projy + node.height
if node.selected:
dc.SetPen(self.painter.GetLinePen())
dc.SetBrush(self.painter.GetForegroundBrush())
dc.SetTextForeground(wxNamedColour("WHITE"))
dc.DrawRectangle(node.projx -1, node.projy -1, node.width + 3, node.height + 3)
else:
+ if drawRects:
+ dc.SetBrush(self.painter.GetBackgroundBrush())
+ dc.SetPen(self.painter.GetBackgroundPen())
+ dc.DrawRectangle(node.projx -1, node.projy -1, node.width + 3, node.height + 3)
dc.SetTextForeground(self.painter.GetTextColour())
dc.DrawText(text, node.projx, node.projy)
self.painter.rectangles.append((node, Rect(node.projx, node.projy, node.width, node.height)))
class TreeLinePainter(LinePainter):
- def paint(self, parent, child, dc):
+ def Paint(self, parent, child, dc):
dc.SetPen(self.painter.GetDashPen())
px = py = cx = cy = 0
if parent is None or child == self.painter.tree.currentRoot:
px = (child.projx - self.painter.tree.layout.NODE_STEP) + 5
- py = child.projy + self.painter.tree.layout.NODE_HEIGHT/2
+ py = child.projy + self.painter.tree.layout.NODE_HEIGHT/2 -2
cx = child.projx
cy = py
dc.DrawLine(px, py, cx, cy)
px = parent.projx + 5
py = parent.projy + parent.height
cx = child.projx -5
- cy = child.projy + self.painter.tree.layout.NODE_HEIGHT/2
+ cy = child.projy + self.painter.tree.layout.NODE_HEIGHT/2 -3
dc.DrawLine(px, py, px, cy)
dc.DrawLine(px, cy, cx, cy)
self.node = node
self.nodes = nodes
self.keyEvent = keyEvent
-
+ def GetNode(self):
+ return self.node
+ def GetNodes(self):
+ return self.nodes
+ def getKeyEvent(self):
+ return self.keyEvent
class wxMVCTreeNotifyEvent(wxMVCTreeEvent):
def __init__(self, type, id, node = None, nodes = None, **kwargs):
apply(wxMVCTreeEvent.__init__, (self, type, id), kwargs)
self.notify = wxNotifyEvent(type, id)
+ def getNotifyEvent(self):
+ return self.notify
-class wxMVCTree(wxWindow):
+class wxMVCTree(wxScrolledWindow):
"""
- The main mvcTree class.
+ The main mvc tree class.
"""
def __init__(self, parent, id, model = None, layout = None, transform = None,
painter = None, *args, **kwargs):
- apply(wxWindow.__init__, (self, parent, id), kwargs)
+ apply(wxScrolledWindow.__init__, (self, parent, id), kwargs)
self.nodemap = {}
self._multiselect = false
self._selections = []
self._assumeChildren = false
self._scrollx = false
self._scrolly = false
- self.doubleBuffered = true
+ self.doubleBuffered = false
+ self._lastPhysicalSize = self.GetSize()
self._editors = []
if not model:
model = BasicTreeModel()
self.painter = painter
self.SetFont(wxFont(9, wxDEFAULT, wxNORMAL, wxNORMAL, false))
EVT_MOUSE_EVENTS(self, self.OnMouse)
- EVT_SCROLLWIN(self, self.OnScroll)
EVT_KEY_DOWN(self, self.OnKeyDown)
+ self.doubleBuffered = true
+
+ def Refresh(self):
+ if self.doubleBuffered:
+ self.painter.ClearBuffer()
+ wxScrolledWindow.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 "<wxMVCTree instance at %s>" % str(hex(id(self)))
def NodeAdded(self, parent, child):
e = wxMVCTreeEvent(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 = wxMVCTreeEvent(wxEVT_MVCTREE_ADD_ITEM, self.GetId(), node = child, nodes = [parent, child])
self.GetEventHandler().ProcessEvent(e)
-
+ self.painter.ClearBuffer()
def NodeRemoved(self, node):
e = wxMVCTreeEvent(wxEVT_MVCTREE_DELETE_ITEM, self.GetId(), node = child, nodes = [parent, child])
self.GetEventHandler().ProcessEvent(e)
-
+ self.painter.ClearBuffer()
def OnKeyDown(self, evt):
e = wxMVCTreeEvent(wxEVT_MVCTREE_KEY_DOWN, self.GetId(), keyEvent = evt)
self.GetEventHandler().ProcessEvent(e)
dc = wxClientDC(self)
dc.SetFont(font)
self.layout.SetHeight(dc.GetTextExtent("")[1] + 18)
-
+ self.painter.ClearBuffer()
def GetFont(self):
return self.painter.GetFont()
self.painter.OnMouse(evt)
def OnNodeClick(self, node, mouseEvent):
- if node.selected:
+ if node.selected and (self.IsMultiSelect() and mouseEvent.ControlDown()):
self.RemoveFromSelection(node.data)
else:
- self.AddToSelection(node.data, mouseEvent.ControlDown())
- self.Refresh()
+ 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)
+ return self.painter.textConverter.Convert(treenode)
def IsDoubleBuffered(self):
return self.doubleBuffered
self.currentRoot = self.layoutRoot
self.offset = [0,0]
self.rotation = 0
+ self._scrollset = None
self.Refresh()
def GetCurrentRoot(self):
pass
def OnSize(self, evt):
- try:
- size = self.GetSizeTuple()
- self.center = (size[0]/2, size[1]/2)
- del self.bmp
- except:
- pass
+ 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."
else:
e = wxMVCTreeEvent(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.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):
+ def AddToSelection(self, nodeOrTuple, enableMulti = true, shiftMulti = false):
nodeTuple = nodeOrTuple
if type(nodeOrTuple)!= type(()):
nodeTuple = (nodeOrTuple,)
self.GetEventHandler().ProcessEvent(e)
if not e.notify.IsAllowed():
return
- if not self.IsMultiSelect() or not enableMulti:
+ 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:
- for node in nodeTuple:
- try:
- self._selections.index(node)
- except ValueError:
- self._selections.append(node)
+ if shiftMulti:
+ for node in nodeTuple:
treenode = self.nodemap[node]
- treenode.selected = true
+ 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 = wxMVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), nodeTuple[0], nodes = nodeTuple)
self.GetEventHandler().ProcessEvent(e)
+ dc = wxClientDC(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:
- try:
- self._selections.index(node)
- except IndexError:
- self._selections.remove(node)
- treenode = self.nodemap[node]
- node.selected = false
+ self._selections.remove(node)
+ treenode = self.nodemap[node]
+ changeparents.append(treenode)
+ treenode.selected = false
e = wxMVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), node, nodes = nodeTuple)
self.GetEventHandler().ProcessEvent(e)
-
+ dc = wxClientDC(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):
def GetAssumeChildren(self):
return self._assumeChildren
- def OnScroll(self, evt):
- type = evt.GetEventType()
- field = [self.painter.maxx - self.painter.minx, self.painter.maxy - self.painter.miny]
- size = self.GetSizeTuple()
- index = 1
- if evt.GetOrientation() == wxHORIZONTAL:
- index = 0
- self._scrollx = true
- else:
- self._scrolly = true
- index = 1
- if type == wxEVT_SCROLLWIN_TOP:
- self.offset[index] = 0
- elif type == wxEVT_SCROLLWIN_LINEUP:
- self.offset[index] = self.offset[index] + 1
- elif type == wxEVT_SCROLLWIN_LINEDOWN:
- self.offset[index] = self.offset[index] - 1
- elif type == wxEVT_SCROLLWIN_PAGEUP:
- self.offset[index] = self.offset[index] + int(20 * float(field[index])/float(size[index]))
- elif type == wxEVT_SCROLLWIN_PAGEDOWN:
- self.offset[index] = self.offset[index] - int(20 * float(field[index])/float(size[index]))
- elif type == wxEVT_SCROLLWIN_THUMBTRACK:
- self.offset[index] = -(evt.GetPosition())
- elif type == wxEVT_SCROLLWIN_BOTTOM:
- self.offset[index] = field[index]
- self.transformed = false
- self.Refresh()
-
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.layout.Layout(self.currentRoot)
self.laidOut = true
+ self.transformed = false
if not self.transformed:
- self.transform.transform(self.currentRoot, self.offset, self.rotation)
+ 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
+ size = self.GetSizeTuple()
+ if tsize[0] > size[0] or tsize[1] > size[1]:
+ if not hasattr(self, '_oldsize') or (tsize[0] > self._oldsize[0] or tsize[1] > self._oldsize[1]):
+ self._oldsize = tsize
+ oldstart = self.ViewStart()
+ self._lastPhysicalSize = self.GetSize()
+ self.SetScrollbars(10, 10, tsize[0]/10, tsize[1]/10)
+ self.Scroll(oldstart[0], oldstart[1])
dc = wxPaintDC(self)
+ self.PrepareDC(dc)
dc.SetFont(self.GetFont())
- if self.doubleBuffered:
- size = self.GetSize()
- if not hasattr(self, 'bmp'):
- self.bmp = bmp =wxEmptyBitmap(size.width, size.height)
- else:
- bmp = self.bmp
- mem_dc = wxMemoryDC()
- mem_dc.SetFont(self.GetFont())
- mem_dc.SelectObject(bmp)
- self.painter.paint(mem_dc, self.currentRoot)
- dc.Blit(0, 0, size.width, size.height, mem_dc, 0, 0);
- else:
- self.painter.paint(dc, self.currentRoot)
- size = self.GetSizeTuple()
- if self._scrollx or self.painter.minx < 0 or self.painter.maxx > size[0]:
- field = self.painter.maxx - self.painter.minx
- self.SetScrollbar(wxHORIZONTAL, -self.offset[0], size[0]/field, field, true)
- self._scrollx = false
- if self._scrolly or self.painter.miny < 0 or self.painter.maxy > size[1]:
- field = self.painter.maxy - self.painter.miny
- self.SetScrollbar(wxVERTICAL, -self.offset[1], size[1]/field, field, true)
- self._scrolly = false
+ self.painter.Paint(dc, self.currentRoot, self.doubleBuffered)
except:
- import traceback;traceback.print_exc()
-
-if __name__ == '__main__':
- def exit(evt):
- import sys;sys.exit()
-
- block = 0
-
- def selchanging(evt):
- print "SelChanging!"
- print evt.node
- global block
- if block:
- evt.notify.Veto()
- block = not block
-
- def selchanged(evt):
- print "SelChange!"
- print evt.node
- def expanded(evt):
- print "Expanded!"
- def closed(evt):
- print "Closed!"
- def key(evt):
- print "Key"
- def add(evt):
- print "Add"
- def delitem(evt):
- print "Delete"
-
- class MyApp(wxApp):
- def OnInit(self):
- f = wxFrame(NULL, -1, "wxMVCTree")
- p = None
- p = wxMVCTree(f, -1)
- p.SetAssumeChildren(true)
- if len(sys.argv) > 1:
- p.SetModel(LateFSTreeModel(sys.argv[1]))
- p.AddEditor(FileEditor(p))
- p.SetMultiSelect(true)
- f.Show(true)
- EVT_CLOSE(f, exit)
- EVT_MVCTREE_SEL_CHANGED(p, p.GetId(), selchanged)
- EVT_MVCTREE_SEL_CHANGING(p, p.GetId(), selchanging)
- EVT_MVCTREE_ITEM_EXPANDED(p, p.GetId(), expanded)
- EVT_MVCTREE_ITEM_COLLAPSED(p, p.GetId(), closed)
- EVT_MVCTREE_ADD_ITEM(p, p.GetId(), add)
- EVT_MVCTREE_DELETE_ITEM(p, p.GetId(), delitem)
- EVT_MVCTREE_KEY_DOWN(p, p.GetId(), key)
- p.SetForegroundColour(wxNamedColour("GREEN"))
- self.SetTopWindow(f)
- return true
-
- app = MyApp(false)
- app.MainLoop()
+ traceback.print_exc()
+