]> git.saurik.com Git - wxWidgets.git/blame - wxPython/demo/PseudoDC.py
For whatever reason, font-size 9 is now hardly readable on Mac. Using default font...
[wxWidgets.git] / wxPython / demo / PseudoDC.py
CommitLineData
7e664d85
RD
1
2import wx
3import images
4import random
5
6#---------------------------------------------------------------------------
7
b2bfee6c
RD
8W = 2000
9H = 2000
7e664d85
RD
10SW = 150
11SH = 150
b2bfee6c 12SHAPE_COUNT = 2500
6f67d537 13hitradius = 5
7e664d85
RD
14
15#---------------------------------------------------------------------------
16
17colours = [
18 "BLACK",
19 "BLUE",
20 "BLUE VIOLET",
21 "BROWN",
22 "CYAN",
23 "DARK GREY",
24 "DARK GREEN",
25 "GOLD",
26 "GREY",
27 "GREEN",
28 "MAGENTA",
29 "NAVY",
30 "PINK",
31 "RED",
32 "SKY BLUE",
33 "VIOLET",
34 "YELLOW",
35 ]
36
37
38
39class MyCanvas(wx.ScrolledWindow):
40 def __init__(self, parent, id, log, size = wx.DefaultSize):
41 wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, style=wx.SUNKEN_BORDER)
42
43 self.lines = []
44 self.maxWidth = W
45 self.maxHeight = H
46 self.x = self.y = 0
47 self.curLine = []
48 self.drawing = False
49
50 self.SetBackgroundColour("WHITE")
51 bmp = images.getTest2Bitmap()
52 mask = wx.Mask(bmp, wx.BLUE)
53 bmp.SetMask(mask)
54 self.bmp = bmp
55
56 self.SetVirtualSize((self.maxWidth, self.maxHeight))
57 self.SetScrollRate(20,20)
58
59 # create a PseudoDC to record our drawing
60 self.pdc = wx.PseudoDC()
61 self.pen_cache = {}
62 self.brush_cache = {}
63 self.DoDrawing(self.pdc)
64 log.write('Created PseudoDC draw list with %d operations!'%self.pdc.GetLen())
65
66 self.Bind(wx.EVT_PAINT, self.OnPaint)
67 self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x:None)
6f67d537 68 self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouse)
7e664d85 69
6f67d537
RD
70 # vars for handling mouse clicks
71 self.dragid = -1
72 self.lastpos = (0,0)
73
74 def ConvertEventCoords(self, event):
75 xView, yView = self.GetViewStart()
76 xDelta, yDelta = self.GetScrollPixelsPerUnit()
77 return (event.GetX() + (xView * xDelta),
78 event.GetY() + (yView * yDelta))
7e664d85 79
6f67d537
RD
80 def OffsetRect(self, r):
81 xView, yView = self.GetViewStart()
82 xDelta, yDelta = self.GetScrollPixelsPerUnit()
83 r.OffsetXY(-(xView*xDelta),-(yView*yDelta))
84
85 def OnMouse(self, event):
86 global hitradius
87 if event.LeftDown():
88 x,y = self.ConvertEventCoords(event)
89 #l = self.pdc.FindObjectsByBBox(x, y)
90 l = self.pdc.FindObjects(x, y, hitradius)
91 for id in l:
92 if not self.pdc.GetIdGreyedOut(id):
93 self.dragid = id
94 self.lastpos = (event.GetX(),event.GetY())
95 break
96 elif event.RightDown():
97 x,y = self.ConvertEventCoords(event)
98 #l = self.pdc.FindObjectsByBBox(x, y)
99 l = self.pdc.FindObjects(x, y, hitradius)
100 if l:
101 self.pdc.SetIdGreyedOut(l[0], not self.pdc.GetIdGreyedOut(l[0]))
102 r = self.pdc.GetIdBounds(l[0])
103 r.Inflate(4,4)
104 self.OffsetRect(r)
105 self.RefreshRect(r, False)
106 elif event.Dragging() or event.LeftUp():
107 if self.dragid != -1:
108 x,y = self.lastpos
109 dx = event.GetX() - x
110 dy = event.GetY() - y
111 r = self.pdc.GetIdBounds(self.dragid)
112 self.pdc.TranslateId(self.dragid, dx, dy)
113 r2 = self.pdc.GetIdBounds(self.dragid)
114 r = r.Union(r2)
115 r.Inflate(4,4)
116 self.OffsetRect(r)
7e664d85 117 self.RefreshRect(r, False)
6f67d537
RD
118 self.lastpos = (event.GetX(),event.GetY())
119 if event.LeftUp():
120 self.dragid = -1
7e664d85
RD
121
122 def RandomPen(self):
123 c = random.choice(colours)
124 t = random.randint(1, 4)
125 if not self.pen_cache.has_key( (c, t) ):
126 self.pen_cache[(c, t)] = wx.Pen(c, t)
127 return self.pen_cache[(c, t)]
128
129
130 def RandomBrush(self):
131 c = random.choice(colours)
132 if not self.brush_cache.has_key(c):
133 self.brush_cache[c] = wx.Brush(c)
134
135 return self.brush_cache[c]
136
137 def RandomColor(self):
138 return random.choice(colours)
139
140
141 def OnPaint(self, event):
142 # Create a buffered paint DC. It will create the real
143 # wx.PaintDC and then blit the bitmap to it when dc is
144 # deleted.
145 dc = wx.BufferedPaintDC(self)
6f67d537
RD
146 # use PrepateDC to set position correctly
147 self.PrepareDC(dc)
7e664d85
RD
148 # we need to clear the dc BEFORE calling PrepareDC
149 bg = wx.Brush(self.GetBackgroundColour())
150 dc.SetBackground(bg)
151 dc.Clear()
7e664d85
RD
152 # create a clipping rect from our position and size
153 # and the Update Region
154 xv, yv = self.GetViewStart()
155 dx, dy = self.GetScrollPixelsPerUnit()
156 x, y = (xv * dx, yv * dy)
157 rgn = self.GetUpdateRegion()
158 rgn.Offset(x,y)
159 r = rgn.GetBox()
160 # draw to the dc using the calculated clipping rect
161 self.pdc.DrawToDCClipped(dc,r)
162
163 def DoDrawing(self, dc):
164 random.seed()
165 self.objids = []
166 self.boundsdict = {}
167 dc.BeginDrawing()
168 for i in range(SHAPE_COUNT):
169 id = wx.NewId()
170 dc.SetId(id)
171 choice = random.randint(0,8)
172 if choice in (0,1):
173 x = random.randint(0, W)
174 y = random.randint(0, H)
6f67d537
RD
175 pen = self.RandomPen()
176 dc.SetPen(pen)
7e664d85 177 dc.DrawPoint(x,y)
6f67d537
RD
178 r = wx.Rect(x,y,1,1)
179 r.Inflate(pen.GetWidth(),pen.GetWidth())
180 dc.SetIdBounds(id,r)
7e664d85
RD
181 elif choice in (2,3):
182 x1 = random.randint(0, W-SW)
183 y1 = random.randint(0, H-SH)
184 x2 = random.randint(x1, x1+SW)
185 y2 = random.randint(y1, y1+SH)
6f67d537
RD
186 pen = self.RandomPen()
187 dc.SetPen(pen)
7e664d85 188 dc.DrawLine(x1,y1,x2,y2)
6f67d537
RD
189 r = wx.Rect(x1,y1,x2-x1,y2-y1)
190 r.Inflate(pen.GetWidth(),pen.GetWidth())
191 dc.SetIdBounds(id,r)
7e664d85
RD
192 elif choice in (4,5):
193 w = random.randint(10, SW)
194 h = random.randint(10, SH)
195 x = random.randint(0, W - w)
196 y = random.randint(0, H - h)
6f67d537
RD
197 pen = self.RandomPen()
198 dc.SetPen(pen)
7e664d85
RD
199 dc.SetBrush(self.RandomBrush())
200 dc.DrawRectangle(x,y,w,h)
6f67d537
RD
201 r = wx.Rect(x,y,w,h)
202 r.Inflate(pen.GetWidth(),pen.GetWidth())
203 dc.SetIdBounds(id,r)
7e664d85
RD
204 self.objids.append(id)
205 elif choice == 6:
206 Np = 8 # number of characters in text
207 word = []
208 for i in range(Np):
209 c = chr( random.randint(48, 122) )
210 word.append( c )
211 word = "".join(word)
212 w,h = self.GetFullTextExtent(word)[0:2]
213 x = random.randint(0, W-w)
214 y = random.randint(0, H-h)
6f67d537 215 dc.SetFont(self.GetFont())
7e664d85
RD
216 dc.SetTextForeground(self.RandomColor())
217 dc.SetTextBackground(self.RandomColor())
218 dc.DrawText(word, x, y)
6f67d537
RD
219 r = wx.Rect(x,y,w,h)
220 r.Inflate(2,2)
221 dc.SetIdBounds(id, r)
7e664d85
RD
222 self.objids.append(id)
223 elif choice == 7:
224 Np = 8 # number of points per polygon
225 poly = []
226 minx = SW
227 miny = SH
228 maxx = 0
229 maxy = 0
230 for i in range(Np):
231 x = random.randint(0, SW)
232 y = random.randint(0, SH)
233 if x < minx: minx = x
234 if x > maxx: maxx = x
235 if y < miny: miny = y
236 if y > maxy: maxy = y
237 poly.append(wx.Point(x,y))
238 x = random.randint(0, W-SW)
239 y = random.randint(0, H-SH)
6f67d537
RD
240 pen = self.RandomPen()
241 dc.SetPen(pen)
7e664d85
RD
242 dc.SetBrush(self.RandomBrush())
243 dc.DrawPolygon(poly, x,y)
6f67d537
RD
244 r = wx.Rect(minx+x,miny+y,maxx-minx,maxy-miny)
245 r.Inflate(pen.GetWidth(),pen.GetWidth())
246 dc.SetIdBounds(id,r)
7e664d85
RD
247 self.objids.append(id)
248 elif choice == 8:
249 w,h = self.bmp.GetSize()
250 x = random.randint(0, W-w)
251 y = random.randint(0, H-h)
252 dc.DrawBitmap(self.bmp,x,y,True)
253 dc.SetIdBounds(id,wx.Rect(x,y,w,h))
254 self.objids.append(id)
255 dc.EndDrawing()
256
6f67d537
RD
257class ControlPanel(wx.Panel):
258 def __init__(self, parent, id, pos=wx.DefaultPosition,
259 size=wx.DefaultSize, style = wx.TAB_TRAVERSAL):
260 wx.Panel.__init__(self,parent,id,pos,size,style)
261 lbl = wx.StaticText(self, wx.ID_ANY, "Hit Test Radius: ")
262 lbl2 = wx.StaticText(self, wx.ID_ANY, "Left Click to drag, Right Click to enable/disable")
263 sc = wx.SpinCtrl(self, wx.ID_ANY, "5")
264 sc.SetRange(0,100)
265 global hitradius
266 sc.SetValue(hitradius)
267 self.sc = sc
268 sz = wx.BoxSizer(wx.HORIZONTAL)
269 sz.Add(lbl,0,wx.EXPAND)
270 sz.Add(sc,0)
271 sz.Add(lbl2,0,wx.LEFT,5)
272 sz.Add((10,10),1,wx.EXPAND)
273 self.SetSizerAndFit(sz)
274 sc.Bind(wx.EVT_SPINCTRL,self.OnChange)
275 sc.Bind(wx.EVT_TEXT,self.OnChange)
276
277 def OnChange(self, event):
278 global hitradius
279 hitradius = self.sc.GetValue()
280
7e664d85
RD
281
282#---------------------------------------------------------------------------
283
284def runTest(frame, nb, log):
6f67d537
RD
285 pnl = wx.Panel(nb, wx.ID_ANY,size=(200,30))
286 pnl2 = ControlPanel(pnl,wx.ID_ANY)
287 win = MyCanvas(pnl, wx.ID_ANY, log)
288 sz = wx.BoxSizer(wx.VERTICAL)
289 sz.Add(pnl2,0,wx.EXPAND|wx.ALL,5)
290 sz.Add(win,1,wx.EXPAND)
291 pnl.SetSizerAndFit(sz)
292 return pnl
7e664d85
RD
293
294#---------------------------------------------------------------------------
295
296
297
298overview = """
299<html>
300<body>
619d5930
RD
301<h2>wx.PseudoDC</h2>
302
7e664d85
RD
303The wx.PseudoDC class provides a way to record operations on a DC and then
304play them back later. The PseudoDC can be passed to a drawing routine as
305if it were a real DC. All Drawing methods are supported except Blit but
306GetXXX methods are not supported and none of the drawing methods return
307a value. The PseudoDC records the drawing to an operation
308list. The operations can be played back to a real DC using:<pre>
309DrawToDC(dc)
310</pre>
311The operations can be tagged with an id in order to associated them with a
312specific object. To do this use:<pre>
619d5930 313 SetId(id)
7e664d85
RD
314</pre>
315Every operation after this will be associated with id until SetId is called
316again. The PseudoDC also supports object level clipping. To enable this use:<pre>
619d5930 317 SetIdBounds(id,rect)
7e664d85
RD
318</pre>
319for each object that should be clipped. Then use:<pre>
619d5930 320 DrawToDCClipped(dc, clippingRect)
7e664d85
RD
321</pre>
322To draw the PseudoDC to a real dc. This is useful for large scrolled windows
323where many objects are offscreen.
324
325Objects can be moved around without re-drawing using:<pre>
619d5930 326 TranslateId(id, dx, dy)
7e664d85
RD
327</pre>
328
329To re-draw an object use:<pre>
619d5930
RD
330 ClearId(id)
331 SetId(id)
7e664d85
RD
332</pre>
333and then re-draw the object.
334</body>
335</html>
336"""
337
338
339if __name__ == '__main__':
340 import sys,os
341 import run
342 run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
343