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 )