File Coverage

blib/lib/Tk/ForDummies/Graph/Mixed.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             package Tk::ForDummies::Graph::Mixed;
2            
3 1     1   6506 use warnings;
  1         2  
  1         45  
4 1     1   6 use strict;
  1         2  
  1         36  
5 1     1   7 use Carp;
  1         2  
  1         82  
6            
7             #==================================================================
8             # Author : Djibril Ousmanou
9             # Copyright : 2010
10             # Update : 19/06/2010 22:47:03
11             # AIM : Create Mixed graph
12             #==================================================================
13            
14 1     1   6 use vars qw($VERSION);
  1         2  
  1         212  
15             $VERSION = '1.03';
16            
17 1     1   9 use base qw/Tk::Derived Tk::Canvas::GradientColor/;
  1         2  
  1         991  
18             use Tk::Balloon;
19            
20             use Tk::ForDummies::Graph::Utils qw ( :DUMMIES :DISPLAY );
21             use Tk::ForDummies::Graph qw (:DUMMIES);
22            
23             Construct Tk::Widget 'Mixed';
24            
25             sub Populate {
26            
27             my ( $CompositeWidget, $RefParameters ) = @_;
28            
29             # Get initial parameters
30             $CompositeWidget->{RefInfoDummies} = _InitConfig();
31            
32             $CompositeWidget->SUPER::Populate($RefParameters);
33            
34             $CompositeWidget->Advertise( 'GradientColor' => $CompositeWidget );
35             $CompositeWidget->Advertise( 'canvas' => $CompositeWidget->SUPER::Canvas );
36             $CompositeWidget->Advertise( 'Canvas' => $CompositeWidget->SUPER::Canvas );
37            
38             # remove highlightthickness if necessary
39             unless ( exists $RefParameters->{-highlightthickness} ) {
40             $CompositeWidget->configure( -highlightthickness => 0 );
41             }
42            
43             $CompositeWidget->ConfigSpecs(
44             -title => [ 'PASSIVE', 'Title', 'Title', undef ],
45             -titlecolor => [ 'PASSIVE', 'Titlecolor', 'TitleColor', 'black' ],
46             -titlefont =>
47             [ 'PASSIVE', 'Titlefont', 'TitleFont', $CompositeWidget->{RefInfoDummies}->{Font}{DefaultTitle} ],
48             -titleposition => [ 'PASSIVE', 'Titleposition', 'TitlePosition', 'center' ],
49             -titleheight =>
50             [ 'PASSIVE', 'Titleheight', 'TitleHeight', $CompositeWidget->{RefInfoDummies}->{Title}{Height} ],
51            
52             -xlabel => [ 'PASSIVE', 'Xlabel', 'XLabel', undef ],
53             -xlabelcolor => [ 'PASSIVE', 'Xlabelcolor', 'XLabelColor', 'black' ],
54             -xlabelfont =>
55             [ 'PASSIVE', 'Xlabelfont', 'XLabelFont', $CompositeWidget->{RefInfoDummies}->{Font}{DefaultLabel} ],
56             -xlabelposition => [ 'PASSIVE', 'Xlabelposition', 'XLabelPosition', 'center' ],
57             -xlabelheight => [
58             'PASSIVE', 'Xlabelheight',
59             'XLabelHeight', $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{xlabelHeight}
60             ],
61             -xlabelskip => [ 'PASSIVE', 'Xlabelskip', 'XLabelSkip', 0 ],
62            
63             -xvaluecolor => [ 'PASSIVE', 'Xvaluecolor', 'XValueColor', 'black' ],
64             -xvaluevertical => [ 'PASSIVE', 'Xvaluevertical', 'XValueVertical', 0 ],
65             -xvaluespace => [
66             'PASSIVE', 'Xvaluespace',
67             'XValueSpace', $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight}
68             ],
69             -xvalueview => [ 'PASSIVE', 'Xvalueview', 'XValueView', 1 ],
70             -yvalueview => [ 'PASSIVE', 'Yvalueview', 'YValueView', 1 ],
71             -xvaluesregex => [ 'PASSIVE', 'Xvaluesregex', 'XValuesRegex', qr/.+/ ],
72            
73             -ylabel => [ 'PASSIVE', 'Ylabel', 'YLabel', undef ],
74             -ylabelcolor => [ 'PASSIVE', 'Ylabelcolor', 'YLabelColor', 'black' ],
75             -ylabelfont =>
76             [ 'PASSIVE', 'Ylabelfont', 'YLabelFont', $CompositeWidget->{RefInfoDummies}->{Font}{DefaultLabel} ],
77             -ylabelposition => [ 'PASSIVE', 'Ylabelposition', 'YLabelPosition', 'center' ],
78             -ylabelwidth => [
79             'PASSIVE', 'Ylabelwidth',
80             'YLabelWidth', $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{ylabelWidth}
81             ],
82            
83             -yvaluecolor => [ 'PASSIVE', 'Yvaluecolor', 'YValueColor', 'black' ],
84            
85             -labelscolor => [ 'PASSIVE', 'Labelscolor', 'LabelsColor', undef ],
86             -valuescolor => [ 'PASSIVE', 'Valuescolor', 'ValuesColor', undef ],
87             -textcolor => [ 'PASSIVE', 'Textcolor', 'TextColor', undef ],
88             -textfont => [ 'PASSIVE', 'Textfont', 'TextFont', undef ],
89            
90             -boxaxis => [ 'PASSIVE', 'Boxaxis', 'BoxAxis', 0 ],
91             -noaxis => [ 'PASSIVE', 'Noaxis', 'NoAxis', 0 ],
92             -zeroaxisonly => [ 'PASSIVE', 'Zeroaxisonly', 'ZeroAxisOnly', 0 ],
93             -zeroaxis => [ 'PASSIVE', 'Zeroaxis', 'ZeroAxis', 0 ],
94             -longticks => [ 'PASSIVE', 'Longticks', 'LongTicks', 0 ],
95            
96             -xtickheight => [
97             'PASSIVE', 'Xtickheight',
98             'XTickHeight', $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight}
99             ],
100             -xtickview => [ 'PASSIVE', 'Xtickview', 'XTickView', 1 ],
101            
102             -yticknumber => [
103             'PASSIVE', 'Yticknumber',
104             'YTickNumber', $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{TickNumber}
105             ],
106             -ytickwidth =>
107             [ 'PASSIVE', 'Ytickwidth', 'YtickWidth', $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{TickWidth} ],
108             -ytickview => [ 'PASSIVE', 'Ytickview', 'YTickView', 1 ],
109            
110             -alltickview => [ 'PASSIVE', 'Alltickview', 'AllTickView', 1 ],
111            
112             -width => [ 'SELF', 'width', 'Width', $CompositeWidget->{RefInfoDummies}->{Canvas}{Width} ],
113             -height => [ 'SELF', 'height', 'Height', $CompositeWidget->{RefInfoDummies}->{Canvas}{Height} ],
114            
115             -linewidth => [ 'PASSIVE', 'Linewidth', 'LineWidth', 1 ],
116             -colordata =>
117             [ 'PASSIVE', 'Colordata', 'ColorData', $CompositeWidget->{RefInfoDummies}->{Legend}{Colors} ],
118             -overwrite => [ 'PASSIVE', 'Overwrite', 'OverWrite', 0 ],
119             -cumulate => [ 'PASSIVE', 'Cumulate', 'Cumulate', 0 ],
120             -spacingbar => [ 'PASSIVE', 'Spacingbar', 'SpacingBar', 1 ],
121             -showvalues => [ 'PASSIVE', 'Showvalues', 'ShowValues', 0 ],
122            
123             # splined
124             -bezier => [ 'PASSIVE', 'Bezier', 'Bezier', 0 ],
125             -spline => [ 'PASSIVE', 'Spline', 'Spline', 0 ],
126            
127             # points
128             -pointline => [ 'PASSIVE', 'Pointline', 'PointLine', 0 ],
129             -markersize => [ 'PASSIVE', 'Markersize', 'MarkerSize', 8 ],
130             -markers => [ 'PASSIVE', 'Markers', 'Markers', [ 1 .. 8 ] ],
131            
132             # type mixed
133             -typemixed => [ 'PASSIVE', 'Typemixed', 'TypeMixed', undef ],
134             -defaulttype => [ 'PASSIVE', 'Defaulttype', 'DefaulTtype', 'lines' ],
135             -outlinearea => [ 'PASSIVE', 'Outlinearea', 'OutlineArea', 'black' ],
136             -outlinebar => [ 'PASSIVE', 'Outlinebar', 'OutlineBar', 'black' ],
137             );
138            
139             $CompositeWidget->Delegates( DEFAULT => $CompositeWidget, );
140            
141             # recreate graph after widget resize
142             $CompositeWidget->enabled_automatic_redraw();
143             $CompositeWidget->disabled_gradientcolor();
144             }
145            
146             sub _Balloon {
147             my ($CompositeWidget) = @_;
148            
149             # balloon defined and user want to stop it
150             if ( defined $CompositeWidget->{RefInfoDummies}->{Balloon}{Obj}
151             and $CompositeWidget->{RefInfoDummies}->{Balloon}{State} == 0 )
152             {
153             $CompositeWidget->_DestroyBalloonAndBind();
154             return;
155             }
156            
157             # balloon not defined and user want to stop it
158             elsif ( $CompositeWidget->{RefInfoDummies}->{Balloon}{State} == 0 ) {
159             return;
160             }
161            
162             # balloon defined and user want to start it again (may be new option)
163             elsif ( defined $CompositeWidget->{RefInfoDummies}->{Balloon}{Obj}
164             and $CompositeWidget->{RefInfoDummies}->{Balloon}{State} == 1 )
165             {
166            
167             # destroy the balloon, it will be re create above
168             $CompositeWidget->_DestroyBalloonAndBind();
169             }
170            
171             # Balloon creation
172             $CompositeWidget->{RefInfoDummies}->{Balloon}{Obj} = $CompositeWidget->Balloon(
173             -statusbar => $CompositeWidget,
174             -background => $CompositeWidget->{RefInfoDummies}->{Balloon}{Background},
175             );
176             $CompositeWidget->{RefInfoDummies}->{Balloon}{Obj}->attach(
177             $CompositeWidget,
178             -balloonposition => 'mouse',
179             -msg => $CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon},
180             );
181            
182             # no legend, no bind
183             unless ( my $LegendTextNumber = $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber} ) {
184             return;
185             }
186            
187             # bind legend and Mixed
188             for my $IndexLegend ( 1 .. $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber} ) {
189            
190             my $LegendTag = $IndexLegend . $CompositeWidget->{RefInfoDummies}->{TAGS}{Legend};
191             my $MixedTag = $IndexLegend . $CompositeWidget->{RefInfoDummies}->{TAGS}{Mixed};
192            
193             $CompositeWidget->bind(
194             $LegendTag,
195             '',
196             sub {
197             my $OtherColor = $CompositeWidget->{RefInfoDummies}->{Balloon}{ColorData}->[0];
198            
199             # Change color if bar have the same color
200             if ( $OtherColor eq $CompositeWidget->{RefInfoDummies}{Mixed}{$MixedTag}{color} ) {
201             $OtherColor = $CompositeWidget->{RefInfoDummies}->{Balloon}{ColorData}->[1];
202             }
203             $CompositeWidget->itemconfigure( $MixedTag, -fill => $OtherColor, );
204             my $ElementType = $CompositeWidget->type($MixedTag);
205             if ( $ElementType =~ m{^polygon|oval|arc$} ) {
206             $CompositeWidget->itemconfigure( $MixedTag, -outline => $OtherColor, );
207             }
208             }
209             );
210            
211             $CompositeWidget->bind(
212             $LegendTag,
213             '',
214             sub {
215             $CompositeWidget->itemconfigure( $MixedTag,
216             -fill => $CompositeWidget->{RefInfoDummies}{Mixed}{$MixedTag}{color}, );
217            
218             my $ElementType = $CompositeWidget->type($MixedTag);
219             if ( $ElementType =~ m{^polygon|oval|arc$} ) {
220             $CompositeWidget->itemconfigure( $MixedTag,
221             -outline => $CompositeWidget->{RefInfoDummies}{Mixed}{$MixedTag}{color}, );
222             }
223            
224             # Allow value bar to display
225             $CompositeWidget->itemconfigure( $CompositeWidget->{RefInfoDummies}->{TAGS}{BarValues},
226             -fill => 'black', );
227            
228             # area outline
229             my $outlinearea = $CompositeWidget->cget( -outlinearea );
230             $CompositeWidget->itemconfigure( $CompositeWidget->{RefInfoDummies}->{TAGS}{Area},
231             -outline => $outlinearea, );
232            
233             # area outlinebar
234             my $outlinebar = $CompositeWidget->cget( -outlinebar );
235             $CompositeWidget->itemconfigure( $CompositeWidget->{RefInfoDummies}->{TAGS}{Bar},
236             -outline => $outlinebar, );
237            
238             }
239             );
240             }
241            
242             return;
243             }
244            
245             sub set_legend {
246             my ( $CompositeWidget, %InfoLegend ) = @_;
247            
248             my $RefLegend = $InfoLegend{-data};
249             unless ( defined $RefLegend ) {
250             $CompositeWidget->_error(
251             "Can't set -data in set_legend method. "
252             . "May be you forgot to set the value\n"
253             . "Eg : set_legend( -data => ['legend1', 'legend2', ...] );",
254             1
255             );
256             }
257            
258             unless ( defined $RefLegend and ref($RefLegend) eq 'ARRAY' ) {
259             $CompositeWidget->_error(
260             "Can't set -data in set_legend method. Bad data\n"
261             . "Eg : set_legend( -data => ['legend1', 'legend2', ...] );",
262             1
263             );
264             }
265            
266             my @LegendOption = qw / -box -legendmarkerheight -legendmarkerwidth -heighttitle /;
267            
268             foreach my $OptionName (@LegendOption) {
269             if ( defined $InfoLegend{$OptionName}
270             and $InfoLegend{$OptionName} !~ m{^\d+$} )
271             {
272             $CompositeWidget->_error(
273             "'Can't set $OptionName to " . "'$InfoLegend{$OptionName}', $InfoLegend{$OptionName}' isn't numeric",
274             1
275             );
276             }
277             }
278            
279             # Check legend and data size
280             if ( my $RefData = $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData} ) {
281             unless ( $CompositeWidget->_CheckSizeLengendAndData( $RefData, $RefLegend ) ) {
282             undef $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend};
283             return;
284             }
285             }
286            
287             # Get Legend options
288             # Title
289             if ( defined $InfoLegend{-title} ) {
290             $CompositeWidget->{RefInfoDummies}->{Legend}{title} = $InfoLegend{-title};
291             }
292             else {
293             undef $CompositeWidget->{RefInfoDummies}->{Legend}{title};
294             $CompositeWidget->{RefInfoDummies}->{Legend}{HeightTitle} = 0;
295             }
296            
297             # Title and legend font
298             if ( defined $InfoLegend{-titlefont} ) {
299             $CompositeWidget->{RefInfoDummies}->{Legend}{titlefont} = $InfoLegend{-titlefont};
300             }
301             if ( defined $InfoLegend{-legendfont} ) {
302             $CompositeWidget->{RefInfoDummies}->{Legend}{legendfont} = $InfoLegend{-legendfont};
303             }
304            
305             # box legend
306             if ( defined $InfoLegend{-box} ) {
307             $CompositeWidget->{RefInfoDummies}->{Legend}{box} = $InfoLegend{-box};
308             }
309            
310             # title color
311             if ( defined $InfoLegend{-titlecolors} ) {
312             $CompositeWidget->{RefInfoDummies}->{Legend}{titlecolors} = $InfoLegend{-titlecolors};
313             }
314            
315             # legendmarkerheight
316             if ( defined $InfoLegend{-legendmarkerheight} ) {
317             $CompositeWidget->{RefInfoDummies}->{Legend}{HCube} = $InfoLegend{-legendmarkerheight};
318             }
319            
320             # legendmarkerwidth
321             if ( defined $InfoLegend{-legendmarkerwidth} ) {
322             $CompositeWidget->{RefInfoDummies}->{Legend}{WCube} = $InfoLegend{-legendmarkerwidth};
323             }
324            
325             # heighttitle
326             if ( defined $InfoLegend{-heighttitle} ) {
327             $CompositeWidget->{RefInfoDummies}->{Legend}{HeightTitle} = $InfoLegend{-heighttitle};
328             }
329            
330             # Get the biggest length of legend text
331             my @LengthLegend = map { length; } @{$RefLegend};
332             my $BiggestLegend = _MaxArray( \@LengthLegend );
333            
334             # 100 pixel => 13 characters, 1 pixel => 0.13 pixels then 1 character = 7.69 pixels
335             $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter} = 7.69;
336            
337             # Max pixel width for a legend text for us
338             $CompositeWidget->{RefInfoDummies}->{Legend}{LengthTextMax}
339             = int( $CompositeWidget->{RefInfoDummies}->{Legend}{WidthText}
340             / $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter} );
341            
342             # We have free space
343             my $Diff = $CompositeWidget->{RefInfoDummies}->{Legend}{LengthTextMax} - $BiggestLegend;
344            
345             # Get new size width for a legend text with one pixel security
346             $CompositeWidget->{RefInfoDummies}->{Legend}{WidthText}
347             -= ( $Diff - 1 ) * $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter};
348            
349             # Store Reference data
350             $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend} = $RefLegend;
351             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLegend} = scalar @{$RefLegend};
352            
353             return 1;
354             }
355            
356             sub _Legend {
357             my ( $CompositeWidget, $RefLegend ) = @_;
358            
359             # One legend width
360             $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend}
361             = +$CompositeWidget->{RefInfoDummies}->{Legend}{SpaceBeforeCube} # space between each legend
362             + $CompositeWidget->{RefInfoDummies}->{Legend}{WCube} # width legend marker
363             + $CompositeWidget->{RefInfoDummies}->{Legend}{SpaceAfterCube} # space after marker
364             + $CompositeWidget->{RefInfoDummies}->{Legend}{WidthText} # legend text width allowed
365             ;
366            
367             # Number of legends per line
368             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine}
369             = int( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{Width}
370             / $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend} );
371             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine} = 1
372             if ( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine} == 0 );
373            
374             # How many legend we will have
375             $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber}
376             = scalar @{ $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData} } - 1;
377            
378             =for NumberLines:
379             We calculate the number of lines set for the legend graph.
380             If wa can set 11 legends per line, then for 3 legend, we will need one line
381             and for 12 legends, we will need 2 lines
382             If NbrLeg / NbrPerLine = integer => get number of lines
383             If NbrLeg / NbrPerLine = float => int(float) + 1 = get number of lines
384            
385             =cut
386            
387             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine}
388             = $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber}
389             / $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine};
390             unless (
391             int( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine} )
392             == $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine} )
393             {
394             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine}
395             = int( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine} ) + 1;
396             }
397            
398             # Total Height of Legend
399             $CompositeWidget->{RefInfoDummies}->{Legend}{Height}
400             = $CompositeWidget->{RefInfoDummies}->{Legend}{HeightTitle} # Hauteur Titre légende
401             + $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine}
402             * $CompositeWidget->{RefInfoDummies}->{Legend}{HLine};
403            
404             # Get number legend text max per line to reajust our graph
405             if ( $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber}
406             < $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine} )
407             {
408             $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine}
409             = $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber};
410             }
411            
412             return;
413             }
414            
415             sub _ViewLegend {
416             my ($CompositeWidget) = @_;
417            
418             # legend option
419             my $LegendTitle = $CompositeWidget->{RefInfoDummies}->{Legend}{title};
420             my $legendmarkercolors = $CompositeWidget->cget( -colordata );
421             my $legendfont = $CompositeWidget->{RefInfoDummies}->{Legend}{legendfont};
422             my $titlecolor = $CompositeWidget->{RefInfoDummies}->{Legend}{titlecolors};
423             my $titlefont = $CompositeWidget->{RefInfoDummies}->{Legend}{titlefont};
424            
425             # display legend title
426             if ( defined $LegendTitle ) {
427             my $xLegendTitle = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin}
428             + $CompositeWidget->{RefInfoDummies}->{Legend}{SpaceBeforeCube};
429             my $yLegendTitle
430             = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin}
431             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight}
432             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight}
433             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{xlabelHeight};
434            
435             $CompositeWidget->createText(
436             $xLegendTitle,
437             $yLegendTitle,
438             -text => $LegendTitle,
439             -anchor => 'nw',
440             -font => $titlefont,
441             -fill => $titlecolor,
442             -width => $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{Width},
443             -tags => [
444             $CompositeWidget->{RefInfoDummies}->{TAGS}{TitleLegend},
445             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
446             ],
447             );
448             }
449            
450             # Display legend
451             my $IndexColor = 0;
452             my $IndexLegend = 0;
453             my $IndexMarker = 0;
454            
455             # initialisation of balloon message
456             #$CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon} = {};
457             for my $NumberLine ( 0 .. $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLine} - 1 ) {
458             my $x1Cube = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin}
459             + $CompositeWidget->{RefInfoDummies}->{Legend}{SpaceBeforeCube};
460             my $y1Cube
461             = ( $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin}
462             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight}
463             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight}
464             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{xlabelHeight}
465             + $CompositeWidget->{RefInfoDummies}->{Legend}{HeightTitle}
466             + $CompositeWidget->{RefInfoDummies}->{Legend}{HLine} / 2 )
467             + $NumberLine * $CompositeWidget->{RefInfoDummies}->{Legend}{HLine};
468            
469             my $x2Cube = $x1Cube + $CompositeWidget->{RefInfoDummies}->{Legend}{WCube};
470             my $y2Cube = $y1Cube - $CompositeWidget->{RefInfoDummies}->{Legend}{HCube};
471             my $xText = $x2Cube + $CompositeWidget->{RefInfoDummies}->{Legend}{SpaceAfterCube};
472             my $yText = $y2Cube;
473             my $MaxLength = $CompositeWidget->{RefInfoDummies}->{Legend}{LengthTextMax};
474            
475             LEGEND:
476             for my $NumberLegInLine ( 0 .. $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine} - 1 ) {
477            
478             my $LineColor = $legendmarkercolors->[$IndexColor];
479             unless ( defined $LineColor ) {
480             $IndexColor = 0;
481             $LineColor = $legendmarkercolors->[$IndexColor];
482             }
483            
484             # Cut legend text if too long
485             my $Legende = $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend}->[$IndexLegend];
486             next unless ( defined $Legende );
487             my $NewLegend = $Legende;
488            
489             if ( length $NewLegend > $MaxLength ) {
490             $MaxLength -= 3;
491             $NewLegend =~ s/^(.{$MaxLength}).*/$1/;
492             $NewLegend .= '...';
493             }
494            
495             my $Tag = ( $IndexLegend + 1 ) . $CompositeWidget->{RefInfoDummies}->{TAGS}{Legend};
496            
497             # Marker type to display
498             my $defaulttype = $CompositeWidget->cget( -defaulttype );
499             my $MarkerType = $CompositeWidget->cget( -typemixed )->[$IndexLegend] || $defaulttype;
500            
501             if ( $MarkerType eq 'lines' or $MarkerType eq 'dashlines' ) {
502             my $y1 = $y2Cube - ( ( $y2Cube - $y1Cube ) / 2 );
503             my $y2 = $y1;
504             my $dashline = $CompositeWidget->cget( -dashline );
505             $dashline = '.' if ( $MarkerType eq 'dashlines' );
506            
507             $CompositeWidget->createLine(
508             $x1Cube, $y1, $x2Cube, $y2,
509             -fill => $LineColor,
510             -width => 4,
511             -dash => $dashline,
512             -tags => [ $Tag, $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph}, ],
513             );
514             }
515             elsif ( $MarkerType eq 'points' ) {
516             my $markersize = $CompositeWidget->cget( -markersize );
517             my $markers = $CompositeWidget->cget( -markers );
518             my $NumMarker = $markers->[$IndexMarker];
519             unless ( defined $NumMarker ) {
520             $IndexMarker = 0;
521             $NumMarker = $markers->[$IndexMarker];
522             }
523             my $RefType = $CompositeWidget->_GetMarkerType($NumMarker);
524             my %Option;
525             if ( $RefType->[1] == 1 ) {
526             $Option{-fill} = $LineColor;
527             }
528             if ( $NumMarker =~ m{^[125678]$} ) {
529             $Option{-outline} = $LineColor;
530             }
531             my $x = $x1Cube + ( ( $x2Cube - $x1Cube ) / 2 );
532             my $y = $y1Cube + ( ( $y2Cube - $y1Cube ) / 2 );
533             $Option{-tags} = [ $Tag, $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph}, ];
534             $CompositeWidget->_CreateType(
535             x => $x,
536             y => $y,
537             pixel => 10,
538             type => $RefType->[0],
539             option => \%Option,
540             );
541             $IndexMarker++;
542             }
543             else {
544             $CompositeWidget->createRectangle(
545             $x1Cube, $y1Cube, $x2Cube, $y2Cube,
546             -fill => $LineColor,
547             -outline => $LineColor,
548             -tags => [ $Tag, $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph}, ],
549             );
550             }
551            
552             my $Id = $CompositeWidget->createText(
553             $xText, $yText,
554             -text => $NewLegend,
555             -anchor => 'nw',
556             -tags => [ $Tag, $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph}, ],
557             );
558             if ($legendfont) {
559             $CompositeWidget->itemconfigure( $Id, -font => $legendfont, );
560             }
561            
562             $IndexColor++;
563             $IndexLegend++;
564            
565             # cube
566             $x1Cube += $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend};
567             $x2Cube += $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend};
568            
569             # Text
570             $xText += $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend};
571             my $MixedTag = $IndexLegend . $CompositeWidget->{RefInfoDummies}->{TAGS}{Mixed};
572             $CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon}->{$Tag} = $Legende;
573            
574             last LEGEND
575             if ( $IndexLegend == $CompositeWidget->{RefInfoDummies}->{Legend}{LegendTextNumber} );
576             }
577             }
578            
579             # box legend
580             my $x1Box = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin};
581             my $y1Box
582             = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin}
583             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight}
584             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight}
585             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{xlabelHeight};
586             my $x2Box
587             = $x1Box
588             + ( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrPerLine}
589             * $CompositeWidget->{RefInfoDummies}->{Legend}{LengthOneLegend} );
590            
591             # Reajuste box if width box < legend title text
592             my @InfoLegendTitle = $CompositeWidget->bbox( $CompositeWidget->{RefInfoDummies}->{TAGS}{TitleLegend} );
593             if ( $InfoLegendTitle[2] and $x2Box <= $InfoLegendTitle[2] ) {
594             $x2Box = $InfoLegendTitle[2] + 2;
595             }
596             my $y2Box = $y1Box + $CompositeWidget->{RefInfoDummies}->{Legend}{Height};
597             $CompositeWidget->createRectangle(
598             $x1Box, $y1Box, $x2Box, $y2Box,
599             -tags => [
600             $CompositeWidget->{RefInfoDummies}->{TAGS}{BoxLegend},
601             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
602             ],
603             );
604            
605             return;
606             }
607            
608             sub _axis {
609             my ($CompositeWidget) = @_;
610            
611             # x axis width
612             $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{Width}
613             = $CompositeWidget->{RefInfoDummies}->{Canvas}{Width}
614             - ( 2 * $CompositeWidget->{RefInfoDummies}->{Canvas}{WidthEmptySpace}
615             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{ylabelWidth}
616             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{ScaleValuesWidth}
617             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{TickWidth} );
618            
619             # get Height legend
620             if ( $CompositeWidget->{RefInfoDummies}->{Legend}{NbrLegend} > 0 ) {
621             $CompositeWidget->_Legend( $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend} );
622             }
623            
624             # Height y axis
625             $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{Height}
626             = $CompositeWidget->{RefInfoDummies}->{Canvas}{Height} # Largeur canvas
627             - (
628             2 * $CompositeWidget->{RefInfoDummies}->{Canvas}{HeightEmptySpace} # 2 fois les espace vides
629             + $CompositeWidget->{RefInfoDummies}->{Title}{Height} # Hauteur du titre
630             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight} # Hauteur tick (axe x)
631             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight} # Hauteur valeurs axe
632             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{xlabelHeight} # Hauteur x label
633             + $CompositeWidget->{RefInfoDummies}->{Legend}{Height} # Hauteur légende
634             );
635            
636             #===========================
637             # Y axis
638             # Set 2 points (CxMin, CyMin) et (CxMin, CyMax)
639             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin} # Coordonnées CxMin
640             = $CompositeWidget->{RefInfoDummies}->{Canvas}{WidthEmptySpace} # Largeur vide
641             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{ylabelWidth} # Largeur label y
642             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{ScaleValuesWidth} # Largeur valeur axe y
643             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{TickWidth}; # Largeur tick axe y
644            
645             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMax} # Coordonnées CyMax
646             = $CompositeWidget->{RefInfoDummies}->{Canvas}{HeightEmptySpace} # Hauteur vide
647             + $CompositeWidget->{RefInfoDummies}->{Title}{Height} # Hauteur titre
648             ;
649            
650             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin} # Coordonnées CyMin
651             = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMax} # Coordonnées CyMax (haut)
652             + $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{Height} # Hauteur axe Y
653             ;
654            
655             # display Y axis
656             $CompositeWidget->createLine(
657             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin},
658             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin},
659             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin},
660             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMax},
661             -tags => [
662             $CompositeWidget->{RefInfoDummies}->{TAGS}{yAxis},
663             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllAXIS},
664             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
665             ],
666             );
667            
668             #===========================
669             # X axis
670             # Set 2 points (CxMin,CyMin) et (CxMax,CyMin)
671             # ou (Cx0,Cy0) et (CxMax,Cy0)
672             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMax} = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin}
673             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{Width};
674            
675             # Bottom x axis
676             $CompositeWidget->createLine(
677             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin},
678             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin},
679             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMax},
680             $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin},
681             -tags => [
682             $CompositeWidget->{RefInfoDummies}->{TAGS}{xAxis},
683             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllAXIS},
684             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
685             ],
686             );
687            
688             # POINT (0,0)
689             # min positive value >= 0
690             if ( $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} >= 0 ) {
691             $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0} = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin};
692             $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0} = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin};
693            
694             $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} # Height unit for value = 1
695             = $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{Height}
696             / ( $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue} - 0 );
697             }
698            
699             # min positive value < 0
700             else {
701            
702             $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} # Height unit for value = 1
703             = $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{Height}
704             / ( $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue}
705             - $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} );
706             $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0} = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin};
707             $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0}
708             = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin}
709             + ( $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit}
710             * $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} );
711            
712             # X Axis (0,0)
713             $CompositeWidget->createLine(
714             $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0},
715             $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0},
716             $CompositeWidget->{RefInfoDummies}->{Axis}{CxMax},
717             $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0},
718             -tags => [
719             $CompositeWidget->{RefInfoDummies}->{TAGS}{xAxis0},
720             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllAXIS},
721             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
722             ],
723             );
724             }
725            
726             return;
727             }
728            
729             sub _xtick {
730             my ($CompositeWidget) = @_;
731            
732             my $xvaluecolor = $CompositeWidget->cget( -xvaluecolor );
733             my $longticks = $CompositeWidget->cget( -longticks );
734            
735             # x coordinates y ticks on bottom x axis
736             my $Xtickx1 = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin};
737             my $Xticky1 = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin};
738            
739             # x coordinates y ticks on 0,0 x axis if the graph have only y value < 0
740             if ( $CompositeWidget->cget( -zeroaxisonly ) == 1
741             and $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue} > 0 )
742             {
743             $Xticky1 = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0};
744             }
745            
746             my $Xtickx2 = $Xtickx1;
747             my $Xticky2 = $Xticky1 + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{TickHeight};
748            
749             # Coordinates of x values (first value)
750             my $XtickxValue = $CompositeWidget->{RefInfoDummies}->{Axis}{CxMin}
751             + ( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} / 2 );
752             my $XtickyValue = $Xticky2 + ( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{ScaleValuesHeight} / 2 );
753             my $NbrLeg = scalar( @{ $CompositeWidget->{RefInfoDummies}->{Data}{RefXLegend} } );
754            
755             my $xlabelskip = $CompositeWidget->cget( -xlabelskip );
756            
757             # index of tick and vlaues that will be skip
758             my %IndiceToSkip;
759             if ( defined $xlabelskip ) {
760             for ( my $i = 1; $i <= $NbrLeg; $i++ ) {
761             $IndiceToSkip{$i} = 1;
762             $i += $xlabelskip;
763             }
764             }
765            
766             for ( my $Indice = 1; $Indice <= $NbrLeg; $Indice++ ) {
767             my $data = $CompositeWidget->{RefInfoDummies}->{Data}{RefXLegend}->[ $Indice - 1 ];
768            
769             # tick
770             $Xtickx1 += $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick};
771             $Xtickx2 = $Xtickx1;
772            
773             # tick legend
774             my $RegexXtickselect = $CompositeWidget->cget( -xvaluesregex );
775            
776             if ( $data =~ m{$RegexXtickselect} ) {
777             next unless ( defined $IndiceToSkip{$Indice} );
778            
779             # Long tick
780             if ( defined $longticks and $longticks == 1 ) {
781             $Xticky1 = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMax};
782             $Xticky2 = $CompositeWidget->{RefInfoDummies}->{Axis}{CyMin};
783             }
784            
785             $CompositeWidget->createLine(
786             $Xtickx1, $Xticky1, $Xtickx2, $Xticky2,
787             -tags => [
788             $CompositeWidget->{RefInfoDummies}->{TAGS}{xTick},
789             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTick},
790             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
791             ],
792             );
793            
794             if ( defined $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
795             and defined $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter} )
796             {
797             my $MaxLength = $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick};
798             my $WidthData = $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter} * length $data;
799             my $NbrCharacter = int( $MaxLength / $CompositeWidget->{RefInfoDummies}->{Legend}{WidthOneCaracter} );
800             if ( defined $MaxLength and $WidthData > $MaxLength ) {
801             $data =~ s/^(.{$NbrCharacter}).*/$1/;
802             $data .= '...';
803             }
804             }
805            
806             $CompositeWidget->createText(
807             $XtickxValue,
808             $XtickyValue,
809             -text => $data,
810             -fill => $xvaluecolor,
811             -tags => [
812             $CompositeWidget->{RefInfoDummies}->{TAGS}{xValues},
813             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllValues},
814             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
815             ],
816             );
817             }
818             $XtickxValue += $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick};
819             }
820            
821             return;
822             }
823            
824             sub _ViewData {
825             my ($CompositeWidget) = @_;
826            
827             my $RefTypemixed = $CompositeWidget->cget( -typemixed );
828             my $defaulttype = $CompositeWidget->cget( -defaulttype );
829            
830             my $RefData = $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData};
831            
832             # number of value for x axis
833             $CompositeWidget->{RefInfoDummies}->{Data}{xtickNumber}
834             = $CompositeWidget->{RefInfoDummies}->{Data}{NumberXValues};
835            
836             # Space between x ticks
837             $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
838             = $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{Width}
839             / ( $CompositeWidget->{RefInfoDummies}->{Data}{xtickNumber} + 1 );
840            
841             my $NumberBarData = 1; # Number of bar data
842             my $NumberPointData = 1;
843             my @PointsData; # coordinate x and y
844             my $IdData = 0;
845             $CompositeWidget->{Index}{Color}{Line} = 0;
846             $CompositeWidget->{Index}{Marker}{id} = 0;
847            
848             my @CumulateY = (0) x scalar @{ $RefData->[0] };
849            
850             # each list data
851             foreach my $RefArrayData ( @{$RefData} ) {
852            
853             # skipp legend
854             if ( $IdData == 0 ) {
855             $IdData++;
856             next;
857             }
858            
859             my $type = $RefTypemixed->[ $IdData - 1 ] || $defaulttype;
860             if ( $type eq 'lines' ) {
861             $CompositeWidget->_ViewDataLines( $RefArrayData, $IdData );
862             }
863             elsif ( $type eq 'dashlines' ) {
864             $CompositeWidget->_ViewDataLines( $RefArrayData, $IdData, '.' ); # . for dash
865             }
866             elsif ( $type eq 'bars' ) {
867             $CompositeWidget->_ViewDataBars( $RefArrayData, \@CumulateY, $NumberBarData, $IdData );
868             $NumberBarData++;
869             }
870             elsif ( $type eq 'points' ) {
871             $CompositeWidget->_ViewDataPoints( $RefArrayData, $IdData );
872             $NumberPointData++;
873             }
874             elsif ( $type eq 'areas' ) {
875             $CompositeWidget->_ViewDataAreas( $RefArrayData, $IdData );
876             }
877             else {
878             $CompositeWidget->_error( "Type '$type' unknown", 1 );
879             }
880            
881             $IdData++;
882             }
883            
884             return 1;
885             }
886            
887             sub _ViewDataAreas {
888             my ( $CompositeWidget, $RefArrayData, $IdData ) = @_;
889            
890             my $legendmarkercolors = $CompositeWidget->cget( -colordata );
891             my $viewsection = $CompositeWidget->cget( -viewsection );
892             my $outlinearea = $CompositeWidget->cget( -outlinearea );
893             my $IndexColor = $CompositeWidget->{Index}{Color}{Line};
894             my $LineColor = $legendmarkercolors->[$IndexColor];
895             my $NumberData = 1;
896             my $tag = $IdData . $CompositeWidget->{RefInfoDummies}->{TAGS}{Mixed};
897             my $tag2 = $IdData . "_$NumberData" . $CompositeWidget->{RefInfoDummies}->{TAGS}{Mixed};
898             $CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon}->{$tag2}
899             = $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend}->[ $IdData - 1 ];
900             my $tag_area = $CompositeWidget->{RefInfoDummies}->{TAGS}{Area};
901            
902             my @PointsData; # coordinate x and y
903             my @DashPointsxLines;
904            
905             # First point, in x axis
906             my $Fisrtx
907             = $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0}
908             + $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
909             - ( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} / 2 );
910             my $Fisrty = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0};
911             push( @PointsData, ( $Fisrtx, $Fisrty ) );
912            
913             foreach my $data ( @{$RefArrayData} ) {
914             unless ( defined $data ) {
915             $NumberData++;
916             next;
917             }
918            
919             # coordinates x and y values
920             my $x
921             = $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0}
922             + $NumberData * $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
923             - ( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} / 2 );
924             my $y = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0}
925             - ( $data * $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} );
926            
927             push( @PointsData, ( $x, $y ) );
928            
929             push( @DashPointsxLines, $x, $y );
930             $NumberData++;
931             }
932            
933             # Last point, in x axis
934             my $Lastx
935             = $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0}
936             + ( $NumberData - 1 ) * $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
937             - ( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} / 2 );
938            
939             my $Lastty = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0};
940             push( @PointsData, ( $Lastx, $Lastty ) );
941            
942             $CompositeWidget->createPolygon(
943             @PointsData,
944             -fill => $LineColor,
945             -tags => [ $tag, $tag2, $tag_area, $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph}, ],
946             -width => $CompositeWidget->cget( -linewidth ),
947             -outline => $outlinearea,
948             );
949            
950             # display Dash line
951             if ( defined $viewsection and $viewsection == 1 ) {
952             for ( my $i = 0; $i < scalar(@DashPointsxLines); $i++ ) {
953             my $IndexX1 = $i;
954             my $IndexY1 = $i + 1;
955             my $IndexX2 = $i;
956             $CompositeWidget->createLine(
957             $DashPointsxLines[$IndexX1],
958             $DashPointsxLines[$IndexY1],
959             $DashPointsxLines[$IndexX2],
960             $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0},
961             -dash => '.',
962             -tags => [
963             $tag, $tag_area,
964             $CompositeWidget->{RefInfoDummies}->{TAGS}{DashLines},
965             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
966             ],
967             );
968             $i++;
969             }
970             }
971            
972             # Display values above each points of lines
973             my $LineNumber = $IdData - 1;
974             $CompositeWidget->_display_line( \@PointsData, $LineNumber );
975            
976             $CompositeWidget->{RefInfoDummies}{Line}{$tag}{color} = $LineColor;
977            
978             $IndexColor++;
979             $CompositeWidget->{Index}{Color}{Line} = $IndexColor;
980             $CompositeWidget->{RefInfoDummies}{Mixed}{$tag}{color} = $LineColor;
981            
982             return 1;
983             }
984            
985             sub _ViewDataPoints {
986             my ( $CompositeWidget, $RefArrayData, $IdData ) = @_;
987            
988             my $legendmarkercolors = $CompositeWidget->cget( -colordata );
989             my $markersize = $CompositeWidget->cget( -markersize );
990             my $markers = $CompositeWidget->cget( -markers );
991             my $IndexColor = $CompositeWidget->{Index}{Color}{Line};
992             my $IndexMarker = $CompositeWidget->{Index}{Marker}{id};
993             my $LineColor = $legendmarkercolors->[$IndexColor];
994            
995             my $NumMarker = $markers->[$IndexMarker] || $markers->[0];
996             my $NumberData = 1;
997             my $tag = $IdData . $CompositeWidget->{RefInfoDummies}->{TAGS}{Mixed};
998             my $tag_point = $CompositeWidget->{RefInfoDummies}->{TAGS}{Point};
999            
1000             $CompositeWidget->{RefInfoDummies}{Point}{$tag}{color} = $LineColor;
1001            
1002             my @PointsData; # coordinate x and y
1003             foreach my $data ( @{$RefArrayData} ) {
1004             unless ( defined $data ) {
1005             $NumberData++;
1006             next;
1007             }
1008            
1009             # coordinates x and y values
1010             my $x
1011             = $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0}
1012             + ( $NumberData * $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} )
1013             - ( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} / 2 );
1014             my $y = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0}
1015             - ( $data * $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} );
1016            
1017             my $tag2 = $IdData . "_$NumberData" . $CompositeWidget->{RefInfoDummies}->{TAGS}{Mixed};
1018             $CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon}->{$tag2}
1019             = $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend}->[ $IdData - 1 ];
1020            
1021             my %Option = (
1022             -tags => [ $tag, $tag2, $tag_point, $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph}, ],
1023             -width => $CompositeWidget->cget( -linewidth ),
1024             );
1025             my $RefType = $CompositeWidget->_GetMarkerType($NumMarker);
1026             if ( $RefType->[1] == 1 ) {
1027             $Option{-fill} = $LineColor;
1028             }
1029             if ( $NumMarker =~ m{^[125678]$} ) {
1030             $Option{-outline} = $LineColor;
1031             }
1032            
1033             $CompositeWidget->_CreateType(
1034             x => $x,
1035             y => $y,
1036             pixel => $markersize,
1037             type => $RefType->[0],
1038             option => \%Option,
1039             );
1040             $NumberData++;
1041             push( @PointsData, ( $x, $y ) );
1042             }
1043            
1044             # Display values above each points of lines
1045             my $LineNumber = $IdData - 1;
1046             $CompositeWidget->_display_line( \@PointsData, $LineNumber );
1047            
1048             $IndexColor++;
1049             $CompositeWidget->{Index}{Color}{Line} = $IndexColor;
1050             $IndexMarker++;
1051             $CompositeWidget->{Index}{Marker}{id} = $IndexMarker;
1052             $CompositeWidget->{RefInfoDummies}{Mixed}{$tag}{color} = $LineColor;
1053            
1054             return 1;
1055             }
1056            
1057             sub _ViewDataBars {
1058             my ( $CompositeWidget, $RefArrayData, $RefCumulateY, $NumberBarData, $IdData ) = @_;
1059            
1060             my $legendmarkercolors = $CompositeWidget->cget( -colordata );
1061             my $overwrite = $CompositeWidget->cget( -overwrite );
1062             my $cumulate = $CompositeWidget->cget( -cumulate );
1063             my $spacingbar = $CompositeWidget->cget( -spacingbar );
1064             my $showvalues = $CompositeWidget->cget( -showvalues );
1065             my $outlinebar = $CompositeWidget->cget( -outlinebar );
1066            
1067             my $IndexColor = $CompositeWidget->{Index}{Color}{Line};
1068             my $LineColor = $legendmarkercolors->[$IndexColor];
1069             my $NumberData = 1; # Number of data
1070             my $tag_bar = $CompositeWidget->{RefInfoDummies}->{TAGS}{Bar};
1071            
1072             my $WidthBar = $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
1073             / $CompositeWidget->{RefInfoDummies}->{Data}{NumberRealDataBars};
1074            
1075             foreach my $data ( @{$RefArrayData} ) {
1076             unless ( defined $data ) {
1077             push @{$RefCumulateY}, 0;
1078             $NumberData++;
1079             next;
1080             }
1081            
1082             my ( $x, $y, $x0, $y0 ) = ();
1083             if ( $overwrite == 1 or $cumulate == 1 ) {
1084            
1085             # coordinates x and y values
1086             $x = $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0}
1087             + $NumberData * $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick};
1088             $y = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0}
1089             - ( $data * $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} );
1090            
1091             # coordinates x0 and y0 values
1092             $x0 = $x - $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick};
1093             $y0 = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0};
1094            
1095             # cumulate bars
1096             if ( $cumulate == 1 ) {
1097            
1098             $y -= $RefCumulateY->[ $NumberData - 1 ];
1099             $y0 = $y + ( $data * $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} );
1100            
1101             $RefCumulateY->[ $NumberData - 1 ]
1102             += ( $data * $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} );
1103             }
1104            
1105             # space between bars
1106             if ( $spacingbar == 1 ) {
1107             $x -= $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} / 4;
1108             $x0 += $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} / 4;
1109             }
1110             }
1111            
1112             # No overwrite
1113             else {
1114             $x
1115             = $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0}
1116             + $NumberData * $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick}
1117             - ( ( $CompositeWidget->{RefInfoDummies}->{Data}{NumberRealDataBars} - $NumberBarData ) * $WidthBar );
1118             $y = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0}
1119             - ( $data * $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} );
1120            
1121             # coordinates x0 and y0 values
1122             $x0 = $x - $WidthBar;
1123             $y0 = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0};
1124            
1125             # space between bars
1126             if ( $spacingbar == 1 ) {
1127             $x -= $WidthBar / 4;
1128             $x0 += $WidthBar / 4;
1129             }
1130             }
1131            
1132             my $tag = $IdData . $CompositeWidget->{RefInfoDummies}->{TAGS}{Mixed};
1133             my $tag2 = $IdData . "_$NumberData" . $CompositeWidget->{RefInfoDummies}->{TAGS}{Mixed};
1134             $CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon}->{$tag2}
1135             = "Sample : $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData}->[0]->[$NumberData-1]\n"
1136             . "Value : $data";
1137            
1138             $CompositeWidget->createRectangle(
1139             $x0, $y0, $x, $y,
1140             -fill => $LineColor,
1141             -tags => [ $tag, $tag2, $tag_bar, $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph}, ],
1142             -width => $CompositeWidget->cget( -linewidth ),
1143             -outline => $outlinebar,
1144             );
1145             if ( $showvalues == 1 ) {
1146             $CompositeWidget->createText(
1147             $x0 + ( $x - $x0 ) / 2,
1148             $y - 8,
1149             -text => $data,
1150             -font => $CompositeWidget->{RefInfoDummies}->{Font}{DefaultBarValues},
1151             -tags => [
1152             $tag, $tag_bar,
1153             $CompositeWidget->{RefInfoDummies}->{TAGS}{BarValues},
1154             $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph},
1155             ],
1156             );
1157             }
1158            
1159             $CompositeWidget->{RefInfoDummies}{Mixed}{$tag}{color} = $LineColor;
1160             $NumberData++;
1161             }
1162            
1163             $IndexColor++;
1164             $CompositeWidget->{Index}{Color}{Line} = $IndexColor;
1165             return 1;
1166             }
1167            
1168             sub _ViewDataLines {
1169             my ( $CompositeWidget, $RefArrayData, $IdData, $dash ) = @_;
1170            
1171             my $legendmarkercolors = $CompositeWidget->cget( -colordata );
1172             my $bezier = $CompositeWidget->cget( -bezier );
1173             my $spline = $CompositeWidget->cget( -spline );
1174            
1175             my $IndexColor = $CompositeWidget->{Index}{Color}{Line};
1176             my $LineColor = $legendmarkercolors->[$IndexColor];
1177             my $NumberData = 1; # Number of data
1178             my $tag_line;
1179             if ( defined $dash ) {
1180             $tag_line = $CompositeWidget->{RefInfoDummies}->{TAGS}{Line};
1181             }
1182             else {
1183             $tag_line = $CompositeWidget->{RefInfoDummies}->{TAGS}{PointLine};
1184             }
1185             my $tag2 = $IdData . "_$NumberData" . $CompositeWidget->{RefInfoDummies}->{TAGS}{Mixed};
1186             $CompositeWidget->{RefInfoDummies}->{Legend}{MsgBalloon}->{$tag2}
1187             = $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend}->[ $IdData - 1 ];
1188            
1189             my @PointsData; # coordinate x and y
1190             foreach my $data ( @{$RefArrayData} ) {
1191             unless ( defined $data ) {
1192             $NumberData++;
1193             next;
1194             }
1195            
1196             # coordinates x and y values
1197             my $x
1198             = ( $CompositeWidget->{RefInfoDummies}->{Axis}{Cx0}
1199             + $NumberData * $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} )
1200             - ( $CompositeWidget->{RefInfoDummies}->{Axis}{Xaxis}{SpaceBetweenTick} / 2 );
1201             my $y = $CompositeWidget->{RefInfoDummies}->{Axis}{Cy0}
1202             - ( $data * $CompositeWidget->{RefInfoDummies}->{Axis}{Yaxis}{HeightUnit} );
1203             push( @PointsData, ( $x, $y ) );
1204             $NumberData++;
1205             }
1206            
1207             my $tag = $IdData . $CompositeWidget->{RefInfoDummies}->{TAGS}{Mixed};
1208            
1209             # Add control points
1210             my @PointsDataWithoutControlPoints;
1211             if ( $spline == 1 and $bezier == 1 ) {
1212             @PointsDataWithoutControlPoints = @PointsData;
1213             my $RefPointsData = $CompositeWidget->_GetControlPoints( \@PointsData );
1214             @PointsData = @{$RefPointsData};
1215             }
1216            
1217             $CompositeWidget->createLine(
1218             @PointsData,
1219             -fill => $LineColor,
1220             -tags => [ $tag, $tag2, $tag_line, $CompositeWidget->{RefInfoDummies}->{TAGS}{AllTagsDummiesGraph}, ],
1221             -width => $CompositeWidget->cget( -linewidth ),
1222             -smooth => $bezier,
1223             -dash => $dash,
1224             );
1225            
1226             # Display values above each points of lines
1227             my $LineNumber = $IdData - 1;
1228             if (@PointsDataWithoutControlPoints) {
1229             @PointsData = @PointsDataWithoutControlPoints;
1230             @PointsDataWithoutControlPoints = ();
1231             undef @PointsDataWithoutControlPoints;
1232             }
1233            
1234             if ( !( $spline == 0 and $bezier == 1 ) ) {
1235             $CompositeWidget->_display_line( \@PointsData, $LineNumber );
1236             }
1237            
1238             $CompositeWidget->{RefInfoDummies}{Mixed}{$tag}{color} = $LineColor;
1239            
1240             $IndexColor++;
1241             $CompositeWidget->{Index}{Color}{Line} = $IndexColor;
1242            
1243             if ( $spline == 0 and $bezier == 1 and $CompositeWidget->{RefInfoDummies}->{Data}{RefDataToDisplay} ) {
1244             $CompositeWidget->_error(
1245             'The values are not displayed because the curve crosses only by the extreme points.');
1246             }
1247            
1248             return 1;
1249             }
1250            
1251             sub display_order {
1252             my ( $CompositeWidget, $ref_order ) = @_;
1253            
1254             unless ( defined $ref_order ) {
1255             $ref_order = $CompositeWidget->{RefInfoDummies}->{Mixed}{Display}{Order};
1256             return unless defined $ref_order;
1257             }
1258            
1259             my %TAG = (
1260             areas => $CompositeWidget->{RefInfoDummies}->{TAGS}{Area},
1261             bars => $CompositeWidget->{RefInfoDummies}->{TAGS}{Bar},
1262             lines => $CompositeWidget->{RefInfoDummies}->{TAGS}{Line},
1263             dashlines => $CompositeWidget->{RefInfoDummies}->{TAGS}{PointLine},
1264             points => $CompositeWidget->{RefInfoDummies}->{TAGS}{Point},
1265             );
1266            
1267             # Get order from user and store it
1268             my @order = grep { exists $TAG{$_} } _delete_array_doublon($ref_order);
1269             $TAG{xTick} = $CompositeWidget->{RefInfoDummies}->{TAGS}{xTick};
1270             push( @order, 'xTick' );
1271            
1272             # tag pile order
1273             for ( my $i = 0; $i <= $#order; $i++ ) {
1274             for ( my $next = $i + 1; $next <= $#order; $next++ ) {
1275             my $test_tag_next = $CompositeWidget->find( 'withtag', $TAG{ $order[$next] } );
1276             my $test_tag_i = $CompositeWidget->find( 'withtag', $TAG{ $order[$i] } );
1277             if ( $test_tag_next and $test_tag_i ) {
1278             $CompositeWidget->raise( $TAG{ $order[$next] }, $TAG{ $order[$i] } );
1279             }
1280             }
1281             }
1282            
1283             $CompositeWidget->{RefInfoDummies}->{Mixed}{Display}{Order} = $ref_order;
1284             return;
1285             }
1286            
1287             sub plot {
1288             my ( $CompositeWidget, $RefData, %option ) = @_;
1289            
1290             my $overwrite = $CompositeWidget->cget( -overwrite );
1291             my $cumulate = $CompositeWidget->cget( -cumulate );
1292             my $yticknumber = $CompositeWidget->cget( -yticknumber );
1293             my $RefTypemixed = $CompositeWidget->cget( -typemixed );
1294            
1295             if ( defined $option{-substitutionvalue}
1296             and _isANumber( $option{-substitutionvalue} ) )
1297             {
1298             $CompositeWidget->{RefInfoDummies}->{Data}{SubstitutionValue} = $option{-substitutionvalue};
1299             }
1300            
1301             $CompositeWidget->{RefInfoDummies}->{Data}{NumberRealDataBars} = 0;
1302             if ( defined $RefTypemixed ) {
1303             foreach my $type ( @{$RefTypemixed} ) {
1304             if ( defined $type and $type eq 'bars' ) {
1305             $CompositeWidget->{RefInfoDummies}->{Data}{NumberRealDataBars}++;
1306             }
1307             }
1308             }
1309            
1310             # USe -defaulttype to calculated number of bar data
1311             elsif ( $CompositeWidget->cget( -defaulttype ) eq 'bars' ) {
1312             $CompositeWidget->{RefInfoDummies}->{Data}{NumberRealDataBars} = scalar @{$RefData} - 1;
1313             }
1314            
1315             unless ( defined $RefData ) {
1316             $CompositeWidget->_error('data not defined');
1317             return;
1318             }
1319            
1320             unless ( scalar @{$RefData} > 1 ) {
1321             $CompositeWidget->_error('You must have at least 2 arrays');
1322             return;
1323             }
1324            
1325             # Check legend and data size
1326             if ( my $RefLegend = $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend} ) {
1327             unless ( $CompositeWidget->_CheckSizeLengendAndData( $RefData, $RefLegend ) ) {
1328             undef $CompositeWidget->{RefInfoDummies}->{Legend}{DataLegend};
1329             }
1330             }
1331            
1332             # Check array size
1333             $CompositeWidget->{RefInfoDummies}->{Data}{NumberXValues} = scalar @{ $RefData->[0] };
1334             my $i = 0;
1335             my @arrayTemp = (0) x scalar @{ $RefData->[0] };
1336             foreach my $RefArray ( @{$RefData} ) {
1337             unless ( scalar @{$RefArray} == $CompositeWidget->{RefInfoDummies}->{Data}{NumberXValues} ) {
1338             $CompositeWidget->_error( 'Make sure that every array has the ' . 'same size in plot data method', 1 );
1339             return;
1340             }
1341            
1342             # Get min and max size
1343             if ( $i != 0 ) {
1344            
1345             # substitute none real value
1346             my $j = 0;
1347             foreach my $data ( @{$RefArray} ) {
1348             if ( defined $data and !_isANumber($data) ) {
1349             $data = $CompositeWidget->{RefInfoDummies}->{Data}{SubstitutionValue};
1350             }
1351             elsif ( defined $data ) {
1352             $arrayTemp[$j] += $data; # For cumulate option
1353             }
1354             $j++;
1355             }
1356             $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue}
1357             = _MaxArray( [ $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue}, _MaxArray($RefArray) ] );
1358             $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue}
1359             = _MinArray( [ $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue}, _MinArray($RefArray) ] );
1360             }
1361             $i++;
1362             }
1363             $CompositeWidget->{RefInfoDummies}->{Data}{RefXLegend} = $RefData->[0];
1364             $CompositeWidget->{RefInfoDummies}->{Data}{RefAllData} = $RefData;
1365            
1366             if ( $cumulate == 1 ) {
1367             $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue} = _MaxArray( \@arrayTemp );
1368             $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} = _MinArray( \@arrayTemp );
1369             }
1370            
1371             if ( $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} > 0 ) {
1372             $CompositeWidget->{RefInfoDummies}->{Data}{MinYValue} = 0;
1373             }
1374             while ( ( $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue} / $yticknumber ) % 5 != 0 ) {
1375             $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue}
1376             = int( $CompositeWidget->{RefInfoDummies}->{Data}{MaxYValue} + 1 );
1377             }
1378            
1379             # Plotting ok
1380             $CompositeWidget->{RefInfoDummies}->{Data}{PlotDefined} = 1;
1381             $CompositeWidget->_GraphForDummiesConstruction;
1382            
1383             return 1;
1384             }
1385            
1386             1;
1387             __END__