|
Data::Region - define hierarchical areas with behaviors |
Data::Region - define hierarchical areas with behaviors
use Data::Region;
$r = Data::Region->new( 8.5, 11, { data => PageObj->new() } );
$r->data( PageObj->new() );
foreach my $c ( $r->subdivide(2.5,3) ) {
$a = $c->area(0.25,0.25, 2.25,2.75);
$a2 = $c->area(0.25,0.25, -0.25,-0.25); # as offset from lower right
($t,$m,$b) = $a->split_vertical(2,5,1); # sequential heights
($t,$m,$b) = $a->split_vertical_abs(0,2,7); # absolute offsets
($l,$r) = $a->split_horizontal(2); # $l gets width of 2, $r gets the rest
my($x1,$y1,$x2,$y2) = $a->coords();
my $data = $a->data(); # data inherits from parent, if not set
$a->action( sub { $data->setfont("Times-Bold", 10);
$data->text($x1,$y1, "Some Text");
$data->line( $_[0]->coords() ); # the non-closure way
} );
}
$r->render(); # heirarchically perform all the actions
# Get some info about a region:
($w,$h) = ( $a->width(), $a->height() );
($x1,$y1, $x2,$y2) = $a->coords();
($x1,$y1) = $a->top_left();
($x2,$y1) = $a->top_right();
($x1,$y2) = $a->bottom_left();
($x2,$y2) = $a->bottom_right();
Data::Region allows you to easily define a set of nested (2-dimensional) areas, defined by related coordinates, and to associate actions with them. The actions can then be performed hierarchically from any root of the tree.
Data::Region was written to provide an easy way to do simple page layout, but has, perhaps, more general uses.
The following methods allow you to create Data::Regions, and Data::Regions within Data::Regions (from whence it's turtles all the way down).
The final argument, if given, is a hashref of options. Currently the only supported option is 'data'.
data() method. Child Data::Regions created under this one automatically
inherit this reference as their own 'data', but can override it for
themselves if desired.
$r. The corner coordinates of this
area are relative to $r's coordinates, so for example
$r->area( 1,1, 2,2 );
creates an area whose top left coordinate is offset (1,1) from the top
left coordinate of $r, and whose bottom right coordinate is offset
(2,2), also from $r's top left corner. In this case, if the
corners of $r were (5,5)-(10,10), the created area would have
corners (6,6)-(7,7).
If you specify (either or both coordinates of) the bottom right corner as negative numbers, the area's bottom right corner will be offset from the parent Data::Region's bottom right corner. For example
$r->area( 1,1, -1,-1 );
Given the same parent region as the previous example, this would create an area with corners (6,6)-(9,9).
area() returns a new Data::Region object.
subdivide() will try to fit as many in as possibly, but will return
only whole areas and so the returned areas might not cover the entire
parent region. The first area created will be in the top left-most
corner of the parent region, and proceeds in a left-to-right,
top-to-bottom manner while space remains.
For example, if $r has width of 8.5 and height of 11, this
@a = $r->subdivide( 2.5, 3 );
returns 9 new Data::Regions into @a (int(8.5/2.5)=3, int(11/3)=3, 3*3=9).
subdivide() returns a list of new Data::Region objects.
For example, if $r has corners at (5,5)-(10,10), this
($a,$b,$c,$d) = $r->split_vertical( 2, 0.5, 1 );
creates the following: $a is (5,5)-(10,7), $b is (5,7)-(10,7.5),
$c is (5,7.5)-(10,8.5), and $d gets all the rest
(5,8.5)-(10,10).
split_vertical() returns a list of new Data::Region objects.
split_vertical(), but the arguments specify
Y-coordinates of successive top-left corners, instead of heights
(relative to the parent Data::Region). The first argument does not need to
be 0.
split_vertical_abs() returns a list of new Data::Region objects.
split_vertical(), except tiled child areas are created
left-to-right, instead of top-to-bottom.
split_horizontal() returns a list of new Data::Region objects.
split_horizontal() as split_vertical_abs() is to
split_vertical().
split_horizontal_abs() returns a list of new Data::Region objects.
The following methods allow you to query Data::Region objects for data about the areas they represent.
coords()width()height()top_left()
The following methods allow you to associate data and callbacks to a tree of Data::Regions, and to request a Data::Region to perform its tree of callbacks.
data reference associated with
this Data::Region. Any child regions created under this Data::Region inherit the
reference of their parent (at the time they are created).
data() returns the a reference for the current 'data' field.
render() method
is called.
The argument is a code reference, which will be called with the Data::Region object as its parameter. So for example, you may do
$r->action( sub {
my $self = shift;
# ...$self is the same obj as $r when this is run
} );
A Data::Region may have any number of actions. Actions will be executed in
the order that they were assocaited with action().
render()Actions are performed for this region first, then for all of its children recursively. For each Data::Region, actions are performed in the order that they were added to that Data::Region. The order in which child Data::Regions are recursed into is undefined, but is probably the same as the order they were created in (eg, that's the way it currently works, but is subject to change).
The following should be used only within the module itself.
new(), the purpose of
this method is to separate initialization logic from object-creation
gruntwork. If you subclass this module, it should be sufficient to
override _init() rather than new().
The list of arguments passed to new() are provided.
_init() returns nothing.
$r, using the given absolute
coordinates and dimensions. This method handles maintenence of the
parent's list of children, and the new children's attribute
inheritance from the parent. _spawn() is used by all the Data::Region
creation methods (except new()).
_spawn() returns a new Data::Region object.
Greg Fast <gdf@speakeasy.net>
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
|
Data::Region - define hierarchical areas with behaviors |