updated wxMVCTree, VTK, and the demo
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4629 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -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
|
What's new in 2.1.11
|
||||||
--------------------
|
--------------------
|
||||||
|
@@ -21,6 +21,8 @@ _useSplitter = true
|
|||||||
_useNestedSplitter = true
|
_useNestedSplitter = true
|
||||||
|
|
||||||
_treeList = [
|
_treeList = [
|
||||||
|
('New since last release', ['wxMVCTree', 'wxVTKRenderWindow']),
|
||||||
|
|
||||||
('Managed Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame']),
|
('Managed Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame']),
|
||||||
|
|
||||||
('Non-Managed Windows', ['wxGrid', 'wxSashWindow',
|
('Non-Managed Windows', ['wxGrid', 'wxSashWindow',
|
||||||
@@ -47,7 +49,7 @@ _treeList = [
|
|||||||
|
|
||||||
('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
|
('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
|
||||||
'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
|
'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
|
||||||
'PyShell', 'wxCalendar']),
|
'PyShell', 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow']),
|
||||||
|
|
||||||
('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']),
|
('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']),
|
||||||
|
|
||||||
|
61
utils/wxPython/demo/wxMVCTree.py
Normal file
61
utils/wxPython/demo/wxMVCTree.py
Normal file
@@ -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!
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
60
utils/wxPython/demo/wxVTKRenderWindow.py
Normal file
60
utils/wxPython/demo/wxVTKRenderWindow.py
Normal file
@@ -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.
|
||||||
|
|
||||||
|
"""
|
@@ -2,10 +2,8 @@
|
|||||||
wxMVCTree is a control which handles hierarchical data. It is constructed
|
wxMVCTree is a control which handles hierarchical data. It is constructed
|
||||||
in model-view-controller architecture, so the display of that data, and
|
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.
|
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:
|
almost every aspect of it is pluggable:
|
||||||
wxMVCTree - Overall controller, and the window that actually gets placed
|
wxMVCTree - Overall controller, and the window that actually gets placed
|
||||||
in the GUI.
|
in the GUI.
|
||||||
@@ -24,7 +22,7 @@ Author/Maintainer - Bryn Keller <xoltar@starship.python.net>
|
|||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
from wxPython.wx import *
|
from wxPython.wx import *
|
||||||
import os, sys
|
import os, sys, traceback
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
|
|
||||||
class MVCTreeNode:
|
class MVCTreeNode:
|
||||||
@@ -94,6 +92,8 @@ class LayoutEngine:
|
|||||||
self.tree = tree
|
self.tree = tree
|
||||||
def layout(self, node):
|
def layout(self, node):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
def GetNodeList(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
class Transform:
|
class Transform:
|
||||||
"""
|
"""
|
||||||
@@ -110,6 +110,13 @@ class Transform:
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def GetSize(self):
|
||||||
|
"""
|
||||||
|
Returns the size of the entire tree as laid out and transformed
|
||||||
|
as a tuple
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
class Painter:
|
class Painter:
|
||||||
"""
|
"""
|
||||||
This is the interface that wxMVCTree expects from painters. All painters should
|
This is the interface that wxMVCTree expects from painters. All painters should
|
||||||
@@ -122,9 +129,7 @@ class Painter:
|
|||||||
self.fgcolor = wxNamedColour("BLUE")
|
self.fgcolor = wxNamedColour("BLUE")
|
||||||
self.linecolor = wxNamedColour("GREY")
|
self.linecolor = wxNamedColour("GREY")
|
||||||
self.font = wxFont(9, wxDEFAULT, wxNORMAL, wxNORMAL, false)
|
self.font = wxFont(9, wxDEFAULT, wxNORMAL, wxNORMAL, false)
|
||||||
self.knobs = []
|
self.bmp = None
|
||||||
self.rectangles = []
|
|
||||||
self.minx = self.maxx = self.miny = self.maxy = 0
|
|
||||||
|
|
||||||
def GetFont(self):
|
def GetFont(self):
|
||||||
return self.font
|
return self.font
|
||||||
@@ -132,8 +137,11 @@ class Painter:
|
|||||||
def SetFont(self, font):
|
def SetFont(self, font):
|
||||||
self.font = font
|
self.font = font
|
||||||
self.tree.Refresh()
|
self.tree.Refresh()
|
||||||
|
def GetBuffer(self):
|
||||||
def paint(self, dc, node):
|
return self.bmp
|
||||||
|
def ClearBuffer(self):
|
||||||
|
self.bmp = None
|
||||||
|
def paint(self, dc, node, doubleBuffered=1, paintBackground=1):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
def GetTextColour(self):
|
def GetTextColour(self):
|
||||||
return self.textcolor
|
return self.textcolor
|
||||||
@@ -177,19 +185,20 @@ class Painter:
|
|||||||
return self.linebrush
|
return self.linebrush
|
||||||
def OnMouse(self, evt):
|
def OnMouse(self, evt):
|
||||||
if evt.LeftDClick():
|
if evt.LeftDClick():
|
||||||
|
x, y = self.tree.CalcUnscrolledPosition(evt.GetX(), evt.GetY())
|
||||||
for item in self.rectangles:
|
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.Edit(item[0].data)
|
||||||
self.tree.OnNodeClick(item[0], evt)
|
self.tree.OnNodeClick(item[0], evt)
|
||||||
return
|
return
|
||||||
elif evt.ButtonDown():
|
elif evt.ButtonDown():
|
||||||
#self.oldpos = (evt.GetX(), evt.GetY())
|
x, y = self.tree.CalcUnscrolledPosition(evt.GetX(), evt.GetY())
|
||||||
for item in self.rectangles:
|
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)
|
self.tree.OnNodeClick(item[0], evt)
|
||||||
return
|
return
|
||||||
for item in self.knobs:
|
for item in self.knobs:
|
||||||
if item[1].contains((evt.GetX(), evt.GetY())):
|
if item[1].contains((x, y)):
|
||||||
self.tree.OnKnobClick(item[0])
|
self.tree.OnKnobClick(item[0])
|
||||||
return
|
return
|
||||||
evt.Skip()
|
evt.Skip()
|
||||||
@@ -331,7 +340,8 @@ class FileEditor(Editor):
|
|||||||
self.editcomp.SetSelection(0, len(node.fileName))
|
self.editcomp.SetSelection(0, len(node.fileName))
|
||||||
self.editcomp.SetFocus()
|
self.editcomp.SetFocus()
|
||||||
self.treenode = treenode
|
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)
|
EVT_LEFT_DOWN(self.editcomp, self._mdown)
|
||||||
self.editcomp.CaptureMouse()
|
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())
|
os.rename(node.path + os.sep + node.fileName, node.path + os.sep + self.editcomp.GetValue())
|
||||||
node.fileName = self.editcomp.GetValue()
|
node.fileName = self.editcomp.GetValue()
|
||||||
except:
|
except:
|
||||||
import traceback;traceback.print_exc()
|
traceback.print_exc()
|
||||||
self.editcomp.ReleaseMouse()
|
self.editcomp.ReleaseMouse()
|
||||||
self.editcomp.Destroy()
|
self.editcomp.Destroy()
|
||||||
del self.editcomp
|
del self.editcomp
|
||||||
|
self.tree.Refresh()
|
||||||
|
|
||||||
|
|
||||||
def _key(self, evt):
|
def _key(self, evt):
|
||||||
@@ -364,7 +375,6 @@ class FileEditor(Editor):
|
|||||||
def _mdown(self, evt):
|
def _mdown(self, evt):
|
||||||
if evt.IsButton():
|
if evt.IsButton():
|
||||||
pos = evt.GetPosition()
|
pos = evt.GetPosition()
|
||||||
print pos.x, pos.y
|
|
||||||
edsize = self.editcomp.GetSize()
|
edsize = self.editcomp.GetSize()
|
||||||
if pos.x < 0 or pos.y < 0 or pos.x > edsize.width or pos.y > edsize.height:
|
if pos.x < 0 or pos.y < 0 or pos.x > edsize.width or pos.y > edsize.height:
|
||||||
self.EndEdit(false)
|
self.EndEdit(false)
|
||||||
@@ -416,7 +426,6 @@ class LateFSTreeModel(FSTreeModel):
|
|||||||
import string
|
import string
|
||||||
name = string.split(path, os.sep)[-1]
|
name = string.split(path, os.sep)[-1]
|
||||||
pathpart = path[:-len(name)]
|
pathpart = path[:-len(name)]
|
||||||
print pathpart
|
|
||||||
fw = FileWrapper(pathpart, name)
|
fw = FileWrapper(pathpart, name)
|
||||||
self._Build(path, fw)
|
self._Build(path, fw)
|
||||||
self.SetRoot(fw)
|
self.SetRoot(fw)
|
||||||
@@ -445,11 +454,19 @@ class StrTextConverter(TextConverter):
|
|||||||
return str(node.data)
|
return str(node.data)
|
||||||
|
|
||||||
class NullTransform(Transform):
|
class NullTransform(Transform):
|
||||||
|
def GetSize(self):
|
||||||
|
return tuple(self.size)
|
||||||
|
|
||||||
def transform(self, node, offset, rotation):
|
def transform(self, node, offset, rotation):
|
||||||
node.projx = node.x + offset[0]
|
self.size = [0,0]
|
||||||
node.projy = node.y + offset[1]
|
list = self.tree.GetLayoutEngine().GetNodeList()
|
||||||
for kid in node.kids:
|
for node in list:
|
||||||
self.transform(kid, offset, rotation)
|
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:
|
class Rect:
|
||||||
def __init__(self, x, y, width, height):
|
def __init__(self, x, y, width, height):
|
||||||
@@ -485,17 +502,27 @@ class TreeLayout(LayoutEngine):
|
|||||||
LayoutEngine.__init__(self, tree)
|
LayoutEngine.__init__(self, tree)
|
||||||
self.NODE_STEP = 20
|
self.NODE_STEP = 20
|
||||||
self.NODE_HEIGHT = 20
|
self.NODE_HEIGHT = 20
|
||||||
|
self.nodelist = []
|
||||||
|
|
||||||
def layout(self, node):
|
def layout(self, node):
|
||||||
|
self.nodelist = []
|
||||||
|
self.layoutwalk(node)
|
||||||
|
|
||||||
|
def GetNodeList(self):
|
||||||
|
return self.nodelist
|
||||||
|
|
||||||
|
def layoutwalk(self, node):
|
||||||
if node == self.tree.currentRoot:
|
if node == self.tree.currentRoot:
|
||||||
node.level = 1
|
node.level = 1
|
||||||
self.lastY = (-self.NODE_HEIGHT)
|
self.lastY = (-self.NODE_HEIGHT)
|
||||||
node.x = self.NODE_STEP * node.level
|
node.x = self.NODE_STEP * node.level
|
||||||
node.y = self.lastY + self.NODE_HEIGHT
|
node.y = self.lastY + self.NODE_HEIGHT
|
||||||
self.lastY = node.y
|
self.lastY = node.y
|
||||||
|
self.nodelist.append(node)
|
||||||
if node.expanded:
|
if node.expanded:
|
||||||
for kid in node.kids:
|
for kid in node.kids:
|
||||||
kid.level = node.level + 1
|
kid.level = node.level + 1
|
||||||
self.layout(kid)
|
self.layoutwalk(kid)
|
||||||
|
|
||||||
class TreePainter(Painter):
|
class TreePainter(Painter):
|
||||||
"""
|
"""
|
||||||
@@ -515,7 +542,7 @@ class TreePainter(Painter):
|
|||||||
self.textConverter = textConverter
|
self.textConverter = textConverter
|
||||||
self.charWidths = []
|
self.charWidths = []
|
||||||
|
|
||||||
def paint(self, dc, node):
|
def paint(self, dc, node, doubleBuffered=1, paintBackground=1):
|
||||||
if not self.charWidths:
|
if not self.charWidths:
|
||||||
self.charWidths = []
|
self.charWidths = []
|
||||||
for i in range(25):
|
for i in range(25):
|
||||||
@@ -530,15 +557,41 @@ class TreePainter(Painter):
|
|||||||
self.fgbrush = wxBrush(self.GetForegroundColour(), wxSOLID)
|
self.fgbrush = wxBrush(self.GetForegroundColour(), wxSOLID)
|
||||||
self.bgbrush = wxBrush(self.GetBackgroundColour(), wxSOLID)
|
self.bgbrush = wxBrush(self.GetBackgroundColour(), wxSOLID)
|
||||||
self.linebrush = wxPen(self.GetLineColour(), 1, wxSOLID)
|
self.linebrush = wxPen(self.GetLineColour(), 1, wxSOLID)
|
||||||
self.rectangles = []
|
treesize = self.tree.GetSize()
|
||||||
self.knobs = []
|
size = self.tree.transform.GetSize()
|
||||||
|
size = (max(treesize.width, size[0]+50), max(treesize.height, size[1]+50))
|
||||||
dc.BeginDrawing()
|
dc.BeginDrawing()
|
||||||
dc.SetPen(self.GetBackgroundPen())
|
if doubleBuffered:
|
||||||
dc.SetBrush(self.GetBackgroundBrush())
|
mem_dc = wxMemoryDC()
|
||||||
size = self.tree.GetSize()
|
if not self.GetBuffer():
|
||||||
dc.DrawRectangle(0, 0, size.width, size.height)
|
self.knobs = []
|
||||||
if node:
|
self.rectangles = []
|
||||||
self.paintWalk(node, dc)
|
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()
|
dc.EndDrawing()
|
||||||
|
|
||||||
def GetDashPen(self):
|
def GetDashPen(self):
|
||||||
@@ -548,60 +601,57 @@ class TreePainter(Painter):
|
|||||||
Painter.SetLinePen(self, pen)
|
Painter.SetLinePen(self, pen)
|
||||||
self.dashpen = wxPen(pen.GetColour(), 1, wxDOT)
|
self.dashpen = wxPen(pen.GetColour(), 1, wxDOT)
|
||||||
|
|
||||||
def drawBox(self, px, py, node, dc):
|
def paintWalk(self, node, dc, paintRects=0):
|
||||||
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.linePainter.paint(node.parent, node, dc)
|
||||||
self.nodePainter.paint(node, dc)
|
self.nodePainter.paint(node, dc, drawRects = paintRects)
|
||||||
if node.expanded:
|
if node.expanded:
|
||||||
for kid in node.kids:
|
for kid in node.kids:
|
||||||
if not self.paintWalk(kid, dc):
|
if not self.paintWalk(kid, dc, paintRects):
|
||||||
return false
|
return false
|
||||||
for kid in node.kids:
|
for kid in node.kids:
|
||||||
px = (kid.projx - self.tree.layout.NODE_STEP) + 5
|
px = (kid.projx - self.tree.layout.NODE_STEP) + 5
|
||||||
py = kid.projy + kid.height/2
|
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:
|
if node == self.tree.currentRoot:
|
||||||
px = (node.projx - self.tree.layout.NODE_STEP) + 5
|
px = (node.projx - self.tree.layout.NODE_STEP) + 5
|
||||||
py = node.projy + node.height/2
|
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
|
return true
|
||||||
|
|
||||||
def OnMouse(self, evt):
|
def OnMouse(self, evt):
|
||||||
Painter.OnMouse(self, evt)
|
Painter.OnMouse(self, evt)
|
||||||
|
|
||||||
class TreeNodePainter(NodePainter):
|
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)
|
text = self.painter.textConverter.convert(node)
|
||||||
extent = dc.GetTextExtent(text)
|
extent = dc.GetTextExtent(text)
|
||||||
node.width = extent[0]
|
node.width = extent[0]
|
||||||
node.height = extent[1]
|
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:
|
if node.selected:
|
||||||
dc.SetPen(self.painter.GetLinePen())
|
dc.SetPen(self.painter.GetLinePen())
|
||||||
dc.SetBrush(self.painter.GetForegroundBrush())
|
dc.SetBrush(self.painter.GetForegroundBrush())
|
||||||
dc.SetTextForeground(wxNamedColour("WHITE"))
|
dc.SetTextForeground(wxNamedColour("WHITE"))
|
||||||
dc.DrawRectangle(node.projx -1, node.projy -1, node.width + 3, node.height + 3)
|
dc.DrawRectangle(node.projx -1, node.projy -1, node.width + 3, node.height + 3)
|
||||||
else:
|
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.SetTextForeground(self.painter.GetTextColour())
|
||||||
dc.DrawText(text, node.projx, node.projy)
|
dc.DrawText(text, node.projx, node.projy)
|
||||||
self.painter.rectangles.append((node, Rect(node.projx, node.projy, node.width, node.height)))
|
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
|
px = py = cx = cy = 0
|
||||||
if parent is None or child == self.painter.tree.currentRoot:
|
if parent is None or child == self.painter.tree.currentRoot:
|
||||||
px = (child.projx - self.painter.tree.layout.NODE_STEP) + 5
|
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
|
cx = child.projx
|
||||||
cy = py
|
cy = py
|
||||||
dc.DrawLine(px, py, cx, cy)
|
dc.DrawLine(px, py, cx, cy)
|
||||||
@@ -620,7 +670,7 @@ class TreeLinePainter(LinePainter):
|
|||||||
px = parent.projx + 5
|
px = parent.projx + 5
|
||||||
py = parent.projy + parent.height
|
py = parent.projy + parent.height
|
||||||
cx = child.projx -5
|
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, py, px, cy)
|
||||||
dc.DrawLine(px, cy, cx, cy)
|
dc.DrawLine(px, cy, cx, cy)
|
||||||
|
|
||||||
@@ -671,27 +721,35 @@ class wxMVCTreeEvent(wxPyCommandEvent):
|
|||||||
self.node = node
|
self.node = node
|
||||||
self.nodes = nodes
|
self.nodes = nodes
|
||||||
self.keyEvent = keyEvent
|
self.keyEvent = keyEvent
|
||||||
|
def GetNode(self):
|
||||||
|
return self.node
|
||||||
|
def GetNodes(self):
|
||||||
|
return self.nodes
|
||||||
|
def getKeyEvent(self):
|
||||||
|
return self.keyEvent
|
||||||
|
|
||||||
class wxMVCTreeNotifyEvent(wxMVCTreeEvent):
|
class wxMVCTreeNotifyEvent(wxMVCTreeEvent):
|
||||||
def __init__(self, type, id, node = None, nodes = None, **kwargs):
|
def __init__(self, type, id, node = None, nodes = None, **kwargs):
|
||||||
apply(wxMVCTreeEvent.__init__, (self, type, id), kwargs)
|
apply(wxMVCTreeEvent.__init__, (self, type, id), kwargs)
|
||||||
self.notify = wxNotifyEvent(type, id)
|
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,
|
def __init__(self, parent, id, model = None, layout = None, transform = None,
|
||||||
painter = None, *args, **kwargs):
|
painter = None, *args, **kwargs):
|
||||||
apply(wxWindow.__init__, (self, parent, id), kwargs)
|
apply(wxScrolledWindow.__init__, (self, parent, id), kwargs)
|
||||||
self.nodemap = {}
|
self.nodemap = {}
|
||||||
self._multiselect = false
|
self._multiselect = false
|
||||||
self._selections = []
|
self._selections = []
|
||||||
self._assumeChildren = false
|
self._assumeChildren = false
|
||||||
self._scrollx = false
|
self._scrollx = false
|
||||||
self._scrolly = false
|
self._scrolly = false
|
||||||
self.doubleBuffered = true
|
self.doubleBuffered = false
|
||||||
|
self._lastPhysicalSize = self.GetSize()
|
||||||
self._editors = []
|
self._editors = []
|
||||||
if not model:
|
if not model:
|
||||||
model = BasicTreeModel()
|
model = BasicTreeModel()
|
||||||
@@ -708,8 +766,22 @@ class wxMVCTree(wxWindow):
|
|||||||
self.painter = painter
|
self.painter = painter
|
||||||
self.SetFont(wxFont(9, wxDEFAULT, wxNORMAL, wxNORMAL, false))
|
self.SetFont(wxFont(9, wxDEFAULT, wxNORMAL, wxNORMAL, false))
|
||||||
EVT_MOUSE_EVENTS(self, self.OnMouse)
|
EVT_MOUSE_EVENTS(self, self.OnMouse)
|
||||||
EVT_SCROLLWIN(self, self.OnScroll)
|
|
||||||
EVT_KEY_DOWN(self, self.OnKeyDown)
|
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):
|
def __repr__(self):
|
||||||
return "<wxMVCTree instance at %s>" % str(hex(id(self)))
|
return "<wxMVCTree instance at %s>" % str(hex(id(self)))
|
||||||
@@ -720,15 +792,16 @@ class wxMVCTree(wxWindow):
|
|||||||
def NodeAdded(self, parent, child):
|
def NodeAdded(self, parent, child):
|
||||||
e = wxMVCTreeEvent(wxEVT_MVCTREE_ADD_ITEM, self.GetId(), node = child, nodes = [parent, child])
|
e = wxMVCTreeEvent(wxEVT_MVCTREE_ADD_ITEM, self.GetId(), node = child, nodes = [parent, child])
|
||||||
self.GetEventHandler().ProcessEvent(e)
|
self.GetEventHandler().ProcessEvent(e)
|
||||||
|
self.painter.ClearBuffer()
|
||||||
|
|
||||||
def NodeInserted(self, parent, child, index):
|
def NodeInserted(self, parent, child, index):
|
||||||
e = wxMVCTreeEvent(wxEVT_MVCTREE_ADD_ITEM, self.GetId(), node = child, nodes = [parent, child])
|
e = wxMVCTreeEvent(wxEVT_MVCTREE_ADD_ITEM, self.GetId(), node = child, nodes = [parent, child])
|
||||||
self.GetEventHandler().ProcessEvent(e)
|
self.GetEventHandler().ProcessEvent(e)
|
||||||
|
self.painter.ClearBuffer()
|
||||||
def NodeRemoved(self, node):
|
def NodeRemoved(self, node):
|
||||||
e = wxMVCTreeEvent(wxEVT_MVCTREE_DELETE_ITEM, self.GetId(), node = child, nodes = [parent, child])
|
e = wxMVCTreeEvent(wxEVT_MVCTREE_DELETE_ITEM, self.GetId(), node = child, nodes = [parent, child])
|
||||||
self.GetEventHandler().ProcessEvent(e)
|
self.GetEventHandler().ProcessEvent(e)
|
||||||
|
self.painter.ClearBuffer()
|
||||||
def OnKeyDown(self, evt):
|
def OnKeyDown(self, evt):
|
||||||
e = wxMVCTreeEvent(wxEVT_MVCTREE_KEY_DOWN, self.GetId(), keyEvent = evt)
|
e = wxMVCTreeEvent(wxEVT_MVCTREE_KEY_DOWN, self.GetId(), keyEvent = evt)
|
||||||
self.GetEventHandler().ProcessEvent(e)
|
self.GetEventHandler().ProcessEvent(e)
|
||||||
@@ -738,7 +811,7 @@ class wxMVCTree(wxWindow):
|
|||||||
dc = wxClientDC(self)
|
dc = wxClientDC(self)
|
||||||
dc.SetFont(font)
|
dc.SetFont(font)
|
||||||
self.layout.SetHeight(dc.GetTextExtent("")[1] + 18)
|
self.layout.SetHeight(dc.GetTextExtent("")[1] + 18)
|
||||||
|
self.painter.ClearBuffer()
|
||||||
def GetFont(self):
|
def GetFont(self):
|
||||||
return self.painter.GetFont()
|
return self.painter.GetFont()
|
||||||
|
|
||||||
@@ -752,11 +825,10 @@ class wxMVCTree(wxWindow):
|
|||||||
self.painter.OnMouse(evt)
|
self.painter.OnMouse(evt)
|
||||||
|
|
||||||
def OnNodeClick(self, node, mouseEvent):
|
def OnNodeClick(self, node, mouseEvent):
|
||||||
if node.selected:
|
if node.selected and (self.IsMultiSelect() and mouseEvent.ControlDown()):
|
||||||
self.RemoveFromSelection(node.data)
|
self.RemoveFromSelection(node.data)
|
||||||
else:
|
else:
|
||||||
self.AddToSelection(node.data, mouseEvent.ControlDown())
|
self.AddToSelection(node.data, mouseEvent.ControlDown(), mouseEvent.ShiftDown())
|
||||||
self.Refresh()
|
|
||||||
|
|
||||||
def OnKnobClick(self, node):
|
def OnKnobClick(self, node):
|
||||||
self.SetExpanded(node.data, not node.expanded)
|
self.SetExpanded(node.data, not node.expanded)
|
||||||
@@ -793,6 +865,7 @@ class wxMVCTree(wxWindow):
|
|||||||
self.currentRoot = self.layoutRoot
|
self.currentRoot = self.layoutRoot
|
||||||
self.offset = [0,0]
|
self.offset = [0,0]
|
||||||
self.rotation = 0
|
self.rotation = 0
|
||||||
|
self._scrollset = None
|
||||||
self.Refresh()
|
self.Refresh()
|
||||||
|
|
||||||
def GetCurrentRoot(self):
|
def GetCurrentRoot(self):
|
||||||
@@ -817,12 +890,11 @@ class wxMVCTree(wxWindow):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def OnSize(self, evt):
|
def OnSize(self, evt):
|
||||||
try:
|
size = self.GetSize()
|
||||||
size = self.GetSizeTuple()
|
self.center = (size.width/2, size.height/2)
|
||||||
self.center = (size[0]/2, size[1]/2)
|
if self._lastPhysicalSize.width < size.width or self._lastPhysicalSize.height < size.height:
|
||||||
del self.bmp
|
self.painter.ClearBuffer()
|
||||||
except:
|
self._lastPhysicalSize = size
|
||||||
pass
|
|
||||||
|
|
||||||
def GetSelection(self):
|
def GetSelection(self):
|
||||||
"Returns a tuple of selected nodes."
|
"Returns a tuple of selected nodes."
|
||||||
@@ -909,7 +981,7 @@ class wxMVCTree(wxWindow):
|
|||||||
def IsExpanded(self, node):
|
def IsExpanded(self, node):
|
||||||
return self.nodemap[node].expanded
|
return self.nodemap[node].expanded
|
||||||
|
|
||||||
def AddToSelection(self, nodeOrTuple, enableMulti = true):
|
def AddToSelection(self, nodeOrTuple, enableMulti = true, shiftMulti = false):
|
||||||
nodeTuple = nodeOrTuple
|
nodeTuple = nodeOrTuple
|
||||||
if type(nodeOrTuple)!= type(()):
|
if type(nodeOrTuple)!= type(()):
|
||||||
nodeTuple = (nodeOrTuple,)
|
nodeTuple = (nodeOrTuple,)
|
||||||
@@ -917,38 +989,68 @@ class wxMVCTree(wxWindow):
|
|||||||
self.GetEventHandler().ProcessEvent(e)
|
self.GetEventHandler().ProcessEvent(e)
|
||||||
if not e.notify.IsAllowed():
|
if not e.notify.IsAllowed():
|
||||||
return
|
return
|
||||||
if not self.IsMultiSelect() or not enableMulti:
|
changeparents = []
|
||||||
|
if not (self.IsMultiSelect() and (enableMulti or shiftMulti)):
|
||||||
for node in self._selections:
|
for node in self._selections:
|
||||||
treenode = self.nodemap[node]
|
treenode = self.nodemap[node]
|
||||||
treenode.selected = false
|
treenode.selected = false
|
||||||
|
changeparents.append(treenode)
|
||||||
node = nodeTuple[0]
|
node = nodeTuple[0]
|
||||||
self._selections = [node]
|
self._selections = [node]
|
||||||
treenode = self.nodemap[node]
|
treenode = self.nodemap[node]
|
||||||
|
changeparents.append(treenode)
|
||||||
treenode.selected = true
|
treenode.selected = true
|
||||||
else:
|
else:
|
||||||
for node in nodeTuple:
|
if shiftMulti:
|
||||||
try:
|
for node in nodeTuple:
|
||||||
self._selections.index(node)
|
|
||||||
except ValueError:
|
|
||||||
self._selections.append(node)
|
|
||||||
treenode = self.nodemap[node]
|
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)
|
e = wxMVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), nodeTuple[0], nodes = nodeTuple)
|
||||||
self.GetEventHandler().ProcessEvent(e)
|
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):
|
def RemoveFromSelection(self, nodeTuple):
|
||||||
if type(nodeTuple) != type(()):
|
if type(nodeTuple) != type(()):
|
||||||
nodeTuple = (nodeTuple,)
|
nodeTuple = (nodeTuple,)
|
||||||
|
changeparents = []
|
||||||
for node in nodeTuple:
|
for node in nodeTuple:
|
||||||
try:
|
self._selections.remove(node)
|
||||||
self._selections.index(node)
|
treenode = self.nodemap[node]
|
||||||
except IndexError:
|
changeparents.append(treenode)
|
||||||
self._selections.remove(node)
|
treenode.selected = false
|
||||||
treenode = self.nodemap[node]
|
|
||||||
node.selected = false
|
|
||||||
e = wxMVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), node, nodes = nodeTuple)
|
e = wxMVCTreeEvent(wxEVT_MVCTREE_SEL_CHANGED, self.GetId(), node, nodes = nodeTuple)
|
||||||
self.GetEventHandler().ProcessEvent(e)
|
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 GetBackgroundColour(self):
|
||||||
@@ -978,126 +1080,39 @@ class wxMVCTree(wxWindow):
|
|||||||
def GetAssumeChildren(self):
|
def GetAssumeChildren(self):
|
||||||
return self._assumeChildren
|
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):
|
def OnPaint(self, evt):
|
||||||
"""
|
"""
|
||||||
Ensures that the tree has been laid out and transformed, then calls the painter
|
Ensures that the tree has been laid out and transformed, then calls the painter
|
||||||
to paint the control.
|
to paint the control.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
self.EnableScrolling(false, false)
|
||||||
if not self.laidOut:
|
if not self.laidOut:
|
||||||
self.layout.layout(self.currentRoot)
|
self.layout.layout(self.currentRoot)
|
||||||
self.laidOut = true
|
self.laidOut = true
|
||||||
|
self.transformed = false
|
||||||
if not self.transformed:
|
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
|
self.transformed = true
|
||||||
dc = wxPaintDC(self)
|
tsize = None
|
||||||
dc.SetFont(self.GetFont())
|
tsize = list(self.transform.GetSize())
|
||||||
if self.doubleBuffered:
|
tsize[0] = tsize[0] + 50
|
||||||
size = self.GetSize()
|
tsize[1] = tsize[1] + 50
|
||||||
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()
|
size = self.GetSizeTuple()
|
||||||
if self._scrollx or self.painter.minx < 0 or self.painter.maxx > size[0]:
|
if tsize[0] > size[0] or tsize[1] > size[1]:
|
||||||
field = self.painter.maxx - self.painter.minx
|
if not hasattr(self, '_oldsize') or (tsize[0] > self._oldsize[0] or tsize[1] > self._oldsize[1]):
|
||||||
self.SetScrollbar(wxHORIZONTAL, -self.offset[0], size[0]/field, field, true)
|
self._oldsize = tsize
|
||||||
self._scrollx = false
|
oldstart = self.ViewStart()
|
||||||
if self._scrolly or self.painter.miny < 0 or self.painter.maxy > size[1]:
|
self._lastPhysicalSize = self.GetSize()
|
||||||
field = self.painter.maxy - self.painter.miny
|
self.SetScrollbars(10, 10, tsize[0]/10, tsize[1]/10)
|
||||||
self.SetScrollbar(wxVERTICAL, -self.offset[1], size[1]/field, field, true)
|
self.Scroll(oldstart[0], oldstart[1])
|
||||||
self._scrolly = false
|
dc = wxPaintDC(self)
|
||||||
|
self.PrepareDC(dc)
|
||||||
|
dc.SetFont(self.GetFont())
|
||||||
|
self.painter.paint(dc, self.currentRoot, self.doubleBuffered)
|
||||||
except:
|
except:
|
||||||
import traceback;traceback.print_exc()
|
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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -109,49 +109,50 @@ class wxVTKRenderWindow(wxWindow):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## testcode is now in the demo ##
|
||||||
|
|
||||||
if __name__ == '__main__':
|
## if __name__ == '__main__':
|
||||||
class TestFrame(wxFrame):
|
## class TestFrame(wxFrame):
|
||||||
def __init__(self, parent):
|
## def __init__(self, parent):
|
||||||
wxFrame.__init__(self, parent, -1, "VTK Test", size=(450,450))
|
## wxFrame.__init__(self, parent, -1, "VTK Test", size=(450,450))
|
||||||
|
|
||||||
rw = wxVTKRenderWindow(self, -1)
|
## rw = wxVTKRenderWindow(self, -1)
|
||||||
|
|
||||||
# Get the render window
|
## # Get the render window
|
||||||
renWin = rw.GetRenderWindow()
|
## renWin = rw.GetRenderWindow()
|
||||||
|
|
||||||
# Next, do the VTK stuff
|
## # Next, do the VTK stuff
|
||||||
ren = vtkRenderer()
|
## ren = vtkRenderer()
|
||||||
renWin.AddRenderer(ren)
|
## renWin.AddRenderer(ren)
|
||||||
cone = vtkConeSource()
|
## cone = vtkConeSource()
|
||||||
cone.SetResolution(80)
|
## cone.SetResolution(80)
|
||||||
coneMapper = vtkPolyDataMapper()
|
## coneMapper = vtkPolyDataMapper()
|
||||||
coneMapper.SetInput(cone.GetOutput())
|
## coneMapper.SetInput(cone.GetOutput())
|
||||||
coneActor = vtkActor()
|
## coneActor = vtkActor()
|
||||||
coneActor.SetMapper(coneMapper)
|
## coneActor.SetMapper(coneMapper)
|
||||||
ren.AddActor(coneActor)
|
## ren.AddActor(coneActor)
|
||||||
coneMapper.GetLookupTable().Build()
|
## coneMapper.GetLookupTable().Build()
|
||||||
|
|
||||||
# Create a scalar bar
|
## # Create a scalar bar
|
||||||
scalarBar = vtkScalarBarActor()
|
## scalarBar = vtkScalarBarActor()
|
||||||
scalarBar.SetLookupTable(coneMapper.GetLookupTable())
|
## scalarBar.SetLookupTable(coneMapper.GetLookupTable())
|
||||||
scalarBar.SetTitle("Temperature")
|
## scalarBar.SetTitle("Temperature")
|
||||||
scalarBar.GetPositionCoordinate().SetCoordinateSystemToNormalizedViewport()
|
## scalarBar.GetPositionCoordinate().SetCoordinateSystemToNormalizedViewport()
|
||||||
scalarBar.GetPositionCoordinate().SetValue(0.1, 0.01)
|
## scalarBar.GetPositionCoordinate().SetValue(0.1, 0.01)
|
||||||
scalarBar.SetOrientationToHorizontal()
|
## scalarBar.SetOrientationToHorizontal()
|
||||||
scalarBar.SetWidth(0.8)
|
## scalarBar.SetWidth(0.8)
|
||||||
scalarBar.SetHeight(0.17)
|
## scalarBar.SetHeight(0.17)
|
||||||
ren.AddActor2D(scalarBar)
|
## ren.AddActor2D(scalarBar)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TestApp(wxApp):
|
## class TestApp(wxApp):
|
||||||
def OnInit(self):
|
## def OnInit(self):
|
||||||
f = TestFrame(None)
|
## f = TestFrame(None)
|
||||||
self.SetTopWindow(f)
|
## self.SetTopWindow(f)
|
||||||
f.Show(true)
|
## f.Show(true)
|
||||||
return true
|
## return true
|
||||||
|
|
||||||
app = TestApp(0)
|
## app = TestApp(0)
|
||||||
app.MainLoop()
|
## app.MainLoop()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user