mfGraph Library version 0.4.2 (May 20, 2006)
Copyright 2003-2006 Michael Fötsch
Homepage: http://mfgraph.sourceforge.net/
Mail: foetsch@users.sourceforge.net
Table of Contents
Contents
Revision History
- 0.4.2 (May 20, 2006):
- Added Visual Studio 2005 project files (".vcproj", ".sln")
- Minor code fixes to resolve compiler errors and warnings in Visual Studio 2005
- 0.4.1 (August 2, 2005):
- Fix export feature (like when file is saved with .png extension)
- 0.4.0 (July 17, 2005):
New class GraphWindow for wxPython ("pymfg/graph_window.py")
- wx.Window descendant for rendering graphs
- Supports scrolling and zooming
- Supports object selection using the mouse and keyboard
- Provides event handlers for customizing the behavior
- "contrib/pymfg_demo" demonstrates how to use the class
New class GraphDrawer for wxPython ("pymfg/graph_drawer.py")
- Draw a graph to a wx.DC
- All-new "mfGraph Editor" ("contrib/wx_graph_editor")
- wxPython application
- Point-and-click editing of graphs
- Front-end to DOT
- Embedded DOT listing editor
- Exports to Windows Metafiles (Microsoft Windows only)
Added method AsDrawObject() to Python class pymfg.Object
Allows type-casting from/to Object/Node/Edge/Subgraph
- Added "contrib/windows_pymfg/setup.py"
- Removed pre-compiled executables "contrib/mfc_demo.exe" and "contrib/mfgraphui.exe"
- 0.3.0 (June 10, 2005):
- Ported to GNU Automake
- Various code fixes for GNU/Linux
- mfGraphUI bug fixes
- Added MFC demo
- Added wxPython demo
- 0.2.0 (Oct 8, 2003):
- Added pymfg (Python bindings)
- 0.1.0 (Sep 21, 2003):
- Initial version
License
mfGraph is distributed under the terms of the GNU Lesser General Public License.
Exception: The demo application in contrib/bcb_demo is distributed under the terms of the GNU General Public License.
Prerequisites
To be able to build/run the mfGraph library and the demo applications, you might have to install additional software packages:
Build-Time Requirements:
Required for: To rebuild the source code documentation in the doc directory
Version I tested with: 1.4.1
How to disable: Doxygen is only required for running "make dist"
Required for: To rebuild the DOT parser if you modify src/mfg_bison.yy and/or src/mfg_flex.ll
Version I tested with: Bison 1.875; Flex 2.5.4
How to disable: Not required if you don't modify the parser.
Visual C++: In the project contrib\windows_lib\mfgraph_lib.dsp, you might want to disable the Custom-Build Step for the files mfg_flex.ll and mfg_bison.yy.
Required for: To build the "pymfg" Python extension
Version I tested with: 2.4 (GNU/Linux) / 2.3 (Windows)
How to disable: -
Required for: To build the "pymfg" Python extension if you modify any of the *.i files in the pymfg directory
Version I tested with: 1.3.21
Attention: SWIG versions after 1.3.21 cause compilation errors with Visual C++ (and maybe other compilers). Download the older 1.3.21 instead!
How to disable: Not required if you don't modify the .i files.
Visual C++: In the project contrib\windows_pymfg\pymfg.dsp, you may disable the Custom-Build Step for file swig.i.
Run-Time Requirements:
Required for: To run any of the wxPython demo applications (contrib/pymfg_demo, contrib/wx_graph_editor)
Version I tested with: 2.5.3.1 (GNU/Linux) / 2.4.1.2 (Windows)
How to disable: -
Required for: To layout DOT graphs. Invoked by some of the demo applications (contrib/wx_graph_editor, contrib/bcb_demo, contrib/mfgraphui.exe).
Version I tested with: 2.2
How to disable: -
Build Instructions GNU/Linux
In the mfgraph-0.4 directory, run these shell commands:
mkdir build cd build ../configure make make install
If you haven't worked with "configure" before, read the file "INSTALL" or run "configure --help" for a list of options.
Users of KDevelop users can also open mfgraph-0.4/mfgraph.kdevelop and build in the IDE.
The following items will be installed:
C++ header files (installed to, e.g., /usr/include/mfgraph)
libmfgraph shared library (installted to, e.g., /usr/lib)
Python package "mfgraph" (installed to, e.g., /usr/lib/Python2.4/Lib/site-packages/mfgraph)
To change the installation directory, use "configure --prefix", as always.
To test the installation, try this:
Run "make check"
Run the Python demo contrib/pymfg_demo/pymfg_demo.py (requires wxPython!)
Run the Python demo contrib/wx_graph_editor/wx_graph_editor.py (requires wxPython and the GraphViz package!)
Build Instructions Windows
I tested the Windows build with Microsoft Visual C++ 6.0 and Borland C++Builder 5.
If you need Flex/Bison (see Prerequisites), you can download them from here:
Microsoft Visual C++-Specific
If you want/need to run Flex/Bison/SWIG, add the paths to flex.exe, bison.exe, and swig.exe in "Tools" -> "Options"
VC++ 6.0: "Tools" -> "Options" -> "Directories"
VS 2005: "Tools" -> "Options" -> "Projects and Solutions" -> "VC++ Directories"
See Prerequisites for information on how you can avoid having to run these tools.
If you want to build the Python extension (contrib\windows_pymfg):
Add the path to Python.h in "Tools" -> "Options" (typically C:\Python2x\include)
Add the path to python2x.lib in "Tools" -> "Options" (typically C:\Python2x\libs)
Open the workspace contrib\mfc_demo\mfc_demo.dsw (for VC++ 6.0) or mfc_demo.sln (for VS 2005) and build the project "mfc_demo".
This will also build the mfGraph static library in contrib\windows_lib
- Run the application to test the library
VS 2005: If you are using VS 2005 Express and have no MFC, use the solution contrib\windows_lib\mfgraph_lib.sln instead. Sorry, no test application specifically for VS 2005.
- To build the Python extension:
Open the workspace contrib\windows_pymfg\pymfg.dsw (for VC++ 6.0) or pymfg.sln (for VS 2005) and build the project "pymfg"
To install the Python extension DLL, run "setup.py install" on the command prompt
- To test, run the Python demos:
contrib\pymfg_demo\pymfg_demo.py (requires wxPython!)
contrib\wx_graph_editor\wx_graph_editor.py (requires wxPython and the GraphViz package!)
Issues (mostly for package maintainers):
The GNU/Linux Automake build creates files with a ".cc" extension when flex/bison is run. Visual C++ 6.0 does not know how to handle such files. As I don't know how to tell Automake to name these files ".cpp", I simply copied the generated files to contrib\windows_lib and changed the extension from ".cc" to ".cpp". (More precisely, there's a make rule "dist-hook" in the Automake build that does this automatically.)
- There's a (minor) problem with this:
- The "#line" directives in the files still refer to the original ".cc" file, which confuses the IDE when there's a compiler error or when debugging.
- There's a (minor) problem with this:
Borland C++Builder-Specific
Before you can build or run the mfGraph UI Sample Application (contrib\bcb_demo), you must
Download and install GraphViz
Make sure that the path to DOT.EXE is in the PATH environment variable (usually, that's C:\Program Files\ATT\GraphViz\bin)
To build the mfGraphUI Sample Application:
Open the project group contrib\bcb_demo\ProjectGroup1.bpg
- Build the project "mfgraph_lib"
- Build and install the package "mf"; new VCL components will be registered
- Build the project "mfgraphui"
To build the Python extension DLL:
Convert the Python import library python23.lib (typically in C:\Python23\libs) to OMF format, e.g.:
> cd C:\Python23\libs > C:\Program Files\Borland\CBuilder5\bin\coff2omf.exe python23.lib python23_omf.lib
Open the project group contrib\bcb_pymfg\ProjectGroup1.bpg
If Python is not installed in C:\Python23 (for example, because you are using a different version), you will have to modify the paths in the Project Options accordingly
If python23_omf.lib is not in C:\Python23\libs, remove python23_omf.lib from the project and re-add it from its actual location
- Build the project "_pymfg"
To install the Python extension DLL, run "setup.py install" on the command prompt.
Issues:
When building mf_release.bpk from an unpatched version of BCB 5, I get this linker error:
[Linker Error] Unresolved external '__fastcall Graphics::TMetafileCanvas::TMetafileCanvas( Graphics::TMetafile *, int)' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER5\LIB\RELEASE\VCLE50.LIB|_t_Graph
A workaround is to modify the VCL header graphics.hpp:
Change this: __fastcall TMetafileCanvas(TMetafile* AMetafile, HDC ReferenceDevice); To this: __fastcall TMetafileCanvas(TMetafile* AMetafile, unsigned int ReferenceDevice);
This is a known bug in BCB. Search the newsgroup archives for more info.
When you open the project mfgraphui_release.bpr, you might get this error:
Error creating form: Error reading mfGraph1->DotListing.Strings: DOT.EXE could not be run..
Solution: Before you open the project, make sure that DOT.EXE is on the path.
Programming Examples
C++
(Those parts that make use of class mfg::GraphDrawer are specific to Microsoft Windows.)
This is a simple usage example to demonstrate
using the mfg::DrawGraph class to manipulate graphs in memory
- invoking DOT.EXE to convert DOT listings into the XDOT format
using the mfg::GraphDrawer class to draw graphs to device contexts
Note: You can find the API docs in doc/html/index.htm.
We would like to render the following graph:
digraph G { a -> x [color=red] subgraph { b [style=filled fillcolor=green] } a -> b }
Step 1. Create a new application and either add mfgraph_lib.lib or add all CPP files in the mfGraph root directory.
Step 2. Create the graph using the mfg::DrawGraph class as follows:
1 #include "mfg_draw_graph.h"
2 #include "mfg_graph_drawer.h"
3 using namespace mfg;
4 ...
5 DrawGraph g;
6 Node* a = g.CreateNode();
7 Node* x = g.CreateNode();
8 Edge* ax = g.CreateEdge(a, x);
9 ax->Attribs()["color"] = "red";
10 Subgraph* s = g.CreateSubgraph();
11 Node* b = g.CreateNode(s);
12 b->Attribs()["style"] = "filled";
13 b->Attribs()["fillcolor"] = "green";
14 Edge* ab = g.CreateEdge(a, b);
Step 3. Write the graph to a DOT file on disk. (We could have written the DOT listing to a file directly, but it's more interesting this way.)
1 #include <iostream>
2 ...
3 std::ofstream dot("temp.dot");
4 g.PrintAsDot(dot);
Step 4. Have DOT.EXE convert the DOT listing to XDOT format. (This is the format that contains information about the graphic primitives such as ellipses and Bézier curves.)
1 system("dot -Txdot -otemp.xdot temp.dot");
2 // requires the GraphViz package
Step 5. Windows only*. Load the XDOT graph from the newly created file and have mfg::GraphDrawer render the graph:
1 HDC hdc; // assumed to contain a valid device context
2 ...
3 std::ifstream xdot("temp.xdot");
4 g.LoadFromXdot(xdot);
5 GraphDrawer::DrawGraph(hdc, &g);
) To render the graph on other platforms, you can use the Python module mfgraph.graph_drawer, which uses wxPython.
Run the application.
Python
This is a port of the preceding C++ example using the "pymfg" Python extension.
Note: Some functions/classes/methods behave differently in Python than in C++. In addition to the docs in doc/html/index.htm, see the files pymfg/*.i for more info.
Step 1. Create the graph.
1 from mfgraph import pymfg
2 g = pymfg.DrawGraph()
3 a = g.CreateNode()
4 x = g.CreateNode()
5 ax = g.CreateEdge(a, x)
6 ax.Attribs()["color"] = "red"
7 s = g.CreateSubgraph()
8 b = g.CreateNode(s)
9 b.Attribs()["style"] = "filled"
10 b.Attribs()["fillcolor"] = "green"
11 ab = g.CreateEdge(a, b)
Step 2. Write the graph to a DOT file on disk.
1 dot = file("temp.dot", "w")
2 dot.write(g.PrintAsDot())
3 dot.close()
Step 3. Have DOT.EXE convert the DOT listing to XDOT format.
1 import os
2 ...
3 os.system("dot -Txdot -otemp.xdot temp.dot")
4 # requires the GraphViz package
5
Step 4. wxPython only. Load the XDOT graph from the newly created file and have mfgraph.graph_window.GraphWindow render the graph:
1 from mfgraph.graph_window import GraphWindow
2 import wx
3 ...
4 class MyFrame(wx.Frame):
5 def __init__(self):
6 wx.Frame.__init__(self, None, -1, "pymfg Example")
7 graph_window = GraphWindow(self, -1, style=wx.SUNKEN_BORDER)
8 graph_window.XdotListing = file("temp.xdot").read()
9 graph_window.SetFocus()
10
11 class MyApp(wx.PySimpleApp):
12 def OnInit(self):
13 frame = MyFrame()
14 frame.Show()
15 self.SetTopWindow(frame)
16 return True
17
18 app = MyApp()
19 app.MainLoop()
You can click on objects to select them, Ctrl+click to select multiple objects. Press TAB to cycle through the objects. Press Numpad +/- to zoom.
mfGraph Editor (wx_graph_editor.py)
Before you can use the mfGraph Editor, you must
Download and install GraphViz from http://www.research.att.com/sw/tools/graphviz/download.html
- Either make sure that the DOT executable ("dot.exe" on Windows, "dot" on GNU/Linux) is on the search path
Or place DOT.EXE into the directory "contrib/wx_graph_editor"
Or set the variable "DOT_EXECUTABLE" in wx_graph_editor.py to an absolute path
- Make sure that you are using Python 2.3 or later and wxPython 2.4 or later
Run the application with "python wx_graph_editor.py" in the directory contrib/wx_graph_editor.
The menu and toolbar commands should be self-explaining. A few hints:
You can find a number of DOT files to play around with as part of the GraphViz installation:
Windows: C:\Program Files\ATT\GraphViz\graphs
GNU/Linux: /usr/share/graphviz/graphs
- See the DOT manual for information about DOT syntax:
Windows: C:\Program Files\ATT\GraphViz\doc\dotguide.pdf
GNU/Linux: /usr/share/doc/packages/graphviz/dotguide.pdf
To save the graph in one of the formats supported by DOT, use "File" -> "Save As..." and specify one of the known filename extensions from the "File Types" drop-down list box.
Note: Basically, every file type supported by DOT's "-T" command line option works as a filename extension: "-Tpng" -> ".png", "-Tcanon" -> ".canon", ... See the DOT manual for a list of supported formats.
- You can right-click on the attributes grid to the left to open a context menu:
"Propagate Attribute": When you select multiple objects by Ctrl-clicking on them, the attributes of the last selected object show up in the grid. To set the value of a specific attribute in all selected objects, right-click on the attribute, then click "Propagate Attribute".
Note: You can achieve the same thing in the Listing editor, for example by setting a default attribute value for the entire graph or by using subgraphs. See the DOT manual for more information.
See also Known Issues for wx_graph_editor.py.
Known Issues
See also the Bug List on SF.net.
wx_graph_editor.py
- Error message at startup: "Cannot convert from the charset '@LOCALE,UTF-8,ISO-8859-15,CP1252'!"
Does not happen with all versions of wxPython. Just click OK. Does not seem to be my fault, as it also happens with the wxPython Demo Application from http://www.wxpython.org.
- wxPython 2.6 on GNU/Linux (wxGTK): The drop-down list boxes in the attributes grid don't seem to work
- (Same thing happens with the wxPython Demo Application.) Clicking on items has no effect. Using the keyboard does work: Press F2 to get into edit mode, then press Up/Down to scroll through the items.
XDOT attributes such as "_draw_", "lp", "bb" show up in the attributes grid and confuse the user ;-)
Setting these attributes has no effect because they are immediately re-generated when DOT is run. There is one exception: "width" and "height" are often not specified by the user either, but are generated when DOT is run for the first time. After that, DOT honors these attributes as a minimum node size. When you change the "label" attribute to a shorter string and a node does not seem to shrink accordingly, right-click the "width" and "height" attributes and click "Delete Attribute" to reset them.
- Subgraphs cannot be edited in the graphical view
- For grouping nodes into subgraphs, please use the Listing editor. See the DOT manual for more information on subgraphs.
Note: Subgraphs can be selected when you traverse objects using Ctrl+Left/Ctrl+Right. Because subgraphs are usually invisible, it might look like pressing Ctrl+Left/Ctrl+Right has no effect. Just press Ctrl+Left/Ctrl+Right until you reach a node/edge.
- For grouping nodes into subgraphs, please use the Listing editor. See the DOT manual for more information on subgraphs.
- Ctrl+Left/Ctrl+Right does not traverse nodes/edges in the order users expect
The function "_CompareRects" in pymfg/object_selection.py determines the ordering of objects according to their graphical position. Currently, I'm trying to sort from top to bottom and from left to right, which often doesn't look right for objects that are very wide or very high (such as long edges or clusters). I'd be glad to accept your patches if you come up with a better solution.
- Unicode: DOT listings may only use the ISO-8859-1 encoding
I don't know what else DOT is able to handle. However, if you get a Unicode exception of some sort or non-ASCII labels don't show up in the editor, you might want to check the methods "__EncodeStr" and "__DecodeStr" in the file contrib/wx_graph_editor/wx_graph_editor.py.