# -*- coding: iso-8859-1 -*-# 11/20/2003 - Jeff Grimmett (grimmtooth@softhome.net)## o Updated for wx namespace# # 20040508 - Pierre Hjälm## o Changed to use the python version of OGL# o Added TextShape, CompositeShape and CompositeShape with divisions## 20040830 - Pierre Hjälm## o Added DrawnShape#importwximportwx.lib.oglasoglimportimages#----------------------------------------------------------------------classDrawnShape(ogl.DrawnShape):def__init__(self):ogl.DrawnShape.__init__(self)self.SetDrawnBrush(wx.WHITE_BRUSH)self.SetDrawnPen(wx.BLACK_PEN)self.DrawArc((0,-10),(30,0),(-30,0))self.SetDrawnPen(wx.Pen("#ff8030"))self.DrawLine((-30,5),(30,5))self.SetDrawnPen(wx.Pen("#00ee10"))self.DrawRoundedRectangle((-20,10,40,10),5)self.SetDrawnPen(wx.Pen("#9090f0"))self.DrawEllipse((-30,25,60,20))self.SetDrawnTextColour(wx.BLACK)self.SetDrawnFont(wx.Font(8,wx.SWISS,wx.NORMAL,wx.NORMAL))self.DrawText("DrawText",(-26,28))self.SetDrawnBrush(wx.GREEN_BRUSH)self.DrawPolygon([(-100,5),(-45,30),(-35,20),(-30,5)])self.SetDrawnPen(wx.BLACK_PEN)self.DrawLines([(30,-45),(40,-45),(40,45),(30,45)])# Make sure to call CalculateSize when all drawing is doneself.CalculateSize()#----------------------------------------------------------------------classDiamondShape(ogl.PolygonShape):def__init__(self,w=0.0,h=0.0):ogl.PolygonShape.__init__(self)ifw==0.0:w=60.0ifh==0.0:h=60.0points=[(0.0,-h/2.0),(w/2.0,0.0),(0.0,h/2.0),(-w/2.0,0.0),]self.Create(points)#----------------------------------------------------------------------classRoundedRectangleShape(ogl.RectangleShape):def__init__(self,w=0.0,h=0.0):ogl.RectangleShape.__init__(self,w,h)self.SetCornerRadius(-0.3)#----------------------------------------------------------------------classCompositeDivisionShape(ogl.CompositeShape):def__init__(self,canvas):ogl.CompositeShape.__init__(self)self.SetCanvas(canvas)# create a division in the compositeself.MakeContainer()# add a shape to the original divisionshape2=ogl.RectangleShape(40,60)self.GetDivisions()[0].AddChild(shape2)# now divide the division so we get 2self.GetDivisions()[0].Divide(wx.HORIZONTAL)# and add a shape to the second division (and move it to the# centre of the division)shape3=ogl.CircleShape(40)shape3.SetBrush(wx.CYAN_BRUSH)self.GetDivisions()[1].AddChild(shape3)shape3.SetX(self.GetDivisions()[1].GetX())fordivisioninself.GetDivisions():division.SetSensitivityFilter(0)#----------------------------------------------------------------------classCompositeShape(ogl.CompositeShape):def__init__(self,canvas):ogl.CompositeShape.__init__(self)self.SetCanvas(canvas)constraining_shape=ogl.RectangleShape(120,100)constrained_shape1=ogl.CircleShape(50)constrained_shape2=ogl.RectangleShape(80,20)constraining_shape.SetBrush(wx.BLUE_BRUSH)constrained_shape2.SetBrush(wx.RED_BRUSH)self.AddChild(constraining_shape)self.AddChild(constrained_shape1)self.AddChild(constrained_shape2)constraint=ogl.Constraint(ogl.CONSTRAINT_MIDALIGNED_BOTTOM,constraining_shape,[constrained_shape1,constrained_shape2])self.AddConstraint(constraint)self.Recompute()# If we don't do this, the shapes will be able to move on their# own, instead of moving the compositeconstraining_shape.SetDraggable(False)constrained_shape1.SetDraggable(False)constrained_shape2.SetDraggable(False)# If we don't do this the shape will take all left-clicks for itselfconstraining_shape.SetSensitivityFilter(0)#----------------------------------------------------------------------classDividedShape(ogl.DividedShape):def__init__(self,width,height,canvas):ogl.DividedShape.__init__(self,width,height)region1=ogl.ShapeRegion()region1.SetText('DividedShape')region1.SetProportions(0.0,0.2)region1.SetFormatMode(ogl.FORMAT_CENTRE_HORIZ)self.AddRegion(region1)region2=ogl.ShapeRegion()region2.SetText('This is Region number two.')region2.SetProportions(0.0,0.3)region2.SetFormatMode(ogl.FORMAT_CENTRE_HORIZ|ogl.FORMAT_CENTRE_VERT)self.AddRegion(region2)region3=ogl.ShapeRegion()region3.SetText('Region 3\nwith embedded\nline breaks')region3.SetProportions(0.0,0.5)region3.SetFormatMode(ogl.FORMAT_NONE)self.AddRegion(region3)self.SetRegionSizes()self.ReformatRegions(canvas)defReformatRegions(self,canvas=None):rnum=0ifcanvasisNone:canvas=self.GetCanvas()dc=wx.ClientDC(canvas)# used for measuringforregioninself.GetRegions():text=region.GetText()self.FormatText(dc,text,rnum)rnum+=1defOnSizingEndDragLeft(self,pt,x,y,keys,attch):print"***",selfogl.DividedShape.OnSizingEndDragLeft(self,pt,x,y,keys,attch)self.SetRegionSizes()self.ReformatRegions()self.GetCanvas().Refresh()#----------------------------------------------------------------------classMyEvtHandler(ogl.ShapeEvtHandler):def__init__(self,log,frame):ogl.ShapeEvtHandler.__init__(self)self.log=logself.statbarFrame=framedefUpdateStatusBar(self,shape):x,y=shape.GetX(),shape.GetY()width,height=shape.GetBoundingBoxMax()self.statbarFrame.SetStatusText("Pos: (%d, %d) Size: (%d, %d)"%(x,y,width,height))defOnLeftClick(self,x,y,keys=0,attachment=0):shape=self.GetShape()canvas=shape.GetCanvas()dc=wx.ClientDC(canvas)canvas.PrepareDC(dc)ifshape.Selected():shape.Select(False,dc)#canvas.Redraw(dc)canvas.Refresh(False)else:redraw=FalseshapeList=canvas.GetDiagram().GetShapeList()toUnselect=[]forsinshapeList:ifs.Selected():# If we unselect it now then some of the objects in# shapeList will become invalid (the control points are# shapes too!) and bad things will happen...toUnselect.append(s)shape.Select(True,dc)iftoUnselect:forsintoUnselect:s.Select(False,dc)##canvas.Redraw(dc)canvas.Refresh(False)self.UpdateStatusBar(shape)defOnEndDragLeft(self,x,y,keys=0,attachment=0):shape=self.GetShape()ogl.ShapeEvtHandler.OnEndDragLeft(self,x,y,keys,attachment)ifnotshape.Selected():self.OnLeftClick(x,y,keys,attachment)self.UpdateStatusBar(shape)defOnSizingEndDragLeft(self,pt,x,y,keys,attch):ogl.ShapeEvtHandler.OnSizingEndDragLeft(self,pt,x,y,keys,attch)self.UpdateStatusBar(self.GetShape())defOnMovePost(self,dc,x,y,oldX,oldY,display):shape=self.GetShape()ogl.ShapeEvtHandler.OnMovePost(self,dc,x,y,oldX,oldY,display)self.UpdateStatusBar(shape)if"wxMac"inwx.PlatformInfo:shape.GetCanvas().Refresh(False)defOnRightClick(self,*dontcare):self.log.WriteText("%s\n"%self.GetShape())#----------------------------------------------------------------------classTestWindow(ogl.ShapeCanvas):def__init__(self,parent,log,frame):ogl.ShapeCanvas.__init__(self,parent)maxWidth=1000maxHeight=1000self.SetScrollbars(20,20,maxWidth/20,maxHeight/20)self.log=logself.frame=frameself.SetBackgroundColour("LIGHT BLUE")#wx.WHITE)self.diagram=ogl.Diagram()self.SetDiagram(self.diagram)self.diagram.SetCanvas(self)self.shapes=[]self.save_gdi=[]rRectBrush=wx.Brush("MEDIUM TURQUOISE",wx.SOLID)dsBrush=wx.Brush("WHEAT",wx.SOLID)self.MyAddShape(CompositeDivisionShape(self),270,310,wx.BLACK_PEN,wx.BLUE_BRUSH,"Division")self.MyAddShape(CompositeShape(self),100,260,wx.BLACK_PEN,wx.RED_BRUSH,"Composite")self.MyAddShape(ogl.CircleShape(80),75,110,wx.Pen(wx.BLUE,3),wx.GREEN_BRUSH,"Circle")self.MyAddShape(ogl.TextShape(120,45),160,35,wx.GREEN_PEN,wx.LIGHT_GREY_BRUSH,"OGL is now a\npure Python lib!")self.MyAddShape(ogl.RectangleShape(85,50),305,60,wx.BLACK_PEN,wx.LIGHT_GREY_BRUSH,"Rectangle")self.MyAddShape(DrawnShape(),500,80,wx.BLACK_PEN,wx.BLACK_BRUSH,"DrawnShape")ds=self.MyAddShape(DividedShape(140,150,self),520,265,wx.BLACK_PEN,dsBrush,'')self.MyAddShape(DiamondShape(90,90),355,260,wx.Pen(wx.BLUE,3,wx.DOT),wx.RED_BRUSH,"Polygon")self.MyAddShape(RoundedRectangleShape(95,70),345,145,wx.Pen(wx.RED,2),rRectBrush,"Rounded Rect")bmp=images.Test2.GetBitmap()mask=wx.Mask(bmp,wx.BLUE)bmp.SetMask(mask)s=ogl.BitmapShape()s.SetBitmap(bmp)self.MyAddShape(s,225,130,None,None,"Bitmap")#dc = wx.ClientDC(self)#self.PrepareDC(dc)forxinrange(len(self.shapes)):fromShape=self.shapes[x]ifx+1==len(self.shapes):toShape=self.shapes[0]else:toShape=self.shapes[x+1]line=ogl.LineShape()line.SetCanvas(self)line.SetPen(wx.BLACK_PEN)line.SetBrush(wx.BLACK_BRUSH)line.AddArrow(ogl.ARROW_ARROW)line.MakeLineControlPoints(2)fromShape.AddLine(line,toShape)self.diagram.AddShape(line)line.Show(True)defMyAddShape(self,shape,x,y,pen,brush,text):# Composites have to be moved for all children to get in placeifisinstance(shape,ogl.CompositeShape):dc=wx.ClientDC(self)self.PrepareDC(dc)shape.Move(dc,x,y)else:shape.SetDraggable(True,True)shape.SetCanvas(self)shape.SetX(x)shape.SetY(y)ifpen:shape.SetPen(pen)ifbrush:shape.SetBrush(brush)iftext:forlineintext.split('\n'):shape.AddText(line)#shape.SetShadowMode(ogl.SHADOW_RIGHT)self.diagram.AddShape(shape)shape.Show(True)evthandler=MyEvtHandler(self.log,self.frame)evthandler.SetShape(shape)evthandler.SetPreviousHandler(shape.GetEventHandler())shape.SetEventHandler(evthandler)self.shapes.append(shape)returnshapedefOnBeginDragLeft(self,x,y,keys):self.log.write("OnBeginDragLeft: %s, %s, %s\n"%(x,y,keys))defOnEndDragLeft(self,x,y,keys):self.log.write("OnEndDragLeft: %s, %s, %s\n"%(x,y,keys))#----------------------------------------------------------------------defrunTest(frame,nb,log):# This creates some pens and brushes that the OGL library uses.# It should be called after the app object has been created, but# before OGL is used.ogl.OGLInitialize()win=TestWindow(nb,log,frame)returnwin#----------------------------------------------------------------------overview="""<html><body><h2>Object Graphics Library</h2>The Object Graphics Library is a library supporting the creation andmanipulation of simple and complex graphic images on a canvas.<p>The OGL library was originally written in C++ and provided towxPython via an extension module wrapper as is most of the rest ofwxPython. The code has now been ported to Python (with many thanks toPierre Hjälm!) in order to make it be more easily maintainable andless likely to get rusty because nobody cares about the C++ lib anymore."""if__name__=='__main__':importsys,osimportrunrun.main(['',os.path.basename(sys.argv[0])]+sys.argv[1:])