From: <ror...@us...> - 2007-06-22 22:33:41
|
Revision: 9 http://roreditor.svn.sourceforge.net/roreditor/?rev=9&view=rev Author: rorthomas Date: 2007-06-22 15:33:39 -0700 (Fri, 22 Jun 2007) Log Message: ----------- removed senseless stuff Removed Paths: ------------- trunk/lib/ror/SharedTestOgreWindow.py trunk/lib/rorterraineditor/TerrainOgreWindow.py_ trunk/lib/testapp/ Deleted: trunk/lib/ror/SharedTestOgreWindow.py =================================================================== --- trunk/lib/ror/SharedTestOgreWindow.py 2007-06-22 22:12:29 UTC (rev 8) +++ trunk/lib/ror/SharedTestOgreWindow.py 2007-06-22 22:33:39 UTC (rev 9) @@ -1,62 +0,0 @@ -#Thomas Fischer 31/05/2007, th...@th... -import sys -import wx -import ogre.renderer.OGRE as ogre -from wxogre.OgreManager import * -from wxogre.wxOgreWindow import * -from random import random - -class SharedTestOgreWindow(wxOgreWindow): - def __init__(self, parent, ID, sceneManager, size = wx.Size(200,200), renderSystem = "OpenGL", **kwargs): - self.sceneManager = sceneManager - self.rand = str(random()) - wxOgreWindow.__init__(self, parent, ID, size = size, renderSystem = renderSystem, **kwargs) - self.parent = parent - - def SceneInitialisation(self): - # create a camera - self.camera = self.sceneManager.createCamera('SharedCamera' + self.rand) - self.camera.lookAt(ogre.Vector3(0, 0, 0)) - self.camera.setPosition(ogre.Vector3(0, 0, 100)) - self.camera.nearClipDistance = 1 - self.camera.setAutoAspectRatio(True) - - # create the Viewport" - self.viewport = self.renderWindow.addViewport(self.camera, 0, 0.0, 0.0, 1.0, 1.0) - self.viewport.backgroundColour = ogre.ColourValue(0, 0, 0) - - # bind mouse and keyboard - d=10.0 #displacement for key strokes - self.ControlKeyDict={wx.WXK_LEFT:ogre.Vector3(-d,0.0,0.0), - wx.WXK_RIGHT:ogre.Vector3(d,0.0,0.0), - wx.WXK_UP:ogre.Vector3(0.0,0.0,-d), - wx.WXK_DOWN:ogre.Vector3(0.0,0.0,d), - wx.WXK_PAGEUP:ogre.Vector3(0.0,d,0.0), - wx.WXK_PAGEDOWN:ogre.Vector3(0.0,-d,0.0)} - self.Bind(wx.EVT_KEY_DOWN, self.onKeyDown) - self.Bind(wx.EVT_MOUSE_EVENTS, self.onMouseEvent) - - def onKeyDown(self,event): - validMove = self.ControlKeyDict.get(event.m_keyCode, False) - if validMove: - pos = self.camera.getPosition() - pos += validMove - self.camera.setPosition(pos) - event.Skip() - - def onMouseEvent(self, event): - self.SetFocus() #Gives Keyboard focus to the window - - if event.RightDown(): #Precedes dragging - self.StartDragX, self.StartDragY = event.GetPosition() #saves position of initial click - - if event.Dragging() and event.RightIsDown(): #Dragging with RMB - x,y = event.GetPosition() - dx = self.StartDragX - x - dy = self.StartDragY - y - self.StartDragX, self.StartDragY = x, y - - self.camera.yaw(ogre.Degree(dx/3.0)) - self.camera.pitch(ogre.Degree(dy/3.0)) - event.Skip() - \ No newline at end of file Deleted: trunk/lib/rorterraineditor/TerrainOgreWindow.py_ =================================================================== --- trunk/lib/rorterraineditor/TerrainOgreWindow.py_ 2007-06-22 22:12:29 UTC (rev 8) +++ trunk/lib/rorterraineditor/TerrainOgreWindow.py_ 2007-06-22 22:33:39 UTC (rev 9) @@ -1,181 +0,0 @@ -#Thomas Fischer 31/05/2007, th...@th... -import wx -import ogre.renderer.OGRE as ogre -from wxogre.OgreManager import * -from wxogre.wxOgreWindow import * -from random import random - -class TerrainOgreWindow(wxOgreWindow): - def __init__(self, parent, ID, size = wx.Size(200,200), renderSystem = "OpenGL", **kwargs): - self.rand = str(random()) - wxOgreWindow.__init__(self, parent, ID, size = size, renderSystem = renderSystem, **kwargs) - self.parent = parent - - def OnFrameStarted(self): - if not self.camAxesNode is None: - self.camAxesNode.setPosition(self.camera.getPosition()) - self.camAxesNode.setOrientation(self.camera.getOrientation()) - #self.camAxesEnt.setVisible(False) - - return - - - def OnFrameEnded(self): - #self.camAxesEnt.setVisible(True) - return - - def SceneInitialisation(self, add = None): - # only init things in the main window, not in shared ones! - # setup resources - if not add is None: - for r in add: - ogre.ResourceGroupManager.getSingleton().addResourceLocation(r, "FileSystem", "General", False) - - ogre.ResourceGroupManager.getSingleton().addResourceLocation("media/packs/OgreCore.zip", "Zip", "Bootstrap", False) - ogre.ResourceGroupManager.getSingleton().addResourceLocation("media", "FileSystem", "General", False) - ogre.ResourceGroupManager.getSingleton().addResourceLocation("media/materials", "FileSystem", "General", False) - ogre.ResourceGroupManager.getSingleton().addResourceLocation("media/models", "FileSystem", "General", False) - ogre.ResourceGroupManager.getSingleton().initialiseAllResourceGroups() - - #get the scenemanager - self.sceneManager = getOgreManager().createSceneManager(ogre.ST_EXTERIOR_CLOSE) - - # create a camera - self.camera = self.sceneManager.createCamera('Camera' + self.rand) - self.camera.lookAt(ogre.Vector3(0, 0, 0)) - self.camera.setPosition(ogre.Vector3(0, 0, 100)) - self.camera.nearClipDistance = 0.1 - self.camera.setAutoAspectRatio(True) - - # create the Viewport" - self.viewport = self.renderWindow.addViewport(self.camera, 0, 0.0, 0.0, 1.0, 1.0) - self.viewport.backgroundColour = ogre.ColourValue(0, 0, 0) - - #set some default values - self.sceneDetailIndex = 0 - self.filtering = ogre.TFO_BILINEAR - - # bind mouse and keyboard - self.Bind(wx.EVT_KEY_DOWN, self.onKeyDown) - self.Bind(wx.EVT_MOUSE_EVENTS, self.onMouseEvent) - - #create objects - self.populateScene() - - self.showDebugOverlay(False) - - def showDebugOverlay(self, show): - """Turns the debug overlay (frame statistics) on or off.""" - overlay = ogre.OverlayManager.getSingleton().getByName('Core/DebugOverlay') - try: - if overlay is None: - pass - if show: - overlay.show() - else: - overlay.hide() - except: - pass - - def populateScene(self): - self.sceneManager.AmbientLight = 0.5, 0.5, 0.5 - - l = self.sceneManager.createLight("MainLight" + self.rand) - l.setPosition(20,80,50) - fadeColour = (0.93, 0.86, 0.76) - self.sceneManager.setFog(ogre.FOG_LINEAR, fadeColour, 0.001, 5000.0, 10000.0) - self.renderWindow.getViewport(0).BackgroundColour = fadeColour - - self.sceneManager.setWorldGeometry('media/terrain.cfg') - plane = ogre.Plane() - plane.d = 5000 - plane.normal = -ogre.Vector3.UNIT_Y - - self.sceneManager.AmbientLight = ogre.ColourValue(0.7, 0.7, 0.7 ) - self.sceneManager.setShadowTechnique(ogre.ShadowTechnique.SHADOWTYPE_STENCIL_ADDITIVE); - self.sceneManager.setSkyDome(True, 'Examples/CloudySky', 4.0, 8.0) - - self.MainLight = self.sceneManager.createLight('MainLight') - self.MainLight.setPosition (ogre.Vector3(20, 80, 130)) - - #create the camera Axes object - self.camAxesNode = self.sceneManager.getRootSceneNode().createChildSceneNode("camaxes" + self.rand) - self.camAxesEnt = self.sceneManager.createEntity('camAxesEnt' + self.rand, 'axes.mesh') - self.camAxesNode.attachObject(self.camAxesEnt) - - - - def onKeyDown(self,event): - #print event.m_keyCode - d = 5 - if event.ShiftDown(): - d = 30 - - if event.m_keyCode == 65: # A, wx.WXK_LEFT: - self.camera.moveRelative(ogre.Vector3(-d,0,0)) - elif event.m_keyCode == 68: # D, wx.WXK_RIGHT: - self.camera.moveRelative(ogre.Vector3(d,0,0)) - elif event.m_keyCode == 87: # W ,wx.WXK_UP: - self.camera.moveRelative(ogre.Vector3(0,0,-d)) - elif event.m_keyCode == 83: # S, wx.WXK_DOWN: - self.camera.moveRelative(ogre.Vector3(0,0,d)) - elif event.m_keyCode == wx.WXK_PAGEUP: - self.camera.moveRelative(ogre.Vector3(0,d,0)) - elif event.m_keyCode == wx.WXK_PAGEDOWN: - self.camera.moveRelative(ogre.Vector3(0,-d,0)) - elif event.m_keyCode == 84: # 84 = T - if self.filtering == ogre.TFO_BILINEAR: - self.filtering = ogre.TFO_TRILINEAR - self.Aniso = 1 - elif self.filtering == ogre.TFO_TRILINEAR: - self.filtering = ogre.TFO_ANISOTROPIC - self.Aniso = 8 - else: - self.filtering = ogre.TFO_BILINEAR - self.Aniso = 1 - ogre.MaterialManager.getSingleton().setDefaultTextureFiltering(self.filtering) - ogre.MaterialManager.getSingleton().setDefaultAnisotropy(self.Aniso) - elif event.m_keyCode == 82: # 82 = R - detailsLevel = [ ogre.PM_SOLID, - ogre.PM_WIREFRAME, - ogre.PM_POINTS ] - self.sceneDetailIndex = (self.sceneDetailIndex + 1) % len(detailsLevel) - self.camera.polygonMode=detailsLevel[self.sceneDetailIndex] - elif event.m_keyCode == 80: # 80 = P - pos = self.camera.getDerivedPosition() - o = self.camera.getDerivedOrientation() - print "P: %.3f %.3f %.3f O: %.3f %.3f %.3f %.3f" % (pos.x,pos.y,pos.z, o.w,o.x,o.y,o.z) - - event.Skip() - - def onMouseEvent(self, event): - self.SetFocus() #Gives Keyboard focus to the window - - - if event.RightDown(): #Precedes dragging - self.StartDragX, self.StartDragY = event.GetPosition() #saves position of initial click - if event.GetWheelRotation() != 0: - zfactor = 0.1 - if event.ShiftDown(): - zfactor = 5 - zoom = zfactor * -event.GetWheelRotation() - self.camera.moveRelative(ogre.Vector3(0,0, zoom)) - if event.Dragging() and event.RightIsDown() and event.ControlDown(): - x,y = event.GetPosition() - dx = self.StartDragX - x - dy = self.StartDragY - y - self.StartDragX, self.StartDragY = x, y - if event.ShiftDown(): - dx = float(dx) / 10 - dy = float(dy) / 10 - self.camera.moveRelative(ogre.Vector3(dx,-dy,0)) - elif event.Dragging() and event.RightIsDown(): #Dragging with RMB - x,y = event.GetPosition() - dx = self.StartDragX - x - dy = self.StartDragY - y - self.StartDragX, self.StartDragY = x, y - - self.camera.yaw(ogre.Degree(dx/3.0)) - self.camera.pitch(ogre.Degree(dy/3.0)) - event.Skip() - \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ror...@us...> - 2007-06-27 15:57:49
|
Revision: 33 http://roreditor.svn.sourceforge.net/roreditor/?rev=33&view=rev Author: rorthomas Date: 2007-06-27 08:57:43 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * first window close fixtures Modified Paths: -------------- trunk/lib/ror/starter.py trunk/lib/rortruckeditor/MainFrame.py trunk/lib/rortruckeditor/RoRTruckOgreWindow.py trunk/lib/rortruckeditor/UVFrame.py trunk/lib/wxogre/OgreManager.py trunk/lib/wxogre/wxOgreWindow.py Modified: trunk/lib/ror/starter.py =================================================================== --- trunk/lib/ror/starter.py 2007-06-26 01:22:44 UTC (rev 32) +++ trunk/lib/ror/starter.py 2007-06-27 15:57:43 UTC (rev 33) @@ -58,7 +58,9 @@ def OnStartRoR(self, event=None): - p = Popen(os.path.join(self.rordir, "RoR.exe"), shell=True, cwd=self.rordir) + #escape spaces! + path = newpath.replace(" ", "\ ") + p = Popen(os.path.join(path, "RoR.exe"), shell=True, cwd=self.rordir) #sts = os.waitpid(p.pid, 0) def OnTruckEditor(self, event=None): @@ -85,12 +87,12 @@ pass def checkRoRDir(self, fn): - withoutspaces = (fn.find(" ") == -1) - if not withoutspaces: - dlg = wx.MessageDialog(self, "Your RoR installation directory contains spaces. Rename/move it to a directory with no spaces.\nFor example c:\\ror", "Error", wx.OK | wx.ICON_INFORMATION) - dlg.ShowModal() - dlg.Destroy() - return False + # withoutspaces = (fn.find(" ") == -1) + # if not withoutspaces: + # dlg = wx.MessageDialog(self, "Your RoR installation directory contains spaces. Rename/move it to a directory with no spaces.\nFor example c:\\ror", "Error", wx.OK | wx.ICON_INFORMATION) + # dlg.ShowModal() + # dlg.Destroy() + # return False exists = os.path.isfile(os.path.join(fn,"RoR.exe")) if not exists: @@ -108,7 +110,9 @@ newpath = dialog.GetPath() if not self.checkRoRDir(newpath): return - + + # no need to escape here! + #newpath = newpath.replace(" ", "\ ") self.rordir = newpath self.lblRoRDir.SetLabel(newpath) getSettings().setRoRDir(newpath) Modified: trunk/lib/rortruckeditor/MainFrame.py =================================================================== --- trunk/lib/rortruckeditor/MainFrame.py 2007-06-26 01:22:44 UTC (rev 32) +++ trunk/lib/rortruckeditor/MainFrame.py 2007-06-27 15:57:43 UTC (rev 33) @@ -275,7 +275,7 @@ dialog = wx.FileDialog(self, "Open Terrain", default, "", "Trucks or Loads (*.truck, *.load)|*.truck;*.load", wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) res = dialog.ShowModal() if res == wx.ID_OK: - self.fileopenmenu.Enable(False) + #self.fileopenmenu.Enable(False) filename = dialog.GetPath() print filename self.truckOgreWin.LoadTruck(filename) Modified: trunk/lib/rortruckeditor/RoRTruckOgreWindow.py =================================================================== --- trunk/lib/rortruckeditor/RoRTruckOgreWindow.py 2007-06-26 01:22:44 UTC (rev 32) +++ trunk/lib/rortruckeditor/RoRTruckOgreWindow.py 2007-06-27 15:57:43 UTC (rev 33) @@ -45,8 +45,10 @@ self.sceneManager.destroyEntity(e) except: pass - if not self.uvFrame is None: + try: self.uvFrame.Close() + except: + pass self.nodes = {} self.beams = {} self.shocks = {} Modified: trunk/lib/rortruckeditor/UVFrame.py =================================================================== --- trunk/lib/rortruckeditor/UVFrame.py 2007-06-26 01:22:44 UTC (rev 32) +++ trunk/lib/rortruckeditor/UVFrame.py 2007-06-27 15:57:43 UTC (rev 33) @@ -5,13 +5,16 @@ from ror.rorcommon import * from RoRUVOgreWindow import * +ID_CLOSEWINDOW = 100 + class UVFrame(wx.Frame): rordir = None def __init__(self, *args, **kwds): kwds["style"] = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLIP_CHILDREN | wx.CLOSE_BOX wx.Frame.__init__(self, *args, **kwds) - + self.Bind(wx.EVT_CLOSE, self.OnClose, self) + #main splitter self.splitter = wx.SplitterWindow(self, wx.ID_ANY, style=wx.SP_PERMIT_UNSPLIT|wx.SP_3DSASH) self.splitterleft = wx.Panel(self.splitter, wx.ID_ANY) @@ -23,7 +26,7 @@ self.rordir = getSettings().getRoRDir() #ogre windows - self.truckOgreWin = RoRUVOgreWindow(self.splitterleft, wx.ID_ANY) + self.uvOgreWin = RoRUVOgreWindow(self.splitterleft, wx.ID_ANY) #some labels #self.helptext = wx.StaticText(self.splitterleft, wx.ID_ANY, "short help: right click = rotate; ctrl + right click, AWSD, mouse wheel = move") @@ -40,23 +43,23 @@ self.__do_layout() def setTree(self,tree): - self.truckOgreWin.setTree(tree) + self.uvOgreWin.setTree(tree) self.trucktree = tree - def OnExit(self, event): - self.Close(True) - sys.exit(0) - + def OnClose(self, event = None): + print "onClose" + self.uvOgreWin.close() + self.Destroy() def __set_properties(self): self.SetTitle("UV Editor") - self.truckOgreWin.SetMinSize((640,480)) + self.uvOgreWin.SetMinSize((640,480)) def __do_layout(self): sizer_main = wx.BoxSizer(wx.HORIZONTAL) sizer_left = wx.BoxSizer(wx.VERTICAL) - sizer_left.Add(self.truckOgreWin, 2, wx.EXPAND, 0) + sizer_left.Add(self.uvOgreWin, 2, wx.EXPAND, 0) self.splitterleft.SetSizer(sizer_left) self.splitter.SplitVertically(self.splitterleft, self.splitterright) Modified: trunk/lib/wxogre/OgreManager.py =================================================================== --- trunk/lib/wxogre/OgreManager.py 2007-06-26 01:22:44 UTC (rev 32) +++ trunk/lib/wxogre/OgreManager.py 2007-06-27 15:57:43 UTC (rev 33) @@ -60,6 +60,11 @@ self.renderWindows[wxOgrewin] = renderWindow return renderWindow + def removeRenderWindow(self, wxOgrewin): + print "removing render target" + self.ogreRoot.detachRenderTarget(self.renderWindows[wxOgrewin]) + del self.renderWindows[wxOgrewin] + def RenderAll(self): for ogrewin in self.renderWindows.keys(): try: @@ -82,3 +87,7 @@ def createSceneManager(self, type): return self.ogreRoot.createSceneManager(type, "SceneManager" + str(len(self.renderWindows))) + + def destroySceneManager(self, sm): + return self.ogreRoot.destroySceneManager(sm) + \ No newline at end of file Modified: trunk/lib/wxogre/wxOgreWindow.py =================================================================== --- trunk/lib/wxogre/wxOgreWindow.py 2007-06-26 01:22:44 UTC (rev 32) +++ trunk/lib/wxogre/wxOgreWindow.py 2007-06-27 15:57:43 UTC (rev 33) @@ -26,19 +26,31 @@ # create a new RenderWindow self.renderWindow = getOgreManager().createRenderWindow(self, "wxPythonWxOgreRenderWindow", size[0], size[1], False, self.GetHandle()) self.renderWindow.active = True + self.sceneManager = None self.SceneInitialisation() self.SetFocus() + + def __del__(self): + self.close() + def close(self): + getOgreManager().removeRenderWindow(self) + if not self.sceneManager is None: + getOgreManager().destroySceneManager(self.sceneManager) + def _OnSize(self, event): """ Is called when the ogre Window is getting resized @param event: the sizing event @return: none """ - if getattr(self, 'ogreRoot', None): - self.renderWindow.windowMovedOrResized() - event.Skip() + try: + if getattr(self, 'ogreRoot', None): + self.renderWindow.windowMovedOrResized() + event.Skip() + except: + pass def _OnEraseBackground(self, event): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ror...@us...> - 2007-06-28 05:55:47
|
Revision: 45 http://roreditor.svn.sourceforge.net/roreditor/?rev=45&view=rev Author: rorthomas Date: 2007-06-27 22:55:46 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * removed Examples * svn update now working with https Modified Paths: -------------- trunk/lib/ror/svn.py Removed Paths: ------------- trunk/lib/pysvn/Examples/ Modified: trunk/lib/ror/svn.py =================================================================== --- trunk/lib/ror/svn.py 2007-06-28 05:43:58 UTC (rev 44) +++ trunk/lib/ror/svn.py 2007-06-28 05:55:46 UTC (rev 45) @@ -23,7 +23,10 @@ def getRevision(client, path): info = client.info(path) return info['revision'].number - + +def callback_ssl_server_trust_prompt(trust_data): + return True, trust_data['failures'], True + def svnupdate(): global changes path = getRootPath() @@ -34,6 +37,7 @@ revision_before = getRevision(client, path) print "updating from revision %d ..." % revision_before client.callback_notify = notify + client.callback_ssl_server_trust_prompt = callback_ssl_server_trust_prompt client.update(path, recurse = True, revision = pysvn.Revision(pysvn.opt_revision_kind.head), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ror...@us...> - 2007-06-28 06:12:05
|
Revision: 46 http://roreditor.svn.sourceforge.net/roreditor/?rev=46&view=rev Author: rorthomas Date: 2007-06-27 23:12:03 -0700 (Wed, 27 Jun 2007) Log Message: ----------- * added update button to starter * removed start ror button * revision number is now displayed instead of version number * wxOgreWindow BugFix Modified Paths: -------------- trunk/lib/ror/starter.py trunk/lib/ror/svn.py trunk/lib/rorterraineditor/MainFrame.py trunk/lib/rortruckeditor/MainFrame.py trunk/lib/wxogre/wxOgreWindow.py Modified: trunk/lib/ror/starter.py =================================================================== --- trunk/lib/ror/starter.py 2007-06-28 05:55:46 UTC (rev 45) +++ trunk/lib/ror/starter.py 2007-06-28 06:12:03 UTC (rev 46) @@ -18,8 +18,8 @@ self.btnSelectRoRDir = wx.Button(self.panel, wx.ID_ANY, "Select RoR Directory") self.Bind(wx.EVT_BUTTON, self.OnSelectRoRDir, self.btnSelectRoRDir) - self.btnStartRoR = wx.Button(self.panel, wx.ID_ANY, "Start RoR") - self.Bind(wx.EVT_BUTTON, self.OnStartRoR, self.btnStartRoR) + #self.btnStartRoR = wx.Button(self.panel, wx.ID_ANY, "Start RoR") + #self.Bind(wx.EVT_BUTTON, self.OnStartRoR, self.btnStartRoR) self.btnStartTerrainEditor = wx.Button(self.panel, wx.ID_ANY, "Start Terrain Editor") self.Bind(wx.EVT_BUTTON, self.OnTerrainEditor, self.btnStartTerrainEditor) @@ -40,19 +40,19 @@ #print self.rordir if not self.rordir is None: if self.checkRoRDir(self.rordir): - self.btnStartRoR.Enable(True) + #self.btnStartRoR.Enable(True) self.btnStartTruckEditor.Enable(True) self.btnStartTerrainEditor.Enable(True) self.lblRoRDir.SetLabel(self.rordir) else: self.rordir = "" - self.btnStartRoR.Enable(False) + #self.btnStartRoR.Enable(False) self.btnStartTruckEditor.Enable(False) self.btnStartTerrainEditor.Enable(False) self.lblRoRDir.SetLabel("Please select Rigs of Rods Directory!") else: - self.btnStartRoR.Enable(False) + #self.btnStartRoR.Enable(False) self.btnStartTruckEditor.Enable(False) self.btnStartTerrainEditor.Enable(False) self.__set_properties() @@ -64,13 +64,15 @@ def OnStartRoR(self, event=None): #escape spaces! - path = newpath.replace(" ", "\ ") - p = Popen(os.path.join(path, "RoR.exe"), shell=True, cwd=self.rordir) + path = os.path.join(self.rordir, "RoR.exe") + print path + p = Popen(path, shell=False, cwd=self.rordir) #sts = os.waitpid(p.pid, 0) def OnTruckEditor(self, event=None): import rortruckeditor.MainFrame try: + self.Close() app = rortruckeditor.MainFrame.startApp() del app except: @@ -86,6 +88,7 @@ def OnTerrainEditor(self, event=None): import rorterraineditor.MainFrame try: + self.Close() app = rorterraineditor.MainFrame.startApp() del app except: @@ -121,7 +124,7 @@ self.rordir = newpath self.lblRoRDir.SetLabel(newpath) getSettings().setRoRDir(newpath) - self.btnStartRoR.Enable(True) + #self.btnStartRoR.Enable(True) self.btnStartTruckEditor.Enable(True) self.btnStartTerrainEditor.Enable(True) @@ -136,7 +139,7 @@ sizer_panel = wx.BoxSizer(wx.VERTICAL) sizer_panel.Add(self.lblRoRDir, 0, wx.EXPAND, 0) sizer_panel.Add(self.btnSelectRoRDir, 0, wx.EXPAND, 0) - sizer_panel.Add(self.btnStartRoR, 0, wx.EXPAND, 0) + #sizer_panel.Add(self.btnStartRoR, 0, wx.EXPAND, 0) sizer_panel.Add(self.btnStartTerrainEditor, 0, wx.EXPAND, 0) sizer_panel.Add(self.btnStartTruckEditor, 0, wx.EXPAND, 0) sizer_panel.Add(self.btnBugReport, 0, wx.EXPAND, 0) Modified: trunk/lib/ror/svn.py =================================================================== --- trunk/lib/ror/svn.py 2007-06-28 05:55:46 UTC (rev 45) +++ trunk/lib/ror/svn.py 2007-06-28 06:12:03 UTC (rev 46) @@ -1,5 +1,6 @@ #Thomas Fischer 28/06/2007, th...@th... import sys, os, os.path +import pysvn URL = "http://roreditor.svn.sourceforge.net/svnroot/roreditor/trunk" changes = 0 @@ -20,7 +21,11 @@ #print event_dict print str(event_dict['action']) + ", " + event_dict['path'] -def getRevision(client, path): +def getRevision(client=None, path=None): + if client is None: + client = pysvn.Client() + if path is None: + path = getRootPath() info = client.info(path) return info['revision'].number @@ -32,7 +37,6 @@ path = getRootPath() changes = 0 try: - import pysvn client = pysvn.Client() revision_before = getRevision(client, path) print "updating from revision %d ..." % revision_before @@ -57,13 +61,13 @@ path = getRootPath() changes = 0 try: - import pysvn client = pysvn.Client() client.callback_notify = notify client.checkout(URL, path) except: print "error while checkout!" + def run(): if os.path.isdir(os.path.join(getRootPath(), "media")): svnupdate() Modified: trunk/lib/rorterraineditor/MainFrame.py =================================================================== --- trunk/lib/rorterraineditor/MainFrame.py 2007-06-28 05:55:46 UTC (rev 45) +++ trunk/lib/rorterraineditor/MainFrame.py 2007-06-28 06:12:03 UTC (rev 46) @@ -331,7 +331,12 @@ sys.exit(0) def __set_properties(self): - self.SetTitle("RoREditor version 0.0.4") + try: + import ror.svn + self.SetTitle("RoR Terrain Editor revision %d" % ror.svn.getRevision()) + except: + self.SetTitle("RoR Terrain Editor") + self.terrainOgreWin.SetMinSize((640,480)) def __do_layout(self): Modified: trunk/lib/rortruckeditor/MainFrame.py =================================================================== --- trunk/lib/rortruckeditor/MainFrame.py 2007-06-28 05:55:46 UTC (rev 45) +++ trunk/lib/rortruckeditor/MainFrame.py 2007-06-28 06:12:03 UTC (rev 46) @@ -306,7 +306,12 @@ dlg.Destroy() def __set_properties(self): - self.SetTitle("RoR Truck Editor version 0.0.1") + try: + import ror.svn + self.SetTitle("RoR Truck Editor revision %d" % ror.svn.getRevision()) + except: + self.SetTitle("RoR Truck Editor") + self.truckOgreWin.SetMinSize((640,480)) def __do_layout(self): Modified: trunk/lib/wxogre/wxOgreWindow.py =================================================================== --- trunk/lib/wxogre/wxOgreWindow.py 2007-06-28 05:55:46 UTC (rev 45) +++ trunk/lib/wxogre/wxOgreWindow.py 2007-06-28 06:12:03 UTC (rev 46) @@ -26,8 +26,13 @@ # create a new RenderWindow self.renderWindow = getOgreManager().createRenderWindow(self, "wxPythonWxOgreRenderWindow", size[0], size[1], False, self.GetHandle()) self.renderWindow.active = True - self.sceneManager = None + try: + if not self.sceneManager is None: + pass + except: + self.sceneManager = None + self.SceneInitialisation() self.SetFocus() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ror...@us...> - 2007-06-29 13:18:44
|
Revision: 66 http://roreditor.svn.sourceforge.net/roreditor/?rev=66&view=rev Author: rorthomas Date: 2007-06-29 06:18:42 -0700 (Fri, 29 Jun 2007) Log Message: ----------- * added newton.chm - newton help * fixed UVFrame.py and RoRUVOgreWindow.py * beams are now updated, but the bad way :( Modified Paths: -------------- trunk/lib/ror/editor.ini trunk/lib/rortruckeditor/RoRTruckOgreWindow.py trunk/lib/rortruckeditor/RoRUVOgreWindow.py trunk/lib/rortruckeditor/UVFrame.py Added Paths: ----------- trunk/lib/ogre/newton.chm Added: trunk/lib/ogre/newton.chm =================================================================== (Binary files differ) Property changes on: trunk/lib/ogre/newton.chm ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Modified: trunk/lib/ror/editor.ini =================================================================== --- trunk/lib/ror/editor.ini 2007-06-29 09:37:09 UTC (rev 65) +++ trunk/lib/ror/editor.ini 2007-06-29 13:18:42 UTC (rev 66) @@ -1,7 +1,6 @@ [RigsOfRods] basepath = C:\games\RoR-0.31a - -# this is a comment + [gui] usegui = yes Modified: trunk/lib/rortruckeditor/RoRTruckOgreWindow.py =================================================================== --- trunk/lib/rortruckeditor/RoRTruckOgreWindow.py 2007-06-29 09:37:09 UTC (rev 65) +++ trunk/lib/rortruckeditor/RoRTruckOgreWindow.py 2007-06-29 13:18:42 UTC (rev 66) @@ -73,6 +73,7 @@ def OnFrameStarted(self): if self.enablephysics: self.World.update(TIMER) + self.updateBeams() pass def OnFrameEnded(self): @@ -267,12 +268,32 @@ line.position(pos2) line.end() line.setCastShadows(False) + line.setDynamic(True) linenode = self.sceneManager.getRootSceneNode().createChildSceneNode() linenode.attachObject(line) self.beams[id0] = [linenode, id1, id2, options, line] + print id0 except: pass + def updateBeams(self): + for bk in self.beams.keys(): + beam = self.beams[bk] + line = beam[4] + id1 = beam[1] + id2 = beam[2] + try: + pos1 = self.nodes[id1][0].getPosition() + pos2 = self.nodes[id2][0].getPosition() + line.beginUpdate(0) + line.position(pos1) + line.position(pos2) + line.end() + except Exception, e: + print str(e) + continue + + def createShock(self, id0, id1, id2, options): try: pos1 = self.nodes[id1][0].getPosition() @@ -344,7 +365,7 @@ smnode = self.sceneManager.getRootSceneNode().createChildSceneNode() smnode.attachObject(sm) - self.submeshs[smgid] = [smnode, smgid, smg] + self.submeshs[smgid] = [smnode, smgid, smg, sm] except: pass @@ -514,9 +535,9 @@ #print beam try: self.createBeam(beamcounter, int(beam[0]),int(beam[1]), option) + beamcounter += 1 except: pass - beamcounter += 1 if 'shocks' in tree.keys(): Modified: trunk/lib/rortruckeditor/RoRUVOgreWindow.py =================================================================== --- trunk/lib/rortruckeditor/RoRUVOgreWindow.py 2007-06-29 09:37:09 UTC (rev 65) +++ trunk/lib/rortruckeditor/RoRUVOgreWindow.py 2007-06-29 13:18:42 UTC (rev 66) @@ -2,7 +2,10 @@ import wx, os, os.path import ogre.renderer.OGRE as ogre from ror.truckparser import * -from ror.rorsettings import * + +from ror.logger import log +from ror.settingsManager import getSettingsManager + from ror.rorcommon import * from wxogre.OgreManager import * from wxogre.wxOgreWindow import * @@ -16,7 +19,7 @@ class RoRUVOgreWindow(wxOgreWindow): def __init__(self, parent, ID, size = wx.Size(200,200), **kwargs): self.parent = parent - self.rordir = getSettings().getRoRDir() + self.rordir = getSettingsManager().getSetting("RigsOfRods", "BasePath") self.World = OgreNewt.World() self.sceneManager = None self.trucktree = None Modified: trunk/lib/rortruckeditor/UVFrame.py =================================================================== --- trunk/lib/rortruckeditor/UVFrame.py 2007-06-29 09:37:09 UTC (rev 65) +++ trunk/lib/rortruckeditor/UVFrame.py 2007-06-29 13:18:42 UTC (rev 66) @@ -1,7 +1,10 @@ #Thomas Fischer 31/05/2007, th...@th... from wxogre.OgreManager import * from ror.RoROgreWindow import * -from ror.rorsettings import * + +from ror.logger import log +from ror.settingsManager import getSettingsManager + from ror.rorcommon import * from RoRUVOgreWindow import * @@ -23,7 +26,7 @@ self.splitter.SetSashPosition(100) self.splitter.SetMinimumPaneSize(200) - self.rordir = getSettings().getRoRDir() + self.rordir = getSettingsManager().getSetting("RigsOfRods", "BasePath") #ogre windows self.uvOgreWin = RoRUVOgreWindow(self.splitterleft, wx.ID_ANY) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ror...@us...> - 2007-07-08 20:27:40
|
Revision: 100 http://roreditor.svn.sourceforge.net/roreditor/?rev=100&view=rev Author: rorthomas Date: 2007-07-08 13:27:33 -0700 (Sun, 08 Jul 2007) Log Message: ----------- * added pydot / missing files Added Paths: ----------- trunk/lib/dot_parser.py trunk/lib/pydot.py Added: trunk/lib/dot_parser.py =================================================================== --- trunk/lib/dot_parser.py (rev 0) +++ trunk/lib/dot_parser.py 2007-07-08 20:27:33 UTC (rev 100) @@ -0,0 +1,380 @@ +# -*- coding: Latin-1 -*- +"""Graphviz's dot language parser. + +The dotparser parses graphviz files in dot and dot files and transforms them +into a class representation defined by pydot. + +The module needs pyparsing (tested with version 1.2.2) and pydot (tested with 0.9.10) + +Author: Michael Krause <mi...@kr...> +""" + +__author__ = 'Michael Krause' +__license__ = 'MIT' + +import sys +import glob +import pydot +import re + +from pyparsing import __version__ as pyparsing_version +from pyparsing import Literal, CaselessLiteral, Word, \ + Upcase, OneOrMore, ZeroOrMore, Forward, NotAny, \ + delimitedList, oneOf, Group, Optional, Combine, \ + alphas, nums, restOfLine, cStyleComment, nums, \ + alphanums, printables, empty, quotedString, \ + ParseException, ParseResults, CharsNotIn, _noncomma,\ + dblQuotedString + + +class P_AttrList: + def __init__(self, toks): + self.attrs = {} + i = 0 + while i < len(toks): + attrname = toks[i] + attrvalue = toks[i+1] + self.attrs[attrname] = attrvalue + i += 2 + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self.attrs) + + +class DefaultStatement(P_AttrList): + def __init__(self, default_type, attrs): + self.default_type = default_type + self.attrs = attrs + + def __repr__(self): + return "%s(%s, %r)" % \ + (self.__class__.__name__, self.default_type, self.attrs) + + +def push_top_graph_stmt(str, loc, toks): + attrs = {} + g = None + + for element in toks: + if isinstance(element, ParseResults) or \ + isinstance(element, tuple) or \ + isinstance(element, list): + + element = element[0] + + if element == 'strict': + attrs['strict'] = True + elif element in ['graph', 'digraph']: + attrs['graph_type'] = element + elif type(element) == type(''): + attrs['graph_name'] = element + elif isinstance(element, pydot.Graph): + g = pydot.Graph(**attrs) + g.__dict__.update(element.__dict__) + for e in g.get_edge_list(): + e.parent_graph = g + for e in g.get_node_list(): + e.parent_graph = g + for e in g.get_subgraph_list(): + e.set_graph_parent(g) + + elif isinstance(element, P_AttrList): + attrs.update(element.attrs) + else: + raise ValueError, "Unknown element statement: %r " % element + + if g is not None: + g.__dict__.update(attrs) + return g + + +def add_defaults(element, defaults): + d = element.__dict__ + for key, value in defaults.items(): + if not d.get(key): + d[key] = value + + +def add_elements(g, toks, defaults_graph=None, defaults_node=None, defaults_edge=None): + + if defaults_graph is None: + defaults_graph = {} + if defaults_node is None: + defaults_node = {} + if defaults_edge is None: + defaults_edge = {} + + for element in toks: + if isinstance(element, pydot.Graph): + add_defaults(element, defaults_graph) + g.add_subgraph(element) + elif isinstance(element, pydot.Node): + add_defaults(element, defaults_node) + g.add_node(element) + elif isinstance(element, pydot.Edge): + add_defaults(element, defaults_edge) + g.add_edge(element) + elif isinstance(element, ParseResults): + for e in element: + add_elements(g, [e], defaults_graph, defaults_node, defaults_edge) + elif isinstance(element, DefaultStatement): + if element.default_type == 'graph': + default_graph_attrs = pydot.Node('graph') + default_graph_attrs.__dict__.update(element.attrs) + g.add_node(default_graph_attrs) + defaults_graph.update(element.attrs) + g.__dict__.update(element.attrs) + elif element.default_type == 'node': + default_node_attrs = pydot.Node('node') + default_node_attrs.__dict__.update(element.attrs) + g.add_node(default_node_attrs) +# defaults_node.update(element.attrs) + elif element.default_type == 'edge': + default_edge_attrs = pydot.Node('edge') + default_edge_attrs.__dict__.update(element.attrs) + g.add_node(default_edge_attrs) + defaults_edge.update(element.attrs) + else: + raise ValueError, "Unknown DefaultStatement: %s " % element.default_type + elif isinstance(element, P_AttrList): + g.__dict__.update(element.attrs) + else: + raise ValueError, "Unknown element statement: %r " % element + + +def push_graph_stmt(str, loc, toks): + g = pydot.Subgraph() + add_elements(g, toks) + return g + + +def push_subgraph_stmt(str, loc, toks): + + for e in toks: + if len(e)==3: + g = e[2] + g.set_name(e[1]) + if len(e)==1: + e[0].set_name('') + return e[0] + + return g + + +def push_default_stmt(str, loc, toks): + # The pydot class instances should be marked as + # default statements to be inherited by actual + # graphs, nodes and edges. + # print "push_default_stmt", toks + default_type = toks[0][0] + if len(toks) > 1: + attrs = toks[1].attrs + else: + attrs = {} + + if default_type in ['graph', 'node', 'edge']: + return DefaultStatement(default_type, attrs) + else: + raise ValueError, "Unknown default statement: %r " % toks + + +def push_attr_list(str, loc, toks): + p = P_AttrList(toks) + return p + + +def get_port(node): + + if len(node)>1: + if isinstance(node[1], ParseResults): + if len(node[1][0])==2: + if node[1][0][0]==':': + return node[1][0][1] + + return None + + +def do_node_ports(n_prev, n_next): + port = get_port(n_prev) + if port is not None: + n_prev_port = ':'+port + else: + n_prev_port = '' + + port = get_port(n_next) + if port is not None: + n_next_port = ':'+port + else: + n_next_port = '' + + return (n_prev_port, n_next_port) + + +def push_edge_stmt(str, loc, toks): + + tok_attrs = [a for a in toks if isinstance(a, P_AttrList)] + attrs = {} + for a in tok_attrs: + attrs.update(a.attrs) + + e = [] + n_prev = toks[0] + if isinstance(toks[2][0], pydot.Graph): + n_next_list = [[n.get_name(),] for n in toks[2][0].get_node_list()] + for n_next in [n for n in n_next_list]: + n_prev_port, n_next_port = do_node_ports(n_prev, n_next) + e.append(pydot.Edge(n_prev[0]+n_prev_port, n_next[0]+n_next_port, **attrs)) + else: + for n_next in [n for n in tuple(toks)[2::2]]: + n_prev_port, n_next_port = do_node_ports(n_prev, n_next) + e.append(pydot.Edge(n_prev[0]+n_prev_port, n_next[0]+n_next_port, **attrs)) + n_prev = n_next + + return e + + +def push_node_stmt(str, loc, toks): + + if len(toks) == 2: + attrs = toks[1].attrs + else: + attrs = {} + + node_name = toks[0] + if isinstance(node_name, list) or isinstance(node_name, tuple): + if len(node_name)>0: + node_name = node_name[0] + + n = pydot.Node('"'+node_name+'"', **attrs) + return n + + +def strip_quotes( s, l, t ): + return [ t[0].strip('"') ] + + +graphparser = None +def graph_definition(): + global graphparser + + if not graphparser: + # punctuation + colon = Literal(":") + lbrace = Literal("{") + rbrace = Literal("}") + lbrack = Literal("[") + rbrack = Literal("]") + lparen = Literal("(") + rparen = Literal(")") + equals = Literal("=") + comma = Literal(",") + dot = Literal(".") + slash = Literal("/") + bslash = Literal("\\") + star = Literal("*") + semi = Literal(";") + at = Literal("@") + minus = Literal("-") + + # keywords + strict_ = Literal("strict") + graph_ = Literal("graph") + digraph_ = Literal("digraph") + subgraph_ = Literal("subgraph") + node_ = Literal("node") + edge_ = Literal("edge") + + + # token definitions + + identifier = Word(alphanums + "_" ).setName("identifier") + + double_quoted_string = dblQuotedString + + alphastring_ = OneOrMore(CharsNotIn(_noncomma)) + + ID = (identifier | double_quoted_string.setParseAction(strip_quotes) |\ + alphastring_).setName("ID") + + html_text = Combine(Literal("<<") + OneOrMore(CharsNotIn(",]"))) + + float_number = Combine(Optional(minus) + \ + OneOrMore(Word(nums + "."))).setName("float_number") + + righthand_id = (float_number | ID | html_text).setName("righthand_id") + + port_angle = (at + ID).setName("port_angle") + + port_location = (Group(colon + ID) | \ + Group(colon + lparen + ID + comma + ID + rparen)).setName("port_location") + + port = (Group(port_location + Optional(port_angle)) | \ + Group(port_angle + Optional(port_location))).setName("port") + + node_id = (ID + Optional(port)) + a_list = OneOrMore(ID + Optional(equals.suppress() + righthand_id) + \ + Optional(comma.suppress())).setName("a_list") + + attr_list = OneOrMore(lbrack.suppress() + Optional(a_list) + \ + rbrack.suppress()).setName("attr_list") + + attr_stmt = (Group(graph_ | node_ | edge_) + attr_list).setName("attr_stmt") + + edgeop = (Literal("--") | Literal("->")).setName("edgeop") + + stmt_list = Forward() + graph_stmt = Group(lbrace.suppress() + Optional(stmt_list) + \ + rbrace.suppress()).setName("graph_stmt") + + subgraph = (Group(Optional(subgraph_ + Optional(ID)) + graph_stmt) | \ + Group(subgraph_ + ID)).setName("subgraph") + + edgeRHS = OneOrMore(edgeop + Group(node_id | subgraph)) + + edge_stmt = Group(node_id | subgraph) + edgeRHS + Optional(attr_list) + + node_stmt = (node_id + Optional(attr_list) + Optional(semi.suppress())).setName("node_stmt") + + assignment = (ID + equals.suppress() + righthand_id).setName("assignment") + stmt = (assignment | edge_stmt | attr_stmt | subgraph | node_stmt).setName("stmt") + stmt_list << OneOrMore(stmt + Optional(semi.suppress())) + + graphparser = (Optional(strict_) + Group((graph_ | digraph_)) + \ + Optional(ID) + graph_stmt).setResultsName("graph") + + singleLineComment = "//" + restOfLine + + + # actions + + graphparser.ignore(singleLineComment) + graphparser.ignore(cStyleComment) + + assignment.setParseAction(push_attr_list) + a_list.setParseAction(push_attr_list) + edge_stmt.setParseAction(push_edge_stmt) + node_stmt.setParseAction(push_node_stmt) + attr_stmt.setParseAction(push_default_stmt) + + subgraph.setParseAction(push_subgraph_stmt) + graph_stmt.setParseAction(push_graph_stmt) + graphparser.setParseAction(push_top_graph_stmt) + + + return graphparser + + +def parse_dot_data(data): + try: + data = data.replace('\\\n', '') + graphparser = graph_definition() + if pyparsing_version >= '1.2': + graphparser.parseWithTabs() + tokens = graphparser.parseString(data) + graph = tokens.graph + return graph + except ParseException, err: + print err.line + print " "*(err.column-1) + "^" + print err + return None Added: trunk/lib/pydot.py =================================================================== --- trunk/lib/pydot.py (rev 0) +++ trunk/lib/pydot.py 2007-07-08 20:27:33 UTC (rev 100) @@ -0,0 +1,1234 @@ +# -*- coding: Latin-1 -*- +"""Graphviz's dot language Python interface. + +This module provides with a full interface to create handle modify +and process graphs in Graphviz's dot language. + +References: + +pydot Homepage: http://www.dkbza.org/pydot.html +Graphviz: http://www.research.att.com/sw/tools/graphviz/ +DOT Language: http://www.research.att.com/~erg/graphviz/info/lang.html + +Programmed and tested with Graphviz 1.16 and Python 2.3.4 on GNU/Linux +by Ero Carrera (c) 2004 [er...@dk...] + +Distributed under MIT license [http://opensource.org/licenses/mit-license.html]. +""" + +__author__ = 'Ero Carrera' +__version__ = '0.9.10' +__license__ = 'MIT' + +import os +import tempfile +import copy +import dot_parser + + +def graph_from_dot_data(data): + """Load graph as defined by data in DOT format. + + The data is assumed to be in DOT format. It will + be parsed and a Dot class will be returned, + representing the graph. + """ + + graph = dot_parser.parse_dot_data(data) + if graph is not None: + dot = Dot() + dot.__dict__.update(graph.__dict__) + return dot + + return None + +def graph_from_dot_file(path): + """Load graph as defined by a DOT file. + + The file is assumed to be in DOT format. It will + be loaded, parsed and a Dot class will be returned, + representing the graph. + """ + + fd = file(path, 'rb') + data = fd.read() + fd.close() + + return graph_from_dot_data(data) + + +def graph_from_edges(edge_list, node_prefix='', directed=False): + """Creates a basic graph out of an edge list. + + The edge list has to be a list of tuples representing + the nodes connected by the edge. + The values can be anything: bool, int, float, str. + + If the graph is undirected by default, it is only + calculated from one of the symmetric halves of the matrix. + """ + if directed: + graph = Dot(graph_type='digraph') + else: + graph = Dot(graph_type='graph') + for edge in edge_list: + e = Edge(node_prefix+str(edge[0]), node_prefix+str(edge[1])) + graph.add_edge(e) + return graph + + +def graph_from_adjacency_matrix(matrix, node_prefix='', directed=False): + """Creates a basic graph out of an adjacency matrix. + + The matrix has to be a list of rows of values + representing an adjacency matrix. + The values can be anything: bool, int, float, as long + as they can evaluate to True or False. + """ + node_orig = 1 + if directed: + graph = Dot(graph_type='digraph') + else: + graph = Dot(graph_type='graph') + for row in matrix: + if not directed: + skip = matrix.index(row) + r = row[skip:] + else: + skip = 0 + r = row + node_dest = skip+1 + for e in r: + if e: + graph.add_edge( \ + Edge( node_prefix+str(node_orig), \ + node_prefix+str(node_dest))) + node_dest += 1 + node_orig += 1 + return graph + +def graph_from_incidence_matrix(matrix, node_prefix='', directed=False): + """Creates a basic graph out of an incidence matrix. + + The matrix has to be a list of rows of values + representing an incidence matrix. + The values can be anything: bool, int, float, as long + as they can evaluate to True or False. + """ + node_orig = 1 + if directed: + graph = Dot(graph_type='digraph') + else: + graph = Dot(graph_type='graph') + for row in matrix: + nodes = [] + c = 1 + for node in row: + if node: + nodes.append(c*node) + c += 1 + nodes.sort() + if len(nodes) == 2: + graph.add_edge( \ + Edge(node_prefix+str(abs(nodes[0])), \ + node_prefix+str(nodes[1]) )) + if not directed: + graph.set_simplify(True) + return graph + + +def find_graphviz(): + """Locate Graphviz's executables in the system. + + Attempts to locate graphviz's executables in a Unix system. + It will look for 'dot', 'twopi' and 'neato' in all the directories + specified in the PATH environment variable. + It will return a dictionary containing the program names as keys + and their paths as values. + """ + progs = {'dot': '', 'twopi': '', 'neato': '', 'circo': '', 'fdp': ''} + if not os.environ.has_key('PATH'): + return None + for path in os.environ['PATH'].split(os.pathsep): + for prg in progs.keys(): + if os.path.exists(path+os.path.sep+prg): + progs[prg] = path+os.path.sep+prg + elif os.path.exists(path+os.path.sep+prg + '.exe'): + progs[prg] = path+os.path.sep+prg + '.exe' + return progs + +class Common: + """Common information to several classes. + + Should not be directly used, several classes are derived from + this one. + """ + chars_ID = None + parent_graph = None + + def char_range(self, a,b): + """Generate a list containing a range of characters. + + Returns a list of characters starting from 'a' up to 'b' + both inclusive. + """ + return map(chr, range(ord(a), ord(b)+1)) + + def is_ID(self, s): + """Checks whether a string is an dot language ID. + + It will check whether the string is solely composed + by the characters allowed in an ID or not. + """ + if not self.chars_ID: + self.chars_ID = self.char_range('a','z')+self.char_range('A','Z')+ \ + self.char_range('0','9')+['_'] + for c in s: + if c not in self.chars_ID: + return False + return True + +class Error(Exception): + """General error handling class. + """ + def __init__(self, value): + self.value = value + def __str__(self): + return self.value + + +class Node(object, Common): + """A graph node. + + This class represents a graph's node with all its attributes. + + node(name, attribute=value, ...) + + name: node's name + + All the attributes defined in the Graphviz dot language should + be supported. + """ + attributes = ['showboxes', 'URL', 'fontcolor', 'fontsize', 'label', 'fontname', \ + 'comment', 'root', 'toplabel', 'vertices', 'width', 'z', 'bottomlabel', \ + 'distortion', 'fixedsize', 'group', 'height', 'orientation', 'pin', \ + 'rects', 'regular', 'shape', 'shapefile', 'sides', 'skew', 'pos', \ + 'layer', 'tooltip', 'style', 'target', 'color', 'peripheries', + 'fillcolor', 'margin', 'nojustify'] + + def __init__(self, name, **attrs): + + if isinstance(name, str) and not name.startswith('"'): + idx = name.find(':') + if idx>0: + name = name[:idx] + + self.name = str(name) + for attr in self.attributes: + # Set all the attributes to None. + self.__setattr__(attr, None) + # Generate all the Setter methods. + self.__setattr__('set_'+attr, lambda x, a=attr : self.__setattr__(a, x)) + # Generate all the Getter methods. + self.__setattr__('get_'+attr, lambda a=attr : self.__get_attribute__(a)) + for attr, val in attrs.items(): + self.__setattr__(attr, val) + + def __getstate__(self): + + dict = copy.copy(self.__dict__) + for attr in self.attributes: + del dict['set_'+attr] + del dict['get_'+attr] + + return dict + + def __setstate__(self, state): + for k, v in state.items(): + self.__setattr__(k, v) + + def __get_attribute__(self, attr): + """Look for default attributes for this node""" + attr_val = self.__getattribute__(attr) + if attr_val is None: + defaults = self.parent_graph.get_node('node') + if defaults: + attr_val = defaults.__getattribute__(attr) + if attr_val: + return attr_val + else: + return attr_val + return None + + + def set_name(self, node_name): + """Set the node's name.""" + + self.name = str(node_name) + + def get_name(self): + """Get the node's name.""" + + return self.name + + def set(self, name, value): + """Set an attribute value by name. + + Given an attribute 'name' it will set its value to 'value'. + There's always the possibility of using the methods: + set_'name'(value) + which are defined for all the existing attributes. + """ + if name in self.attributes: + self.__dict__[name] = value + return True + # Attribute is not known + return False + + def to_string(self): + """Returns a string representation of the node in dot language. + """ + + if not isinstance(self.name, str): + self.name = str(self.name) + + # RMF: special case defaults for node, edge and graph properties. + if self.name in ['node', 'edge', 'graph'] or self.name.startswith('"'): + node = self.name + else: + node = '"'+self.name+'"' + + node_attr = None + all_attrs = [a for a in self.attributes] + all_attrs += [a for a in Graph.attributes if a not in all_attrs] + all_attrs += [a for a in Edge.attributes if a not in all_attrs] + for attr in all_attrs: + if self.__dict__.has_key(attr) \ + and self.__getattribute__(attr) is not None: + if not node_attr: + node_attr = '' + else: + node_attr += ', ' + node_attr += attr+'=' + val = str(self.__dict__[attr]) + + if val.startswith('<') and val.endswith('>'): + node_attr += val + elif ((isinstance(val, str) or isinstance(val, unicode)) and \ + not self.is_ID(val)) or val == '' : + + node_attr += '"'+val+'"' + else: + node_attr += str(val) + + if node_attr: + node += ' ['+node_attr+']' + node += ';' + + return node + + +class Edge(object, Common): + """A graph edge. + + This class represents a graph's edge with all its attributes. + + edge(src, dst, attribute=value, ...) + + src: source node's name + dst: destination node's name + + All the attributes defined in the Graphviz dot language should + be supported. + + Attributes can be set through the dynamically generated methods: + + set_[attribute name], i.e. set_label, set_fontname + + or using the instance's attributes: + + Edge.[attribute name], i.e. edge_instance.label, edge_instance.fontname + """ + attributes = ['style', 'target', 'pos', 'layer', 'tooltip', 'color', 'showboxes',\ + 'URL', 'fontcolor', 'fontsize', 'label', 'fontname', 'comment', 'lp', \ + 'arrowhead', 'arrowsize', 'arrowtail', 'constraint', 'decorate', 'dir', \ + 'headURL', 'headclip', 'headhref', 'headlabel', 'headport', \ + 'headtarget', 'headtooltip', 'href', 'labelangle', 'labeldistance', \ + 'labelfloat', 'labelfontcolor', 'labelfontname', 'labelfontsize', 'len',\ + 'lhead', 'ltail', 'minlen', 'samehead', 'sametail', 'weight', 'tailURL',\ + 'tailclip', 'tailhref', 'taillabel', 'tailport', 'tailtarget', \ + 'tailtooltip', 'nojustify'] + + def __init__(self, src, dst, **attrs): + self.src = src + self.dst = dst + for attr in self.attributes: + # Set all the attributes to None. + self.__setattr__(attr, None) + # Generate all the Setter methods. + self.__setattr__('set_'+attr, lambda x, a=attr : self.__setattr__(a, x)) + # Generate all the Getter methods. + self.__setattr__('get_'+attr, lambda a=attr : self.__get_attribute__(a)) + for attr, val in attrs.items(): + self.__setattr__(attr, val) + + def __getstate__(self): + + dict = copy.copy(self.__dict__) + for attr in self.attributes: + del dict['set_'+attr] + del dict['get_'+attr] + + return dict + + def __setstate__(self, state): + for k, v in state.items(): + self.__setattr__(k, v) + + def __get_attribute__(self, attr): + """Look for default attributes for this edge""" + attr_val = self.__getattribute__(attr) + if attr_val is None: + defaults = self.parent_graph.get_node('edge') + if defaults: + attr_val = defaults.__getattribute__(attr) + if attr_val: + return attr_val + else: + return attr_val + return None + + + def get_source(self): + """Get the edges source node name.""" + + return self.src + + def get_destination(self): + """Get the edge's destination node name.""" + + return self.dst + + def __eq__(self, edge): + """Compare two edges. + + If the parent graph is directed, arcs linking + node A to B are considered equal and A->B != B->A + + If the parent graph is undirected, any edge + connecting two nodes is equal to any other + edge connecting the same nodes, A->B == B->A + """ + + if not isinstance(edge, Edge): + raise Error, 'Can\'t compare and edge to a non-edge object.' + if self.parent_graph.graph_type=='graph': + # If the graph is undirected, the edge has neither + # source nor destination. + if (self.src==edge.src and self.dst==edge.dst) or \ + (self.src==edge.dst and self.dst==edge.src): + return True + else: + if self.src==edge.src and self.dst==edge.dst: + return True + return False + + + def set(self, name, value): + """Set an attribute value by name. + + Given an attribute 'name' it will set its value to 'value'. + There's always the possibility of using the methods: + set_'name'(value) + which are defined for all the existing attributes. + """ + if name in self.attributes: + self.__dict__[name] = value + return True + # Attribute is not known + return False + + + def parse_node_ref(self, node_str): + + if not isinstance(node_str, str): + node_str = str(node_str) + + if node_str[0]=='"' and node_str[-1]=='"' and node_str[0].count('"')%2!=0: + return node_str + + node_port_idx = node_str.rfind(':') + + if node_port_idx>0 and node_str[0]=='"' and node_str[node_port_idx-1]=='"': + return node_str + + node_str = node_str.replace('"', '') + + if node_port_idx>0: + a = node_str[:node_port_idx] + b = node_str[node_port_idx+1:] + if self.is_ID(a): + node = a + else: + node = '"'+a+'"' + if self.is_ID(b): + node += ':'+b + else: + node+=':"'+b+'"' + return node + + return '"'+node_str+'"' + + + def to_string(self): + """Returns a string representation of the edge in dot language. + """ + + src = self.parse_node_ref(self.src) + dst = self.parse_node_ref(self.dst) + + edge = src + if self.parent_graph and \ + self.parent_graph.graph_type and \ + self.parent_graph.graph_type=='digraph': + edge+=' -> ' + else: + edge+=' -- ' + edge+=dst + + edge_attr = None + for attr in self.attributes: + if self.__dict__.has_key(attr) \ + and self.__getattribute__(attr) is not None: + if not edge_attr: + edge_attr = '' + else: + edge_attr+=', ' + edge_attr+=attr+'=' + val = str(self.__dict__[attr]) + if (isinstance(val, str) or isinstance(val, unicode)) and not self.is_ID(val): + edge_attr+='"'+val+'"' + else: + edge_attr+=str(val) + + if edge_attr: + edge+=' ['+edge_attr+']' + edge+=';' + + return edge + +class Graph(object, Common): + + """Class representing a graph in Graphviz's dot language. + + This class implements the methods to work on a representation + of a graph in Graphviz's dot language. + + graph(graph_name='G', type='digraph', strict=False, suppress_disconnected=False, attribute=value, ...) + + graph_name: + the graph's name + type: + can be 'graph' or 'digraph' + suppress_disconnected: + defaults to False, which will remove from the + graph any disconnected nodes. + simplify: + if True it will avoid displaying equal edges, i.e. + only one edge between two nodes. removing the + duplicated ones. + + All the attributes defined in the Graphviz dot language should + be supported. + + Attributes can be set through the dynamically generated methods: + + set_[attribute name], i.e. set_size, set_fontname + + or using the instance's attributes: + + Graph.[attribute name], i.e. graph_instance.label, graph_instance.fontname + """ + + attributes = ['Damping', 'bb', 'center', 'clusterrank', 'compound', 'concentrate',\ + 'defaultdist', 'dim', 'fontpath', 'epsilon', 'layers', 'layersep', \ + 'margin', 'maxiter', 'mclimit', 'mindist', 'pack', 'packmode', 'model', \ + 'page', 'pagedir', 'nodesep', 'normalize', 'nslimit1', 'ordering', \ + 'orientation', 'outputorder', 'overlap', 'remincross', 'resolution', \ + 'rankdir', 'ranksep', 'ratio', 'rotate', 'samplepoints', 'searchsize', \ + 'sep', 'size', 'splines', 'start', 'stylesheet', 'truecolor', \ + 'viewport', 'voro_margin', 'quantum', 'bgcolor', 'labeljust', \ + 'labelloc', 'root', 'showboxes', 'URL', 'fontcolor', 'fontsize', \ + 'label' ,'fontname', 'comment', 'lp', 'target', 'color', 'style', \ + 'concentrators', 'rank', 'dpi', 'mode', 'nojustify', 'nslimit'] + + def __init__(self, graph_name='G', graph_type='digraph', strict=False, \ + suppress_disconnected=False, simplify=False, **attrs): + + if graph_type not in ['graph', 'digraph']: + raise Error, 'Invalid type. Accepted graph types are: graph, digraph, subgraph' + self.graph_type = graph_type + self.graph_name = graph_name + self.strict = strict + self.suppress_disconnected = suppress_disconnected + self.simplify = simplify + self.node_list = [] + self.edge_list = [] + self.edge_src_list = [] + self.edge_dst_list = [] + self.subgraph_list = [] + self.sorted_graph_elements = [] + self.parent_graph = self + for attr in self.attributes: + # Set all the attributes to None. + self.__setattr__(attr, None) + # Generate all the Setter methods. + self.__setattr__('set_'+attr, lambda x, a=attr : self.__setattr__(a, x)) + # Generate all the Getter methods. + self.__setattr__('get_'+attr, lambda a=attr : self.__get_attribute__(a)) + for attr, val in attrs.items(): + self.__setattr__(attr, val) + + def __getstate__(self): + + dict = copy.copy(self.__dict__) + for attr in self.attributes: + del dict['set_'+attr] + del dict['get_'+attr] + + return dict + + def __setstate__(self, state): + for k, v in state.items(): + self.__setattr__(k, v) + + def __get_attribute__(self, attr): + """Look for default attributes for this graph""" + attr_val = self.__getattribute__(attr) + if attr_val is None: + defaults = self.get_node('graph') + if defaults: + attr_val = defaults.__getattribute__(attr) + if attr_val: + return attr_val + else: + return attr_val + return None + + def set_simplify(self, simplify): + """Set whether to simplify or not. + + If True it will avoid displaying equal edges, i.e. + only one edge between two nodes. removing the + duplicated ones. + """ + + self.simplify = simplify + + def get_simplify(self): + """Get whether to simplify or not. + + Refer to set_simplify for more information. + """ + + return self.simplify + + + def set_type(self, graph_type): + """Set the graph's type, 'graph' or 'digraph'.""" + self.graph_type = graph_type + + def get_type(self): + """Get the graph's type, 'graph' or 'digraph'.""" + return self.graph_type + + def set_name(self, graph_name): + """Set the graph's name.""" + + self.graph_name = graph_name + + def get_name(self): + """Get the graph's name.""" + + return self.graph_name + + def set_strict(self, val): + """Set graph to 'strict' mode. + + This option is only valid for top level graphs. + """ + + self.strict = val + + def get_strict(self, val): + """Get graph's 'strict' mode (True, False). + + This option is only valid for top level graphs. + """ + + return self.strict + + def set_suppress_disconnected(self, val): + """Suppress disconnected nodes in the output graph. + + This option will skip nodes in the graph with no incoming or outgoing + edges. This option works also for subgraphs and has effect only in the + current graph/subgraph. + """ + + self.suppress_disconnected = val + + def get_suppress_disconnected(self, val): + """Get if suppress disconnected is set. + + Refer to set_suppress_disconnected for more information. + """ + + self.suppress_disconnected = val + + def set(self, name, value): + """Set an attribute value by name. + + Given an attribute 'name' it will set its value to 'value'. + There's always the possibility of using the methods: + + set_'name'(value) + + which are defined for all the existing attributes. + """ + if name in self.attributes: + self.__dict__[name] = value + return True + # Attribute is not known + return False + + def get(self, name): + """Get an attribute value by name. + + Given an attribute 'name' it will get its value. + There's always the possibility of using the methods: + + get_'name'() + + which are defined for all the existing attributes. + """ + return self.__dict__[name] + + def add_node(self, graph_node): + """Adds a node object to the graph. + + It takes a node object as its only argument and returns + None. + """ + + if not isinstance(graph_node, Node): + raise Error, 'add_node received a non node class object' + + node = self.get_node(graph_node.get_name()) + if node is None or graph_node.get_name() in ('graph', 'node', 'edge'): + self.node_list.append(graph_node) + graph_node.parent_graph = self.parent_graph + elif (node.__dict__.has_key('added_from_edge') and node.added_from_edge): + for k, v in graph_node.__dict__.items(): + if v is not None and node.__dict__.has_key(k) and node.__dict__[k] is None: + node.__dict__[k] = v + + self.sorted_graph_elements.append(graph_node) + + def get_node(self, name): + """Retrieved a node from the graph. + + Given a node's name the corresponding Node + instance will be returned. + + If multiple nodes exist with that name, a list of + Node instances is returned. + If only one node exists, the instance is returned. + None is returned otherwise. + """ + + match = [node for node in self.node_list if node.get_name() == str(name)] + + l = len(match) + if l==1: + return match[0] + elif l>1: + return match + else: + return None + + def get_node_list(self): + """Get the list of Node instances. + + This method returns the list of Node instances + composing the graph. + """ + + return [n for n in self.node_list if n.get_name() not in ('graph', 'edge', 'node')] + + def add_edge(self, graph_edge): + """Adds an edge object to the graph. + + It takes a edge object as its only argument and returns + None. + """ + + if not isinstance(graph_edge, Edge): + raise Error, 'add_edge received a non edge class object' + + self.edge_list.append(graph_edge) + + src = self.get_node(graph_edge.get_source()) + if src is None: + self.add_node(Node(graph_edge.get_source(), added_from_edge=True)) + + dst = self.get_node(graph_edge.get_destination()) + if dst is None: + self.add_node(Node(graph_edge.get_destination(), added_from_edge=True)) + + graph_edge.parent_graph = self.parent_graph + + if graph_edge.src not in self.edge_src_list: + self.edge_src_list.append(graph_edge.src) + + if graph_edge.dst not in self.edge_dst_list: + self.edge_dst_list.append(graph_edge.dst) + + self.sorted_graph_elements.append(graph_edge) + + def get_edge(self, src, dst): + """Retrieved an edge from the graph. + + Given an edge's source and destination the corresponding + Edge instance will be returned. + + If multiple edges exist with that source and destination, + a list of Edge instances is returned. + If only one edge exists, the instance is returned. + None is returned otherwise. + """ + + match = [edge for edge in self.edge_list if edge.src == src and edge.dst == dst] + + l = len(match) + if l==1: + return match[0] + elif l>1: + return match + else: + return None + + def get_edge_list(self): + """Get the list of Edge instances. + + This method returns the list of Edge instances + composing the graph. + """ + + return self.edge_list + + def add_subgraph(self, sgraph): + """Adds an edge object to the graph. + + It takes a subgraph object as its only argument and returns + None. + """ + if not isinstance(sgraph, Subgraph) and not isinstance(sgraph, Cluster): + raise Error, 'add_subgraph received a non subgraph class object' + + self.subgraph_list.append(sgraph) + + sgraph.set_graph_parent(self.parent_graph) + + self.sorted_graph_elements.append(sgraph) + + return None + + def get_subgraph(self, name): + """Retrieved a subgraph from the graph. + + Given a subgraph's name the corresponding + Subgraph instance will be returned. + + If multiple subgraphs exist with the same name, a list of + Subgraph instances is returned. + If only one Subgraph exists, the instance is returned. + None is returned otherwise. + """ + + match = [sgraph for sgraph in self.subgraph_list if sgraph.graph_name == name] + + l = len(match) + if l==1: + return match[0] + elif l>1: + return match + else: + return None + + def get_subgraph_list(self): + """Get the list of Subgraph instances. + + This method returns the list of Subgraph instances + in the graph. + """ + + return self.subgraph_list + + def set_graph_parent(self, parent): + """Sets a graph and its elements to point the the parent. + + Any subgraph added to a parent graph receives a reference + to the parent to access some common data. + """ + self.parent_graph = parent + + for elm in self.edge_list: + elm.parent_graph = parent + + for elm in self.node_list: + elm.parent_graph = parent + + for elm in self.subgraph_list: + elm.parent_graph = parent + elm.set_graph_parent(parent) + + def to_string(self): + """Returns a string representation of the graph in dot language. + + It will return the graph and all its subelements in string from. + """ + graph = '' + if self.__dict__.has_key('strict'): + if self==self.parent_graph and self.strict: + graph+='strict ' + + graph+=self.graph_type+' '+self.graph_name+' {\n' + + for attr in self.attributes: + if self.__dict__.has_key(attr) \ + and self.__getattribute__(attr) is not None: + graph += attr+'=' + val = str(self.__dict__[attr]) + if isinstance(val, str) and not self.is_ID(val): + graph += '"'+val+'"' + else: + graph += str(val) + graph+=';\n' + + + edges_done = [] + for elm in self.sorted_graph_elements: + if isinstance(elm, Node): + if self.suppress_disconnected: + if elm.name not in self.edge_src_list+self.edge_dst_list: + continue + graph += elm.to_string()+'\n' + elif isinstance(elm, Edge): + if self.simplify and elm in edges_done: + continue + graph += elm.to_string()+'\n' + edges_done.append(elm) + else: + graph += elm.to_string()+'\n' + + graph += '}\n' + + return graph + + +class Subgraph(Graph): + + """Class representing a subgraph in Graphviz's dot language. + + This class implements the methods to work on a representation + of a subgraph in Graphviz's dot language. + + subgraph(graph_name='subG', suppress_disconnected=False, attribute=value, ...) + + graph_name: + the subgraph's name + suppress_disconnected: + defaults to false, which will remove from the + subgraph any disconnected nodes. + All the attributes defined in the Graphviz dot language should + be supported. + + Attributes can be set through the dynamically generated methods: + + set_[attribute name], i.e. set_size, set_fontname + + or using the instance's attributes: + + Subgraph.[attribute name], i.e. + subgraph_instance.label, subgraph_instance.fontname + """ + + attributes = Graph.attributes + + # RMF: subgraph should have all the attributes of graph so it can be passed + # as a graph to all methods + def __init__(self, graph_name='subG', suppress_disconnected=False, \ + simplify=False, **attrs): + + self.graph_type = 'subgraph' + self.graph_name = graph_name + self.suppress_disconnected = suppress_disconnected + self.simplify = simplify + self.node_list = [] + self.edge_list = [] + self.edge_src_list = [] + self.edge_dst_list = [] + self.subgraph_list = [] + self.sorted_graph_elements = [] + for attr in self.attributes: + # Set all the attributes to None. + self.__setattr__(attr, None) + # Generate all the Setter methods. + self.__setattr__('set_'+attr, lambda x, a=attr : self.__setattr__(a, x)) + # Generate all the Getter methods. + self.__setattr__('get_'+attr, lambda a=attr : self.__get_attribute__(a)) + for attr, val in attrs.items(): + self.__setattr__(attr, val) + + def __getstate__(self): + + dict = copy.copy(self.__dict__) + for attr in self.attributes: + del dict['set_'+attr] + del dict['get_'+attr] + + return dict + + def __setstate__(self, state): + for k, v in state.items(): + self.__setattr__(k, v) + + def __get_attribute__(self, attr): + """Look for default attributes for this subgraph""" + attr_val = self.__getattribute__(attr) + if attr_val is None: + defaults = self.get_node('graph') + if defaults: + attr_val = defaults.__getattribute__(attr) + if attr_val: + return attr_val + else: + return attr_val + return None + + +class Cluster(Graph): + + """Class representing a cluster in Graphviz's dot language. + + This class implements the methods to work on a representation + of a cluster in Graphviz's dot language. + + cluster(graph_name='subG', suppress_disconnected=False, attribute=value, ...) + + graph_name: + the cluster's name (the string 'cluster' will be always prepended) + suppress_disconnected: + defaults to false, which will remove from the + cluster any disconnected nodes. + All the attributes defined in the Graphviz dot language should + be supported. + + Attributes can be set through the dynamically generated methods: + + set_[attribute name], i.e. set_color, set_fontname + + or using the instance's attributes: + + Cluster.[attribute name], i.e. + cluster_instance.color, cluster_instance.fontname + """ + + attributes = ['pencolor', 'bgcolor', 'labeljust', 'labelloc', 'URL', 'fontcolor', \ + 'fontsize', 'label', 'fontname', 'lp', 'style', 'target', 'color', \ + 'peripheries', 'fillcolor', 'nojustify'] + + def __init__(self, graph_name='subG', suppress_disconnected=False, \ + simplify=False, **attrs): + + #if type not in ['subgraph']: + # raise Error, 'Invalid type. Accepted graph types are: subgraph' + self.graph_type = 'subgraph' + self.graph_name = 'cluster_'+graph_name + self.suppress_disconnected = suppress_disconnected + self.simplify = simplify + self.node_list = [] + self.edge_list = [] + self.edge_src_list = [] + self.edge_dst_list = [] + self.subgraph_list = [] + self.sorted_graph_elements = [] + for attr in self.attributes: + # Set all the attributes to None. + self.__setattr__(attr, None) + # Generate all the Setter methods. + self.__setattr__('set_'+attr, lambda x, a=attr : self.__setattr__(a, x)) + # Generate all the Getter methods. + self.__setattr__('get_'+attr, lambda a=attr : self.__get_attribute__(a)) + for attr, val in attrs.items(): + self.__setattr__(attr, val) + + def __getstate__(self): + + dict = copy.copy(self.__dict__) + for attr in self.attributes: + del dict['set_'+attr] + del dict['get_'+attr] + + return dict + + def __setstate__(self, state): + for k, v in state.items(): + self.__setattr__(k, v) + + def __get_attribute__(self, attr): + """Look for default attributes for this cluster""" + attr_val = self.__getattribute__(attr) + if attr_val is None: + defaults = self.get_node('graph') + if defaults: + attr_val = defaults.__getattribute__(attr) + if attr_val: + return attr_val + else: + return attr_val + return None + + +class Dot(Graph): + """A container for handling a dot language file. + + This class implements methods to write and process + a dot language file. It is a derived class of + the base class 'Graph'. + """ + + progs = None + + formats = ['ps', 'ps2', 'hpgl', 'pcl', 'mif', 'pic', 'gd', 'gd2', 'gif', 'jpg', \ + 'jpeg', 'png', 'wbmp', 'ismap', 'imap', 'cmap', 'cmapx', 'vrml', 'vtx', 'mp', \ + 'fig', 'svg', 'svgz', 'dia', 'dot', 'canon', 'plain', 'plain-ext', 'xdot'] + + def __init__(self, prog='dot', **args): + Graph.__init__(self, **args) + + self.prog = prog + + # Automatically creates all the methods enabling the creation + # of output in any of the supported formats. + for frmt in self.formats: + self.__setattr__('create_'+frmt, lambda f=frmt, prog=self.prog : self.create(format=f, prog=prog)) + f = self.__dict__['create_'+frmt] + f.__doc__ = '''Refer to docstring from 'create' for more information.''' + + for frmt in self.formats+['raw']: + self.__setattr__('write_'+frmt, lambda path, f=frmt, prog=self.prog : self.write(path, format=f, prog=prog)) + f = self.__dict__['write_'+frmt] + f.__doc__ = '''Refer to docstring from 'write' for more information.''' + + + def __getstate__(self): + + dict = copy.copy(self.__dict__) + for attr in self.attributes: + del dict['set_'+attr] + del dict['get_'+attr] + + for k in [x for x in dict.keys() if x.startswith('write_')] + \ + [x for x in dict.keys() if x.startswith('create_')]: + del dict[k] + + return dict + + def __setstate__(self, state): + self.__init__() + for k, v in state.items(): + self.__setattr__(k, v) + + + def set_prog(self, prog): + """Sets the default program. + + Sets the default program in charge of processing + the dot file into a graph. + """ + self.prog = prog + + def write(self, path, prog=None, format='raw'): + """Writes a graph to a file. + + Given a filename 'path' it will open/create and truncate + such file and write on it a representation of the graph + defined by the dot object and in the format specified by + 'format'. + The format 'raw' is used to dump the string representation + of the Dot object, without further processing. + The output can be processed by any of graphviz tools, defined + in 'prog', which defaults to 'dot' + Returns True or False according to the success of the write + operation. + + There's also the preferred possibility of using: + + write_'format'(path, prog='program') + + which are automatically defined for all the supported formats. + [write_ps(), write_gif(), write_dia(), ...] + """ + + if prog is None: + prog = self.prog + + dot_fd = file(path, "w+b") + if format == 'raw': + dot_fd.write(self.to_string()) + else: + dot_fd.write(self.create(prog, format)) + dot_fd.close() + + return True + + def create(self, prog=None, format='ps'): + """Creates and returns a Postscript representation of the graph. + + create will write the graph to a temporary dot file and process + it with the program given by 'prog' (which defaults to 'twopi'), + reading the Postscript output and returning it as a string is the + operation is successful. + On failure None is returned. + + There's also the preferred possibility of using: + + create_'format'(prog='program') + + which are automatically defined for all the supported formats. + [create_ps(), create_gif(), create_dia(), ...] + """ + if prog is None: + prog = self.prog + + if self.progs is None: + self.progs = find_graphviz() + if self.progs is None: + return None + if not self.progs.has_key(prog): + # Program not found ?!?! + return None + + tmp_fd, tmp_name = tempfile.mkstemp() + os.close(tmp_fd) + self.write(tmp_name) + stdin, stdout, stderr = os.popen3(self.progs[prog]+' -T'+format+' '+tmp_name, 'b') + stdin.close() + stderr.close() + data = stdout.read() + stdout.close() + os.unlink(tmp_name) + return data + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |