
// GraphvizTest.java
// Andrew Davison, ad@coe.psu.ac.th, Nov. 2022

/* GraphViz (https://graphviz.org/) is visualization software 
   with an emphasis on drawing graphs. 
   
   Examples:
   * https://graphviz.org/gallery/
   * https://graphs.grevian.org/example
   * https://renenyffenegger.ch/notes/tools/Graphviz/examples/index

   The drawGraph() function at the end of the file hides some of the
   details of preparing the GraphViz commands for zt-exec.
   It also passes the renderd image to my ImageViewer class so 
   the generated graph can be seen.

    Usage:
      > compile GraphvizTest.java
      > run GraphvizTest
*/

import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.image.*;

import org.zeroturnaround.exec.*;



public class GraphvizTest
{

  public static void main(String[] args)
  {
    if ( ZUtils.cmdExit("dot", "-V") == 0)
      System.out.println("Graphviz installed");
    else {
      System.out.println("Graphviz not installed");
      return;
    }

    // Uncomment the String array declaration you want to
    // try out ...

    String[] dotLines = { "digraph {",
                              "layout=neato",
                              "a -> b",
                              "b -> c",
                              "c -> d",
                              "d -> a",
                          "}"   };

/*
    String[] dotLines = { 
       "graph  {",
	      "fontname=\"Helvetica,Arial,sans-serif\"",
	      "node [fontname=\"Helvetica,Arial,sans-serif\"]",
	      "edge [fontname=\"Helvetica,Arial,sans-serif\"]",
	      "layout=neato",
          "zombie -- kernel",  
	      "run -- intr",  "run -- kernel",
          "intr -- runbl",
	      "runbl -- run",
	      "kernel -- runmem", "kernel -- sleep",  
	      "sleep -- swap",  "sleep -- runmem",
	      "swap -- runswap",
	      "runswap -- runmem", "runswap -- new", 
	      "new -- runmem",
       "}"
    };
*/

/*
    String[] dotLines = { 
        "graph {",
           "fontname=\"Helvetica,Arial,sans-serif\"",
           "node [fontname=\"Helvetica,Arial,sans-serif\"]",
           "edge [fontname=\"Helvetica,Arial,sans-serif\"]",
           "layout=fdp",
           "subgraph clusterA {", 
              "a -- b",
              "subgraph clusterC {",
                "C -- D",
             "}",
           "}",
           "subgraph clusterB {",
             "d -- f",
           "}",
           "d -- D",
           "e -- clusterB",
           "clusterC -- clusterB",
       "}"
    };
*/
/*
    String[] dotLines = { 
             "digraph {",
                "node [shape=record];",
                "{ rank=same rA sA tA }",
                "{ rank=same uB vB wB }",
                "rA -> sA",
                "sA -> vB",
                "t  -> rA",
                "uB -> vB",
                "wB -> u",
                "wB -> tA",
              "}",
    };
*/

    String pngFnm = drawGraph(dotLines);
    // load the created image to check its size
    if (pngFnm != null) {
      BufferedImage im = ZUtils.loadImage(pngFnm);
      System.out.println("Image dimensions: " + im.getWidth() +
                                " x " + im.getHeight());
    }
  }  // end of main()


  // -------------------- utils -----------------------


  private static String drawGraph(String[] dotLines)
  /* The GraphViz commands are saved to a temporary file,
     which is passed to GraphViz's dot command for rendering.
     A temporary PNG file is also created, and the image is
     saved there. 

     The filename is passed to my support class, ImageViewer,
     which loads the image into a Java window. The filename
     is also returned.
  */
  {
    String dotFnm = ZUtils.writeToTemp(dotLines);
    String pngFnm = ZUtils.makeTemp(".png");
    
    if (ZUtils.cmdExit("dot", "-Tpng", dotFnm, "-o", pngFnm) == 0) {
      System.out.println("Displaying graph...");
      ImageViewer.view(pngFnm);
      return pngFnm;
    }
    return null;
  }  // end of drawGraph


}  // end of GraphvizTest class