#========================================================================== # Copyright (c) 1995-1998 Martien Verbruggen #-------------------------------------------------------------------------- # # Name: # GIFgraph::legend.pm # # $Id: legend.pm,v 1.0 1999/02/18 # #========================================================================== package GIFgraph::legend; use strict qw(vars refs subs); use GIFgraph; use GIFgraph::utils qw(:all); @GIFgraph::legend::ISA = qw( GIFgraph ); my %Defaults = ( # Size of the legend markers legend_marker_height => 8, legend_marker_width => 12, legend_spacing => 4, legend_placement => 'BC', # '[B][LCR]' ); { # PUBLIC sub plot_legend($) # GD::Image { my $s = shift; my $g = shift; $s->setup_legend(); $s->draw_legend($g); } sub set_legend(@) # List of legend keys { my $self = shift; $self->set( legend => [@_]); } sub set_legend_font($) # (font name) { my $self = shift; $self->{lgf} = shift; $self->set( lgfw => $self->{lgf}->width, lgfh => $self->{lgf}->height, ); } # PRIVATE # called on construction, by new # use inherited defaults sub initialise() { my $self = shift; $self->SUPER::initialise(); my $key; foreach $key (keys %Defaults) { $self->set( $key => $Defaults{$key} ); } $self->set_legend_font(GD::gdTinyFont); } # # Legend # sub setup_legend() { my $s = shift; return unless defined($s->{legend}); my $maxlen = 0; my $num = 0; # Save some variables $s->{r_margin_abs} = $s->{r_margin}; $s->{b_margin_abs} = $s->{b_margin}; my $legend; foreach $legend (@{$s->{legend}}) { if (defined($legend) and $legend ne "") { my $len = length($legend); $maxlen = ($maxlen > $len) ? $maxlen : $len; $num++; } } $s->{lg_num} = $num; # calculate the height and width of each element my $text_width = $maxlen * $s->{lgfw}; my $legend_height = _max($s->{lgfh}, $s->{legend_marker_height}); $s->{lg_el_width} = $text_width + $s->{legend_marker_width} + 3 * $s->{legend_spacing}; $s->{lg_el_height} = $legend_height + 2 * $s->{legend_spacing}; my ($lg_pos, $lg_align) = split(//, $s->{legend_placement}); if ($lg_pos eq 'R') { # Always work in one column $s->{lg_cols} = 1; $s->{lg_rows} = $num; # Just for completeness, might use this in later versions $s->{lg_x_size} = $s->{lg_cols} * $s->{lg_el_width}; $s->{lg_y_size} = $s->{lg_rows} * $s->{lg_el_height}; # Adjust the right margin for the rest of the graph $s->{r_margin} += $s->{lg_x_size}; # Set the x starting point $s->{lg_xs} = $s->{gifx} - $s->{r_margin}; # Set the y starting point, depending on alignment if ($lg_align eq 'T') { $s->{lg_ys} = $s->{t_margin}; } elsif ($lg_align eq 'B') { $s->{lg_ys} = $s->{gify} - $s->{b_margin} - $s->{lg_y_size}; } else # default 'C' { my $height = $s->{gify} - $s->{t_margin} - $s->{b_margin}; $s->{lg_ys} = int($s->{t_margin} + $height/2 - $s->{lg_y_size}/2) ; } } else # 'B' is the default { # What width can we use my $width = $s->{gifx} - $s->{l_margin} - $s->{r_margin}; (!defined($s->{lg_cols})) and $s->{lg_cols} = int($width/$s->{lg_el_width}); $s->{lg_cols} = _min($s->{lg_cols}, $num); $s->{lg_rows} = int($num/$s->{lg_cols}) + (($num % $s->{lg_cols}) ? 1 : 0); $s->{lg_x_size} = $s->{lg_cols} * $s->{lg_el_width}; $s->{lg_y_size} = $s->{lg_rows} * $s->{lg_el_height}; # Adjust the bottom margin for the rest of the graph $s->{b_margin} += $s->{lg_y_size}; # Set the y starting point $s->{lg_ys} = $s->{gify} - $s->{b_margin}; # Set the x starting point, depending on alignment if ($lg_align eq 'R') { $s->{lg_xs} = $s->{gifx} - $s->{r_margin} - $s->{lg_x_size}; } elsif ($lg_align eq 'L') { $s->{lg_xs} = $s->{l_margin}; } else # default 'C' { $s->{lg_xs} = int($s->{l_margin} + $width/2 - $s->{lg_x_size}/2); } } } sub draw_legend($) # (GD::Image) { my $s = shift; my $g = shift; return unless defined($s->{legend}); my $xl = $s->{lg_xs} + $s->{legend_spacing}; my $y = $s->{lg_ys} + $s->{legend_spacing} - 1; my $i = 0; my $row = 1; my $x = $xl; # start position of current element my $legend; foreach $legend (@{$s->{legend}}) { $i++; my $xe = $x; # position within an element next unless (defined($legend) && $legend ne ""); $s->draw_legend_marker($g, $i, $xe, $y); $xe += $s->{legend_marker_width} + $s->{legend_spacing}; my $ys = int($y + $s->{lg_el_height}/2 - $s->{lgfh}/2); $g->string($s->{lgf}, $xe, $ys, $legend, $s->{tci}); $x += $s->{lg_el_width}; if (++$row > $s->{lg_cols}) { $row = 1; $y += $s->{lg_el_height}; $x = $xl; } } } # This will be virtual; every sub class should define their own # if this one doesn't suffice sub draw_legend_marker($$$$) # (GD::Image, data_set_number, x, y) { my $s = shift; my $g = shift; my $n = shift; my $x = shift; my $y = shift; my $ci = $s->set_clr( $g, $s->pick_data_clr($n) ); $y += int($s->{lg_el_height}/2 - $s->{legend_marker_height}/2); $g->filledRectangle( $x, $y, $x + $s->{legend_marker_width}, $y + $s->{legend_marker_height}, $ci ); $g->rectangle( $x, $y, $x + $s->{legend_marker_width}, $y + $s->{legend_marker_height}, $s->{acci} ); } } # End of package GIFgraph::legend 1;