]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/OGL.py
wxUSE_STL/wxArrayString fixes.
[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 75, 110, wx.Pen(wx.BLUE, 3), wx.GREEN_BRUSH, "Circle"
261 )
262
263 self.MyAddShape(
264 ogl.TextShape(120, 45),
265 160, 35, wx.GREEN_PEN, wx.LIGHT_GREY_BRUSH, "OGL is now a\npure Python lib!"
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:
331 for line in text.split('\n'):
332 shape.AddText(line)
333 #shape.SetShadowMode(ogl.SHADOW_RIGHT)
334 self.diagram.AddShape(shape)
335 shape.Show(True)
336
337 evthandler = MyEvtHandler(self.log, self.frame)
338 evthandler.SetShape(shape)
339 evthandler.SetPreviousHandler(shape.GetEventHandler())
340 shape.SetEventHandler(evthandler)
341
342 self.shapes.append(shape)
343 return shape
344
345
346 def OnBeginDragLeft(self, x, y, keys):
347 self.log.write("OnBeginDragLeft: %s, %s, %s\n" % (x, y, keys))
348
349 def OnEndDragLeft(self, x, y, keys):
350 self.log.write("OnEndDragLeft: %s, %s, %s\n" % (x, y, keys))
351
352
353 #----------------------------------------------------------------------
354
355 def runTest(frame, nb, log):
356 # This creates some pens and brushes that the OGL library uses.
357 # It should be called after the app object has been created, but
358 # before OGL is used.
359 ogl.OGLInitialize()
360
361 win = TestWindow(nb, log, frame)
362 return win
363
364 #----------------------------------------------------------------------
365
366
367 overview = """<html><body>
368 <h2>Object Graphics Library</h2>
369
370 The Object Graphics Library is a library supporting the creation and
371 manipulation of simple and complex graphic images on a canvas.
372
373 <p>The OGL library was originally written in C++ and provided to
374 wxPython via an extension module wrapper as is most of the rest of
375 wxPython. The code has now been ported to Python (with many thanks to
376 Pierre Hjälm!) in order to make it be more easily maintainable and
377 less likely to get rusty because nobody cares about the C++ lib any
378 more.
379
380 <p>The Python version should be mostly drop-in compatible with the
381 wrapped C++ version, except for the location of the package
382 (wx.lib.ogl instead of wx.ogl) and that the base class methods are
383 called the normal Python way (superclass.Method(self, ...)) instead of the
384 hacky way that had to be done to support overloaded methods with the
385 old SWIG (self.base_Method(...))
386
387
388 """
389
390 if __name__ == '__main__':
391 import sys, os
392 import run
393 run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
394