Text::Flowchart - ASCII Flowchart maker |
Text::Flowchart - ASCII Flowchart maker
Jim Thomason, jim3@psynet.net
+-------+ +-------------+ | BEGIN >---+ | | +-------+ +--> Do you need | | to make a N------+ +--------Y flowchart? | | | | | | | +-------------+ | | | | +------------+ | | | | | +-----V-------+ | So use it. | | | | | | | | Then my | +--^---V-----+ | | module may | | | | | help. | | | | | >----+ | | +-------------+ | | | +-----V-------+ | | | | | Then go do | +------> something | | else. | | | +-------------+
Text::Flowchart does what the synopsis implies, it makes ASCII flowcharts. It also (hopefully) makes it easy to make ASCII flowcharts.
Carp
New flowcharts are created with the new constructor.
$object = Text::Flowchart->new();
You can also initialize values at creation time, such as:
$object = Text::Flowchart->new( "width" => 120, "debug" => 1 );
There aren't any. Well, there aren't any that you really should use.
Why's that, you ask? Because that's how the module is written. Once an object is added into a flowchart, its appearance becomes set in stone. And I mean totally set in stone, you cannot remove a box from a flowchart, it sticks around until the flowchart is destroyed. Even if you poked around in the internals of the module and discovered that ->string is an accessor in the box class, for instance, it wouldn't do you any good since objects are immediately rendered upon their creation. Even if you re-render the object after fiddling with it, it's not going to work since the objects are inserted into the flowchart's internal grid once they're rendered.
So basically, declare everything you need to declare about an object when you create it, and make sure that that's the information you're going to use when you print it out. It's not that hard. :)
There are several methods you are allowed to invoke upon your flowchart object.
The width of a flowchart must be specified, it cannot grow to accomodate objects placed within it. If you try to place an object beyond the edge of the flowchart, you'll die with an error.
The default height of 0 means that your flowchart will grow in height as much as necessary to accomodate the height of whatever you insert into your flowchart. You can also specify a specific height so that your flowchart will be no taller than 17 rows, for example. If you try to place an object beyond the bottom of the flowchart, you'll die with an error.
For example:
$flowchart = Text::Flowchart::new->(); #boring flowchart, no options
$flowchart = Text::Flowchart::new->( #flowchart specifying new width, a % as the padding character, and using the debugging option "width" => 100, "pad" => "%", "debug" => 1 );
$flowchart = Text::Flowchart::new( #using periods as the padding character "pad" => "." );
The text within a box is wrapped at word boundaries if possible, or at the appropriate width if not possible so that all of your text fits inside your box.
If you specify a width of 0 (zero), then your box will grow horizontally to accomodate all of your text, or until it reaches the width of the flowchart, whichever is lesser. Be careful! This will put all of your box message onto the same line. You almost never want your width to be 0.
If you specify a height of 0 (zero), then your box will grow vertically to accomodate all of your text, or until it reaches the height of the flowchart, whichever is lesser. You most likely want a box width of some fixed value, and a box height of zero so it will grow to accomodate your message.
If you specify a non-zero box height, then your string will be truncated once the box reaches the height that you specified. It will still be created, you just won't have all of your text in it.
For example:
$example_box = $flowchart->box( #creates a box at (15,0) "string" => "Do you need to make a flowchart?", "x_coord" => 15, "y_coord" => 0 );
Output:
+-------------+ | | | Do you need | | to make a | | flowchart? | | | +-------------+
$example_box2 = $flowchart->box( #creates a box at (0,0), with new x_pad and y_pad values "string" => "Do you need to make a flowchart?", "x_coord" => 0, "y_coord" => 0, "x_pad" => 0, "y_pad" => 3 );
Output:
+-------------+ | | | | | | |Do you need | |to make a | |flowchart? | | | | | | | +-------------+
$example_box3 = $flowchart->box( #creates a box at (0,0), with new x_pad and y_pad values "string" => "Do you need to make a flowchart?", "x_coord" => 0, "y_coord" => 0, "x_pad" => 2, "y_pad" => 0 );
Output:
+-------------+ | Do you | | need to | | make a | | flowchart | | ? | +-------------+
For example:
$flowchart = Text::Flowchart->new( "width" => 50, "directed" => 1);
$example_box = $flowchart->box( #creates a box at (0,0) "string" => "Do you need to make a flowchart?", "x_coord" => 0, "y_coord" => 2, );
$example_box2 = $flowchart->box( #creates a box at (15,0) "string" => "Yes I do.", "x_coord" => 19, "y_coord" => 0, "width" => 13 );
$example_box3 = $flowchart->box( #creates a box at (15,0) "string" => "No I don't.", "x_coord" => 19, "y_coord" => 7 );
$flowchart->relate( [$example_box, "right"] => [$example_box2, "left"] );
$flowchart->relate( [$example_box, "right", -1] => [$example_box3, "left"] );
$flowchart->draw();
Output:
+-----------+ +--> | +-------------+ | | Yes I do. | | >-+ | | | Do you need | +-----------+ | to make a | | flowchart? | | >--+ +-------------+ +-------------+ +-> | | No I don't. | | | +-------------+
$flowchart = Text::Flowchart->new( | ||
``width'' => 50); | #A non-directed chart |
$example_box = $flowchart->box( #creates a box at (0,0) "string" => "Do you need to make a flowchart?", "x_coord" => 0, "y_coord" => 2, );
$example_box2 = $flowchart->box( #creates a box at (15,0) "string" => "Yes I do.", "x_coord" => 19, "y_coord" => 0, "width" => 13 );
$example_box3 = $flowchart->box( #creates a box at (15,0) "string" => "No I don't.", "x_coord" => 19, "y_coord" => 7 );
$flowchart->relate( [$example_box, "right"] => [$example_box2, "left"] );
$flowchart->relate( [$example_box, "right", -1] => [$example_box3, "left"] );
$flowchart->draw();
Output:
+-----------+ +--+ | +-------------+ | | Yes I do. | | +-+ | | | Do you need | +-----------+ | to make a | | flowchart? | | +--+ +-------------+ +-------------+ +-+ | | No I don't. | | | +-------------+
$flowchart = Text::Flowchart->new( ``width'' => 50, ``directed'' => 1 );
$example_box = $flowchart->box( #creates a box at (0,0) "string" => "Do you need to make a flowchart?", "x_coord" => 0, "y_coord" => 2, );
$example_box2 = $flowchart->box( #creates a box at (15,0) "string" => "Yes I do.", "x_coord" => 19, "y_coord" => 0, "width" => 13 );
$example_box3 = $flowchart->box( #creates a box at (15,0) "string" => "No I don't.", "x_coord" => 19, "y_coord" => 7 );
$flowchart->relate( [$example_box, "right"] => [$example_box2, "left"], "reason" => "Y" );
$flowchart->relate( [$example_box, "right", -1] => [$example_box3, "left"], "reason" => "N" );
$flowchart->draw();
Output:
+-----------+ +--> | +-------------+ | | Yes I do. | | Y-+ | | | Do you need | +-----------+ | to make a | | flowchart? | | N--+ +-------------+ +-------------+ +-> | | No I don't. | | | +-------------+
the draw method actuall outputs your flowchart. You can optionally give it a glob to a filehandle to re-direct the output to that filehandle.
For example:
$flowchart->draw(); #draw your flowchart on STDOUT;
$flowchart->draw(*FILE); #send it to the FILE filehandle.
Required. This is the box that you're relating from or to, it's the first item in an anonymous array.
This code will print out the flowchart shown up in the SYNOPSIS.
use Text::Flowchart;
$flowchart = Text::Flowchart->new( "width" => 50, "directed" => 0);
$begin = $flowchart->box( "string" => "BEGIN", "x_coord" => 0, "y_coord" => 0, "width" => 9, "y_pad" => 0 );
$start = $flowchart->box( "string" => "Do you need to make a flowchart?", "x_coord" => 15, "y_coord" => 0 );
$yes = $flowchart->box( "string" => "Then my module may help.", "x_coord" => 0, "y_coord" => 10 );
$use = $flowchart->box( "string" => "So use it.", "x_coord" => 16, "y_coord" => 8, "width" => 14 );
$no = $flowchart->box( "string" => "Then go do something else.", "x_coord" => 30, "y_coord" => 17 );
$flowchart->relate( [$begin, "right"] => [$start, "left", 1] );
$flowchart->relate( [$start, "left", 3] => [$yes, "top", 5], "reason" => "Y" );
$flowchart->relate( [$start, "right", 2] => [$no, "top", 5], "reason" => "N" );
$flowchart->relate( [$yes, "right", 4] => [$use, "bottom", 2] );
$flowchart->relate( [$use, "bottom", 6] => [$no, "left", 2] );
$flowchart->draw();
Why in the world did you write this thing?
There's a flowcharting-type program that a couple of people use at work. It is only available on PCs. I got cranky about not being able to use it, so I wrote my own. Admittedly, mine isn't as powerful or as easy to use as theirs is, but I'm quite pleased with it nonetheless. Real programmers don't use software tools. Real programmers write software tools.
Hey! I created a box, and then I tried to change its string and it didn't work! What gives?
Boxes are rendered upon their creation. You cannot change their strings once their are created. I may change this in a future release, but for now just wait until you're U<sure> you know what you want in a box before you create it, okay? That way you won't have to change it later.
Hey! I'm running a memory tracer, and even though I deleted a box, the memory wasn't freed up. Do you have a memory leak or what?
Nope. Boxes are stored internally inside the flowchart object. The box variable that you get back from ->box is just a reference to the box that lives inside the flowchart. Since the flowchart still knows the box exists (even if you don't), the memory is not freed up. Naturally, it will be freed once perl exits. I may add in the ability to remove boxes to a future release.
I want to draw lines from the left side of a box to the left side of another box, but I get an error. Why?
Because you can't draw lines like that. :)
Basically, there are 10 types of lines that can be drawn (all of which are done by the relate method, naturally). They look like:
+---+ +--+ +--+ + + + +-+ +-+ + + | | | | | | | | | +--+ +--+ + +--+ +--+ + + +--+ +--+ | | + +
Or horizontal, zig-zagging horizontal, vertical, zig-zagging vertical, and corners. Connecting the same sides of boxes would require another type of line, (the "handle", FWIW), and Text::Flowchart can't draw those. If I can think of a good way to implement them I will. Incidentally, you can draw your own lines if you need to, using the ->line method.
$flowchart->line( "from" => [xfrom, yfrom], "to" => [yfrom, yto], "reason"=> "Y" );
But you really should use relate and not connect the same sides of boxes, it will make your life much simpler.
I made a flowchart, but all of the lines cross over each other and make a mess. Why?
Text::Flowchart has no collision detection. If you try to place a box where another box already was, it'll gladly be drawn over. Whichever boxes or lines are drawn last will take priority. If things are being over-written, then you need to change the coordinates of your boxes so they stop over-writing each other, or change the box sides that are related so they don't draw over boxes.
Squares and rectangles are boring. Can I draw other shapes?
Not yet. The module is actually numerous packages, heavily subclassing each other. Adding in additional shapes is quite easy, actually. You'd just need to define a subclass of the Text::Flowchart::Shape class and define the necessary functions. You'd have to declare a render method to actually create the ASCII object, a relate method that knows how to draw the lines between objects, a get_next_coord method to get the next available coordinate on a given side, and make the necessary modifications to your new constructor (calling ::Shape's init(), of course), and you're done!
It's actually much easier than it sounds, from a programming standpoint. Figuring out how to properly render and relate object, that's tricky. I will be adding more shapes into a future release. If anyone wants to add their own shapes, e-mail 'em to me and I may add them in in the future.
So what is it with these version numbers anyway?
I'm going to try to be consistent in how I number the releases.
The hundredths digit will indicate bug fixes, etc.
The tenths digit will indicate new and/or better functionality, as well as some minor new features.
The ones digit will indicate a major new feature or re-write.
Basically, if you have x.ab and x.ac comes out, you want to get it guaranteed. Same for x.ad, x.ae, etc.
If you have x.ac and x.ba comes out, you'll probably want to get it. Invariably there will be bug fixes from the last ``hundredths'' release, but it'll also have additional features. These will be the releases to be sure to read up on to make sure that nothing drastic has changes.
If you have x.ac and y.ac comes out, it will be the same as x.ac->x.ba but on a much larger scale.
Anything else you want to tell me?
Sure, anything you need to know. Just drop me a message.
If there's something that you feel would be worthwhile to include, please let me know and I'll consider adding it.
How do you know what's a worthwhile addition? Basically, if it would make your life easier. Am I definitely going to include it? Nope. No way. But I'll certainly consider it, all suggestions are appreciated. I may even be nice and fill you in on some of the ideas I have for a future release, if you ask nicely. :)
Copyright (c) 1999 James A Thomason III (jim3@psynet.net) All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Except if you profit from its distribution. If this module or works based upon this module are distributed in a way that makes you money, you must first contact me to work out a licensing arrangement. I'm just giving the thing away, but I'm not going to allow people to make money off of it unless I get a cut. :) Amounts will be hammered out on an individual basis. CPAN mirrors are exempt from this stipulation. If you're not sure if you're distributing it in a way that makes you money, contact me with details and we'll make a decision.
So you don't have to scroll all the way back to the top, I'm Jim Thomason (jim3@psynet.net) and feedback is appreciated. Bug reports/suggestions/questions/etc. Hell, drop me a line to let me know that you're using the module and that it's made your life easier. :-)
Text::Flowchart - ASCII Flowchart maker |