diff --git a/data/System/GraphvizPlugin.txt b/data/System/GraphvizPlugin.txt
index 6bc003e..fa53149 100644
--- a/data/System/GraphvizPlugin.txt
+++ b/data/System/GraphvizPlugin.txt
@@ -1,4 +1,4 @@
-%META:TOPICINFO{author="ProjectContributor" comment="" date="1439247692" format="1.1" version="1"}%
+%META:TOPICINFO{author="ProjectContributor" comment="" date="1439299038" format="1.1" version="1"}%
---+!! %TOPIC%
%SHORTDESCRIPTION%
@@ -11,7 +11,7 @@ in visual interfaces for many other domains.
This plugin uses [[http://www.graphviz.org/][Graphviz's]] applications to
create an image of a directed graph. The directed graph is described using a
-simple text markup called "The _dot_ Language". This markup is written between
+simple text markup called "The DOT Language". This markup is written between
=<graphviz>= and =</graphviz>= tags or using the =%GRAPHVIZ= macro.
By default, an svg image attachment is created and displayed inline, replacing the =<graphviz>= markup.
@@ -27,18 +27,18 @@ There are two ways to specify a graph:
1 using the =<graphviz>= xml tag
2 using the =%GRAPHVIZ= Foswiki macro
-Both can be used to generate a graph inline, that is by specifying the =graphviz= code as part of the page. Below
+Both can be used to generate a graph inline, that is by specifying the DOT language as part of the page. Below
examples are mostly equivalent:
-digraph G {Hello->World}
+digraph G {Hello[fontcolor="red"]; Hello->World}
%GRAPHVIZ{
- "digraph G {Hello->World}"
+ "digraph G {Hello[fontcolor=\"red\"]; Hello->World}"
renderer="dot"
type="png"
}%
@@ -48,7 +48,7 @@ Both should render as
%IF{"context GraphvizPluginEnabled"
then="$percntGRAPHVIZ{
- \"digraph G {Hello->World}\"
+ \"digraph G {Hello[fontcolor=\"red\"]; Hello->World}\"
renderer=\"dot\"
type=\"png\"
}$percnt"
@@ -58,7 +58,7 @@ Both should render as
when installed.
The =<graphviz>= xml syntax has got the advantage of being in line with other wikis, such as dokuwiki. Also,
-the =graphviz= code does not have to escape any double-quotes (="=) as is the case using the Foswiki macro way.
+the DOT code does not have to escape any double-quotes (="=) as is the case using the Foswiki macro way.
However using a proper =%GRAPHVIZ= macro has got the advantage of being well integrated into Foswiki's Topic Markup Language.
For instance it can be properly escaped when in a [[FormattedSearch]].
@@ -66,12 +66,12 @@ For compatibility with !DirectedGraphPlugin you may use =<dot>= instead of =&
---++ Syntax
-=<graphviz [params]> ... graphviz code ... <graphviz>=
+=<graphviz [params]> ... DOT code ... <graphviz>=
-=%GRAPHVIZ{" ... graphviz code ... " [params]}%=
+=%GRAPHVIZ{" ... DOT code ... " [params]}%=
| *Parameter* | *Description* | *Default* |
-| =graphviz code= | this is the graph specified in the graph description language | |
+| =DOT code= | this is the graph specified in the graph description language | |
| =type="png|jpeg|gif|svg|svgz|pdf"= | output format | svg |
| =renderer="dot|neato|twopi|circle|fdp|sfdp|patchwork"= | rendering engine | dot |
| =topic="[web.]topic"= | specify the topic where to store the graph image | current topic |
@@ -79,11 +79,51 @@ For compatibility with !DirectedGraphPlugin you may use =<dot>= instead of =&
| =section=" ... "= | named section in =topic= that holds a graph description (only available in =%GRAPHVIZ=) | |
| =library="[web.]topic"= | specify the topic where to search for images to be used in the dot graph | =topic= |
| =inline="on|off"= | boolean flag to specify the way how to add an svg result to the html page; if =inline="on"= then an =<svg>= html tag is generated; otherwise an html =<img ... >= tag is used; note that for properly linking URLs in the =graphviz= graph you will need to switch this on | off |
-| =expand="on|off"= | boolean flag, when switched on, will expand TML macros in the graphviz code before rendering it | off |
+| =expand="on|off"= | boolean flag, when switched on, will expand TML macros in the DOT code before rendering it | off |
| =style=" ... "= | css styles to be added to the output | |
| =width=" ... "= | width of the image result | |
| =height=" ... "= | height of the image result | |
+---++ Graphviz from Table
+
+Instead of having to learn the dot language, nodes and edges can also be specified in Foswiki tables:
+
+| *Node* | *Attributes* |
+| hello | color="red" |
+| world | shape=box |
+
+| *Source* | *Label* | *Target* | *Attributes* |
+| hello | | world | |
+
+Given these two tables where the only two tables in a topic then this would render the appropriate graph:
+
+
+%GRAPHVIZ{
+ topic="SomeTopic"
+
+ nodestable="0"
+ nodecol="0"
+ nodeattrcol="1"
+
+ edgestable="1"
+ sourcecol="0"
+ labelcol="1"
+ targetcol="2"
+ edgeattrcol="3"
+}%
+
+
+| *Parameter* | *Description* | *Default* |
+| =table="int"= / =edgestable="int"=| index of table in =topic= to extract edges from | |
+| =nodestable="int"= | index of table in =topic= to extract nodes from | |
+| =nodecol="int"= | index of column that holds the node name | 0 |
+| =nodeattrcol="int"= | index of colum that holds node attributs |
+| =sourcecol="int"= | index of the colum holding the source node name | 0 |
+| =targetcol="int"= | index of the colum holding the target node name | 1 |
+| =labelcol="int"= | index of column holding the edge label | |
+| =edgeattrcol="int"= | index of column holding the edge attributes |
+| =preamble= | some dot code to be added before the generated node and edge code | |
+
---++ Examples
---+++ Example 1
@@ -156,5 +196,5 @@ digraph G {
| Home page: | Foswiki:Extensions/%TOPIC% |
| Support: | Foswiki:Support/%TOPIC% |
-%META:FILEATTACHMENT{name="hello_world.png" attachment="hello_world.png" attr="" comment="" date="1439247692" size="6201" user="ProjectContributor" version="1"}%
-%META:FILEATTACHMENT{name="softmaint.txt" attachment="softmaint.gv" attr="h" comment="" date="1439247692" moveby="micha" movedto="System.GraphvizPlugin.softmaint.txt" movedwhen="1439247180" movefrom="System.GraphvizPlugin.softmaint.gv" size="14946" user="ProjectContributor" version="1"}%
+%META:FILEATTACHMENT{name="hello_world.png" attachment="hello_world.png" attr="" comment="" date="1439299038" size="6201" user="ProjectContributor" version="1"}%
+%META:FILEATTACHMENT{name="softmaint.txt" attachment="softmaint.gv" attr="h" comment="" date="1439299038" moveby="micha" movedto="System.GraphvizPlugin.softmaint.txt" movedwhen="1439247180" movefrom="System.GraphvizPlugin.softmaint.gv" size="14946" user="ProjectContributor" version="1"}%
diff --git a/lib/Foswiki/Plugins/GraphvizPlugin.pm b/lib/Foswiki/Plugins/GraphvizPlugin.pm
index f248eb6..0dda09f 100644
--- a/lib/Foswiki/Plugins/GraphvizPlugin.pm
+++ b/lib/Foswiki/Plugins/GraphvizPlugin.pm
@@ -23,8 +23,8 @@ use Foswiki::Plugins ();
use Foswiki::Attrs ();
use Foswiki::Plugins::WysiwygPlugin ();
-our $VERSION = '0.01';
-our $RELEASE = '0.01';
+our $VERSION = '0.02';
+our $RELEASE = '11 Aug 2015';
our $SHORTDESCRIPTION = 'Draw graphs using the !GraphViz utility';
our $NO_PREFS_IN_TOPIC = 1;
our $core;
diff --git a/lib/Foswiki/Plugins/GraphvizPlugin/Core.pm b/lib/Foswiki/Plugins/GraphvizPlugin/Core.pm
index 4c3c9b7..5d446f4 100644
--- a/lib/Foswiki/Plugins/GraphvizPlugin/Core.pm
+++ b/lib/Foswiki/Plugins/GraphvizPlugin/Core.pm
@@ -58,10 +58,23 @@ sub GRAPHVIZ {
my $text = "";
my $attachment = $params->{attachment};
my $section = $params->{section};
+ my $nodeTable = $params->{nodestable};
+ my $edgeTable = $params->{edgestable} || $params->{table};
+ my $doGraphFromTable = (defined $nodeTable || defined $edgeTable);
+ my $parser;
+
+ if ($doGraphFromTable) {
+ require Foswiki::Plugins::GraphvizPlugin::TableParser;
+ $parser = Foswiki::Plugins::GraphvizPlugin::TableParser->new();
+ my ($meta) = Foswiki::Func::readTopic($theWeb, $theTopic);
+ $parser->parse($meta->text, $meta);
+ $text = "digraph $theTopic {\n";
+ $text .= "\n".($params->{preamble} || '')."\n";
+ }
# .... read attachment
if (defined $attachment) {
- return _inlineError("attachment '$attachment' not found at $theWeb.$theTopic")
+ return _inlineError("Error: attachment '$attachment' not found at $theWeb.$theTopic")
unless Foswiki::Func::attachmentExists($theWeb, $theTopic, $attachment);
$text = Foswiki::Func::readAttachment($theWeb, $theTopic, $attachment);
}
@@ -75,8 +88,14 @@ sub GRAPHVIZ {
$thisParams->{$key} = $val;
}
$thisParams->{_DEFAULT} = "$theWeb.$theTopic";
- my ($obj) = Foswiki::Func::readTopic($web, $topic);
- $text = $session->INCLUDE($thisParams, $obj)
+ my ($meta) = Foswiki::Func::readTopic($web, $topic);
+ $text = $session->INCLUDE($thisParams, $meta)
+ }
+
+ # ... from table
+ elsif (defined $nodeTable || defined $edgeTable) {
+ $text .= $parser->getNodes($nodeTable, $params) if defined $nodeTable;
+ $text .= $parser->getEdges($edgeTable, $params) if defined $edgeTable;
}
# ... from text param
@@ -84,18 +103,24 @@ sub GRAPHVIZ {
$text = $params->remove("_DEFAULT") || $params->remove("text");
}
+ if ($doGraphFromTable) {
+ $text .= "}";
+ }
+
# expand
$text = Foswiki::Func::expandCommonVariables($text)
if Foswiki::Func::isTrue($params->{expand}, 0);
+ return _inlineError("Error: no dot code") unless defined $text;
+
$text = Encode::encode_utf8($text);
my $type = $params->{type} || "svg";
- return _inlineError("unknown type '$type'")
+ return _inlineError("Error: unknown type '$type'")
unless $type =~ /^(svgz?|png|gif|jpe?g|pdf)$/;
my $renderer = $params->{renderer} || $params->{engine} || "dot";
- return _inlineError("unknown renderer '$renderer'")
+ return _inlineError("Error: unknown renderer '$renderer'")
unless $renderer =~ /^(dot|neato|twopi|circle|s?fdp|patchwork)$/;
my $library = $params->{library};
diff --git a/lib/Foswiki/Plugins/GraphvizPlugin/TableParser.pm b/lib/Foswiki/Plugins/GraphvizPlugin/TableParser.pm
new file mode 100644
index 0000000..cfaf9d0
--- /dev/null
+++ b/lib/Foswiki/Plugins/GraphvizPlugin/TableParser.pm
@@ -0,0 +1,98 @@
+# Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/
+#
+# GraphvizPlugin is Copyright (C) 2015 Michael Daum http://michaeldaumconsulting.com
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details, published at
+# http://www.gnu.org/copyleft/gpl.html
+
+package Foswiki::Plugins::GraphvizPlugin::TableParser;
+
+use strict;
+use warnings;
+
+use Foswiki::Tables::Reader ();
+use Data::Dump qw(dump);
+our @ISA = ('Foswiki::Tables::Reader');
+
+sub parse {
+ my ($this, $text, $meta) = @_;
+
+ $this->SUPER::parse($text, $meta);
+
+ return $this->{result};
+}
+
+sub getNodes {
+ my ($this, $tableIndex, $params) = @_;
+
+ my $table = $this->{result}[$tableIndex];
+
+ return unless $table;
+
+ $params->{nodecol} = 0 unless defined $params->{nodecol};
+
+ my @lines = ();
+
+ # generate nodes
+ my $index = 0;
+ foreach my $table ($table->getCellData) {
+ foreach my $row (@$table) {
+ $index++;
+ next if $index == 1;# skip header
+ my @attrs = ();
+ push @attrs, "$params->{nodeattrcol}]\"" if defined $params->{nodeattrcol};
+ my $attrs = '';
+ $attrs = "[".join(", ", @attrs)."]" if @attrs;
+ push @lines, " \"$row->[$params->{nodecol}]\" $attrs";
+ }
+ }
+
+ return join("\n", @lines);
+}
+
+sub getEdges {
+ my ($this, $tableIndex, $params) = @_;
+
+ my $table = $this->{result}[$tableIndex];
+
+ return unless $table;
+
+ $params->{sourcecol} = 0 unless defined $params->{sourcecol};
+ $params->{targetcol} = 1 unless defined $params->{targetcol};
+
+ my @lines = ();
+
+ # generate edges
+ my $index = 0;
+ foreach my $table ($table->getCellData) {
+ foreach my $row (@$table) {
+ $index++;
+ next if $index == 1;# skip header
+ my @attrs = ();
+ push @attrs, "xlabel=\"$row->[$params->{labelcol}]\"" if defined $params->{labelcol};
+ push @attrs, "$params->{edgeattrcol}]\"" if defined $params->{edgeattrcol};
+ my $attrs = '';
+ $attrs = "[".join(", ", @attrs)."]" if @attrs;
+ push @lines, " \"$row->[$params->{sourcecol}]\" -> \"$row->[$params->{targetcol}]\" $attrs";
+ }
+ }
+
+ return join("\n", @lines);
+}
+
+sub line {
+ my ( $this, $line ) = @_;
+
+ # ignore all non-table lines
+}
+
+1;
+