1 # multibox.tcl - Multi-column listbox.
2 # Copyright (C) 1997 Cygnus Solutions.
3 # Written by Tom Tromey <tromey@cygnus.com>.
6 # * Should support sashes so user can repartition widget sizes.
7 # * Should support itemcget, itemconfigure.
11 public selectmode browse {
12 _apply_all configure [list -selectmode $selectmode]
17 _apply_all configure [list -height $height]
20 # This is a list of all the listbox widgets we've created. Private
22 protected _listboxen {}
24 # Tricky: take the class bindings for the Listbox widget and turn
25 # them into Multibox bindings that directly run our bindings. That
26 # way any binding on any of our children will automatically work the
28 # FIXME: this loses if any Listbox bindings are added later.
29 # To really fix we need Uhler's change to support megawidgets.
30 foreach seq [bind Listbox] {
31 regsub -all -- %W [bind Listbox $seq] {[winfo parent %W]} sub
32 bind Multibox $seq $sub
35 constructor {config} {
36 # The standard widget-making trick.
37 set class [$this info class]
38 set hull [namespace tail $this]
40 ::rename $this $this-tmp-
41 ::frame $hull -class $class -relief flat -borderwidth 0
42 ::rename $hull $old_name-win-
43 ::rename $this $old_name
45 scrollbar [namespace tail $this].vs -orient vertical
46 bind [namespace tail $this].vs <Destroy> [list $this delete]
48 grid rowconfigure [namespace tail $this] 0 -weight 0
49 grid rowconfigure [namespace tail $this] 1 -weight 1
62 # The first array set sets up the default values, and the second
63 # overwrites with what the user wants.
64 array set opts {-width 20 -fix 0 -title Zardoz}
67 set num [llength $_listboxen]
68 listbox [namespace tail $this].box$num -exportselection 0 -height $height \
69 -selectmode $selectmode -width $opts(-width)
71 [namespace tail $this].box$num configure -yscrollcommand [list [namespace tail $this].vs set]
72 [namespace tail $this].vs configure -command [list $this yview]
74 label [namespace tail $this].label$num -text $opts(-title) -anchor w
76 # No more class bindings.
77 set tag_list [bindtags [namespace tail $this].box$num]
78 set index [lsearch -exact $tag_list Listbox]
79 bindtags [namespace tail $this].box$num [lreplace $tag_list $index $index Multibox]
81 grid [namespace tail $this].label$num -row 0 -column $num -sticky new
82 grid [namespace tail $this].box$num -row 1 -column $num -sticky news
83 if {$opts(-fix)} then {
84 grid columnconfigure [namespace tail $this] $num -weight 0 \
85 -minsize [winfo reqwidth [namespace tail $this].box$num]
87 grid columnconfigure [namespace tail $this] $num -weight 1
90 lappend _listboxen [namespace tail $this].box$num
92 # Move the scrollbar over.
94 grid [namespace tail $this].vs -row 1 -column $num -sticky nsw
95 grid columnconfigure [namespace tail $this] $num -weight 0
98 method configure {config} {}
100 # FIXME: should handle automatically.
101 method cget {option} {
111 error "option $option not supported"
116 # FIXME: this isn't ideal. But we want to support adding bindings
117 # at least. A "bind" method might be better.
118 method get_boxes {} {
124 # Methods that duplicate Listbox interface.
127 method activate index {
128 _apply_all activate [list $index]
132 error "bbox method not supported"
135 method curselection {} {
136 return [_apply_first curselection {}]
139 # FIXME: In itcl 1.5, can't have a method name "delete". Sigh.
140 method delete_hack {args} {
141 _apply_all delete $args
144 # Return some contents. We return each item as a list of the
146 method get {first {last {}}} {
147 if {$last == ""} then {
149 foreach l $_listboxen {
150 lappend r [$l get $first]
154 # We do things this way so that we don't have to specially
155 # handle the index "end".
156 foreach box $_listboxen {
157 set seen(var-$box) [$box get $first $last]
160 # Tricky: we use the array indices as variable names and the
161 # array values as values. This lets us "easily" construct the
164 eval foreach [array get seen] {{
166 foreach box $_listboxen {
167 lappend elt [set var-$box]
176 return [_apply_first index [list $index]]
179 # Insert some items. Each new item is a list of items for all
181 method insert {index args} {
182 if {[llength $args]} then {
186 foreach value $args {
187 foreach columnvalue $value lname $_listboxen {
188 lappend seen($lname) $columnvalue
192 foreach box $_listboxen {
193 eval $box insert $index $seen($box)
199 return [_apply_first nearest [list $y]]
202 method scan {option args} {
203 _apply_all scan $option $args
207 _apply_all see [list $index]
210 method selection {option args} {
211 if {$option == "includes"} then {
212 return [_apply_first selection [concat $option $args]]
214 return [_apply_all selection [concat $option $args]]
219 return [_apply_first size {}]
223 error "xview method not supported"
227 if {! [llength $args]} then {
228 return [_apply_first yview {}]
230 return [_apply_all yview $args]
239 # This applies METHOD to every listbox.
240 method _apply_all {method argList} {
241 foreach l $_listboxen {
242 eval $l $method $argList
246 # This applies METHOD to the first listbox, and returns the result.
247 method _apply_first {method argList} {
248 set l [lindex $_listboxen 0]
249 return [eval $l $method $argList]