diff src/docgen/graphutils/dotwriter.d @ 806:bcb74c9b895c

Moved out files in the trunk folder to the root.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sun, 09 Mar 2008 00:12:19 +0100
parents trunk/src/docgen/graphutils/dotwriter.d@ec8dd7b8bf0c
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/docgen/graphutils/dotwriter.d	Sun Mar 09 00:12:19 2008 +0100
@@ -0,0 +1,170 @@
+/**
+ * Author: Aziz Köksal & Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.graphutils.dotwriter;
+import docgen.graphutils.writer;
+
+import tango.io.Print: Print;
+import tango.text.convert.Layout : Layout;
+import tango.io.FilePath;
+import tango.text.Util;
+import tango.text.convert.Sprint;
+debug import tango.io.Stdout;
+
+/**
+ * Creates a graph rule file for the dot utility.
+ */
+class DotWriter : AbstractGraphWriter {
+  public:
+
+  this(GraphWriterFactory factory, PageWriter writer) {
+    super(factory, writer);
+  }
+
+  void generateDepGraph(DepGraph depGraph, OutputStream imageFile) {
+    generateImageTag(imageFile);
+    
+    auto image = generateDepImageFile(depGraph);
+    auto printer = new Print!(char)(new Layout!(char), imageFile);
+    printer(image);
+  }
+
+  protected:
+
+  char[] generateDepImageFile(DepGraph depGraph) {
+    char[] image;
+    auto sprint = new Sprint!(char);
+    
+    auto edges = depGraph.edges;
+    auto vertices = depGraph.vertices;
+
+    DepGraph.Vertex[][char[]] verticesByPckgName;
+    if (factory.options.graph.groupByFullPackageName ||
+        factory.options.graph.groupByPackageNames) {
+      foreach (mod; vertices) {
+        auto parts = mod.name.delimit(".");
+
+        if (parts.length>1) {
+          auto pkg = parts[0..$-1].join(".");
+          verticesByPckgName[pkg] ~= mod;
+        }
+      }
+    }
+
+    if (factory.options.graph.highlightCyclicVertices ||
+        factory.options.graph.highlightCyclicEdges)
+      depGraph.markCycles();
+
+    image ~= "Digraph ModuleDependencies {\n";
+
+    foreach (module_; vertices) {
+      auto nodeName = 
+        factory.options.graph.groupByPackageNames ?
+        module_.name.split(".")[$-1] :
+        module_.name;
+
+      image ~= sprint.format(
+        `  n{} [label="{}",style=filled,fillcolor={}];`\n,
+        module_.id,
+        nodeName,
+        module_.cyclic && factory.options.graph.highlightCyclicVertices ?
+          factory.options.graph.cyclicNodeColor :
+        module_.incoming.length == 0 && module_.outgoing.length == 0 ?
+          factory.options.graph.unlocatableNodeColor :
+          factory.options.graph.nodeColor
+      );
+    }
+
+    foreach (edge; edges)
+      image ~= sprint.format(
+        `  n{} -> n{}[color={}];`\n,
+        edge.outgoing.id,
+        edge.incoming.id,
+        edge.cyclic ?
+          factory.options.graph.cyclicDepColor :
+        edge.isPublic ?
+          factory.options.graph.publicDepColor ~ ",style=bold" :
+          factory.options.graph.depColor
+      );
+
+    if (factory.options.graph.groupByPackageNames)
+
+      if (!factory.options.graph.groupByFullPackageName) {
+        foreach (packageName, vertices; verticesByPckgName) {
+          auto name = packageName.split(".");
+
+          if (name.length > 1) {
+            char[] pkg;
+            foreach(part; name) {
+              pkg ~= part ~ ".";
+              image ~= sprint.format(
+                `subgraph "cluster_{0}" {{`\n`  label="{0}"`\n,
+                pkg[0..$-1],
+                pkg[0..$-1]
+              );
+            }
+            for (int i=0; i< name.length; i++) {
+              image ~= "}\n";
+            }
+          }
+        }
+      }
+      foreach (packageName, vertices; verticesByPckgName) {
+        image ~= sprint.format(
+          `  subgraph "cluster_{0}" {{`\n`  label="{0}";color=`
+          ~ factory.options.graph.clusterColor ~ `;`\n`  `,
+          packageName,
+          packageName
+        );
+
+        foreach (module_; vertices)
+          image ~= sprint.format(`n{0};`, module_.id);
+        image ~= "\n  }\n";
+      }
+
+    image ~= "}";
+
+    return image;
+  }
+        
+  void generateImageTag(OutputStream imageFile) {
+    // name of the .dot file
+    char[] fn = (cast(Object)imageFile.conduit).toString();
+    fn = FilePath(fn).file;
+
+    fn = fn[0..$-3] ~ imageFormatExts[factory.options.graph.imageFormat];
+    
+    writer.addGraphics(fn);
+  } 
+}
+
+class CachingDotWriter : DotWriter {
+  private:
+
+  CachingGraphWriterFactory factory;
+
+  public:
+
+  this(CachingGraphWriterFactory factory, PageWriter writer) {
+    super(factory, writer);
+    this.factory = factory;
+  }
+
+  override void generateDepGraph(DepGraph depGraph, OutputStream imageFile) {
+    generateImageTag(imageFile);
+
+    auto cached = factory.graphCache.getCachedGraph(depGraph, GraphFormat.Dot);
+
+    auto printer = new Print!(char)(new Layout!(char), imageFile);
+    
+    if (cached) {
+      printer(cached);
+    } else {
+      auto image = generateDepImageFile(depGraph);
+      factory.graphCache.setCachedGraph(depGraph, GraphFormat.Dot, image);
+      printer(image);
+    }
+  }
+}
+