]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/OGL.py
Inital fill in background, removed tabs, -1->wxID_ANY, TRUE->true, FALSE->false
[wxWidgets.git] / wxPython / demo / OGL.py
1 # -*- coding: iso-8859-1 -*-
2 # 11/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)
3 #
4 # o Updated for wx namespace
5 #
6 # 20040508 - Pierre Hjälm
7 #
8 # o Changed to use the python version of OGL
9 # o Added TextShape, CompositeShape and CompositeShape with divisions
10 #
11
12 import wx
13 import wx.lib.ogl as ogl
14
15 import images
16
17 #----------------------------------------------------------------------
18
19 class DiamondShape(ogl.PolygonShape):
20 def __init__(self, w=0.0, h=0.0):
21 ogl.PolygonShape.__init__(self)
22 if w == 0.0:
23 w = 60.0
24 if h == 0.0:
25 h = 60.0
26
27 points = [ (0.0, -h/2.0),
28 (w/2.0, 0.0),
29 (0.0, h/2.0),
30 (-w/2.0, 0.0),
31 ]
32
33 self.Create(points)
34
35
36 #----------------------------------------------------------------------
37
38 class RoundedRectangleShape(ogl.RectangleShape):
39 def __init__(self, w=0.0, h=0.0):
40 ogl.RectangleShape.__init__(self, w, h)
41 self.SetCornerRadius(-0.3)
42
43
44 #----------------------------------------------------------------------
45
46 class CompositeDivisionShape(ogl.CompositeShape):
47 def __init__(self, canvas):
48 ogl.CompositeShape.__init__(self)
49
50 self.SetCanvas(canvas)
51
52 # create a division in the composite
53 self.MakeContainer()
54
55 # add a shape to the original division
56 shape2 = ogl.RectangleShape(40, 60)
57 self.GetDivisions()[0].AddChild(shape2)
58
59 # now divide the division so we get 2
60 self.GetDivisions()[0].Divide(wx.HORIZONTAL)
61
62 # and add a shape to the second division (and move it to the
63 # centre of the division)
64 shape3 = ogl.CircleShape(40)
65 shape3.SetBrush(wx.CYAN_BRUSH)
66 self.GetDivisions()[1].AddChild(shape3)
67 shape3.SetX(self.GetDivisions()[1].GetX())
68
69 for division in self.GetDivisions():
70 division.SetSensitivityFilter(0)
71
72 #----------------------------------------------------------------------
73
74 class CompositeShape(ogl.CompositeShape):
75 def __init__(self, canvas):
76 ogl.CompositeShape.__init__(self)
77
78 self.SetCanvas(canvas)
79
80 constraining_shape = ogl.RectangleShape(120, 100)
81 constrained_shape1 = ogl.CircleShape(50)
82 constrained_shape2 = ogl.RectangleShape(80, 20)
83
84 constraining_shape.SetBrush(wx.BLUE_BRUSH)
85 constrained_shape2.SetBrush(wx.RED_BRUSH)
86
87 self.AddChild(constraining_shape)
88 self.AddChild(constrained_shape1)
89 self.AddChild(constrained_shape2)
90
91 constraint = ogl.Constraint(ogl.CONSTRAINT_MIDALIGNED_BOTTOM, constraining_shape, [constrained_shape1, constrained_shape2])
92 self.AddConstraint(constraint)
93 self.Recompute()
94
95 # If we don't do this, the shapes will be able to move on their
96 # own, instead of moving the composite
97 constraining_shape.SetDraggable(False)
98 constrained_shape1.SetDraggable(False)
99 constrained_shape2.SetDraggable(False)
100
101 # If we don't do this the shape will take all left-clicks for itself
102 constraining_shape.SetSensitivityFilter(0)
103
104
105 #----------------------------------------------------------------------
106
107 class DividedShape(ogl.DividedShape):
108 def __init__(self, width, height, canvas):
109 ogl.DividedShape.__init__(self, width, height)
110
111 region1 = ogl.ShapeRegion()
112 region1.SetText('DividedShape')
113 region1.SetProportions(0.0, 0.2)
114 region1.SetFormatMode(ogl.FORMAT_CENTRE_HORIZ)
115 self.AddRegion(region1)
116
117 region2 = ogl.ShapeRegion()
118 region2.SetText('This is Region number two.')
119 region2.SetProportions(0.0, 0.3)
120 region2.SetFormatMode(ogl.FORMAT_CENTRE_HORIZ|ogl.FORMAT_CENTRE_VERT)
121 self.AddRegion(region2)
122
123 region3 = ogl.ShapeRegion()
124 region3.SetText('Region 3\nwith embedded\nline breaks')
125 region3.SetProportions(0.0, 0.5)
126 region3.SetFormatMode(ogl.FORMAT_NONE)
127 self.AddRegion(region3)
128
129 self.SetRegionSizes()
130 self.ReformatRegions(canvas)
131
132
133 def ReformatRegions(self, canvas=None):
134 rnum = 0
135
136 if canvas is None:
137 canvas = self.GetCanvas()
138
139 dc = wx.ClientDC(canvas) # used for measuring
140
141 for region in self.GetRegions():
142 text = region.GetText()
143 self.FormatText(dc, text, rnum)
144 rnum += 1
145
146
147 def OnSizingEndDragLeft(self, pt, x, y, keys, attch):
148 print "***", self
149 ogl.DividedShape.OnSizingEndDragLeft(self, pt, x, y, keys, attch)
150 self.SetRegionSizes()
151 self.ReformatRegions()
152 self.GetCanvas().Refresh()
153
154
155 #----------------------------------------------------------------------
156
157 class MyEvtHandler(ogl.ShapeEvtHandler):
158 def __init__(self, log, frame):
159 ogl.ShapeEvtHandler.__init__(self)
160 self.log = log
161 self.statbarFrame = frame
162
163 def UpdateStatusBar(self, shape):
164 x, y = shape.GetX(), shape.GetY()
165 width, height = shape.GetBoundingBoxMax()
166 self.statbarFrame.SetStatusText("Pos: (%d, %d) Size: (%d, %d)" %
167 (x, y, width, height))
168
169
170 def OnLeftClick(self, x, y, keys=0, attachment=0):
171 shape = self.GetShape()
172 canvas = shape.GetCanvas()
173 dc = wx.ClientDC(canvas)
174 canvas.PrepareDC(dc)
175
176 if shape.Selected():
177 shape.Select(False, dc)
178 canvas.Redraw(dc)
179 else:
180 redraw = False
181 shapeList = canvas.GetDiagram().GetShapeList()
182 toUnselect = []
183
184 for s in shapeList:
185 if s.Selected():
186 # If we unselect it now then some of the objects in
187 # shapeList will become invalid (the control points are
188 # shapes too!) and bad things will happen...
189 toUnselect.append(s)
190
191 shape.Select(True, dc)
192
193 if toUnselect:
194 for s in toUnselect:
195 s.Select(False, dc)
196
197 canvas.Redraw(dc)
198
199 self.UpdateStatusBar(shape)
200
201
202 def OnEndDragLeft(self, x, y, keys=0, attachment=0):
203 shape = self.GetShape()
204 ogl.ShapeEvtHandler.OnEndDragLeft(self, x, y, keys, attachment)
205
206 if not shape.Selected():
207 self.OnLeftClick(x, y, keys, attachment)
208
209 self.UpdateStatusBar(shape)
210
211
212 def OnSizingEndDragLeft(self, pt, x, y, keys, attch):
213 ogl.ShapeEvtHandler.OnSizingEndDragLeft(self, pt, x, y, keys, attch)
214 self.UpdateStatusBar(self.GetShape())
215
216
217 def OnMovePost(self, dc, x, y, oldX, oldY, display):
218 ogl.ShapeEvtHandler.OnMovePost(self, dc, x, y, oldX, oldY, display)
219 self.UpdateStatusBar(self.GetShape())
220
221
222 def OnRightClick(self, *dontcare):
223 self.log.WriteText("%s\n" % self.GetShape())
224
225
226 #----------------------------------------------------------------------
227
228 class TestWindow(ogl.ShapeCanvas):
229 def __init__(self, parent, log, frame):
230 ogl.ShapeCanvas.__init__(self, parent)
231
232 maxWidth = 1000
233 maxHeight = 1000
234 self.SetScrollbars(20, 20, maxWidth/20, maxHeight/20)
235
236 self.log = log
237 self.frame = frame
238 self.SetBackgroundColour("LIGHT BLUE") #wx.WHITE)
239 self.diagram = ogl.Diagram()
240 self.SetDiagram(self.diagram)
241 self.diagram.SetCanvas(self)
242 self.shapes = []
243 self.save_gdi = []
244
245 rRectBrush = wx.Brush("MEDIUM TURQUOISE", wx.SOLID)
246 dsBrush = wx.Brush("WHEAT", wx.SOLID)
247
248 self.MyAddShape(
249 CompositeDivisionShape(self),
250 310, 310, wx.BLACK_PEN, wx.BLUE_BRUSH, "Division"
251 )
252
253 self.MyAddShape(
254 CompositeShape(self),
255 100, 260, wx.BLACK_PEN, wx.RED_BRUSH, "Composite"
256 )
257
258 self.MyAddShape(
259 ogl.CircleShape(80),
260 100, 100, wx.Pen(wx.BLUE, 3), wx.GREEN_BRUSH, "Circle"
261 )
262
263 self.MyAddShape(
264 ogl.TextShape(45, 30),
265 205, 60, wx.GREEN_PEN, wx.LIGHT_GREY_BRUSH, "Text"
266 )
267
268 self.MyAddShape(
269 ogl.RectangleShape(85, 50),
270 305, 60, wx.BLACK_PEN, wx.LIGHT_GREY_BRUSH, "Rectangle"
271 )
272
273 ds = self.MyAddShape(
274 DividedShape(140, 150, self),
275 515, 145, wx.BLACK_PEN, dsBrush, ''
276 )
277
278 self.MyAddShape(
279 DiamondShape(90, 90),
280 445, 305, wx.Pen(wx.BLUE, 3, wx.DOT), wx.RED_BRUSH, "Polygon"
281 )
282
283 self.MyAddShape(
284 RoundedRectangleShape(95, 70),
285 345, 145, wx.Pen(wx.RED, 2), rRectBrush, "Rounded Rect"
286 )
287
288 bmp = images.getTest2Bitmap()
289 mask = wx.Mask(bmp, wx.BLUE)
290 bmp.SetMask(mask)
291
292 s = ogl.BitmapShape()
293 s.SetBitmap(bmp)
294 self.MyAddShape(s, 225, 130, None, None, "Bitmap")
295
296 dc = wx.ClientDC(self)
297 self.PrepareDC(dc)
298
299 for x in range(len(self.shapes)):
300 fromShape = self.shapes[x]
301 if x+1 == len(self.shapes):
302 toShape = self.shapes[0]
303 else:
304 toShape = self.shapes[x+1]
305
306 line = ogl.LineShape()
307 line.SetCanvas(self)
308 line.SetPen(wx.BLACK_PEN)
309 line.SetBrush(wx.BLACK_BRUSH)
310 line.AddArrow(ogl.ARROW_ARROW)
311 line.MakeLineControlPoints(2)
312 fromShape.AddLine(line, toShape)
313 self.diagram.AddShape(line)
314 line.Show(True)
315
316
317 def MyAddShape(self, shape, x, y, pen, brush, text):
318 # Composites have to be moved for all children to get in place
319 if isinstance(shape, ogl.CompositeShape):
320 dc = wx.ClientDC(self)
321 self.PrepareDC(dc)
322 shape.Move(dc, x, y)
323 else:
324 shape.SetDraggable(True, True)
325 shape.SetCanvas(self)
326 shape.SetX(x)
327 shape.SetY(y)
328 if pen: shape.SetPen(pen)
329 if brush: shape.SetBrush(brush)
330 if text: shape.AddText(text)
331 #shape.SetShadowMode(ogl.SHADOW_RIGHT)
332 self.diagram.AddShape(shape)
333 shape.Show(True)
334
335 evthandler = MyEvtHandler(self.log, self.frame)
336 evthandler.SetShape(shape)
337 evthandler.SetPreviousHandler(shape.GetEventHandler())
338 shape.SetEventHandler(evthandler)
339
340 self.shapes.append(shape)
341 return shape
342
343
344 def OnBeginDragLeft(self, x, y, keys):
345 self.log.write("OnBeginDragLeft: %s, %s, %s\n" % (x, y, keys))
346
347 def OnEndDragLeft(self, x, y, keys):
348 self.log.write("OnEndDragLeft: %s, %s, %s\n" % (x, y, keys))
349
350
351 #----------------------------------------------------------------------
352
353 def runTest(frame, nb, log):
354 # This creates some pens and brushes that the OGL library uses.
355 # It should be called after the app object has been created, but
356 # before OGL is used.
357 ogl.OGLInitialize()
358
359 win = TestWindow(nb, log, frame)
360 return win
361
362 #----------------------------------------------------------------------
363
364
365 overview = """<html><body>
366 <h2>Object Graphics Library</h2>
367
368 The Object Graphics Library is a library supporting the creation and
369 manipulation of simple and complex graphic images on a canvas.
370
371 <p>The OGL library was originally written in C++ and provided to
372 wxPython via an extension module wrapper as is most of the rest of
373 wxPython. The code has now been ported to Python (with many thanks to
374 Pierre Hjälm!) in order to make it be more easily maintainable and
375 less likely to get rusty because nobody cares about the C++ lib any
376 more.
377
378 <p>The Python version should be mostly drop-in compatible with the
379 wrapped C++ version, except for the location of the package
380 (wx.lib.ogl instead of wx.ogl) and that the base class methods are
381 called the normal Python way (superclass.Method(self, ...)) instead of the
382 hacky way that had to be done to support overloaded methods with the
383 old SWIG (self.base_Method(...))
384
385
386 """
387
388 if __name__ == '__main__':
389 import sys, os
390 import run
391 run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
392