packages feed

xdot (empty) → 0.1

raw patch · 15 files changed

+1826/−0 lines, 15 filesdep +basedep +cairodep +graphvizsetup-changed

Dependencies added: base, cairo, graphviz, gtk, mtl, polyparse, text

Files

+ Demo.hs view
@@ -0,0 +1,130 @@+-- Example of an XDot drawing with clickable nodes++import System.Environment+import Control.Monad+import Data.IORef++import Data.Text.IO hiding (putStrLn)+import qualified Data.Text.Lazy.IO as L+import qualified Data.Text.Lazy as B++import Data.GraphViz+import qualified Data.GraphViz.Types.Generalised as G++import Graphics.XDot.Parser+import Graphics.XDot.Viewer+import Graphics.XDot.Types hiding (w, h)++import Graphics.UI.Gtk hiding (Box, Signal, Dot, Point, Rectangle)+import Graphics.Rendering.Cairo+import qualified Graphics.UI.Gtk.Gdk.Events as E++data State = State+  { objects  :: ([(Maybe String, Operation)], Rectangle)+  , bounds   :: [(String, Rectangle)]+  , mousePos :: Point+  , hover    :: Maybe String+  }++main :: IO ()+main = do+  args <- getArgs++  if length args == 1 then run $ head args else error "Usage: Demo file.dot"++run :: String -> IO ()+run file = do+  dotText <- L.readFile file+  let dg = parseDotGraph dotText :: G.DotGraph String++  -- You can choose another graphviz command by changing Dot to Neato, TwoPi, Circo or Fdp+  xDotText <- graphvizWithHandle Dot dg XDot hGetContents+  let xdg = parseDotGraph $ B.fromChunks [xDotText] :: G.DotGraph String++  let objs = (getOperations xdg, getSize xdg)++  --putStrLn $ show xdg+  --putStrLn $ show objs++  state <- newIORef $ State objs [] (0,0) Nothing++  initGUI+  window <- windowNew+  canvas <- drawingAreaNew++  set window [ windowTitle := "XDot Demo"+             , containerChild := canvas+             ]++  onExpose canvas $ const $ do+    redraw canvas state+    return True++  onMotionNotify canvas False $ \e -> do+    modifyIORef state (\s -> s {mousePos = (E.eventX e, E.eventY e)})+    tick canvas state+    return True++  onButtonPress canvas $ \e -> do+    when (E.eventButton e == LeftButton && E.eventClick e == SingleClick) $+      click state dg+    return True++  widgetShowAll window+  onDestroy window mainQuit+  mainGUI++click :: IORef State -> G.DotGraph String -> IO ()+click state dg = do+  s <- readIORef state++  case hover s of+    Just t ->+      putStrLn $ t ++ " clicked"+    _ -> return ()++tick :: WidgetClass w => w -> IORef State -> IO ()+tick canvas state = do+  oldS <- readIORef state+  let oldHover = hover oldS++  modifyIORef state $ \s' -> (+    let (mx, my) = mousePos s'+        check (name', (x,y,w,h)) =+          if x <= mx && mx <= x + w &&+             y <= my && my <= y + h+          then Just name' else Nothing+    in s' {hover = msum $ map check (bounds s')}+    )++  s <- readIORef state+  unless (oldHover == hover s) $ widgetQueueDraw canvas++redraw :: WidgetClass w => w -> IORef State -> IO ()+redraw canvas state = do+  s <- readIORef state+  E.Rectangle _ _ rw rh <- widgetGetAllocation canvas++  let (ops, size'@(_,_,sw,sh)) = objects s++  boundingBoxes <- render canvas $ do+    -- Proportional scaling+    let scalex = min (fromIntegral rw / sw) (fromIntegral rh / sh)+        scaley = scalex+        offsetx = 0.5 * fromIntegral rw+        offsety = 0.5 * fromIntegral rh+    save+    translate offsetx offsety+    scale scalex scaley++    result <- drawAll (hover s) size' ops++    restore+    return $ map (\(o, (x,y,w,h)) -> (o, (x*scalex+offsetx,y*scaley+offsety,w*scalex,h*scaley))) result++  modifyIORef state (\s' -> s' {bounds = boundingBoxes})++render :: WidgetClass w => w -> Render b -> IO b+render canvas r = do+    win <- widgetGetDrawWindow canvas+    renderWithDrawable win r
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2012 Dennis Felsing++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,3 @@+module Main where+import Distribution.Simple+main = defaultMain
+ dot-examples/ER.dot view
@@ -0,0 +1,20 @@+graph ER {+	node [shape=box]; course; institute; student;+	node [shape=diamond,style=filled,color=lightgrey]; "C-I"; "S-C"; "S-I";++	name0 -- course;+	code -- course;+	course -- "C-I" [label="n",len=1.00];+	"C-I" -- institute [label="1",len=1.00];+	institute -- name1;+	institute -- "S-I" [label="1",len=1.00];+	"S-I" -- student [label="n",len=1.00];+	student -- grade;+	student -- name2;+	student -- number;+	student -- "S-C" [label="m",len=1.00];+	"S-C" -- course [label="n",len=1.00];++	label = "\n\nEntity Relation Diagram\ndrawn by NEATO";+	fontsize=20;+}
+ dot-examples/crazy.dot view
@@ -0,0 +1,104 @@+digraph "unix" {+	graph [	fontname = "Helvetica-Oblique",+		fontsize = 36,+		label = "\n\n\n\nObject Oriented Graphs\nStephen North, 3/19/93",+		size = "6,6" ];+	node [	shape = polygon,+		sides = 4,+		distortion = "0.0",+		orientation = "0.0",+		skew = "0.0",+		color = white,+		style = filled,+		fontname = "Helvetica-Outline" ];+	"5th Edition" [sides=9, distortion="0.936354", orientation=28, skew="-0.126818", color=salmon2];+	"6th Edition" [sides=5, distortion="0.238792", orientation=11, skew="0.995935", color=deepskyblue];+	"PWB 1.0" [sides=8, distortion="0.019636", orientation=79, skew="-0.440424", color=goldenrod2];+	LSX [sides=9, distortion="-0.698271", orientation=22, skew="-0.195492", color=burlywood2];+	"1 BSD" [sides=7, distortion="0.265084", orientation=26, skew="0.403659", color=gold1];+	"Mini Unix" [distortion="0.039386", orientation=2, skew="-0.461120", color=greenyellow];+	Wollongong [sides=5, distortion="0.228564", orientation=63, skew="-0.062846", color=darkseagreen];+	Interdata [distortion="0.624013", orientation=56, skew="0.101396", color=dodgerblue1];+	"Unix/TS 3.0" [sides=8, distortion="0.731383", orientation=43, skew="-0.824612", color=thistle2];+	"PWB 2.0" [sides=6, distortion="0.592100", orientation=34, skew="-0.719269", color=darkolivegreen3];+	"7th Edition" [sides=10, distortion="0.298417", orientation=65, skew="0.310367", color=chocolate];+	"8th Edition" [distortion="-0.997093", orientation=50, skew="-0.061117", color=turquoise3];+	"32V" [sides=7, distortion="0.878516", orientation=19, skew="0.592905", color=steelblue3];+	V7M [sides=10, distortion="-0.960249", orientation=32, skew="0.460424", color=navy];+	"Ultrix-11" [sides=10, distortion="-0.633186", orientation=10, skew="0.333125", color=darkseagreen4];+	Xenix [sides=8, distortion="-0.337997", orientation=52, skew="-0.760726", color=coral];+	"UniPlus+" [sides=7, distortion="0.788483", orientation=39, skew="-0.526284", color=darkolivegreen3];+	"9th Edition" [sides=7, distortion="0.138690", orientation=55, skew="0.554049", color=coral3];+	"2 BSD" [sides=7, distortion="-0.010661", orientation=84, skew="0.179249", color=blanchedalmond];+	"2.8 BSD" [distortion="-0.239422", orientation=44, skew="0.053841", color=lightskyblue1];+	"2.9 BSD" [distortion="-0.843381", orientation=70, skew="-0.601395", color=aquamarine2];+	"3 BSD" [sides=10, distortion="0.251820", orientation=18, skew="-0.530618", color=lemonchiffon];+	"4 BSD" [sides=5, distortion="-0.772300", orientation=24, skew="-0.028475", color=darkorange1];+	"4.1 BSD" [distortion="-0.226170", orientation=38, skew="0.504053", color=lightyellow1];+	"4.2 BSD" [sides=10, distortion="-0.807349", orientation=50, skew="-0.908842", color=darkorchid4];+	"4.3 BSD" [sides=10, distortion="-0.030619", orientation=76, skew="0.985021", color=lemonchiffon2];+	"Ultrix-32" [distortion="-0.644209", orientation=21, skew="0.307836", color=goldenrod3];+	"PWB 1.2" [sides=7, distortion="0.640971", orientation=84, skew="-0.768455", color=cyan];+	"USG 1.0" [distortion="0.758942", orientation=42, skew="0.039886", color=blue];+	"CB Unix 1" [sides=9, distortion="-0.348692", orientation=42, skew="0.767058", color=firebrick];+	"USG 2.0" [distortion="0.748625", orientation=74, skew="-0.647656", color=chartreuse4];+	"CB Unix 2" [sides=10, distortion="0.851818", orientation=32, skew="-0.020120", color=greenyellow];+	"CB Unix 3" [sides=10, distortion="0.992237", orientation=29, skew="0.256102", color=bisque4];+	"Unix/TS++" [sides=6, distortion="0.545461", orientation=16, skew="0.313589", color=mistyrose2];+	"PDP-11 Sys V" [sides=9, distortion="-0.267769", orientation=40, skew="0.271226", color=cadetblue1];+	"USG 3.0" [distortion="-0.848455", orientation=44, skew="0.267152", color=bisque2];+	"Unix/TS 1.0" [distortion="0.305594", orientation=75, skew="0.070516", color=orangered];+	"TS 4.0" [sides=10, distortion="-0.641701", orientation=50, skew="-0.952502", color=crimson];+	"System V.0" [sides=9, distortion="0.021556", orientation=26, skew="-0.729938", color=darkorange1];+	"System V.2" [sides=6, distortion="0.985153", orientation=33, skew="-0.399752", color=darkolivegreen4];+	"System V.3" [sides=7, distortion="-0.687574", orientation=58, skew="-0.180116", color=lightsteelblue1];+	"5th Edition" -> "6th Edition";+	"5th Edition" -> "PWB 1.0";+	"6th Edition" -> LSX;+	"6th Edition" -> "1 BSD";+	"6th Edition" -> "Mini Unix";+	"6th Edition" -> Wollongong;+	"6th Edition" -> Interdata;+	Interdata -> "Unix/TS 3.0";+	Interdata -> "PWB 2.0";+	Interdata -> "7th Edition";+	"7th Edition" -> "8th Edition";+	"7th Edition" -> "32V";+	"7th Edition" -> V7M;+	"7th Edition" -> "Ultrix-11";+	"7th Edition" -> Xenix;+	"7th Edition" -> "UniPlus+";+	V7M -> "Ultrix-11";+	"8th Edition" -> "9th Edition";+	"1 BSD" -> "2 BSD";+	"2 BSD" -> "2.8 BSD";+	"2.8 BSD" -> "Ultrix-11";+	"2.8 BSD" -> "2.9 BSD";+	"32V" -> "3 BSD";+	"3 BSD" -> "4 BSD";+	"4 BSD" -> "4.1 BSD";+	"4.1 BSD" -> "4.2 BSD";+	"4.1 BSD" -> "2.8 BSD";+	"4.1 BSD" -> "8th Edition";+	"4.2 BSD" -> "4.3 BSD";+	"4.2 BSD" -> "Ultrix-32";+	"PWB 1.0" -> "PWB 1.2";+	"PWB 1.0" -> "USG 1.0";+	"PWB 1.2" -> "PWB 2.0";+	"USG 1.0" -> "CB Unix 1";+	"USG 1.0" -> "USG 2.0";+	"CB Unix 1" -> "CB Unix 2";+	"CB Unix 2" -> "CB Unix 3";+	"CB Unix 3" -> "Unix/TS++";+	"CB Unix 3" -> "PDP-11 Sys V";+	"USG 2.0" -> "USG 3.0";+	"USG 3.0" -> "Unix/TS 3.0";+	"PWB 2.0" -> "Unix/TS 3.0";+	"Unix/TS 1.0" -> "Unix/TS 3.0";+	"Unix/TS 3.0" -> "TS 4.0";+	"Unix/TS++" -> "TS 4.0";+	"CB Unix 3" -> "TS 4.0";+	"TS 4.0" -> "System V.0";+	"System V.0" -> "System V.2";+	"System V.2" -> "System V.3";+}
+ dot-examples/fsm.dot view
@@ -0,0 +1,20 @@+digraph finite_state_machine {+	rankdir=LR;+	size="8,5"+	node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8;+	node [shape = circle];+	LR_0 -> LR_2 [ label = "SS(B)" ];+	LR_0 -> LR_1 [ label = "SS(S)" ];+	LR_1 -> LR_3 [ label = "S($end)" ];+	LR_2 -> LR_6 [ label = "SS(b)" ];+	LR_2 -> LR_5 [ label = "SS(a)" ];+	LR_2 -> LR_4 [ label = "S(A)" ];+	LR_5 -> LR_7 [ label = "S(b)" ];+	LR_5 -> LR_5 [ label = "S(a)" ];+	LR_6 -> LR_6 [ label = "S(b)" ];+	LR_6 -> LR_5 [ label = "S(a)" ];+	LR_7 -> LR_8 [ label = "S(b)" ];+	LR_7 -> LR_5 [ label = "S(a)" ];+	LR_8 -> LR_6 [ label = "S(b)" ];+	LR_8 -> LR_5 [ label = "S(a)" ];+}
+ dot-examples/sdh.dot view
@@ -0,0 +1,284 @@+digraph G {+	graph [bgcolor=black];	/* set background */+	edge [color=white];+	graph[page="8.5,11",size="7.5,7",ratio=fill,center=1];+	node[style=filled,label=""];+	subgraph ds3CTP {+		rank = same;+		node[shape=box,color=green];+		ds3CTP_1_1;+		ds3CTP_1_2;+		ds3CTP_5_1;+		ds3CTP_5_2;+	}+	subgraph t3TTP {+		rank = same;+		node[shape=invtriangle,color=red];+		t3TTP_1_1;+		t3TTP_5_2;+	}+	subgraph vc3TTP {+		rank = same;+		node[shape=invtriangle,color=red];+		vc3TTP_1_2;+		vc3TTP_5_1;+	}+	subgraph fabric {+		rank = same;+		node[shape=hexagon,color=blue];+		fabric_1_2;+		fabric_4_1;+		fabric_5_1;+	}+	subgraph xp {+		rank = same;+		node[shape=diamond,color=blue];+		xp_1_2;+		xp_4_1;+		xp_5_1;+	}+	subgraph au3CTP {+		rank = same;+		node[shape=box,color=green];+		au3CTP_1_2;+		au3CTP_4_1;+		au3CTP_4_2;+		au3CTP_5_1;+	}+	subgraph aug {+		rank = same;+		node[shape=invtrapezium,color=pink];+		aug_1_2;+		aug_4_1;+		aug_4_2;+		aug_5_1;+	}+	subgraph protectionTTP {+		rank = same;+		node[shape=invtriangle,color=red];+		prTTP_1_2;+		prTTP_4_1;+		prTTP_4_2;+		prTTP_5_1;+	}+	subgraph protectionGroup {+		rank = same;+		node[shape=hexagon,color=blue];+		pg_1_2;+		pg_4_1;+		pg_4_2;+		pg_5_1;+	}+	subgraph protectionUnit {+		rank = same;+		node[shape=diamond,color=blue];+		pu_1_2;+		pu_4_1;+		pu_4_2;+		pu_5_1;+	}+	subgraph protectionCTP {+		node[shape=box,color=green];+		prCTP_1_2;+		prCTP_4_1;+		prCTP_4_2;+		prCTP_5_1;+	}+	subgraph msTTP {+		rank = same;+		node[shape=invtriangle,color=red];+		msTTP_1_2;+		msTTP_4_1;+		msTTP_4_2;+		msTTP_5_1;+	}+	subgraph msCTP {+		rank = same;+		node[shape=box,color=green];+		msCTP_1_2;+		msCTP_3_1;+		msCTP_3_2;+		msCTP_4_1;+		msCTP_4_2;+		msCTP_5_1;+	}+	subgraph rsTTP {+		rank = same;+		node[shape=invtriangle,color=red];+		rsTTP_1_2;+		rsTTP_3_1;+		rsTTP_3_2;+		rsTTP_4_1;+		rsTTP_4_2;+		rsTTP_5_1;+	}+	subgraph rsCTP {+		rank = same;+		node[shape=box,color=green];+		rsCTP_1_2;+		rsCTP_2_1;+		rsCTP_2_2;+		rsCTP_3_1;+		rsCTP_3_2;+		rsCTP_4_1;+		rsCTP_4_2;+		rsCTP_5_1;+	}+	subgraph spiTTP {+		rank = same;+		node[shape=invtriangle,color=red];+		spiTTP_1_2;+		spiTTP_2_1;+		spiTTP_2_2;+		spiTTP_3_1;+		spiTTP_3_2;+		spiTTP_4_1;+		spiTTP_4_2;+		spiTTP_5_1;+	}+	subgraph me {+		rank = same;+		node[shape=box,peripheries=2];+		me_1;+		me_2;+		me_3;+		me_4;+		me_5;+	}+	subgraph client_server {+		edge[style=dotted,dir=none,weight=100];+		ds3CTP_1_1->t3TTP_1_1;+		ds3CTP_1_2->vc3TTP_1_2;+		au3CTP_1_2->aug_1_2->prTTP_1_2;+		prCTP_1_2->msTTP_1_2;+		msCTP_1_2->rsTTP_1_2;+		rsCTP_1_2->spiTTP_1_2;+		rsCTP_2_1->spiTTP_2_1;+		rsCTP_2_2->spiTTP_2_2;+		msCTP_3_1->rsTTP_3_1;+		rsCTP_3_1->spiTTP_3_1;+		msCTP_3_2->rsTTP_3_2;+		rsCTP_3_2->spiTTP_3_2;+		au3CTP_4_1->aug_4_1->prTTP_4_1;+		prCTP_4_1->msTTP_4_1;+		msCTP_4_1->rsTTP_4_1;+		rsCTP_4_1->spiTTP_4_1;+		au3CTP_4_2->aug_4_2->prTTP_4_2;+		prCTP_4_2->msTTP_4_2;+		msCTP_4_2->rsTTP_4_2;+		rsCTP_4_2->spiTTP_4_2;+		ds3CTP_5_1->vc3TTP_5_1;+		au3CTP_5_1->aug_5_1->prTTP_5_1;+		prCTP_5_1->msTTP_5_1;+		msCTP_5_1->rsTTP_5_1;+		rsCTP_5_1->spiTTP_5_1;+		ds3CTP_5_2->t3TTP_5_2;+	}+	subgraph trail {+		edge[style=dashed,dir=none];+		vc3TTP_1_2->vc3TTP_5_1;+		prTTP_1_2->prTTP_4_1;+		prTTP_4_2->prTTP_5_1;+		msTTP_1_2->msTTP_4_1;+		msTTP_4_2->msTTP_5_1;+		rsTTP_1_2->rsTTP_3_1;+		rsTTP_3_2->rsTTP_4_1;+		rsTTP_4_2->rsTTP_5_1;+		spiTTP_1_2->spiTTP_2_1;+		spiTTP_2_2->spiTTP_3_1;+		spiTTP_3_2->spiTTP_4_1;+		spiTTP_4_2->spiTTP_5_1;+	}+	subgraph contain {+		pu_1_2->pg_1_2;+		pu_4_1->pg_4_1;+		pu_4_2->pg_4_2;+		pu_5_1->pg_5_1;+		xp_1_2->fabric_1_2;+		xp_4_1->fabric_4_1;+		xp_5_1->fabric_5_1;+		fabric_1_2->me_1;+		fabric_4_1->me_4;+		fabric_5_1->me_5;+		pg_1_2->me_1;+		pg_4_1->me_4;+		pg_4_2->me_4;+		pg_5_1->me_5;+		t3TTP_1_1->me_1;+		t3TTP_5_2->me_5;+		vc3TTP_1_2->me_1;+		vc3TTP_5_1->me_5;+		prTTP_1_2->me_1;+		prTTP_4_1->me_4;+		prTTP_4_2->me_4;+		prTTP_5_1->me_5;+		msTTP_1_2->me_1;+		msTTP_4_1->me_4;+		msTTP_4_2->me_4;+		msTTP_5_1->me_5;+		rsTTP_1_2->me_1;+		rsTTP_3_1->me_3;+		rsTTP_3_2->me_3;+		rsTTP_4_1->me_4;+		rsTTP_4_2->me_4;+		rsTTP_5_1->me_5;+		spiTTP_1_2->me_1;+		spiTTP_2_1->me_2;+		spiTTP_2_2->me_2;+		spiTTP_3_1->me_3;+		spiTTP_3_2->me_3;+		spiTTP_4_1->me_4;+		spiTTP_4_2->me_4;+		spiTTP_5_1->me_5;+	}+	subgraph connectedBy {+		vc3TTP_1_2->fabric_1_2;+		au3CTP_1_2->fabric_1_2;+		au3CTP_4_1->fabric_4_1;+		au3CTP_4_2->fabric_4_1;+		vc3TTP_5_1->fabric_5_1;+		au3CTP_5_1->fabric_5_1;+		prTTP_1_2->pg_1_2;+		prTTP_4_1->pg_4_1;+		prTTP_4_2->pg_4_2;+		prTTP_5_1->pg_5_1;+		prCTP_1_2->pg_1_2;+		prCTP_4_1->pg_4_1;+		prCTP_4_2->pg_4_2;+		prCTP_5_1->pg_5_1;+	}+	subgraph crossConnection {+		edge[style=dotted,dir=none];+		vc3TTP_1_2->xp_1_2->au3CTP_1_2;+		prTTP_1_2->pu_1_2->prCTP_1_2;+		prTTP_4_1->pu_4_1->prCTP_4_1;+		au3CTP_4_1->xp_4_1->au3CTP_4_2;+		prTTP_4_2->pu_4_2->prCTP_4_2;+		prTTP_5_1->pu_5_1->prCTP_5_1;+		vc3TTP_5_1->xp_5_1->au3CTP_5_1;+	}+	subgraph bindingConnection {+		edge[style=bold,dir=none,weight=100];+		ds3CTP_1_1->ds3CTP_1_2;+		vc3TTP_1_2->au3CTP_1_2;+		prTTP_1_2->prCTP_1_2;+		msTTP_1_2->msCTP_1_2;+		rsTTP_1_2->rsCTP_1_2;+		rsCTP_2_1->rsCTP_2_2;+		rsTTP_3_1->rsCTP_3_1;+		msCTP_3_1->msCTP_3_2;+		rsTTP_3_2->rsCTP_3_2;+		prTTP_4_1->prCTP_4_1;+		msTTP_4_1->msCTP_4_1;+		rsTTP_4_1->rsCTP_4_1;+		au3CTP_4_1->au3CTP_4_2;+		prTTP_4_2->prCTP_4_2;+		msTTP_4_2->msCTP_4_2;+		rsTTP_4_2->rsCTP_4_2;+		prTTP_5_1->prCTP_5_1;+		msTTP_5_1->msCTP_5_1;+		rsTTP_5_1->rsCTP_5_1;+		ds3CTP_5_1->ds3CTP_5_2;+		vc3TTP_5_1->au3CTP_5_1;+	}+}
+ dot-examples/siblings.dot view
@@ -0,0 +1,512 @@+/*
+This is a graphviz-produced layout of the "family tree" of a fraternity and sorority.
+
+Each member in the graph was assigned a "big brother" from one organization and a "big sister" from the other. Blue icons represent Brothers from the fraternity, Pink represents Sisters from the sorority (Purple members are in both organizations - like honoraries.)
+
+Charter members (who can have no parent nodes) are outlined.
+
+...
+
+dot -Tgif -Goverlap=false -o siblings.gif siblings.dot
+
+
+We're experimenting with different ways of coloring and graphing, but found this the easiest for now. When we have more people in, we might look at different shades depending on generation number -- earlier people would get lighter colors, more recent members darker. Thumbnail images would be an interesting alteration as well.
+
+from Japheth Cleaver
+*/
+
+
+digraph sdsu {
+	size="36,36";
+	node [color=grey, style=filled];    
+	node [fontname="Verdana", size="30,30"];
+	graph [ fontname = "Arial",
+	  fontsize = 36,
+          style = "bold",
+          label = "\nKappa Kappa Psi/Tau Beta Sigma\nSan Diego State University\nEta Mu and Zeta Xi Family Tree\n\nto date: November 30th, 2008\n",
+	  ssize = "30,60" ];
+"Lori Brede" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=10"];
+"Michael Griffith" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=24"];
+"Amie Holston" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=30"];
+"Michael Griffith" -> "Lori Brede"
+"Amie Holston" -> "Lori Brede"
+"Casey Carter" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=11"];
+"Laura De'Armond" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=14"];
+"Laura De'Armond" -> "Casey Carter"
+"Japheth Cleaver" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=12"];
+"Chuk Gawlik" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=22"];
+"Stacy Snyder" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=309"];
+"Chuk Gawlik" -> "Japheth Cleaver"
+"Stacy Snyder" -> "Japheth Cleaver"
+"Jillian Clifton" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=13"];
+"David Guthrie" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=25"];
+"David Guthrie" -> "Jillian Clifton"
+"Japheth Cleaver" -> "Jillian Clifton"
+"Tony Sacco" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=55"];
+"Heather Smith" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=59"];
+"Tony Sacco" -> "Laura De'Armond"
+"Heather Smith" -> "Laura De'Armond"
+"Kevin Decker" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=15"];
+"Alex Hansen" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=26"];
+"Wanda Livelsberger" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=53"];
+"Alex Hansen" -> "Kevin Decker"
+"Wanda Livelsberger" -> "Kevin Decker"
+"Patrick Doerr" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=16"];
+"Deanna Jagow" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=23"];
+"Alex Hansen" -> "Patrick Doerr"
+"Deanna Jagow" -> "Patrick Doerr"
+"Lori Asaro" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=178"];
+"Mark Pearson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=169"];
+"Lori Ball" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=167"];
+"Mark Pearson" -> "Lori Asaro"
+"Lori Ball" -> "Lori Asaro"
+"Ryan Farris" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=18"];
+"Rob Reiner" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=51"];
+"Cindy Teel" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=62"];
+"Rob Reiner" -> "Ryan Farris"
+"Cindy Teel" -> "Ryan Farris"
+"Ginger Palmer" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=180"];
+"Mark Newton-John" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=46"];
+"Mark Newton-John" -> "Ginger Palmer"
+"Matthew FitzGerald" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=19"];
+"Mervin Maniago" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=41"];
+"Mervin Maniago" -> "Matthew FitzGerald"
+"Amie Holston" -> "Matthew FitzGerald"
+"Tani Miller" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=195"];
+"Mark Pearson" -> "Tani Miller"
+"Vienna McMurtry" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=196"];
+"Robert Walwick" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=153"];
+"Robert Walwick" -> "Vienna McMurtry"
+"Ginger Palmer" -> "Vienna McMurtry"
+"Chuck Foster" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=20"];
+"Karen Saye" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=56"];
+"Kevin Decker" -> "Chuck Foster"
+"Karen Saye" -> "Chuck Foster"
+"Gary Frampton" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=201"];
+"Ginger Palmer" -> "Gary Frampton"
+"Pat Norris" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=207"];
+"Sean Tipps" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=204"];
+"Teresa Long" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=194"];
+"Sean Tipps" -> "Pat Norris"
+"Teresa Long" -> "Pat Norris"
+"Marc Martin-ez" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=208"];
+"Mark Pearson" -> "Marc Martin-ez"
+"Tani Miller" -> "Marc Martin-ez"
+"Kristen Villone" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=209"];
+"Kelly Erickson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=199"];
+"Anna Pedroza" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=197"];
+"Kelly Erickson" -> "Kristen Villone"
+"Anna Pedroza" -> "Kristen Villone"
+"Geoff Frank" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=21"];
+"Chris Livelsberger" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=40"];
+"Amy Price" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=57"];
+"Chris Livelsberger" -> "Geoff Frank"
+"Amy Price" -> "Geoff Frank"
+"Tracy Murray" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=210"];
+"John FitzGibbon" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=92"];
+"Judy Dulcich" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=177"];
+"John FitzGibbon" -> "Tracy Murray"
+"Judy Dulcich" -> "Tracy Murray"
+"Ian McIntosh" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=215"];
+"Barbara Tollison" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=172"];
+"Robert Walwick" -> "Ian McIntosh"
+"Barbara Tollison" -> "Ian McIntosh"
+"Jayson Smith" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=58"];
+"Jayson Smith" -> "Chuk Gawlik"
+"Heather Smith" -> "Chuk Gawlik"
+"Kelly McKinney" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=222"];
+"Mark Nadeau" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=183"];
+"Mark Nadeau" -> "Kelly McKinney"
+"Judy Dulcich" -> "Kelly McKinney"
+"Chris Livelsberger" -> "Deanna Jagow"
+"Amy Price" -> "Deanna Jagow"
+"Renee Thompson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=231"];
+"J. Angeles" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=3"];
+"Kelley Smith" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=223"];
+"J. Angeles" -> "Renee Thompson"
+"Kelley Smith" -> "Renee Thompson"
+"Steven Smith" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=233"];
+"John FitzGibbon" -> "Steven Smith"
+"Charlene Andrews" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=234"];
+"Diane Reoch" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=227"];
+"Diane Reoch" -> "Charlene Andrews"
+"Tonya Alexander" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=238"];
+"Gail Vasquez" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=225"];
+"Gail Vasquez" -> "Tonya Alexander"
+"Spencer Caldwell" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=239"];
+"Becky Bernal" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=218"];
+"Becky Bernal" -> "Spencer Caldwell"
+"Chuk Gawlik" -> "Michael Griffith"
+"Wanda Livelsberger" -> "Michael Griffith"
+"Russell Grant" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=242"];
+"Steven Smith" -> "Russell Grant"
+"Tiffany Worthington" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=66"];
+"Chuck Foster" -> "David Guthrie"
+"Tiffany Worthington" -> "David Guthrie"
+"Jerry Maya" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=250"];
+"John FitzGibbon" -> "Jerry Maya"
+"Melissa Schwartz" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=252"];
+"Russell Grant" -> "Melissa Schwartz"
+"Delphy Shaulis" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=255"];
+"Renee Thompson" -> "Delphy Shaulis"
+"Martin Naiman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=45"];
+"Janean Angeles" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=86"];
+"Martin Naiman" -> "Alex Hansen"
+"Janean Angeles" -> "Alex Hansen"
+"Leslie Harlow" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=265"];
+"Dennis McColl" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=251"];
+"Denise Luna" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=236"];
+"Dennis McColl" -> "Leslie Harlow"
+"Denise Luna" -> "Leslie Harlow"
+"Jonathan Yudman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=267"];
+"April Ortiz-cloninger" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=258"];
+"April Ortiz-cloninger" -> "Jonathan Yudman"
+"Michael Elgo" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=268"];
+"Carol Kropp" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=254"];
+"Spencer Caldwell" -> "Michael Elgo"
+"Carol Kropp" -> "Michael Elgo"
+"Denmark Vea" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=269"];
+"Marc Martin-ez" -> "Denmark Vea"
+"Kelley Smith" -> "Denmark Vea"
+"Kathleen Hansen" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=27"];
+"Martin Naiman" -> "Kathleen Hansen"
+"Heather Smith" -> "Kathleen Hansen"
+"Laura Stegner" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=274"];
+"April Ortiz-cloninger" -> "Laura Stegner"
+"Kathy Jones" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=28"];
+"J. Angeles" -> "Kathy Jones"
+"Eric Gates" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=282"];
+"Erick Sugimura" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=280"];
+"Erick Sugimura" -> "Eric Gates"
+"Laura Stegner" -> "Eric Gates"
+"Jennifer Stoewe" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=288"];
+"Eric Gates" -> "Jennifer Stoewe"
+"Karen Helbling" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=29"];
+"Regan Ashker" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=5"];
+"Kevin Decker" -> "Karen Helbling"
+"Regan Ashker" -> "Karen Helbling"
+"Scott Wood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=295"];
+"Eric Gates" -> "Scott Wood"
+"Greg Flood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=200"];
+"Greg Flood" -> "J. Angeles"
+"Ginger Palmer" -> "J. Angeles"
+"Lynn Reeves" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=48"];
+"Chuk Gawlik" -> "Amie Holston"
+"Lynn Reeves" -> "Amie Holston"
+"Susan Colwell" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=302"];
+"Michael Elgo" -> "Susan Colwell"
+"Christopher Jouan" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=306"];
+"Kevin Owens" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=245"];
+"Kevin Owens" -> "Christopher Jouan"
+"Kristianna Reynante" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=308"];
+"Michael Elgo" -> "Kristianna Reynante"
+"Janean Angeles" -> "Kristianna Reynante"
+"Amy Berner" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=300"];
+"Amy Berner" -> "Stacy Snyder"
+"Deanna Johnson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=31"];
+"Alex Hansen" -> "Deanna Johnson"
+"Laura De'Armond" -> "Deanna Johnson"
+"Johnny Richardson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=310"];
+"Russell Grant" -> "Johnny Richardson"
+"Nathan Fellhauer" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=313"];
+"James Rowland" [color=thistle, URL="http://sdsu.kkytbs.net/members/profile.html?who=52"];
+"James Rowland" -> "Nathan Fellhauer"
+"Kristianna Reynante" -> "Nathan Fellhauer"
+"Brian Raneses" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=314"];
+"Sean McHenry" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=42"];
+"Sean McHenry" -> "Brian Raneses"
+"Penny Lewis" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=315"];
+"Martin Naiman" -> "Penny Lewis"
+"Becky Graham" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=316"];
+"Kristen Elgo" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=7"];
+"Kristen Elgo" -> "Becky Graham"
+"Steven Gross" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=318"];
+"Rob Reiner" -> "Steven Gross"
+"Stacy Snyder" -> "Steven Gross"
+"Sedona Reynolds" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=32"];
+"Mark Newton-John" -> "Sedona Reynolds"
+"Cindy Teel" -> "Sedona Reynolds"
+"Klair Mayerchak" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=320"];
+"Nathan Fellhauer" -> "Klair Mayerchak"
+"Becky Graham" -> "Klair Mayerchak"
+"Shari VerBerkmoes" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=321"];
+"Sean McHenry" -> "Shari VerBerkmoes"
+"Janean Angeles" -> "Shari VerBerkmoes"
+"Anson Summers" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=326"];
+"James Rowland" -> "Anson Summers"
+"Dusty Jolliff" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=33"];
+"Rob Reiner" -> "Dusty Jolliff"
+"Stacy Snyder" -> "Dusty Jolliff"
+"Jennifer Garman" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=331"];
+"James Rowland" -> "Jennifer Garman"
+"Kelly Greenhill" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=333"];
+"Rob Reiner" -> "Kelly Greenhill"
+"Kristen Elgo" -> "Kelly Greenhill"
+"Lucinda Farless" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=334"];
+"J. Angeles" -> "Lucinda Farless"
+"Susan Colwell" -> "Lucinda Farless"
+"Alfredo Cardenas" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=335"];
+"Chuk Gawlik" -> "Alfredo Cardenas"
+"Kathleen Hansen" -> "Alfredo Cardenas"
+"Jennifer Jouan" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=34"];
+"Andrea Owens" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=276"];
+"Andrea Owens" -> "Jennifer Jouan"
+"Tamara Scrivner" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=345"];
+"Joseph Butler" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=69"];
+"Sarah Maltese" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=83"];
+"Joseph Butler" -> "Tamara Scrivner"
+"Sarah Maltese" -> "Tamara Scrivner"
+"Bradley Stouse" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=346"];
+"Ryan Underwood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=74"];
+"Ryan Underwood" -> "Bradley Stouse"
+"Cindy Teel" -> "Bradley Stouse"
+"Casondra Brimmage" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=347"];
+"Kristopher Lininger" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=85"];
+"Ilana Melcher" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=73"];
+"Kristopher Lininger" -> "Casondra Brimmage"
+"Ilana Melcher" -> "Casondra Brimmage"
+"Cassiopeia Guthrie" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=348"];
+"Jeremy Frazier" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=79"];
+"Christine Mount" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=76"];
+"Jeremy Frazier" -> "Cassiopeia Guthrie"
+"Christine Mount" -> "Cassiopeia Guthrie"
+"Kathleen Moran" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=349"];
+"Matthew FitzGerald" -> "Kathleen Moran"
+"Lori Brede" -> "Kathleen Moran"
+"Tiffany Kalland" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=35"];
+"Tony Sacco" -> "Tiffany Kalland"
+"Karen Helbling" -> "Tiffany Kalland"
+"Kristen Anderson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=350"];
+"Jennie Bogart" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=78"];
+"David Guthrie" -> "Kristen Anderson"
+"Jennie Bogart" -> "Kristen Anderson"
+"Laura Simonette" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=351"];
+"Jon Weisel" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=89"];
+"Jon Weisel" -> "Laura Simonette"
+"Japheth Cleaver" -> "Laura Simonette"
+"Nathan Williams" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=352"];
+"David Guthrie" -> "Nathan Williams"
+"Karen Helbling" -> "Nathan Williams"
+"Rebecca Hippert" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=353"];
+"Ryan Underwood" -> "Rebecca Hippert"
+"Tiffany Kalland" -> "Rebecca Hippert"
+"Samuel Wallace" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=354"];
+"Joseph Butler" -> "Samuel Wallace"
+"Deanna Jagow" -> "Samuel Wallace"
+"Scott Gardner" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=355"];
+"Jeremy Frazier" -> "Scott Gardner"
+"Christine Mount" -> "Scott Gardner"
+"Alberto Ayon" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=356"];
+"Bradley Stouse" -> "Alberto Ayon"
+"Jennie Bogart" -> "Alberto Ayon"
+"Susannah Clayton" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=357"];
+"Nathan Williams" -> "Susannah Clayton"
+"Karen Helbling" -> "Susannah Clayton"
+"Lisa Gochnauer" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=358"];
+"Scott Gardner" -> "Lisa Gochnauer"
+"Casondra Brimmage" -> "Lisa Gochnauer"
+"Jamie Jackson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=359"];
+"Samuel Wallace" -> "Jamie Jackson"
+"Tamara Scrivner" -> "Jamie Jackson"
+"Christina Kelly" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=36"];
+"Matthew FitzGerald" -> "Christina Kelly"
+"Lori Brede" -> "Christina Kelly"
+"Gara Thornton" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=360"];
+"Mark Newton-John" -> "Gara Thornton"
+"Laura Simonette" -> "Gara Thornton"
+"Robert Winebarger" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=361"];
+"Robin Ellison" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=90"];
+"Scott Gardner" -> "Robert Winebarger"
+"Robin Ellison" -> "Robert Winebarger"
+"Jeremy Kirchner" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=37"];
+"Rob Reiner" -> "Jeremy Kirchner"
+"Sandy Konar" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=38"];
+"Jennifer Brandon" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=9"];
+"Jennifer Brandon" -> "Sandy Konar"
+"Dan Kuhlman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=39"];
+"Rob Reiner" -> "Dan Kuhlman"
+"Dusty Jolliff" -> "Dan Kuhlman"
+"Lindsay Arehart" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=4"];
+"Martin Naiman" -> "Lindsay Arehart"
+"Jennifer Brandon" -> "Lindsay Arehart"
+"J. Angeles" -> "Mervin Maniago"
+"Kathy Jones" -> "Mervin Maniago"
+"Jarrod Monroe" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=43"];
+"Jamie Fratacci" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=44"];
+"Mark Newton-John" -> "Jarrod Monroe"
+"Jamie Fratacci" -> "Jarrod Monroe"
+"Chuk Gawlik" -> "Jamie Fratacci"
+"Tiffany Worthington" -> "Jamie Fratacci"
+"Russell Grant" -> "Martin Naiman"
+"Tonya Alexander" -> "Martin Naiman"
+"Edward Givens" [color=lightblue, outline=bold, style=bold, URL="http://sdsu.kkytbs.net/members/profile.html?who=106"];
+"Edward Givens" -> "Mark Newton-John"
+"Veronica Nickel" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=47"];
+"Regan Ashker" -> "Veronica Nickel"
+"Wanda Livelsberger" -> "Lynn Reeves"
+"Bryan Ransom" [color=thistle, URL="http://sdsu.kkytbs.net/members/profile.html?who=49"];
+"Jayson Smith" -> "Bryan Ransom"
+"Tony Sacco" -> "Regan Ashker"
+"Dusty Jolliff" -> "Regan Ashker"
+"Jennifer Stout" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=50"];
+"Matthew FitzGerald" -> "Jennifer Stout"
+"Deanna Jagow" -> "Jennifer Stout"
+"Sean McHenry" -> "James Rowland"
+"James Rowland" -> "Wanda Livelsberger"
+"Janean Angeles" -> "Wanda Livelsberger"
+"Melissa Roy" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=54"];
+"Mervin Maniago" -> "Melissa Roy"
+"Christina Kelly" -> "Melissa Roy"
+"Dennis McColl" -> "Tony Sacco"
+"April Ortiz-cloninger" -> "Tony Sacco"
+"Tony Sacco" -> "Karen Saye"
+"Tony Sacco" -> "Amy Price"
+"Kathleen Hansen" -> "Amy Price"
+"James Rowland" -> "Jayson Smith"
+"Brian Raneses" -> "Heather Smith"
+"Kristen Elgo" -> "Heather Smith"
+"Josh Atwood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=6"];
+"David Guthrie" -> "Josh Atwood"
+"Lori Brede" -> "Josh Atwood"
+"Katie Browne" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=60"];
+"Patrick Doerr" -> "Katie Browne"
+"Jamie Fratacci" -> "Katie Browne"
+"Kristin Tang" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=61"];
+"James Rowland" -> "Kristin Tang"
+"Heather Smith" -> "Kristin Tang"
+"Mervin Maniago" -> "Cindy Teel"
+"Veronica Nickel" -> "Cindy Teel"
+"Mike Tulumello" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=63"];
+"Matthew FitzGerald" -> "Mike Tulumello"
+"Katie Browne" -> "Mike Tulumello"
+"Veronica Villanueva" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=64"];
+"Ryan Farris" -> "Veronica Villanueva"
+"Sedona Reynolds" -> "Veronica Villanueva"
+"Mervin Maniago" -> "Tiffany Worthington"
+"Jennifer Jouan" -> "Tiffany Worthington"
+"Scott Wright" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=67"];
+"James Rowland" -> "Scott Wright"
+"Kristen Elgo" -> "Scott Wright"
+"Jeremy Browne" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=68"];
+"Matthew FitzGerald" -> "Jeremy Browne"
+"Japheth Cleaver" -> "Jeremy Browne"
+"James Fogelman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=688"];
+"Alberto Ayon" -> "James Fogelman"
+"Susannah Clayton" -> "James Fogelman"
+"Sandra Chase" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=689"];
+"David Guthrie" -> "Sandra Chase"
+"Japheth Cleaver" -> "Sandra Chase"
+"Patrick Doerr" -> "Joseph Butler"
+"Deanna Jagow" -> "Joseph Butler"
+"Laura Fisher" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=690"];
+"Nathan Williams" -> "Laura Fisher"
+"Casondra Brimmage" -> "Laura Fisher"
+"Katie Kozma" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=691"];
+"Scott Wright" -> "Katie Kozma"
+"Robin Ellison" -> "Katie Kozma"
+"Rachel Perkins" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=692"];
+"Joseph Butler" -> "Rachel Perkins"
+"Cassiopeia Guthrie" -> "Rachel Perkins"
+"Sarah Titilah" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=693"];
+"Robert Winebarger" -> "Sarah Titilah"
+"Karen Helbling" -> "Sarah Titilah"
+"Ashley Rehart" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=694"];
+"Laura Fisher" -> "Ashley Rehart"
+"Cara Yancey" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=695"];
+"Katie Kozma" -> "Cara Yancey"
+"Ashley Presley" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=698"];
+"Cara Yancey" -> "Ashley Presley"
+"Leila Wilhelm" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=699"];
+"Robin Ellison" -> "Leila Wilhelm"
+"Sean McHenry" -> "Kristen Elgo"
+"Stacy Snyder" -> "Kristen Elgo"
+"Greg Moody" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=70"];
+"Ryan Farris" -> "Greg Moody"
+"Jennifer Stout" -> "Greg Moody"
+"Lisa Fleck" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=700"];
+"Rachel Perkins" -> "Lisa Fleck"
+"Christine Coyne" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=701"];
+"Rachel Perkins" -> "Christine Coyne"
+"Jennifer Cooley" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=702"];
+"Laura Fisher" -> "Jennifer Cooley"
+"Elizabeth Larios" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=703"];
+"Ashley Rehart" -> "Elizabeth Larios"
+"Cate Threlkeld" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=707"];
+"Katie Kozma" -> "Cate Threlkeld"
+"Erika Tapia" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=71"];
+"Patrick Doerr" -> "Erika Tapia"
+"Melissa Roy" -> "Erika Tapia"
+"Robbyn Rozelle" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=72"];
+"Jarrod Monroe" -> "Robbyn Rozelle"
+"Tiffany Kalland" -> "Robbyn Rozelle"
+"Ryan Farris" -> "Ilana Melcher"
+"Veronica Villanueva" -> "Ilana Melcher"
+"Greg Moody" -> "Ryan Underwood"
+"Katie Browne" -> "Ryan Underwood"
+"Cameron Brown" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=75"];
+"Joseph Butler" -> "Cameron Brown"
+"Tiffany Kalland" -> "Cameron Brown"
+"Ryan Underwood" -> "Christine Mount"
+"Lori Brede" -> "Christine Mount"
+"Janay Rabe" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=77"];
+"Greg Moody" -> "Janay Rabe"
+"Cindy Teel" -> "Janay Rabe"
+"Jeremy Browne" -> "Jennie Bogart"
+"Tiffany Kalland" -> "Jennie Bogart"
+"Ryan Farris" -> "Jeremy Frazier"
+"Ilana Melcher" -> "Jeremy Frazier"
+"Crystal Bozak" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=8"];
+"Patrick Doerr" -> "Crystal Bozak"
+"Katie Browne" -> "Crystal Bozak"
+"Kameka Smith" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=80"];
+"Matthew FitzGerald" -> "Kameka Smith"
+"Ilana Melcher" -> "Kameka Smith"
+"Kyra Sacco" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=81"];
+"Joseph Butler" -> "Kyra Sacco"
+"Robbyn Rozelle" -> "Kyra Sacco"
+"Samuel Behar" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=82"];
+"Ryan Underwood" -> "Samuel Behar"
+"Lori Brede" -> "Samuel Behar"
+"Patrick Doerr" -> "Sarah Maltese"
+"Deanna Jagow" -> "Sarah Maltese"
+"David Bronson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=84"];
+"Kristin Alongi-Hutchins" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=87"];
+"Tony Sacco" -> "David Bronson"
+"Kristin Alongi-Hutchins" -> "David Bronson"
+"Cameron Brown" -> "Kristopher Lininger"
+"Kameka Smith" -> "Kristopher Lininger"
+"Rakan Abu-Rahma" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=852"];
+"Christine Coyne" -> "Rakan Abu-Rahma"
+"Jennifer Berry" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=270"];
+"Jennifer Berry" -> "Janean Angeles"
+"Penny Lewis" -> "Kristin Alongi-Hutchins"
+"Melissa Bebak" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=88"];
+"Greg Moody" -> "Melissa Bebak"
+"Sarah Maltese" -> "Melissa Bebak"
+"Scott Wright" -> "Jennifer Brandon"
+"Japheth Cleaver" -> "Jennifer Brandon"
+"Samuel Behar" -> "Robin Ellison"
+"Kyra Sacco" -> "Robin Ellison"
+"Teresa Simms" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=91"];
+"Joseph Butler" -> "Teresa Simms"
+"Janay Rabe" -> "Teresa Simms"
+"Robert Schmidtke" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=188"];
+"Jean Newman" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=166"];
+"Robert Schmidtke" -> "John FitzGibbon"
+"Jean Newman" -> "John FitzGibbon"
+"Brittany DePew" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=928"];
+"Elizabeth Larios" -> "Brittany DePew"
+"Kathleen Halberg" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=929"];
+"Ashley Rehart" -> "Kathleen Halberg"
+"Terrance Hirsch" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=96"];
+"J. Angeles" -> "Terrance Hirsch"
+"Susan Colwell" -> "Terrance Hirsch"
+"Monique Arellano" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=972"];
+"Ashley Presley" -> "Monique Arellano"
+"Anthony Henderson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=973"];
+"Jennifer Cooley" -> "Anthony Henderson"
+"Amethyst Tagle" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=974"];
+"Cate Threlkeld" -> "Amethyst Tagle"
+"Mallory Williams" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=975"];
+"Lisa Fleck" -> "Mallory Williams"
+}
+ dot-examples/switch.dot view
@@ -0,0 +1,60 @@+digraph G {+	graph [center rankdir=LR bgcolor="#808080"]+	edge [dir=none]+	node [width=0.3 height=0.3 label=""]+	{ node [shape=circle style=invis]+		1 2 3 4 5 6 7 8  10 20 30 40 50 60 70 80+	}+	{ node [shape=circle]+		a b c d e f g h  i j k l m n o p  q r s t u v w x+	}+	{ node [shape=diamond]+		A B C D E F G H  I J K L M N O P  Q R S T U V W X+	}+	1 -> a -> {A B} [color="#0000ff"]+	2 -> b -> {B A} [color="#ff0000"]+	3 -> c -> {C D} [color="#ffff00"]+	4 -> d -> {D C} [color="#00ff00"]+	5 -> e -> {E F} [color="#000000"]+	6 -> f -> {F E} [color="#00ffff"]+	7 -> g -> {G H} [color="#ffffff"]+	8 -> h -> {H G} [color="#ff00ff"]+	{ edge [color="#ff0000:#0000ff"]+		A -> i -> {I K}+		B -> j -> {J L}+	}+	{ edge [color="#00ff00:#ffff00"]+		C -> k -> {K I}+		D -> l -> {L J}+	}+	{ edge [color="#00ffff:#000000"]+		E -> m -> {M O}+		F -> n -> {N P}+	}+	{ edge [color="#ff00ff:#ffffff"]+		G -> o -> {O M}+		H -> p -> {P N}+	}+	{ edge [color="#00ff00:#ffff00:#ff0000:#0000ff"]+		I -> q -> {Q U}+		J -> r -> {R V}+		K -> s -> {S W}+		L -> t -> {T X}+	}+	{ edge [color="#ff00ff:#ffffff:#00ffff:#000000"]+		M -> u -> {U Q}+		N -> v -> {V R}+		O -> w -> {W S}+		P -> x -> {X T}+	}+	{ edge [color="#ff00ff:#ffffff:#00ffff:#000000:#00ff00:#ffff00:#ff0000:#0000ff"]+		Q -> 10+		R -> 20+		S -> 30+		T -> 40+		U -> 50+		V -> 60+		W -> 70+		X -> 80+	}+}
+ dot-examples/unix.dot view
@@ -0,0 +1,55 @@+/* courtesy Ian Darwin and Geoff Collyer, Softquad Inc. */+digraph unix {+	size="6,6";+	node [color=lightblue2, style=filled];+	"5th Edition" -> "6th Edition";+	"5th Edition" -> "PWB 1.0";+	"6th Edition" -> "LSX";+	"6th Edition" -> "1 BSD";+	"6th Edition" -> "Mini Unix";+	"6th Edition" -> "Wollongong";+	"6th Edition" -> "Interdata";+	"Interdata" -> "Unix/TS 3.0";+	"Interdata" -> "PWB 2.0";+	"Interdata" -> "7th Edition";+	"7th Edition" -> "8th Edition";+	"7th Edition" -> "32V";+	"7th Edition" -> "V7M";+	"7th Edition" -> "Ultrix-11";+	"7th Edition" -> "Xenix";+	"7th Edition" -> "UniPlus+";+	"V7M" -> "Ultrix-11";+	"8th Edition" -> "9th Edition";+	"1 BSD" -> "2 BSD";+	"2 BSD" -> "2.8 BSD";+	"2.8 BSD" -> "Ultrix-11";+	"2.8 BSD" -> "2.9 BSD";+	"32V" -> "3 BSD";+	"3 BSD" -> "4 BSD";+	"4 BSD" -> "4.1 BSD";+	"4.1 BSD" -> "4.2 BSD";+	"4.1 BSD" -> "2.8 BSD";+	"4.1 BSD" -> "8th Edition";+	"4.2 BSD" -> "4.3 BSD";+	"4.2 BSD" -> "Ultrix-32";+	"PWB 1.0" -> "PWB 1.2";+	"PWB 1.0" -> "USG 1.0";+	"PWB 1.2" -> "PWB 2.0";+	"USG 1.0" -> "CB Unix 1";+	"USG 1.0" -> "USG 2.0";+	"CB Unix 1" -> "CB Unix 2";+	"CB Unix 2" -> "CB Unix 3";+	"CB Unix 3" -> "Unix/TS++";+	"CB Unix 3" -> "PDP-11 Sys V";+	"USG 2.0" -> "USG 3.0";+	"USG 3.0" -> "Unix/TS 3.0";+	"PWB 2.0" -> "Unix/TS 3.0";+	"Unix/TS 1.0" -> "Unix/TS 3.0";+	"Unix/TS 3.0" -> "TS 4.0";+	"Unix/TS++" -> "TS 4.0";+	"CB Unix 3" -> "TS 4.0";+	"TS 4.0" -> "System V.0";+	"System V.0" -> "System V.2";+	"System V.2" -> "System V.3";+}+
+ dot-examples/world.dot view
@@ -0,0 +1,67 @@+digraph world {+size="7,7";+	{rank=same; S8 S24 S1 S35 S30;}+	{rank=same; T8 T24 T1 T35 T30;}+	{rank=same; 43 37 36 10 2;}+	{rank=same; 25 9 38 40 13 17 12 18;}+	{rank=same; 26 42 11 3 33 19 39 14 16;}+	{rank=same; 4 31 34 21 41 28 20;}+	{rank=same; 27 5 22 32 29 15;}+	{rank=same; 6 23;}+	{rank=same; 7;}++	S8 -> 9;+	S24 -> 25;+	S24 -> 27;+	S1 -> 2;+	S1 -> 10;+	S35 -> 43;+	S35 -> 36;+	S30 -> 31;+	S30 -> 33;+	9 -> 42;+	9 -> T1;+	25 -> T1;+	25 -> 26;+	27 -> T24;+	2 -> {3 ; 16 ; 17 ; T1 ; 18}+	10 -> { 11 ; 14 ; T1 ; 13; 12;}+	31 -> T1;+	31 -> 32;+	33 -> T30;+	33 -> 34;+	42 -> 4;+	26 -> 4;+	3 -> 4;+	16 -> 15;+	17 -> 19;+	18 -> 29;+	11 -> 4;+	14 -> 15;+	37 -> {39 ; 41 ; 38 ; 40;}+	13 -> 19;+	12 -> 29;+	43 -> 38;+	43 -> 40;+	36 -> 19;+	32 -> 23;+	34 -> 29;+	39 -> 15;+	41 -> 29;+	38 -> 4;+	40 -> 19;+	4 -> 5;+	19 -> {21 ; 20 ; 28;}+	5 -> {6 ; T35 ; 23;}+	21 -> 22;+	20 -> 15;+	28 -> 29;+	6 -> 7;+	15 -> T1;+	22 -> T35;+	22 -> 23;+	29 -> T30;+	7 -> T8;+	23 -> T24;+	23 -> T1;+}
+ src/Graphics/XDot/Parser.hs view
@@ -0,0 +1,261 @@+{-# LANGUAGE OverloadedStrings #-}++{- |+   Module      : Graphics.XDot.Parser+   Copyright   : (c) Dennis Felsing+   License     : 3-Clause BSD-style+   Maintainer  : dennis@felsin9.de++   After an xdot file has been opened using GraphViz, its drawing operations+   can be parsed using this module.++   > xDotText <- L.readFile "example.xdot"+   > let xDotGraph = parseDotGraph xDotText :: G.DotGraph String+   > let operations = getOperations xDotGraph++   xdot files can be created using the dot binary from the Graphviz package:++   > $ cat example.dot+   > digraph {+   >     0 [label=""];+   >     1 [label=":"];+   >     0 -> 1 [label="[1..]"];+   > }+   > $ dot -Txdot example.dot > example.xdot++   Or you can skip saving an xdot file and use a dot file directly:++   > $ dotText <- L.readFile "example.dot"+   > $ let dotGraph = parseDotGraph dotText :: G.DotGraph String+   > $ xDotText <- graphvizWithHandle Dot dotGraph XDot T.hGetContents+   > $ let xDotGraph = parseDotGraph $ B.fromChunks [xDotText] :: G.DotGraph String+   > $ getOperations xDotGraph+   > [ (Nothing,Color {rgba = (1.0,1.0,1.0,1.0), filled = False})+   > , (Nothing,Color {rgba = (1.0,1.0,1.0,1.0), filled = True})+   > , (Nothing,Polygon {points = [(0.0,-1.0),(0.0,130.0),(55.0,130.0),(55.0,-1.0)], filled = True})+   > , (Just "0",Color {rgba = (0.0,0.0,0.0,1.0), filled = False})+   > , (Just "0",Ellipse {xy = (27.0,112.0), w = 27.0, h = 18.0, filled = False})+   > , (Just "1",Color {rgba = (0.0,0.0,0.0,1.0), filled = False})+   > , (Just "1",Ellipse {xy = (27.0,19.0), w = 27.0, h = 19.0, filled = False})+   > , (Just "1",Font {size = 14.0, name = "Times-Roman"})+   > , (Just "1",Color {rgba = (0.0,0.0,0.0,1.0), filled = False})+   > , (Just "1",Text {baseline = (27.0,15.0), alignment = CenterAlign, width = 4.0, text = ":"})+   > , (Nothing,Color {rgba = (0.0,0.0,0.0,1.0), filled = False})+   > , (Nothing,BSpline {points = [(27.0,94.0),(27.0,81.0),(27.0,63.0),(27.0,48.0)], filled = False})+   > , (Nothing,Style {style = "solid"})+   > , (Nothing,Color {rgba = (0.0,0.0,0.0,1.0), filled = False})+   > , (Nothing,Color {rgba = (0.0,0.0,0.0,1.0), filled = True})+   > , (Nothing,Polygon {points = [(31.0,48.0),(27.0,38.0),(24.0,48.0)], filled = True})+   > , (Nothing,Font {size = 14.0, name = "Times-Roman"})+   > , (Nothing,Color {rgba = (0.0,0.0,0.0,1.0), filled = False})+   > , (Nothing,Text {baseline = (39.0,62.0), alignment = CenterAlign, width = 24.0, text = "[1..]"})+   > ]++   The following imports are needed for this:++   > import Data.GraphViz+   > import Data.Text.IO as T+   > import qualified Data.Text.Lazy as B+   > import qualified Data.Text.Lazy.IO as L+   > import qualified Data.GraphViz.Types.Generalised as G+ -}+module Graphics.XDot.Parser (+  getOperations,+  getSize+)+where++import Control.Monad+import Data.Maybe+import Data.Char+import Data.Ratio++import qualified Data.Foldable as F+import qualified Data.Text.Lazy as B+import qualified Data.Text.Lazy.Read as B+import qualified Text.ParserCombinators.Poly.StateText as P++import Data.GraphViz.Types hiding (parse, attrs)+import Data.GraphViz.Parsing hiding (parse)+import qualified Data.GraphViz.Attributes.Complete as A+import qualified Data.GraphViz.Types.Generalised as G++import Graphics.XDot.Types hiding (w, h, filled, baseline, width, alignment, size, text, xy, name)++-- | Extract all operations of an xdot graph and connect them to the node they+--   belong to, if any.+getOperations :: G.DotGraph a -> [(Maybe a, Operation)]+getOperations (G.DotGraph _ _ _ graphStatements) = F.foldr handle [] graphStatements+  where handle (G.GA (GraphAttrs attrs)) l = zip (repeat Nothing) (handleInternal attrs) ++ l+        handle (G.DN (DotNode ident attrs)) l = zip (repeat $ Just ident) (handleInternal attrs) ++ l+        -- TODO: Add edge identifiers+        handle (G.DE (DotEdge _ _ attrs)) l = zip (repeat Nothing) (handleInternal attrs) ++ l+        handle (G.SG (G.DotSG _ _ statements)) l = F.foldr handle [] statements ++ l+        handle _ l = l++        handleInternal attrs = foldr handleFirst [] attrs ++ foldr handleSecond [] attrs++        handleFirst (A.UnknownAttribute "_draw_" r) l = parse r ++ l+        handleFirst _ l = l++        handleSecond (A.UnknownAttribute "_ldraw_" r) l = parse r ++ l+        handleSecond (A.UnknownAttribute "_hdraw_" r) l = parse r ++ l+        handleSecond (A.UnknownAttribute "_tdraw_" r) l = parse r ++ l+        handleSecond (A.UnknownAttribute "_hldraw_" r) l = parse r ++ l+        handleSecond (A.UnknownAttribute "_tlldraw_" r) l = parse r ++ l+        handleSecond _ l = l++-- | Extract the dimensions of the graph when drawn.+getSize :: G.DotGraph a -> Rectangle+getSize (G.DotGraph _ _ _ graphStatements) = F.foldr handle (0,0,0,0) graphStatements+  where handle (G.GA (GraphAttrs attrs)) l = if l /= (0,0,0,0) then l else r+          where r = foldr handleInternal (0,0,0,0) attrs+        handle _ l = l++        handleInternal (A.BoundingBox (A.Rect (A.Point x y _ _) (A.Point w h _ _))) r = if r /= (0,0,0,0) then r else (x,y,w,h)+        handleInternal _ l = l++parse :: B.Text -> [Operation]+parse = Data.GraphViz.Parsing.runParser' $ P.many $ do+  t <- P.next+  character ' '++  case t of+    'E' -> parseEllipse True+    'e' -> parseEllipse False+    'P' -> parsePolygon True+    'p' -> parsePolygon False+    'L' -> parsePolyline+    'B' -> parseBSpline False+    'b' -> parseBSpline True+    'T' -> parseText+    'C' -> parseColor True+    'c' -> parseColor False+    'F' -> parseFont+    'S' -> parseStyle+    'I' -> parseImage+    _   -> fail "Unknown Operation"++  where+    parseEllipse filled = do+      p <- parsePoint+      (w,h) <- parsePoint+      return $ Ellipse p w h filled++    parsePolygon filled = do+      xs <- parsePoints+      return $ Polygon xs filled++    parsePolyline = liftM Polyline parsePoints++    parseBSpline filled = do+      xs <- parsePoints+      return $ BSpline xs filled++    parseText = do+      baseline <- parsePoint+      j <- parseInt'+      let alignment = case j of+                        -1 -> LeftAlign+                        0  -> CenterAlign+                        1  -> RightAlign+                        _  -> error "Unexpected alignment"+      character ' '+      width <- parseFloat'+      character ' '+      text <- parseString+      return $ Text baseline alignment width text++    parseFont = do+      size <- parseFloat'+      character ' '+      name <- parseString+      return $ Font size name++    parseStyle = liftM Style parseString++    parseImage = do+      xy <- parsePoint+      (w,h) <- parsePoint+      name <- parseString+      return $ Image xy w h name++    parseString = do+      n <- parseInt+      character ' '+      character '-'+      text <- replicateM (fromInteger n) P.next+      character ' '+      return text++    parsePoints = do+      n <- parseInt+      character ' '+      replicateM (fromInteger n) parsePoint++    parsePoint = do+      x <- parseFloat'+      character ' '+      y <- parseFloat'+      character ' '+      return (x,y)++    parseColor filled = do -- TODO: Not complete+      _ <- parseInt+      character ' '+      character '-'+      character '#'+      r <- parseHex+      g <- parseHex+      b <- parseHex+      a <- parseHex+      character ' '+      return $ Color (r,g,b,a) filled+     where parseHex = liftM hexToFloat $ replicateM 2 P.next+           hexToFloat s = foldl (\x y -> 16 * x + fromIntegral (digitToInt y)) 0 s / 255++    -- The following functions are taken from GraphViz/Parsing.hs, as they are not+    -- exported.++    parseSigned p = (character '-' >> liftM negate p)+                    `P.onFail`+                    p++    parseInt = do cs <- P.many1Satisfy isDigit+                  case B.decimal cs of+                    Right (n,"")  -> return n+                    Right (_,txt) -> fail $ "Trailing digits not parsed as Integral: " ++ B.unpack txt+                    Left err      -> fail $ "Could not read Integral: " ++ err+               `P.adjustErr` ("Expected one or more digits\n\t"++)++    parseInt' = parseSigned parseInt++    parseFloat = do ds   <- P.manySatisfy isDigit+                    frac <- P.optional+                            $ do character '.'+                                 P.manySatisfy isDigit+                    when (B.null ds && noDec frac)+                      (fail "No actual digits in floating point number!")+                    expn  <- P.optional parseExp+                    when (isNothing frac && isNothing expn)+                      (fail "This is an integer, not a floating point number!")+                    let frac' = fromMaybe "" frac+                        expn' = fromMaybe 0 expn+                    ( return . fromRational . (* (10^^(expn' - fromIntegral (B.length frac'))))+                      . (%1) . Data.GraphViz.Parsing.runParser' parseInt) (ds `B.append` frac')+                 `P.onFail`+                 fail "Expected a floating point number"+      where+        parseExp = do character 'e'+                      (character '+' >> parseInt)+                       `P.onFail`+                       parseInt'+        noDec = maybe True B.null++    parseFloat' = parseSigned ( parseFloat+                                `onFail`+                                liftM fI parseInt+                              )+      where+        fI :: Integer -> Double+        fI = fromIntegral
+ src/Graphics/XDot/Types.hs view
@@ -0,0 +1,41 @@+{- |+   Module      : Graphics.XDot.Types+   Copyright   : (c) Dennis Felsing+   License     : 3-Clause BSD-style+   Maintainer  : dennis@felsin9.de++   This module contains various types used to represent xdot parameters.+ -}+module Graphics.XDot.Types (+  Point,+  Rectangle,+  Alignment(..),+  Operation(..)+  )+  where++-- | A simple point, consisting of an x and y position.+type Point = (Double, Double)++-- | A rectangle, x and y position, width and height.+type Rectangle = (Double, Double, Double, Double)++-- | Alignment of text.+data Alignment = LeftAlign+               | CenterAlign+               | RightAlign+               deriving Show++-- | Drawing operations supported by xdot. See+--   <http://www.graphviz.org/doc/info/output.html#d:xdot> for more information++data Operation = Ellipse { xy :: Point, w :: Double, h :: Double, filled :: Bool }+               | Polygon { points :: [Point], filled :: Bool }+               | Polyline { points :: [Point] }+               | BSpline { points :: [Point], filled :: Bool }+               | Text { baseline :: Point, alignment :: Alignment, width :: Double, text :: String }+               | Color { rgba :: (Double, Double, Double, Double), filled :: Bool }+               | Font { size :: Double, name :: String }+               | Style { style :: String } -- TODO: Add type+               | Image { xy :: Point, w :: Double, h :: Double, name :: String }+               deriving Show
+ src/Graphics/XDot/Viewer.hs view
@@ -0,0 +1,206 @@+{- |+   Module      : Graphics.XDot.Viewer+   Copyright   : (c) Dennis Felsing+   License     : 3-Clause BSD-style+   Maintainer  : dennis@felsin9.de++   This module draws the operations of an xdot graph using Cairo and Pango on a+   Gtk canvas.+ -}+module Graphics.XDot.Viewer (+  drawAll+)+where++import Data.Maybe++import Graphics.XDot.Types hiding (w, h, filled, alignment, text, name, size)++import Graphics.UI.Gtk hiding (Color, Rectangle, descent)+import Graphics.Rendering.Cairo++import Control.Monad.State hiding (State)+import qualified Control.Monad.State as MS++type RGBA = (Double, Double, Double, Double)++data DState = DState+  { fontName    :: String+  , fontSize    :: Double+  , lineWidth   :: Double+  , lineStyle   :: [Double]+  , filledColor :: RGBA+  , strokeColor :: RGBA+  }+type DrawState a = MS.StateT DState Render a++-- | Draw an xdot graph, possibly highlighting a node.+drawAll :: Eq t => +     Maybe t -- ^ id of the node to highlight+  -> Rectangle -- ^ dimensions of the graph, as returned by 'Graphics.XDot.Parser.getSize'+  -> [(Maybe t, Operation)] -- ^ operations, as returned by 'Graphics.XDot.Parser.getOperations'+  -> Render [(t, Rectangle)] -- ^ dimensions of the rendered nodes on the screen+drawAll hover (_,_,sw,sh) ops = do+  let scalex = 1+      scaley = -1+      offsetx = -0.5 * sw+      offsety = 0.5 * sh+  save+  translate offsetx offsety+  scale scalex scaley++  boundingBoxes <- evalStateT (mapM (draw hover) ops) $ DState "" 1 1 [] (1,1,1,1) (0,0,0,1)++  restore+  return+    $ map (\(o, (x,y,w,h)) -> (o, (x*scalex+offsetx,y*scaley+offsety,w,h)))+    $ concat boundingBoxes++stylizedDraw :: Eq t => Bool -> Maybe t -> Maybe t -> Render a -> DrawState ()+stylizedDraw filled mn hover renderOps = do+  (r,g,b,a) <- getCorrectColor filled+  lWidth <- gets lineWidth+  lStyle <- gets lineStyle++  lift $ do+    if isJust mn && mn == hover+      then setSourceRGBA 1 0 0 1+      else setSourceRGBA r g b a+    setLineWidth lWidth+    setDash lStyle 0++    save+    renderOps+    restore++    if filled then fillPreserve >> fill else stroke++draw :: Eq t => Maybe t -> (Maybe t, Operation) -> DrawState [(t, Rectangle)]+draw hover (mn, Ellipse (x,y) w h filled) = do+  stylizedDraw filled hover mn $ do+    translate x y+    scale w h+    moveTo 1 0+    arc 0 0 1 0 (2 * pi)++  return $ case mn of+    Just node -> [(node, (x - w, y + h, 2 * w, 2 * h))]+    Nothing   -> []++draw hover (mn, Polygon ((x,y):xys) filled) = do+  stylizedDraw filled hover mn $ do+    moveTo x y+    mapM_ (uncurry lineTo) xys+    closePath++  let xs = x : map fst xys+  let ys = y : map snd xys++  return $ case mn of+    Just node -> [(node, (minimum xs, maximum ys, maximum xs - minimum xs, maximum ys - minimum ys))]+    Nothing   -> []++draw _ (_, Polygon [] _) = return []++draw _ (_, Polyline _) = return []++draw hover (mn, BSpline ((x,y):xys) filled) = do+  stylizedDraw filled hover mn $ do+    moveTo x y+    drawBezier xys++  return []++  where drawBezier ((x1,y1):(x2,y2):(x3,y3):xys2) = do+          curveTo x1 y1 x2 y2 x3 y3+          drawBezier xys2+        drawBezier _ = return ()+++draw _ (_, BSpline [] _) = return []++draw _ (_, Text (x,y) alignment w text) = do+  (r,g,b,a) <- getCorrectColor False -- stroke, not filled+  fontName' <- gets fontName+  fontSize' <- gets fontSize++  lift $ do+    setSourceRGBA r g b a++    layout <- createLayout "text"+    context <- liftIO $ layoutGetContext layout++    fo <- liftIO $ cairoContextGetFontOptions context++    fontOptionsSetAntialias fo AntialiasDefault+    fontOptionsSetHintStyle fo HintStyleNone+    fontOptionsSetHintMetrics fo HintMetricsOff+    liftIO $ cairoContextSetFontOptions context fo++    liftIO $ layoutContextChanged layout++    -- This does not work with "Times Roman", but it works with a font that is+    -- installed on the system+    --font <- liftIO fontDescriptionNew+    --liftIO $ fontDescriptionSetFamily font "Nimbus Roman No9 L, Regular"+    --liftIO $ fontDescriptionSetFamily font "Times Roman"+    --liftIO $ fontDescriptionSetSize font fontSize'++    -- Only fontDescriptionFromString works as expected, choosing a similar+    -- alternative font when the selected one is not available+    font <- liftIO $ fontDescriptionFromString fontName'+    liftIO $ fontDescriptionSetSize font fontSize'+    liftIO $ layoutSetFontDescription layout (Just font)++    liftIO $ layoutSetText layout text++    (_, PangoRectangle _ _ w2 h2) <- liftIO $ layoutGetExtents layout++    let (f, w3, h3, descent) = if w2 > w+          then (w / w2, w,  h2 * w / w2, 4 * w / w2)+          else (1,      w2, h2,          4)++    let x3 = case alignment of+               LeftAlign   -> x+               CenterAlign -> x - 0.5 * w3+               RightAlign  -> x -       w3+        y3 = y + h3 - descent++    moveTo x3 y3+    save+    scale f (-f)++    showLayout layout++    restore++    return []++draw _ (_, Color color filled) = do+  modify (\s -> if filled+    then s{filledColor = color}+    else s{strokeColor = color})+  return []++draw _ (_, Font size name) = do+  modify (\s -> s{fontName = fixedName, fontSize = size})+  return []++  -- Pango does not like "Times-Roman", but works with "Times Roman".+  -- Graphviz handles this in plugin/pango/gvtextlayout_pango.c+  where fixedName = map fixName name+        fixName '-' = ' '+        fixName x   = x++draw _ (_, Style x) = do+  case x of -- TODO: Some styles missing+    "solid"  -> modify (\s -> s{lineStyle = []}) -- always on+    "dashed" -> modify (\s -> s{lineStyle = [6,6]}) -- 6 pts on, 6 pts off+    "dotted" -> modify (\s -> s{lineStyle = [2,4]}) -- 2 pts on, 4 pts off+    _ -> return ()+  return []++draw _ (_, Image{}) = return [] -- TODO++getCorrectColor :: Bool -> DrawState RGBA+getCorrectColor filled = gets $ if filled then filledColor else strokeColor
+ xdot.cabal view
@@ -0,0 +1,33 @@+name:               xdot+version:            0.1+license:            BSD3+license-file:       LICENSE+category:           Graphs, Graphics+cabal-version:      >= 1.10+build-type:         Simple+author:             Dennis Felsing <dennis@felsin9.de>+maintainer:         Dennis Felsing <dennis@felsin9.de>+copyright:          Dennis Felsing 2012+synopsis:           Parse Graphviz xdot files and interactively view them using GTK and Cairo+description:        Parse Graphviz xdot files and interactively view them using+                    GTK and Cairo.+                    .+                    Currently not all xdot features are supported and only+                    nodes can be highlighted by hovering them and clicked.+                    .+                    For an example of using this library try the accompanying+                    @Demo.hs@ with the dot-files in @dot-examples/@.++Extra-source-files: Demo.hs, dot-examples/*.dot+Library+  Exposed-modules: Graphics.XDot.Parser Graphics.XDot.Viewer Graphics.XDot.Types+  Default-Language: Haskell2010+  Build-depends: base == 4.5.*,+                 mtl,+                 cairo,+                 gtk,+                 graphviz,+                 text,+                 polyparse+  Hs-source-dirs: src/+  Ghc-options: -Wall -fno-warn-unused-do-bind