Blob Blame History Raw
#==========================================================================
#			   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;