|
|
| |
Flowchart(3) |
User Contributed Perl Documentation |
Flowchart(3) |
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.
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.
- new (?width? ?height? ?pad? ?debug?)
- This is the object constructor that actually creates your flowchart
object. All parameters are optional and are passed in a hash.
- width
- Optional. Specifies the width of your flowchart object, or uses the
module default (72).
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.
- height
- Optional. Specifies the height of your flowchart object, or uses
the module default (0).
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.
- pad
- Optional. pad allows you to specify a padding character. The
padding character is what is used to fill in the space between boxes and
lines. The default padding character is a space (\040), but you can set it
to anything else you'd like. This is most useful when debugging, IMHO.
Very useful in combination with debug (see below). Set to " " by
default.
- debug
- Optional. debug will print out the x & y coordinates of the
flowchart. This should greatly help you place your boxes where you want
them to be. Off by default, set to 1 to enable.
- directed
- Optional. directed specifies that your flowchart is direction
dependent. This will add on arrows to all of your lines. Flowcharts are
non-directed by default. Set this to 1 to use a directed flowchart.
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" => "."
);
- box (string x_coord y_coord ?x_pad? ?y_pad? ?width? ?height?)
- You use the box method to add a new box into your flowchart object. All
parameters are passed in a hash.
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.
- string
- Required. string is the message that you'll see within the box.
Want your box to say "Hi there!"? "string" =>
"Hi there!"; Easy as pie.
- x_coord
- Required. The x coordinate of the upper left corner of the box. Use
the debug option to help you find your coordinates.
- y_coord
- Required. The y coordinate of the upper left corner of the box. Use
the debug option to help you find your coordinates.
- x_pad
- Optional. x_pad allows you to specify the amount of horizontal
white space between the edges of the box and the text within. If this
option is not specified, it'll use the default of a single space.
- y_pad
- Optional. y_pad allows you to specify the amount of vertical white
space between the edges of the box and the text within. If this option is
not specified, it'll use the default of a single line of white space.
- width
- Optional. width allows you to specify the width of the box. The
narrowest possible box has a width of 3. You must take into account your
x_pad value, as well as the edges of the box when you specify a width. If
no width is specified, it will use the default of 15.
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.
- height
- Optional. height allows you to specify the height of the box. The
shortest possible box has a height of 3. You must take into account your
y_pad value, as well as the edges of the box when you specify a height. If
no height is specified, it will use the default of 0 (zero).
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 |
| ? |
+-------------+
- relate ([from, from side, ?on side?], [to, to side, ?on side?],
?reason?)
- the relate method connects boxes to each other. Once two boxes are
related, a line is automatically drawn between then, listing a reason if
given, and arrows if it's a directed flowchart. The relate method spares
you the trouble of having to re-position your lines if you move your boxes
around. You may still have to do some fiddling (such as changing the sides
that are connected), but it's much less trouble than re-arranging the
boxes and the lines.
- (from or to)
- Required. This is the box that you're relating from or to, it's the
first item in an anonymous array.
- (from or to) side
- Required. This is the side of the box that you're relating from or
to. This must be either "top", "bottom",
"right", or "left". It's the second item in an
anonymous array.
- ?on side?
- Optional. This optional item specifies where on the box side you'd
like to draw the line from. If zero, it will take the first available slot
starting from the left (if drawing from the top or bottom) or from the top
(it drawing from the right or left). If -1, it will take the first
available slot starting from the other side (right for top and bottom or
bottom for right or left). If any other number, it will draw the line at
that position, along the side, again counting from the left or the
top.
- reason
- Optional. reason is a name and value pair that specifies why you
would take that route. The value must be one character long, you'll die
with an error if it isn't. reasons only make sense in a directed
flowchart, they don't appear in non-directed ones. Typical values are
"Y" for yes and "N" for no. If no reason is specified,
the default direction character will be used.
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. |
| |
+-------------+
- draw (?FILEHANDLE?)
-
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.
- - 1.00 12/21/99
- First public release onto CPAN.
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 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. :-)
Hey! The above document had some coding errors, which are explained
below:
- Around line 1288:
- You forgot a '=back' before '=head1'
- Around line 1376:
- Deleting unknown formatting code U<>
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |