1 # $Id: treeview.tcl,v 1.4.2.1 2008/06/20 14:14:20 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 ttk
::copyBindings TtkScrollable Treeview
61 ### Binding procedures.
64 ## Keynav -- Keyboard navigation
66 # @@@ TODO: verify/rewrite up and down code.
68 proc ttk
::treeview::Keynav {w dir
} {
70 if {$focus eq
""} { return }
74 if {[set up
[$w prev
$focus]] eq
""} {
75 set focus [$w parent
$focus]
77 while {[$w item
$up -open] && [llength [$w children
$up]]} {
78 set up
[lindex [$w children
$up] end
]
84 if {[$w item
$focus -open] && [llength [$w children
$focus]]} {
85 set focus [lindex [$w children
$focus] 0]
88 while {$up ne
"" && [set down
[$w next
$up]] eq
""} {
89 set up
[$w parent
$up]
95 if {[$w item
$focus -open] && [llength [$w children
$focus]]} {
98 set focus [$w parent
$focus]
107 SelectOp
$w $focus choose
111 ## Motion -- pointer motion binding.
112 # Sets cursor, active element ...
114 proc ttk
::treeview::Motion {w x y
} {
115 variable ::ttk::Cursors
121 lassign
[$w identify
$x $y] what where detail
123 separator
{ set cursor
$Cursors(hresize
) }
124 heading
{ set activeHeading
$where }
127 if {[$w cget
-cursor] ne
$cursor} {
128 $w configure
-cursor $cursor
130 ActivateHeading
$w $activeHeading
133 ## ActivateHeading -- track active heading element
135 proc ttk
::treeview::ActivateHeading {w heading
} {
138 if {$w != $State(activeWidget
) ||
$heading != $State(activeHeading
)} {
139 if {$State(activeHeading
) != {}} {
140 $State(activeWidget
) heading
$State(activeHeading
) state
!active
142 if {$heading != {}} {
143 $w heading
$heading state active
145 set State
(activeHeading
) $heading
146 set State
(activeWidget
) $w
150 ## Select $w $x $y $selectop
151 # Binding procedure for selection operations.
152 # See "Selection modes", below.
154 proc ttk
::treeview::Select {w x y op
} {
155 if {[set item
[$w identify row
$x $y]] ne
"" } {
156 SelectOp
$w $item $op
160 ## DoubleClick -- Double-ButtonPress-1 binding.
162 proc ttk
::treeview::DoubleClick {w x y
} {
163 if {[set row
[$w identify row
$x $y]] ne
""} {
166 Press
$w $x $y ;# perform single-click action
170 ## Press -- ButtonPress binding.
172 proc ttk
::treeview::Press {w x y
} {
173 lassign
[$w identify
$x $y] what where detail
174 focus $w ;# or: ClickToFocus?
178 heading
{ heading.press
$w $where }
179 separator
{ resize.press
$w $x $where }
182 item
{ SelectOp
$w $where choose
}
184 if {$what eq
"item" && [string match
*indicator
$detail]} {
189 ## Drag -- B1-Motion binding
191 proc ttk
::treeview::Drag {w x y
} {
193 switch $State(pressMode
) {
194 resize
{ resize.drag
$w $x }
195 heading
{ heading.drag
$w $x $y }
199 proc ttk
::treeview::Release {w x y
} {
201 switch $State(pressMode
) {
202 resize
{ resize.release
$w $x }
203 heading
{ heading.release
$w }
205 set State
(pressMode
) none
209 ### Interactive column resizing.
211 proc ttk
::treeview::resize.press
{w x column
} {
213 set State
(pressMode
) "resize"
214 set State
(resizeColumn
) $column
217 proc ttk
::treeview::resize.drag
{w x
} {
219 $w drag
$State(resizeColumn
) $x
222 proc ttk
::treeview::resize.release
{w x
} {
226 ### Heading activation.
229 proc ttk
::treeview::heading.press
{w column
} {
231 set State
(pressMode
) "heading"
232 set State
(heading
) $column
233 $w heading
$column state pressed
236 proc ttk
::treeview::heading.drag
{w x y
} {
238 lassign
[$w identify
$x $y] what where detail
239 if {$what eq
"heading" && $where eq
$State(heading
)} {
240 $w heading
$State(heading
) state pressed
242 $w heading
$State(heading
) state
!pressed
246 proc ttk
::treeview::heading.release
{w
} {
248 if {[lsearch -exact [$w heading
$State(heading
) state
] pressed
] >= 0} {
249 after idle
[$w heading
$State(heading
) -command]
251 $w heading
$State(heading
) state
!pressed
257 ## SelectOp $w $item [ choose | extend | toggle ] --
258 # Dispatch to appropriate selection operation
259 # depending on current value of -selectmode.
261 proc ttk
::treeview::SelectOp {w item op
} {
262 select.
$op.
[$w cget
-selectmode] $w $item
267 proc ttk
::treeview::select.choose.none
{w item
} { $w focus $item }
268 proc ttk
::treeview::select.toggle.none
{w item
} { $w focus $item }
269 proc ttk
::treeview::select.extend.none
{w item
} { $w focus $item }
271 ## -selectmode browse:
273 proc ttk
::treeview::select.choose.browse
{w item
} { BrowseTo
$w $item }
274 proc ttk
::treeview::select.toggle.browse
{w item
} { BrowseTo
$w $item }
275 proc ttk
::treeview::select.extend.browse
{w item
} { BrowseTo
$w $item }
277 ## -selectmode multiple:
279 proc ttk
::treeview::select.choose.extended
{w item
} {
282 proc ttk
::treeview::select.toggle.extended
{w item
} {
283 $w selection toggle
[list $item]
285 proc ttk
::treeview::select.extend.extended
{w item
} {
286 if {[set anchor
[$w focus]] ne
""} {
287 $w selection set [between
$w $anchor $item]
293 ### Tree structure utilities.
296 ## between $tv $item1 $item2 --
297 # Returns a list of all items between $item1 and $item2,
298 # in preorder traversal order. $item1 and $item2 may be
302 # This routine is O(N) in the size of the tree.
303 # There's probably a way to do this that's O(N) in the number
304 # of items returned, but I'm not clever enough to figure it out.
306 proc ttk
::treeview::between {tv item1 item2
} {
307 variable between
[list]
308 variable selectingBetween
0
309 ScanBetween
$tv $item1 $item2 {}
314 # Recursive worker routine for ttk::treeview::between
316 proc ttk
::treeview::ScanBetween {tv item1 item2 item
} {
318 variable selectingBetween
320 if {$item eq
$item1 ||
$item eq
$item2} {
321 lappend between
$item
322 set selectingBetween
[expr {!$selectingBetween}]
323 } elseif
{$selectingBetween} {
324 lappend between
$item
326 foreach child
[$tv children
$item] {
327 ScanBetween
$tv $item1 $item2 $child
331 ### User interaction utilities.
334 ## OpenItem, CloseItem -- Set the open state of an item, generate event
337 proc ttk
::treeview::OpenItem {w item
} {
339 event generate
$w <<TreeviewOpen
>>
340 $w item
$item -open true
343 proc ttk
::treeview::CloseItem {w item
} {
344 $w item
$item -open false
346 event generate
$w <<TreeviewClose
>>
349 ## Toggle -- toggle opened/closed state of item
351 proc ttk
::treeview::Toggle {w item
} {
352 if {[$w item
$item -open]} {
359 ## ToggleFocus -- toggle opened/closed state of focus item
361 proc ttk
::treeview::ToggleFocus {w
} {
368 ## BrowseTo -- navigate to specified item; set focus and selection
370 proc ttk
::treeview::BrowseTo {w item
} {
373 $w selection set [list $item]