webgui/lib/WebGUI/Image/Graph/XYGraph.pm

636 lines
14 KiB
Perl

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;