Update tk to version 8.5.13
[msysgit.git] / mingw / lib / tk8.5 / spinbox.tcl
blobcb501eeefae607316afcd6ec428941fadd56ae85
1 # spinbox.tcl --
3 # This file defines the default bindings for Tk spinbox widgets and provides
4 # procedures that help in implementing those bindings. The spinbox builds
5 # off the entry widget, so it can reuse Entry bindings and procedures.
7 # Copyright (c) 1992-1994 The Regents of the University of California.
8 # Copyright (c) 1994-1997 Sun Microsystems, Inc.
9 # Copyright (c) 1999-2000 Jeffrey Hobbs
10 # Copyright (c) 2000 Ajuba Solutions
12 # See the file "license.terms" for information on usage and redistribution
13 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 #-------------------------------------------------------------------------
17 # Elements of tk::Priv that are used in this file:
19 # afterId - If non-null, it means that auto-scanning is underway
20 # and it gives the "after" id for the next auto-scan
21 # command to be executed.
22 # mouseMoved - Non-zero means the mouse has moved a significant
23 # amount since the button went down (so, for example,
24 # start dragging out a selection).
25 # pressX - X-coordinate at which the mouse button was pressed.
26 # selectMode - The style of selection currently underway:
27 # char, word, or line.
28 # x, y - Last known mouse coordinates for scanning
29 # and auto-scanning.
30 # data - Used for Cut and Copy
31 #-------------------------------------------------------------------------
33 # Initialize namespace
34 namespace eval ::tk::spinbox {}
36 #-------------------------------------------------------------------------
37 # The code below creates the default class bindings for entries.
38 #-------------------------------------------------------------------------
39 bind Spinbox <<Cut>> {
40 if {![catch {::tk::spinbox::GetSelection %W} tk::Priv(data)]} {
41 clipboard clear -displayof %W
42 clipboard append -displayof %W $tk::Priv(data)
43 %W delete sel.first sel.last
44 unset tk::Priv(data)
47 bind Spinbox <<Copy>> {
48 if {![catch {::tk::spinbox::GetSelection %W} tk::Priv(data)]} {
49 clipboard clear -displayof %W
50 clipboard append -displayof %W $tk::Priv(data)
51 unset tk::Priv(data)
54 bind Spinbox <<Paste>> {
55 global tcl_platform
56 catch {
57 if {[tk windowingsystem] ne "x11"} {
58 catch {
59 %W delete sel.first sel.last
62 %W insert insert [::tk::GetSelection %W CLIPBOARD]
63 ::tk::EntrySeeInsert %W
66 bind Spinbox <<Clear>> {
67 %W delete sel.first sel.last
69 bind Spinbox <<PasteSelection>> {
70 if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]
71 || !$tk::Priv(mouseMoved)} {
72 ::tk::spinbox::Paste %W %x
76 bind Spinbox <<TraverseIn>> {
77 %W selection range 0 end
78 %W icursor end
81 # Standard Motif bindings:
83 bind Spinbox <1> {
84 ::tk::spinbox::ButtonDown %W %x %y
86 bind Spinbox <B1-Motion> {
87 ::tk::spinbox::Motion %W %x %y
89 bind Spinbox <Double-1> {
90 set tk::Priv(selectMode) word
91 ::tk::spinbox::MouseSelect %W %x sel.first
93 bind Spinbox <Triple-1> {
94 set tk::Priv(selectMode) line
95 ::tk::spinbox::MouseSelect %W %x 0
97 bind Spinbox <Shift-1> {
98 set tk::Priv(selectMode) char
99 %W selection adjust @%x
101 bind Spinbox <Double-Shift-1> {
102 set tk::Priv(selectMode) word
103 ::tk::spinbox::MouseSelect %W %x
105 bind Spinbox <Triple-Shift-1> {
106 set tk::Priv(selectMode) line
107 ::tk::spinbox::MouseSelect %W %x
109 bind Spinbox <B1-Leave> {
110 set tk::Priv(x) %x
111 ::tk::spinbox::AutoScan %W
113 bind Spinbox <B1-Enter> {
114 tk::CancelRepeat
116 bind Spinbox <ButtonRelease-1> {
117 ::tk::spinbox::ButtonUp %W %x %y
119 bind Spinbox <Control-1> {
120 %W icursor @%x
123 bind Spinbox <Up> {
124 %W invoke buttonup
126 bind Spinbox <Down> {
127 %W invoke buttondown
130 bind Spinbox <Left> {
131 ::tk::EntrySetCursor %W [expr {[%W index insert] - 1}]
133 bind Spinbox <Right> {
134 ::tk::EntrySetCursor %W [expr {[%W index insert] + 1}]
136 bind Spinbox <Shift-Left> {
137 ::tk::EntryKeySelect %W [expr {[%W index insert] - 1}]
138 ::tk::EntrySeeInsert %W
140 bind Spinbox <Shift-Right> {
141 ::tk::EntryKeySelect %W [expr {[%W index insert] + 1}]
142 ::tk::EntrySeeInsert %W
144 bind Spinbox <Control-Left> {
145 ::tk::EntrySetCursor %W [::tk::EntryPreviousWord %W insert]
147 bind Spinbox <Control-Right> {
148 ::tk::EntrySetCursor %W [::tk::EntryNextWord %W insert]
150 bind Spinbox <Shift-Control-Left> {
151 ::tk::EntryKeySelect %W [::tk::EntryPreviousWord %W insert]
152 ::tk::EntrySeeInsert %W
154 bind Spinbox <Shift-Control-Right> {
155 ::tk::EntryKeySelect %W [::tk::EntryNextWord %W insert]
156 ::tk::EntrySeeInsert %W
158 bind Spinbox <Home> {
159 ::tk::EntrySetCursor %W 0
161 bind Spinbox <Shift-Home> {
162 ::tk::EntryKeySelect %W 0
163 ::tk::EntrySeeInsert %W
165 bind Spinbox <End> {
166 ::tk::EntrySetCursor %W end
168 bind Spinbox <Shift-End> {
169 ::tk::EntryKeySelect %W end
170 ::tk::EntrySeeInsert %W
173 bind Spinbox <Delete> {
174 if {[%W selection present]} {
175 %W delete sel.first sel.last
176 } else {
177 %W delete insert
180 bind Spinbox <BackSpace> {
181 ::tk::EntryBackspace %W
184 bind Spinbox <Control-space> {
185 %W selection from insert
187 bind Spinbox <Select> {
188 %W selection from insert
190 bind Spinbox <Control-Shift-space> {
191 %W selection adjust insert
193 bind Spinbox <Shift-Select> {
194 %W selection adjust insert
196 bind Spinbox <Control-slash> {
197 %W selection range 0 end
199 bind Spinbox <Control-backslash> {
200 %W selection clear
202 bind Spinbox <KeyPress> {
203 ::tk::EntryInsert %W %A
206 # Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
207 # Otherwise, if a widget binding for one of these is defined, the
208 # <KeyPress> class binding will also fire and insert the character,
209 # which is wrong. Ditto for Escape, Return, and Tab.
211 bind Spinbox <Alt-KeyPress> {# nothing}
212 bind Spinbox <Meta-KeyPress> {# nothing}
213 bind Spinbox <Control-KeyPress> {# nothing}
214 bind Spinbox <Escape> {# nothing}
215 bind Spinbox <Return> {# nothing}
216 bind Spinbox <KP_Enter> {# nothing}
217 bind Spinbox <Tab> {# nothing}
218 if {[tk windowingsystem] eq "aqua"} {
219 bind Spinbox <Command-KeyPress> {# nothing}
222 # On Windows, paste is done using Shift-Insert. Shift-Insert already
223 # generates the <<Paste>> event, so we don't need to do anything here.
224 if {[tk windowingsystem] ne "win32"} {
225 bind Spinbox <Insert> {
226 catch {::tk::EntryInsert %W [::tk::GetSelection %W PRIMARY]}
230 # Additional emacs-like bindings:
232 bind Spinbox <Control-a> {
233 if {!$tk_strictMotif} {
234 ::tk::EntrySetCursor %W 0
237 bind Spinbox <Control-b> {
238 if {!$tk_strictMotif} {
239 ::tk::EntrySetCursor %W [expr {[%W index insert] - 1}]
242 bind Spinbox <Control-d> {
243 if {!$tk_strictMotif} {
244 %W delete insert
247 bind Spinbox <Control-e> {
248 if {!$tk_strictMotif} {
249 ::tk::EntrySetCursor %W end
252 bind Spinbox <Control-f> {
253 if {!$tk_strictMotif} {
254 ::tk::EntrySetCursor %W [expr {[%W index insert] + 1}]
257 bind Spinbox <Control-h> {
258 if {!$tk_strictMotif} {
259 ::tk::EntryBackspace %W
262 bind Spinbox <Control-k> {
263 if {!$tk_strictMotif} {
264 %W delete insert end
267 bind Spinbox <Control-t> {
268 if {!$tk_strictMotif} {
269 ::tk::EntryTranspose %W
272 bind Spinbox <Meta-b> {
273 if {!$tk_strictMotif} {
274 ::tk::EntrySetCursor %W [::tk::EntryPreviousWord %W insert]
277 bind Spinbox <Meta-d> {
278 if {!$tk_strictMotif} {
279 %W delete insert [::tk::EntryNextWord %W insert]
282 bind Spinbox <Meta-f> {
283 if {!$tk_strictMotif} {
284 ::tk::EntrySetCursor %W [::tk::EntryNextWord %W insert]
287 bind Spinbox <Meta-BackSpace> {
288 if {!$tk_strictMotif} {
289 %W delete [::tk::EntryPreviousWord %W insert] insert
292 bind Spinbox <Meta-Delete> {
293 if {!$tk_strictMotif} {
294 %W delete [::tk::EntryPreviousWord %W insert] insert
298 # A few additional bindings of my own.
300 bind Spinbox <2> {
301 if {!$tk_strictMotif} {
302 ::tk::EntryScanMark %W %x
305 bind Spinbox <B2-Motion> {
306 if {!$tk_strictMotif} {
307 ::tk::EntryScanDrag %W %x
311 # ::tk::spinbox::Invoke --
312 # Invoke an element of the spinbox
314 # Arguments:
315 # w - The spinbox window.
316 # elem - Element to invoke
318 proc ::tk::spinbox::Invoke {w elem} {
319 variable ::tk::Priv
321 if {![info exists Priv(outsideElement)]} {
322 $w invoke $elem
323 incr Priv(repeated)
325 set delay [$w cget -repeatinterval]
326 if {$delay > 0} {
327 set Priv(afterId) [after $delay \
328 [list ::tk::spinbox::Invoke $w $elem]]
332 # ::tk::spinbox::ClosestGap --
333 # Given x and y coordinates, this procedure finds the closest boundary
334 # between characters to the given coordinates and returns the index
335 # of the character just after the boundary.
337 # Arguments:
338 # w - The spinbox window.
339 # x - X-coordinate within the window.
341 proc ::tk::spinbox::ClosestGap {w x} {
342 set pos [$w index @$x]
343 set bbox [$w bbox $pos]
344 if {($x - [lindex $bbox 0]) < ([lindex $bbox 2]/2)} {
345 return $pos
347 incr pos
350 # ::tk::spinbox::ButtonDown --
351 # This procedure is invoked to handle button-1 presses in spinbox
352 # widgets. It moves the insertion cursor, sets the selection anchor,
353 # and claims the input focus.
355 # Arguments:
356 # w - The spinbox window in which the button was pressed.
357 # x - The x-coordinate of the button press.
359 proc ::tk::spinbox::ButtonDown {w x y} {
360 variable ::tk::Priv
362 # Get the element that was clicked in. If we are not directly over
363 # the spinbox, default to entry. This is necessary for spinbox grabs.
365 set Priv(element) [$w identify $x $y]
366 if {$Priv(element) eq ""} {
367 set Priv(element) "entry"
370 switch -exact $Priv(element) {
371 "buttonup" - "buttondown" {
372 if {"disabled" ne [$w cget -state]} {
373 $w selection element $Priv(element)
374 set Priv(repeated) 0
375 set Priv(relief) [$w cget -$Priv(element)relief]
376 catch {after cancel $Priv(afterId)}
377 set delay [$w cget -repeatdelay]
378 if {$delay > 0} {
379 set Priv(afterId) [after $delay \
380 [list ::tk::spinbox::Invoke $w $Priv(element)]]
382 if {[info exists Priv(outsideElement)]} {
383 unset Priv(outsideElement)
387 "entry" {
388 set Priv(selectMode) char
389 set Priv(mouseMoved) 0
390 set Priv(pressX) $x
391 $w icursor [::tk::spinbox::ClosestGap $w $x]
392 $w selection from insert
393 if {"disabled" ne [$w cget -state]} {focus $w}
394 $w selection clear
396 default {
397 return -code error "unknown spinbox element \"$Priv(element)\""
402 # ::tk::spinbox::ButtonUp --
403 # This procedure is invoked to handle button-1 releases in spinbox
404 # widgets.
406 # Arguments:
407 # w - The spinbox window in which the button was pressed.
408 # x - The x-coordinate of the button press.
410 proc ::tk::spinbox::ButtonUp {w x y} {
411 variable ::tk::Priv
413 ::tk::CancelRepeat
415 # Priv(relief) may not exist if the ButtonUp is not paired with
416 # a preceding ButtonDown
417 if {[info exists Priv(element)] && [info exists Priv(relief)] && \
418 [string match "button*" $Priv(element)]} {
419 if {[info exists Priv(repeated)] && !$Priv(repeated)} {
420 $w invoke $Priv(element)
422 $w configure -$Priv(element)relief $Priv(relief)
423 $w selection element none
427 # ::tk::spinbox::MouseSelect --
428 # This procedure is invoked when dragging out a selection with
429 # the mouse. Depending on the selection mode (character, word,
430 # line) it selects in different-sized units. This procedure
431 # ignores mouse motions initially until the mouse has moved from
432 # one character to another or until there have been multiple clicks.
434 # Arguments:
435 # w - The spinbox window in which the button was pressed.
436 # x - The x-coordinate of the mouse.
437 # cursor - optional place to set cursor.
439 proc ::tk::spinbox::MouseSelect {w x {cursor {}}} {
440 variable ::tk::Priv
442 if {$Priv(element) ne "entry"} {
443 # The ButtonUp command triggered by ButtonRelease-1 handles
444 # invoking one of the spinbuttons.
445 return
447 set cur [::tk::spinbox::ClosestGap $w $x]
448 set anchor [$w index anchor]
449 if {($cur ne $anchor) || (abs($Priv(pressX) - $x) >= 3)} {
450 set Priv(mouseMoved) 1
452 switch $Priv(selectMode) {
453 char {
454 if {$Priv(mouseMoved)} {
455 if {$cur < $anchor} {
456 $w selection range $cur $anchor
457 } elseif {$cur > $anchor} {
458 $w selection range $anchor $cur
459 } else {
460 $w selection clear
464 word {
465 if {$cur < [$w index anchor]} {
466 set before [tcl_wordBreakBefore [$w get] $cur]
467 set after [tcl_wordBreakAfter [$w get] [expr {$anchor-1}]]
468 } else {
469 set before [tcl_wordBreakBefore [$w get] $anchor]
470 set after [tcl_wordBreakAfter [$w get] [expr {$cur - 1}]]
472 if {$before < 0} {
473 set before 0
475 if {$after < 0} {
476 set after end
478 $w selection range $before $after
480 line {
481 $w selection range 0 end
484 if {$cursor ne {} && $cursor ne "ignore"} {
485 catch {$w icursor $cursor}
487 update idletasks
490 # ::tk::spinbox::Paste --
491 # This procedure sets the insertion cursor to the current mouse position,
492 # pastes the selection there, and sets the focus to the window.
494 # Arguments:
495 # w - The spinbox window.
496 # x - X position of the mouse.
498 proc ::tk::spinbox::Paste {w x} {
499 $w icursor [::tk::spinbox::ClosestGap $w $x]
500 catch {$w insert insert [::tk::GetSelection $w PRIMARY]}
501 if {"disabled" eq [$w cget -state]} {
502 focus $w
506 # ::tk::spinbox::Motion --
507 # This procedure is invoked when the mouse moves in a spinbox window
508 # with button 1 down.
510 # Arguments:
511 # w - The spinbox window.
513 proc ::tk::spinbox::Motion {w x y} {
514 variable ::tk::Priv
516 if {![info exists Priv(element)]} {
517 set Priv(element) [$w identify $x $y]
520 set Priv(x) $x
521 if {"entry" eq $Priv(element)} {
522 ::tk::spinbox::MouseSelect $w $x ignore
523 } elseif {[$w identify $x $y] ne $Priv(element)} {
524 if {![info exists Priv(outsideElement)]} {
525 # We've wandered out of the spin button
526 # setting outside element will cause ::tk::spinbox::Invoke to
527 # loop without doing anything
528 set Priv(outsideElement) ""
529 $w selection element none
531 } elseif {[info exists Priv(outsideElement)]} {
532 unset Priv(outsideElement)
533 $w selection element $Priv(element)
537 # ::tk::spinbox::AutoScan --
538 # This procedure is invoked when the mouse leaves an spinbox window
539 # with button 1 down. It scrolls the window left or right,
540 # depending on where the mouse is, and reschedules itself as an
541 # "after" command so that the window continues to scroll until the
542 # mouse moves back into the window or the mouse button is released.
544 # Arguments:
545 # w - The spinbox window.
547 proc ::tk::spinbox::AutoScan {w} {
548 variable ::tk::Priv
550 set x $Priv(x)
551 if {$x >= [winfo width $w]} {
552 $w xview scroll 2 units
553 ::tk::spinbox::MouseSelect $w $x ignore
554 } elseif {$x < 0} {
555 $w xview scroll -2 units
556 ::tk::spinbox::MouseSelect $w $x ignore
558 set Priv(afterId) [after 50 [list ::tk::spinbox::AutoScan $w]]
561 # ::tk::spinbox::GetSelection --
563 # Returns the selected text of the spinbox. Differs from entry in that
564 # a spinbox has no -show option to obscure contents.
566 # Arguments:
567 # w - The spinbox window from which the text to get
569 proc ::tk::spinbox::GetSelection {w} {
570 return [string range [$w get] [$w index sel.first] \
571 [expr {[$w index sel.last] - 1}]]