X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e19b71646053a07255b308b24321837f8ea76176..c4c829aeab7444df1374a0c93637eb1a2c0724d1:/utils/wxPython/lib/mvctree.py diff --git a/utils/wxPython/lib/mvctree.py b/utils/wxPython/lib/mvctree.py index 49eb4b7980..f268d9eb41 100644 --- a/utils/wxPython/lib/mvctree.py +++ b/utils/wxPython/lib/mvctree.py @@ -2,10 +2,8 @@ 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. @@ -24,7 +22,7 @@ Author/Maintainer - Bryn Keller #------------------------------------------------------------------------ from wxPython.wx import * -import os, sys +import os, sys, traceback #------------------------------------------------------------------------ class MVCTreeNode: @@ -92,7 +90,9 @@ class LayoutEngine: """ def __init__(self, tree): self.tree = tree - def layout(self, node): + def Layout(self, node): + raise NotImplementedError + def GetNodeList(self): raise NotImplementedError class Transform: @@ -101,7 +101,7 @@ 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 @@ -110,6 +110,13 @@ class Transform: """ 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 @@ -122,9 +129,7 @@ class Painter: 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 @@ -132,8 +137,11 @@ class Painter: 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 @@ -177,19 +185,20 @@ class Painter: 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() @@ -233,7 +242,7 @@ class NodePainter: """ 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 @@ -247,7 +256,7 @@ class LinePainter: """ def __init__(self, painter): self.painter = painter - def paint(self, parent, child, dc): + def Paint(self, parent, child, dc): raise NotImplementedError class TextConverter: @@ -256,7 +265,7 @@ 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. @@ -331,7 +340,8 @@ class FileEditor(Editor): 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() @@ -347,10 +357,11 @@ class FileEditor(Editor): 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): @@ -364,7 +375,6 @@ class FileEditor(Editor): 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) @@ -416,7 +426,6 @@ class LateFSTreeModel(FSTreeModel): 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) @@ -441,15 +450,23 @@ class LateFSTreeModel(FSTreeModel): 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): @@ -464,7 +481,7 @@ class Rect: 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: @@ -485,17 +502,28 @@ class TreeLayout(LayoutEngine): 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): """ @@ -515,7 +543,7 @@ 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): @@ -530,15 +558,41 @@ class TreePainter(Painter): 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): @@ -548,71 +602,68 @@ class TreePainter(Painter): 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) @@ -620,7 +671,7 @@ class TreeLinePainter(LinePainter): 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) @@ -671,27 +722,35 @@ class wxMVCTreeEvent(wxPyCommandEvent): 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() @@ -708,8 +767,23 @@ class wxMVCTree(wxWindow): 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 "" % str(hex(id(self))) @@ -720,15 +794,16 @@ class wxMVCTree(wxWindow): 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) @@ -738,7 +813,7 @@ class wxMVCTree(wxWindow): dc = wxClientDC(self) dc.SetFont(font) self.layout.SetHeight(dc.GetTextExtent("")[1] + 18) - + self.painter.ClearBuffer() def GetFont(self): return self.painter.GetFont() @@ -752,18 +827,17 @@ class wxMVCTree(wxWindow): 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 @@ -793,6 +867,7 @@ class wxMVCTree(wxWindow): self.currentRoot = self.layoutRoot self.offset = [0,0] self.rotation = 0 + self._scrollset = None self.Refresh() def GetCurrentRoot(self): @@ -817,12 +892,11 @@ class wxMVCTree(wxWindow): 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." @@ -902,14 +976,14 @@ class wxMVCTree(wxWindow): 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,) @@ -917,38 +991,69 @@ class wxMVCTree(wxWindow): 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): @@ -978,126 +1083,39 @@ class wxMVCTree(wxWindow): 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() +