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