From: Robin Dunn Date: Wed, 21 Jul 2004 19:19:47 +0000 (+0000) Subject: Updates from Chris X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/5e1796efd30885c38cdf3d4779ad9ce026111649 Updates from Chris git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28362 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/wxPython/demo/FloatCanvas.py b/wxPython/demo/FloatCanvas.py index 275b8d852e..0c1f670d1f 100644 --- a/wxPython/demo/FloatCanvas.py +++ b/wxPython/demo/FloatCanvas.py @@ -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) - - -## ObjectList = [] - -## 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 - -## # 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])) + 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() + + Range = (-10,10) + colors = self.colors + + self.UnBindAllMouseEvents() + Canvas = self.Canvas + + 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) - -## # 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")) + # 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)) -## # 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]) ) + # 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])) -## # 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) + # 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) + ## 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" + 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")) -## # 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") + # 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 diff --git a/wxPython/wx/lib/floatcanvas/FloatCanvas.py b/wxPython/wx/lib/floatcanvas/FloatCanvas.py index 0d5142fcab..5d78e94cb2 100644 --- a/wxPython/wx/lib/floatcanvas/FloatCanvas.py +++ b/wxPython/wx/lib/floatcanvas/FloatCanvas.py @@ -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): -## """ - -## 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 - -## """ + """ + Utility function used by _colorGenerator -## 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. + + 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. - 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. + 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: - 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. + 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) -## Also Fill and line data +class Point(DrawObject,XYObjectMixin,ColorOnlyMixin): + """ + + The Point class takes a 2-tuple, or a (2,) NumPy array of point + coordinates. -## """ -## def __init__(self,x,y,Diameter,LineColor,LineStyle,LineWidth,FillColor,FillStyle,InForeground = False): -## DrawObject.__init__(self,InForeground) + 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.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.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.LineColor = LineColor -## self.LineStyle = LineStyle -## self.LineWidth = LineWidth -## self.FillColor = FillColor -## self.FillStyle = FillStyle + self.HitLineWidth = self.MinHitLineWidth -## self.SetPen(LineColor,LineStyle,LineWidth) -## self.SetBrush(FillColor,FillStyle) + def SetDiameter(self,Diameter): + self.Diameter = Diameter -## 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) + def CalcBoundingBox(self): + self.BoundingBox = array( (self.XY, self.XY), Float ) -class RectEllipse(DrawObject, XYObjectMixin): + 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) + HTdc.DrawCircle(xy[0],xy[1], radius) + +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 diff --git a/wxPython/wx/lib/floatcanvas/NavCanvas.py b/wxPython/wx/lib/floatcanvas/NavCanvas.py index 5d7ee0cadc..6a2f788649 100644 --- a/wxPython/wx/lib/floatcanvas/NavCanvas.py +++ b/wxPython/wx/lib/floatcanvas/NavCanvas.py @@ -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): diff --git a/wxPython/wx/lib/floatcanvas/__init__.py b/wxPython/wx/lib/floatcanvas/__init__.py index 0467819623..b47f4d988b 100644 --- a/wxPython/wx/lib/floatcanvas/__init__.py +++ b/wxPython/wx/lib/floatcanvas/__init__.py @@ -90,6 +90,6 @@ Chris.Barker@noaa.gov """ -__version__ = "0.8.3" +__version__ = "0.8.5"