listbox.tcl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:14k
源码类别:

通讯编程

开发平台:

Visual C++

  1. # listbox.tcl --
  2. #
  3. # This file defines the default bindings for Tk listbox widgets
  4. # and provides procedures that help in implementing those bindings.
  5. #
  6. # RCS: @(#) $Id: listbox.tcl,v 1.13.2.4 2006/01/25 18:21:41 dgp Exp $
  7. #
  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.
  11. #
  12. # See the file "license.terms" for information on usage and redistribution
  13. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  14. #--------------------------------------------------------------------------
  15. # tk::Priv elements used in this file:
  16. #
  17. # afterId - Token returned by "after" for autoscanning.
  18. # listboxPrev - The last element to be selected or deselected
  19. # during a selection operation.
  20. # listboxSelection - All of the items that were selected before the
  21. # current selection operation (such as a mouse
  22. # drag) started;  used to cancel an operation.
  23. #--------------------------------------------------------------------------
  24. #-------------------------------------------------------------------------
  25. # The code below creates the default class bindings for listboxes.
  26. #-------------------------------------------------------------------------
  27. # Note: the check for existence of %W below is because this binding
  28. # is sometimes invoked after a window has been deleted (e.g. because
  29. # there is a double-click binding on the widget that deletes it).  Users
  30. # can put "break"s in their bindings to avoid the error, but this check
  31. # makes that unnecessary.
  32. bind Listbox <1> {
  33.     if {[winfo exists %W]} {
  34. tk::ListboxBeginSelect %W [%W index @%x,%y]
  35.     }
  36. }
  37. # Ignore double clicks so that users can define their own behaviors.
  38. # Among other things, this prevents errors if the user deletes the
  39. # listbox on a double click.
  40. bind Listbox <Double-1> {
  41.     # Empty script
  42. }
  43. bind Listbox <B1-Motion> {
  44.     set tk::Priv(x) %x
  45.     set tk::Priv(y) %y
  46.     tk::ListboxMotion %W [%W index @%x,%y]
  47. }
  48. bind Listbox <ButtonRelease-1> {
  49.     tk::CancelRepeat
  50.     %W activate @%x,%y
  51. }
  52. bind Listbox <Shift-1> {
  53.     tk::ListboxBeginExtend %W [%W index @%x,%y]
  54. }
  55. bind Listbox <Control-1> {
  56.     tk::ListboxBeginToggle %W [%W index @%x,%y]
  57. }
  58. bind Listbox <B1-Leave> {
  59.     set tk::Priv(x) %x
  60.     set tk::Priv(y) %y
  61.     tk::ListboxAutoScan %W
  62. }
  63. bind Listbox <B1-Enter> {
  64.     tk::CancelRepeat
  65. }
  66. bind Listbox <Up> {
  67.     tk::ListboxUpDown %W -1
  68. }
  69. bind Listbox <Shift-Up> {
  70.     tk::ListboxExtendUpDown %W -1
  71. }
  72. bind Listbox <Down> {
  73.     tk::ListboxUpDown %W 1
  74. }
  75. bind Listbox <Shift-Down> {
  76.     tk::ListboxExtendUpDown %W 1
  77. }
  78. bind Listbox <Left> {
  79.     %W xview scroll -1 units
  80. }
  81. bind Listbox <Control-Left> {
  82.     %W xview scroll -1 pages
  83. }
  84. bind Listbox <Right> {
  85.     %W xview scroll 1 units
  86. }
  87. bind Listbox <Control-Right> {
  88.     %W xview scroll 1 pages
  89. }
  90. bind Listbox <Prior> {
  91.     %W yview scroll -1 pages
  92.     %W activate @0,0
  93. }
  94. bind Listbox <Next> {
  95.     %W yview scroll 1 pages
  96.     %W activate @0,0
  97. }
  98. bind Listbox <Control-Prior> {
  99.     %W xview scroll -1 pages
  100. }
  101. bind Listbox <Control-Next> {
  102.     %W xview scroll 1 pages
  103. }
  104. bind Listbox <Home> {
  105.     %W xview moveto 0
  106. }
  107. bind Listbox <End> {
  108.     %W xview moveto 1
  109. }
  110. bind Listbox <Control-Home> {
  111.     %W activate 0
  112.     %W see 0
  113.     %W selection clear 0 end
  114.     %W selection set 0
  115.     event generate %W <<ListboxSelect>>
  116. }
  117. bind Listbox <Shift-Control-Home> {
  118.     tk::ListboxDataExtend %W 0
  119. }
  120. bind Listbox <Control-End> {
  121.     %W activate end
  122.     %W see end
  123.     %W selection clear 0 end
  124.     %W selection set end
  125.     event generate %W <<ListboxSelect>>
  126. }
  127. bind Listbox <Shift-Control-End> {
  128.     tk::ListboxDataExtend %W [%W index end]
  129. }
  130. bind Listbox <<Copy>> {
  131.     if {[selection own -displayof %W] eq "%W"} {
  132. clipboard clear -displayof %W
  133. clipboard append -displayof %W [selection get -displayof %W]
  134.     }
  135. }
  136. bind Listbox <space> {
  137.     tk::ListboxBeginSelect %W [%W index active]
  138. }
  139. bind Listbox <Select> {
  140.     tk::ListboxBeginSelect %W [%W index active]
  141. }
  142. bind Listbox <Control-Shift-space> {
  143.     tk::ListboxBeginExtend %W [%W index active]
  144. }
  145. bind Listbox <Shift-Select> {
  146.     tk::ListboxBeginExtend %W [%W index active]
  147. }
  148. bind Listbox <Escape> {
  149.     tk::ListboxCancel %W
  150. }
  151. bind Listbox <Control-slash> {
  152.     tk::ListboxSelectAll %W
  153. }
  154. bind Listbox <Control-backslash> {
  155.     if {[%W cget -selectmode] ne "browse"} {
  156. %W selection clear 0 end
  157. event generate %W <<ListboxSelect>>
  158.     }
  159. }
  160. # Additional Tk bindings that aren't part of the Motif look and feel:
  161. bind Listbox <2> {
  162.     %W scan mark %x %y
  163. }
  164. bind Listbox <B2-Motion> {
  165.     %W scan dragto %x %y
  166. }
  167. # The MouseWheel will typically only fire on Windows and Mac OS X.
  168. # However, someone could use the "event generate" command to produce
  169. # one on other platforms.
  170. if {[tk windowingsystem] eq "classic" || [tk windowingsystem] eq "aqua"} {
  171.     bind Listbox <MouseWheel> {
  172.         %W yview scroll [expr {- (%D)}] units
  173.     }
  174.     bind Listbox <Option-MouseWheel> {
  175.         %W yview scroll [expr {-10 * (%D)}] units
  176.     }
  177.     bind Listbox <Shift-MouseWheel> {
  178.         %W xview scroll [expr {- (%D)}] units
  179.     }
  180.     bind Listbox <Shift-Option-MouseWheel> {
  181.         %W xview scroll [expr {-10 * (%D)}] units
  182.     }
  183. } else {
  184.     bind Listbox <MouseWheel> {
  185.         %W yview scroll [expr {- (%D / 120) * 4}] units
  186.     }
  187. }
  188. if {"x11" eq [tk windowingsystem]} {
  189.     # Support for mousewheels on Linux/Unix commonly comes through mapping
  190.     # the wheel to the extended buttons.  If you have a mousewheel, find
  191.     # Linux configuration info at:
  192.     # http://www.inria.fr/koala/colas/mouse-wheel-scroll/
  193.     bind Listbox <4> {
  194. if {!$tk_strictMotif} {
  195.     %W yview scroll -5 units
  196. }
  197.     }
  198.     bind Listbox <5> {
  199. if {!$tk_strictMotif} {
  200.     %W yview scroll 5 units
  201. }
  202.     }
  203. }
  204. # ::tk::ListboxBeginSelect --
  205. #
  206. # This procedure is typically invoked on button-1 presses.  It begins
  207. # the process of making a selection in the listbox.  Its exact behavior
  208. # depends on the selection mode currently in effect for the listbox;
  209. # see the Motif documentation for details.
  210. #
  211. # Arguments:
  212. # w - The listbox widget.
  213. # el - The element for the selection operation (typically the
  214. # one under the pointer).  Must be in numerical form.
  215. proc ::tk::ListboxBeginSelect {w el} {
  216.     variable ::tk::Priv
  217.     if {[$w cget -selectmode] eq "multiple"} {
  218. if {[$w selection includes $el]} {
  219.     $w selection clear $el
  220. } else {
  221.     $w selection set $el
  222. }
  223.     } else {
  224. $w selection clear 0 end
  225. $w selection set $el
  226. $w selection anchor $el
  227. set Priv(listboxSelection) {}
  228. set Priv(listboxPrev) $el
  229.     }
  230.     event generate $w <<ListboxSelect>>
  231. }
  232. # ::tk::ListboxMotion --
  233. #
  234. # This procedure is called to process mouse motion events while
  235. # button 1 is down.  It may move or extend the selection, depending
  236. # on the listbox's selection mode.
  237. #
  238. # Arguments:
  239. # w - The listbox widget.
  240. # el - The element under the pointer (must be a number).
  241. proc ::tk::ListboxMotion {w el} {
  242.     variable ::tk::Priv
  243.     if {$el == $Priv(listboxPrev)} {
  244. return
  245.     }
  246.     set anchor [$w index anchor]
  247.     switch [$w cget -selectmode] {
  248. browse {
  249.     $w selection clear 0 end
  250.     $w selection set $el
  251.     set Priv(listboxPrev) $el
  252.     event generate $w <<ListboxSelect>>
  253. }
  254. extended {
  255.     set i $Priv(listboxPrev)
  256.     if {$i eq ""} {
  257. set i $el
  258. $w selection set $el
  259.     }
  260.     if {[$w selection includes anchor]} {
  261. $w selection clear $i $el
  262. $w selection set anchor $el
  263.     } else {
  264. $w selection clear $i $el
  265. $w selection clear anchor $el
  266.     }
  267.     if {![info exists Priv(listboxSelection)]} {
  268. set Priv(listboxSelection) [$w curselection]
  269.     }
  270.     while {($i < $el) && ($i < $anchor)} {
  271. if {[lsearch $Priv(listboxSelection) $i] >= 0} {
  272.     $w selection set $i
  273. }
  274. incr i
  275.     }
  276.     while {($i > $el) && ($i > $anchor)} {
  277. if {[lsearch $Priv(listboxSelection) $i] >= 0} {
  278.     $w selection set $i
  279. }
  280. incr i -1
  281.     }
  282.     set Priv(listboxPrev) $el
  283.     event generate $w <<ListboxSelect>>
  284. }
  285.     }
  286. }
  287. # ::tk::ListboxBeginExtend --
  288. #
  289. # This procedure is typically invoked on shift-button-1 presses.  It
  290. # begins the process of extending a selection in the listbox.  Its
  291. # exact behavior depends on the selection mode currently in effect
  292. # for the listbox;  see the Motif documentation for details.
  293. #
  294. # Arguments:
  295. # w - The listbox widget.
  296. # el - The element for the selection operation (typically the
  297. # one under the pointer).  Must be in numerical form.
  298. proc ::tk::ListboxBeginExtend {w el} {
  299.     if {[$w cget -selectmode] eq "extended"} {
  300. if {[$w selection includes anchor]} {
  301.     ListboxMotion $w $el
  302. } else {
  303.     # No selection yet; simulate the begin-select operation.
  304.     ListboxBeginSelect $w $el
  305. }
  306.     }
  307. }
  308. # ::tk::ListboxBeginToggle --
  309. #
  310. # This procedure is typically invoked on control-button-1 presses.  It
  311. # begins the process of toggling a selection in the listbox.  Its
  312. # exact behavior depends on the selection mode currently in effect
  313. # for the listbox;  see the Motif documentation for details.
  314. #
  315. # Arguments:
  316. # w - The listbox widget.
  317. # el - The element for the selection operation (typically the
  318. # one under the pointer).  Must be in numerical form.
  319. proc ::tk::ListboxBeginToggle {w el} {
  320.     variable ::tk::Priv
  321.     if {[$w cget -selectmode] eq "extended"} {
  322. set Priv(listboxSelection) [$w curselection]
  323. set Priv(listboxPrev) $el
  324. $w selection anchor $el
  325. if {[$w selection includes $el]} {
  326.     $w selection clear $el
  327. } else {
  328.     $w selection set $el
  329. }
  330. event generate $w <<ListboxSelect>>
  331.     }
  332. }
  333. # ::tk::ListboxAutoScan --
  334. # This procedure is invoked when the mouse leaves an entry window
  335. # with button 1 down.  It scrolls the window up, down, left, or
  336. # right, depending on where the mouse left the window, and reschedules
  337. # itself as an "after" command so that the window continues to scroll until
  338. # the mouse moves back into the window or the mouse button is released.
  339. #
  340. # Arguments:
  341. # w - The entry window.
  342. proc ::tk::ListboxAutoScan {w} {
  343.     variable ::tk::Priv
  344.     if {![winfo exists $w]} return
  345.     set x $Priv(x)
  346.     set y $Priv(y)
  347.     if {$y >= [winfo height $w]} {
  348. $w yview scroll 1 units
  349.     } elseif {$y < 0} {
  350. $w yview scroll -1 units
  351.     } elseif {$x >= [winfo width $w]} {
  352. $w xview scroll 2 units
  353.     } elseif {$x < 0} {
  354. $w xview scroll -2 units
  355.     } else {
  356. return
  357.     }
  358.     ListboxMotion $w [$w index @$x,$y]
  359.     set Priv(afterId) [after 50 [list tk::ListboxAutoScan $w]]
  360. }
  361. # ::tk::ListboxUpDown --
  362. #
  363. # Moves the location cursor (active element) up or down by one element,
  364. # and changes the selection if we're in browse or extended selection
  365. # mode.
  366. #
  367. # Arguments:
  368. # w - The listbox widget.
  369. # amount - +1 to move down one item, -1 to move back one item.
  370. proc ::tk::ListboxUpDown {w amount} {
  371.     variable ::tk::Priv
  372.     $w activate [expr {[$w index active] + $amount}]
  373.     $w see active
  374.     switch [$w cget -selectmode] {
  375. browse {
  376.     $w selection clear 0 end
  377.     $w selection set active
  378.     event generate $w <<ListboxSelect>>
  379. }
  380. extended {
  381.     $w selection clear 0 end
  382.     $w selection set active
  383.     $w selection anchor active
  384.     set Priv(listboxPrev) [$w index active]
  385.     set Priv(listboxSelection) {}
  386.     event generate $w <<ListboxSelect>>
  387. }
  388.     }
  389. }
  390. # ::tk::ListboxExtendUpDown --
  391. #
  392. # Does nothing unless we're in extended selection mode;  in this
  393. # case it moves the location cursor (active element) up or down by
  394. # one element, and extends the selection to that point.
  395. #
  396. # Arguments:
  397. # w - The listbox widget.
  398. # amount - +1 to move down one item, -1 to move back one item.
  399. proc ::tk::ListboxExtendUpDown {w amount} {
  400.     variable ::tk::Priv
  401.     if {[$w cget -selectmode] ne "extended"} {
  402. return
  403.     }
  404.     set active [$w index active]
  405.     if {![info exists Priv(listboxSelection)]} {
  406. $w selection set $active
  407. set Priv(listboxSelection) [$w curselection]
  408.     }
  409.     $w activate [expr {$active + $amount}]
  410.     $w see active
  411.     ListboxMotion $w [$w index active]
  412. }
  413. # ::tk::ListboxDataExtend
  414. #
  415. # This procedure is called for key-presses such as Shift-KEndData.
  416. # If the selection mode isn't multiple or extend then it does nothing.
  417. # Otherwise it moves the active element to el and, if we're in
  418. # extended mode, extends the selection to that point.
  419. #
  420. # Arguments:
  421. # w - The listbox widget.
  422. # el - An integer element number.
  423. proc ::tk::ListboxDataExtend {w el} {
  424.     set mode [$w cget -selectmode]
  425.     if {$mode eq "extended"} {
  426. $w activate $el
  427. $w see $el
  428.         if {[$w selection includes anchor]} {
  429.     ListboxMotion $w $el
  430. }
  431.     } elseif {$mode eq "multiple"} {
  432. $w activate $el
  433. $w see $el
  434.     }
  435. }
  436. # ::tk::ListboxCancel
  437. #
  438. # This procedure is invoked to cancel an extended selection in
  439. # progress.  If there is an extended selection in progress, it
  440. # restores all of the items between the active one and the anchor
  441. # to their previous selection state.
  442. #
  443. # Arguments:
  444. # w - The listbox widget.
  445. proc ::tk::ListboxCancel w {
  446.     variable ::tk::Priv
  447.     if {[$w cget -selectmode] ne "extended"} {
  448. return
  449.     }
  450.     set first [$w index anchor]
  451.     set last $Priv(listboxPrev)
  452.     if { $last eq "" } {
  453. # Not actually doing any selection right now
  454. return
  455.     }
  456.     if {$first > $last} {
  457. set tmp $first
  458. set first $last
  459. set last $tmp
  460.     }
  461.     $w selection clear $first $last
  462.     while {$first <= $last} {
  463. if {[lsearch $Priv(listboxSelection) $first] >= 0} {
  464.     $w selection set $first
  465. }
  466. incr first
  467.     }
  468.     event generate $w <<ListboxSelect>>
  469. }
  470. # ::tk::ListboxSelectAll
  471. #
  472. # This procedure is invoked to handle the "select all" operation.
  473. # For single and browse mode, it just selects the active element.
  474. # Otherwise it selects everything in the widget.
  475. #
  476. # Arguments:
  477. # w - The listbox widget.
  478. proc ::tk::ListboxSelectAll w {
  479.     set mode [$w cget -selectmode]
  480.     if {$mode eq "single" || $mode eq "browse"} {
  481. $w selection clear 0 end
  482. $w selection set active
  483.     } else {
  484. $w selection set 0 end
  485.     }
  486.     event generate $w <<ListboxSelect>>
  487. }