-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathexample.tcl
executable file
·151 lines (120 loc) · 4.62 KB
/
example.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# a simple directory viewer
#
# this program uses a multicolumn listbox (mclistbox) to implement
# a simple directory browser
# substitute your favorite method here...
source mclistbox.tcl
package require mclistbox 1.02
catch {namespace import mclistbox::*}
proc showSelection {args} {
puts "selection has changed: $args"
}
proc main {} {
wm title . "Simple Directory Viewer"
# this lets us be reentrant...
eval destroy [winfo children .]
# we want the listbox and two scrollbars to be embedded in a
frame .container -bd 2 -relief sunken
# frame so they look like a single widget
scrollbar .vsb -orient vertical -command [list .listbox yview]
scrollbar .hsb -orient horizontal -command [list .listbox xview]
# we will purposefully make the width less than the sum of the
# columns so that the scrollbars will be functional right off
# the bat.
mclistbox .listbox \
-bd 0 \
-height 10 \
-width 60 \
-columnrelief flat \
-labelanchor w \
-columnborderwidth 0 \
-selectcommand "showSelection" \
-selectmode extended \
-labelborderwidth 2 \
-fillcolumn name \
-xscrollcommand [list .hsb set] \
-yscrollcommand [list .vsb set]
# add the columns we want to see
.listbox column add name -label "Name" -width 40
.listbox column add size -label "Size" -width 12
.listbox column add mod -label "Last Modified" -width 18
# set up bindings to sort the columns.
.listbox label bind name <ButtonPress-1> "sort %W name"
.listbox label bind size <ButtonPress-1> "sort %W size"
.listbox label bind mod <ButtonPress-1> "sort %W mod"
grid .vsb -in .container -row 0 -column 1 -sticky ns
grid .hsb -in .container -row 1 -column 0 -sticky ew
grid .listbox -in .container -row 0 -column 0 -sticky nsew -padx 0 -pady 0
grid columnconfigure .container 0 -weight 1
grid columnconfigure .container 1 -weight 0
grid rowconfigure .container 0 -weight 1
grid rowconfigure .container 1 -weight 0
pack .container -side top -fill both -expand y
# populate the columns with information about the files in the
# current directory
foreach file [lsort [glob *]] {
if {$file == "." || $file == ".."} continue
set size [set mtime ""]
catch {set mtime [clock format [file mtime $file] -format "%x %X"]}
set size [file size $file]
if {$size > 1048576} {
set size [format "%2.2fMB" [expr $size / 1048576.0]]
} elseif {$size > 1024} {
set size [format "%2.2fKB" [expr $size / 1024.0]]
}
.listbox insert end [list $file $size $mtime]
}
# bind the right click to pop up a context-sensitive menu
# we can use the proc ::mclistbox::convert to convert the
# binding substitutions we need. I've included two examples
# to illustrate. Either method should give identical results. The
# first method is slightly more efficient since it calls the
# conversion routine only once. The second method calls the
# procedure once for each of %W, %x and %y.
# bind .listbox <ButtonPress-3> \
# {eval showContextMenu [::mclistbox::convert %W -W -x %x -y %y] %X %Y}
bind .listbox <ButtonPress-3> \
{showContextMenu \
[::mclistbox::convert %W -W] \
[::mclistbox::convert %W -x %x] \
[::mclistbox::convert %W -y %y] \
%X %Y}
}
# x,y are the coordinates relative to the upper-left corner of the
# listbox; rootx,rooty are screen coordinates (for knowing where
# to place the menu). w is the name of the mclistbox widget that was
# clicked on.
proc showContextMenu {w x y rootx rooty} {
catch {destroy .contextMenu}
menu .contextMenu -tearoff false
# ask the widget for what column this is
set column [$w column nearest $x]
set columnLabel [$w column cget $column -label]
.contextMenu configure -title "$columnLabel"
.contextMenu add command \
-label "Sort by $columnLabel" \
-command [list sort $w $column]
.contextMenu add command \
-label "Hide $columnLabel" \
-command [list $w column configure $column -visible false]
.contextMenu add separator
.contextMenu add command \
-label "Show All Hidden Columns" \
-command "showAllColumns $w"
tk_popup .contextMenu $rootx $rooty
}
proc showAllColumns {w} {
foreach column [$w column names] {
$w column configure $column -visible true
}
}
# sort the list based on a particular column
proc sort {w id} {
set data [$w get 0 end]
set index [lsearch -exact [$w column names] $id]
set result [lsort -index $index $data]
$w delete 0 end
# ... and add our sorted data in
eval $w insert end $result
}
main