Updates from Chris

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28362 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2004-07-21 19:19:47 +00:00
parent 6077391138
commit 5e1796efd3
4 changed files with 521 additions and 384 deletions

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2.3
try:
import Numeric
import RandomArray
@@ -34,7 +34,7 @@ else:
if __name__ == "__main__": # parse options if run stand-alone
# check options:
import sys, getopt
optlist, args = getopt.getopt(sys.argv[1:],'l',["local","all","text","map","stext","hit","hitf","animate","speed","temp"])
optlist, args = getopt.getopt(sys.argv[1:],'l',["local","all","text","map","stext","hit","hitf","animate","speed","temp","props"])
for opt in optlist:
if opt[0] == "--all":
@@ -55,6 +55,8 @@ else:
StartUpDemo = "speed"
elif opt[0] == "--temp":
StartUpDemo = "temp"
elif opt[0] == "--props":
StartUpDemo = "props"
import wx
import time, random
@@ -112,12 +114,14 @@ else:
self.Bind(wx.EVT_MENU, self.Clear, item)
item = draw_menu.Append(-1, "&Hit Test","Run a test of the hit test code")
self.Bind(wx.EVT_MENU, self.TestHitTest, item)
item = draw_menu.Append(-1, "&Hit Test Foreground","Run a test of the hit test code with a foreground Object")
item = draw_menu.Append(-1, "Hit Test &Foreground","Run a test of the hit test code with a foreground Object")
self.Bind(wx.EVT_MENU, self.TestHitTestForeground, item)
item = draw_menu.Append(-1, "&Animation","Run a test of Animation")
self.Bind(wx.EVT_MENU, self.TestAnimation, item)
item = draw_menu.Append(-1, "&Speed","Run a test of Drawing Speed")
self.Bind(wx.EVT_MENU, self.SpeedTest, item)
item = draw_menu.Append(-1, "Change &Properties","Run a test of Changing Object Properties")
self.Bind(wx.EVT_MENU, self.PropertiesChangeTest, item)
MenuBar.Append(draw_menu, "&Tests")
view_menu = wx.Menu()
@@ -138,7 +142,7 @@ else:
self.Canvas = NavCanvas.NavCanvas(self,
-1,
(500,500),
Debug = 1,
Debug = 0,
BackgroundColor = "DARK SLATE BLUE")
wx.EVT_CLOSE(self, self.OnCloseWindow)
@@ -267,6 +271,7 @@ else:
self.Destroy()
def DrawTest(self,event=None):
wx.GetApp().Yield()
# import random
# import RandomArray
Range = (-10,10)
@@ -287,7 +292,7 @@ else:
cf = random.randint(0,len(colors)-1)
h = random.randint(1,5)
w = random.randint(1,5)
Canvas.AddRectangle(x,y,h,w,LineWidth = lw,FillColor = colors[cf])
Canvas.AddRectangle(x,y,w,h,LineWidth = lw,FillColor = colors[cf])
# Ellipses
for i in range(3):
@@ -298,14 +303,12 @@ else:
w = random.randint(1,5)
Canvas.AddEllipse(x,y,h,w,LineWidth = lw,FillColor = colors[cf])
## # Dots -- Does anyone need this?
## for i in range(5):
## x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
## D = random.randint(1,50)
## lw = random.randint(1,5)
## cf = random.randint(0,len(colors)-1)
## cl = random.randint(0,len(colors)-1)
## Canvas.AddDot(x,y,D,LineWidth = lw,LineColor = colors[cl],FillColor = colors[cf])
# Points
for i in range(5):
x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
D = random.randint(1,50)
cf = random.randint(0,len(colors)-1)
Canvas.AddPoint((x,y), Color = colors[cf], Diameter = D)
# Circles
for i in range(5):
@@ -379,7 +382,7 @@ else:
having to re-draw the whole background.
"""
print "Running TestAnimation"
wx.GetApp().Yield()
Range = (-10,10)
self.Range = Range
@@ -456,7 +459,7 @@ else:
# Now the Foreground Object:
C = Canvas.AddCircle(0,0,7,LineWidth = 2,LineColor = "Black",FillColor = "Red", InForeground = True)
T = Canvas.AddScaledText("Click to Move",0,0, Size = 0.8, Position = 'cc', InForeground = True)
T = Canvas.AddScaledText("Click to Move",0,0, Size = 0.6, Position = 'cc', InForeground = True)
C.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.MoveMe)
C.Text = T
@@ -478,6 +481,7 @@ else:
Object.Text.Move( (self.dx,self.dy))
self.Canvas.Draw()
self.TimeStep += 1
wx.GetApp().Yield(True)
else:
self.Timer.Stop()
@@ -489,12 +493,13 @@ else:
self.dy = random.uniform(Range[0]/4,Range[1]/4)
#import time
#start = time.time()
self.NumTimeSteps = 500
self.NumTimeSteps = 200
self.TimeStep = 1
self.Timer.Start(self.FrameDelay)
#print "Did %i frames in %f seconds"%(N, (time.time() - start) )
def TestHitTest(self,event=None):
wx.GetApp().Yield()
self.UnBindAllMouseEvents()
Canvas = self.Canvas
@@ -508,28 +513,29 @@ else:
dx = 80
dy = 40
x,y = 20, 20
FontSize = 8
#Add one that is not HitAble
Canvas.AddRectangle(x, y, w, h, LineWidth = 2)
Canvas.AddText("Not Hit-able", x, y, Position = "bl")
Canvas.AddText("Not Hit-able", x, y, Size = FontSize, Position = "bl")
x += dx
R = Canvas.AddRectangle(x, y, w, h,LineWidth = 2)
R = Canvas.AddRectangle(x, y, w, h, LineWidth = 2)
R.Name = "Line Rectangle"
R.HitFill = False
R.HitLineWidth = 5 # Makes it a little easier to hit
R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectGotHit)
Canvas.AddText("Left Click Line", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Left Click Line", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "Red"
R = Canvas.AddRectangle(x, y, w, h, LineWidth = 2, FillColor = color)
R.Name = color + "Rectangle"
R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectGotHit)
Canvas.AddText("Left Click Fill", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Left Click Fill", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x = 20
y += dy
@@ -538,15 +544,15 @@ else:
R.Name = color + " Rectangle"
R.Bind(FloatCanvas.EVT_FC_RIGHT_DOWN, self.RectGotHit)
Canvas.AddText("Right Click Fill", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "Grey"
R = Canvas.AddEllipse(x, y, w, h,LineWidth = 2,FillColor = color)
R.Name = color +" Ellipse"
R.Bind(FloatCanvas.EVT_FC_RIGHT_DOWN, self.RectGotHit)
Canvas.AddText("Right Click Fill", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Right Click Fill", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "Brown"
@@ -554,8 +560,8 @@ else:
R.Name = color + " Circle"
R.HitFill = True
R.Bind(FloatCanvas.EVT_FC_LEFT_DCLICK, self.RectGotHit)
Canvas.AddText("Left D-Click Fill", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Left D-Click Fill", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x = 20
y += dy
@@ -563,24 +569,24 @@ else:
R = Canvas.AddCircle(x+dx/2, y+dy/2, dx/4, LineWidth = 2,FillColor = color)
R.Name = color + " Circle"
R.Bind(FloatCanvas.EVT_FC_LEFT_UP, self.RectGotHit)
Canvas.AddText("Left Up Fill", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Left Up Fill", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "White"
R = Canvas.AddRectangle(x, y, w, h, LineWidth = 2, FillColor = color)
R.Name = color + " Rectangle"
R.Bind(FloatCanvas.EVT_FC_MIDDLE_DOWN, self.RectGotHit)
Canvas.AddText("Middle Down", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Middle Down", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "AQUAMARINE"
R = Canvas.AddRectangle(x, y, w, h, LineWidth = 2, FillColor = color)
R.Name = color + " Rectangle"
R.Bind(FloatCanvas.EVT_FC_MIDDLE_UP, self.RectGotHit)
Canvas.AddText("Middle Up", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Middle Up", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x = 20
y += dy
@@ -588,24 +594,24 @@ else:
R = Canvas.AddRectangle(x, y, w, h, LineWidth = 2, FillColor = color)
R.Name = color + " Rectangle"
R.Bind(FloatCanvas.EVT_FC_MIDDLE_DCLICK, self.RectGotHit)
Canvas.AddText("Middle DoubleClick", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Middle DoubleClick", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "CYAN"
R = Canvas.AddRectangle(x, y, w, h, LineWidth = 2, FillColor = color)
R.Name = color + " Rectangle"
R.Bind(FloatCanvas.EVT_FC_RIGHT_UP, self.RectGotHit)
Canvas.AddText("Right Up", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Right Up", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "LIME GREEN"
R = Canvas.AddRectangle(x, y, w, h, LineWidth = 2, FillColor = color)
R.Name = color + " Rectangle"
R.Bind(FloatCanvas.EVT_FC_RIGHT_DCLICK, self.RectGotHit)
Canvas.AddText("Right Double Click", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Right Double Click", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x = 20
y += dy
@@ -614,24 +620,24 @@ else:
R.Name = color
R.Bind(FloatCanvas.EVT_FC_RIGHT_DOWN, self.RectGotHitRight)
R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectGotHitLeft)
Canvas.AddText("L and R Click", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("L and R Click", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "SALMON"
R = Canvas.AddRectangle(x, y, w, h, LineWidth = 2, FillColor = color)
R.Name = color + " Rectangle"
R.Bind(FloatCanvas.EVT_FC_ENTER_OBJECT, self.RectMouseOver)
Canvas.AddText("Mouse Enter", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Mouse Enter", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "MEDIUM VIOLET RED"
R = Canvas.AddRectangle(x, y, w, h, LineWidth = 2, FillColor = color)
R.Name = color
R.Bind(FloatCanvas.EVT_FC_LEAVE_OBJECT, self.RectMouseLeave)
Canvas.AddText("Mouse Leave", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Mouse Leave", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x = 20
y += dy
@@ -640,8 +646,8 @@ else:
R.Name = color
R.Bind(FloatCanvas.EVT_FC_ENTER_OBJECT, self.RectMouseOver)
R.Bind(FloatCanvas.EVT_FC_LEAVE_OBJECT, self.RectMouseLeave)
Canvas.AddText("Enter and Leave", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Enter and Leave", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "WHEAT"
@@ -649,8 +655,8 @@ else:
R.Name = color
R.Bind(FloatCanvas.EVT_FC_ENTER_OBJECT, self.RectMouseOver)
R.Bind(FloatCanvas.EVT_FC_LEAVE_OBJECT, self.RectMouseLeave)
Canvas.AddText("Mouse Enter&Leave", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Mouse Enter&Leave", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "KHAKI"
@@ -658,16 +664,16 @@ else:
R.Name = color
R.Bind(FloatCanvas.EVT_FC_ENTER_OBJECT, self.RectMouseOver)
R.Bind(FloatCanvas.EVT_FC_LEAVE_OBJECT, self.RectMouseLeave)
Canvas.AddText("Mouse ENter&Leave", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("Mouse ENter&Leave", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x = 20
y += dy
L = Canvas.AddLine(( (x, y), (x+10, y+10), (x+w, y+h) ), LineWidth = 2, LineColor = "Red")
L.Name = "A Line"
L.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectGotHitLeft)
Canvas.AddText("Left Down", x, y, Position = "bl")
Canvas.AddText(L.Name, x, y+h, Position = "tl")
Canvas.AddText("Left Down", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(L.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "SEA GREEN"
@@ -675,8 +681,8 @@ else:
R = Canvas.AddPolygon(Points, LineWidth = 2, FillColor = color)
R.Name = color + " Polygon"
R.Bind(FloatCanvas.EVT_FC_RIGHT_DOWN, self.RectGotHitRight)
Canvas.AddText("RIGHT_DOWN", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("RIGHT_DOWN", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x += dx
color = "Red"
@@ -684,27 +690,27 @@ else:
R = Canvas.AddPointSet(Points, Diameter = 4, Color = color)
R.Name = "PointSet"
R.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.PointSetGotHit)
Canvas.AddText("LEFT_DOWN", x, y, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Position = "tl")
Canvas.AddText("LEFT_DOWN", x, y, Size = FontSize, Position = "bl")
Canvas.AddText(R.Name, x, y+h, Size = FontSize, Position = "tl")
x = 20
y += dy
T = Canvas.AddText("Hit-able Text", x, y, Size = 15, Color = "Red", Position = 'tl')
T.Name = "Hit-able Text"
T.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectGotHitLeft)
Canvas.AddText("Left Down", x, y, Position = "bl")
Canvas.AddText("Left Down", x, y, Size = FontSize, Position = "bl")
x += dx
T = Canvas.AddScaledText("Scaled Text", x, y, Size = 1./2*h, Color = "Pink", Position = 'bl')
Canvas.AddPointSet( (x, y), Diameter = 3)
T.Name = "Scaled Text"
T.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.RectGotHitLeft)
Canvas.AddText("Left Down", x, y, Position = "tl")
Canvas.AddText("Left Down", x, y, Size = FontSize, Position = "tl")
self.Canvas.ZoomToBB()
def TestHitTestForeground(self,event=None):
print "Running: TestHitTestForeground"
wx.GetApp().Yield()
self.UnBindAllMouseEvents()
Canvas = self.Canvas
@@ -809,6 +815,7 @@ else:
def TestText(self, event= None):
wx.GetApp().Yield()
self.BindAllMouseEvents()
Canvas = self.Canvas
@@ -823,10 +830,6 @@ else:
# Text
String = "Some text"
## for i in range(10):
## ts = random.randint(10,40)
## cf = random.randint(0,len(colors)-1)
## x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
self.Canvas.AddText("Top Left",x,y,Size = 14,Color = "Yellow",BackgroundColor = "Blue", Position = "tl")
self.Canvas.AddText("Bottom Left",x,y,Size = 14,Color = "Cyan",BackgroundColor = "Black",Position = "bl")
self.Canvas.AddText("Top Right",x,y,Size = 14,Color = "Black",BackgroundColor = "Cyan",Position = "tr")
@@ -868,6 +871,7 @@ else:
self.Canvas.ZoomToBB()
def TestScaledText(self, event= None):
wx.GetApp().Yield()
self.BindAllMouseEvents()
Canvas = self.Canvas
@@ -918,6 +922,7 @@ else:
self.Canvas.ZoomToBB()
def DrawMap(self,event = None):
wx.GetApp().Yield()
import os, time
self.BindAllMouseEvents()
@@ -937,6 +942,7 @@ else:
def LineTest(self,event = None):
wx.GetApp().Yield()
import os, time
# import random
colors = self.colors
@@ -965,8 +971,7 @@ else:
#print "It took %f seconds to draw %i lines"%(time.clock() - start,len(linepoints) )
def SpeedTest(self,event=None):
# import random
# import RandomArray
wx.GetApp().Yield()
BigRange = (-1000,1000)
colors = self.colors
@@ -976,135 +981,172 @@ else:
Canvas.ClearAll()
Canvas.SetProjectionFun(None)
# Lots of Text
String = "Unscaled text"
# Pointset
coords = []
text = []
for i in range(5000):
for i in range(1000):
x,y = (random.uniform(BigRange[0],BigRange[1]),random.uniform(BigRange[0],BigRange[1]))
coords.append( (x,y) )
print "Drawing the Numbers"
print "Drawing the Points"
start = time.clock()
for i in xrange( len(coords) ):
Canvas.AddText("%i"%(i),
coords[i][0],
coords[i][1],
Size = 12,
Position = "cc",
BackgroundColor = "White")
print "It took %s seconds to add the numbers"%(time.clock() - start)
for Point in coords:
Canvas.AddPoint(Point, Diameter = 4)
print "It took %s seconds to add the points"%(time.clock() - start)
Canvas.ZoomToBB()
def PropertiesChangeTest(self,event=None):
wx.GetApp().Yield()
## ObjectList = []
Range = (-10,10)
colors = self.colors
## print "Building a list of lots of random objects"
## ## Random tests of everything:
## def MakeRange():
## while True:
## Range = ( random.randint(BigRange[0],BigRange[1]), random.randint(BigRange[0],BigRange[1]) )
## if abs (Range[0] - Range[1]) < 10:
## continue
## if Range[0] > Range[1]:
## Range = ( Range[1], Range[0] )
## break
## return Range
self.UnBindAllMouseEvents()
Canvas = self.Canvas
## # Rectangles
## for i in range(300):
## Range = MakeRange()
## x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
## lw = random.randint(1,5)
## cf = random.randint(0,len(colors)-1)
## h = random.randint(1, Range[1] - Range[0])
## w = random.randint(1, Range[1] - Range[0])
## ObjectList.append(FloatCanvas.Rectangle(x,y,h,w,LineWidth = lw,FillColor = colors[cf]))
Canvas.ClearAll()
Canvas.SetProjectionFun(None)
self.ColorObjectsAll = []
self.ColorObjectsLine = []
self.ColorObjectsColor = []
self.ColorObjectsText = []
##One of each object:
# Rectangle
x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
lw = random.randint(1,5)
cf = random.randint(0,len(colors)-1)
h = random.randint(1,5)
w = random.randint(1,5)
self.Rectangle = Canvas.AddRectangle(x,y,w,h,LineWidth = lw,FillColor = colors[cf])
self.ColorObjectsAll.append(self.Rectangle)
## # Ellipses
## for i in range(300):
## Range = MakeRange()
## x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
## lw = random.randint(1,5)
## cf = random.randint(0,len(colors)-1)
## h = random.randint(1, Range[1] - Range[0])
## w = random.randint(1, Range[1] - Range[0])
## ObjectList.append(FloatCanvas.Ellipse(x,y,h,w,LineWidth = lw,FillColor = colors[cf]))
# Ellipse
x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
lw = random.randint(1,5)
cf = random.randint(0,len(colors)-1)
h = random.randint(1,5)
w = random.randint(1,5)
self.Ellipse = Canvas.AddEllipse(x,y,h,w,LineWidth = lw,FillColor = colors[cf])
self.ColorObjectsAll.append(self.Ellipse)
# Point
xy = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
D = random.randint(1,50)
lw = random.randint(1,5)
cf = random.randint(0,len(colors)-1)
cl = random.randint(0,len(colors)-1)
self.ColorObjectsColor.append(Canvas.AddPoint(xy, colors[cf], D))
# Circle
x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
D = random.randint(1,5)
lw = random.randint(1,5)
cf = random.randint(0,len(colors)-1)
cl = random.randint(0,len(colors)-1)
self.Circle = Canvas.AddCircle(x,y,D,LineWidth = lw,LineColor = colors[cl],FillColor = colors[cf])
self.ColorObjectsAll.append(self.Circle)
# Line
points = []
for j in range(random.randint(2,10)):
point = (random.randint(Range[0],Range[1]),random.randint(Range[0],Range[1]))
points.append(point)
lw = random.randint(1,10)
cf = random.randint(0,len(colors)-1)
cl = random.randint(0,len(colors)-1)
self.ColorObjectsLine.append(Canvas.AddLine(points, LineWidth = lw, LineColor = colors[cl]))
# Polygon
## points = []
## for j in range(random.randint(2,6)):
## point = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
## points.append(point)
points = RandomArray.uniform(Range[0],Range[1],(6,2))
lw = random.randint(1,6)
cf = random.randint(0,len(colors)-1)
cl = random.randint(0,len(colors)-1)
self.ColorObjectsAll.append(Canvas.AddPolygon(points,
LineWidth = lw,
LineColor = colors[cl],
FillColor = colors[cf],
FillStyle = 'Solid'))
## Pointset
points = RandomArray.uniform(Range[0],Range[1],(100,2))
cf = random.randint(0,len(colors)-1)
D = random.randint(1,4)
self.PointSet = Canvas.AddPointSet(points, Color = colors[cf], Diameter = D)
self.ColorObjectsColor.append(self.PointSet)
## # Circles
## for i in range(500):
## Range = MakeRange()
## x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
## D = random.randint(1, (Range[1] - Range[0]) / 2)
## lw = random.randint(1,5)
## cf = random.randint(0,len(colors)-1)
## cl = random.randint(0,len(colors)-1)
## ObjectList.append(FloatCanvas.Circle(x,y,D,LineWidth = lw,LineColor = colors[cl],FillColor = colors[cf]))
## #ObjectList.append(FloatCanvas.Text("Circle # %i"%(i),x,y,Size = 12,BackgroundColor = None,Position = "cc"))
## # Lines
## for i in range(500):
## Range = MakeRange()
## points = []
## for j in range(random.randint(2,100)):
## point = (random.randint(Range[0],Range[1]),random.randint(Range[0],Range[1]))
## points.append(point)
## lw = random.randint(1,10)
## cf = random.randint(0,len(colors)-1)
## cl = random.randint(0,len(colors)-1)
## ObjectList.append(FloatCanvas.Line(points, LineWidth = lw, LineColor = colors[cl]) )
## # Polygons
## for i in range(300):
## Range = MakeRange()
## points = []
## for j in range(random.randint(2,60)):
## point = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
## points.append(point)
## lw = random.randint(1,6)
## cf = random.randint(0,len(colors)-1)
## cl = random.randint(0,len(colors)-1)
## ObjectList.append(FloatCanvas.Polygon(points,
## LineWidth = lw,
## LineColor = colors[cl],
## FillColor = colors[cf],
## FillStyle = 'Solid') )
## random.shuffle(ObjectList)
## print "Adding lots of random objects"
## start = time.clock()
## for Object in ObjectList:
## Canvas.AddObject(Object)
## print "It took %s Seconds to add %i objects "%(time.clock() - start, len(ObjectList) )
## ## Pointset
## for i in range(100):
## points = []
## points = RandomArray.uniform(Range[0],Range[1],(100,2))
## cf = random.randint(0,len(colors)-1)
## D = random.randint(1,4)
## Canvas.AddPointSet(points, Color = colors[cf], Diameter = D)
## Point
point = RandomArray.uniform(Range[0],Range[1],(2,))
cf = random.randint(0,len(colors)-1)
D = random.randint(1,4)
self.Point = Canvas.AddPoint(point, Color = colors[cf], Diameter = D)
self.ColorObjectsColor.append(self.Point)
# Text
String = "Unscaled text"
ts = random.randint(10,40)
cf = random.randint(0,len(colors)-1)
x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
self.ColorObjectsText.append(Canvas.AddText(String, x, y, Size = ts, Color = colors[cf], Position = "cc"))
## # Scaled Text
## String = "Scaled text"
## for i in range(30):
## ts = random.random()*3 + 0.2
## cf = random.randint(0,len(colors)-1)
## x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
## Canvas.AddScaledText(String, x, y, Size = ts, Color = colors[cf], Position = "cc")
# Scaled Text
String = "Scaled text"
ts = random.random()*3 + 0.2
cf = random.randint(0,len(colors)-1)
x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
self.ColorObjectsText.append(Canvas.AddScaledText(String, x, y, Size = ts, Color = colors[cf], Position = "cc"))
# A "Button"
Button = Canvas.AddRectangle(-10, -12, 20, 3, LineStyle = None, FillColor = "Red")
Canvas.AddScaledText("Click Here To Change Properties",
0, -10.5,
Size = 0.7,
Color = "Black",
Position = "cc")
Button.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.ChangeProperties)
Canvas.ZoomToBB()
def ChangeProperties(self, Object = None):
colors = self.colors
Range = (-10,10)
for Object in self.ColorObjectsAll:
pass
Object.SetFillColor(colors[random.randint(0,len(colors)-1)])
Object.SetLineColor(colors[random.randint(0,len(colors)-1)])
Object.SetLineWidth(random.randint(1,7))
Object.SetLineStyle(FloatCanvas.DrawObject.LineStyleList.keys()[random.randint(0,5)])
for Object in self.ColorObjectsLine:
Object.SetLineColor(colors[random.randint(0,len(colors)-1)])
Object.SetLineWidth(random.randint(1,7))
Object.SetLineStyle(FloatCanvas.DrawObject.LineStyleList.keys()[random.randint(0,5)])
for Object in self.ColorObjectsColor:
Object.SetColor(colors[random.randint(0,len(colors)-1)])
for Object in self.ColorObjectsText:
Object.SetColor(colors[random.randint(0,len(colors)-1)])
Object.SetBackgroundColor(colors[random.randint(0,len(colors)-1)])
self.Circle.SetDiameter(random.randint(1,10))
self.PointSet.SetDiameter(random.randint(1,8))
self.Point.SetDiameter(random.randint(1,8))
for Object in (self.Rectangle, self.Ellipse):
x,y = (random.uniform(Range[0],Range[1]),random.uniform(Range[0],Range[1]))
w,h = random.randint(1,5), random.randint(1,5)
Object.SetShape(x,y,w,h)
self.Canvas.Draw(Force = True)
def TempTest(self, event= None):
"Running the Temporary test"
wx.GetApp().Yield()
self.UnBindAllMouseEvents()
Canvas = self.Canvas
Canvas.ClearAll()
Canvas.SetProjectionFun(None)
# import random
# import RandomArray
Range = (-10,10)
# Create a random Polygon
@@ -1234,6 +1276,9 @@ else:
elif StartUpDemo == "temp":
"starting temp Test"
frame.TempTest()
elif StartUpDemo == "props":
"starting PropertiesChange Test"
frame.PropertiesChangeTest()
return True

View File

@@ -1,8 +1,7 @@
try:
from Numeric import array,asarray,Float,cos,pi,sum,minimum,maximum,Int32,zeros
from Numeric import array,asarray,Float,cos,pi,sum,minimum,maximum,Int32,zeros, ones, concatenate, sqrt, argmin, power, absolute
except ImportError:
from numarray import array, asarray, Float, cos, pi, sum, minimum, maximum, Int32, zeros
from numarray import array, asarray, Float, cos, pi, sum, minimum, maximum, Int32, zeros, concatenate
from time import clock, sleep
@@ -11,19 +10,17 @@ import wx
import types
import os
import Resources
## A global variable to hold the Pixels per inch that wxWindows thinks is in use
## This is used for scaling fonts.
## This can't be computed on module __init__, because a wx.App might not have iniitalized yet.
global ScreenPPI
global ScreenPPI
## a custom Exceptions:
class FloatCanvasException(Exception):
pass
## All the mouse events
## Create all the mouse events
#EVT_FC_ENTER_WINDOW = wx.NewEventType()
#EVT_FC_LEAVE_WINDOW = wx.NewEventType()
EVT_FC_LEFT_DOWN = wx.NewEventType()
@@ -41,6 +38,7 @@ EVT_FC_MOUSEWHEEL = wx.NewEventType()
EVT_FC_ENTER_OBJECT = wx.NewEventType()
EVT_FC_LEAVE_OBJECT = wx.NewEventType()
##Create all mouse event binding functions
#def EVT_ENTER_WINDOW( window, function ):
# window.Connect( -1, -1, EVT_FC_ENTER_WINDOW, function )
#def EVT_LEAVE_WINDOW( window, function ):
@@ -68,7 +66,7 @@ def EVT_MOTION( window, function ):
def EVT_MOUSEWHEEL( window, function ):
window.Connect( -1, -1,EVT_FC_MOUSEWHEEL , function )
class MouseEvent(wx.PyCommandEvent):
class _MouseEvent(wx.PyCommandEvent):
"""
@@ -82,7 +80,7 @@ class MouseEvent(wx.PyCommandEvent):
GetCoords() , which returns and (x,y) tuple in world coordinates.
Another differnce is that it is a CommandEvent, which propagates up
Another difference is that it is a CommandEvent, which propagates up
the window hierarchy until it is handled.
"""
@@ -104,74 +102,27 @@ class MouseEvent(wx.PyCommandEvent):
#return eval(self.NativeEvent.__getattr__(name) )
return getattr(self._NativeEvent, name)
#### ColorGEnerator class is now obsolete. I'm using a python generator function instead.
##class ColorGenerator:
def _cycleidxs(indexcount, maxvalue, step):
## """
"""
Utility function used by _colorGenerator
## An instance of this class generates a unique color each time
## GetNextColor() is called. Someday I will use a proper Python
## generator for this class.
## The point of this generator is for the hit-test bitmap, each object
## needs to be a unique color. Also, each system can be running a
## different number of colors, and it doesn't appear to be possible to
## have a wxMemDC with a different colordepth as the screen so this
## generates colors far enough apart that they can be distinguished on
## a 16bit screen. Anything less than 16bits won't work. It could, but
## I havn't written the code that way. You also wouldn't get many
## distict colors
## """
## def __init__(self):
## import sys
## ## figure out the color depth of the screen
## ## for some bizare reason, thisdoesn't work on OS-X
## if sys.platform == 'darwin':
## depth = 24
## else:
## b = wx.EmptyBitmap(1,1)
## depth = b.GetDepth()
## self.r = 0
## self.g = 0
## self.b = 0
## if depth == 16:
## self.step = 8
## elif depth >= 24:
## self.step = 1
## else:
## raise FloatCanvasException("ColorGenerator does not work with depth = %s"%depth )
## def GetNextColor(self):
## step = self.step
## ##r,g,b = self.r,self.g,self.b
## self.r += step
## if self.r > 255:
## self.r = step
## self.g += step
## if self.g > 255:
## self.g = step
## self.b += step
## if self.b > 255:
## ## fixme: this should be a derived exception
## raise FloatCanvasException("Too many objects in colorgenerator for HitTest")
## return (self.r,self.g,self.b)
## def Reset(self):
## self.r = 0
## self.g = 0
## self.b = 0
def cycleidxs(indexcount, maxvalue, step):
"""
if indexcount == 0:
yield ()
else:
for idx in xrange(0, maxvalue, step):
for tail in cycleidxs(indexcount - 1, maxvalue, step):
for tail in _cycleidxs(indexcount - 1, maxvalue, step):
yield (idx, ) + tail
def colorGenerator():
def _colorGenerator():
"""
Generates a seris of unique colors used to do hit-tests with the HIt
Test bitmap
"""
import sys
if sys.platform == 'darwin':
depth = 24
@@ -184,12 +135,13 @@ def colorGenerator():
step = 1
else:
raise "ColorGenerator does not work with depth = %s" % depth
return cycleidxs(indexcount=3, maxvalue=256, step=step)
return _cycleidxs(indexcount=3, maxvalue=256, step=step)
#### I don't know if the Set objects are useful, beyond the pointset object
#### The problem is that when zoomed in, the BB is checked to see whether to draw the object.
#### A Set object can defeat this
#### I don't know if the Set objects are useful, beyond the pointset
#### object The problem is that when zoomed in, the BB is checked to see
#### whether to draw the object. A Set object can defeat this. ONe day
#### I plan to write some custon C++ code to draw sets of objects
##class ObjectSetMixin:
## """
@@ -246,12 +198,13 @@ def colorGenerator():
## if length == 1:
## self.Pens = self.Pens[0]
class DrawObject:
"""
This is the base class for all the objects that can be drawn.
One must subclass from this (and an assortment of Mixins) to create
a new DrawObject.
"""
def __init__(self,InForeground = False):
@@ -268,6 +221,11 @@ class DrawObject:
self.HitFill = True
self.MinHitLineWidth = 3
self.HitLineWidth = 3 ## this gets re-set by the subclasses if necessary
self.Brush = None
self.Pen = None
self.FillStyle = "Solid"
# I pre-define all these as class variables to provide an easier
# interface, and perhaps speed things up by caching all the Pens
@@ -326,7 +284,7 @@ class DrawObject:
self._Canvas.MakeNewHTdc()
if not self.HitColor:
if not self._Canvas.HitColorGenerator:
self._Canvas.HitColorGenerator = colorGenerator()
self._Canvas.HitColorGenerator = _colorGenerator()
self._Canvas.HitColorGenerator.next() # first call to prevent the background color from being used.
self.HitColor = self._Canvas.HitColorGenerator.next()
self.SetHitPen(self.HitColor,self.HitLineWidth)
@@ -347,6 +305,7 @@ class DrawObject:
pass
self.HitAble = False
def SetBrush(self,FillColor,FillStyle):
if FillColor is None or FillStyle is None:
self.Brush = wx.TRANSPARENT_BRUSH
@@ -371,7 +330,7 @@ class DrawObject:
if not self.HitLine:
self.HitPen = wx.TRANSPARENT_PEN
else:
self.HitPen = self.PenList.setdefault( (HitColor, "solid", LineWidth), wx.Pen(HitColor, LineWidth, self.LineStyleList["Solid"]) )
self.HitPen = self.PenList.setdefault( (HitColor, "solid", self.HitLineWidth), wx.Pen(HitColor, self.HitLineWidth, self.LineStyleList["Solid"]) )
def PutInBackground(self):
if self._Canvas and self.InForeground:
@@ -387,6 +346,55 @@ class DrawObject:
self._Canvas._BackgroundDirty = True
self.InForeground = True
class ColorOnlyMixin:
"""
Mixin class for objects that have just one color, rather than a fill
color and line color
"""
def SetColor(self, Color):
self.SetPen(Color,"Solid",1)
self.SetBrush(Color,"Solid")
SetFillColor = SetColor # Just to provide a consistant interface
class LineOnlyMixin:
"""
Mixin class for objects that have just one color, rather than a fill
color and line color
"""
def SetLineColor(self, LineColor):
self.LineColor = LineColor
self.SetPen(LineColor,self.LineStyle,self.LineWidth)
def SetLineStyle(self, LineStyle):
self.LineStyle = LineStyle
self.SetPen(self.LineColor,LineStyle,self.LineWidth)
def SetLineWidth(self, LineWidth):
self.LineWidth = LineWidth
self.SetPen(self.LineColor,self.LineStyle,LineWidth)
class LineAndFillMixin(LineOnlyMixin):
"""
Mixin class for objects that have both a line and a fill color and
style.
"""
def SetFillColor(self, FillColor):
self.FillColor = FillColor
self.SetBrush(FillColor,self.FillStyle)
def SetFillStyle(self, FillStyle):
self.FillStyle = FillStyle
self.SetBrush(self.FillColor,FillStyle)
class XYObjectMixin:
"""
@@ -409,6 +417,15 @@ class XYObjectMixin:
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def SetXY(self, x, y):
self.XY = array( (x, y), Float)
self.CalcBoundingBox()
def SetPoint(self, xy):
self.XY = array( xy, Float)
self.XY.shape = (2,)
self.CalcBoundingBox()
class PointsObjectMixin:
"""
@@ -417,12 +434,15 @@ class PointsObjectMixin:
"""
## This is code for the XYMixin object, it needs to be adapeted and tested.
## This is code for the PointsObjectMixin object, it needs to be adapted and tested.
## Is the neccesary at all: you can always do:
## Object.SetPoints( Object.Points + delta, copy = False)
## def Move(self, Delta ):
## """
## Move(Delta): moves the object by delta, where delta is an (dx,
## dy) pair. Ideally a Numpy array or shape (2,)
## dy) pair. Ideally a Numpy array of shape (2,)
## """
@@ -432,15 +452,38 @@ class PointsObjectMixin:
## if self._Canvas:
## self._Canvas.BoundingBoxDirty = True
def SetPoints(self,Points):
self.Points = Points
self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
def CalcBoundingBox(self):
self.BoundingBox = array(((min(self.Points[:,0]),
min(self.Points[:,1]) ),
(max(self.Points[:,0]),
max(self.Points[:,1]) ) ), Float )
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def SetPoints(self, Points, copy = True):
"""
Sets the coordinates of the points of the object to Points (NX2 array).
By default, a copy is made, if copy is set to False, a reference
is used, iff Points is a NumPy array of Floats. This allows you
to change some or all of the points without making any copies.
For example:
Points = Object.Points
Points += (5,10) # shifts the points 5 in the x dir, and 10 in the y dir.
Object.SetPoints(Points, False) # Sets the points to the same array as it was
"""
if copy:
self.Points = array(Points, Float)
self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point
else:
self.Points = asarray(Points, Float)
self.CalcBoundingBox()
class Polygon(DrawObject,PointsObjectMixin):
class Polygon(DrawObject,PointsObjectMixin,LineAndFillMixin):
"""
@@ -450,6 +493,9 @@ class Polygon(DrawObject,PointsObjectMixin):
x-coordinate of point N and Points[N,1] is the y-coordinate for
arrays.
The other parameters specify various properties of the Polygon, and
should be self explanatory.
"""
def __init__(self,
Points,
@@ -461,7 +507,7 @@ class Polygon(DrawObject,PointsObjectMixin):
InForeground = False):
DrawObject.__init__(self,InForeground)
self.Points = array(Points,Float) # this DOES need to make a copy
self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
self.CalcBoundingBox()
self.LineColor = LineColor
self.LineStyle = LineStyle
@@ -517,13 +563,14 @@ class Polygon(DrawObject,PointsObjectMixin):
## dc.DrawLineList(Points,self.Pens)
class Line(DrawObject,PointsObjectMixin):
class Line(DrawObject,PointsObjectMixin,LineOnlyMixin):
"""
The Line class takes a list of 2-tuples, or a NX2 NumPy array of point coordinates.
so that Points[N][0] is the x-coordinate of point N and Points[N][1] is the y-coordinate
or Points[N,0] is the x-coordinate of point N and Points[N,1] is the y-coordinate for arrays.
It will draw a straight line if there are two points, and a polyline if there are more than two.
The Line class takes a list of 2-tuples, or a NX2 NumPy Float array
of point coordinates.
It will draw a straight line if there are two points, and a polyline
if there are more than two.
"""
def __init__(self,Points,
@@ -535,7 +582,7 @@ class Line(DrawObject,PointsObjectMixin):
self.Points = array(Points,Float)
self.BoundingBox = array(((min(self.Points[:,0]),min(self.Points[:,1])),(max(self.Points[:,0]),max(self.Points[:,1]))),Float)
self.CalcBoundingBox()
self.LineColor = LineColor
self.LineStyle = LineStyle
@@ -585,18 +632,24 @@ class Line(DrawObject,PointsObjectMixin):
## Points.shape = (-1,4)
## dc.DrawLineList(Points,self.Pens)
class PointSet(DrawObject):
class PointSet(DrawObject,PointsObjectMixin, ColorOnlyMixin):
"""
The PointSet class takes a list of 2-tuples, or a NX2 NumPy array of point coordinates.
so that Points[N][0] is the x-coordinate of point N and Points[N][1] is the y-coordinate
or Points[N,0] is the x-coordinate of point N and Points[N,1] is the y-coordinate for arrays.
Each point will be drawn the same color and Diameter. The Diameter is in screen points,
not world coordinates.
The PointSet class takes a list of 2-tuples, or a NX2 NumPy array of
point coordinates.
At this point, the hit-test code does not distingish between the
points, you will only know that one of the poins got hit, not which
one.
If Points is a sequence of tuples: Points[N][0] is the x-coordinate of
point N and Points[N][1] is the y-coordinate.
If Points is a NumPy array: Points[N,0] is the x-coordinate of point
N and Points[N,1] is the y-coordinate for arrays.
Each point will be drawn the same color and Diameter. The Diameter
is in screen pixels, not world coordinates.
The hit-test code does not distingish between the points, you will
only know that one of the points got hit, not which one. You can use
PointSet.FindClosestPoint(WorldPoint) to find out which one
In the case of points, the HitLineWidth is used as diameter.
@@ -606,27 +659,34 @@ class PointSet(DrawObject):
self.Points = array(Points,Float)
self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point
self.BoundingBox = array(((min(self.Points[:,0]),
min(self.Points[:,1])),
(max(self.Points[:,0]),
max(self.Points[:,1]))),Float)
self.Color = Color
self.CalcBoundingBox()
self.Diameter = Diameter
self.HitLineWidth = self.MinHitLineWidth
self.SetPen(Color,"Solid",1)
self.SetBrush(Color,"Solid")
self.SetColor(Color)
def SetPoints(self,Points):
self.Points = array(Points, Float)
self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point
self.BoundingBox = array(((min(self.Points[:,0]),
min(self.Points[:,1]) ),
(max(self.Points[:,0]),
max(self.Points[:,1]) ) ) )
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def SetDiameter(self,Diameter):
self.Diameter = Diameter
def FindClosestPoint(self, XY):
"""
Returns the index of the closest point to the point, XY, given
in World coordinates. It's essentially random which you get if
there are more than one that are the same.
This can be used to figure out which point got hit in a mouse
binding callback, for instance. It's a lot faster that using a
lot of separate points.
"""
## kind of ugly to minimize data copying
d = self.Points - XY
d = sum( power(d,2,d), 1 )
d = absolute( d, d ) # don't need the real distance, just which is smallest
#dist = sqrt( sum( (self.Points - XY)**2), 1) )
return argmin(d)
def DrawD2(self, dc, Points):
# A Little optimization for a diameter2 - point
@@ -645,57 +705,77 @@ class PointSet(DrawObject):
else:
dc.SetBrush(self.Brush)
radius = int(round(self.Diameter/2))
for xy in Points:
dc.DrawEllipsePointSize( (xy - radius), (self.Diameter, self.Diameter) )
if len(Points) > 100:
xy = Points
xywh = concatenate((xy-radius, ones(xy.shape) * self.Diameter ), 1 )
dc.DrawEllipseList(xywh)
else:
for xy in Points:
dc.DrawCircle(xy[0],xy[1], radius)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
HTdc.SetBrush(self.HitBrush)
if self.Diameter <= 1:
HTdc.DrawPointList(Points)
elif self.Diameter <= 2:
self.DrawD2(HTdc, Points)
else:
if len(Points) > 100:
xy = Points
xywh = concatenate((xy-radius, ones(xy.shape) * self.Diameter ), 1 )
HTdc.DrawEllipseList(xywh)
else:
for xy in Points:
HTdc.DrawCircle(xy[0],xy[1], radius)
class Point(DrawObject,XYObjectMixin,ColorOnlyMixin):
"""
The Point class takes a 2-tuple, or a (2,) NumPy array of point
coordinates.
The Diameter is in screen points, not world coordinates, So the
Bounding box is just the point, and doesn't include the Diameter.
The HitLineWidth is used as diameter for the
Hit Test.
"""
def __init__(self, XY, Color = "Black", Diameter = 1, InForeground = False):
DrawObject.__init__(self, InForeground)
self.XY = array(XY, Float)
self.XY.shape = (2,) # Make sure it is a 1X2 array, even if there is only one point
self.CalcBoundingBox()
self.SetColor(Color)
self.Diameter = Diameter
self.HitLineWidth = self.MinHitLineWidth
def SetDiameter(self,Diameter):
self.Diameter = Diameter
def CalcBoundingBox(self):
self.BoundingBox = array( (self.XY, self.XY), Float )
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
dc.SetPen(self.Pen)
xy = WorldToPixel(self.XY)
if self.Diameter <= 1:
dc.DrawPoint(xy[0], xy[1])
else:
dc.SetBrush(self.Brush)
radius = int(round(self.Diameter/2))
dc.DrawCircle(xy[0],xy[1], radius)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
if self.Diameter <= 1:
HTdc.DrawPoint(xy[0], xy[1])
else:
HTdc.SetBrush(self.HitBrush)
radius = int(round(self.Diameter/2))
for xy in Points:
HTdc.DrawEllipsePointSize( (xy - radius), (self.Diameter, self.Diameter) )
#### Does anyone need this?
##class Dot(DrawObject):
## """
## The Dot class takes an x.y coordinate pair, and the Diameter of the circle.
## The Diameter is in pixels, so it won't change with zoom.
HTdc.DrawCircle(xy[0],xy[1], radius)
## Also Fill and line data
## """
## def __init__(self,x,y,Diameter,LineColor,LineStyle,LineWidth,FillColor,FillStyle,InForeground = False):
## DrawObject.__init__(self,InForeground)
## self.X = x
## self.Y = y
## self.Diameter = Diameter
## # NOTE: the bounding box does not include the diameter of the dot, as that is in pixel coords.
## # If this is a problem, perhaps you should use a circle, instead!
## self.BoundingBox = array(((x,y),(x,y)),Float)
## self.LineColor = LineColor
## self.LineStyle = LineStyle
## self.LineWidth = LineWidth
## self.FillColor = FillColor
## self.FillStyle = FillStyle
## self.SetPen(LineColor,LineStyle,LineWidth)
## self.SetBrush(FillColor,FillStyle)
## def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
## #def _Draw(self,dc,WorldToPixel,ScaleWorldToPixel):
## dc.SetPen(self.Pen)
## dc.SetBrush(self.Brush)
## radius = int(round(self.Diameter/2))
## (X,Y) = WorldToPixel((self.X,self.Y))
## dc.DrawEllipse((X - radius), (Y - radius), self.Diameter, self.Diameter)
class RectEllipse(DrawObject, XYObjectMixin):
class RectEllipse(DrawObject, XYObjectMixin,LineAndFillMixin):
def __init__(self,x,y,width,height,
LineColor = "Black",
LineStyle = "Solid",
@@ -720,6 +800,11 @@ class RectEllipse(DrawObject, XYObjectMixin):
self.SetPen(LineColor,LineStyle,LineWidth)
self.SetBrush(FillColor,FillStyle)
def SetShape(self,x,y,width,height):
self.XY = array( (x, y), Float)
self.WH = array( (width, height), Float )
self.CalcBoundingBox()
def SetUpDraw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc):
dc.SetPen(self.Pen)
@@ -730,11 +815,9 @@ class RectEllipse(DrawObject, XYObjectMixin):
return ( WorldToPixel(self.XY),
ScaleWorldToPixel(self.WH) )
def SetXY(self, x, y):
self.XY = array( (x, y), Float)
def CalcBoundingBox(self):
self.BoundingBox = array((self.XY, (self.XY + self.WH) ), Float)
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
self._Canvas.BoundingBoxDirty = True
class Rectangle(RectEllipse):
@@ -766,14 +849,22 @@ class Ellipse(RectEllipse):
class Circle(Ellipse):
def __init__(self, x ,y, Diameter, **kwargs):
self.Center = array((x,y),Float)
RectEllipse.__init__(self ,
x-Diameter/2.,
y-Diameter/2.,
Diameter,
Diameter,
**kwargs)
def SetDiameter(self, Diameter):
x,y = self.Center - (Diameter/2.)
self.SetShape(x,
y,
Diameter,
Diameter)
class TextObjectMixin:
class TextObjectMixin(XYObjectMixin):
"""
A mix in class that holds attributes and methods that are needed by
@@ -802,6 +893,12 @@ class TextObjectMixin:
FaceName) )
return self.Font
def SetColor(self, Color):
self.Color = Color
def SetBackgroundColor(self, BackgroundColor):
self.BackgroundColor = BackgroundColor
## store the function that shift the coords for drawing text. The
## "c" parameter is the correction for world coordinates, rather
## than pixel coords as the y axis is reversed
@@ -893,20 +990,12 @@ class Text(DrawObject, TextObjectMixin):
self.XY = ( x,y )
# use a memDC -- ScreenDC doesn't work with 2.5.1 and GTK2
#dc = wx.MemoryDC()
#bitmap = wx.EmptyBitmap(1, 1)
#dc.SelectObject(bitmap)
#dc.SetFont(self.Font)
#(self.TextWidth, self.TextHeight) = dc.GetTextExtent(self.String)
(self.TextWidth, self.TextHeight) = (None, None)
self.ShiftFun = self.ShiftFunDict[Position]
def SetXY(self, x, y):
self.XY = ( x,y )
def CalcBoundingBox(self):
self.BoundingBox = array((self.XY, self.XY),Float)
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
XY = WorldToPixel(self.XY)
@@ -926,7 +1015,7 @@ class Text(DrawObject, TextObjectMixin):
HTdc.SetBrush(self.HitBrush)
HTdc.DrawRectanglePointSize(XY, (self.TextWidth, self.TextHeight) )
class ScaledText(DrawObject, TextObjectMixin, XYObjectMixin):
class ScaledText(DrawObject, TextObjectMixin):
"""
This class creates a text object that is scaled when zoomed. It is
placed at the coordinates, x,y. the "Position" argument is a two
@@ -942,22 +1031,18 @@ class ScaledText(DrawObject, TextObjectMixin, XYObjectMixin):
Family:
Font family, a generic way of referring to fonts without
specifying actual facename. One of::
specifying actual facename. One of:
wx.DEFAULT: Chooses a default font.
wx.DECORATI: A decorative font.
wx.ROMAN: A formal, serif font.
wx.SCRIPT: A handwriting font.
wx.SWISS: A sans-serif font.
wx.MODERN: A fixed pitch font.
NOTE: these are only as good as the wxWindows defaults, which aren't so good.
Style:
One of wx.NORMAL, wx.SLANT and wx.ITALIC.
Weight:
One of wx.NORMAL, wx.LIGHT and wx.BOLD.
Underline:
The value can be True or False. At present this may have an an
effect on Windows only.
@@ -1019,31 +1104,36 @@ class ScaledText(DrawObject, TextObjectMixin, XYObjectMixin):
self.Weight = Font.GetWeight()
# Experimental max font size value on wxGTK2: this works OK on
# my system If it's any larger, there is a crash, with the
# message: The application 'FloatCanvasDemo.py' lost its
# my system. If it's a lot larger, there is a crash, with the
# message:
#
# The application 'FloatCanvasDemo.py' lost its
# connection to the display :0.0; most likely the X server was
# shut down or you killed/destroyed the application.
self.MaxSize = 2750
#
# Windows and OS-X seem to be better behaved in this regard.
# They may not draw it, but they don't crash either!
self.MaxFontSize = 1000
self.ShiftFun = self.ShiftFunDict[Position]
## Compute the BB
self.CalcBoundingBox()
def CalcBoundingBox(self):
## this isn't exact, as fonts don't scale exactly.
dc = wx.MemoryDC()
bitmap = wx.EmptyBitmap(1, 1)
dc.SelectObject(bitmap) #wxMac needs a Bitmap selected for GetTextExtent to work.
DrawingSize = 40 # pts This effectively determines the resolution that the BB is computed to.
ScaleFactor = float(Size) / DrawingSize
ScaleFactor = float(self.Size) / DrawingSize
dc.SetFont(self.SetFont(DrawingSize, self.Family, self.Style, self.Weight, self.Underline, self.FaceName) )
(w,h) = dc.GetTextExtent(self.String)
w = w * ScaleFactor
h = h * ScaleFactor
x, y = self.ShiftFun(x, y, w, h, world = 1)
x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1)
self.BoundingBox = array(((x, y-h ),(x + w, y)),Float)
# the new coords are set to the corner of the BB:
#self.X = self.BoundingBox[0,0]
#self.Y = self.BoundingBox[1,1]
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
(X,Y) = WorldToPixel( (self.XY) )
@@ -1052,8 +1142,7 @@ class ScaledText(DrawObject, TextObjectMixin, XYObjectMixin):
## Check to see if the font size is large enough to blow up the X font server
## If so, limit it. Would it be better just to not draw it?
## note that this limit is dependent on how much memory you have, etc.
if Size > self.MaxSize:
Size = self.MaxSize
Size = min(Size, self.MaxFontSize)
dc.SetFont(self.SetFont(Size, self.Family, self.Style, self.Weight, self.Underline, self.FaceName))
dc.SetTextForeground(self.Color)
if self.BackgroundColor:
@@ -1258,13 +1347,13 @@ class FloatCanvas(wx.Panel):
EVT_FC_LEAVE_OBJECT: {},
}
def RaiseMouseEvent(self, Event, EventType):
def _RaiseMouseEvent(self, Event, EventType):
"""
This is called in various other places to raise a Mouse Event
"""
#print "in Raise Mouse Event", Event
pt = self.PixelToWorld( Event.GetPosition() )
evt = MouseEvent(EventType, Event, self.GetId(), pt)
evt = _MouseEvent(EventType, Event, self.GetId(), pt)
self.GetEventHandler().ProcessEvent(evt)
def HitTest(self, event, HitEvent):
@@ -1342,42 +1431,42 @@ class FloatCanvas(wx.Panel):
if self.GUIMode == "Mouse":
EventType = EVT_FC_LEFT_DCLICK
if not self.HitTest(event, EventType):
self.RaiseMouseEvent(event, EventType)
self._RaiseMouseEvent(event, EventType)
def MiddleDownEvent(self,event):
if self.GUIMode == "Mouse":
EventType = EVT_FC_MIDDLE_DOWN
if not self.HitTest(event, EventType):
self.RaiseMouseEvent(event, EventType)
self._RaiseMouseEvent(event, EventType)
def MiddleUpEvent(self,event):
if self.GUIMode == "Mouse":
EventType = EVT_FC_MIDDLE_UP
if not self.HitTest(event, EventType):
self.RaiseMouseEvent(event, EventType)
self._RaiseMouseEvent(event, EventType)
def MiddleDoubleClickEvent(self,event):
if self.GUIMode == "Mouse":
EventType = EVT_FC_MIDDLE_DCLICK
if not self.HitTest(event, EventType):
self.RaiseMouseEvent(event, EventType)
self._RaiseMouseEvent(event, EventType)
def RightUpEvent(self,event):
if self.GUIMode == "Mouse":
EventType = EVT_FC_RIGHT_UP
if not self.HitTest(event, EventType):
self.RaiseMouseEvent(event, EventType)
self._RaiseMouseEvent(event, EventType)
def RightDoubleCLickEvent(self,event):
if self.GUIMode == "Mouse":
EventType = EVT_FC_RIGHT_DCLICK
if not self.HitTest(event, EventType):
self.RaiseMouseEvent(event, EventType)
self._RaiseMouseEvent(event, EventType)
def WheelEvent(self,event):
if self.GUIMode == "Mouse":
self.RaiseMouseEvent(event, EVT_FC_MOUSEWHEEL)
self._RaiseMouseEvent(event, EVT_FC_MOUSEWHEEL)
def LeftDownEvent(self,event):
@@ -1395,7 +1484,7 @@ class FloatCanvas(wx.Panel):
elif self.GUIMode == "Mouse":
## check for a hit
if not self.HitTest(event, EVT_FC_LEFT_DOWN):
self.RaiseMouseEvent(event,EVT_FC_LEFT_DOWN)
self._RaiseMouseEvent(event,EVT_FC_LEFT_DOWN)
else:
pass
@@ -1432,7 +1521,7 @@ class FloatCanvas(wx.Panel):
elif self.GUIMode == "Mouse":
EventType = EVT_FC_LEFT_UP
if not self.HitTest(event, EventType):
self.RaiseMouseEvent(event, EventType)
self._RaiseMouseEvent(event, EventType)
else:
pass
@@ -1515,10 +1604,10 @@ class FloatCanvas(wx.Panel):
## Only do something if there are mouse over events bound
if self.HitDict and (self.HitDict[ EVT_FC_ENTER_OBJECT ] or self.HitDict[ EVT_FC_LEAVE_OBJECT ] ):
if not self.MouseOverTest(event):
self.RaiseMouseEvent(event,EVT_FC_MOTION)
self._RaiseMouseEvent(event,EVT_FC_MOTION)
else:
pass
self.RaiseMouseEvent(event,EVT_FC_MOTION)
self._RaiseMouseEvent(event,EVT_FC_MOTION)
else:
pass
@@ -1533,7 +1622,7 @@ class FloatCanvas(wx.Panel):
elif self.GUIMode == "Mouse":
EventType = EVT_FC_RIGHT_DOWN
if not self.HitTest(event, EventType):
self.RaiseMouseEvent(event, EventType)
self._RaiseMouseEvent(event, EventType)
else:
pass
@@ -1606,7 +1695,7 @@ class FloatCanvas(wx.Panel):
"""
#print "In Draw"
if self.PanelSize < (1,1):
if self.PanelSize < (1,1): # it's possible for this to get called before being properly initialized.
return
if self.Debug: start = clock()
ScreenDC = wx.ClientDC(self)
@@ -1868,7 +1957,9 @@ class FloatCanvas(wx.Panel):
a 2-tuple, or sequence of 2-tuples.
"""
#Note: this can be called by users code for various reasons, so asarray is needed.
return (((asarray(Coordinates,Float) - self.ViewPortCenter)*self.TransformVector)+(self.HalfPanelSize)).astype('i')
return (((asarray(Coordinates,Float) -
self.ViewPortCenter)*self.TransformVector)+
(self.HalfPanelSize)).astype('i')
def ScaleWorldToPixel(self,Lengths):
"""
@@ -1944,7 +2035,7 @@ class FloatCanvas(wx.Panel):
def _makeFloatCanvasAddMethods(): ## lrk's code for doing this in module __init__
classnames = ["Circle", "Ellipse", "Rectangle", "ScaledText", "Polygon",
"Line", "Text", "PointSet"]
"Line", "Text", "PointSet","Point"]
for classname in classnames:
klass = globals()[classname]
def getaddshapemethod(klass=klass):
@@ -1956,8 +2047,8 @@ def _makeFloatCanvasAddMethods(): ## lrk's code for doing this in module __init_
addshapemethod = getaddshapemethod()
methodname = "Add" + classname
setattr(FloatCanvas, methodname, addshapemethod)
docstring = " Creates %s and adds its reference to the canvas.\n" % classname
docstring += " Argument protocol same as %s class" % classname
docstring = "Creates %s and adds its reference to the canvas.\n" % classname
docstring += "Argument protocol same as %s class" % classname
if klass.__doc__:
docstring += ", whose docstring is:\n%s" % klass.__doc__
FloatCanvas.__dict__[methodname].__doc__ = docstring

View File

@@ -100,7 +100,8 @@ class NavCanvas(wx.Panel):
wx.EVT_BUTTON(self, ID_ZOOM_TO_FIT_BUTTON, self.ZoomToFit)
tb.Realize()
tb.SetSizeHints(tb.GetSize())
S = tb.GetSize()
tb.SetSizeHints(S[0],S[1])
return tb
def SetToolMode(self,event):

View File

@@ -90,6 +90,6 @@ Chris.Barker@noaa.gov
"""
__version__ = "0.8.3"
__version__ = "0.8.5"