3 # Implements the TixControl Widget. It is called the "SpinBox"
6 # Copyright (c) 1996, Expert Interface Technologies
8 # See the file "license.terms" for information on usage and redistribution
9 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 tixWidgetClass tixControl {
14 -superclass tixLabelWidget
16 incr decr invoke update
19 -allowempty -autorepeat -command -decrcmd -disablecallback
20 -disabledforeground -incrcmd -initwait -integer -llimit
21 -repeatrate -max -min -selectmode -step -state -validatecmd
22 -value -variable -ulimit
28 {-allowempty allowEmpty AllowEmpty false}
29 {-autorepeat autoRepeat AutoRepeat true}
30 {-command command Command ""}
31 {-decrcmd decrCmd DecrCmd ""}
32 {-disablecallback disableCallback DisableCallback 0 tixVerifyBoolean}
33 {-disabledforeground disabledForeground DisabledForeground #303030}
34 {-incrcmd incrCmd IncrCmd ""}
35 {-initwait initWait InitWait 500}
36 {-integer integer Integer false}
39 {-repeatrate repeatRate RepeatRate 50}
41 {-state state State normal}
42 {-selectmode selectMode SelectMode normal}
43 {-validatecmd validateCmd ValidateCmd ""}
44 {-value value Value 0}
45 {-variable variable Variable ""}
53 {*entry.relief sunken}
56 {*label.borderWidth 0}
57 {*Label.font -Adobe-Helvetica-Bold-R-Normal--*-120-*}
59 {*Button.borderWidth 2}
60 {*Button.highlightThickness 1}
62 {*Entry.background #c3c3c3}
66 proc tixControl:InitWidgetRec {w} {
69 tixChainMethod $w InitWidgetRec
75 proc tixControl:ConstructFramedWidget {w frame} {
78 tixChainMethod $w ConstructFramedWidget $frame
80 set data(w:entry) [entry $frame.entry]
82 set data(w:incr) [button $frame.incr -bitmap [tix getbitmap incr] \
84 set data(w:decr) [button $frame.decr -bitmap [tix getbitmap decr] \
87 # tixForm $data(w:entry) -left 0 -top 0 -bottom -1 -right $data(w:decr)
88 # tixForm $data(w:incr) -right -1 -top 0 -bottom %50
89 # tixForm $data(w:decr) -right -1 -top $data(w:incr) -bottom -1
91 pack $data(w:entry) -side left -expand yes -fill both
92 pack $data(w:decr) -side bottom -fill both -expand yes
93 pack $data(w:incr) -side top -fill both -expand yes
95 $data(w:entry) delete 0 end
96 $data(w:entry) insert 0 $data(-value)
98 # This value is used to configure the disable/normal fg of the ebtry
99 set data(entryfg) [$data(w:entry) cget -fg]
100 set data(labelfg) [$data(w:label) cget -fg]
103 proc tixControl:SetBindings {w} {
106 tixChainMethod $w SetBindings
108 if {$data(-autorepeat)} {
109 bind $data(w:incr) <ButtonPress-1> \
110 [format {after idle tixControl:StartRepeat %s 1} $w]
111 bind $data(w:decr) <ButtonPress-1> \
112 [format {after idle tixControl:StartRepeat %s -1} $w]
114 # These bindings will stop the button autorepeat when the
116 foreach btn "$data(w:incr) $data(w:decr)" amt {1 -1} {
117 bind $btn <ButtonRelease-1> "tixControl:StopRepeat $w $amt"
120 # Force the non-autorepeat case to use the normal
121 # tk button class bindings
122 $data(w:incr) configure -command "tixControl:incr $w"
123 $data(w:decr) configure -command "tixControl:decr $w"
126 tixSetMegaWidget $data(w:entry) $w
128 # If user press <return>, verify the value and call the -command
130 tixAddBindTag $data(w:entry) TixControl:Entry
133 proc tixControlBind {} {
134 tixBind TixControl:Entry <Return> {
135 tixControl:Invoke [tixGetMegaWidget %W] 1
137 tixBind TixControl:Entry <Escape> {
138 tixControl:Escape [tixGetMegaWidget %W]
140 tixBind TixControl:Entry <Up> {
141 [tixGetMegaWidget %W] incr
143 tixBind TixControl:Entry <Down> {
144 [tixGetMegaWidget %W] decr
146 tixBind TixControl:Entry <FocusOut> {
147 if {"%d" == "NotifyNonlinear" || "%d" == "NotifyNonlinearVirtual"} {
148 tixControl:Tab [tixGetMegaWidget %W] %d
151 tixBind TixControl:Entry <Any-KeyPress> {
152 tixControl:KeyPress [tixGetMegaWidget %W]
154 tixBind TixControl:Entry <Any-Tab> {
155 # This has a higher priority than the <Any-KeyPress> binding
156 # --> so that data(edited) is not set
160 #----------------------------------------------------------------------
162 #----------------------------------------------------------------------
163 proc tixControl:config-state {w arg} {
166 if {$arg == "normal"} {
167 $data(w:incr) config -state $arg
168 $data(w:decr) config -state $arg
170 $data(w:label) config -fg $data(labelfg)
172 $data(w:entry) config -state $arg -fg $data(entryfg)
173 tixControl:SetBindings $w
175 $data(w:incr) config -state $arg
176 $data(w:decr) config -state $arg
178 $data(w:label) config -fg $data(-disabledforeground)
180 $data(w:entry) config -state $arg -fg $data(-disabledforeground)
181 bind $data(w:incr) <ButtonPress-1> {}
182 bind $data(w:decr) <ButtonPress-1> {}
186 proc tixControl:config-value {w value} {
189 tixControl:SetValue $w $value 0 1
191 # This will tell the Intrinsics: "Please use this value"
192 # because "value" might be altered by SetValues
197 proc tixControl:config-variable {w arg} {
200 if [tixVariable:ConfigVariable $w $arg] {
201 # The value of data(-value) is changed if tixVariable:ConfigVariable
203 tixControl:SetValue $w $data(-value) 1 1
206 unset data(varInited)
208 set data(-variable) $arg
211 #----------------------------------------------------------------------
213 #----------------------------------------------------------------------
214 proc tixControl:incr {w {by 1}} {
217 if {$data(-state) != "disabled"} {
218 if {[catch {$data(w:entry) index sel.first}] == 0} {
219 $data(w:entry) select from end
220 $data(w:entry) select to end
222 # CYGNUS LOCAL - why set value before changing it?
223 #tixControl:SetValue $w [$data(w:entry) get] 0 1
224 tixControl:AdjustValue $w $by
228 proc tixControl:decr {w {by 1}} {
231 if {$data(-state) != "disabled"} {
232 if {[catch {$data(w:entry) index sel.first}] == 0} {
233 $data(w:entry) select from end
234 $data(w:entry) select to end
236 # CYGNUS LOCAL - why set value before changing it?
237 #tixControl:SetValue $w [$data(w:entry) get] 0 1
238 tixControl:AdjustValue $w [expr 0 - $by]
242 proc tixControl:invoke {w} {
245 tixControl:Invoke $w 0
248 proc tixControl:update {w} {
251 if [info exists data(edited)] {
256 #----------------------------------------------------------------------
258 #----------------------------------------------------------------------
260 # Change the value by a multiple of the data(-step)
262 proc tixControl:AdjustValue {w amount} {
265 if {$amount == 1 && $data(-incrcmd) != ""} {
266 set newValue [tixEvalCmdBinding $w $data(-incrcmd) "" $data(-value)]
267 } elseif {$amount == -1 && $data(-decrcmd) != ""} {
268 set newValue [tixEvalCmdBinding $w $data(-decrcmd) "" $data(-value)]
270 set newValue [expr $data(-value) + $amount * $data(-step)]
273 if {$data(-state) != "disabled"} {
274 tixControl:SetValue $w $newValue 0 1
278 proc tixControl:SetValue {w newvalue noUpdate forced} {
281 if {[$data(w:entry) selection present]} {
283 "[$data(w:entry) index sel.first] [$data(w:entry) index sel.last]"
286 set oldvalue $data(-value)
287 set oldCursor [$data(w:entry) index insert]
291 if {$data(-validatecmd) != ""} {
292 # Call the user supplied validation command
294 set data(-value) [tixEvalCmdBinding $w $data(-validatecmd) "" $newvalue]
296 # Here we only allow int or floating numbers
298 # If the new value is not a valid number, the old value will be
299 # kept due to the "catch" statements
301 if [catch {expr 0+$newvalue}] {
307 if {$newvalue == ""} {
308 if {![tixGetBoolean -nocomplain $data(-allowempty)]} {
316 if {$newvalue != ""} {
317 # Change this to a valid decimal string (trim leading 0)
319 regsub {^[0]*} $newvalue "" newvalue
320 if [catch {expr 0+$newvalue}] {
325 if {$newvalue == ""} {
329 if [tixGetBoolean -nocomplain $data(-integer)] {
330 set data(-value) [tixGetInt -nocomplain $newvalue]
332 if [catch {set data(-value) [format "%d" $newvalue]}] {
333 if [catch {set data(-value) [expr $newvalue+0.0]}] {
334 set data(-value) $oldvalue
339 # Now perform boundary checking
341 if {$data(-max) != "" && $data(-value) > $data(-max)} {
342 set data(-value) $data(-max)
344 if {$data(-min) != "" && $data(-value) < $data(-min)} {
345 set data(-value) $data(-min)
351 tixVariable:UpdateVariable $w
354 if {$forced || "x$newvalue" != "x$data(-value)" || $changed} {
355 $data(w:entry) delete 0 end
356 $data(w:entry) insert 0 $data(-value)
357 $data(w:entry) icursor $oldCursor
358 if {[info exists oldSelection]} {
359 eval $data(w:entry) selection range $oldSelection
363 if {!$data(-disablecallback) && $data(-command) != ""} {
364 if {![info exists data(varInited)]} {
366 tixEvalCmdBinding $w $data(-command) bind $data(-value)
371 proc tixControl:Invoke {w forced} {
378 if {[catch {$data(w:entry) index sel.first}] == 0} {
379 # THIS ENTRY OWNS SELECTION --> TURN IT OFF
381 $data(w:entry) select from end
382 $data(w:entry) select to end
385 tixControl:SetValue $w [$data(w:entry) get] 0 $forced
388 #----------------------------------------------------------------------
389 # The three functions StartRepeat, Repeat and StopRepeat make use of the
390 # data(serial) variable to discard spurious repeats: If a button is clicked
391 # repeatedly but is not hold down, the serial counter will increase
392 # successively and all "after" time event handlers will be discarded
393 #----------------------------------------------------------------------
394 proc tixControl:StartRepeat {w amount} {
395 if {![winfo exists $w]} {
402 # CYGNUS LOCAL bug fix
403 # Need to set a local variable because otherwise the buttonrelease
404 # callback could change the value of data(serial) between now and
405 # the time the repeat is scheduled.
406 set serial $data(serial)
408 if {$data(-autorepeat)} {
409 tixControl:doAdjustValue $w $amount
410 after $data(-initwait) tixControl:Repeat $w $amount $serial
416 proc tixControl:doAdjustValue {w amount} {
420 if {[catch {$data(w:entry) index sel.first}] == 0} {
421 $data(w:entry) select from end
422 $data(w:entry) select to end
425 if [info exists data(edited)] {
427 tixControl:SetValue $w [$data(w:entry) get] 0 1
430 tixControl:AdjustValue $w $amount
433 proc tixControl:Repeat {w amount serial} {
434 if {![winfo exists $w]} {
439 if {$serial == $data(serial)} {
440 tixControl:AdjustValue $w $amount
442 if {$data(-autorepeat)} {
443 after $data(-repeatrate) tixControl:Repeat $w $amount $serial
448 proc tixControl:StopRepeat {w amount} {
451 if {$data(-autorepeat) == "false" } {
452 tixControl:doAdjustValue $w $amount
458 proc tixControl:Destructor {w} {
460 tixVariable:DeleteVariable $w
462 # Chain this to the superclass
464 tixChainMethod $w Destructor
467 # ToDo: maybe should return -code break if the value is not good ...
469 proc tixControl:Tab {w detail} {
472 if {![info exists data(edited)]} {
481 proc tixControl:Escape {w} {
484 $data(w:entry) delete 0 end
485 $data(w:entry) insert 0 $data(-value)
488 proc tixControl:KeyPress {w} {
491 if {$data(-selectmode) == "normal"} {
496 after 1 tixControl:invoke $w