Tk Library Source Code

Check-in [aedaa3a34d]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2018 Conference, Houston/TX, US, Oct 15-19
Send your abstracts to tclconference@googlegroups.com
or submit via the online form by Aug 20.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Implement a large number of suggestions from the EuroTcl meeting - see ChangeLog
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:aedaa3a34da00b9db4a18fbff4a23440655d13de
User & Date: arjenmarkus 2010-06-06 12:02:56
Context
2010-06-06
15:27
Implemented an example for examining the performance. Adjusted demo.tcl to show a darkening gradient. check-in: 5324d0eda9 user: arjenmarkus tags: trunk
12:02
Implement a large number of suggestions from the EuroTcl meeting - see ChangeLog check-in: aedaa3a34d user: arjenmarkus tags: trunk
2010-06-05
21:14
* README.txt: Small corrections. * doc/tablelist.html: check-in: ed502952e7 user: nemethi tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added examples/plotchart/demo.tcl.





































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#  demo.tcl --
#      Demo program for Plotchart
#
package require Plotchart

proc demo {code} {
    .cnv delete all

    .code delete 1.0 end
    .code insert end $code

    eval $code

    vwait next
}

proc nextDemo {} {
    set ::next 1
}

button .next -text "   >   " -command nextDemo
text   .code -width 70 -height 30
canvas .cnv  -width 600 -height 600
grid .code .cnv -sticky news
grid .next -

# DEMO 1

demo {
set s [::Plotchart::createXYPlot .cnv {0.0 100.0 10.0} {0.0 100.0 20.0}]
set r [::Plotchart::createRightAxis .cnv {0.0 0.1 0.01}]

set xd    5.0
set yd   20.0
set xold  0.0
set yold 50.0

$s dataconfig series1 -colour "red"
$s dataconfig series2 -colour "blue"
$s dataconfig series3 -colour "magenta"

for { set i 0 } { $i < 20 } { incr i } {
   set xnew [expr {$xold+$xd}]
   set ynew [expr {$yold+(rand()-0.5)*$yd}]
   set ynew2 [expr {$yold+(rand()-0.5)*2.0*$yd}]
   $s plot series1 $xnew $ynew
   $s plot series2 $xnew $ynew2
   $s trend series3 $xnew $ynew2
   set xold $xnew
   set yold $ynew
}

$s interval series2 50.0 40.0 60.0 52.0
$s interval series2 60.0 40.0 60.0

$s xtext "X-coordinate"
$s ytext "Y-data"
$r ytext "Right axis"
$s title "Aha!"

#
# Some data for the right axis
#
$r dataconfig right -type both -symbol circle -colour green
$r plot right 10.0 0.01
$r plot right 30.0 0.03
$r plot right 40.0 0.02
}

demo {
set p [::Plotchart::createBoxplot .cnv {0 40 5} {A B C D E F}]

$p plot A {0 1 2 5 7 1 4 5 0.6 5 5.5}
$p plot C {2 2 3 6 1.5 3}

$p plot E {2 3 3 4 7 8 9 9 10 10 11 11 11 14 15 17 17 20 24 29}
}

# Histograms and the like
demo {
set s [::Plotchart::createBarchart .cnv {A B C D E} {0.0 10.0 2.0} 2.5]

$s plot series1 {1.0 4.0 6.0 1.0 7.0} red
$s plot series2 {0.0 3.0 7.0 9.3 2.0} green

$s legend series1 "Series 1"
$s legend series2 "Series 2"

$s title "Arbitrary data"
}

demo {
set s [::Plotchart::createPiechart .cnv]

$s plot {"Long names" 10 "Short names" 30 "Average" 40
         "Ultra-short names" 5}

$s explode auto
$s explode 1
$s title "Names - click on a segment!"
}

demo {
set s [::Plotchart::createGanttchart .cnv "1 january 2004" \
        "31 december 2004" 14]

set from [$s task "Spring" "1 march 2004" "1 june 2004" 30]
set to   [$s task "Summer" "1 june 2004" "1 september 2004" 10]
$s summary "First half" $from $to
$s connect $from $to
$s vertline "1 jan" "1 january 2004"
$s vertline "1 apr" "1 april 2004"
$s vertline "1 jul" "1 july 2004"
$s vertline "1 oct" "1 october 2004"
$s milestone "Longest day" "21 july 2004"
$s title "Seasons (northern hemisphere)"
}

demo {
::Plotchart::plotconfig horizbars leftaxis font "Helvetica 10 italic"
::Plotchart::plotconfig horizbars background outercolor steelblue3
::Plotchart::plotconfig horizbars bottomaxis ticklength -5

set s [::Plotchart::createHorizontalBarchart .cnv {0.0 10.0 2.0} \
         {Antarctica Eurasia "The Americas" "Australia and Oceania" Ocean} 2]

$s plot series1 {1.0 4.0 6.0 1.0 7.0} red left-right
$s plot series2 {0.0 3.0 7.0 9.3 2.0} green right-left
$s title "Arbitrary data"
}

# DEMO 5
demo {
proc cowboyhat {x y} {
   set x1 [expr {$x/9.0}]
   set y1 [expr {$y/9.0}]

   expr { 3.0 * (1.0-($x1*$x1+$y1*$y1))*(1.0-($x1*$x1+$y1*$y1)) }
}

set xlimits {-10. 10.  10.  }
set ylimits {-10. 10.  10.  }
set zlimits { -5. 10.   5.  }

set zmin   0.0
set zmax   3.0

set nc    51
set dz    [expr {($zmax - $zmin) / ($nc - 1)}]

set contours {}
for {set cnt 1} {$cnt < $nc} {incr cnt} {
    set zval [expr {$zmin + ($dz * ($cnt - 1))}]
    lappend contours $zval
}

set chart6 [::Plotchart::create3DPlot .cnv $xlimits $ylimits $zlimits]
::Plotchart::colorMap jet
$chart6 title "3D Plot"
$chart6 plotfuncont cowboyhat $contours
}

# DEMO 9
demo {
#
# Wind rose diagram
#
set p [::Plotchart::createWindRose .cnv {30 6} 4]

$p plot {5 10 0 3} red
$p plot {10 10 10 3} blue

$p title "Simple wind rose - margins need to be corrected ..."
}

demo {
#
# Bands in two directions
#
set p [::Plotchart::createXYPlot .cnv {0 10 2} {0 40 10}]

$p plot data 1 10
$p plot data 6 20
$p plot data 9 10

$p xband 15 25
$p yband 3 5
}

demo {
#
# Label-dots and vertical text
#

set p [::Plotchart::createXYPlot .cnv {0 10 2} {0 40 10}]

$p labeldot 3 10 "Point 1" w
$p labeldot 6 20 "Point 2" e
$p labeldot 9 10 "Point 3" n
$p labeldot 9 30 "Point 4" s
}

demo {
#
# 3D ribbon chart
#

set p [::Plotchart::create3DRibbonChart .cnv {A B C D} {0.0 1.0 0.25} {0.0 50.0 10.0}]

$p area {0.1 10.0 0.2 10.0 0.5 45.0 0.9 20.0 1.0 30.0} green
$p line {0.2 8.0 0.5 25.0 0.7 10.0 0.9 10.0 1.0 50.0} blue
}

demo {
    set s [::Plotchart::createHistogram .cnv {0.0 100.0 10.0} {0.0 100.0 20.0}]

    $s dataconfig series1 -colour green

    set xd    5.0
    set yd   20.0
    set xold  0.0
    set yold 50.0

    for { set i 0 } { $i < 20 } { incr i } {
        set xnew [expr {$xold+$xd}]
        set ynew [expr {$yold+(rand()-0.5)*$yd}]
        $s plot series1 $xnew $ynew
        set xold $xnew
        set yold $ynew
    }

    $s balloonconfig -background green -rimwidth 3 -arrowsize 10 -font "Times 14"
    $s balloon 50 50 "Here it is!"  south-east

    $s balloonconfig -background red
    $s balloonconfig -margin 10
    $s balloon 50 100 "No, here!"  north-east

    $s title "Aha!"
}

exit

Changes to examples/plotchart/plotdemos12.tcl.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
}

#
# Procedure for showing an annotation
#
proc showAnnotation {xcoord ycoord plot w} {

    $plot balloon $xcoord $ycoord "Data point: $xcoord, $ycoord" north

    after 2000 [list removeAnnotation $w]
}

#
# Procedure for erase an annotation
#







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
}

#
# Procedure for showing an annotation
#
proc showAnnotation {xcoord ycoord plot w} {

    $plot balloon $xcoord $ycoord "Data point: [format "%.3f, %.3f" $xcoord $ycoord]" north

    after 2000 [list removeAnnotation $w]
}

#
# Procedure for erase an annotation
#

Changes to modules/plotchart/ChangeLog.


















1
2
3
4
5
6
7

















2010-05-10  Arjen Markus  <arjenmarkus@users.sourceforge.net>
	* plotchart.man: Corrected documentation bug (2999846, thanks to Oliver Bienert)

2009-12-10  Arjen Markus  <arjenmarkus@users.sourceforge.net>
	* plotchart.tcl: Added configuration method for barcharts
	* plotchart.tcl: Added methods implemented by Michael Baudin for isolines
	* plotchart.man: Documented this new configuration method and isoline methods
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2010-06-06  Arjen Markus  <arjenmarkus@users.sourceforge.net>
	* demo.tcl: Added demo program showing  code and plot/chart
	* plotpriv.tcl: Moving DrawVtext to plotaxis.tcl (also checking Tk version)
	* plotpriv.tcl: Enable "exploding" segments in a piechart
	* plotbind.tcl: Provide a procedure to explode a segment in a piechart
	* plotaxis.tcl: Adjusted formatting of axis labels - Tcl 8.5 uses a large precision,
	                leading to labels like 0.09999999 instead of 0.1
	* plotaxis.tcl: Draw labels in bar charts centred wrt the bars, not the bars and gap (suggestion by Harald Oehlmann)
	* plotaxis.tcl: Moving the legend interactively via Button-1
	* scaling.tcl: Added a new scaling procedure: determineScaleFromList
	* plotchart.tcl: Added this new scaling procedure to the exports
	* plotchart.man: Describe the new scaling procedure
	* plotchart.man: Describe the bindplot and bindlast subcommands
	* plotchart.test: Added tests for the new scaling procedure
	* pkgIndex.tcl: Changed version Plotchart to 1.8.3 and xyplot to 1.0.1
	* xyplot.tcl: Updates by Jos DeCoster (adjusted version to 1.0.1)

2010-05-10  Arjen Markus  <arjenmarkus@users.sourceforge.net>
	* plotchart.man: Corrected documentation bug (2999846, thanks to Oliver Bienert)

2009-12-10  Arjen Markus  <arjenmarkus@users.sourceforge.net>
	* plotchart.tcl: Added configuration method for barcharts
	* plotchart.tcl: Added methods implemented by Michael Baudin for isolines
	* plotchart.man: Documented this new configuration method and isoline methods

Changes to modules/plotchart/pkgIndex.tcl.

1
2
3
4
5
6
if {![package vsatisfies [package provide Tcl] 8.4]} {
    # PRAGMA: returnok
    return
}
package ifneeded Plotchart 1.8.2 [list source [file join $dir plotchart.tcl]]
package ifneeded xyplot    1.0.0 [list source [file join $dir xyplot.tcl]]




|
|
1
2
3
4
5
6
if {![package vsatisfies [package provide Tcl] 8.4]} {
    # PRAGMA: returnok
    return
}
package ifneeded Plotchart 1.8.3 [list source [file join $dir plotchart.tcl]]
package ifneeded xyplot    1.0.1 [list source [file join $dir xyplot.tcl]]

Changes to modules/plotchart/plotaxis.tcl.

43
44
45
46
47
48
49




50
51
52
53
54
55
56
..
97
98
99
100
101
102
103


104
105
106
107
108
109
110
...
114
115
116
117
118
119
120




121
122
123
124
125
126
127
...
168
169
170
171
172
173
174


175
176
177
178
179
180
181
...
185
186
187
188
189
190
191




192
193
194
195
196
197
198
...
239
240
241
242
243
244
245


246
247
248
249
250
251
252
...
257
258
259
260
261
262
263




264
265
266
267
268
269
270
...
335
336
337
338
339
340
341


342
343
344
345
346
347
348
...
353
354
355
356
357
358
359




360
361
362
363
364
365
366
...
406
407
408
409
410
411
412


413
414
415
416
417
418
419
...
461
462
463
464
465
466
467























468
469
470
471
472
473
474
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
...
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
...
802
803
804
805
806
807
808





809
810
811
812
813
814
815
...
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
...
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
...
944
945
946
947
948
949
950


























































951
952
953
954
955
956
957
#    None
# Side effects:
#    Axis drawn in canvas
#
proc ::Plotchart::DrawYaxis { w ymin ymax ydelt } {
    variable scaling
    variable config





    set scaling($w,ydelt) $ydelt

    $w delete yaxis

    set linecolor  $config($w,leftaxis,color)
    set textcolor  $config($w,leftaxis,textcolor)
................................................................................

        set y  [expr {$y+abs($ydelt)}]
        set yt [expr {$yt+$ydelt}]
        if { abs($yt) < 0.5*abs($ydelt) } {
            set yt 0.0
        }
    }


}

# DrawRightaxis --
#    Draw the y-axis on the right-hand side
# Arguments:
#    w           Name of the canvas
#    ymin        Minimum y coordinate
................................................................................
#    None
# Side effects:
#    Axis drawn in canvas
#
proc ::Plotchart::DrawRightaxis { w ymin ymax ydelt } {
    variable scaling
    variable config





    set scaling($w,ydelt) $ydelt

    $w delete raxis

    set linecolor  $config($w,rightaxis,color)
    set textcolor  $config($w,rightaxis,textcolor)
................................................................................

        set y  [expr {$y+abs($ydelt)}]
        set yt [expr {$yt+$ydelt}]
        if { abs($yt) < 0.5*abs($ydelt) } {
            set yt 0.0
        }
    }


}

# DrawLogYaxis --
#    Draw the logarithmic y-axis
# Arguments:
#    w           Name of the canvas
#    ymin        Minimum y coordinate
................................................................................
#    None
# Side effects:
#    Axis drawn in canvas
#
proc ::Plotchart::DrawLogYaxis { w ymin ymax ydelt } {
    variable scaling
    variable config





    set scaling($w,ydelt) $ydelt

    $w delete yaxis

    set linecolor  $config($w,leftaxis,color)
    set textcolor  $config($w,leftaxis,textcolor)
................................................................................
            if { $factor == 1.0 } {
                $w create text $xcrd3 $ycrd -text $ylabel -tag yaxis -anchor e \
                    -fill $textcolor -font $textfont
            }
        }
        set y [expr {10.0*$y}]
    }


}

# DrawXaxis --
#    Draw the x-axis
# Arguments:
#    w           Name of the canvas
#    xmin        Minimum x coordinate
................................................................................
#    None
# Side effects:
#    Axis drawn in canvas
#
proc ::Plotchart::DrawXaxis { w xmin xmax xdelt args } {
    variable scaling
    variable config





    $w delete xaxis

    set linecolor  $config($w,bottomaxis,color)
    set textcolor  $config($w,bottomaxis,textcolor)
    set textfont   $config($w,bottomaxis,font)
    set thickness  $config($w,bottomaxis,thickness)
................................................................................
            }

            $w create line $xcrd $ycrd2 $xcrd $ycrd -tag xaxis -fill $linecolor
            $w create text $xcrd $ycrd3 -text $xlabel -tag xaxis -anchor n \
                 -fill $textcolor -font $textfont
        }
    }


}

# DrawLogXaxis --
#    Draw the logarithmic x-axis
# Arguments:
#    w           Name of the canvas
#    xmin        Minimum x coordinate
................................................................................
#    None
# Side effects:
#    Axis drawn in canvas
#
proc ::Plotchart::DrawLogXaxis { w xmin xmax xdelt args } {
    variable scaling
    variable config





    $w delete xaxis

    set linecolor  $config($w,bottomaxis,color)
    set textcolor  $config($w,bottomaxis,textcolor)
    set textfont   $config($w,bottomaxis,font)
    set thickness  $config($w,bottomaxis,thickness)
................................................................................
                    $w create text $xcrd $ycrd3 -text $xlabel -tag xaxis -anchor n \
                        -fill $textcolor -font $textfont
                }
            }
        }
        set x [expr {10.0*$x}]
    }


}

# DrawXtext --
#    Draw text to the x-axis
# Arguments:
#    w           Name of the canvas
#    text        Text to be drawn
................................................................................
        set xt $scaling($w,pxmax)
        set anchor     sw
    }
    set yt [expr {$scaling($w,pymin)-$config($w,font,char_height)/2}]

    $w create text $xt $yt -text $text -fill $textcolor -anchor $anchor -font $textfont
}
























# DrawPolarAxes --
#    Draw thw two polar axes
# Arguments:
#    w           Name of the canvas
#    rad_max     Maximum radius
#    rad_step    Step in radius
................................................................................

    $w delete xaxis

    $w create line $scaling($w,pxmin) $scaling($w,pymax) \
                   $scaling($w,pxmax) $scaling($w,pymax) \
                   -fill $linecolor -width $thickness -tag xaxis

    set x 0.5
    set scaling($w,ybase) {}
    foreach label $xlabels {
        foreach {xcrd ycrd} [coordsToPixel $w $x $scaling($w,ymin)] {break}
        set ycrd [expr {$ycrd+2}]
        $w create text $xcrd $ycrd -text $label -tag xaxis -anchor n \
            -fill $textcolor -font $textfont
        set x [expr {$x+1.0}]
................................................................................

    $w delete yaxis

    $w create line $scaling($w,pxmin) $scaling($w,pymin) \
                   $scaling($w,pxmin) $scaling($w,pymax) \
                   -fill $linecolor -width $thickness -tag yaxis

    set y 0.5
    set scaling($w,xbase) {}
    foreach label $ylabels {
        foreach {xcrd ycrd} [coordsToPixel $w $scaling($w,xmin) $y] {break}
        set xcrd [expr {$xcrd-2}]
        $w create text $xcrd $ycrd -text $label -tag yaxis -anchor e \
            -fill $textcolor -font $textfont
        set y [expr {$y+1.0}]
................................................................................

    set legend($w,background) $config($w,legend,background)
    set legend($w,border)     $config($w,legend,border)
    set legend($w,canvas)     $w
    set legend($w,position)   $config($w,legend,position)
    set legend($w,series)     ""
    set legend($w,text)       ""





}

# LegendConfigure --
#    Configure the legend
# Arguments:
#    w              Name of the canvas
#    args           Key-value pairs
................................................................................
        if { [info exists data_series($w,legendtype)] } {
            set type $data_series($w,legendtype)
        }

        # TODO: line or rectangle!

        if { $type != "rectangle" } {
            $legendw create line 0 $y 15 $y -fill $colour -tag legend

            if { $type == "symbol" || $type == "both" } {
                set symbol "dot"
                if { [info exists data_series($w,$series,-symbol)] } {
                    set symbol $data_series($w,$series,-symbol)
                }
                DrawSymbolPixel $legendw $series 7 $y $symbol $colour [list legend legend_$series]
            }
        } else {
            $legendw create rectangle 0 [expr {$y-3}] 15 [expr {$y+3}] \
                -fill $colour -tag [list legend legend_$series]
        }

        $legendw create text 25 $y -text $text -anchor w -tag [list legend legend_$series]

        incr y 10   ;# TODO: size of font!
    }

    #
    # Now the frame and the background
    #
................................................................................

    set xl [expr {$xl-2}]
    set xr [expr {$xr+2}]
    set yt [expr {$yt-2}]
    set yb [expr {$yb+2}]

    $legendw create rectangle $xl $yt $xr $yb -fill $legend($w,background) \
        -outline $legend($w,border) -tag legendbg

    $legendw raise legend

    if { $w == $legendw } {
        switch -- $legend($w,position) {
            "top-left" {
                 set dx [expr { 10+$scaling($w,pxmin)-$xl}]
................................................................................
        set dx 10
        set dy 10
    }

    $legendw move legend   $dx $dy
    $legendw move legendbg $dx $dy
}



























































# DrawTimeaxis --
#    Draw the date/time-axis
# Arguments:
#    w           Name of the canvas
#    tmin        Minimum date/time
#    tmax        Maximum date/time







>
>
>
>







 







>
>







 







>
>
>
>







 







>
>







 







>
>
>
>







 







>
>







 







>
>
>
>







 







>
>







 







>
>
>
>







 







>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







 







>
>
>
>
>







 







|






|



|


|







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
...
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
...
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
...
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
...
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
...
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
...
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
...
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
...
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
...
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
....
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
#    None
# Side effects:
#    Axis drawn in canvas
#
proc ::Plotchart::DrawYaxis { w ymin ymax ydelt } {
    variable scaling
    variable config

    # Tcl 8.5 treats numbers differently than Tcl 8.4 and previous
    set old_precision   $::tcl_precision
    set ::tcl_precision 12

    set scaling($w,ydelt) $ydelt

    $w delete yaxis

    set linecolor  $config($w,leftaxis,color)
    set textcolor  $config($w,leftaxis,textcolor)
................................................................................

        set y  [expr {$y+abs($ydelt)}]
        set yt [expr {$yt+$ydelt}]
        if { abs($yt) < 0.5*abs($ydelt) } {
            set yt 0.0
        }
    }

    set ::tcl_precision $old_precision
}

# DrawRightaxis --
#    Draw the y-axis on the right-hand side
# Arguments:
#    w           Name of the canvas
#    ymin        Minimum y coordinate
................................................................................
#    None
# Side effects:
#    Axis drawn in canvas
#
proc ::Plotchart::DrawRightaxis { w ymin ymax ydelt } {
    variable scaling
    variable config

    # Tcl 8.5 treats numbers differently than Tcl 8.4 and previous
    set old_precision   $::tcl_precision
    set ::tcl_precision 12

    set scaling($w,ydelt) $ydelt

    $w delete raxis

    set linecolor  $config($w,rightaxis,color)
    set textcolor  $config($w,rightaxis,textcolor)
................................................................................

        set y  [expr {$y+abs($ydelt)}]
        set yt [expr {$yt+$ydelt}]
        if { abs($yt) < 0.5*abs($ydelt) } {
            set yt 0.0
        }
    }

    set ::tcl_precision $old_precision
}

# DrawLogYaxis --
#    Draw the logarithmic y-axis
# Arguments:
#    w           Name of the canvas
#    ymin        Minimum y coordinate
................................................................................
#    None
# Side effects:
#    Axis drawn in canvas
#
proc ::Plotchart::DrawLogYaxis { w ymin ymax ydelt } {
    variable scaling
    variable config

    # Tcl 8.5 treats numbers differently than Tcl 8.4 and previous
    set old_precision   $::tcl_precision
    set ::tcl_precision 12

    set scaling($w,ydelt) $ydelt

    $w delete yaxis

    set linecolor  $config($w,leftaxis,color)
    set textcolor  $config($w,leftaxis,textcolor)
................................................................................
            if { $factor == 1.0 } {
                $w create text $xcrd3 $ycrd -text $ylabel -tag yaxis -anchor e \
                    -fill $textcolor -font $textfont
            }
        }
        set y [expr {10.0*$y}]
    }

    set ::tcl_precision $old_precision
}

# DrawXaxis --
#    Draw the x-axis
# Arguments:
#    w           Name of the canvas
#    xmin        Minimum x coordinate
................................................................................
#    None
# Side effects:
#    Axis drawn in canvas
#
proc ::Plotchart::DrawXaxis { w xmin xmax xdelt args } {
    variable scaling
    variable config

    # Tcl 8.5 treats numbers differently than Tcl 8.4 and previous
    set old_precision   $::tcl_precision
    set ::tcl_precision 12

    $w delete xaxis

    set linecolor  $config($w,bottomaxis,color)
    set textcolor  $config($w,bottomaxis,textcolor)
    set textfont   $config($w,bottomaxis,font)
    set thickness  $config($w,bottomaxis,thickness)
................................................................................
            }

            $w create line $xcrd $ycrd2 $xcrd $ycrd -tag xaxis -fill $linecolor
            $w create text $xcrd $ycrd3 -text $xlabel -tag xaxis -anchor n \
                 -fill $textcolor -font $textfont
        }
    }

    set ::tcl_precision $old_precision
}

# DrawLogXaxis --
#    Draw the logarithmic x-axis
# Arguments:
#    w           Name of the canvas
#    xmin        Minimum x coordinate
................................................................................
#    None
# Side effects:
#    Axis drawn in canvas
#
proc ::Plotchart::DrawLogXaxis { w xmin xmax xdelt args } {
    variable scaling
    variable config

    # Tcl 8.5 treats numbers differently than Tcl 8.4 and previous
    set old_precision   $::tcl_precision
    set ::tcl_precision 12

    $w delete xaxis

    set linecolor  $config($w,bottomaxis,color)
    set textcolor  $config($w,bottomaxis,textcolor)
    set textfont   $config($w,bottomaxis,font)
    set thickness  $config($w,bottomaxis,thickness)
................................................................................
                    $w create text $xcrd $ycrd3 -text $xlabel -tag xaxis -anchor n \
                        -fill $textcolor -font $textfont
                }
            }
        }
        set x [expr {10.0*$x}]
    }

    set ::tcl_precision $old_precision
}

# DrawXtext --
#    Draw text to the x-axis
# Arguments:
#    w           Name of the canvas
#    text        Text to be drawn
................................................................................
        set xt $scaling($w,pxmax)
        set anchor     sw
    }
    set yt [expr {$scaling($w,pymin)-$config($w,font,char_height)/2}]

    $w create text $xt $yt -text $text -fill $textcolor -anchor $anchor -font $textfont
}

# DrawVtext --
#    Draw vertical text to the y-axis
# Arguments:
#    w           Name of the canvas
#    text        Text to be drawn
# Result:
#    None
# Side effects:
#    Text drawn in canvas
# Note:
#    This requires Tk 8.6 or later
#
proc ::Plotchart::DrawVtext { w text } {
    variable scaling

    if { [package vsatisfies [package version Tk] 8.6] } {
        set xt [expr {$scaling($w,pxmin) + 5}]
        set yt [expr {($scaling($w,pymin) + $scaling($w,pymax)) / 2}]

        $w create text $xt $yt -text $text -fill black -anchor n -angle 90
    }
}

# DrawPolarAxes --
#    Draw thw two polar axes
# Arguments:
#    w           Name of the canvas
#    rad_max     Maximum radius
#    rad_step    Step in radius
................................................................................

    $w delete xaxis

    $w create line $scaling($w,pxmin) $scaling($w,pymax) \
                   $scaling($w,pxmax) $scaling($w,pymax) \
                   -fill $linecolor -width $thickness -tag xaxis

    set x [expr {int($noseries)/(2.0*$noseries)}]
    set scaling($w,ybase) {}
    foreach label $xlabels {
        foreach {xcrd ycrd} [coordsToPixel $w $x $scaling($w,ymin)] {break}
        set ycrd [expr {$ycrd+2}]
        $w create text $xcrd $ycrd -text $label -tag xaxis -anchor n \
            -fill $textcolor -font $textfont
        set x [expr {$x+1.0}]
................................................................................

    $w delete yaxis

    $w create line $scaling($w,pxmin) $scaling($w,pymin) \
                   $scaling($w,pxmin) $scaling($w,pymax) \
                   -fill $linecolor -width $thickness -tag yaxis

    set y [expr {int($noseries)/(2.0*$noseries)}]
    set scaling($w,xbase) {}
    foreach label $ylabels {
        foreach {xcrd ycrd} [coordsToPixel $w $scaling($w,xmin) $y] {break}
        set xcrd [expr {$xcrd-2}]
        $w create text $xcrd $ycrd -text $label -tag yaxis -anchor e \
            -fill $textcolor -font $textfont
        set y [expr {$y+1.0}]
................................................................................

    set legend($w,background) $config($w,legend,background)
    set legend($w,border)     $config($w,legend,border)
    set legend($w,canvas)     $w
    set legend($w,position)   $config($w,legend,position)
    set legend($w,series)     ""
    set legend($w,text)       ""
    set legend($w,move)       0

    $w bind legendobj <ButtonPress-1>   [list ::Plotchart::LegendAnchor $w %x %y]
    $w bind legendobj <Motion>          [list ::Plotchart::LegendMove   $w %x %y]
    $w bind legendobj <ButtonRelease-1> [list ::Plotchart::LegendRelease $w]
}

# LegendConfigure --
#    Configure the legend
# Arguments:
#    w              Name of the canvas
#    args           Key-value pairs
................................................................................
        if { [info exists data_series($w,legendtype)] } {
            set type $data_series($w,legendtype)
        }

        # TODO: line or rectangle!

        if { $type != "rectangle" } {
            $legendw create line 0 $y 15 $y -fill $colour -tag {legend legendobj}

            if { $type == "symbol" || $type == "both" } {
                set symbol "dot"
                if { [info exists data_series($w,$series,-symbol)] } {
                    set symbol $data_series($w,$series,-symbol)
                }
                DrawSymbolPixel $legendw $series 7 $y $symbol $colour [list legend legendobj legend_$series]
            }
        } else {
            $legendw create rectangle 0 [expr {$y-3}] 15 [expr {$y+3}] \
                -fill $colour -tag [list legend legendobj legend_$series]
        }

        $legendw create text 25 $y -text $text -anchor w -tag [list legend legendobj legend_$series]

        incr y 10   ;# TODO: size of font!
    }

    #
    # Now the frame and the background
    #
................................................................................

    set xl [expr {$xl-2}]
    set xr [expr {$xr+2}]
    set yt [expr {$yt-2}]
    set yb [expr {$yb+2}]

    $legendw create rectangle $xl $yt $xr $yb -fill $legend($w,background) \
        -outline $legend($w,border) -tag {legendbg legendobj}

    $legendw raise legend

    if { $w == $legendw } {
        switch -- $legend($w,position) {
            "top-left" {
                 set dx [expr { 10+$scaling($w,pxmin)-$xl}]
................................................................................
        set dx 10
        set dy 10
    }

    $legendw move legend   $dx $dy
    $legendw move legendbg $dx $dy
}

# LegendAnchor --
#    Record the coordinates of the button press -
#    for moving the legend
# Arguments:
#    w           Name of the canvas
#    x           X-coordinate
#    y           Y-coordinate
# Result:
#    None
# Side effects:
#    X and Y stored
#
proc ::Plotchart::LegendAnchor { w x y } {
    variable legend

    set legend($w,move)    1
    set legend($w,xbutton) $x
    set legend($w,ybutton) $y
}

# LegendRelease --
#    Release the legend - it no longer moves
# Arguments:
#    w           Name of the canvas
# Result:
#    None
#
proc ::Plotchart::LegendRelease { w } {
    variable legend

    set legend($w,move)    0
}

# LegendMove --
#    Move the legend objects
# Arguments:
#    w           Name of the canvas
#    x           X-coordinate
#    y           Y-coordinate
# Result:
#    None
# Side effects:
#    Legend moved
#
proc ::Plotchart::LegendMove { w x y } {
    variable legend

    if { $legend($w,move) } {
        set dx [expr {$x - $legend($w,xbutton)}]
        set dy [expr {$y - $legend($w,ybutton)}]

        $w move legendobj $dx $dy

        set legend($w,xbutton) $x
        set legend($w,ybutton) $y
    }
}

# DrawTimeaxis --
#    Draw the date/time-axis
# Arguments:
#    w           Name of the canvas
#    tmin        Minimum date/time
#    tmax        Maximum date/time

Changes to modules/plotchart/plotbind.tcl.

79
80
81
82
83
84
85

























































86
87
88
89
90
91
92
    variable scaling

    foreach {x y} [pixelToCoords $w $xcoord $ycoord] {break}

    eval [lindex $cmd 0] $x $y [lrange $cmd 1 end]

}


























































if {0} {

-- this represents an old idea. Keeping it around for the moment --

# BindVar --
#     Bind a variable to a mouse event







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
    variable scaling

    foreach {x y} [pixelToCoords $w $xcoord $ycoord] {break}

    eval [lindex $cmd 0] $x $y [lrange $cmd 1 end]

}

# PieExplodeSegment --
#     Move the indicated segment
#
# Arguments:
#     w               Widget
#     segment         Segment to move
#     button          Whether it came from a button event or not
#
# Result:
#     None
#
# Note:
#     If the segment is "auto", then we accept button clicks
#
proc ::Plotchart::PieExplodeSegment {w segment {button 0}} {
    variable scaling

    console show
    puts "Segment, button: $segment, $button"

    if { $button && $scaling($w,auto) == 0 } {
        return
    }

    if { $segment == "auto" } {
        set scaling($w,auto) 1
        return
    } else {
        if { $segment < 0 || $segment >= [llength $scaling($w,angles)] } {
            return
        }
    }

    if { $scaling($w,exploded) != -1 } {
        $w move segment_$scaling($w,exploded) [expr {-$scaling($w,xexploded)}] [expr {-$scaling($w,yexploded)}]
    }

    if { $segment == $scaling($w,exploded) } {
        set scaling($w,exploded) -1
    } else {
        set angle_bgn [lindex $scaling($w,angles) $segment]
        set angle_ext [lindex $scaling($w,extent) $segment]

        set angle     [expr {3.1415926*($angle_bgn+$angle_ext/2.0)/180.0}]
        set dx        [expr { 15 * cos($angle)}]
        set dy        [expr {-15 * sin($angle)}]

        set scaling($w,exploded)  $segment
        set scaling($w,xexploded) $dx
        set scaling($w,yexploded) $dy
        $w move segment_$segment $dx $dy
    }
}




if {0} {

-- this represents an old idea. Keeping it around for the moment --

# BindVar --
#     Bind a variable to a mouse event

Changes to modules/plotchart/plotchart.man.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
..
90
91
92
93
94
95
96



97
98
99
100
101
102
103
...
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
....
1557
1558
1559
1560
1561
1562
1563













1564
1565
1566
1567
1568
1569
1570
....
2378
2379
2380
2381
2382
2383
2384
















2385
2386
2387
2388
2389
2390
2391
....
2860
2861
2862
2863
2864
2865
2866












































































































2867
2868
2869
2870
2871
2872
2873
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin Plotchart n 1.8]
[copyright {2009 Arjen Markus <arjenmarkus@users.sourceforge.net>}]
[moddesc   Plotchart]
[titledesc {Simple plotting and charting package}]
[require Tcl [opt 8.4]]
[require Tk [opt 8.4]]
[require Plotchart [opt 1.8]]

[description]
[para]

Plotchart is a Tcl-only package that focuses on the easy creation of
xy-plots, barcharts and other common types of graphical presentations.
The emphasis is on ease of use, rather than flexibility. The procedures
................................................................................
[item]
3D plots (both for displaying surfaces and 3D bars)
[list_end]

With version 1.5 a new command has been introduced: plotconfig, which
can be used to configure the plot options for particular types of plots
and charts (cf. [sectref "CONFIGURATION OPTIONS"])




[section "PLOT CREATION COMMANDS"]

You create the plot or chart with one single command and then fill the
plot with data:

[list_begin definitions]
................................................................................
[arg_def string text in]
The text of the y-axis label to be drawn.

[list_end]

[call [cmd \$anyplot] vtext [arg text]]
Draw a [emph vertical] label to the y-axis. Note: this requires Tk 8.6
or later.

[list_begin arguments]
[arg_def string text in]
Text to drawn to the y-axis

[list_end]

................................................................................
[arg_def color colour1 in]
The first colour.

[arg_def color colour2 in]
The second colour, and so on.

[list_end]













[list_end]
[para]

For [emph "radial charts"]:

[list_begin definitions]
[call [cmd \$radial] plot [arg data] [arg colour] [arg thickness]]
................................................................................
[arg_def float xmax in]
Rough maximum value for the scaling.

[arg_def boolean inverted in]
Optional argument: if 1, then the returned list produces an
inverted axis. Defaults to 0 (the axis will be from minimum to maximum)

















[list_end]
[list_end]


[section {MISSING VALUES}]
Often data that need to be plotted contain gaps - in a series of
measurement data, they can occur because the equipment failed, a sample
................................................................................
    pack [canvas .t.c2 -width ...]

    #
    # Copy the two plots above each other in the new canvas
    #
    plotpack .t.c2 top $p1 $p2
}]













































































































[section {NOTES ON TAGS}]
P.M.



[section {TODO - SOME PRIVATE NOTES}]

|





|







 







>
>
>







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
..
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
...
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
....
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
....
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
....
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
[comment {-*- tcl -*- doctools manpage}]
[manpage_begin Plotchart n 1.8.3]
[copyright {2009 Arjen Markus <arjenmarkus@users.sourceforge.net>}]
[moddesc   Plotchart]
[titledesc {Simple plotting and charting package}]
[require Tcl [opt 8.4]]
[require Tk [opt 8.4]]
[require Plotchart [opt 1.8.3]]

[description]
[para]

Plotchart is a Tcl-only package that focuses on the easy creation of
xy-plots, barcharts and other common types of graphical presentations.
The emphasis is on ease of use, rather than flexibility. The procedures
................................................................................
[item]
3D plots (both for displaying surfaces and 3D bars)
[list_end]

With version 1.5 a new command has been introduced: plotconfig, which
can be used to configure the plot options for particular types of plots
and charts (cf. [sectref "CONFIGURATION OPTIONS"])

With version 1.8.3 several new features were introduced, which allow more interactivity
(cf. [sectref "INTERACTIVE USE"])

[section "PLOT CREATION COMMANDS"]

You create the plot or chart with one single command and then fill the
plot with data:

[list_begin definitions]
................................................................................
[arg_def string text in]
The text of the y-axis label to be drawn.

[list_end]

[call [cmd \$anyplot] vtext [arg text]]
Draw a [emph vertical] label to the y-axis. Note: this requires Tk 8.6
or later, for older versions it does nothing.

[list_begin arguments]
[arg_def string text in]
Text to drawn to the y-axis

[list_end]

................................................................................
[arg_def color colour1 in]
The first colour.

[arg_def color colour2 in]
The second colour, and so on.

[list_end]

[call [cmd \$pie] explode [arg segment]

Explode a segment (that is: move one segment out of the circle). If the segment is
indicated as "auto", then you can click on a segment. This will be exploded instead of
any previously exploded segment.

[list_begin arguments]
[arg_def int segment]
The segment to be exploded or "auto" if you want to do this interactively.

[list_end]

[list_end]
[para]

For [emph "radial charts"]:

[list_begin definitions]
[call [cmd \$radial] plot [arg data] [arg colour] [arg thickness]]
................................................................................
[arg_def float xmax in]
Rough maximum value for the scaling.

[arg_def boolean inverted in]
Optional argument: if 1, then the returned list produces an
inverted axis. Defaults to 0 (the axis will be from minimum to maximum)

[list_end]

[call [cmd ::Plotchart::determineScaleFromList] [arg values] [arg inverted]]

Determine "pretty" numbers from the given list of values and return a list
containing the minimum, maximum and stepsize that can be used for a
(linear) axis.

[list_begin arguments]
[arg_def float values in]
List of values that will be examined. May contain missing values (empty strings)

[arg_def boolean inverted in]
Optional argument: if 1, then the returned list produces an
inverted axis. Defaults to 0 (the axis will be from minimum to maximum)

[list_end]
[list_end]


[section {MISSING VALUES}]
Often data that need to be plotted contain gaps - in a series of
measurement data, they can occur because the equipment failed, a sample
................................................................................
    pack [canvas .t.c2 -width ...]

    #
    # Copy the two plots above each other in the new canvas
    #
    plotpack .t.c2 top $p1 $p2
}]

[section {INTERACTIVE USE}]
[emph Plotchart} has several features for interactive use (cf. [sectref {NOTES ON TAGS}]):

[list_begin itemized]

[item]
The legend can be moved around by pressing mouse button 1 in the legend's box and
keeping it down.

[item]
You can use the [emph bindplot] and [emph bindlast] commands to
define actions that are to be taken when the user clicks on an element of the plot or chart.
(see below, see also the sample code in plotdemos12.tcl)

[item]
[emph Piecharts] can show an "exploded" segment that you can select with mouse button 1.

[list_end]

If you require different forms of interaction, not covered by [emph Plotchart] itself,
you can use the tags on the various canvas elements to define other bindings.

[para]
The [emph bindplot] and [emph bindlast] are defined as follows:
[list_begin definitions]

[call [cmd \$anyplot bindplot [arg event] [arg command] [arg args]]
Register a command that will be run whenever the given event occurs in the plot.

[list_begin arguments]
[arg_def string event]
The event that you want to bind the command to

[arg_def string command]
Name of the command/procedure that you want to run. The following arguments
are prefixed: the x- and y-coordinates of the point in the plot (the world coordinates!),
so that the procedure has the signature:
[example {
    cmd $xworld $yworld $string1 $string2 $string3
}]
assuming the argument "command" is: {cmd A B C}

[list_end]

[call [cmd \$anyplot bindlast [arg series] [arg event] [arg command]]
Register a command that will be run when the event occurs within the neighbourhood of
the last point added to the given series. (You can use directly after inserting
a data point. All such commands will remain active).

[list_begin arguments]
[arg_def string event]
The event that you want to bind the command to

[arg_def list command]
Name of the command/procedure that you want to run. The following arguments
are prefixed: the x- and y-coordinates of the point in the plot (the world coordinates!),
so that the procedure has the signature:
[example {
    cmd $xworld $yworld $string1 $string2 $string3
}]
assuming the argument "command" is: {cmd A B C}

[list_end]
[list_end]

Here is an example - show the values of the data points in an annotation
(from the sample code in plotdemos12.tcl):
[example {
#
# Procedure for showing an annotation
#
proc showAnnotation {xcoord ycoord plot w} {

    $plot balloon $xcoord $ycoord "Data point: [format "%.3f, %.3f" $xcoord $ycoord]" north

    after 2000 [list removeAnnotation $w]
}

#
# Procedure for erase an annotation
#
proc removeAnnotation {w} {

    # Use the tags to remove all annotations
    $w delete BalloonText
    $w delete BalloonFrame
}

#
# Create a simple plot and a label
#
pack [canvas .c -bg white] [label .l -textvariable coords]

set p [::Plotchart::createXYPlot .c {0 1000 200} {0 10 1}]

$p dataconfig series1 -type both -symbol cross

foreach x {1 2 5 10 20 50 100 200 500 1000} {
    $p plot series1 $x [expr {log($x)}]

    #
    # Show the annotation for each data point
    #
    $p bindlast series1 <Enter> [list showAnnotation $p %W]
}
}]


[section {NOTES ON TAGS}]
P.M.



[section {TODO - SOME PRIVATE NOTES}]

Changes to modules/plotchart/plotchart.tcl.

19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
..
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
...
142
143
144
145
146
147
148

149
150
151
152
153
154
155
....
1012
1013
1014
1015
1016
1017
1018

1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035



1036
1037
1038
1039
1040
1041
1042
....
1854
1855
1856
1857
1858
1859
1860
1861
   variable methodProc
   variable data_series

   namespace export worldCoordinates viewPort coordsToPixel \
                    polarCoordinates setZoomPan \
                    world3DCoordinates coordsToPixel \
                    coords3DToPixel polarToPixel \
                    pixelToCoords pixelToIndex determineScale \

                    createXYPlot createPolarPlot createPiechart \
                    createBarchart createHorizontalBarchart \
                    createTimechart createStripchart \
                    createIsometricPlot create3DPlot \
                    createGanttChart createHistogram colorMap \
                    create3DBars createRadialchart \
                    createTXPlot createRightAxis \
................................................................................
   set methodProc(xyplot,rescale)           RescalePlot
   set methodProc(xyplot,box-and-whiskers)  DrawBoxWhiskers
   set methodProc(xyplot,xband)             DrawXband
   set methodProc(xyplot,yband)             DrawYband
   set methodProc(xyplot,labeldot)          DrawLabelDot
   set methodProc(xyplot,bindplot)          BindPlot
   set methodProc(xyplot,bindlast)          BindLast
   set methodProc(xyplot,bindseries)        BindSeries
   set methodProc(xyplot,contourlinesfunctionvalues)      DrawIsolinesFunctionValues
   set methodProc(xyplot,contourlinesfunctionpoints)      DrawIsolinesFunctionPoints
   set methodProc(xlogyplot,title)          DrawTitle
   set methodProc(xlogyplot,xtext)          DrawXtext
   set methodProc(xlogyplot,ytext)          DrawYtext
   set methodProc(xlogyplot,vtext)          DrawVtext
   set methodProc(xlogyplot,plot)           DrawLogYData
................................................................................
   set methodProc(logxlogyplot,balloonconfig)  ConfigBalloon
   set methodProc(logxlogyplot,plaintext)      DrawPlainText
   set methodProc(piechart,title)           DrawTitle
   set methodProc(piechart,plot)            DrawPie
   set methodProc(piechart,saveplot)        SavePlot
   set methodProc(piechart,balloon)         DrawBalloon
   set methodProc(piechart,balloonconfig)   ConfigBalloon

   set methodProc(piechart,plaintext)       DrawPlainText
   set methodProc(polarplot,title)          DrawTitle
   set methodProc(polarplot,plot)           DrawPolarData
   set methodProc(polarplot,saveplot)       SavePlot
   set methodProc(polarplot,dataconfig)     DataConfig
   set methodProc(polarplot,background)     BackgroundColour
   set methodProc(polarplot,legendconfig)   LegendConfigure
................................................................................
# Result:
#    Name of a new command
# Note:
#    The entire canvas will be dedicated to the pie chart.
#
proc ::Plotchart::createPiechart { w } {
   variable data_series


   foreach s [array names data_series "$w,*"] {
      unset data_series($s)
   }

   set newchart "piechart_$w"
   interp alias {} $newchart {} ::Plotchart::PlotHandler piechart $w
   CopyConfig piechart $w

   foreach {pxmin pymin pxmax pymax} [MarginsCircle $w] {break}

   viewPort $w $pxmin $pymin $pxmax $pymax
   $w create oval $pxmin $pymin $pxmax $pymax

   SetColours $w blue lightblue green yellow orange red magenta brown
   DefaultLegend  $w
   DefaultBalloon $w




   return $newchart
}

# createPolarplot --
#    Create a command for drawing a polar plot
# Arguments:
................................................................................
source [file join [file dirname [info script]] "plotannot.tcl"]
source [file join [file dirname [info script]] "plotconfig.tcl"]
source [file join [file dirname [info script]] "plotpack.tcl"]
source [file join [file dirname [info script]] "plotbind.tcl"]

# Announce our presence
#
package provide Plotchart 1.8.2







|
>







 







<







 







>







 







>












|




>
>
>







 







|
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
72
73
74
75
76
77
78

79
80
81
82
83
84
85
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
....
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
....
1859
1860
1861
1862
1863
1864
1865
1866
   variable methodProc
   variable data_series

   namespace export worldCoordinates viewPort coordsToPixel \
                    polarCoordinates setZoomPan \
                    world3DCoordinates coordsToPixel \
                    coords3DToPixel polarToPixel \
                    pixelToCoords pixelToIndex \
                    determineScale determineScaleFromList \
                    createXYPlot createPolarPlot createPiechart \
                    createBarchart createHorizontalBarchart \
                    createTimechart createStripchart \
                    createIsometricPlot create3DPlot \
                    createGanttChart createHistogram colorMap \
                    create3DBars createRadialchart \
                    createTXPlot createRightAxis \
................................................................................
   set methodProc(xyplot,rescale)           RescalePlot
   set methodProc(xyplot,box-and-whiskers)  DrawBoxWhiskers
   set methodProc(xyplot,xband)             DrawXband
   set methodProc(xyplot,yband)             DrawYband
   set methodProc(xyplot,labeldot)          DrawLabelDot
   set methodProc(xyplot,bindplot)          BindPlot
   set methodProc(xyplot,bindlast)          BindLast

   set methodProc(xyplot,contourlinesfunctionvalues)      DrawIsolinesFunctionValues
   set methodProc(xyplot,contourlinesfunctionpoints)      DrawIsolinesFunctionPoints
   set methodProc(xlogyplot,title)          DrawTitle
   set methodProc(xlogyplot,xtext)          DrawXtext
   set methodProc(xlogyplot,ytext)          DrawYtext
   set methodProc(xlogyplot,vtext)          DrawVtext
   set methodProc(xlogyplot,plot)           DrawLogYData
................................................................................
   set methodProc(logxlogyplot,balloonconfig)  ConfigBalloon
   set methodProc(logxlogyplot,plaintext)      DrawPlainText
   set methodProc(piechart,title)           DrawTitle
   set methodProc(piechart,plot)            DrawPie
   set methodProc(piechart,saveplot)        SavePlot
   set methodProc(piechart,balloon)         DrawBalloon
   set methodProc(piechart,balloonconfig)   ConfigBalloon
   set methodProc(piechart,explode)         PieExplodeSegment
   set methodProc(piechart,plaintext)       DrawPlainText
   set methodProc(polarplot,title)          DrawTitle
   set methodProc(polarplot,plot)           DrawPolarData
   set methodProc(polarplot,saveplot)       SavePlot
   set methodProc(polarplot,dataconfig)     DataConfig
   set methodProc(polarplot,background)     BackgroundColour
   set methodProc(polarplot,legendconfig)   LegendConfigure
................................................................................
# Result:
#    Name of a new command
# Note:
#    The entire canvas will be dedicated to the pie chart.
#
proc ::Plotchart::createPiechart { w } {
   variable data_series
   variable scaling

   foreach s [array names data_series "$w,*"] {
      unset data_series($s)
   }

   set newchart "piechart_$w"
   interp alias {} $newchart {} ::Plotchart::PlotHandler piechart $w
   CopyConfig piechart $w

   foreach {pxmin pymin pxmax pymax} [MarginsCircle $w] {break}

   viewPort $w $pxmin $pymin $pxmax $pymax
  #$w create oval $pxmin $pymin $pxmax $pymax

   SetColours $w blue lightblue green yellow orange red magenta brown
   DefaultLegend  $w
   DefaultBalloon $w

   set scaling($w,auto)      0
   set scaling($w,exploded) -1

   return $newchart
}

# createPolarplot --
#    Create a command for drawing a polar plot
# Arguments:
................................................................................
source [file join [file dirname [info script]] "plotannot.tcl"]
source [file join [file dirname [info script]] "plotconfig.tcl"]
source [file join [file dirname [info script]] "plotpack.tcl"]
source [file join [file dirname [info script]] "plotbind.tcl"]

# Announce our presence
#
package provide Plotchart 1.8.3

Changes to modules/plotchart/plotchart.test.

158
159
160
161
162
163
164








165
166
167
168
169
170
171
test Plotchart-2.11 {Nice scale 8} -match numbers -body {
    ::Plotchart::determineScale -1.7 26.8
} -result {-10.0 30.0 10.0}

test Plotchart-2.12 {Nice scale 9} -match numbers -body {
    ::Plotchart::determineScale 0.99999999999999911  1.0000000000000007
} -result {0.999999994 1.000000006 2e-009}











test Plotchart-3.1 {XY-plot} -constraints tk -body {
    canvas .c -width 300 -height 200 -bg white
    pack   .c -fill both
    .c delete all







>
>
>
>
>
>
>
>







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
test Plotchart-2.11 {Nice scale 8} -match numbers -body {
    ::Plotchart::determineScale -1.7 26.8
} -result {-10.0 30.0 10.0}

test Plotchart-2.12 {Nice scale 9} -match numbers -body {
    ::Plotchart::determineScale 0.99999999999999911  1.0000000000000007
} -result {0.999999994 1.000000006 2e-009}

test Plotchart-2.13 {Nice scale from list} -match numbers -body {
    ::Plotchart::determineScaleFromList {-0.25 -0.1 0.6 0.6 0.85}
} -result {-0.4 1.0 0.2}

test Plotchart-2.14 {Nice scale from list with missing data} -match numbers -body {
    ::Plotchart::determineScaleFromList {-0.25 -0.1 0.6 {} {} {} 0.6 0.85}
} -result {-0.4 1.0 0.2}



test Plotchart-3.1 {XY-plot} -constraints tk -body {
    canvas .c -width 300 -height 200 -bg white
    pack   .c -fill both
    .c delete all

Changes to modules/plotchart/plotpriv.tcl.

1019
1020
1021
1022
1023
1024
1025
1026

1027
1028

1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041

1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057


1058

1059
1060
1061
1062
1063
1064
1065
....
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
       #
       # Draw the line piece
       #
       set angle_bgn 0.0
       set angle_ext 0.0
       set sum       0.0

       set idx 0


       array unset scaling ${w},angles

       set colours [CycleColours ${colours} [expr {[llength ${data}] / 2}]]

       foreach {label value} $data {
          set colour [lindex $colours $idx]
          incr idx

          if { $value == "" } {
              break
          }

          set angle_bgn [expr {$sum   * $factor}]
          set angle_ext [expr {$value * $factor}]
          lappend scaling(${w},angles) [expr {int(${angle_bgn})}]


          $w create arc  $pxmin $pymin $pxmax $pymax \
                         -start $angle_bgn -extent $angle_ext \
                         -fill $colour -style pieslice

          set rad   [expr {($angle_bgn+0.5*$angle_ext)*3.1415926/180.0}]
          set xtext [expr {($pxmin+$pxmax+cos($rad)*($pxmax-$pxmin+20))/2}]
          set ytext [expr {($pymin+$pymax-sin($rad)*($pymax-$pymin+20))/2}]
          if { $xtext > ($pxmin+$pymax)/2 } {
             set dir w
          } else {
             set dir e
          }

          $w create text $xtext $ytext -text $label -anchor $dir



          set sum [expr {$sum + $value}]

       }
   }
}

# DrawPolarData --
#    Draw data given in polar coordinates
# Arguments:
................................................................................

    set xcrd [expr {$rad*cos($phi*$torad)}]
    set ycrd [expr {$rad*sin($phi*$torad)}]

    DrawLabelDot $w $xcrd $ycrd $text $orient
}

# DrawVtext --
#    Draw vertical text to the y-axis
# Arguments:
#    w           Name of the canvas
#    text        Text to be drawn
# Result:
#    None
# Side effects:
#    Text drawn in canvas
# Note:
#    This requires Tk 8.6 or later
#
proc ::Plotchart::DrawVtext { w text } {
   variable scaling

   set xt [expr {$scaling($w,pxmin) + 5}]
   set yt [expr {($scaling($w,pymin) + $scaling($w,pymax)) / 2}]

   $w create text $xt $yt -text $text -fill black -anchor n -angle 90
}

# ConfigBar --
#    Configuration options for vertical and horizontal barcharts
# Arguments:
#    w           Name of the canvas
#    args        List of arguments
# Result:
#    None







|
>


>













>



|










|

>
>

>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
....
2637
2638
2639
2640
2641
2642
2643





















2644
2645
2646
2647
2648
2649
2650
       #
       # Draw the line piece
       #
       set angle_bgn 0.0
       set angle_ext 0.0
       set sum       0.0

       set idx     0
       set segment 0

       array unset scaling ${w},angles
       array unset scaling ${w},extent
       set colours [CycleColours ${colours} [expr {[llength ${data}] / 2}]]

       foreach {label value} $data {
          set colour [lindex $colours $idx]
          incr idx

          if { $value == "" } {
              break
          }

          set angle_bgn [expr {$sum   * $factor}]
          set angle_ext [expr {$value * $factor}]
          lappend scaling(${w},angles) [expr {int(${angle_bgn})}]
          lappend scaling(${w},extent) [expr {int(${angle_ext})}]

          $w create arc  $pxmin $pymin $pxmax $pymax \
                         -start $angle_bgn -extent $angle_ext \
                         -fill $colour -style pieslice -tag segment_$segment

          set rad   [expr {($angle_bgn+0.5*$angle_ext)*3.1415926/180.0}]
          set xtext [expr {($pxmin+$pxmax+cos($rad)*($pxmax-$pxmin+20))/2}]
          set ytext [expr {($pymin+$pymax-sin($rad)*($pymax-$pymin+20))/2}]
          if { $xtext > ($pxmin+$pymax)/2 } {
             set dir w
          } else {
             set dir e
          }

          $w create text $xtext $ytext -text $label -anchor $dir -tag segment_$segment

          $w bind segment_$segment <ButtonPress-1> [list ::Plotchart::PieExplodeSegment $w $segment 1]

          set sum [expr {$sum + $value}]
          incr segment
       }
   }
}

# DrawPolarData --
#    Draw data given in polar coordinates
# Arguments:
................................................................................

    set xcrd [expr {$rad*cos($phi*$torad)}]
    set ycrd [expr {$rad*sin($phi*$torad)}]

    DrawLabelDot $w $xcrd $ycrd $text $orient
}






















# ConfigBar --
#    Configuration options for vertical and horizontal barcharts
# Arguments:
#    w           Name of the canvas
#    args        List of arguments
# Result:
#    None

Added modules/plotchart/plotscada.tcl.





































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# plotscada.tcl --
#     Facilities for plotting "SCADA" displays:
#     - Schematic drawings of a factory for instance
#       and measured values in the various parts
#     - Telemetry systems
#

source plotchart.tcl

namespace eval ::Plotchart {

   set methodProc(scada,scaling)           ScadaScaling
   set methodProc(scada,axis)              ScadaAxis
   set methodProc(scada,object)            ScadaObject
   set methodProc(scada,plot)              ScadaPlot
   set methodProc(scada,angular-scaling)   ScadaAngularScaling
}

# createScada --
#     Create a new command for plotting SCADA displays
#
# Arguments:
#    w             Name of the canvas
# Result:
#    Name of a new command
# Note:
#    The entire canvas will be dedicated to the display
#
proc ::Plotchart::createScada { w } {
    variable scada_scaling

    set newchart "scada_$w"
    interp alias {} $newchart {} ::Plotchart::PlotHandler scada $w
    #CopyConfig scada $w

    set pxmin 0
    set pxmax [expr {[WidthCanvas $w]  - 1}]
    set pymin [expr {[HeightCanvas $w] - 1}]
    set pymax 0

    # Default scaling: use pixels - not an error
    ScadaScaling $w default [list $pxmin $pymax $pxmax $pymin] \
                            [list $pxmin $pymin $pxmax $pymax]

    return $newchart
}


# ScadaScaling --
#     Create a new scaling for the SCADA display
#
# Arguments:
#    w             Name of the canvas
#    name          Name of the scaling
#    rectangle     Rectangle in the window (pixels)
#    worldcoords   Associated world coordinates
# Result:
#    None
# Note:
#    Order of the pixel coordinates: xmin, ymin, xmax, ymax
#    Ditto for the world coordinates, but the pixel y-coordinate
#    is actually inverted
#
proc ::Plotchart::ScadaScaling { w name rectangle worldcoords } {

    viewPort         $w,$name {*}$rectangle
    worldCoordinates $w,$name {*}$worldcoords

}


# ScadaObject --
#     Create a new object in the SCADA display
#
# Arguments:
#    w             Name of the canvas
#    type          Type of the object
#    objname       Name of the object
#    coords        List of coordinates
#    args          List of all remaining arguments
# Result:
#    None
# Side effects:
#    A new object is created on the canvas and its properties are stored
#
proc ::Plotchart::ScadaObject { w type objname coords args} {
    variable scada_scaling
    variable scada_object

    set scada_object($w,$objname,scaling) default

    set options {}
    foreach {key value} $args {
        switch -- $key {
            "-scaling" {
                set scada_object($w,$objname,scaling) $value
            }
            "-text" {
                set scada_object($w,$objname,text) $value
            }
            default {
                lappend options $key $value
            }
        }
    }

    switch -- $type {
        "rectangle" {
            set scada_object($w,$objname,canvasid) \
                [$w create rectangle {-10 -10 -10 -10} {*}$options]
        }
        "line" {
            set scada_object($w,$objname,canvasid) \
                [$w create line {-10 -10 -10 -10} {*}$options]
        }
        "polygon" {
            set scada_object($w,$objname,canvasid) \
                [$w create polygon {-10 -10 -10 -10 -10 -10} {*}$options]
        }
        "text" {
            set scada_object($w,$objname,canvasid) \
                [$w create text {-10 -10} -text $scada_object($w,$objname,text) {*}$options]
        }
        default {
            return -code error "Unknown object type: $type"
        }
    }

    set scada_object($w,$objname,coords) $coords
    set scada_object($w,$objname,type)   $type
}


# ScadaPlot --
#     Change the properties (coordinates or text) of a SCADA object
#
# Arguments:
#    w             Name of the canvas
#    objname       Name of the object
#    args          List of the parameters that need to be changed
# Result:
#    None
# Side effects:
#    The coordinates or the text are changed
#
proc ::Plotchart::ScadaPlot { w objname args} {
    variable scada_scaling
    variable scada_object

    set wcoords $scada_object($w,$objname,coords)

    set replace 0
    set index   0
    foreach coord $wcoords {
        if { $coord eq "*" } {
            lset wcoords $index [lindex $args $replace]
            incr replace
        }
        incr index
    }

    set scaling $w,$scada_object($w,$objname,scaling)

    set coords {}
    foreach {x y} $wcoords {
        if {[catch {
        foreach {px py} [coordsToPixel $scaling $x $y] {break}
        lappend coords $px $py
        } msg] } {
            puts "problem: $scaling -- $x -- $y"
        }
    }

    $w coords $scada_object($w,$objname,canvasid) $coords

    if { $scada_object($w,$objname,type) eq "text" } {
        if { $scada_object($w,$objname,text) eq "*" } {
            set text [lindex $args end]
            $w itemconfig $scada_object($w,$objname,canvasid) -text $text
        }
    }
}

# main --
#     Simple test
#

if {0} {
pack [canvas .c -height 400]

set p [::Plotchart::createScada .c]


$p scaling height {0 0 40 300} {0 0 40 1.5}

$p object rectangle box {10 0.0 30 *} -fill green -outline black -width 3 -scaling height
$p object text      label {35 *} -text * -anchor w                       -scaling height

$p plot box 1.2
$p plot label 1.2 "1.2"

after 2000 {
    $p plot box 0.6
    $p plot label 0.6 "0.6"
}
}

#
# Display a simple vessel
#
pack [canvas .c -height 300 -width 600]

set p [::Plotchart::createScada .c]

scale .c.scalea -orient vertical -from 0.10 -to 0.0 -variable ratea -tickinterval 0.02 -digits 3 -resolution 0.001
scale .c.scaleb -orient vertical -from 0.10 -to 0.0 -variable rateb -tickinterval 0.02 -digits 3 -resolution 0.001
button .c.start -text Start -command {startComputation} -width 10
button .c.stop  -text Stop  -command {stopComputation}  -width 10

.c create window  10  30 -window .c.scalea -anchor nw
.c create window 110  70 -window .c.scaleb -anchor nw
.c create window  10 200 -window .c.start  -anchor nw
.c create window 110 200 -window .c.stop   -anchor nw

.c create line { 20  40  230   40} -width 2 -arrow last -fill red
.c create text  230  30  -text "Component A" -anchor e  -fill red
.c create line {200  70  230   70} -width 2 -arrow last -fill blue
.c create text  230  60  -text "Component B" -anchor e  -fill blue
.c create line {325 210  360  210} -width 2 -arrow last
.c create text  340 200  -text "Product C" -anchor w
.c create polygon {240  10 240  10
                   240 240 240 240
                   280 260
                   320 240 320 240
                   320  10 320  10} \
     -fill orange -smooth 1 -outline black -width 2

.c create line      {280   0 280 200} -width 2
.c create line      {270 200 290 200} -width 2
.c create rectangle {250 190 270 210} -width 2 -fill black
.c create rectangle {290 190 310 210} -width 2 -fill black


$p scaling temperature {400  22 428  148} {0.0 10.0 1.0 100.0}
.c create rectangle {400 20 430 150} -width 2 -fill white -outline black

$p object rectangle thermometer {0.0 10.0 1.0 *} -scaling temperature -fill red
$p object text temperature {1.3 *} -text * -scaling temperature -anchor w

$p scaling concentration {480 102 510 248} {0.0 0.0 1.0 1.0}
.c create rectangle {480 100 510 250} -width 2 -fill yellow -outline black

$p object rectangle conca   { 0.0 0.0  1.0 *} -fill red    -scaling concentration
$p object rectangle concb   { 0.0   *  1.0 *} -fill blue   -scaling concentration

$p object text      labela  {1.3 *} -text A      -scaling concentration
$p object text      labelb  {1.3 *} -text B      -scaling concentration
$p object text      labelc  {1.3 *} -text C      -scaling concentration

$p object line      maxline {-0.1   *  1.4 *}              -scaling concentration
$p object text      maximum { 1.4   *}       -text Maximum -scaling concentration -anchor w

$p plot maxline 0.25 0.25
$p plot maximum 0.25
$p plot labelc  1.0

$p plot thermometer 25.0
$p plot temperature 25.0 "25"

$p plot conca  0.1
$p plot concb  0.1 0.3
$p plot labela 0.1
$p plot labelb 0.3

Changes to modules/plotchart/scaling.tcl.

18
19
20
21
22
23
24

































25
26
27
28
29
30
31
         expr {$a < $b }
      }
      proc tgt {a b} {
         expr {$a > $b }
      }
   }
}


































# determineScale --
#    Determine nice values for an axis from the given extremes
#
# Arguments:
#    xmin      Minimum value
#    xmax      Maximum value







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
         expr {$a < $b }
      }
      proc tgt {a b} {
         expr {$a > $b }
      }
   }
}

# determineScaleFromList --
#    Determine nice values for an axis from a list of values
#
# Arguments:
#    values    List of values
#    inverted  Whether to return values for an inverted axis (1) or not (0)
#              Defaults to 0.
# Result:
#    A list of three values, a nice minimum and maximum
#    and stepsize
# Note:
#    Missing values (empty strings) are allowed in the list of values
#
proc ::Plotchart::determineScaleFromList { values {inverted 0} } {

    set xmin {}
    set xmax {}

    foreach v $values {
        if { $v == {} } {
            continue
        }
        if { $xmin == {} || $xmin > $v } {
            set xmin $v
        }
        if { $xmax == {} || $xmax < $v } {
            set xmax $v
        }
    }

    return [determineScale $xmin $xmax $inverted]
}

# determineScale --
#    Determine nice values for an axis from the given extremes
#
# Arguments:
#    xmin      Minimum value
#    xmax      Maximum value

Changes to modules/plotchart/xyplot.tcl.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23

24
25
26
27
28
29
30
31
32

33
34
35
36
37

38
39
40

41
42
43
44
45
46

47






48
49
50
51

52
53
54
55
56
57
58
...
335
336
337
338
339
340
341

























342
343
344
345
346
347
348
...
404
405
406
407
408
409
410



411

412
413
414
415
416
417
418
...
446
447
448
449
450
451
452



453

454
455
456
457
458
459
460
...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
#     Interactive layer for plotting XY graphs via Plotchart
#     Package provided by Jos Decoster
#
package require Tcl 8.5
package require Tk 8.5
package require Plotchart 1.5
package require cmdline
package provide xyplot 1.0.0

namespace eval xyplot {
    proc ::xyplot { path args } {
	return [::xyplot::create $path {*}$args]
    }
}

proc xyplot::create { path args } {
    variable data

    set options {

	{xtext.arg            ""         "Set x-axis text"}
	{xticks.arg           "10"       "Set number of x-axis ticks"}
	{xformat.arg          ""         "Set x-scale format"}

	{ytext.arg            ""         "Set y-axis text"}
	{yticks.arg           "10"       "Set number of y-axis ticks"}
	{yformat.arg          ""         "Set y-scale format"}
	{canvasbackground.arg ""         "Set plot canvas background"}
	{background.arg       ""         "Set plot background"}
	{title.arg            ""         "Set barchart title"}
	{type.arg             "line"     "Set plot type (line/dot)"}
	{width.arg            "600"      "Set plot width"}
	{height.arg           "400"      "Set plot height"}

    }
    set usage "::xyplot <path> \[options\]"
    array set params [::cmdline::getoptions args $options $usage]

    set data($path,title)   $params(title)

    set data($path,xformat) $params(xformat)
    set data($path,yformat) $params(yformat)
    set data($path,xtext)   $params(xtext)

    set data($path,ytext)   $params(ytext)
    set data($path,xticks)  $params(xticks)
    set data($path,yticks)  $params(yticks)
    set data($path,cbg)     $params(canvasbackground)
    set data($path,bg)      $params(background)
    set data($path,type)    $params(type)








    set f [frame $path]
    set c [canvas $f.c -xscrollcommand [list xyplot::sbx_set $f] -yscrollcommand [list xyplot::sby_set $f]]
    set sbx [scrollbar $f.sbx -orient horizontal -command [list xyplot::c_xview $f]]
    set sby [scrollbar $f.sby -orient vertical   -command [list xyplot::c_yview $f]]

    grid $c $sby -sticky ewns
    grid $sbx -sticky ew
    grid columnconfigure $f 0 -weight 1
    grid rowconfigure $f 0 -weight 1
    bind $c <1> [list xyplot::zoom_start $path %x %y]
    bind $c <B1-Motion> [list xyplot::zoom_move $path %x %y]
    bind $c <ButtonRelease-1> [list xyplot::zoom_end $path %x %y]
................................................................................
	set nsy $sy
	set nSy [expr {$sy+$nh}]
    }
    if {$nSy < $sy || $nSy > $Sy} {
	set nSy $Sy
	set nsy [expr {$Sy-$nh}]
    }

























    lappend data($path,zoomstack) [list $nsx $nSx $nsy $nSy]
    rescale $path $mx $Mx $my $My $nsx $nSx $nsy $nSy
    return
}

proc xyplot::unzoom { path } {
    variable data
................................................................................
	    }
	    set sx [expr {$mx+$w*$number}]
	    set Sx [expr {$sx+$sw}]
	}
	scroll {
	    switch -exact -- $unit {
		units {



		    set pfactor 0.05

		}
		pages {
		    set pfactor 1
		}
	    }
	    set sw [expr {double($Sx-$sx)}]
	    set sx [expr {$sx + $number*$sw*$pfactor}]
................................................................................
	    }
	    set Sy [expr {$My-$w*$number}]
	    set sy [expr {$Sy-$sw}]
	}
	scroll {
	    switch -exact -- $unit {
		units {



		    set pfactor 0.05

		}
		pages {
		    set pfactor 1
		}
	    }
	    set sw [expr {double($Sy-$sy)}]
	    set sy [expr {$sy - $number*$sw*$pfactor}]
................................................................................
for { set i 0 } { $i < 1024 } { incr i } {
    lappend xydata1 [expr {$i-1000}] [expr {$i * sin($i/4096.0*3.1415*2) * (sin($i/256.0*3.1415*2))}]
    lappend xydata2 [expr {$i-1000}] [expr {$i * sin($i/4096.0*3.1415*2) * (sin($i/256.0*3.1415*2) + 0.25 * sin($i/256.0*3.1415*6))}]
    lappend xydata3 [expr {$i-1000}] [expr {$i * sin($i/4096.0*3.1415*2) * (sin($i/256.0*3.1415*2) + 0.25 * sin($i/256.0*3.1415*6) + 0.0625 * sin($i/256.0*3.1415*10))}]
    lappend xydata4 [expr {$i-1000}] [expr {$i * sin($i/4096.0*3.1415*2) * (sin($i/256.0*3.1415*2) + 0.25 * sin($i/256.0*3.1415*6) + 0.0625 * sin($i/256.0*3.1415*10) + 0.015625 * sin($i/256.0*3.1415*14))}]
}

set xyp [xyplot .xyp -xformat "%5.0f" -yformat "%5.0f" -title "XY plot testing" -background gray90]
pack $xyp -fill both -expand true

set s1 [$xyp add_data sf1 $xydata1 -legend "Serie 1 data" -color red]
set s2 [$xyp add_data sf2 $xydata2 -legend "Serie 2 data" -color green]
set s3 [$xyp add_data sf3 $xydata3 -legend "Serie 3 data" -color blue]
set s4 [$xyp add_data sf4 $xydata4 -legend "Serie 4 data" -color orange]








|











>



>









>




|
>
|
|
|
>
|
|
|
|
|
|
>
|
>
>
>
>
>
>
|
|
|
|
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
|
>







 







>
>
>
|
>







 







|







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
...
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
#     Interactive layer for plotting XY graphs via Plotchart
#     Package provided by Jos Decoster
#
package require Tcl 8.5
package require Tk 8.5
package require Plotchart 1.5
package require cmdline
package provide xyplot 1.0.1

namespace eval xyplot {
    proc ::xyplot { path args } {
	return [::xyplot::create $path {*}$args]
    }
}

proc xyplot::create { path args } {
    variable data

    set options {
	{xinteger.arg         0          "Integer X-axis"}
	{xtext.arg            ""         "Set x-axis text"}
	{xticks.arg           "10"       "Set number of x-axis ticks"}
	{xformat.arg          ""         "Set x-scale format"}
	{yinteger.arg         0          "Integer Y-axis"}
	{ytext.arg            ""         "Set y-axis text"}
	{yticks.arg           "10"       "Set number of y-axis ticks"}
	{yformat.arg          ""         "Set y-scale format"}
	{canvasbackground.arg ""         "Set plot canvas background"}
	{background.arg       ""         "Set plot background"}
	{title.arg            ""         "Set barchart title"}
	{type.arg             "line"     "Set plot type (line/dot)"}
	{width.arg            "600"      "Set plot width"}
	{height.arg           "400"      "Set plot height"}
	{ttk.arg              0          "Use TTK widgets"}
    }
    set usage "::xyplot <path> \[options\]"
    array set params [::cmdline::getoptions args $options $usage]

    set data($path,title)    $params(title)
    set data($path,xinteger) $params(xinteger)
    set data($path,xformat)  $params(xformat)
    set data($path,yformat)  $params(yformat)
    set data($path,xtext)    $params(xtext)
    set data($path,yinteger) $params(yinteger)
    set data($path,ytext)    $params(ytext)
    set data($path,xticks)   $params(xticks)
    set data($path,yticks)   $params(yticks)
    set data($path,cbg)      $params(canvasbackground)
    set data($path,bg)       $params(background)
    set data($path,type)     $params(type)
    set data($path,ttk)      $params(ttk)

    if {$data($path,ttk)} {
	set f [ttk::frame $path]
	set c [canvas $f.c -xscrollcommand [list xyplot::sbx_set $f] -yscrollcommand [list xyplot::sby_set $f]]
	set sbx [ttk::scrollbar $f.sbx -orient horizontal -command [list xyplot::c_xview $f]]
	set sby [ttk::scrollbar $f.sby -orient vertical   -command [list xyplot::c_yview $f]]
    } else {
	set f [frame $path]
	set c [canvas $f.c -xscrollcommand [list xyplot::sbx_set $f] -yscrollcommand [list xyplot::sby_set $f]]
	set sbx [scrollbar $f.sbx -orient horizontal -command [list xyplot::c_xview $f]]
	set sby [scrollbar $f.sby -orient vertical   -command [list xyplot::c_yview $f]]
    }
    grid $c $sby -sticky ewns
    grid $sbx -sticky ew
    grid columnconfigure $f 0 -weight 1
    grid rowconfigure $f 0 -weight 1
    bind $c <1> [list xyplot::zoom_start $path %x %y]
    bind $c <B1-Motion> [list xyplot::zoom_move $path %x %y]
    bind $c <ButtonRelease-1> [list xyplot::zoom_end $path %x %y]
................................................................................
	set nsy $sy
	set nSy [expr {$sy+$nh}]
    }
    if {$nSy < $sy || $nSy > $Sy} {
	set nSy $Sy
	set nsy [expr {$Sy-$nh}]
    }

    if {$data($path,xinteger)} {
	set nsx [expr {int($nsx)}]
	set nSx [expr {int($nSx)}]
	if {[expr {$nSx-$nsx}] < $data($path,xticks)} {
	    set nSx [expr {$nsx+$data($path,xticks)}]
	}
	if {[expr {($nSx-$nsx)%$data($path,xticks)}]} {
	    set n [expr {round(($nSx-$nsx)/$data($path,xticks))}]
	    set nSx [expr {$nsx+$data($path,xticks)*$n}]
	}
    }

    if {$data($path,yinteger)} {
	set nsy [expr {int($nsy)}]
	set nSy [expr {int($nSy)}]
	if {[expr {$nSy-$nsy}] < $data($path,yticks)} {
	    set nSy [expr {$nsy+$data($path,yticks)}]
	}
	if {[expr {($nSy-$nsy)%$data($path,yticks)}]} {
	    set n [expr {round(($nSy-$nsy)/$data($path,yticks))}]
	    set nSy [expr {$nsy+$data($path,yticks)*$n}]
	}
    }

    lappend data($path,zoomstack) [list $nsx $nSx $nsy $nSy]
    rescale $path $mx $Mx $my $My $nsx $nSx $nsy $nSy
    return
}

proc xyplot::unzoom { path } {
    variable data
................................................................................
	    }
	    set sx [expr {$mx+$w*$number}]
	    set Sx [expr {$sx+$sw}]
	}
	scroll {
	    switch -exact -- $unit {
		units {
		    if {$data($path,xticks)} {
			set pfactor [expr {1.0/$data($path,xticks)}]
		    } else {
			set pfactor 0.05
		    }
		}
		pages {
		    set pfactor 1
		}
	    }
	    set sw [expr {double($Sx-$sx)}]
	    set sx [expr {$sx + $number*$sw*$pfactor}]
................................................................................
	    }
	    set Sy [expr {$My-$w*$number}]
	    set sy [expr {$Sy-$sw}]
	}
	scroll {
	    switch -exact -- $unit {
		units {
		    if {$data($path,yticks)} {
			set pfactor [expr {1.0/$data($path,yticks)}]
		    } else {
			set pfactor 0.05
		    }
		}
		pages {
		    set pfactor 1
		}
	    }
	    set sw [expr {double($Sy-$sy)}]
	    set sy [expr {$sy - $number*$sw*$pfactor}]
................................................................................
for { set i 0 } { $i < 1024 } { incr i } {
    lappend xydata1 [expr {$i-1000}] [expr {$i * sin($i/4096.0*3.1415*2) * (sin($i/256.0*3.1415*2))}]
    lappend xydata2 [expr {$i-1000}] [expr {$i * sin($i/4096.0*3.1415*2) * (sin($i/256.0*3.1415*2) + 0.25 * sin($i/256.0*3.1415*6))}]
    lappend xydata3 [expr {$i-1000}] [expr {$i * sin($i/4096.0*3.1415*2) * (sin($i/256.0*3.1415*2) + 0.25 * sin($i/256.0*3.1415*6) + 0.0625 * sin($i/256.0*3.1415*10))}]
    lappend xydata4 [expr {$i-1000}] [expr {$i * sin($i/4096.0*3.1415*2) * (sin($i/256.0*3.1415*2) + 0.25 * sin($i/256.0*3.1415*6) + 0.0625 * sin($i/256.0*3.1415*10) + 0.015625 * sin($i/256.0*3.1415*14))}]
}

set xyp [xyplot .xyp -xformat "%5.2f" -yformat "%5.0f" -title "XY plot testing" -background gray90 -xinteger 1 -yinteger 1]
pack $xyp -fill both -expand true

set s1 [$xyp add_data sf1 $xydata1 -legend "Serie 1 data" -color red]
set s2 [$xyp add_data sf2 $xydata2 -legend "Serie 2 data" -color green]
set s3 [$xyp add_data sf3 $xydata3 -legend "Serie 3 data" -color blue]
set s4 [$xyp add_data sf4 $xydata4 -legend "Serie 4 data" -color orange]