git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41653 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			344 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			344 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
 | |
| import wx
 | |
| import images
 | |
| import random
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| W = 2000
 | |
| H = 2000
 | |
| SW = 150
 | |
| SH = 150
 | |
| SHAPE_COUNT = 2500
 | |
| hitradius = 5
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| colours = [
 | |
|     "BLACK",
 | |
|     "BLUE",
 | |
|     "BLUE VIOLET",
 | |
|     "BROWN",
 | |
|     "CYAN",
 | |
|     "DARK GREY",
 | |
|     "DARK GREEN",
 | |
|     "GOLD",
 | |
|     "GREY",
 | |
|     "GREEN",
 | |
|     "MAGENTA",
 | |
|     "NAVY",
 | |
|     "PINK",
 | |
|     "RED",
 | |
|     "SKY BLUE",
 | |
|     "VIOLET",
 | |
|     "YELLOW",
 | |
|     ]
 | |
| 
 | |
| 
 | |
| 
 | |
| class MyCanvas(wx.ScrolledWindow):
 | |
|     def __init__(self, parent, id, log, size = wx.DefaultSize):
 | |
|         wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, style=wx.SUNKEN_BORDER)
 | |
| 
 | |
|         self.lines = []
 | |
|         self.maxWidth  = W
 | |
|         self.maxHeight = H
 | |
|         self.x = self.y = 0
 | |
|         self.curLine = []
 | |
|         self.drawing = False
 | |
| 
 | |
|         self.SetBackgroundColour("WHITE")
 | |
|         bmp = images.getTest2Bitmap()
 | |
|         mask = wx.Mask(bmp, wx.BLUE)
 | |
|         bmp.SetMask(mask)
 | |
|         self.bmp = bmp
 | |
| 
 | |
|         self.SetVirtualSize((self.maxWidth, self.maxHeight))
 | |
|         self.SetScrollRate(20,20)
 | |
|         
 | |
|         # create a PseudoDC to record our drawing
 | |
|         self.pdc = wx.PseudoDC()
 | |
|         self.pen_cache = {}
 | |
|         self.brush_cache = {}
 | |
|         self.DoDrawing(self.pdc)
 | |
|         log.write('Created PseudoDC draw list with %d operations!'%self.pdc.GetLen())
 | |
| 
 | |
|         self.Bind(wx.EVT_PAINT, self.OnPaint)
 | |
|         self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x:None)
 | |
|         self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
 | |
|         
 | |
|         # vars for handling mouse clicks
 | |
|         self.dragid = -1
 | |
|         self.lastpos = (0,0)
 | |
|     
 | |
|     def ConvertEventCoords(self, event):
 | |
|         xView, yView = self.GetViewStart()
 | |
|         xDelta, yDelta = self.GetScrollPixelsPerUnit()
 | |
|         return (event.GetX() + (xView * xDelta),
 | |
|             event.GetY() + (yView * yDelta))
 | |
| 
 | |
|     def OffsetRect(self, r):
 | |
|         xView, yView = self.GetViewStart()
 | |
|         xDelta, yDelta = self.GetScrollPixelsPerUnit()
 | |
|         r.OffsetXY(-(xView*xDelta),-(yView*yDelta))
 | |
| 
 | |
|     def OnMouse(self, event):
 | |
|         global hitradius
 | |
|         if event.LeftDown():
 | |
|             x,y = self.ConvertEventCoords(event)
 | |
|             #l = self.pdc.FindObjectsByBBox(x, y)
 | |
|             l = self.pdc.FindObjects(x, y, hitradius)
 | |
|             for id in l:
 | |
|                 if not self.pdc.GetIdGreyedOut(id):
 | |
|                     self.dragid = id
 | |
|                     self.lastpos = (event.GetX(),event.GetY())
 | |
|                     break
 | |
|         elif event.RightDown():
 | |
|             x,y = self.ConvertEventCoords(event)
 | |
|             #l = self.pdc.FindObjectsByBBox(x, y)
 | |
|             l = self.pdc.FindObjects(x, y, hitradius)
 | |
|             if l:
 | |
|                 self.pdc.SetIdGreyedOut(l[0], not self.pdc.GetIdGreyedOut(l[0]))
 | |
|                 r = self.pdc.GetIdBounds(l[0])
 | |
|                 r.Inflate(4,4)
 | |
|                 self.OffsetRect(r)
 | |
|                 self.RefreshRect(r, False)
 | |
|         elif event.Dragging() or event.LeftUp():
 | |
|             if self.dragid != -1:
 | |
|                 x,y = self.lastpos
 | |
|                 dx = event.GetX() - x
 | |
|                 dy = event.GetY() - y
 | |
|                 r = self.pdc.GetIdBounds(self.dragid)
 | |
|                 self.pdc.TranslateId(self.dragid, dx, dy)
 | |
|                 r2 = self.pdc.GetIdBounds(self.dragid)
 | |
|                 r = r.Union(r2)
 | |
|                 r.Inflate(4,4)
 | |
|                 self.OffsetRect(r)
 | |
|                 self.RefreshRect(r, False)
 | |
|                 self.lastpos = (event.GetX(),event.GetY())
 | |
|             if event.LeftUp():
 | |
|                 self.dragid = -1
 | |
| 
 | |
|     def RandomPen(self):
 | |
|         c = random.choice(colours)
 | |
|         t = random.randint(1, 4)
 | |
|         if not self.pen_cache.has_key( (c, t) ):
 | |
|             self.pen_cache[(c, t)] = wx.Pen(c, t)
 | |
|         return self.pen_cache[(c, t)]
 | |
| 
 | |
| 
 | |
|     def RandomBrush(self):
 | |
|         c = random.choice(colours)
 | |
|         if not self.brush_cache.has_key(c):
 | |
|             self.brush_cache[c] = wx.Brush(c)
 | |
| 
 | |
|         return self.brush_cache[c]
 | |
| 
 | |
|     def RandomColor(self):
 | |
|         return random.choice(colours)
 | |
| 
 | |
| 
 | |
|     def OnPaint(self, event):
 | |
|         # Create a buffered paint DC.  It will create the real
 | |
|         # wx.PaintDC and then blit the bitmap to it when dc is
 | |
|         # deleted.  
 | |
|         dc = wx.BufferedPaintDC(self)
 | |
|         # use PrepateDC to set position correctly
 | |
|         self.PrepareDC(dc)
 | |
|         # we need to clear the dc BEFORE calling PrepareDC
 | |
|         bg = wx.Brush(self.GetBackgroundColour())
 | |
|         dc.SetBackground(bg)
 | |
|         dc.Clear()
 | |
|         # create a clipping rect from our position and size
 | |
|         # and the Update Region
 | |
|         xv, yv = self.GetViewStart()
 | |
|         dx, dy = self.GetScrollPixelsPerUnit()
 | |
|         x, y   = (xv * dx, yv * dy)
 | |
|         rgn = self.GetUpdateRegion()
 | |
|         rgn.Offset(x,y)
 | |
|         r = rgn.GetBox()
 | |
|         # draw to the dc using the calculated clipping rect
 | |
|         self.pdc.DrawToDCClipped(dc,r)
 | |
| 
 | |
|     def DoDrawing(self, dc):
 | |
|         random.seed()
 | |
|         self.objids = []
 | |
|         self.boundsdict = {}
 | |
|         dc.BeginDrawing()
 | |
|         for i in range(SHAPE_COUNT):
 | |
|             id = wx.NewId()
 | |
|             dc.SetId(id)
 | |
|             choice = random.randint(0,8)
 | |
|             if choice in (0,1):
 | |
|                 x = random.randint(0, W)
 | |
|                 y = random.randint(0, H)
 | |
|                 pen = self.RandomPen()
 | |
|                 dc.SetPen(pen)
 | |
|                 dc.DrawPoint(x,y)
 | |
|                 r = wx.Rect(x,y,1,1)
 | |
|                 r.Inflate(pen.GetWidth(),pen.GetWidth())
 | |
|                 dc.SetIdBounds(id,r)
 | |
|             elif choice in (2,3):
 | |
|                 x1 = random.randint(0, W-SW)
 | |
|                 y1 = random.randint(0, H-SH)
 | |
|                 x2 = random.randint(x1, x1+SW)
 | |
|                 y2 = random.randint(y1, y1+SH)
 | |
|                 pen = self.RandomPen()
 | |
|                 dc.SetPen(pen)
 | |
|                 dc.DrawLine(x1,y1,x2,y2)
 | |
|                 r = wx.Rect(x1,y1,x2-x1,y2-y1)
 | |
|                 r.Inflate(pen.GetWidth(),pen.GetWidth())
 | |
|                 dc.SetIdBounds(id,r)
 | |
|             elif choice in (4,5):
 | |
|                 w = random.randint(10, SW)
 | |
|                 h = random.randint(10, SH)
 | |
|                 x = random.randint(0, W - w)
 | |
|                 y = random.randint(0, H - h)
 | |
|                 pen = self.RandomPen()
 | |
|                 dc.SetPen(pen)
 | |
|                 dc.SetBrush(self.RandomBrush())
 | |
|                 dc.DrawRectangle(x,y,w,h)
 | |
|                 r = wx.Rect(x,y,w,h)
 | |
|                 r.Inflate(pen.GetWidth(),pen.GetWidth())
 | |
|                 dc.SetIdBounds(id,r)
 | |
|                 self.objids.append(id)
 | |
|             elif choice == 6:
 | |
|                 Np = 8 # number of characters in text
 | |
|                 word = []
 | |
|                 for i in range(Np):
 | |
|                     c = chr( random.randint(48, 122) )
 | |
|                     word.append( c )
 | |
|                 word = "".join(word)
 | |
|                 w,h = self.GetFullTextExtent(word)[0:2]
 | |
|                 x = random.randint(0, W-w)
 | |
|                 y = random.randint(0, H-h)
 | |
|                 dc.SetFont(self.GetFont())
 | |
|                 dc.SetTextForeground(self.RandomColor())
 | |
|                 dc.SetTextBackground(self.RandomColor())
 | |
|                 dc.DrawText(word, x, y)
 | |
|                 r = wx.Rect(x,y,w,h)
 | |
|                 r.Inflate(2,2)
 | |
|                 dc.SetIdBounds(id, r)
 | |
|                 self.objids.append(id)
 | |
|             elif choice == 7:
 | |
|                 Np = 8 # number of points per polygon
 | |
|                 poly = []
 | |
|                 minx = SW
 | |
|                 miny = SH
 | |
|                 maxx = 0
 | |
|                 maxy = 0
 | |
|                 for i in range(Np):
 | |
|                     x = random.randint(0, SW)
 | |
|                     y = random.randint(0, SH)
 | |
|                     if x < minx: minx = x
 | |
|                     if x > maxx: maxx = x
 | |
|                     if y < miny: miny = y
 | |
|                     if y > maxy: maxy = y
 | |
|                     poly.append(wx.Point(x,y))
 | |
|                 x = random.randint(0, W-SW)
 | |
|                 y = random.randint(0, H-SH)
 | |
|                 pen = self.RandomPen()
 | |
|                 dc.SetPen(pen)
 | |
|                 dc.SetBrush(self.RandomBrush())
 | |
|                 dc.DrawPolygon(poly, x,y)
 | |
|                 r = wx.Rect(minx+x,miny+y,maxx-minx,maxy-miny)
 | |
|                 r.Inflate(pen.GetWidth(),pen.GetWidth())
 | |
|                 dc.SetIdBounds(id,r)
 | |
|                 self.objids.append(id)
 | |
|             elif choice == 8:
 | |
|                 w,h = self.bmp.GetSize()
 | |
|                 x = random.randint(0, W-w)
 | |
|                 y = random.randint(0, H-h)
 | |
|                 dc.DrawBitmap(self.bmp,x,y,True)
 | |
|                 dc.SetIdBounds(id,wx.Rect(x,y,w,h))
 | |
|                 self.objids.append(id)
 | |
|         dc.EndDrawing()
 | |
| 
 | |
| class ControlPanel(wx.Panel):
 | |
|     def __init__(self, parent, id, pos=wx.DefaultPosition,
 | |
|             size=wx.DefaultSize, style = wx.TAB_TRAVERSAL):
 | |
|         wx.Panel.__init__(self,parent,id,pos,size,style)
 | |
|         lbl = wx.StaticText(self, wx.ID_ANY, "Hit Test Radius: ")
 | |
|         lbl2 = wx.StaticText(self, wx.ID_ANY, "Left Click to drag, Right Click to enable/disable")
 | |
|         sc = wx.SpinCtrl(self, wx.ID_ANY, "5")
 | |
|         sc.SetRange(0,100)
 | |
|         global hitradius
 | |
|         sc.SetValue(hitradius)
 | |
|         self.sc = sc
 | |
|         sz = wx.BoxSizer(wx.HORIZONTAL)
 | |
|         sz.Add(lbl,0,wx.EXPAND)
 | |
|         sz.Add(sc,0)
 | |
|         sz.Add(lbl2,0,wx.LEFT,5)
 | |
|         sz.Add((10,10),1,wx.EXPAND)
 | |
|         self.SetSizerAndFit(sz)
 | |
|         sc.Bind(wx.EVT_SPINCTRL,self.OnChange)
 | |
|         sc.Bind(wx.EVT_TEXT,self.OnChange)
 | |
| 
 | |
|     def OnChange(self, event):
 | |
|         global hitradius
 | |
|         hitradius = self.sc.GetValue()
 | |
|     
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| def runTest(frame, nb, log):
 | |
|     pnl = wx.Panel(nb, wx.ID_ANY,size=(200,30))
 | |
|     pnl2 = ControlPanel(pnl,wx.ID_ANY)
 | |
|     win = MyCanvas(pnl, wx.ID_ANY, log)
 | |
|     sz = wx.BoxSizer(wx.VERTICAL)
 | |
|     sz.Add(pnl2,0,wx.EXPAND|wx.ALL,5)
 | |
|     sz.Add(win,1,wx.EXPAND)
 | |
|     pnl.SetSizerAndFit(sz)
 | |
|     return pnl
 | |
| 
 | |
| #---------------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| 
 | |
| overview = """
 | |
| <html>
 | |
| <body>
 | |
| <h2>wx.PseudoDC</h2>
 | |
| 
 | |
| The wx.PseudoDC class provides a way to record operations on a DC and then
 | |
| play them back later.  The PseudoDC can be passed to a drawing routine as
 | |
| if it were a real DC.  All Drawing methods are supported except Blit but
 | |
| GetXXX methods are not supported and none of the drawing methods return
 | |
| a value. The PseudoDC records the drawing to an operation
 | |
| list.  The operations can be played back to a real DC using:<pre>
 | |
| DrawToDC(dc)
 | |
| </pre>
 | |
| The operations can be tagged with an id in order to associated them with a
 | |
| specific object.  To do this use:<pre>
 | |
|     SetId(id)
 | |
| </pre>
 | |
| Every operation after this will be associated with id until SetId is called
 | |
| again.  The PseudoDC also supports object level clipping.  To enable this use:<pre>
 | |
|     SetIdBounds(id,rect)
 | |
| </pre>
 | |
| for each object that should be clipped.  Then use:<pre>
 | |
|     DrawToDCClipped(dc, clippingRect)
 | |
| </pre>
 | |
| To draw the PseudoDC to a real dc. This is useful for large scrolled windows 
 | |
| where many objects are offscreen.
 | |
| 
 | |
| Objects can be moved around without re-drawing using:<pre>
 | |
|     TranslateId(id, dx, dy)
 | |
| </pre>
 | |
| 
 | |
| To re-draw an object use:<pre>
 | |
|     ClearId(id)
 | |
|     SetId(id)
 | |
| </pre>
 | |
| and then re-draw the object.
 | |
| </body>
 | |
| </html>
 | |
| """
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     import sys,os
 | |
|     import run
 | |
|     run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
 | |
| 
 |