Chad Baldwin
Chad Baldwin

Reputation: 2602

Set pre-defined node styles?

I've been googling around for the last 15 minutes trying to find an answer to this. But I can't seem to figure it out.

I was tasked with building some small flowcharts for some applications I've developed at work. They don't need anything fancy because they are going to convert it into their preferred format in vizio. They even said we could do it pen and paper. So I figured I would play around with graphviz/dot.

They have 6 pre-defined shapes/colors that they like to use, so I figured I would use them. I've already built them all in dot...but if I plan to re-use them many times, I'd like to find a way to save them as a sort of template.

Is that possible?

For example...These are the predefined shapes.

digraph G {
    node [color="#4271C6"]

    process [
        shape=Mrecord,
        style=filled, fillcolor="#E1F4FF",
        label="{1. Process\l | Description}"];

    subprocess [
        shape=record,
        style=filled, color="#FFFFFF", fillcolor="#A5A5A5",
        label="| Sub-Process |"];

    database [
        shape=cylinder, color="#18589A",
        label="Database"];

    inputoutput [
        shape=polygon,
        style=filled, fontcolor=white,
        fixedsize=true, skew=0.3, margin=0,
        width=2, label="Input / Output"];

    file [
        shape=folder,
        label="File"];

    external [
        shape=box3d,
        label="External entity"];
}

Nodes produced from above code

Upvotes: 7

Views: 1681

Answers (3)

Saaru Lindestøkke
Saaru Lindestøkke

Reputation: 2544

No affiliation, but the Excel to Graphviz application can create re-usable styles as can be seen in this screenshot:

enter image description here

Upvotes: 0

Chad Baldwin
Chad Baldwin

Reputation: 2602

Okay, so I figured it out. I didn't realize you could do this...but apparently you can break up a node definition into multiple parts...so this is what I came up with, which solves my problem...

I have a "Styles" section that goes at the top. Here I can define each node style. I use comments as a way of naming them. And I don't need to copy paste, because I can just define multiple nodes as a comma separated list.

I also found that you can put them into subgraphs as well, like subgraph style_file {...}. But it seemed simpler to just use a comment as a way to name the style.

digraph G {
    newrank=true;

    ///////////////////////////////////////////////////////////
    // Styles
    ///////////////////////////////////////////////////////////
        node [color="#4271C6"];
        edge [color="#4271C6"];

        //process
            createfile, uploadfile
            [shape=Mrecord, style=filled, fillcolor="#E1F4FF"];
        //subprocess
            exportfile, wait
            [shape=record, style=filled, color="#FFFFFF", fillcolor="#A5A5A5"];
        //external
            ftp
            [shape=box3d];
        //datastore
            database
            [shape=cylinder, color="#18589A"];
        //io
            exportproc
            [shape=polygon, style=filled, fontcolor=white, margin=0, width=3.1, fixedsize=true, skew=0.3];
        //file
            workfile
            [shape=folder];

    ///////////////////////////////////////////////////////////
    // Clusters
    ///////////////////////////////////////////////////////////
        subgraph cluster_0 {
            createfile  [label="{1. Process\l | Create file}"];
            exportfile  [label="|Export Data\nfrom DB|"];
            database    [label="Database"];
            exportproc  [label="Export Data"];
            workfile    [label="Generated file\n(Archived on server)"];
        }

        subgraph cluster_1 {
            uploadfile  [label="{2. Process\l | Upload file}"];
            ftp         [label="FTP Server"];
            wait        [label="|Wait for\nresponse file|"];
        }

    ///////////////////////////////////////////////////////////
    // Relationships
    ///////////////////////////////////////////////////////////
        {
            rank=same;
            createfile;
            uploadfile;
        }

    ///////////////////////////////////////////////////////////
    // Relationships
    ///////////////////////////////////////////////////////////
        # cluster_0
        createfile -> exportfile;
        exportfile -> database;
        database   -> exportproc;
        exportproc -> workfile [style=dashed];

        workfile -> uploadfile;

        # cluster_1
        uploadfile -> ftp [style=dashed];
        ftp -> wait;
}

Which produces this:

enter image description here

Upvotes: 6

sroush
sroush

Reputation: 6763

unfortunately there is no way to define macros or objects and reuse - especially across multiple graphs. However there are ways using other tools. Some folks use m4 (the macro language) or cpp (the C pre-processor) Both work, but there are potential OS issues. Python, awk, ... would also work.
Here is a gvpr program (gvpr is part of the Graphviz package) that also does what you want (I think):

 digraph pre{
  a [_type=process label="{1. Process\l | Something}"]
  b [_type=process label="{2. Process\l | Something else}"]
  c [_type=subprocess label="do it"]
  d [_type=database label="lots of data"]
  e [_type=database label="a bit of data"]
  f [_type=inputoutput label="inOut"]
  g [_type=file label="nail file"]
  h [_type=external label="outside"]  

 a->b->c->d->e->f->g->h
}

The gvpr program:

BEG_G{
  $G.newrank="true";
}
N{
  $.color="#4271C6";  // default
}
N[_type=="process"]{
  $.shape="Mrecord";
  $.style="filled";
  $.fillcolor="#E1F4FF";
  // maybe redo $.label
}
N[_type=="subprocess"]{
  $.shape="record";
  $.style="filled";
  $.color="#FFFFFF";
  $.fillcolor="#A5A5A5";
  $.label=sprintf("|%s|", $.label);  // embed in pipes
}
N[_type=="database"]{
  $.shape="cylinder";
  $.color="#18589A";
}
N[_type=="inputoutput"]{
  $.shape="polygon";
  $.style='filled';
  $.fontcolor="white",
  $.ixedsize="true";
  $.skew="0.3";
  $.margin="0";
  $.width="2";
}
N[_type=="file"]{
  $.shape="folder";
}
N[_type=="external"]{
  $.shape="box3d";
}

Produces:
enter image description here

There may currently be problems with gvpr on Windows, but I know the development team is working on it

Here is the command line:
gvpr -c -f predefined.gvpr predefined2.gv | dot -Tpng > predefined2.png

Upvotes: 3

Related Questions