Graph-Easy
view release on metacpan or search on metacpan
lib/Graph/Easy/Edge/Cell.pm view on Meta::CPAN
#############################################################################
# Part of Graph::Easy.
#
#############################################################################
package Graph::Easy::Edge::Cell;
use strict;
use warnings;
use Graph::Easy::Edge;
use Graph::Easy::Attributes;
require Exporter;
use vars qw/$VERSION @EXPORT_OK @ISA/;
@ISA = qw/Exporter Graph::Easy::Edge/;
$VERSION = '0.76';
use Scalar::Util qw/weaken/;
#############################################################################
# The different cell types:
use constant {
EDGE_CROSS => 0, # + crossing lines
EDGE_HOR => 1, # -- horizontal line
EDGE_VER => 2, # | vertical line
EDGE_N_E => 3, # |_ corner (N to E)
EDGE_N_W => 4, # _| corner (N to W)
EDGE_S_E => 5, # ,- corner (S to E)
EDGE_S_W => 6, # -, corner (S to W)
# Joints:
EDGE_S_E_W => 7, # -,- three-sided corner (S to W/E)
EDGE_N_E_W => 8, # -'- three-sided corner (N to W/E)
EDGE_E_N_S => 9, # |- three-sided corner (E to S/N)
EDGE_W_N_S => 10, # -| three-sided corner (W to S/N)
EDGE_HOLE => 11, # a hole (placeholder for the "other"
# edge in a crossing section
# Holes are inserted in the layout stage
# and removed in the optimize stage, before
# rendering occurs.
# these loop types must come last
EDGE_N_W_S => 12, # v--+ loop, northwards
EDGE_S_W_N => 13, # ^--+ loop, southwards
EDGE_E_S_W => 14, # [_ loop, westwards
EDGE_W_S_E => 15, # _] loop, eastwards
EDGE_MAX_TYPE => 15, # last valid type
EDGE_LOOP_TYPE => 12, # first LOOP type
# Flags:
EDGE_START_E => 0x0100, # start from East (sorted ESWN)
EDGE_START_S => 0x0200, # start from South
EDGE_START_W => 0x0400, # start from West
EDGE_START_N => 0x0800, # start from North
EDGE_END_W => 0x0010, # end points to West (sorted WNES)
EDGE_END_N => 0x0020, # end points to North
EDGE_END_E => 0x0040, # end points to East
EDGE_END_S => 0x0080, # end points to South
EDGE_LABEL_CELL => 0x1000, # this cell carries the label
EDGE_SHORT_CELL => 0x2000, # a short edge pice (for filling)
EDGE_ARROW_MASK => 0x0FF0, # mask out the end/start type
EDGE_START_MASK => 0x0F00, # mask out the start type
EDGE_END_MASK => 0x00F0, # mask out the end type
EDGE_TYPE_MASK => 0x000F, # mask out the basic cell type
EDGE_FLAG_MASK => 0xFFF0, # mask out the flags
EDGE_MISC_MASK => 0xF000, # mask out the misc. flags
EDGE_NO_M_MASK => 0x0FFF, # anything except the misc. flags
ARROW_RIGHT => 0,
ARROW_LEFT => 1,
ARROW_UP => 2,
lib/Graph/Easy/Edge/Cell.pm view on Meta::CPAN
EDGE_END_N() => 'ending north',
EDGE_END_S() => 'ending south',
};
use constant isa_cell => 1;
sub edge_type
{
# convert edge type number to some descriptive text
my $type = shift;
my $flags = $type & EDGE_FLAG_MASK;
$type &= EDGE_TYPE_MASK;
my $t = $edge_types->{$type} || ('unknown edge type #' . $type);
$flags &= EDGE_FLAG_MASK;
my $mask = 0x0010;
while ($mask < 0xFFFF)
{
my $tf = $flags & $mask; $mask <<= 1;
$t .= ", $flag_types->{$tf}" if $tf != 0;
}
$t;
}
#############################################################################
sub _init
{
# generic init, override in subclasses
my ($self,$args) = @_;
$self->{type} = EDGE_SHORT_E(); # -->
$self->{style} = 'solid';
$self->{x} = 0;
$self->{y} = 0;
$self->{w} = undef;
$self->{h} = 3;
foreach my $k (sort keys %$args)
{
# don't store "after" and "before"
next unless $k =~ /^(graph|edge|x|y|type)\z/;
$self->{$k} = $args->{$k};
}
$self->_croak("Creating edge cell without a parent edge object")
unless defined $self->{edge};
$self->_croak("Creating edge cell without a type")
unless defined $self->{type};
# take over settings from edge
$self->{style} = $self->{edge}->style();
$self->{class} = $self->{edge}->class();
$self->{graph} = $self->{edge}->{graph};
$self->{group} = $self->{edge}->{group};
weaken($self->{graph});
weaken($self->{group});
$self->{att} = $self->{edge}->{att};
# register ourselves at this edge
$self->{edge}->_add_cell ($self, $args->{after}, $args->{before});
$self;
}
sub arrow_count
{
# return 0, 1 or 2, depending on the number of end points
my $self = shift;
return 0 if $self->{edge}->{undirected};
my $count = 0;
my $type = $self->{type};
$count ++ if ($type & EDGE_END_N) != 0;
$count ++ if ($type & EDGE_END_S) != 0;
$count ++ if ($type & EDGE_END_W) != 0;
$count ++ if ($type & EDGE_END_E) != 0;
if ($self->{edge}->{bidirectional})
{
$count ++ if ($type & EDGE_START_N) != 0;
$count ++ if ($type & EDGE_START_S) != 0;
$count ++ if ($type & EDGE_START_W) != 0;
$count ++ if ($type & EDGE_START_E) != 0;
}
$count;
}
sub _make_cross
{
# Upgrade us to a cross-section.
my ($self, $edge, $flags) = @_;
my $type = $self->{type} & EDGE_TYPE_MASK;
$self->_croak("Trying to cross non hor/ver piece at $self->{x},$self->{y}")
if (($type != EDGE_HOR) && ($type != EDGE_VER));
$self->{color} = $self->get_color_attribute('color');
$self->{style_ver} = $edge->style();
$self->{color_ver} = $edge->get_color_attribute('color');
# if we are the VER piece, switch styles around
if ($type == EDGE_VER)
{
($self->{style_ver}, $self->{style}) = ($self->{style},$self->{style_ver});
($self->{color_ver}, $self->{color}) = ($self->{color},$self->{color});
}
$self->{type} = EDGE_CROSS + ($flags || 0);
$self;
}
sub _make_joint
{
# Upgrade us to a joint
( run in 0.557 second using v1.01-cache-2.11-cpan-39bf76dae61 )