The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Graph::Flowchart - Generate easily flowcharts as Graph::Easy objects

SYNOPSIS

        use Graph::Flowchart;

        my $flow = Graph::Flowchart->new();

        print $flow->as_ascii();

DESCRIPTION

This module lets you easily create flowcharts as Graph::Easy objects. This means you can output your flowchart as HTML, ASCII, Boxart (unicode drawing) or SVG.

Classes

The nodes constructed by the various add_* methods will set the subclass of the node according to the following list:

start

The start block.

end

The end block, created by finish().

block

Orindary code blocks, f.i. from $b = 9;.

if, for, while, until

Blocks for the various constructs for conditional and loop constructs.

sub

For sub routine declarations.

use

For use, no and require statements.

goto, break, return, next, last, continue

Blocks for the various constructs for jumps/returns.

true, false, goto, call, return, break, next, continue

Classes for edges of the true and false if-branches, and for goto, as well as sub routine calls.

Each class will get some default attributes, like if constructs having a diamond-shape.

You can override the graph appearance most easily by changing the (sub)-class attributes:

        my $chart = Graph::Flowchart->new();

        $chart->add_block('$a = 9;');
        $chart->add_if_then('$a == 9;', '$b = 1;');
        $chart->finish();

        my $graph = $chart->as_graph();

Now $graph is a Graph::Easy object and you can manipulate the class attributes like so:

        $graph->set_attribute('node.if', 'fill', 'red');
        $graph->set_attribute('edge.true', 'color', 'green');
        print $graph->as_html_file();

This will color all conditional blocks red, and edges that represent the true branch green.

EXPORT

Exports nothing.

METHODS

All block-inserting routines on the this model will insert the block on the given position, or if this is not provided, on the current position. After inserting the blocks, the current position will be updated.

In addition, the newly inserted block(s) might be merged with blodcks at the current position.

new()

        my $grapher = Graph::Flowchart->new();

Creates a new Graph::Flowchart object.

as_graph()

        my $graph = $grapher->as_graph();

Return the internal data structure as Graph::Easy object.

as_ascii()

        print $grapher->as_ascii();

Returns the flow chart as ASCII art drawing.

as_boxart()

        print $grapher->as_boxart();

Returns the flow chart as a Unicode boxart drawing.

as_html_file()

        print $grapher->as_html_file();

Returns the flow chart as entire HTML page.

current_block()

        my $insertion = $grapher->current_block();      # get
        $grapher->current_block( $block);               # set

Get or set the current block in the flow chart, e.g. where new code blocks will be inserted by the add_* methods.

Needs a Graph::Flowchart::Node as argument, which is usually an object returned by one of the add_* methods.

current()

current() is an alias for current_block().

make_current()

        $grapher->make_current($block);

Set the given block as current, and convert it to a joint.

first_block()

        my $first = $grapher->first_block();            # get
        $grapher->first_block( $block );                # set

Get or set the first block in the flow chart, usually the 'start' block.

Needs a Graph::Flowchart::Node as argument, which is usually an object returned by one of the add_* methods.

last_block()

        my $last = $grapher->last_block();              # get
        $grapher->last_block( $block);                  # set

Get or set the last block in the flow chart, usually the block where you last added something via one of the add_* routines.

Needs a Graph::Flowchart::Node as argument, which is usually an object returned by one of the add_* methods.

The returned block will only be the last block if you call finish() beforehand.

start_node()

        my $start = $grapher->start_node();

Returns the START node. See also first_block().

end_node()

        my $end = $grapher->end_node();

Returns the END node. See also last_block().

finish()

        my $last = $grapher->finish( $block );
        my $last = $grapher->finish( );

Adds an end-block. If no parameter is given, uses the current position, otherwise appends the end block to the given $block. See also current_block. Will also update the position of last_block to point to the newly added block, and return this block.

new_block()

        my $block = $grapher->new_block( $text, $type );
        my $block = $grapher->new_block( $text, $type, $label );

Creates a new block from the given text and type. The type is one of the N_* from Graph::Flowchart::Node.

The optional label gives the label name, which can be used by goto constructs as target node. See also find_target().

find_target()

        my $target = $grapher->find_target( $label );

Given the label $label, find the block that has this text as label and returns it. Returns undef if the block doesn't exists yet.

add_group()

        $grapher->add_group($group_name);

Add a group to the flowchart, and set it as current.

no_group()

        $grapher->no_group();

Forget the current group.

add_block()

        my $current = $grapher->add_block( $block );
        my $current = $grapher->add_block( $block, $where );

Add the given block. See new_block on creating the block before hand.

The optional $where parameter is the point where the code will be inserted. If not specified, it will be appended to the current block, see current_block.

Returns the newly added block as current.

Example:

        +---------+
    --> | $a = 9; | -->
        +---------+

add_new_block()

        my $new = $grapher->add_new_block( $text, $type, $label, $where);

Creates a new block, and adds it to the flowchart. Might merge the new block into the current one, and then returns the new current block.

add_new_joint()

        my $joint = $grapher->add_new_joint();
        my $joint = $grapher->add_new_joint($where);

Is a shortcut for add_block(new_block('', N_JOINT())) and creates and adds a joint to the flowchart. The optional parameter $where takes the block where to attach the join to.

insert_block

        my $new = $grapher->insert_block($block, $where);

Insert a block to the current (or $where) block. Any outgoing connections from $where are moved to the new block (unless the blocks are merged).

insert_new_block

        my $new = $grapher->insert_new_block($where);

A short cut for:

        my $block = $grapher->new_block( ... );
        my $new = $grapher->insert_block($block, $where);

See insert_block().

insert_new_joint

        my $new = $grapher->insert_new_joint($where);

A short cut for:

        my $joint = $grapher->add_joint( ... );
        my $new = $grapher->insert_block($joint, $where);

See insert_block().

connect()

        my $edge = $grapher->connect( $from, $to );
        my $edge = $grapher->connect( $from, $to, $edge_label );
        my $edge = $grapher->connect( $from, $to, $edge_label, $edge_class );

Connects two blocks with an edge, setting the optional edge label and edge class.

Returns the Graph::Easy::Edge object for the connection.

merge_blocks()

        $grapher->merge_blocks($first,$second);

If possible, merge the given two blocks into one block, keeping all connections to the first, and all from the second. Any connections between the two blocks is dropped.

Example:

        +---------+     +---------+
    --> | $a = 9; | --> | $b = 2; | -->
        +---------+     +---------+

This will be turned into:

        +---------+ 
    --> | $a = 9; | -->
        | $b = 2; | 
        +---------+

collapse_joints()

        $grapher->cleanup_joints();

Is called automatically by finish(). This will collapse any left-over joint nodes:

                +---+             +-------+
    -- false --> | * | -- next --> | $b++; | -->
                +---+             +-------+

Will be turned into:

                       +-------+
    -- false, next --> | $b++; | -->
                       +-------+

ADDITIONAL METHODS

Note that the following routines will not work when used recursively, because they add the entire structure already connect, at once.

If you want a if-then-else, which contains another if-then-else, for instance, you need to construct the blocks first, and then connect them manually.

Pleasee Devel::Graph on how to do this.

add_if_then()

        my $current = $grapher->add_if_then( $if, $then);
        my $current = grapher->add_if_then( $if, $then, $where);

Add an if-then branch to the flowchart. The optional $where parameter defines at which block to attach the construct.

Returns the new current block, which is a joint.

Example:

                                             false
          +--------------------------------------------+
          |                                            v
        +-------------+  true   +---------+
    --> | if ($a = 9) | ------> | $b = 1; | ------->   *   -->
        +-------------+         +---------+

add_if_then_else()

        my $current = $grapher->add_if_then_else( $if, $then, $else);
        my $current = $grapher->add_if_then_else( $if, $then, $else, $where);

Add an if-then-else branch to the flowchart.

The optional $where parameter defines at which block to attach the construct.

Returns the new current block, which is a joint.

Example:

        +-------------+
        |   $b = 2;   | --------------------------+
        +-------------+                           |
          ^                                       |
          | false                                 |
          |                                       v
        +-------------+  true   +---------+
    --> | if ($a = 9) | ------> | $b = 1; | -->   *   -->
        +-------------+         +---------+

If $else is not defined, works just like add_if_then().

add_for()

        my ($current,$body,$continue) = $grapher->add_for( $init, $while, $cont, $body, $continue);
        my ($current,$body,$continue) = $grapher->add_for( $init, $while, $cont, $body, $continue, $where);

Add a for (my $i = 0; $i < 12; $i++) { ... } continue {} style loop.

The optional $where parameter defines at which block to attach the construct.

This routine returns three block positions, the current block (e.g. after the loop), the block of the loop body and the position of the (optional) continue block.

Example:

        +--------------------+  false        
    --> |   for: $i < 10;    | ------->  *  -->
        +--------------------+
          |                ^
          | true           +----+
          v                     |
        +---------------+     +--------+
        |     $a++;     | --> |  $i++  |
        +---------------+     +--------+

add_foreach()

        my ($current,$body,$continue) = $grapher->add_foreach( $list, $body, $cont);
        my ($current,$body,$continue) = $grapher->add_foreach( $list, $body, $cont, $where);

Add a for my $var (@lies) { ... } style loop.

The optional $where parameter defines at which block to attach the construct.

This routine returns three block positions, the current block (e.g. after the loop), the block of the loop body and the position of the (optional) continue block.

Example:

        +----------------------+  false        
    --> |   for my $i (@list)  | ------->  *  -->
        +----------------------+
          |                ^
          | true           +----+
          v                     |
        +---------------+     +--------+
        |     $a++;     | --> |  $i++  |        # body and continue block
        +---------------+     +--------+

add_while()

        my ($current,$body, $cont) = 
          $grapher->add_while($while, $body, $cont, $where) = @_;

To skip the continue block, pass $cont as undef.

This routine returns three block positions, the current block (e.g. after the loop), the block of the loop body and the continue block.

Example of a while loop with only the body (or only the continue block):

        +----------------------+  false  
    --> |   while ($b < 19)    | ------->  *  -->
        +----------------------+
          |                  ^
          | true             |
          v                  |
        +-----------------+  |
        |      $b++;      |--+
        +-----------------+

Example of a while loop with body and continue block (note similiarity to for loop):

        +--------------------+  false        
    --> | while ($i < 10)    | ------->  *  -->
        +--------------------+
          |                ^
          | true           +----+
          v                     |
        +---------------+     +--------+
        |     $a++;     | --> |  $i++  |
        +---------------+     +--------+

add_until()

        my ($current,$body, $cont) = 
          $grapher->add_until($until, $body, $cont, $where) = @_;

To skip the continue block, pass $cont as undef.

Works just like while, but reverses the true and false edges to represent a until () BLOCK continue BLOCK loop.

See also add_while().

add_jump()

        my $jump = $grapher->add_jump ( $text, $type, $label, $target);
        my ($jump,$target) = $grapher->add_jump ( $text, $type, $label);

Adds a jump block, with a connection to $target. If $target is just the label name, will try to find a block with that label. If no block can be found, will create it.

The type is one of:

        goto
        break
        return
        last
        next
        continue

add_joint()

        my $joint = $grapher->add_joint( @blocks );

Adds a joint (an unlabeled, star-shaped node) to the flowchart and then connects each block in the given list to that joint. This is used f.i. by if-then-else constructs that need a common joint where all the branches join together again.

When adding a block right after a joint, they will be merged together and the joint will be effectively replaced by the block.

Example:

    -->   *   -->

SEE ALSO

Graph::Easy, Devel::Graph.

COPYRIGHT AND LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms of the GPL version 2 or later. See the LICENSE file for information.

AUTHOR

Copyright (C) 2004-2007 by Tels http://bloodgate.com