1 # $Id: treeview.tcl,v 1.2 2006/12/18 19:33:14 jenglish Exp $
3 # ttk::treeview widget bindings and utilities.
6 namespace eval ttk
::treeview {
11 set State
(activeWidget
) {}
12 set State
(activeHeading
) {}
16 set State
(pressMode
) none
19 # For pressMode == "resize"
20 set State
(resizeColumn
) #0
22 # For pressmode == "heading"
25 # Provide [lassign] if not already present
26 # (@@@ TODO: check if this is still needed after horrible-identify purge)
28 if {![llength [info commands lassign
]]} {
29 proc lassign
{vals args
} {
30 uplevel 1 [list foreach $args $vals break]
38 bind Treeview
<Motion
> { ttk
::treeview::Motion %W
%x
%y
}
39 bind Treeview
<B1-Leave
> { #nothing }
40 bind Treeview
<Leave
> { ttk
::treeview::ActivateHeading {} {}}
41 bind Treeview
<ButtonPress-1
> { ttk
::treeview::Press %W
%x
%y
}
42 bind Treeview
<Double-ButtonPress-1
> { ttk
::treeview::DoubleClick %W
%x
%y
}
43 bind Treeview
<ButtonRelease-1
> { ttk
::treeview::Release %W
%x
%y
}
44 bind Treeview
<B1-Motion
> { ttk
::treeview::Drag %W
%x
%y
}
45 bind Treeview
<KeyPress-Up
> { ttk
::treeview::Keynav %W up
}
46 bind Treeview
<KeyPress-Down
> { ttk
::treeview::Keynav %W down
}
47 bind Treeview
<KeyPress-Right
> { ttk
::treeview::Keynav %W right
}
48 bind Treeview
<KeyPress-Left
> { ttk
::treeview::Keynav %W left
}
49 bind Treeview
<KeyPress-Prior
> { %W yview scroll
-1 pages
}
50 bind Treeview
<KeyPress-Next
> { %W yview scroll
1 pages
}
51 bind Treeview
<KeyPress-Return
> { ttk
::treeview::ToggleFocus %W
}
52 bind Treeview
<KeyPress-space
> { ttk
::treeview::ToggleFocus %W
}
54 bind Treeview
<Shift-ButtonPress-1
> \
55 { ttk
::treeview::Select %W
%x
%y extend
}
56 bind Treeview
<Control-ButtonPress-1
> \
57 { ttk
::treeview::Select %W
%x
%y toggle
}
59 # Standard mousewheel bindings:
61 bind Treeview
<MouseWheel
> { %W yview scroll
[expr {- (%D
/ 120) * 4}] units
}
62 if {[string equal
"x11" [tk windowingsystem
]]} {
63 bind Treeview
<ButtonPress-4
> { %W yview scroll
-5 units
}
64 bind Treeview
<ButtonPress-5
> { %W yview scroll
5 units
}
67 ### Binding procedures.
70 ## Keynav -- Keyboard navigation
72 # @@@ TODO: verify/rewrite up and down code.
74 proc ttk
::treeview::Keynav {w dir
} {
76 if {$focus eq
""} { return }
80 if {[set up
[$w prev
$focus]] eq
""} {
81 set focus [$w parent
$focus]
83 while {[$w item
$up -open] && [llength [$w children
$up]]} {
84 set up
[lindex [$w children
$up] end
]
90 if {[$w item
$focus -open] && [llength [$w children
$focus]]} {
91 set focus [lindex [$w children
$focus] 0]
94 while {$up ne
"" && [set down
[$w next
$up]] eq
""} {
95 set up
[$w parent
$up]
101 if {[$w item
$focus -open] && [llength [$w children
$focus]]} {
104 set focus [$w parent
$focus]
113 SelectOp
$w $focus choose
117 ## Motion -- pointer motion binding.
118 # Sets cursor, active element ...
120 proc ttk
::treeview::Motion {w x y
} {
121 variable ::ttk::Cursors
127 lassign
[$w identify
$x $y] what where detail
129 separator
{ set cursor
$Cursors(hresize
) }
130 heading
{ set activeHeading
$where }
133 if {[$w cget
-cursor] ne
$cursor} {
134 $w configure
-cursor $cursor
136 ActivateHeading
$w $activeHeading
139 ## ActivateHeading -- track active heading element
141 proc ttk
::treeview::ActivateHeading {w heading
} {
144 if {$w != $State(activeWidget
) ||
$heading != $State(activeHeading
)} {
145 if {$State(activeHeading
) != {}} {
146 $State(activeWidget
) heading
$State(activeHeading
) state
!active
148 if {$heading != {}} {
149 $w heading
$heading state active
151 set State
(activeHeading
) $heading
152 set State
(activeWidget
) $w
156 ## Select $w $x $y $selectop
157 # Binding procedure for selection operations.
158 # See "Selection modes", below.
160 proc ttk
::treeview::Select {w x y op
} {
161 if {[set item
[$w identify row
$x $y]] ne
"" } {
162 SelectOp
$w $item $op
166 ## DoubleClick -- Double-ButtonPress-1 binding.
168 proc ttk
::treeview::DoubleClick {w x y
} {
169 if {[set row
[$w identify row
$x $y]] ne
""} {
172 Press
$w $x $y ;# perform single-click action
176 ## Press -- ButtonPress binding.
178 proc ttk
::treeview::Press {w x y
} {
179 lassign
[$w identify
$x $y] what where detail
180 focus $w ;# or: ClickToFocus?
184 heading
{ heading.press
$w $where }
185 separator
{ resize.press
$w $x $where }
188 item
{ SelectOp
$w $where choose
}
190 if {$what eq
"item" && [string match
*indicator
$detail]} {
195 ## Drag -- B1-Motion binding
197 proc ttk
::treeview::Drag {w x y
} {
199 switch $State(pressMode
) {
200 resize
{ resize.drag
$w $x }
201 heading
{ heading.drag
$w $x $y }
205 proc ttk
::treeview::Release {w x y
} {
207 switch $State(pressMode
) {
208 resize
{ resize.release
$w $x }
209 heading
{ heading.release
$w }
211 set State
(pressMode
) none
215 ### Interactive column resizing.
217 proc ttk
::treeview::resize.press
{w x column
} {
219 set State
(pressMode
) "resize"
220 set State
(resizeColumn
) $column
223 proc ttk
::treeview::resize.drag
{w x
} {
225 $w drag
$State(resizeColumn
) $x
228 proc ttk
::treeview::resize.release
{w x
} {
232 ### Heading activation.
235 proc ttk
::treeview::heading.press
{w column
} {
237 set State
(pressMode
) "heading"
238 set State
(heading
) $column
239 $w heading
$column state pressed
242 proc ttk
::treeview::heading.drag
{w x y
} {
244 lassign
[$w identify
$x $y] what where detail
245 if {$what eq
"heading" && $where eq
$State(heading
)} {
246 $w heading
$State(heading
) state pressed
248 $w heading
$State(heading
) state
!pressed
252 proc ttk
::treeview::heading.release
{w
} {
254 if {[lsearch -exact [$w heading
$State(heading
) state
] pressed
] >= 0} {
255 after idle
[$w heading
$State(heading
) -command]
257 $w heading
$State(heading
) state
!pressed
263 ## SelectOp $w $item [ choose | extend | toggle ] --
264 # Dispatch to appropriate selection operation
265 # depending on current value of -selectmode.
267 proc ttk
::treeview::SelectOp {w item op
} {
268 select.
$op.
[$w cget
-selectmode] $w $item
273 proc ttk
::treeview::select.choose.none
{w item
} { $w focus $item }
274 proc ttk
::treeview::select.toggle.none
{w item
} { $w focus $item }
275 proc ttk
::treeview::select.extend.none
{w item
} { $w focus $item }
277 ## -selectmode browse:
279 proc ttk
::treeview::select.choose.browse
{w item
} { BrowseTo
$w $item }
280 proc ttk
::treeview::select.toggle.browse
{w item
} { BrowseTo
$w $item }
281 proc ttk
::treeview::select.extend.browse
{w item
} { BrowseTo
$w $item }
283 ## -selectmode multiple:
285 proc ttk
::treeview::select.choose.extended
{w item
} {
288 proc ttk
::treeview::select.toggle.extended
{w item
} {
289 $w selection toggle
$item
291 proc ttk
::treeview::select.extend.extended
{w item
} {
292 if {[set anchor
[$w focus]] ne
""} {
293 $w selection set [between
$w $anchor $item]
299 ### Tree structure utilities.
302 ## between $tv $item1 $item2 --
303 # Returns a list of all items between $item1 and $item2,
304 # in preorder traversal order. $item1 and $item2 may be
308 # This routine is O(N) in the size of the tree.
309 # There's probably a way to do this that's O(N) in the number
310 # of items returned, but I'm not clever enough to figure it out.
312 proc ttk
::treeview::between {tv item1 item2
} {
313 variable between
[list]
314 variable selectingBetween
0
315 ScanBetween
$tv $item1 $item2 {}
320 # Recursive worker routine for ttk::treeview::between
322 proc ttk
::treeview::ScanBetween {tv item1 item2 item
} {
324 variable selectingBetween
326 if {$item eq
$item1 ||
$item eq
$item2} {
327 lappend between
$item
328 set selectingBetween
[expr {!$selectingBetween}]
329 } elseif
{$selectingBetween} {
330 lappend between
$item
332 foreach child
[$tv children
$item] {
333 ScanBetween
$tv $item1 $item2 $child
337 ### User interaction utilities.
340 ## OpenItem, CloseItem -- Set the open state of an item, generate event
343 proc ttk
::treeview::OpenItem {w item
} {
345 event generate
$w <<TreeviewOpen
>>
346 $w item
$item -open true
349 proc ttk
::treeview::CloseItem {w item
} {
350 $w item
$item -open false
352 event generate
$w <<TreeviewClose
>>
355 ## Toggle -- toggle opened/closed state of item
357 proc ttk
::treeview::Toggle {w item
} {
358 if {[$w item
$item -open]} {
365 ## ToggleFocus -- toggle opened/closed state of focus item
367 proc ttk
::treeview::ToggleFocus {w
} {
374 ## BrowseTo -- navigate to specified item; set focus and selection
376 proc ttk
::treeview::BrowseTo {w item
} {
379 $w selection set [list $item]