← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 19:05:14 2015
Reported on Fri Jul 31 19:08:10 2015

Filename/var/www/foswiki11/lib/Foswiki/Plugins/ChartPlugin.pm
StatementsExecuted 55 statements in 2.73ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1311170µs170µsFoswiki::Plugins::ChartPlugin::::commonTagsHandlerFoswiki::Plugins::ChartPlugin::commonTagsHandler
11128µs188µsFoswiki::Plugins::ChartPlugin::::initPluginFoswiki::Plugins::ChartPlugin::initPlugin
11114µs27µsFoswiki::Plugins::ChartPlugin::::BEGIN@39Foswiki::Plugins::ChartPlugin::BEGIN@39
11110µs142µsFoswiki::Plugins::ChartPlugin::::BEGIN@42Foswiki::Plugins::ChartPlugin::BEGIN@42
0000s0sFoswiki::Plugins::ChartPlugin::::ChartPluginFoswiki::Plugins::ChartPlugin::ChartPlugin
0000s0sFoswiki::Plugins::ChartPlugin::::_ParametersFoswiki::Plugins::ChartPlugin::_Parameters
0000s0sFoswiki::Plugins::ChartPlugin::::_init_defaultsFoswiki::Plugins::ChartPlugin::_init_defaults
0000s0sFoswiki::Plugins::ChartPlugin::::_makeChartFoswiki::Plugins::ChartPlugin::_makeChart
0000s0sFoswiki::Plugins::ChartPlugin::::_make_errorFoswiki::Plugins::ChartPlugin::_make_error
0000s0sFoswiki::Plugins::ChartPlugin::::_make_filenameFoswiki::Plugins::ChartPlugin::_make_filename
0000s0sFoswiki::Plugins::ChartPlugin::::_maxFoswiki::Plugins::ChartPlugin::_max
0000s0sFoswiki::Plugins::ChartPlugin::::_minFoswiki::Plugins::ChartPlugin::_min
0000s0sFoswiki::Plugins::ChartPlugin::::_setParametersFoswiki::Plugins::ChartPlugin::_setParameters
0000s0sFoswiki::Plugins::ChartPlugin::::_setTablesFoswiki::Plugins::ChartPlugin::_setTables
0000s0sFoswiki::Plugins::ChartPlugin::::_setTopicContentsFoswiki::Plugins::ChartPlugin::_setTopicContents
0000s0sFoswiki::Plugins::ChartPlugin::::_tablesFoswiki::Plugins::ChartPlugin::_tables
0000s0sFoswiki::Plugins::ChartPlugin::::_timeitFoswiki::Plugins::ChartPlugin::_timeit
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# ChartPlugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/
2#
3# Copyright (C) 2004-2006 Peter Thoeny, Peter@Thoeny.org
4# Plugin written by http://TWiki.org/cgi-bin/view/Main/TaitCyrus
5# Copyright (C) 2008-2011 Foswiki Contributors
6#
7# For licensing info read LICENSE file in the Foswiki root.
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public License
10# as published by the Free Software Foundation; either version 2
11# of the License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details, published at
17# http://www.gnu.org/copyleft/gpl.html
18#
19# As per the GPL, removal of this notice is prohibited.
20#
21# =========================
22#
23# This file contains routines for producing PNG graphic files containing
24# chart information, useful for building dashboards.
25# NOTE: ONLY in the case where an old version of GD (1.19 or earlier) is
26# available will GIF's be created. If the GD version is > 1.19, then
27# PNG's are created.
28#
29# This plugin uses Perl object oriented programming. The ChartPlugin
30# object contains several other Perl objects:
31# Table
32# Parameters
33# Chart
34# In addition to having it's own getter/setters.
35
36# =========================
37package Foswiki::Plugins::ChartPlugin;
38
39256µs240µs
# spent 27µs (14+13) within Foswiki::Plugins::ChartPlugin::BEGIN@39 which was called: # once (14µs+13µs) by Foswiki::Plugin::BEGIN@2.6 at line 39
use strict;
# spent 27µs making 1 call to Foswiki::Plugins::ChartPlugin::BEGIN@39 # spent 13µs making 1 call to strict::import
40
41# =========================
4216µs1132µs
# spent 142µs (10+132) within Foswiki::Plugins::ChartPlugin::BEGIN@42 which was called: # once (10µs+132µs) by Foswiki::Plugin::BEGIN@2.6 at line 50
use vars qw(
# spent 132µs making 1 call to vars::import
43 $installWeb $VERSION $RELEASE $debug
44 $pluginInitialized $initError
45 $defaultType @defaultAreaColors @defaultLineColors
46 $defaultWidth $defaultHeight $defaultBGcolor $defaultNumYGrids
47 $defaultDataValue $defaultScale $defaultGridColor $defaultPointSize
48 $defaultLineWidth
49 $defaultBarLeadingSpace $defaultBarTrailingSpace $defaultBarSpace
501165µs1142µs );
# spent 142µs making 1 call to Foswiki::Plugins::ChartPlugin::BEGIN@42
51
521500nsour $VERSION = '$Rev: 11481 (2011-04-17) $';
531400nsour $RELEASE = '1.6.0';
541300nsour $SHORT_DESCRIPTION = 'Create area, bar, line and scatter charts to visualize table data';
55
561100ns$pluginInitialized = 0;
571200ns$initError = '';
58
59# =========================
60
# spent 188µs (28+160) within Foswiki::Plugins::ChartPlugin::initPlugin which was called: # once (28µs+160µs) by Foswiki::Plugin::__ANON__[/var/www/foswiki11/lib/Foswiki/Plugin.pm:241] at line 234 of /var/www/foswiki11/lib/Foswiki/Plugin.pm
sub initPlugin {
6114µs ( my $topic, my $web, my $user, $installWeb ) = @_;
62
63 # check for Plugins.pm versions
64118µs19µs if( $Foswiki::Plugins::VERSION < 1 ) {
# spent 9µs making 1 call to version::vxs::VCMP
65 &Foswiki::Func::writeWarning( "Version mismatch between ChartPlugin and Plugins.pm" );
66 return 0;
67 }
68
69 # Get plugin debug flag
7013µs1151µs $debug = &Foswiki::Func::getPreferencesFlag( "CHARTPLUGIN_DEBUG" ) || 0;
# spent 151µs making 1 call to Foswiki::Func::getPreferencesFlag
71
721400ns &Foswiki::Func::writeDebug( "- Foswiki::Plugins::ChartPlugin::initPlugin($web.$topic) is OK" ) if $debug;
73
74 # Mark that we are not fully initialized yet. Only get the default
75 # values from the plugin topic page iff a CHART is found in a topic
761300ns $pluginInitialized = 0;
7716µs return 1;
78}
79
80# =========================
81
82# Initialize all default values from the plugin topic page.
83sub _init_defaults {
84 return if $pluginInitialized;
85 $pluginInitialized = 1;
86 require Exporter;
87 foreach my $module qw( GD POSIX
88 Foswiki::Plugins::ChartPlugin::Chart
89 Foswiki::Plugins::ChartPlugin::Parameters
9012.32ms1236µs Foswiki::Plugins::ChartPlugin::Table) {
# spent 236µs making 1 call to CGI::Carp::warn
91 eval "require $module";
92 if ($@) {
93 $initError = "Required Perl module '$module' not found: $@";
94 return;
95 }
96 }
97
98 # Get default chart type
99 $defaultType = Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_TYPE" ) || 'line';
100 # Get default chart values
101 $defaultWidth = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_WIDTH" ) || 60;
102 $defaultHeight = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_HEIGHT" ) || 16;
103 my $defaultAreaColors = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_AREA_COLORS" )
104 || "#FF0000 #FFFF00 #00FF00";
105 @defaultAreaColors = split(/[\s,]+/, $defaultAreaColors);
106 my $defaultLineColors = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_LINE_COLORS" )
107 || "#FFFF00 #FF00FF #00FFFF";
108 @defaultLineColors = split(/[\s,]+/, $defaultLineColors);
109 # Get default chart bgcolor
110 $defaultBGcolor = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_BGCOLOR" ) || '#FFFFFF #FFFFFF';
111 # Get default number of Y axis grids
112 $defaultNumYGrids = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_NUMYGRIDS" ) || 10;
113 # Get default value to use if there is no data seen in the table
114 $defaultDataValue = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_DEFAULTDATA" );
115 # Get default value for the scale (linear/semilog)
116 $defaultScale = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_SCALE" );
117 # Get default grid color.
118 $defaultGridColor = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_GRIDCOLOR" ) || '#000000';
119 # Get default value for the size, in pixels, of drawn data points
120 $defaultPointSize = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_POINTSIZE" ) || 2;
121 # Get default value for the width, in pixels, of drawn lines
122 $defaultLineWidth = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_LINEWIDTH" ) || 3;
123 # Get default value for the leading space before the first bar.
124 $defaultBarLeadingSpace = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_BARLEADINGSPACE" ) || 0;
125 # Get default value for the trailing space after the last bar.
126 $defaultBarTrailingSpace = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_BARTRAILINGSPACE" ) || 0;
127 # Get default value for the space between bars.
128 $defaultBarSpace = &Foswiki::Func::getPreferencesValue( "CHARTPLUGIN_BARSPACE" ) || 0;
129}
130
131# Object constructor for creating a ChartPlugin Perl object. The object is
132# initialized with the current web.topic.
133sub ChartPlugin {
134 my ($currentTopic, $currentWeb, $currentTopicContents) = @_;
135 my $this = {};
136 bless $this;
137 $this->{CURRENT_TOPIC} = $currentTopic;
138 $this->{CURRENT_WEB} = $currentWeb;
139 $this->{CURRENT_TOPICONTENTS} = $currentTopicContents;
140 return $this;
141}
142
143# Setter for storing the Table object
144sub _setTables { my ($this, $table) = @_; $this->{TABLES} = $table; }
145# Getter for Table object
146sub _tables { my ($this) = @_; return $this->{TABLES}; }
147
148# Setter for storing the Parameters object
149sub _setParameters {
150 my ($this, $args) = @_;
151 $this->{PARAMETERS} = Foswiki::Plugins::ChartPlugin::Parameters->new($args);
152}
153
154# Getter for Parameters object
155sub _Parameters { my ($this) = @_; return $this->{PARAMETERS}; }
156
157# This routine sets the specified web.topic as the location from where to
158# get the table information. If the specified web.topic happen to be the
159# same as the web.topic from which the %CHART% was found, then the
160# web.topic contents is already part of the ChartPlugin object so there is
161# nothing to do. Otherwise, this routine will read in the specified
162# web.topic getting its contents and using that as the source to parse out
163# table information.
164sub _setTopicContents {
165 my ($this, $inWeb, $inTopic) = @_;
166 my $topicContents;
167 # If $inWeb and $inTopic match the current web/topic, then we already
168 # have the topic contents in the object so there is nothing to do.
169 # Otherwise, we need to open the specified web/topic and read in its
170 # contents.
171 if ( ($inWeb eq $this->{CURRENT_WEB}) && ($inTopic eq $this->{CURRENT_TOPIC}) ) {
172 $topicContents = $this->{CURRENT_TOPICONTENTS};
173 } else {
174 # A difference, so read in the topic.
175 (my $meta, $topicContents) = Foswiki::Func::readTopic( $inWeb, $inTopic );
176 # Check to make sure the web.topic actually exists. If not, return
177 # undef so the caller can catch the error.
178 return undef if (!defined($topicContents) || $topicContents eq "");
179 $topicContents = Foswiki::Func::expandCommonVariables($topicContents, $inTopic, $inWeb);
180 }
181
182 # Lets parse the specified topic contents looking for tables.
183 $this->_setTables(Foswiki::Plugins::ChartPlugin::Table->new($topicContents));
184 return 1;
185}
186
187# Return the maximum value of the two specified numbers.
188sub _max {
189 my ( $v1, $v2 ) = @_;
190 return $v1 if( $v1 > $v2 );
191 return $v2;
192}
193
194# Return the minimum value of the two specified numbers.
195sub _min {
196 my ( $v1, $v2 ) = @_;
197 return $v1 if( $v1 < $v2 );
198 return $v2;
199}
200
201# Generate the file name in which the graphic file will be placed.
202sub _make_filename {
203 my ( $type, $name ) = @_;
204 # Generate the file name to be created
205 my $fullname;
206 # If GD version 1.19 or earlier, then create gif files else png files.
207 if( $GD::VERSION > 1.19 ) {
208 $fullname = "_ChartPlugin_${type}_${name}.png";
209 } else {
210 $fullname = "_ChartPlugin_${type}_${name}.gif";
211 }
212
213 return $fullname;
214}
215
216# This routine returns an red colored error message.
217sub _make_error {
218 my ( $msg ) = @_;
219 return "<font color=red>ChartPlugin error: $msg</font>";
220}
221
222# Actually construct the chart by parsing out each of the %CHART%
223# parameters, putting the parameters into the chart object, and then
224# creating the chart.
225sub _makeChart {
226 my ( $this, $args, $topic, $web ) = @_;
227
228 # Check to see if the GD module was found. If not, then create an
229 # error message to display back to the user.
230 if( $initError ) {
231 # It appears that a library wasn't found so we return a
232 # different type of error that is just plain text.
233 return _make_error($initError);
234 }
235 # Set/parse the %CHART% parameters putting into the ChartPlugin object
236 $this->_setParameters ($args);
237
238 # Make a chart object in which we will place user specified parameters
239 my $chart = Foswiki::Plugins::ChartPlugin::Chart->new();
240
241 # See if the parameter 'type' is available. This is a required
242 # parameter. If it is missing, then generate an error message.
243 my $type = $this->_Parameters->getParameter( "type", $defaultType);
244 return _make_error("parameter *type* must be specified") if( ! defined $type );
245 my @unknownTypes = grep(!/area|line|bar|arealine|combo|scatter/, ($type));
246 # Check for a valid type
247 return _make_error("Invalid value of *$type* for parameter *type* ") if (@unknownTypes);
248 $chart->setType($type);
249
250 # See if the parameter 'subtype' (old name 'datatype') is available.
251 my $dataType = $this->_Parameters->getParameter( "datatype", undef);
252 my $subType = $this->_Parameters->getParameter( "subtype", undef);
253 return _make_error("paramters *datatype* and *subtype* can't both be specified") if (defined $dataType && defined $subType);
254 $subType = $dataType if (defined $dataType);
255 if (defined $subType) {
256 my @subTypes = split(/[\s,]+/, $subType);
257 # Check for valid subtypes
258 my @unknownSubTypes = grep(!/area|line|point|pline|scatter|bar/, @subTypes);
259 return _make_error("unknown subtypes: " . join(", ", @unknownSubTypes)) if (@unknownSubTypes);
260 # Now check to make sure that the subtypes specified are valid for the
261 # specified type.
262 ### Check 'line' type
263 if ($type eq "line") {
264 @unknownSubTypes = grep(!/line|point|pline/, @subTypes);
265 return _make_error("unsupported subtypes: " . join(", ", @unknownSubTypes) . " for type line") if (@unknownSubTypes);
266 }
267
268 ### Check 'area' type
269 if ($type eq "area") {
270 @unknownSubTypes = grep(!/area/, @subTypes);
271 return _make_error("unsupported subtypes: " . join(", ", @unknownSubTypes) . " for type area") if (@unknownSubTypes);
272 }
273
274 ### Check 'scatter' type
275 if ($type eq "scatter") {
276 @unknownSubTypes = grep(!/area|line|point|pline|bar/, @subTypes);
277 return _make_error("unsupported subtypes: " . join(", ", @unknownSubTypes) . " for type scatter") if (@unknownSubTypes);
278 }
279
280 ### Check 'combo' type
281 if ($type eq "combo") {
282 @unknownSubTypes = grep(!/area|line|point|pline|bar/, @subTypes);
283 return _make_error("unsupported subtypes: " . join(", ", @unknownSubTypes) . " for type combo") if (@unknownSubTypes);
284 }
285
286 # All OK so set the subtype.
287 $chart->setSubTypes(@subTypes);
288 }
289
290 # See if the parameter 'scale' is available.
291 my $scale = $this->_Parameters->getParameter( "scale", $defaultScale);
292 if ($scale ne "base10" and $scale ne "linear" and $scale ne "semilog") {
293 return _make_error("Invalid value of *$scale* for parameter *scale* ");
294 }
295 $chart->setScale($scale);
296
297 # See if the parameter 'name' is available. This is a required
298 # parameter. If it is missing, then generate an error message.
299 my $name = $this->_Parameters->getParameter( "name", undef);
300 return _make_error("parameter *name* must be specified") if( ! defined $name );
301
302 # See if the parameter 'web' is available. If not, then default to
303 # looking for tables in the current web.
304 my $inWeb = $this->_Parameters->getParameter( "web", $web);
305
306 # See if the parameter 'topic' is available. If not, then default to
307 # looking for tables in the current topic.
308 my $inTopic = $this->_Parameters->getParameter( "topic", $topic);
309
310 # Before we parse any further parameters, lets get the contents of the
311 # specified web/topic.
312 if (! $this->_setTopicContents($inWeb, $inTopic)) {
313 return _make_error("Error retrieving Foswiki topic $inWeb<nop>.$inTopic");
314 }
315
316 # Determine which table the user wants to chart
317 my $tableName = $this->_Parameters->getParameter( "table", 1);
318 # Verify that the table name is valid.
319 if (! $this->_tables->checkTableExists($tableName) ) {
320 return _make_error("parameter *table* is not valid table; the specified table '$tableName' does not exist.");
321 }
322
323 # See if the parameter 'title' is available.
324 $chart->setTitle($this->_Parameters->getParameter( "title", undef));
325
326 # See if the parameter 'xlabel' is available.
327 $chart->setXlabel($this->_Parameters->getParameter( "xlabel", undef));
328
329 # See if the parameter 'ylabel' is available.
330 $chart->setYlabel($this->_Parameters->getParameter( "ylabel", undef));
331
332 # See if the parameter 'data' is available. This is a required
333 # parameter. If it is missing, then generate an error message.
334 my $data = $this->_Parameters->getParameter( "data", undef);
335 return _make_error("parameter *data* must be specified") if( ! defined $data );
336
337 # See if the parameter 'xaxis' is available.
338 my $xAxis = $this->_Parameters->getParameter( "xaxis", undef);
339
340 # See if the parameter 'yaxis' is available.
341 my $yAxis = $this->_Parameters->getParameter( "yaxis", "off");
342 $chart->setYaxis($yAxis);
343
344 # See if the parameter 'ytic' is available.
345 my $yTic = $this->_Parameters->getParameter( "ytics", -1);
346 $chart->setNumYTics($yTic);
347
348 # See if the parameter 'xaxisangle' is available.
349 my $xaxisangle = $this->_Parameters->getParameter( "xaxisangle", 0);
350 $chart->setXaxisAngle($xaxisangle);
351
352 # See if the parameter 'ymin' is available.
353 my $yMin = $this->_Parameters->getParameter( "ymin", undef);
354 if (defined $yMin) {
355 if ($scale eq "semilog" && $yMin <= 0) {
356 return _make_error("user set ymin=$yMin is &lt;= 0 which is not valid when scale=semilog");
357 }
358 }
359 $chart->setYmin( $yMin );
360
361 # See if the parameter 'ymax' is available.
362 my $yMax = $this->_Parameters->getParameter( "ymax", undef);
363 if (defined $yMax) {
364 if ($scale eq "semilog" && $yMax <= 0) {
365 return _make_error("user set ymax=$yMax is &lt;= 0 which is not valid when scale=semilog");
366 }
367 }
368 $chart->setYmax( $yMax );
369
370 # See if the parameter 'numygrids' is available.
371 $chart->setNumYGrids( $this->_Parameters->getParameter( "numygrids", $defaultNumYGrids) );
372
373 # See if the parameter 'numxgrids' is available.
374 my $numxgrids = $this->_Parameters->getParameter( "numxgrids", 10);
375 $chart->setNumXGrids($numxgrids);
376
377 # See if the parameter 'xgrid' is available.
378 my $xGrid = $this->_Parameters->getParameter( "xgrid", "dot");
379 $chart->setXgrid($xGrid);
380
381 # See if the parameter 'ygrid' is available.
382 my $yGrid = $this->_Parameters->getParameter( "ygrid", "dot");
383 $chart->setYgrid($yGrid);
384
385 # See if the parameter 'datalabel' is available.
386 my $dataLabels = $this->_Parameters->getParameter( "datalabel", "off");
387 $chart->setDataLabels(split(/[\s,]+/, $dataLabels)) if (defined $dataLabels);
388
389 # See if the parameter 'legend' is available.
390 my $legend = $this->_Parameters->getParameter( "legend", undef);
391
392 # Get the chart width and height
393 $chart->setImageWidth( $this->_Parameters->getParameter( "width", $defaultWidth) );
394 $chart->setImageHeight( $this->_Parameters->getParameter( "height", $defaultHeight) );
395
396 # Get the chart IMG 'alt' text.
397 my $alt = $this->_Parameters->getParameter( "alt", "");
398
399 # Get the chart 'bgcolor' color.
400 my $bgcolor = $this->_Parameters->getParameter( "bgcolor", $defaultBGcolor);
401 $chart->setBGcolor(split(/[\s,]+/, $bgcolor));
402
403 # Set line/area colors. If the parameter 'colors' is defined, then the
404 # chart will be made with the user specified colors. Otherwise the
405 # chart will be made with the default colors, and then it will depend
406 # on if an 'area' or 'line' is being drawn which will determine which
407 # set of colors to use.
408 $chart->setLineColors(@defaultLineColors);
409 $chart->setAreaColors(@defaultAreaColors);
410 # See if the parameter 'colors' is available.
411 my $colors = $this->_Parameters->getParameter( "colors", undef);
412 $chart->setColors(split(/[\s,]+/, $colors)) if (defined $colors);
413
414 # Get the chart grid color.
415 my $gridColor = $this->_Parameters->getParameter( "gridcolor", $defaultGridColor);
416 $chart->setGridColor(split(/[\s,]+/, $gridColor));
417
418 # See if the parameter 'defaultdata' is available.
419 my $DataValueDefault = $this->_Parameters->getParameter( "defaultdata", $defaultDataValue);
420 $DataValueDefault = '' if ($DataValueDefault eq "none");
421 $chart->setDefaultDataValue($DataValueDefault);
422
423 # Get the filename in which to create the graphics file.
424 my $filename = _make_filename($type, $name);
425 $chart->setAttachmentName($web, $topic, $filename);
426
427 # Validate the legend data making sure it only specifies a single row
428 # or a single column.
429 my @legend;
430 if ($legend) {
431 my $cnt = my @d = $this->_tables->getData($tableName, $legend);
432 if ($cnt > 1) {
433 @d = Foswiki::Plugins::ChartPlugin::Table::transpose( @d );
434 $cnt = scalar(@d);
435 }
436 if ($cnt > 1) {
437 return _make_error("parameter *legend* specifies multiple ($cnt) rows.");
438 }
439 if ($cnt == 0) {
440 return _make_error("parameter *legend* contains an invalid value '$legend'.");
441 }
442 @legend = @{$d[0]};
443 #die Data::Dumper->Dump([\@legend]);
444 $chart->setLegend(@legend);
445 }
446
447 # If the user specified an X axis range, then extract from the X axis
448 # data the starting and ending row/columns. This defines whether the
449 # data is row ordered or column ordered. If there is no X axis
450 # information specified, then assume that the data is in column order.
451 my $columnOrdered = 0;
452 my $rowOrdered = 0;
453 if (defined ($xAxis)) {
454 my ($xAxisRows, $xAxisColumns) =
455 $this->_tables->getRowColumnCount($tableName, $xAxis);
456 return _make_error("parameter *xaxis* value of '$xAxis' is not valid")
457 if (! defined($xAxisRows));
458 if (abs($xAxisRows) > 1) {
459 if ($xAxisColumns > 1) {
460 return _make_error("parameter *xaxis* specifies multiple (${xAxisRows}X$xAxisColumns) rows and columns.");
461 }
462 $columnOrdered = 1;
463 } else {
464 $rowOrdered = 1;
465 }
466 my @d = $this->_tables->getData($tableName, $xAxis, $columnOrdered);
467 return _make_error("no X axis data found in specified area of table [$xAxis]") if (! @d);
468 $chart->setXaxis(@{$d[0]});
469 } else {
470 $columnOrdered = 1;
471 }
472
473 # Validate the data range as valid
474 #my ($dataRows, $dataColumns) =
475 # $this->_tables->getRowColumnCount($tableName, $data);
476 #return _make_error("parameter *data* value of '$data' is not valid") if (! defined($dataRows));
477
478 # Get the actual area data.
479 my @data = ();
480 @data = $this->_tables->getData($tableName, $data, $columnOrdered );
481 # Validate that there is real data returned.
482 return _make_error("no data found in specified area of table [$data]") if (! @data);
483 #my @ranges = $this->_tables->getTableRanges($tableName, $data);
484 #die $data, ' ', Data::Dumper->Dump([\@ranges]);
485 $yMin = $chart->setData(@data);
486 # If scale=semilog and any data is <= 0, then error
487 if ($scale eq "semilog" && $yMin <= 0) {
488 return _make_error("data ($yMin) &lt;= 0 not valid when scale=semilog");
489 }
490
491 # Make sure that there are enough legends to go with all specified
492 # data sets (if legends were specified)
493 if ($legend) {
494 my $numLegends = @legend;
495 my $numDataSets = @data;
496 if ($numDataSets != $numLegends) {
497 return _make_error("parameter *legend* contains an invalid value '$legend' since it specifies $numLegends legends and there are $numDataSets data sets.");
498 }
499 }
500
501 # Set the default point size
502 $chart->setPointSize( $this->_Parameters->getParameter( "pointsize", $defaultPointSize ) );
503
504 # Set the default line width
505 $chart->setLineWidth( $this->_Parameters->getParameter( "linewidth", $defaultLineWidth ) );
506
507 # Set default bar graph values
508 $chart->setBarLeadingSpace($defaultBarLeadingSpace);
509 $chart->setBarTrailingSpace($defaultBarTrailingSpace);
510 $chart->setBarSpace($defaultBarSpace);
511
512 # Create the actual chart.
513 my $err = $chart->makeChart();
514 return _make_error("chart error: name=$name: $err") if ($err);
515
516 # Get remaining parameters and pass to <img ... />
517 my $options = "";
518 my %parameters = $this->_Parameters->getAllParameters();
519 foreach my $k (keys %parameters) {
520 $options .= "$k=\"$parameters{$k}\" ";
521 }
522 # Make a unique value to append to the image name that forces a web
523 # browser to reload the image each time the image is viewed. This is
524 # done so changes to the values used to generate the chart, or the
525 # chart layout specifications, are seen immediately and not ignored
526 # because the browser has cached the image. Eventually a hash value
527 # should be used such that the user's browser CAN cache the image iff
528 # none of the values/parameters used in creating the chart have changed.
529 my $timestamp = time();
530 return "<img src=\"%ATTACHURL%/$filename?t=$timestamp\" alt=\"$alt\" $options />";
531}
532
533# The following is really for debugging and timing purposes and is not an
534# advertised interface. This routine basically creates a number of charts
535# and (roughly) times how long it took to create them.
536# Usage: %CHART_TIMER{### <parameters>}%
537# where ### is the number of charts to create and <parameters> are valid
538# %CHART% parameters ('name' is overridden by the timer so is ignored if
539# specified in <parameters>
540sub _timeit {
541 my ( $this, $loops, $params, $topic, $web ) = @_;
542 my $removeFiles = 0; # Flag on whether to remove the test graphics or not
543 my $start_time = time();
544 for (my $i = 0; $i < $loops; $i++) {
545 my $str = "$params name=\"timeit_$i\"";
546 $this->_makeChart( $str, $topic, $web );
547 }
548 my $finish_time = time();
549 my $diff = $finish_time - $start_time;
550 # Remove the just created test files.
551 if ($removeFiles) {
552 for (my $i = 0; $i < $loops; $i++) {
553 my ($dir, $filename) = _make_filename("area", "timeit_$i", $topic, $web);
554 unlink("$dir/$filename");
555 }
556 }
557 return "To make $loops charts it (roughly) took $diff seconds.<BR>";
558}
559
560# =========================
561
# spent 170µs within Foswiki::Plugins::ChartPlugin::commonTagsHandler which was called 13 times, avg 13µs/call: # 13 times (170µs+0s) by Foswiki::Plugin::invoke at line 294 of /var/www/foswiki11/lib/Foswiki/Plugin.pm, avg 13µs/call
sub commonTagsHandler {
562 ### my ( $text ) = @_; # do not uncomment, use $_[0] instead
5631315µs my $topic = $_[1];
564135µs my $web = $_[2];
565
566 # If no %CHART%s on this page, then there is nothing to do so just
567 # return.
56813121µs if ( $_[0] !~ m/%CHART.*{.*}%/) {
569 # nothing to do
570 return;
571 }
572 _init_defaults();
573 my $chart = ChartPlugin($topic, $web, $_[0]);
574 $_[0] =~ s/%CHART{(.*?)}%/$chart->_makeChart($1, $topic, $web)/eog;
575 $_[0] =~ s/%CHART_TIMER{(\d+) (.*)}%/$chart->_timeit($1, $2, $topic, $web)/eog;
576}
577
57814µs1;