Server IP : 103.119.228.120 / Your IP : 3.143.214.226 Web Server : Apache System : Linux v8.techscape8.com 3.10.0-1160.119.1.el7.tuxcare.els2.x86_64 #1 SMP Mon Jul 15 12:09:18 UTC 2024 x86_64 User : nobody ( 99) PHP Version : 5.6.40 Disable Function : shell_exec,symlink,system,exec,proc_get_status,proc_nice,proc_terminate,define_syslog_variables,syslog,openlog,closelog,escapeshellcmd,passthru,ocinum cols,ini_alter,leak,listen,chgrp,apache_note,apache_setenv,debugger_on,debugger_off,ftp_exec,dl,dll,myshellexec,proc_open,socket_bind,proc_close,escapeshellarg,parse_ini_filepopen,fpassthru,exec,passthru,escapeshellarg,escapeshellcmd,proc_close,proc_open,ini_alter,popen,show_source,proc_nice,proc_terminate,proc_get_status,proc_close,pfsockopen,leak,apache_child_terminate,posix_kill,posix_mkfifo,posix_setpgid,posix_setsid,posix_setuid,dl,symlink,shell_exec,system,dl,passthru,escapeshellarg,escapeshellcmd,myshellexec,c99_buff_prepare,c99_sess_put,fpassthru,getdisfunc,fx29exec,fx29exec2,is_windows,disp_freespace,fx29sh_getupdate,fx29_buff_prepare,fx29_sess_put,fx29shexit,fx29fsearch,fx29ftpbrutecheck,fx29sh_tools,fx29sh_about,milw0rm,imagez,sh_name,myshellexec,checkproxyhost,dosyayicek,c99_buff_prepare,c99_sess_put,c99getsource,c99sh_getupdate,c99fsearch,c99shexit,view_perms,posix_getpwuid,posix_getgrgid,posix_kill,parse_perms,parsesort,view_perms_color,set_encoder_input,ls_setcheckboxall,ls_reverse_all,rsg_read,rsg_glob,selfURL,dispsecinfo,unix2DosTime,addFile,system,get_users,view_size,DirFiles,DirFilesWide,DirPrintHTMLHeaders,GetFilesTotal,GetTitles,GetTimeTotal,GetMatchesCount,GetFileMatchesCount,GetResultFiles,fs_copy_dir,fs_copy_obj,fs_move_dir,fs_move_obj,fs_rmdir,SearchText,getmicrotime MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/local/share/perl5/Graph/Easy/Edge/ |
Upload File : |
############################################################################# # 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, ARROW_DOWN => 3, }; use constant { EDGE_ARROW_HOR => EDGE_END_E() + EDGE_END_W(), EDGE_ARROW_VER => EDGE_END_N() + EDGE_END_S(), # shortcuts to not need to write EDGE_HOR + EDGE_START_W + EDGE_END_E EDGE_SHORT_E => EDGE_HOR + EDGE_END_E + EDGE_START_W, # |-> start/end at this cell EDGE_SHORT_S => EDGE_VER + EDGE_END_S + EDGE_START_N, # v start/end at this cell EDGE_SHORT_W => EDGE_HOR + EDGE_END_W + EDGE_START_E, # <-| start/end at this cell EDGE_SHORT_N => EDGE_VER + EDGE_END_N + EDGE_START_S, # ^ start/end at this cell EDGE_SHORT_BD_EW => EDGE_HOR + EDGE_END_E + EDGE_END_W, # <-> start/end at this cell EDGE_SHORT_BD_NS => EDGE_VER + EDGE_END_S + EDGE_END_N, # ^ # | start/end at this cell # v EDGE_SHORT_UN_EW => EDGE_HOR + EDGE_START_E + EDGE_START_W, # -- EDGE_SHORT_UN_NS => EDGE_VER + EDGE_START_S + EDGE_START_N, # | EDGE_LOOP_NORTH => EDGE_N_W_S + EDGE_END_S + EDGE_START_N + EDGE_LABEL_CELL, EDGE_LOOP_SOUTH => EDGE_S_W_N + EDGE_END_N + EDGE_START_S + EDGE_LABEL_CELL, EDGE_LOOP_WEST => EDGE_W_S_E + EDGE_END_E + EDGE_START_W + EDGE_LABEL_CELL, EDGE_LOOP_EAST => EDGE_E_S_W + EDGE_END_W + EDGE_START_E + EDGE_LABEL_CELL, }; ############################################################################# @EXPORT_OK = qw/ EDGE_START_E EDGE_START_W EDGE_START_N EDGE_START_S EDGE_END_E EDGE_END_W EDGE_END_N EDGE_END_S EDGE_SHORT_E EDGE_SHORT_W EDGE_SHORT_N EDGE_SHORT_S EDGE_SHORT_BD_EW EDGE_SHORT_BD_NS EDGE_SHORT_UN_EW EDGE_SHORT_UN_NS EDGE_HOR EDGE_VER EDGE_CROSS EDGE_HOLE EDGE_N_E EDGE_N_W EDGE_S_E EDGE_S_W EDGE_S_E_W EDGE_N_E_W EDGE_E_N_S EDGE_W_N_S EDGE_LOOP_NORTH EDGE_LOOP_SOUTH EDGE_LOOP_EAST EDGE_LOOP_WEST EDGE_N_W_S EDGE_S_W_N EDGE_E_S_W EDGE_W_S_E EDGE_TYPE_MASK EDGE_FLAG_MASK EDGE_ARROW_MASK EDGE_START_MASK EDGE_END_MASK EDGE_MISC_MASK EDGE_LABEL_CELL EDGE_SHORT_CELL EDGE_NO_M_MASK ARROW_RIGHT ARROW_LEFT ARROW_UP ARROW_DOWN /; my $edge_types = { EDGE_HOR() => 'horizontal', EDGE_VER() => 'vertical', EDGE_CROSS() => 'crossing', EDGE_N_E() => 'north/east corner', EDGE_N_W() => 'north/west corner', EDGE_S_E() => 'south/east corner', EDGE_S_W() => 'south/west corner', EDGE_S_E_W() => 'joint south to east/west', EDGE_N_E_W() => 'joint north to east/west', EDGE_E_N_S() => 'joint east to north/south', EDGE_W_N_S() => 'joint west to north/south', EDGE_N_W_S() => 'selfloop, northwards', EDGE_S_W_N() => 'selfloop, southwards', EDGE_E_S_W() => 'selfloop, eastwards', EDGE_W_S_E() => 'selfloop, westwards', }; my $flag_types = { EDGE_LABEL_CELL() => 'labeled', EDGE_SHORT_CELL() => 'short', EDGE_START_E() => 'starting east', EDGE_START_W() => 'starting west', EDGE_START_N() => 'starting north', EDGE_START_S() => 'starting south', EDGE_END_E() => 'ending east', EDGE_END_W() => 'ending west', 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 my ($self, $edge, $new_type) = @_; my $type = $self->{type} & EDGE_TYPE_MASK; $self->_croak("Trying to join non hor/ver piece (type: $type) at $self->{x},$self->{y}") if $type >= EDGE_S_E_W; $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}); } print STDERR "# creating joint at $self->{x}, $self->{y} with new type $new_type (old $type)\n" if $self->{graph}->{debug}; $self->{type} = $new_type; $self; } ############################################################################# # conversion to HTML my $edge_end_north = ' <td colspan=2 class="##class## eb" style="##bg####ec##"> </td>' . "\n" . ' <td colspan=2 class="##class## eb" style="##bg####ec##"><span class="su">^</span></td>' . "\n"; my $edge_end_south = ' <td colspan=2 class="##class## eb" style="##bg####ec##"> </td>' . "\n" . ' <td colspan=2 class="##class## eb" style="##bg####ec##"><span class="sv">v</span></td>' . "\n"; my $edge_empty_row = ' <td colspan=4 class="##class## eb"></td>'; my $edge_arrow_west_upper = '<td rowspan=2 class="##class## eb" style="##ec####bg##"><span class="shl"><</span></td>' . "\n"; my $edge_arrow_west_lower = '<td rowspan=2 class="##class## eb"> </td>' . "\n"; my $edge_arrow_east_upper = '<td rowspan=2 class="##class## eb" style="##ec####bg##"><span class="sh">></span></td>' . "\n"; my $edge_arrow_east_lower = '<td rowspan=2 class="##class## eb"></td>' . "\n"; my $edge_html = { # The " " in empty table cells with borders are here to make IE display # the border. I so hate browser bugs :-( EDGE_S_E() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>', '', ' <td colspan=2 rowspan=2 class="##class## eb"></td>'. "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', '', ], EDGE_S_E() + EDGE_START_E() + EDGE_END_S() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td rowspan=4 class="##class## el"></td>', '', ' <td colspan=2 class="##class## eb"></td>'. "\n" . ' <td class="##class## eb" style="border-left: ##border##;"> </td>', $edge_end_south, ], EDGE_S_E() + EDGE_START_E() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td rowspan=4 class="##class## el"></td>', '', ' <td colspan=2 rowspan=2 class="##class## eb"></td>'. "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', '', ], EDGE_S_E() + EDGE_END_E() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td rowspan=4 class="##class##"##edgecolor##><span class="sa">></span></td>', '', ' <td colspan=2 rowspan=2 class="##class## eb"></td>'. "\n" . ' <td rowspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', '', ], EDGE_S_E() + EDGE_START_S() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>', '', ' <td colspan=2 class="##class## eb"></td>'. "\n" . ' <td colspan=2 class="##class## eb" style="border-left: ##border##;"> </td>' . "\n", $edge_empty_row, ], EDGE_S_E() + EDGE_START_S() + EDGE_END_E() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>'. ' <td rowspan=4 class="##class##"##edgecolor##><span class="sa">></span></td>', '', ' <td colspan=2 rowspan=2 class="##class## eb"></td>'. "\n" . ' <td class="##class## eb" style="border-left: ##border##;"> </td>' . "\n", ' <td class="##class## eb"></td>', ], EDGE_S_E() + EDGE_END_S() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>', '', ' <td colspan=2 class="##class## eb"></td>'. "\n" . ' <td colspan=2 class="##class## eb" style="border-left: ##border##;"> </td>' . "\n", $edge_end_south, ], EDGE_S_E() + EDGE_END_S() + EDGE_END_E() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td rowspan=4 class="##class## ha"##edgecolor##><span class="sa">></span></td>', '', ' <td colspan=2 class="##class## eb"></td>'. "\n" . ' <td class="##class## eb" style="border-left: ##border##;"> </td>' . "\n", ' <td colspan=3 class="##class## v"##edgecolor##>v</td>', ], ########################################################################### ########################################################################### # S_W EDGE_S_W() => [ ' <td colspan=2 rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb"></td>', '', ' <td colspan=2 rowspan=2 class="##class## eb"></td>'. "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', '', ], EDGE_S_W() + EDGE_START_W() => [ ' <td rowspan=2 class="##class## el"></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb"></td>', '', ' <td colspan=2 rowspan=2 class="##class## eb"></td>'. "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', '', ], EDGE_S_W() + EDGE_END_W() => [ ' <td rowspan=2 class="##class## va"##edgecolor##><span class="shl"><</span></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb"></td>', '', ' <td colspan=2 rowspan=2 class="##class## eb"></td>'. "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', '', ], EDGE_S_W() + EDGE_START_S() => [ ' <td colspan=2 rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb"></td>', '', ' <td colspan=2 class="##class## eb"></td>'. "\n" . ' <td colspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', $edge_empty_row, ], EDGE_S_W() + EDGE_END_S() => [ ' <td colspan=2 rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb"></td>', '', ' <td colspan=2 class="##class## eb"></td>'. "\n" . ' <td colspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', $edge_end_south, ], EDGE_S_W() + EDGE_START_W() + EDGE_END_S() => [ ' <td rowspan=2 class="##class## el"></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb"></td>', '', ' <td colspan=2 class="##class## eb"></td>'. "\n" . ' <td colspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', $edge_end_south, ], EDGE_S_W() + EDGE_START_S() + EDGE_END_W() => [ ' <td rowspan=3 class="##class## sh"##edgecolor##><</td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb"></td>', '', ' <td class="##class## eb"></td>'. "\n" . ' <td colspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', $edge_empty_row, ], ########################################################################### ########################################################################### # N_W EDGE_N_W() => [ ' <td colspan=2 rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', '', ' <td colspan=4 rowspan=2 class="##class## eb"></td>', '', ], EDGE_N_W() + EDGE_START_N() => [ $edge_empty_row, ' <td colspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', '', ' <td colspan=4 rowspan=2 class="##class## eb"></td>', ], EDGE_N_W() + EDGE_END_N() => [ $edge_end_north, ' <td colspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', ' <td colspan=4 rowspan=2 class="##class## eb"></td>', '', ], EDGE_N_W() + EDGE_END_N() + EDGE_START_W() => [ $edge_end_north, ' <td rowspan=3 class="##class## eb"></td>'. ' <td class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 class="##class## eb" style="border-left: ##border##;"> </td>', ' <td colspan=4 rowspan=2 class="##class## eb"></td>', '', ], EDGE_N_W() + EDGE_START_W() => [ ' <td rowspan=2 class="##class## el"></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##border##;"> </td>' . "\n", '', ' <td colspan=4 rowspan=2 class="##class## eb"></td>', '', ], EDGE_N_W() + EDGE_END_W() => [ ' <td rowspan=4 class="##class## sh"##edgecolor##><</td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##;"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##border##;"> </td>' . "\n", '', ' <td colspan=3 rowspan=2 class="##class## eb"></td>', '', ], ########################################################################### ########################################################################### # N_E EDGE_N_E() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-bottom: ##border##; border-left: ##border##;"> </td>', '', ' <td colspan=4 rowspan=2 class="##class## eb"></td>', '', ], EDGE_N_E() + EDGE_START_E() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##; border-left: ##border##;"> </td>' . "\n" . ' <td rowspan=4 class="##class## el"></td>', '', ' <td colspan=3 rowspan=2 class="##class## eb"></td>', '', ], EDGE_N_E() + EDGE_END_E() => [ ' <td colspan=2 rowspan=2 class="##class## eb"></td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-bottom: ##border##; border-left: ##border##;"> </td>' . "\n" . ' <td rowspan=4 class="##class## va"##edgecolor##><span class="sa">></span></td>', '', ' <td colspan=3 rowspan=2 class="##class## eb"></td>', '', ], EDGE_N_E() + EDGE_END_E() + EDGE_START_N() => [ $edge_empty_row, ' <td colspan=2 class="##class## eb"></td>' . "\n" . ' <td class="##class## eb" style="border-bottom: ##border##; border-left: ##border##;"> </td>' . "\n" . ' <td rowspan=3 class="##class## va"##edgecolor##><span class="sa">></span></td>', ' <td colspan=3 rowspan=2 class="##class## eb"></td>', '', ], EDGE_N_E() + EDGE_START_E() + EDGE_END_N() => [ $edge_end_north, ' <td colspan=2 class="##class## eb"></td>' . "\n" . ' <td class="##class## eb" style="border-bottom: ##border##; border-left: ##border##;"> </td>' . "\n" . ' <td rowspan=3 class="##class## eb"> </td>', ' <td colspan=3 rowspan=2 class="##class## eb"></td>', '', ], EDGE_N_E() + EDGE_START_N() => [ $edge_empty_row, ' <td colspan=2 rowspan=3 class="##class## eb"></td>' . "\n" . ' <td colspan=2 class="##class## eb" style="border-bottom: ##border##; border-left: ##border##;"> </td>', ' <td colspan=2 class="##class## eb"></td>', '', ], EDGE_N_E() + EDGE_END_N() => [ $edge_end_north, ' <td colspan=2 rowspan=3 class="##class## eb"></td>' . "\n" . ' <td colspan=2 class="##class## eb" style="border-bottom: ##border##; border-left: ##border##;"> </td>', '', ' <td colspan=2 class="##class## eb"></td>', ], ########################################################################### ########################################################################### # self loops EDGE_LOOP_NORTH() - EDGE_LABEL_CELL() => [ '<td rowspan=2 class="##class## eb"> </td>' . "\n". ' <td colspan=2 rowspan=2 class="##class## lh" style="border-bottom: ##border##;##lc####bg##">##label##</td>' . "\n" . ' <td rowspan=2 class="##class## eb"> </td>', '', '<td class="##class## eb"> </td>' . "\n". ' <td colspan=2 class="##class## eb" style="border-left: ##border##;##bg##"> </td>'."\n". ' <td class="##class## eb" style="border-left: ##border##;##bg##"> </td>', '<td colspan=2 class="##class## v" style="##bg##"##edgecolor##>v</td>' . "\n" . ' <td colspan=2 class="##class## eb"> </td>', ], EDGE_LOOP_SOUTH() - EDGE_LABEL_CELL() => [ '<td colspan=2 class="##class## v" style="##bg##"##edgecolor##>^</td>' . "\n" . ' <td colspan=2 class="##class## eb"> </td>', '<td rowspan=2 class="##class## eb"> </td>' . "\n". ' <td colspan=2 rowspan=2 class="##class## lh" style="border-left:##border##;border-bottom:##border##;##lc####bg##">##label##</td>'."\n". ' <td rowspan=2 class="##class## eb" style="border-left:##border##;##bg##"> </td>', '', '<td colspan=4 class="##class## eb"> </td>', ], EDGE_LOOP_WEST() - EDGE_LABEL_CELL() => [ $edge_empty_row. ' <td colspan=2 rowspan=2 class="##class## lh" style="border-bottom: ##border##;##lc####bg##">##label##</td>'."\n". ' <td rowspan=2 class="##class## eb"> </td>', '', '<td colspan=2 class="##class## eb" style="border-left: ##border##; border-bottom: ##border##;##bg##"> </td>' . "\n". ' <td rowspan=2 class="##class## va" style="##bg##"##edgecolor##><span class="sa">></span></td>', '<td colspan=2 class="##class## eb"> </td>', ], EDGE_LOOP_EAST() - EDGE_LABEL_CELL() => [ '<td rowspan=2 class="##class## eb"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## lh" style="border-bottom: ##border##;##lc####bg##">##label##</td>' ."\n". ' <td rowspan=2 class="##class## eb"> </td>', '', '<td rowspan=2 class="##class## va" style="##bg##"##edgecolor##><span class="sh"><</span></td>' ."\n". ' <td colspan=2 class="##class## eb" style="border-bottom: ##border##;##bg##"> </td>'."\n". ' <td class="##class## eb" style="border-left: ##border##;##bg##"> </td>', '<td colspan=3 class="##class## eb"> </td>', ], ########################################################################### ########################################################################### # joints ########################################################################### # E_N_S EDGE_E_N_S() => [ '<td colspan=2 rowspan=2 class="##class## eb"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left:##borderv##;border-bottom:##border##;##bg##"> </td>', '', '<td colspan=2 rowspan=2 class="##class## eb"> </td>' ."\n". ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##borderv##;##bg##"> </td>', '', ], EDGE_E_N_S() + EDGE_END_E() => [ '<td colspan=2 rowspan=2 class="##class## eb"> </td>' . "\n" . ' <td rowspan=2 class="##class## eb" style="border-left: ##borderv##; border-bottom: ##border##;##bg##"> </td>' . "\n" . ' <td rowspan=4 class="##class## va"##edgecolor##><span class="sa">></span></td>', '', '<td colspan=2 rowspan=2 class="##class## eb"> </td>' ."\n". ' <td rowspan=2 class="##class## eb" style="border-left: ##borderv##;##bg##"> </td>', '', ], ########################################################################### # W_N_S EDGE_W_N_S() => [ '<td colspan=2 rowspan=2 class="##class## eb" style="border-bottom: ##border##;##bg##"> </td>' . "\n" . ' <td colspan=2 rowspan=4 class="##class## eb" style="border-left: ##borderv##;##bg##"> </td>', '', '<td colspan=2 rowspan=2 class="##class## eb"> </td>', '', ], ########################################################################### # S_E_W EDGE_S_E_W() => [ '<td colspan=4 rowspan=2 class="##class## eb" style="border-bottom: ##border##;##bg##"> </td>', '', '<td colspan=2 rowspan=2 class="##class## eb"> </td>' ."\n". ' <td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##borderv##;##bg##"> </td>', '', ], EDGE_S_E_W() + EDGE_END_S() => [ '<td colspan=4 rowspan=2 class="##class## eb" style="border-bottom: ##border##;##bg##"> </td>', '', '<td colspan=2 class="##class## eb"> </td>' ."\n". ' <td colspan=2 class="##class## eb" style="border-left: ##borderv##;##bg##"> </td>', $edge_end_south, ], EDGE_S_E_W() + EDGE_START_S() => [ '<td colspan=4 rowspan=2 class="##class## eb" style="border-bottom: ##border##;##bg##"> </td>', '', '<td colspan=2 class="##class## eb"> </td>' ."\n". ' <td colspan=2 class="##class## eb" style="border-left: ##borderv##;##bg##"> </td>', ' <td colspan=4 class="##class## eb"></td>', ], EDGE_S_E_W() + EDGE_START_W() => [ '<td rowspan=4 class="##class## el"></td>' . "\n" . '<td colspan=3 rowspan=2 class="##class## eb" style="border-bottom: ##border##;##bg##"> </td>', '', '<td rowspan=2 class="##class## eb"> </td>' ."\n". ' <td rowspan=2 class="##class## eb" style="border-left: ##borderv##;##bg##"> </td>', '', ], EDGE_S_E_W() + EDGE_END_E() => [ '<td colspan=3 rowspan=2 class="##class## eb" style="border-bottom: ##border##;##bg##"> </td>' . "\n" . ' <td rowspan=4 class="##class## va"##edgecolor##><span class="sa">></span></td>', '', '<td colspan=2 rowspan=2 class="##class## eb"> </td>' ."\n". ' <td rowspan=2 class="##class## eb" style="border-left: ##borderv##;##bg##"> </td>', '', ], EDGE_S_E_W() + EDGE_END_W() => [ $edge_arrow_west_upper . '<td colspan=3 rowspan=2 class="##class## eb" style="border-bottom: ##border##;##bg##"> </td>' . "\n" , '', '<td colspan=2 rowspan=2 class="##class## eb"> </td>' ."\n" . '<td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##borderv##;##bg##"> </td>', ], ########################################################################### # N_E_W EDGE_N_E_W() => [ ' <td colspan=2 rowspan=2 class="##class## eb" style="border-bottom: ##borderv##;##bg##"> </td>' ."\n". '<td colspan=2 rowspan=2 class="##class## eb" style="border-left: ##borderv##; border-bottom: ##border##;##bg##"> </td>', '', '<td colspan=4 rowspan=2 class="##class## eb"> </td>', '', ], EDGE_N_E_W() + EDGE_END_N() => [ $edge_end_north, ' <td colspan=2 class="##class## eb" style="border-bottom: ##borderv##;##bg##"> </td>' ."\n". '<td colspan=2 class="##class## eb" style="border-left: ##borderv##; border-bottom: ##border##;##bg##"> </td>', '', '<td colspan=4 rowspan=2 class="##class## eb"> </td>', '', ], EDGE_N_E_W() + EDGE_START_N() => [ $edge_empty_row, ' <td colspan=2 class="##class## eb" style="border-bottom: ##borderv##;##bg##"> </td>' ."\n". '<td colspan=2 class="##class## eb" style="border-left: ##borderv##; border-bottom: ##border##;##bg##"> </td>', '', '<td colspan=4 rowspan=2 class="##class## eb"> </td>', '', ], }; sub _html_edge_hor { # Return HTML code for a horizontal edge (with all start/end combinations) # as [], with code for each table row. my ($self, $as) = @_; my $s_flags = $self->{type} & EDGE_START_MASK; my $e_flags = $self->{type} & EDGE_END_MASK; $e_flags = 0 if $as eq 'none'; # XXX TODO: we could skip the output of "eb" parts when this edge doesn't belong # to a group. my $rc = [ ' <td colspan=##mod## rowspan=2 class="##class## lh" style="border-bottom: ##border##;##lc####bg##">##label##</td>', '', '<td colspan=##mod## rowspan=2 class="##class## eb"> </td>', '', ]; # This assumes that only 2 end/start flags are set at the same time: my $mod = 4; # modifier if ($s_flags & EDGE_START_W) { $mod--; $rc->[0] = '<td rowspan=4 class="##class## el"></td>' . "\n" . $rc->[0]; }; if ($s_flags & EDGE_START_E) { $mod--; $rc->[0] .= "\n " . '<td rowspan=4 class="##class## el"></td>'; }; if ($e_flags & EDGE_END_W) { $mod--; $rc->[0] = $edge_arrow_west_upper . $rc->[0]; $rc->[2] = $edge_arrow_west_lower . $rc->[2]; } if ($e_flags & EDGE_END_E) { $mod--; $rc->[0] .= "\n " . $edge_arrow_east_upper; $rc->[2] .= "\n " . $edge_arrow_east_lower; }; # cx == 1: mod = 2..4, cx == 2: mod = 6..8, etc. $self->{cx} ||= 1; $mod = $self->{cx} * 4 - 4 + $mod; for my $e (@$rc) { $e =~ s/##mod##/$mod/g; } $rc; } sub _html_edge_ver { # Return HTML code for a vertical edge (with all start/end combinations) # as [], with code for each table row. my ($self, $as) = @_; my $s_flags = $self->{type} & EDGE_START_MASK; my $e_flags = $self->{type} & EDGE_END_MASK; $e_flags = 0 if $as eq 'none'; my $mod = 4; # modifier # normal vertical edge with no start/end flags my $rc = [ '<td colspan=2 rowspan=##mod## class="##class## el"> </td>' . "\n " . '<td colspan=2 rowspan=##mod## class="##class## lv" style="border-left: ##border##;##lc####bg##">##label##</td>' . "\n", '', '', '', ]; # flag north if ($s_flags & EDGE_START_N) { $mod--; unshift @$rc, '<td colspan=4 class="##class## eb"></td>' . "\n"; delete $rc->[-1]; } elsif ($e_flags & EDGE_END_N) { $mod--; unshift @$rc, $edge_end_north; delete $rc->[-1]; } # flag south if ($s_flags & EDGE_START_S) { $mod--; $rc->[3] = '<td colspan=4 class="##class## eb"></td>' . "\n" } if ($e_flags & EDGE_END_S) { $mod--; $rc->[3] = $edge_end_south; } $self->{cy} ||= 1; $mod = $self->{cy} * 4 - 4 + $mod; for my $e (@$rc) { $e =~ s/##mod##/$mod/g; } $rc; } sub _html_edge_cross { # Return HTML code for a crossingedge (with all start/end combinations) # as [], with code for each table row. my ($self, $N, $S, $E, $W) = @_; # my $s_flags = $self->{type} & EDGE_START_MASK; # my $e_flags = $self->{type} & EDGE_END_MASK; my $rc = [ ' <td colspan=2 rowspan=2 class="##class## eb el" style="border-bottom: ##border##"> </td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb el" style="border-left: ##borderv##; border-bottom: ##border##"> </td>' . "\n", '', ' <td colspan=2 rowspan=2 class="##class## eb el"></td>' . "\n" . ' <td colspan=2 rowspan=2 class="##class## eb el" style="border-left: ##borderv##"> </td>' . "\n", '', ]; $rc; } sub as_html { my ($self) = shift; my $type = $self->{type} & EDGE_NO_M_MASK; my $style = $self->{style}; # none, open, filled, closed my $as; $as = 'none' if $self->{edge}->{undirected}; $as = $self->attribute('arrowstyle') unless $as; # triangle, box, dot, inv, diamond, line etc. my $ashape; $ashape = 'triangle' if $self->{edge}->{undirected}; $ashape = $self->attribute('arrowshape') unless $ashape; my $code = $edge_html->{$type}; if (!defined $code) { my $t = $self->{type} & EDGE_TYPE_MASK; if ($style ne 'invisible') { $code = $self->_html_edge_hor($as) if $t == EDGE_HOR; $code = $self->_html_edge_ver($as) if $t == EDGE_VER; $code = $self->_html_edge_cross($as) if $t == EDGE_CROSS; } else { $code = [ ' <td colspan=4 rowspan=4 class="##class##"> </td>' ]; } if (!defined $code) { $code = [ ' <td colspan=4 rowspan=4 class="##class##">???</td>' ]; warn ("as_html: Unimplemented edge type $self->{type} ($type) at $self->{x},$self->{y} " . edge_type($self->{type})); } } my $id = $self->{graph}->{id}; my $color = $self->get_color_attribute('color'); my $label = ''; my $label_style = ''; # only include the label if we are the label cell if ($style ne 'invisible' && ($self->{type} & EDGE_LABEL_CELL)) { my $switch_to_center; ($label,$switch_to_center) = $self->_label_as_html(); # replace linebreaks by <br>, but remove extra spaces $label =~ s/\s*\\n\s*/<br \/>/g; my $label_color = $self->raw_color_attribute('labelcolor') || $color; $label_color = '' if $label_color eq '#000000'; $label_style = "color: $label_color;" if $label_color; my $font = $self->attribute('font') || ''; $font = '' if $font eq ($self->default_attribute('font') || ''); $label_style = "font-family: $font;" if $font; $label_style .= $self->text_styles_as_css(1,1) unless $label eq ''; $label_style =~ s/^\s*//; my $link = $self->link(); if ($link ne '') { # encode critical entities $link =~ s/\s/\+/g; # space $link =~ s/'/%27/g; # single-quote # put the style on the link $label_style = " style='$label_style'" if $label_style; $label = "<a href='$link'$label_style>$label</a>"; $label_style = ''; } } # without , IE doesn't draw the cell-border nec. for edges $label = ' ' unless $label ne ''; ########################################################################### # get the border styles/colors: # width for the edge is "2px" my $bow = '2'; my $border = Graph::Easy::_border_attribute_as_html( $self->{style}, $bow, $color); my $border_v = $border; if (($self->{type} & EDGE_TYPE_MASK) == EDGE_CROSS) { $border_v = Graph::Easy::_border_attribute_as_html( $self->{style_ver}, $bow, $self->{color_ver}); } ########################################################################### my $edge_color = ''; $edge_color = " color: $color;" if $color; # If the group doesn't have a fill attribute, then it is defined in the CSS # of the group, and since we get the same class, we can skip the background. # But if the group has a fill, we need to use this as override. # The idea behind is to omit the "background: #daffff;" as much as possible. my $bg = $self->attribute('background') || ''; my $group = $self->{edge}->{group}; $bg = '' if $bg eq 'inherit'; $bg = $group->{att}->{fill} if $group->{att}->{fill} && $bg eq ''; $bg = '' if $bg eq 'inherit'; $bg = " background: $bg;" if $bg; my $title = $self->title(); $title =~ s/"//g; # replace quotation marks $title = " title=\"$title\"" if $title ne ''; # add mouse-over title ########################################################################### # replace templates require Graph::Easy::As_ascii if $as ne 'none'; # for _unicode_arrow() # replace borderv with the border for the vertical edge on CROSS sections $border =~ s/\s+/ /g; # collapse multiple spaces $border_v =~ s/\s+/ /g; my $cl = $self->class(); $cl =~ s/\./_/g; # group.cities => group_cities my $rc; for my $a (@$code) { if (ref($a)) { for my $c (@$a) { push @$rc, $self->_format_td($c, $border, $border_v, $label_style, $edge_color, $bg, $as, $ashape, $title, $label, $cl); } } else { push @$rc, $self->_format_td($a, $border, $border_v, $label_style, $edge_color, $bg, $as, $ashape, $title, $label, $cl); } } $rc; } sub _format_td { my ($self, $c, $border, $border_v, $label_style, $edge_color, $bg, $as, $ashape, $title, $label, $cl) = @_; # insert 'style="##bg##"' unless there is already a style $c =~ s/( e[bl]")(>( )?<\/td>)/$1 style="##bg##"$2/g; # insert missing "##bg##" $c =~ s/style="border/style="##bg##border/g; $c =~ s/##class##/$cl/g; $c =~ s/##border##/$border/g; $c =~ s/##borderv##/$border_v/g; $c =~ s/##lc##/$label_style/g; $c =~ s/##edgecolor##/ style="$edge_color"/g; $c =~ s/##ec##/$edge_color/g; $c =~ s/##bg##/$bg/g; $c =~ s/ style=""//g; # remove empty styles # remove arrows if edge is undirected $c =~ s/>(v|\^|<|>)/>/g if $as eq 'none'; # insert "nice" looking Unicode arrows $c =~ s/>(v|\^|<|>)/'>' . $self->_unicode_arrow($ashape, $as, $1); /eg; # insert the label last, other "v" as label might get replaced above $c =~ s/>##label##/$title>$label/; # for empty labels use a different class $c =~ s/ lh"/ eb"/ if $label eq ''; $c .= "\n" unless $c =~ /\n\z/; $self->quoted_comment() . $c; } sub class { my $self = shift; my $c = $self->{class} . ($self->{cell_class} || ''); $c = $self->{edge}->{group}->class() . ' ' . $c if ref($self->{edge}->{group}); $c; } sub group { # return the group we belong to as the group of our parent-edge my $self = shift; $self->{edge}->{group}; } ############################################################################# # accessor methods sub type { # get/set type of this path element # type - EDGE_START, EDGE_END, EDGE_HOR, EDGE_VER, etc my ($self,$type) = @_; if (defined $type) { if (defined $type && $type < 0 || $type > EDGE_MAX_TYPE) { require Carp; Carp::confess ("Cell type $type for cell $self->{x},$self->{y} is not valid."); } $self->{type} = $type; } $self->{type}; } ############################################################################# # For rendering this path element as ASCII, we need to correct our width based # on whether we have a border or not. But this is only known after parsing is # complete. sub _correct_size { my ($self,$format) = @_; return if defined $self->{w}; # min-size is this $self->{w} = 5; $self->{h} = 3; # make short cell pieces very small if (($self->{type} & EDGE_SHORT_CELL) != 0) { $self->{w} = 1; $self->{h} = 1; return; } my $arrows = ($self->{type} & EDGE_ARROW_MASK); my $type = ($self->{type} & EDGE_TYPE_MASK); if ($self->{edge}->{bidirectional} && $arrows != 0) { $self->{w}++ if $type == EDGE_HOR; $self->{h}++ if $type == EDGE_VER; } # make joints bigger if they got arrows my $ah = $self->{type} & EDGE_ARROW_HOR; my $av = $self->{type} & EDGE_ARROW_VER; $self->{w}++ if $ah && ($type == EDGE_S_E_W || $type == EDGE_N_E_W); $self->{h}++ if $av && ($type == EDGE_E_N_S || $type == EDGE_W_N_S); my $style = $self->{edge}->attribute('style') || 'solid'; # make the edge to display ' ..-> ' instead of ' ..> ': $self->{w}++ if $style eq 'dot-dot-dash'; if ($type >= EDGE_LOOP_TYPE) { # +---+ # | V # + # +--> | # | | # +--- | # + $self->{w} = 7; $self->{w} = 8 if $type == EDGE_N_W_S || $type == EDGE_S_W_N; $self->{h} = 3; $self->{h} = 5 if $type != EDGE_N_W_S && $type != EDGE_S_W_N; } if ($self->{type} == EDGE_HOR) { $self->{w} = 0; } elsif ($self->{type} == EDGE_VER) { $self->{h} = 0; } elsif ($self->{type} & EDGE_LABEL_CELL) { # edges do not have borders my ($w,$h) = $self->dimensions(); $h-- unless $h == 0; $h += $self->{h}; $w += $self->{w}; $self->{w} = $w; $self->{h} = $h; } } ############################################################################# # attribute handling sub attribute { my ($self, $name) = @_; my $edge = $self->{edge}; # my $native = $edge->{att}->{$name}; # return $native if defined $native && $native ne 'inherit'; # shortcut, look up the attribute directly return $edge->{att}->{$name} if defined $edge->{att}->{$name} && $edge->{att}->{$name} ne 'inherit'; return $edge->attribute($name); # XXX TODO This does not work, since caching the attribute doesn't get invalidated # upon set_attribute(). # $edge->{cache} = {} unless exists $edge->{cache}; # $edge->{cache}->{att} = {} unless exists $edge->{cache}->{att}; # # my $cache = $edge->{cache}->{att}; # return $cache->{$name} if exists $cache->{$name}; # # my $rc = $edge->attribute($name); # # only cache values that weren't inherited to avoid cache problems # $cache->{$name} = $rc unless defined $native && $native eq 'inherit'; # # $rc; } 1; ############################################################################# ############################################################################# package Graph::Easy::Edge::Cell::Empty; require Graph::Easy::Node::Cell; our @ISA = qw/Graph::Easy::Node::Cell/; #use vars qw/$VERSION/; our $VERSION = '0.76'; use constant isa_cell => 1; 1; __END__ =head1 NAME Graph::Easy::Edge::Cell - A cell in an edge in Graph::Easy =head1 SYNOPSIS use Graph::Easy; my $ssl = Graph::Easy::Edge->new( label => 'encrypted connection', style => 'solid', color => 'red', ); my $src = Graph::Easy::Node->new( 'source' ); my $dst = Graph::Easy::Node->new( 'destination' ); $graph = Graph::Easy->new(); $graph->add_edge($src, $dst, $ssl); print $graph->as_ascii(); =head1 DESCRIPTION A C<Graph::Easy::Edge::Cell> represents an edge between two (or more) nodes in a simple graph. Each edge has a direction (from source to destination, or back and forth), plus a style (line width and style), colors etc. It can also have a name, e.g. a text label associated with it. There should be no need to use this package directly. =head1 METHODS =head2 error() $last_error = $edge->error(); $cvt->error($error); # set new messages $cvt->error(''); # clear error Returns the last error message, or '' for no error. =head2 as_ascii() my $ascii = $path->as_ascii(); Returns the path-cell as a little ascii representation. =head2 as_html() my $html = $path->as_html($tag,$id); eturns the path-cell as HTML code. =head2 label() my $label = $path->label(); Returns the name (also known as 'label') of the path-cell. =head2 style() my $style = $edge->style(); Returns the style of the edge. =head1 EXPORT None by default. Can export the following on request: EDGE_START_E EDGE_START_W EDGE_START_N EDGE_START_S EDGE_END_E EDGE_END_W EDGE_END_N EDGE_END_S EDGE_SHORT_E EDGE_SHORT_W EDGE_SHORT_N EDGE_SHORT_S EDGE_SHORT_BD_EW EDGE_SHORT_BD_NS EDGE_SHORT_UN_EW EDGE_SHORT_UN_NS EDGE_HOR EDGE_VER EDGE_CROSS EDGE_N_E EDGE_N_W EDGE_S_E EDGE_S_W EDGE_S_E_W EDGE_N_E_W EDGE_E_N_S EDGE_W_N_S EDGE_LOOP_NORTH EDGE_LOOP_SOUTH EDGE_LOOP_EAST EDGE_LOOP_WEST EDGE_N_W_S EDGE_S_W_N EDGE_E_S_W EDGE_W_S_E EDGE_TYPE_MASK EDGE_FLAG_MASK EDGE_ARROW_MASK EDGE_START_MASK EDGE_END_MASK EDGE_MISC_MASK ARROW_RIGHT ARROW_LEFT ARROW_UP ARROW_DOWN =head1 SEE ALSO L<Graph::Easy>. =head1 AUTHOR Copyright (C) 2004 - 2007 by Tels L<http://bloodgate.com>. See the LICENSE file for more details. =cut