3 # This file defines the default bindings for Tk listbox widgets
4 # and provides procedures that help in implementing those bindings.
6 # RCS: @(#) $Id: listbox.tcl,v 1.13.2.4 2006/01/25 18:21:41 dgp Exp $
8 # Copyright (c) 1994 The Regents of the University of California.
9 # Copyright (c) 1994-1995 Sun Microsystems, Inc.
10 # Copyright (c) 1998 by Scriptics Corporation.
12 # See the file "license.terms" for information on usage and redistribution
13 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 #--------------------------------------------------------------------------
16 # tk::Priv elements used in this file:
18 # afterId - Token returned by "after" for autoscanning.
19 # listboxPrev - The last element to be selected or deselected
20 # during a selection operation.
21 # listboxSelection - All of the items that were selected before the
22 # current selection operation (such as a mouse
23 # drag) started; used to cancel an operation.
24 #--------------------------------------------------------------------------
26 #-------------------------------------------------------------------------
27 # The code below creates the default class bindings for listboxes.
28 #-------------------------------------------------------------------------
30 # Note: the check for existence of %W below is because this binding
31 # is sometimes invoked after a window has been deleted (e.g. because
32 # there is a double-click binding on the widget that deletes it). Users
33 # can put "break"s in their bindings to avoid the error, but this check
34 # makes that unnecessary.
37 if {[winfo exists
%W
]} {
38 tk::ListboxBeginSelect %W
[%W index
@%x
,%y
]
42 # Ignore double clicks so that users can define their own behaviors.
43 # Among other things, this prevents errors if the user deletes the
44 # listbox on a double click.
46 bind Listbox
<Double-1
> {
50 bind Listbox
<B1-Motion
> {
53 tk::ListboxMotion %W
[%W index
@%x
,%y
]
55 bind Listbox
<ButtonRelease-1
> {
59 bind Listbox
<Shift-1
> {
60 tk::ListboxBeginExtend %W
[%W index
@%x
,%y
]
62 bind Listbox
<Control-1
> {
63 tk::ListboxBeginToggle %W
[%W index
@%x
,%y
]
65 bind Listbox
<B1-Leave
> {
68 tk::ListboxAutoScan %W
70 bind Listbox
<B1-Enter
> {
75 tk::ListboxUpDown %W
-1
77 bind Listbox
<Shift-Up
> {
78 tk::ListboxExtendUpDown %W
-1
81 tk::ListboxUpDown %W
1
83 bind Listbox
<Shift-Down
> {
84 tk::ListboxExtendUpDown %W
1
87 %W xview scroll
-1 units
89 bind Listbox
<Control-Left
> {
90 %W xview scroll
-1 pages
92 bind Listbox
<Right
> {
93 %W xview scroll
1 units
95 bind Listbox
<Control-Right
> {
96 %W xview scroll
1 pages
98 bind Listbox
<Prior
> {
99 %W yview scroll
-1 pages
102 bind Listbox
<Next
> {
103 %W yview scroll
1 pages
106 bind Listbox
<Control-Prior
> {
107 %W xview scroll
-1 pages
109 bind Listbox
<Control-Next
> {
110 %W xview scroll
1 pages
112 bind Listbox
<Home
> {
118 bind Listbox
<Control-Home
> {
121 %W
selection clear
0 end
123 event generate
%W
<<ListboxSelect
>>
125 bind Listbox
<Shift-Control-Home
> {
126 tk::ListboxDataExtend %W
0
128 bind Listbox
<Control-End
> {
131 %W
selection clear
0 end
133 event generate
%W
<<ListboxSelect
>>
135 bind Listbox
<Shift-Control-End
> {
136 tk::ListboxDataExtend %W
[%W index end
]
138 bind Listbox
<<Copy
>> {
139 if {[selection own
-displayof %W
] eq
"%W"} {
140 clipboard clear
-displayof %W
141 clipboard append -displayof %W
[selection get
-displayof %W
]
144 bind Listbox
<space
> {
145 tk::ListboxBeginSelect %W
[%W index active
]
147 bind Listbox
<Select
> {
148 tk::ListboxBeginSelect %W
[%W index active
]
150 bind Listbox
<Control-Shift-space
> {
151 tk::ListboxBeginExtend %W
[%W index active
]
153 bind Listbox
<Shift-Select
> {
154 tk::ListboxBeginExtend %W
[%W index active
]
156 bind Listbox
<Escape
> {
159 bind Listbox
<Control-slash
> {
160 tk::ListboxSelectAll %W
162 bind Listbox
<Control-backslash
> {
163 if {[%W cget
-selectmode] ne
"browse"} {
164 %W
selection clear
0 end
165 event generate
%W
<<ListboxSelect
>>
169 # Additional Tk bindings that aren't part of the Motif look and feel:
174 bind Listbox
<B2-Motion
> {
178 # The MouseWheel will typically only fire on Windows and Mac OS X.
179 # However, someone could use the "event generate" command to produce
180 # one on other platforms.
181 if {[tk windowingsystem
] eq
"classic" ||
[tk windowingsystem
] eq
"aqua"} {
182 bind Listbox
<MouseWheel
> {
183 %W yview scroll
[expr {- (%D
)}] units
185 bind Listbox
<Option-MouseWheel
> {
186 %W yview scroll
[expr {-10 * (%D
)}] units
188 bind Listbox
<Shift-MouseWheel
> {
189 %W xview scroll
[expr {- (%D
)}] units
191 bind Listbox
<Shift-Option-MouseWheel
> {
192 %W xview scroll
[expr {-10 * (%D
)}] units
195 bind Listbox
<MouseWheel
> {
196 %W yview scroll
[expr {- (%D
/ 120) * 4}] units
200 if {"x11" eq
[tk windowingsystem
]} {
201 # Support for mousewheels on Linux/Unix commonly comes through mapping
202 # the wheel to the extended buttons. If you have a mousewheel, find
203 # Linux configuration info at:
204 # http://www.inria.fr/koala/colas/mouse-wheel-scroll/
206 if {!$tk_strictMotif} {
207 %W yview scroll
-5 units
211 if {!$tk_strictMotif} {
212 %W yview scroll
5 units
217 # ::tk::ListboxBeginSelect --
219 # This procedure is typically invoked on button-1 presses. It begins
220 # the process of making a selection in the listbox. Its exact behavior
221 # depends on the selection mode currently in effect for the listbox;
222 # see the Motif documentation for details.
225 # w - The listbox widget.
226 # el - The element for the selection operation (typically the
227 # one under the pointer). Must be in numerical form.
229 proc ::tk::ListboxBeginSelect {w el
} {
231 if {[$w cget
-selectmode] eq
"multiple"} {
232 if {[$w selection includes
$el]} {
233 $w selection clear
$el
238 $w selection clear
0 end
240 $w selection anchor
$el
241 set Priv
(listboxSelection
) {}
242 set Priv
(listboxPrev
) $el
244 event generate
$w <<ListboxSelect
>>
247 # ::tk::ListboxMotion --
249 # This procedure is called to process mouse motion events while
250 # button 1 is down. It may move or extend the selection, depending
251 # on the listbox's selection mode.
254 # w - The listbox widget.
255 # el - The element under the pointer (must be a number).
257 proc ::tk::ListboxMotion {w el
} {
259 if {$el == $Priv(listboxPrev
)} {
262 set anchor
[$w index anchor
]
263 switch [$w cget
-selectmode] {
265 $w selection clear
0 end
267 set Priv
(listboxPrev
) $el
268 event generate
$w <<ListboxSelect
>>
271 set i
$Priv(listboxPrev
)
276 if {[$w selection includes anchor
]} {
277 $w selection clear
$i $el
278 $w selection set anchor
$el
280 $w selection clear
$i $el
281 $w selection clear anchor
$el
283 if {![info exists Priv
(listboxSelection
)]} {
284 set Priv
(listboxSelection
) [$w curselection
]
286 while {($i < $el) && ($i < $anchor)} {
287 if {[lsearch $Priv(listboxSelection
) $i] >= 0} {
292 while {($i > $el) && ($i > $anchor)} {
293 if {[lsearch $Priv(listboxSelection
) $i] >= 0} {
298 set Priv
(listboxPrev
) $el
299 event generate
$w <<ListboxSelect
>>
304 # ::tk::ListboxBeginExtend --
306 # This procedure is typically invoked on shift-button-1 presses. It
307 # begins the process of extending a selection in the listbox. Its
308 # exact behavior depends on the selection mode currently in effect
309 # for the listbox; see the Motif documentation for details.
312 # w - The listbox widget.
313 # el - The element for the selection operation (typically the
314 # one under the pointer). Must be in numerical form.
316 proc ::tk::ListboxBeginExtend {w el
} {
317 if {[$w cget
-selectmode] eq
"extended"} {
318 if {[$w selection includes anchor
]} {
321 # No selection yet; simulate the begin-select operation.
322 ListboxBeginSelect
$w $el
327 # ::tk::ListboxBeginToggle --
329 # This procedure is typically invoked on control-button-1 presses. It
330 # begins the process of toggling a selection in the listbox. Its
331 # exact behavior depends on the selection mode currently in effect
332 # for the listbox; see the Motif documentation for details.
335 # w - The listbox widget.
336 # el - The element for the selection operation (typically the
337 # one under the pointer). Must be in numerical form.
339 proc ::tk::ListboxBeginToggle {w el
} {
341 if {[$w cget
-selectmode] eq
"extended"} {
342 set Priv
(listboxSelection
) [$w curselection
]
343 set Priv
(listboxPrev
) $el
344 $w selection anchor
$el
345 if {[$w selection includes
$el]} {
346 $w selection clear
$el
350 event generate
$w <<ListboxSelect
>>
354 # ::tk::ListboxAutoScan --
355 # This procedure is invoked when the mouse leaves an entry window
356 # with button 1 down. It scrolls the window up, down, left, or
357 # right, depending on where the mouse left the window, and reschedules
358 # itself as an "after" command so that the window continues to scroll until
359 # the mouse moves back into the window or the mouse button is released.
362 # w - The entry window.
364 proc ::tk::ListboxAutoScan {w
} {
366 if {![winfo exists
$w]} return
369 if {$y >= [winfo height
$w]} {
370 $w yview scroll
1 units
372 $w yview scroll
-1 units
373 } elseif
{$x >= [winfo width
$w]} {
374 $w xview scroll
2 units
376 $w xview scroll
-2 units
380 ListboxMotion
$w [$w index
@$x,$y]
381 set Priv
(afterId
) [after 50 [list tk::ListboxAutoScan $w]]
384 # ::tk::ListboxUpDown --
386 # Moves the location cursor (active element) up or down by one element,
387 # and changes the selection if we're in browse or extended selection
391 # w - The listbox widget.
392 # amount - +1 to move down one item, -1 to move back one item.
394 proc ::tk::ListboxUpDown {w amount
} {
396 $w activate
[expr {[$w index active
] + $amount}]
398 switch [$w cget
-selectmode] {
400 $w selection clear
0 end
401 $w selection set active
402 event generate
$w <<ListboxSelect
>>
405 $w selection clear
0 end
406 $w selection set active
407 $w selection anchor active
408 set Priv
(listboxPrev
) [$w index active
]
409 set Priv
(listboxSelection
) {}
410 event generate
$w <<ListboxSelect
>>
415 # ::tk::ListboxExtendUpDown --
417 # Does nothing unless we're in extended selection mode; in this
418 # case it moves the location cursor (active element) up or down by
419 # one element, and extends the selection to that point.
422 # w - The listbox widget.
423 # amount - +1 to move down one item, -1 to move back one item.
425 proc ::tk::ListboxExtendUpDown {w amount
} {
427 if {[$w cget
-selectmode] ne
"extended"} {
430 set active
[$w index active
]
431 if {![info exists Priv
(listboxSelection
)]} {
432 $w selection set $active
433 set Priv
(listboxSelection
) [$w curselection
]
435 $w activate
[expr {$active + $amount}]
437 ListboxMotion
$w [$w index active
]
440 # ::tk::ListboxDataExtend
442 # This procedure is called for key-presses such as Shift-KEndData.
443 # If the selection mode isn't multiple or extend then it does nothing.
444 # Otherwise it moves the active element to el and, if we're in
445 # extended mode, extends the selection to that point.
448 # w - The listbox widget.
449 # el - An integer element number.
451 proc ::tk::ListboxDataExtend {w el
} {
452 set mode
[$w cget
-selectmode]
453 if {$mode eq
"extended"} {
456 if {[$w selection includes anchor
]} {
459 } elseif
{$mode eq
"multiple"} {
465 # ::tk::ListboxCancel
467 # This procedure is invoked to cancel an extended selection in
468 # progress. If there is an extended selection in progress, it
469 # restores all of the items between the active one and the anchor
470 # to their previous selection state.
473 # w - The listbox widget.
475 proc ::tk::ListboxCancel w
{
477 if {[$w cget
-selectmode] ne
"extended"} {
480 set first
[$w index anchor
]
481 set last
$Priv(listboxPrev
)
483 # Not actually doing any selection right now
486 if {$first > $last} {
491 $w selection clear
$first $last
492 while {$first <= $last} {
493 if {[lsearch $Priv(listboxSelection
) $first] >= 0} {
494 $w selection set $first
498 event generate
$w <<ListboxSelect
>>
501 # ::tk::ListboxSelectAll
503 # This procedure is invoked to handle the "select all" operation.
504 # For single and browse mode, it just selects the active element.
505 # Otherwise it selects everything in the widget.
508 # w - The listbox widget.
510 proc ::tk::ListboxSelectAll w
{
511 set mode
[$w cget
-selectmode]
512 if {$mode eq
"single" ||
$mode eq
"browse"} {
513 $w selection clear
0 end
514 $w selection set active
516 $w selection set 0 end
518 event generate
$w <<ListboxSelect
>>