123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
- #
- # $Id: Control.tcl,v 1.9 2004/03/28 02:44:57 hobbs Exp $
- #
- # Control.tcl --
- #
- # Implements the TixControl Widget. It is called the "SpinBox"
- # in other toolkits.
- #
- # Copyright (c) 1993-1999 Ioi Kim Lam.
- # Copyright (c) 2000-2001 Tix Project Group.
- # Copyright (c) 2004 ActiveState
- #
- # See the file "license.terms" for information on usage and redistribution
- # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- #
- tixWidgetClass tixControl {
- -classname TixControl
- -superclass tixLabelWidget
- -method {
- incr decr invoke update
- }
- -flag {
- -allowempty -autorepeat -command -decrcmd -disablecallback
- -disabledforeground -incrcmd -initwait -integer -llimit
- -repeatrate -max -min -selectmode -step -state -validatecmd
- -value -variable -ulimit
- }
- -forcecall {
- -variable -state
- }
- -configspec {
- {-allowempty allowEmpty AllowEmpty false}
- {-autorepeat autoRepeat AutoRepeat true}
- {-command command Command ""}
- {-decrcmd decrCmd DecrCmd ""}
- {-disablecallback disableCallback DisableCallback 0 tixVerifyBoolean}
- {-disabledforeground disabledForeground DisabledForeground #303030}
- {-incrcmd incrCmd IncrCmd ""}
- {-initwait initWait InitWait 500}
- {-integer integer Integer false}
- {-max max Max ""}
- {-min min Min ""}
- {-repeatrate repeatRate RepeatRate 50}
- {-step step Step 1}
- {-state state State normal}
- {-selectmode selectMode SelectMode normal}
- {-validatecmd validateCmd ValidateCmd ""}
- {-value value Value 0}
- {-variable variable Variable ""}
- }
- -alias {
- {-llimit -min}
- {-ulimit -max}
- }
- -default {
- {.borderWidth 0}
- {*entry.relief sunken}
- {*entry.width 5}
- {*label.anchor e}
- {*label.borderWidth 0}
- {*Button.anchor c}
- {*Button.borderWidth 2}
- {*Button.highlightThickness 1}
- {*Button.takeFocus 0}
- }
- }
- proc tixControl:InitWidgetRec {w} {
- upvar #0 $w data
- tixChainMethod $w InitWidgetRec
- set data(varInited) 0
- set data(serial) 0
- }
- proc tixControl:ConstructFramedWidget {w frame} {
- upvar #0 $w data
- tixChainMethod $w ConstructFramedWidget $frame
- set data(w:entry) [entry $frame.entry]
- set data(w:incr) \
- [button $frame.incr -bitmap [tix getbitmap incr] -takefocus 0]
- set data(w:decr) \
- [button $frame.decr -bitmap [tix getbitmap decr] -takefocus 0]
- # tixForm $data(w:entry) -left 0 -top 0 -bottom -1 -right $data(w:decr)
- # tixForm $data(w:incr) -right -1 -top 0 -bottom %50
- # tixForm $data(w:decr) -right -1 -top $data(w:incr) -bottom -1
- pack $data(w:entry) -side left -expand yes -fill both
- pack $data(w:decr) -side bottom -fill both -expand yes
- pack $data(w:incr) -side top -fill both -expand yes
- $data(w:entry) delete 0 end
- $data(w:entry) insert 0 $data(-value)
- # This value is used to configure the disable/normal fg of the ebtry
- set data(entryfg) [$data(w:entry) cget -fg]
- set data(labelfg) [$data(w:label) cget -fg]
- }
- proc tixControl:SetBindings {w} {
- upvar #0 $w data
- tixChainMethod $w SetBindings
- bind $data(w:incr) <ButtonPress-1> \
- [list after idle tixControl:StartRepeat $w 1]
- bind $data(w:decr) <ButtonPress-1> \
- [list after idle tixControl:StartRepeat $w -1]
- # These bindings will stop the button autorepeat when the
- # mouse button is up
- foreach btn [list $data(w:incr) $data(w:decr)] {
- bind $btn <ButtonRelease-1> [list tixControl:StopRepeat $w]
- }
- tixSetMegaWidget $data(w:entry) $w
- # If user press <return>, verify the value and call the -command
- #
- tixAddBindTag $data(w:entry) TixControl:Entry
- }
- proc tixControlBind {} {
- tixBind TixControl:Entry <Return> {
- tixControl:Invoke [tixGetMegaWidget %W] 1
- }
- tixBind TixControl:Entry <Escape> {
- tixControl:Escape [tixGetMegaWidget %W]
- }
- tixBind TixControl:Entry <Up> {
- [tixGetMegaWidget %W] incr
- }
- tixBind TixControl:Entry <Down> {
- [tixGetMegaWidget %W] decr
- }
- tixBind TixControl:Entry <FocusOut> {
- if {"%d" eq "NotifyNonlinear" || "%d" eq "NotifyNonlinearVirtual"} {
- tixControl:Tab [tixGetMegaWidget %W] %d
- }
- }
- tixBind TixControl:Entry <Any-KeyPress> {
- tixControl:KeyPress [tixGetMegaWidget %W]
- }
- tixBind TixControl:Entry <Any-Tab> {
- # This has a higher priority than the <Any-KeyPress> binding
- # --> so that data(edited) is not set
- }
- }
- #----------------------------------------------------------------------
- # CONFIG OPTIONS
- #----------------------------------------------------------------------
- proc tixControl:config-state {w arg} {
- upvar #0 $w data
- if {$arg eq "normal"} {
- $data(w:incr) config -state $arg
- $data(w:decr) config -state $arg
- catch {
- $data(w:label) config -fg $data(labelfg)
- }
- $data(w:entry) config -state $arg -fg $data(entryfg)
- } else {
- $data(w:incr) config -state $arg
- $data(w:decr) config -state $arg
- catch {
- $data(w:label) config -fg $data(-disabledforeground)
- }
- $data(w:entry) config -state $arg -fg $data(-disabledforeground)
- }
- }
- proc tixControl:config-value {w value} {
- upvar #0 $w data
- tixControl:SetValue $w $value 0 1
- # This will tell the Intrinsics: "Please use this value"
- # because "value" might be altered by SetValues
- #
- return $data(-value)
- }
- proc tixControl:config-variable {w arg} {
- upvar #0 $w data
- if {[tixVariable:ConfigVariable $w $arg]} {
- # The value of data(-value) is changed if tixVariable:ConfigVariable
- # returns true
- tixControl:SetValue $w $data(-value) 1 1
- }
- catch {
- unset data(varInited)
- }
- set data(-variable) $arg
- }
- #----------------------------------------------------------------------
- # User Commands
- #----------------------------------------------------------------------
- proc tixControl:incr {w {by 1}} {
- upvar #0 $w data
- if {$data(-state) ne "disabled"} {
- if {![catch {$data(w:entry) index sel.first}]} {
- $data(w:entry) select from end
- $data(w:entry) select to end
- }
- # CYGNUS - why set value before changing it?
- #tixControl:SetValue $w [$data(w:entry) get] 0 1
- tixControl:AdjustValue $w $by
- }
- }
- proc tixControl:decr {w {by 1}} {
- upvar #0 $w data
- if {$data(-state) ne "disabled"} {
- if {![catch {$data(w:entry) index sel.first}]} {
- $data(w:entry) select from end
- $data(w:entry) select to end
- }
- # CYGNUS - why set value before changing it?
- #tixControl:SetValue $w [$data(w:entry) get] 0 1
- tixControl:AdjustValue $w [expr {0 - $by}]
- }
- }
- proc tixControl:invoke {w} {
- upvar #0 $w data
- tixControl:Invoke $w 0
- }
- proc tixControl:update {w} {
- upvar #0 $w data
- if {[info exists data(edited)]} {
- tixControl:invoke $w
- }
- }
- #----------------------------------------------------------------------
- # Internal Commands
- #----------------------------------------------------------------------
- # Change the value by a multiple of the data(-step)
- #
- proc tixControl:AdjustValue {w amount} {
- upvar #0 $w data
- if {$amount == 1 && [llength $data(-incrcmd)]} {
- set newValue [tixEvalCmdBinding $w $data(-incrcmd) "" $data(-value)]
- } elseif {$amount == -1 && [llength $data(-decrcmd)]} {
- set newValue [tixEvalCmdBinding $w $data(-decrcmd) "" $data(-value)]
- } else {
- set newValue [expr {$data(-value) + $amount * $data(-step)}]
- }
- if {$data(-state) ne "disabled"} {
- tixControl:SetValue $w $newValue 0 1
- }
- }
- proc tixControl:SetValue {w newvalue noUpdate forced} {
- upvar #0 $w data
- if {[$data(w:entry) selection present]} {
- set oldSelection [list [$data(w:entry) index sel.first] \
- [$data(w:entry) index sel.last]]
- }
- set oldvalue $data(-value)
- set oldCursor [$data(w:entry) index insert]
- set changed 0
- if {[llength $data(-validatecmd)]} {
- # Call the user supplied validation command
- #
- set data(-value) [tixEvalCmdBinding $w $data(-validatecmd) "" $newvalue]
- } else {
- # Here we only allow int or floating numbers
- #
- # If the new value is not a valid number, the old value will be
- # kept due to the "catch" statements
- #
- if {[catch {expr 0+$newvalue}]} {
- set newvalue 0
- set data(-value) 0
- set changed 1
- }
- if {$newvalue == ""} {
- if {![string is true -strict $data(-allowempty)]} {
- set newvalue 0
- set changed 1
- } else {
- set data(-value) ""
- }
- }
- if {$newvalue != ""} {
- # Change this to a valid decimal string (trim leading 0)
- #
- regsub -- {^[0]*} $newvalue "" newvalue
- if {[catch {expr 0+$newvalue}]} {
- set newvalue 0
- set data(-value) 0
- set changed 1
- }
- if {$newvalue == ""} {
- set newvalue 0
- }
- if {[string is true -strict $data(-integer)]} {
- set data(-value) [tixGetInt -nocomplain $newvalue]
- } else {
- if {[catch {set data(-value) [format "%d" $newvalue]}]} {
- if {[catch {set data(-value) [expr $newvalue+0.0]}]} {
- set data(-value) $oldvalue
- }
- }
- }
-
- # Now perform boundary checking
- #
- if {$data(-max) != "" && $data(-value) > $data(-max)} {
- set data(-value) $data(-max)
- }
- if {$data(-min) != "" && $data(-value) < $data(-min)} {
- set data(-value) $data(-min)
- }
- }
- }
- if {! $noUpdate} {
- tixVariable:UpdateVariable $w
- }
- if {$forced || ($newvalue ne $data(-value)) || $changed} {
- $data(w:entry) delete 0 end
- $data(w:entry) insert 0 $data(-value)
- $data(w:entry) icursor $oldCursor
- if {[info exists oldSelection]} {
- eval [list $data(w:entry) selection range] $oldSelection
- }
- }
- if {!$data(-disablecallback) && $data(-command) != ""} {
- if {![info exists data(varInited)]} {
- set bind(specs) ""
- tixEvalCmdBinding $w $data(-command) bind $data(-value)
- }
- }
- }
- proc tixControl:Invoke {w forced} {
- upvar #0 $w data
- catch {
- unset data(edited)
- }
- if {[catch {$data(w:entry) index sel.first}] == 0} {
- # THIS ENTRY OWNS SELECTION --> TURN IT OFF
- #
- $data(w:entry) select from end
- $data(w:entry) select to end
- }
- tixControl:SetValue $w [$data(w:entry) get] 0 $forced
- }
- #----------------------------------------------------------------------
- # The three functions StartRepeat, Repeat and StopRepeat make use of the
- # data(serial) variable to discard spurious repeats: If a button is clicked
- # repeatedly but is not hold down, the serial counter will increase
- # successively and all "after" time event handlers will be discarded
- #----------------------------------------------------------------------
- proc tixControl:StartRepeat {w amount} {
- if {![winfo exists $w]} {
- return
- }
- upvar #0 $w data
- incr data(serial)
- # CYGNUS bug fix
- # Need to set a local variable because otherwise the buttonrelease
- # callback could change the value of data(serial) between now and
- # the time the repeat is scheduled.
- set serial $data(serial)
- if {![catch {$data(w:entry) index sel.first}]} {
- $data(w:entry) select from end
- $data(w:entry) select to end
- }
- if {[info exists data(edited)]} {
- unset data(edited)
- tixControl:SetValue $w [$data(w:entry) get] 0 1
- }
- tixControl:AdjustValue $w $amount
- if {$data(-autorepeat)} {
- after $data(-initwait) tixControl:Repeat $w $amount $serial
- }
- focus $data(w:entry)
- }
- proc tixControl:Repeat {w amount serial} {
- if {![winfo exists $w]} {
- return
- }
- upvar #0 $w data
- if {$serial eq $data(serial)} {
- tixControl:AdjustValue $w $amount
- if {$data(-autorepeat)} {
- after $data(-repeatrate) tixControl:Repeat $w $amount $serial
- }
- }
- }
- proc tixControl:StopRepeat {w} {
- upvar #0 $w data
- incr data(serial)
- }
- proc tixControl:Destructor {w} {
- tixVariable:DeleteVariable $w
- # Chain this to the superclass
- #
- tixChainMethod $w Destructor
- }
- # ToDo: maybe should return -code break if the value is not good ...
- #
- proc tixControl:Tab {w detail} {
- upvar #0 $w data
- if {![info exists data(edited)]} {
- return
- } else {
- unset data(edited)
- }
- tixControl:invoke $w
- }
- proc tixControl:Escape {w} {
- upvar #0 $w data
- $data(w:entry) delete 0 end
- $data(w:entry) insert 0 $data(-value)
- }
- proc tixControl:KeyPress {w} {
- upvar #0 $w data
- if {$data(-selectmode) eq "normal"} {
- set data(edited) 0
- return
- } else {
- # == "immediate"
- after 1 tixControl:invoke $w
- }
- }
|