1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
/* $Id: Graph.cs,v 1.5 2009/06/03 01:10:59 ellson Exp $ $Revision: 1.5 $ */
/* vim:set shiftwidth=4 ts=8: */
/**********************************************************
* This software is part of the graphviz package *
* http://www.graphviz.org/ *
* *
* Copyright (c) 1994-2008 AT&T Corp. *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Corp. *
* *
* Information and Software Systems Research *
* AT&T Research, Florham Park NJ *
**********************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
namespace Graphviz
{
public class Graph : IDisposable
{
public enum API
{
Render = 0,
Layout = 1,
TextLayout = 2,
Device = 3,
LoadImage = 4
}
public class Exception : ApplicationException
{
public Exception(string message): base(message)
{
}
}
public static IList<string> GetPlugins(API api, bool showFullPath)
{
SortedList<string, string> plugins = new SortedList<string, string>();
IntPtr pluginList = gvplugin_list(_context, api, showFullPath ? ":" : "");
foreach (string nextPlugin in Marshal.PtrToStringAnsi(pluginList).Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries))
{
int lastColon = nextPlugin.LastIndexOf(':');
string plugin = nextPlugin.Substring(0, lastColon == -1 ? nextPlugin.Length : lastColon);
plugins[plugin] = plugin;
}
free(pluginList);
return plugins.Keys;
}
public event EventHandler Changed;
public IDictionary<string, string> Arguments
{
get { return _arguments; }
}
public IDictionary<string, string> GraphAttributes
{
get { return _graphAttributes; }
}
public IDictionary<string, string> DefaultNodeAttributes
{
get { return _defaultNodeAttributes; }
}
public IDictionary<string, string> DefaultEdgeAttributes
{
get { return _defaultEdgeAttributes; }
}
public Graph(string filename)
{
IntPtr file = fopen(filename, "r");
if (file == IntPtr.Zero)
throw new Win32Exception();
_graph = agread(file);
if (_graph == IntPtr.Zero)
throw new Win32Exception();
fclose(file);
_freeLastLayout = false;
_arguments = new GraphArguments(this);
_graphAttributes = new GraphDefaultAttributes(this, _graph);
_defaultNodeAttributes = new GraphDefaultAttributes(this, agprotonode(_graph));
_defaultEdgeAttributes = new GraphDefaultAttributes(this, agprotoedge(_graph));
}
public void Save(string filename)
{
IntPtr file = fopen(filename, "w");
if (file == IntPtr.Zero)
throw new Win32Exception();
if (agwrite(_graph, file) != 0)
throw new Win32Exception();
fclose(file);
}
public Stream Render(string format)
{
unsafe {
byte* result;
uint length;
if (gvRenderData(_context, _graph, format, out result, out length) != 0)
throw new Exception("bad render");
return new RenderStream(result, length);
}
}
public void Render(string format, string filename)
{
if (gvRenderFilename(_context, _graph, format, filename) != 0)
throw new Exception("bad render");
}
public void NoteChanged(bool relayout)
{
if (relayout) {
string layout;
Arguments.TryGetValue("layout", out layout);
if (layout != null) {
if (_freeLastLayout)
gvFreeLayout(_context, _graph);
if (gvLayout(_context, _graph, layout) != 0)
throw new Exception("bad layout");
_freeLastLayout = true;
}
}
if (Changed != null)
Changed(this, EventArgs.Empty);
}
void IDisposable.Dispose()
{
agclose(_graph);
}
private unsafe class RenderStream : UnmanagedMemoryStream
{
public RenderStream(byte* pointer, long length): base(pointer, length)
{
_pointer = pointer;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
free(_pointer);
}
private readonly byte* _pointer;
}
[DllImport("libgraph-4.dll", SetLastError = true)]
private static extern void agclose(IntPtr file);
[DllImport("libgraph-4.dll")]
private static extern IntPtr agprotonode(IntPtr graph);
[DllImport("libgraph-4.dll")]
private static extern IntPtr agprotoedge(IntPtr graph);
[DllImport("libgraph-4.dll", SetLastError = true)]
private static extern IntPtr agread(IntPtr file);
[DllImport("libgraph-4.dll", SetLastError = true)]
private static extern int agwrite(IntPtr graph, IntPtr file);
[DllImport("libgvc-4.dll")]
private static extern IntPtr gvContext();
[DllImport("libgvc-4.dll")]
private static extern int gvFreeLayout(IntPtr context, IntPtr graph);
[DllImport("libgvc-4.dll")]
private static extern int gvLayout(IntPtr context, IntPtr graph, string engine);
[DllImport("libgvc-4.dll")]
private static extern IntPtr gvplugin_list(IntPtr context, API api, string str);
[DllImport("libgvc-4.dll")]
private static extern int gvRenderFilename(IntPtr context, IntPtr graph, string format, string filename);
[DllImport("libgvc-4.dll")]
private static extern unsafe int gvRenderData(IntPtr context, IntPtr graph, string format, out byte* result, out uint length);
[DllImport("msvcrt.dll", SetLastError = true)]
private static extern int fclose(IntPtr file);
[DllImport("msvcrt.dll", SetLastError = true)]
private static extern IntPtr fopen(string filename, string mode);
[DllImport("msvcrt.dll", SetLastError = true)]
private static extern unsafe void free(byte* pointer);
[DllImport("msvcrt.dll", SetLastError = true)]
private static extern void free(IntPtr pointer);
private static readonly IntPtr _context = gvContext();
private readonly IntPtr _graph;
private bool _freeLastLayout;
private readonly GraphArguments _arguments;
private readonly GraphDefaultAttributes _graphAttributes;
private readonly GraphDefaultAttributes _defaultNodeAttributes;
private readonly GraphDefaultAttributes _defaultEdgeAttributes;
}
}
|