1# plotbind.tcl --
2#     Facilities for interaction with the plot, via event bindings
3#
4# Note:
5#     This source contains private functions only.
6#     It accompanies "plotchart.tcl"
7#
8
9# BindPlot --
10#     Bind an event to the entire plot area
11#
12# Arguments:
13#     w               Widget
14#     event           Type of event
15#     cmd             Command to execute
16#
17# Result:
18#     None
19#
20proc ::Plotchart::BindPlot {w event cmd} {
21    variable scaling
22
23    if { $scaling($w,eventobj) == "" } {
24
25        set pxmin $scaling($w,pxmin)
26        set pxmax $scaling($w,pxmax)
27        set pymin $scaling($w,pymin)
28        set pymax $scaling($w,pymax)
29
30        set scaling($w,eventobj) [$w create rectangle $pxmin $pymin $pxmax $pymax -fill {} -outline {}]
31    }
32    $w lower $scaling($w,eventobj)
33
34    $w bind $scaling($w,eventobj) $event [list ::Plotchart::BindCmd %x %y $w $cmd]
35
36}
37
38# BindLast --
39#     Bind an event to the last data point of a data series
40#
41# Arguments:
42#     w               Widget
43#     series          Data series in question
44#     event           Type of event
45#     cmd             Command to execute
46#
47# Result:
48#     None
49#
50proc ::Plotchart::BindLast {w series event cmd} {
51    variable data_series
52
53    foreach {x y} [coordsToPixel $w $data_series($w,$series,x) $data_series($w,$series,y)] {break}
54
55    set pxmin [expr {$x-5}]
56    set pxmax [expr {$x+5}]
57    set pymin [expr {$y-5}]
58    set pymax [expr {$y+5}]
59
60    set object [$w create rectangle $pxmin $pymin $pxmax $pymax -fill {} -outline {}]
61
62    $w bind $object $event \
63        [list ::Plotchart::BindCmd $x $y $w $cmd]
64}
65
66# BindCmd --
67#     Call the command that is bound to the event
68#
69# Arguments:
70#     xcoord          X coordinate of event
71#     ycoord          Y coordinate of event
72#     w               Canvas widget
73#     cmd             Command to execute
74#
75# Result:
76#     None
77#
78proc ::Plotchart::BindCmd {xcoord ycoord w cmd} {
79    variable scaling
80
81    foreach {x y} [pixelToCoords $w $xcoord $ycoord] {break}
82
83    eval [lindex $cmd 0] $x $y [lrange $cmd 1 end]
84
85}
86
87# PieExplodeSegment --
88#     Move the indicated segment
89#
90# Arguments:
91#     w               Widget
92#     segment         Segment to move
93#     button          Whether it came from a button event or not
94#
95# Result:
96#     None
97#
98# Note:
99#     If the segment is "auto", then we accept button clicks
100#
101proc ::Plotchart::PieExplodeSegment {w segment {button 0}} {
102    variable scaling
103
104    if { $button && $scaling($w,auto) == 0 } {
105        return
106    }
107
108    if { $segment == "auto" } {
109        set scaling($w,auto) 1
110        return
111    } else {
112        if { $segment < 0 || $segment >= [llength $scaling($w,angles)] } {
113            return
114        }
115    }
116
117    if { $scaling($w,exploded) != -1 } {
118        $w move segment_$scaling($w,exploded) [expr {-$scaling($w,xexploded)}] [expr {-$scaling($w,yexploded)}]
119    }
120
121    if { $segment == $scaling($w,exploded) } {
122        set scaling($w,exploded) -1
123    } else {
124        set angle_bgn [lindex $scaling($w,angles) $segment]
125        set angle_ext [lindex $scaling($w,extent) $segment]
126
127        set angle     [expr {3.1415926*($angle_bgn+$angle_ext/2.0)/180.0}]
128        set dx        [expr { 15 * cos($angle)}]
129        set dy        [expr {-15 * sin($angle)}]
130
131        set scaling($w,exploded)  $segment
132        set scaling($w,xexploded) $dx
133        set scaling($w,yexploded) $dy
134        $w move segment_$segment $dx $dy
135    }
136}
137
138
139
140
141if {0} {
142
143-- this represents an old idea. Keeping it around for the moment --
144
145# BindVar --
146#     Bind a variable to a mouse event
147#
148# Arguments:
149#     w               Widget
150#     event           Type of event
151#     varname         Name of a global variable
152#     text            Text containing %x and %y to set the variable to
153#
154# Result:
155#     None
156#
157# Note:
158#     This procedure makes it easy to build a label widget showing
159#     the current position of the mouse in the plot's coordinate
160#     system for instance.
161#
162proc ::Plotchart::BindVar {w event varname text} {
163
164    BindCmd $w $event [list ::Plotchart::SetText $w "%x %y" $varname \
165        [string map {% @} $text]]
166
167}
168
169# BindCmd --
170#     Bind a command to a mouse event
171#
172# Arguments:
173#     w               Widget
174#     event           Type of event
175#     cmd             Command to be run
176#
177# Result:
178#     None
179#
180# Note:
181#     This procedure makes it easy to define interactive plots
182#     But it defines bindings for the whole canvas window, not the
183#     individual items. -- TODO --
184#
185proc ::Plotchart::BindCmd {w event cmd} {
186    switch -- $event {
187        "mouse"  { set b "<Motion>" }
188        "button" { set b "<ButtonPress-1>" }
189        default  { return -code error "Unknown event type $event" }
190    }
191
192    bind $w $b $cmd
193}
194
195# SetText --
196#     Substitute the coordinates in the given text
197#
198# Arguments:
199#     w               Widget
200#     coords          Current coordinates
201#     varname         Name of a global variable
202#     text            Text containing %x and %y to set the variable to
203#
204# Result:
205#     None
206#
207# Side effects:
208#     The text is assigned to the variable after making the
209#     various substitutions
210#
211proc ::Plotchart::SetText {w coords varname text} {
212    upvar #0 $varname V
213
214    foreach {x y} [pixelToCoords $w [lindex $coords 0] [lindex $coords 1]] {break}
215
216    set V [string map [list @x $x @y $y] $text]
217}
218
219--- end of old code ---
220}
221