GJS 2012/5/6 The dtree widget is a directory tree.
Methods
Options (Also supports standard ttk::treeview options)
#tkoo/dtree-v0.1.1.tm package provide tkoo::dtree 0.1.1 package require tkoo tkoo::class ::tkoo::dtree { superclass tkoo::ttk_treeview variable widCmd pathname options exists location constructor {wid args} { #check to see if the class already exists my Exists $wid #defaults set pathname $wid set location [pwd] #create the widget if {![winfo exists $wid]} { ttk::treeview $wid -columns [list fullpath expanded] -displaycolumns [list] -selectmode browse } #options #use in list of pairs, list type and image #-images [list drive driveimage directory dirimage file fileimage] #use dict my Opt add -images images Images [list] { my variable widCmd pathname options exists location images if {[llength $value] % 2} { error [msgcat::mc "list must have an even number of elements"] } } #what items to list should be a list of the following, or all #directory files hidden #defaults to all my Opt add -list list List [list directory files hidden] { my variable widCmd pathname options exists location images set list [list] foreach v $value { switch -exact -- $v { hidden {lappend list $v} directory - directories - folder - folders {lappend list directory} file - files {lappend list files} all {set list [list directory files hidden]} default {error [msgcat::mc "bad type \"$v\" for \"-list\": must be a list containing current, directory, drives, files, hidden, or up"]} } } set options(-list,val) [lsort -dictionary -unique $list] } my Opt add -singleexpand singleExpand SingleExpand false { my variable widCmd pathname options exists location images if {![string is boolean -strict $value]} {error [msgcat::mc "expected boolean value but got \"%s\"" $value]} } #bindings bind $wid <<TreeviewOpen>> [namespace code {my BindTreeviewOpen}] bind $wid <*> [namespace code {my BindAsterisk}] bind $wid <Shift-*> [namespace code {my BindShiftAsterisk}] bind $wid <F5> [namespace code {my BindF5}] #default code next $wid {*}$args #configure the widget my configure {*}$args } #methods for bindings method BindTreeviewOpen {} { if {[my Opt get -singleexpand]} { set node [my focus] #get siblings set siblings [lsearch -exact -all -inline -not [my children [my parent $node]] $node] #collapse siblings foreach s $siblings { my Collapse $s } #scroll to show node my see $node } my Populate [my focus] "" 1 } method BindAsterisk {} { if {![my Opt get -singleexpand]} { my Expand [my focus] } } method BindShiftAsterisk {} { if {![my Opt get -singleexpand]} { my Collapse [my focus] } } method BindF5 {} { set node [my focus] my set $node expanded no my Populate $node "" 1 } #method set the top level of the tree widget and return top level directory method location {{directory ""}} { if {$directory ne ""} { if {[file isdirectory $directory]} { my Populate {} $directory 1 set location $directory } } return $location } #method to populate the treeview method Populate {node {dir {}} {expand 0}} { #set the dir variable properly if {$node eq {} && $dir eq ""} { set dir [file normalize ~] } elseif {$node ne {}} { #has the tree already been expanded if {[my set $node expanded]} { if {$expand} { foreach c [my children $node] { my Populate $c } } return } set dir [my set $node fullpath] } else { set dir [file normalize $dir] } #clear children my delete [my children $node] #get options set list [my Opt get -list] #list directories if {"directory" in $list} { set dList [list] if {"hidden" in $list} { catch {lappend dList {*}[glob -directory $dir -nocomplain -types [list d hidden] *]} } catch {lappend dList {*}[glob -directory $dir -nocomplain -types d *]} set dList [lsort -dictionary -unique $dList] foreach d $dList { set id [my ListFile $node directory $d] if {$expand} { my Populate $id } } } if {"files" in $list} { set dList [list] if {"hidden" in $list} { catch {lappend dList {*}[glob -directory $dir -nocomplain -types [list f hidden] *]} } catch {lappend dList {*}[glob -directory $dir -nocomplain -types f *]} set dList [lsort -dictionary -unique $dList] foreach d $dList { my ListFile $node file $d } } #set flag that tells us not to run next time my set $node expanded yes } #method to list a file method ListFile {node type file} { set a [list] set imgs [my Opt get -images] switch -exact -- $type { file { if {[dict exists $imgs file]} { set img [dict get [my Opt get -images] file] lappend a -image $img } } directory - folder { if {[dict exists $imgs directory]} { set img [dict get [my Opt get -images] directory] lappend a -image $img } } volume - drive { if {[dict exists $imgs drive]} { set img [dict get [my Opt get -images] drive] lappend a -image $img } } default {return} } if {[string length file]} { set id [my insert $node end -text [file tail $file] {*}$a] my set $id expanded no my set $id fullpath $file if {$type ne "file"} { my insert $id 0 -text <load> } } return $id } #method to fully expand a node method Expand {node} { set nList $node while {[llength $nList]} { set n [lindex $nList 0] set nList [lrange $nList 1 end] my item $n -open true my Populate $n foreach cn [my children $n] { if {$cn ne ""} { lappend nList $cn } } } } #method to fully collapse a node method Collapse {node} { set nList $node while {[llength $nList]} { set n [lindex $nList 0] set nList [lrange $nList 1 end] my item $n -open false foreach cn [my children $n] { if {$cn ne ""} { lappend nList $cn } } } } #method to get current selection method get {args} { set nodes [my selection] set ret [list] foreach n $nodes { set f [my set $n fullpath] lappend ret $n $f } return $ret } }