From e395c057a357ea8e8fb54a161897e6c4fb27266d Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Fri, 19 Nov 1999 05:34:40 +0000 Subject: [PATCH] updated wxMVCTree, VTK, and the demo git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4629 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- utils/wxPython/README.txt | 9 + utils/wxPython/demo/Main.py | 4 +- utils/wxPython/demo/wxMVCTree.py | 61 ++++ utils/wxPython/demo/wxVTKRenderWindow.py | 60 ++++ utils/wxPython/lib/mvctree.py | 415 ++++++++++++----------- utils/wxPython/lib/vtk.py | 91 ++--- 6 files changed, 394 insertions(+), 246 deletions(-) create mode 100644 utils/wxPython/demo/wxMVCTree.py create mode 100644 utils/wxPython/demo/wxVTKRenderWindow.py diff --git a/utils/wxPython/README.txt b/utils/wxPython/README.txt index d884e91b57..11a9dfe696 100644 --- a/utils/wxPython/README.txt +++ b/utils/wxPython/README.txt @@ -45,6 +45,15 @@ Or you can send mail directly to the list using this address: ---------------------------------------------------------------------- +What's new in 2.1.12 +-------------------- +Updated wxMVCTree and added a demo for it. + +Added a wrapper class for the Visualization ToolKit (or VTK) in the +wxPython.lib.vtk module. (http://www.kitware.com/) + + + What's new in 2.1.11 -------------------- diff --git a/utils/wxPython/demo/Main.py b/utils/wxPython/demo/Main.py index 5df81877ac..3b474d0b09 100644 --- a/utils/wxPython/demo/Main.py +++ b/utils/wxPython/demo/Main.py @@ -21,6 +21,8 @@ _useSplitter = true _useNestedSplitter = true _treeList = [ + ('New since last release', ['wxMVCTree', 'wxVTKRenderWindow']), + ('Managed Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame']), ('Non-Managed Windows', ['wxGrid', 'wxSashWindow', @@ -47,7 +49,7 @@ _treeList = [ ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog', 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar', - 'PyShell', 'wxCalendar']), + 'PyShell', 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow']), ('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']), diff --git a/utils/wxPython/demo/wxMVCTree.py b/utils/wxPython/demo/wxMVCTree.py new file mode 100644 index 0000000000..8630080db0 --- /dev/null +++ b/utils/wxPython/demo/wxMVCTree.py @@ -0,0 +1,61 @@ + +import sys, os +from wxPython.wx import * +from wxPython.lib.mvctree import * + + +logger = None +def selchanging(evt): + logger.write("SelChanging!\n") + +def selchanged(evt): + logger.write("SelChange!\n") + logger.write(str(evt.node)) +def expanded(evt): + logger.write("Expanded\n") +def closed(evt): + logger.write("Closed!\n") +def key(evt): + logger.write("Key\n") +def add(evt): + logger.write("Add\n") +def delitem(evt): + logger.write("Delete\n") + +def runTest(frame, nb, log): + #f = wxFrame(frame, -1, "wxMVCTree", wxPoint(0,0), wxSize(200,500)) + global logger + logger = log + p = wxMVCTree(nb, -1) + p.SetAssumeChildren(true) + p.SetModel(LateFSTreeModel(os.path.normpath(os.getcwd() + os.sep +'..'))) + #Uncomment this to enable live filename editing! +# p.AddEditor(FileEditor(p)) + p.SetMultiSelect(true) + EVT_MVCTREE_SEL_CHANGING(p, p.GetId(), selchanging) + EVT_MVCTREE_SEL_CHANGED(p, p.GetId(), selchanged) + 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) + return p + +overview = """\ +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. + +Multiple selections are possible by holding down the Ctrl key. + +This demo shows the wxPython directory structure. The interesting part is that the tree model is late-bound to the filesystem, so the filenames are not retrieved until the directory is expanded. In mvctree.py are models for generic data, and both the early and late-bound filesystem models. + +There is also support for editing, though it's not enabled in this demo, to avoid accidentally renaming files! + +""" + + + + + + + + diff --git a/utils/wxPython/demo/wxVTKRenderWindow.py b/utils/wxPython/demo/wxVTKRenderWindow.py new file mode 100644 index 0000000000..eed4fd22e3 --- /dev/null +++ b/utils/wxPython/demo/wxVTKRenderWindow.py @@ -0,0 +1,60 @@ + +from wxPython.wx import * +try: + from wxPython.lib import vtk + haveVTK = true +except ImportError: + haveVTK = false + +#---------------------------------------------------------------------- + +def runTest(frame, nb, log): + if haveVTK: + win = vtk.wxVTKRenderWindow(nb, -1) + + # Get the render window + renWin = win.GetRenderWindow() + + # Next, do the VTK stuff + ren = vtk.vtkRenderer() + renWin.AddRenderer(ren) + cone = vtk.vtkConeSource() + cone.SetResolution(80) + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + ren.AddActor(coneActor) + coneMapper.GetLookupTable().Build() + + # Create a scalar bar + scalarBar = vtk.vtkScalarBarActor() + scalarBar.SetLookupTable(coneMapper.GetLookupTable()) + scalarBar.SetTitle("Temperature") + scalarBar.GetPositionCoordinate().SetCoordinateSystemToNormalizedViewport() + scalarBar.GetPositionCoordinate().SetValue(0.1, 0.01) + scalarBar.SetOrientationToHorizontal() + scalarBar.SetWidth(0.8) + scalarBar.SetHeight(0.17) + ren.AddActor2D(scalarBar) + + return win + + + else: + wxMessageBox("Unable to import VTK, which is a required component " + "of this demo. You need to download and install the " + "Python extension module for VTK from http://www.kitware.com/", + "Import Error") + return None + +#---------------------------------------------------------------------- + + +overview = """\ +wxVTKRenderWindow is a wrapper around the vtkRenderWindow from the +VTK Visualization Toolkit. The VTK Python extensions are required, +they can be obtained from http://www.kitware.com/ where you can also +find some nifty pictures and stuff. + +""" diff --git a/utils/wxPython/lib/mvctree.py b/utils/wxPython/lib/mvctree.py index 49eb4b7980..8c6dbfd593 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: @@ -94,6 +92,8 @@ class LayoutEngine: self.tree = tree def layout(self, node): raise NotImplementedError + def GetNodeList(self): + raise NotImplementedError class Transform: """ @@ -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() @@ -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) @@ -445,11 +454,19 @@ class StrTextConverter(TextConverter): return str(node.data) class NullTransform(Transform): + def GetSize(self): + return tuple(self.size) + 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) + 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): @@ -485,17 +502,27 @@ class TreeLayout(LayoutEngine): LayoutEngine.__init__(self, tree) self.NODE_STEP = 20 self.NODE_HEIGHT = 20 + self.nodelist = [] + def layout(self, node): + self.nodelist = [] + 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 +542,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 +557,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,60 +601,57 @@ 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): + def paintWalk(self, node, dc, paintRects=0): self.linePainter.paint(node.parent, node, dc) - self.nodePainter.paint(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): + 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))) @@ -612,7 +662,7 @@ class TreeLinePainter(LinePainter): 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 +670,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 +721,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 +766,22 @@ 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) + + 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 +792,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 +811,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,11 +825,10 @@ 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) @@ -793,6 +865,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 +890,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." @@ -909,7 +981,7 @@ class wxMVCTree(wxWindow): 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 +989,68 @@ 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 +1080,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.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 + 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() + diff --git a/utils/wxPython/lib/vtk.py b/utils/wxPython/lib/vtk.py index 66c1c4dfbb..0f01f64b26 100644 --- a/utils/wxPython/lib/vtk.py +++ b/utils/wxPython/lib/vtk.py @@ -109,49 +109,50 @@ class wxVTKRenderWindow(wxWindow): - -if __name__ == '__main__': - class TestFrame(wxFrame): - def __init__(self, parent): - wxFrame.__init__(self, parent, -1, "VTK Test", size=(450,450)) - - rw = wxVTKRenderWindow(self, -1) - - # Get the render window - renWin = rw.GetRenderWindow() - - # Next, do the VTK stuff - ren = vtkRenderer() - renWin.AddRenderer(ren) - cone = vtkConeSource() - cone.SetResolution(80) - coneMapper = vtkPolyDataMapper() - coneMapper.SetInput(cone.GetOutput()) - coneActor = vtkActor() - coneActor.SetMapper(coneMapper) - ren.AddActor(coneActor) - coneMapper.GetLookupTable().Build() - - # Create a scalar bar - scalarBar = vtkScalarBarActor() - scalarBar.SetLookupTable(coneMapper.GetLookupTable()) - scalarBar.SetTitle("Temperature") - scalarBar.GetPositionCoordinate().SetCoordinateSystemToNormalizedViewport() - scalarBar.GetPositionCoordinate().SetValue(0.1, 0.01) - scalarBar.SetOrientationToHorizontal() - scalarBar.SetWidth(0.8) - scalarBar.SetHeight(0.17) - ren.AddActor2D(scalarBar) - - - - class TestApp(wxApp): - def OnInit(self): - f = TestFrame(None) - self.SetTopWindow(f) - f.Show(true) - return true - - app = TestApp(0) - app.MainLoop() +## testcode is now in the demo ## + +## if __name__ == '__main__': +## class TestFrame(wxFrame): +## def __init__(self, parent): +## wxFrame.__init__(self, parent, -1, "VTK Test", size=(450,450)) + +## rw = wxVTKRenderWindow(self, -1) + +## # Get the render window +## renWin = rw.GetRenderWindow() + +## # Next, do the VTK stuff +## ren = vtkRenderer() +## renWin.AddRenderer(ren) +## cone = vtkConeSource() +## cone.SetResolution(80) +## coneMapper = vtkPolyDataMapper() +## coneMapper.SetInput(cone.GetOutput()) +## coneActor = vtkActor() +## coneActor.SetMapper(coneMapper) +## ren.AddActor(coneActor) +## coneMapper.GetLookupTable().Build() + +## # Create a scalar bar +## scalarBar = vtkScalarBarActor() +## scalarBar.SetLookupTable(coneMapper.GetLookupTable()) +## scalarBar.SetTitle("Temperature") +## scalarBar.GetPositionCoordinate().SetCoordinateSystemToNormalizedViewport() +## scalarBar.GetPositionCoordinate().SetValue(0.1, 0.01) +## scalarBar.SetOrientationToHorizontal() +## scalarBar.SetWidth(0.8) +## scalarBar.SetHeight(0.17) +## ren.AddActor2D(scalarBar) + + + +## class TestApp(wxApp): +## def OnInit(self): +## f = TestFrame(None) +## self.SetTopWindow(f) +## f.Show(true) +## return true + +## app = TestApp(0) +## app.MainLoop() -- 2.45.2