package WebGUI::Image::Graph::XYGraph; use strict; use WebGUI::Image::Graph; use WebGUI::International; use List::Util; use POSIX; our @ISA = qw(WebGUI::Image::Graph); #------------------------------------------------------------------- =head1 configurationForm The configuration form part for this object. See WebGUI::Image::Graph for documentation. =cut sub configurationForm { my ($configForms, $f); my $self = shift; my $i18n = WebGUI::International->new($self->session, 'Image_Graph_XYGraph'); $configForms = $self->SUPER::configurationForm; $f = WebGUI::HTMLForm->new($self->session); $f->trClass('Graph_XYGraph'); $f->integer( name => 'xyGraph_chartWidth', value => $self->getChartWidth, label => $i18n->get('chart width'), ); $f->integer( name => 'xyGraph_chartHeight', value => $self->getChartHeight, label => $i18n->get('chart height'), ); $f->yesNo( name => 'xyGraph_drawLabels', value => $self->showLabels, label => $i18n->get('draw labels'), ); $f->yesNo( name => 'xyGraph_drawAxis', value => $self->showAxis, label => $i18n->get('draw axis'), ); $f->color( name => 'xyGraph_axisColor', value => $self->getAxisColor, label => $i18n->get('axis color'), ); $f->yesNo( name => 'xyGraph_drawRulers', value => $self->showRulers, label => $i18n->get('draw rulers'), ); $f->color( name => 'xyGraph_rulerColor', value => $self->getRulerColor, label => $i18n->get('ruler color'), ); $f->selectBox( name => 'xyGraph_drawMode', value => [ $self->getDrawMode ], label => $i18n->get('draw mode'), multiple=> 0, options => { sideBySide => 'Side by side', stacked => 'Stacked (cumulative', }, ); $f->float( name => 'xyGraph_yGranularity', value => $self->getYGranularity, label => $i18n->get('y granularity'), ); $configForms->{'graph_xygraph'} = $f->printRowsOnly; return $configForms; } #------------------------------------------------------------------- =head1 draw Draws the graph. =cut sub draw { my $self = shift; # Automagically set the chart offset. my $maxYLabelWidth = List::Util::max(map {$self->getLabelDimensions($_)->{width}} @{$self->getYLabels}); $self->setChartOffset({ x=> $maxYLabelWidth + 2*$self->getLabelOffset, y=> $self->getLabelOffset }); $self->drawRulers if ($self->showRulers); $self->drawGraph; $self->drawAxis if ($self->showAxis); $self->drawLabels if ($self->showLabels); } #------------------------------------------------------------------- =head1 drawAxis Draws the axis. =cut sub drawAxis { my $self = shift; my $chartOffset = $self->getChartOffset; $self->image->Draw( primitive => 'Path', stroke => $self->getAxisColor, points => " M ".$chartOffset->{x}.",".$chartOffset->{y}. " L ".$chartOffset->{x}.",".($self->getChartHeight + $chartOffset->{y}). " L ".($self->getChartWidth + $chartOffset->{x}).",".($self->getChartHeight + $chartOffset->{y}) ); } #------------------------------------------------------------------- =head1 drawLabels Draws the labels. =cut sub drawLabels { my $self = shift; my $location = shift; my %anchorPoint = %{$self->getFirstAnchorLocation};# %$location; # Draw x-axis labels foreach (@{$self->getLabel}) { my $text = $self->wrapLabelToWidth($_, $self->getAnchorSpacing->{x}); $self->drawLabel($text, ( alignHorizontal => 'center', alignVertical => 'top', align => 'Center', x => $anchorPoint{x}, y => $anchorPoint{y}, )); $anchorPoint{x} += $self->getAnchorSpacing->{x}; #$groupWidth + $self->getGroupSpacing; $anchorPoint{y} += $self->getAnchorSpacing->{y}; } # Draw y-axis labels $anchorPoint{x} = $self->getChartOffset->{x} - $self->getLabelOffset; $anchorPoint{y} = $self->getChartOffset->{y} + $self->getChartHeight; # for (1 .. $self->getYRange / $self->getYGranularity) { foreach (@{$self->getYLabels}) { $self->drawLabel($_, ( alignHorizontal => 'right', alignVertical => 'center', x => $anchorPoint{x}, #$self->getChartOffset->{x} - $self->getLabelOffset, y => $anchorPoint{y}, #$self->getChartOffset->{y} + $self->getChartHeight - $self->getPixelsPerUnit * $_*$self->getYGranularity, )); $anchorPoint{y} -= $self->getPixelsPerUnit * $self->getYGranularity } } #------------------------------------------------------------------- =head drawRulers Draws the rulers. =cut sub drawRulers { my $self = shift; my $chartOffset = $self->getChartOffset; my $dist = $self->getLabelOffset; for (1 .. $self->getYRange / $self->getYGranularity) { $self->image->Draw( primitive => 'Path', stroke => $self->getRulerColor, points => " M ".$chartOffset->{x}.",".($chartOffset->{y}+$self->getChartHeight - $self->getPixelsPerUnit * $_*$self->getYGranularity). " L ".($chartOffset->{x}+$self->getChartWidth).",".($chartOffset->{y}+$self->getChartHeight - $self->getPixelsPerUnit * $_*$self->getYGranularity) ); } } #------------------------------------------------------------------- =head1 formNamespace Extends the form namespace for this object. See WebGUI::Image::Graph for documentation. =cut sub formNamespace { my $self = shift; return $self->SUPER::formNamespace.'_XYGraph'; } #------------------------------------------------------------------- =head1 getAxisColor Returns the color triplet for the axis. Defaults to '#222222'. =cut sub getAxisColor { my $self = shift; return $self->{_axisProperties}->{axisColor} || '#222222'; } #------------------------------------------------------------------- =head1 getChartHeight Returns the height of the chart. Defaults to 200. =cut sub getChartHeight { my $self = shift; return $self->{_properties}->{chartHeight} || 200; } #------------------------------------------------------------------- =head1 getChartOffset Returns the coordinates of the top-left corner of the chart. he coordinates are contained in a hasref with keys 'x' and 'y'. =cut sub getChartOffset { my $self = shift; return $self->{_properties}->{chartOffset} || { x=>0, y=>0 } } #------------------------------------------------------------------- =head1 getChartWidth Returns the width of the chart. Defaults to 200. =cut sub getChartWidth { my $self = shift; return $self->{_properties}->{chartWidth} || 200; } #------------------------------------------------------------------- =head1 getConfiguration Returns a configuration hashref. See WebGUI::Image::Graph for documentation. =cut sub getConfiguration { my $self = shift; my $config = $self->SUPER::getConfiguration; $config->{xyGraph_chartWidth} = $self->getChartWidth; $config->{xyGraph_chartHeight} = $self->getChartHeight; $config->{xyGraph_drawLabels} = $self->showLabels; $config->{xyGraph_drawAxis} = $self->showAxis; $config->{xyGraph_drawRulers} = $self->showRulers; $config->{xyGraph_drawMode} = $self->getDrawMode; $config->{xyGraph_yGranularity} = $self->getYGranularity; return $config; } #------------------------------------------------------------------- =head1 getDrawMode Returns the drawmode. Currently supported are 'stacked' and 'sideBySide'. Defaults to 'sideBySide'. =cut sub getDrawMode { my $self = shift; return $self->{_barProperties}->{drawMode} || 'sideBySide'; } #------------------------------------------------------------------- =head1 getPixelsPerUnit Returns the number of pixels that correspond with one unit of the dataset values. =cut sub getPixelsPerUnit { my $self = shift; return $self->getChartHeight / $self->getYRange; } #------------------------------------------------------------------- =head1 getRulerColor Returns the color triplet of the rulers in the graph. Defaults to '#777777'. =cut sub getRulerColor { my $self = shift; return $self->{_axisProperties}->{rulerColor} || '#777777'; } #------------------------------------------------------------------- =head1 getYGranularity Returns the granularity of the labels and rulers in the Y direction. Defaults to 10. This is value is in terms of the values in the dataset and has no direct relation to pixels. =cut sub getYGranularity { my $self = shift; return $self->{_properties}->{yGranularity} || 10; } #------------------------------------------------------------------- =head1 getYLabels Returns an arrayref containing the labels for the Y axis. =cut sub getYLabels { my $self = shift; my @yLabels; for (0 .. $self->getYRange / $self->getYGranularity) { push(@yLabels, $_ * $self->getYGranularity); } return \@yLabels; } #------------------------------------------------------------------- =head1 getYRange Returns the maxmimal value of the range that contains a whole number of times the y granularity and is bigger than the maximum value in the dataset. =cut sub getYRange { my $self = shift; return $self->getYGranularity*ceil($self->getMaxValueFromDataset / $self->getYGranularity) || 1; } #------------------------------------------------------------------- =head1 setAxisColor ( color ) Sets the color of the axis to the supplied value. =head2 color The triplet of the color you want to set the axis to. Must have the following form: #ffffff. =cut sub setAxisColor { my $self = shift; my $color = shift; $self->{_axisProperties}->{axisColor} = $color; } #------------------------------------------------------------------- =head1 setChartHeight ( height ) Sets the height of the chart to the specified value. =head2 height The desired height in pixels. =cut sub setChartHeight { my $self = shift; my $height = shift; $self->{_properties}->{chartHeight} = $height; } #------------------------------------------------------------------- =head1 setChartOffset ( location ) Sets the location of the top-left corner of the graph within the image. =head2 location A hashref containing the desired location. Use the 'x' and 'y' as keys for the x and y coordinate respectively. =cut sub setChartOffset { my $self = shift; my $point = shift; $self->{_properties}->{chartOffset} = {%$point}; } #------------------------------------------------------------------- =head1 setChartHeight ( width ) Sets the width of the chart to the specified value. =head2 width The desired width in pixels. =cut sub setChartWidth { my $self = shift; my $width = shift; $self->{_properties}->{chartWidth} =$width; } #------------------------------------------------------------------- =head1 setConfiguration ( config ) Applies the settings in the given configuration hash. See WebGUI::Image::Graph for more information. =head2 config A configuration hash. =cut sub setConfiguration { my $self = shift; my $config = shift; $self->SUPER::setConfiguration($config); $self->setChartWidth($config->{xyGraph_chartWidth}); $self->setChartHeight($config->{xyGraph_chartHeight}); $self->setShowLabels($config->{xyGraph_drawLabels}); $self->setShowAxis($config->{xyGraph_drawAxis}); $self->setShowRulers($config->{xyGraph_drawRulers}); $self->setDrawMode($config->{xyGraph_drawMode}); $self->setYGranularity($config->{xyGraph_yGranularity}); $self->setAxisColor($config->{xyGraph_axisColor}); $self->setRulerColor($config->{xyGraph_rulerColor}); return $config; } #------------------------------------------------------------------- =head1 setDrawMode ( mode ) Set the way the datasets are drawn. Currently supported are 'stacked' and 'sideBySide' which correspond to respectivly cumulative drawing and normal processing. =head2 mode The desired mode. Can be 'sideBySide' or 'stacked'. =cut sub setDrawMode { my $self = shift; my $mode = shift; if ($mode eq 'stacked' || $mode eq 'sideBySide') { $self->{_barProperties}->{drawMode} = $mode; } else { $self->{_barProperties}->{drawMode} = 'sideBySide'; } } #------------------------------------------------------------------- =head1 setRulerColor ( color ) Set the color of the rulers. =head2 color The triplet of the desired ruler color. Must be in the following format: '#ffffff'. =cut sub setRulerColor { my $self = shift; my $color = shift; $self->{_axisProperties}->{rulerColor} = $color; } #------------------------------------------------------------------- =head1 setShowAxis ( boolean ) Set whether or not to draw the axis. =head2 boolean If set to false the axis won't be drawn. =cut sub setShowAxis { my $self = shift; my $yesNo = shift; $self->{_properties}->{showAxis} = $yesNo; } #------------------------------------------------------------------- =head1 setShowLabels ( boolean ) Set whether or not to draw the labels. =head2 boolean If set to false the labels won't be drawn. =cut sub setShowLabels { my $self = shift; my $yesNo = shift; $self->{_properties}->{showLabels} = $yesNo; } #------------------------------------------------------------------- =head1 setShowRulers ( boolean ) Set whether or not to draw the rulers. =head2 boolean If set to false the rulers won't be drawn. =cut sub setShowRulers { my $self = shift; my $yesNo = shift; $self->{_properties}->{showRulers} = $yesNo; } #------------------------------------------------------------------- =head1 setYGranularity ( value ) Sets the y granularity. See getYGranularity for explanation of this concept. =head2 value The granularity in dataset units, not pixels. =cut sub setYGranularity { my $self = shift; my $granularity = shift; $self->{_properties}->{yGranularity} = $granularity; } #------------------------------------------------------------------- =head1 showAxis Returns a boolean indicating whether to draw the axis. =cut sub showAxis { my $self = shift; return 1 unless (defined $self->{_properties}->{showAxis}); return $self->{_properties}->{showAxis}; } #------------------------------------------------------------------- =head1 showLabels Returns a boolean indicating whether to draw the labels. =cut sub showLabels { my $self = shift; return 1 unless (defined $self->{_properties}->{showLabels}); return $self->{_properties}->{showLabels}; } #------------------------------------------------------------------- =head1 showRulers Returns a boolean indicating whether to draw the rulers. =cut sub showRulers { my $self = shift; return 1 unless (defined $self->{_properties}->{showRulers}); return $self->{_properties}->{showRulers}; } 1;