source: tol/tolbase/lib/mkWidgets1.3/Combobox.tcl @ 1b5b24e

devel
Last change on this file since 1b5b24e was 32535cc, checked in by Jorge Pérez <josp.jorge@…>, 18 years ago

adding more types to config, added mkWidget1.3

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@16 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 8.0 KB
Line 
1package require Metawidget
2
3# name: Combobox
4# args: args
5# for the first instance defines the image for the arrow button.
6# creates all widgets including the popup list and its toplevel window.
7# the toplevel is withdrawn. defines bindings for keys and mouse clicks.
8# initializes option values by calling the respective option members.
9metawidget create Combobox {
10  # initialize the icon and try to find out if KDE is running
11  if { ! [ourinfo exists pDown] } {
12    our pDown [image create bitmap -data {
13      #define _width 8
14      #define _height 4
15      static char _bits[] = { 0xfe, 0x7c, 0x38, 0x10 };
16    }]
17
18    # on Linux and KDE, the <FocusOut> binding (see below) doesn't work
19    our bKde [expr { $::tcl_platform(os) == "Linux" && ! [catch { exec ps -C kde }] }]
20    our wToplevel [winfo toplevel $this]
21  }
22
23  entry     $this.entr      -bg white -selectborder 0 -selectback black -selectfore white
24  button    $this.entr.arrb -padx 0 -pady 0 -image [our pDown] -command "$this _showList" -cursor arrow
25  toplevel  $this.topl      -border 0
26  scrollbar $this.topl.scrv -command "$this.topl.list yview"
27  listbox   $this.topl.list -bg white -border 0 -yscroll "$this.topl.scrv set" \
28                             -selectborder 0 -selectback {dark blue} -selectfore white
29
30  # the list is in a window without border. the binding is supposed to let
31  # it disappear when some other window is clicked. does not quite work on
32  # KDE: when the window to which the combobox belongs is clicked, the focus
33  # doesn't get out, and the bind script doesn't get triggered. there's a
34  # workaround in _showList and _hideList.
35  wm overrideredirect $this.topl 1
36  wm withdraw $this.topl
37  bind $this.topl <FocusOut> "$this _hideList"
38
39  pack  $this.entr      -fill x -expand 1
40  place $this.entr.arrb -relx 1 -y 0 -relh 1 -anchor ne
41  pack  $this.topl.scrv -side right -fill y
42  pack  $this.topl.list -side left -fill both -expand 1
43
44  bind $this.entr <Up>   "$this see -"
45  bind $this.entr <Down> "$this see +"
46
47  bind $this.topl.list <ButtonRelease-1> "$this _hideList; $this see ?"
48  bind $this.topl.list <Key-Return>      "$this _hideList; $this see ?"
49  bind $this.topl.list <Key-Escape>      "$this _hideList"
50
51  my iIndex -1                         ;# currently displayed
52  my iListH 40                         ;# required height for list in pixels
53  my -command {}                       ;# evaluated on value change
54
55  -lines 5                             ;# set box to 5 lines
56} {} -default entr
57
58# name: _showList
59# args: -
60# displays the toplevel with listbox and scrollbar at the appropriate
61# position. the <FocusOut> binding and the <Escape> key lets it
62# disappear by calling _hideList. the toplevel window is positioned
63# either above or below the entry widget, depending on the space
64# left below of it.
65metawidget proc Combobox _showList {} {
66  set iX [winfo rootx  $this]
67  set iY [winfo rooty  $this]
68  set iW [winfo width  $this]
69  set iH [winfo height $this]
70
71  # show listbox above the entry, if there's not enough space below
72  if { [expr [winfo screenheight $this] - ( $iY + $iH )] >= [my iListH] } {
73    incr iY $iH
74  } else {
75    incr iY -[my iListH]
76  }
77
78  # position window, then show it
79  wm geometry  $this.topl ${iW}x[my iListH]+$iX+$iY
80  wm deiconify $this.topl
81
82  $this.topl.list selection clear 0 end
83  $this.topl.list selection set [my iIndex]
84
85  raise $this.topl
86  focus $this.topl.list
87
88  # workaround for KDE: the listbox doesn't disappear when the application
89  # window is clicked outside of a widget that can receive the focus. it
90  # would even stay on the screen when the app. window is moved. to prevent
91  # this, a <Configure> binding helps. we need to save any previous script
92  # for this binding, though.
93  if { [our bKde] } {
94    our sConfScript [bind [our wToplevel] <Configure>]
95    bind [our wToplevel] <Configure> "$this _hideList"
96  }
97}
98
99# name: _hideList
100# args: -
101# releases the grab. lets the listbox toplevel disappear.
102metawidget proc Combobox _hideList {} {
103  wm withdraw  $this.topl
104  focus        $this.entr
105
106  # restore the original <Configure> bind script again!
107  if { [our bKde] } {
108    bind [our wToplevel] <Configure> [our sConfScript]
109  }
110}
111
112# name: -lines
113# args: iLines: number of listbox lines
114# set the number of lines for the listbox. converts it into pixels by
115# multiplying it with the font height. stores pixel height in iListH.
116metawidget proc Combobox -lines { iLines } {
117  $this.topl.list configure -height $iLines
118  my -lines $iLines
119
120  set iFontH [font metrics [$this.topl.list cget -font] -linespace]
121  my iListH [expr (1+$iFontH)*[my -lines]+2]
122}
123
124# name: -entries
125# args: lEntries: list of entries to set for the Combobox
126# repopulates the list with the given values in lEntries.
127metawidget proc Combobox -entries { args } {
128  if { ! [llength $args] } {
129    $this.topl.list get 0 end
130  } else {
131    $this.topl.list delete 0 end
132    eval $this.topl.list insert 0 [lindex $args 0]
133  }
134}
135
136# name: -state
137# args: sState: state to change the Combobox to
138# applies normal and disabled state simply to the entry widget and the button.
139# for restricted state, the two bindings prevent input to the entry field.
140# only values from the list can be set with cursor up/down.
141metawidget proc Combobox -state { sState } {
142  my -state [mkw.complete $sState {normal disabled restricted}]
143
144  switch [my -state] {
145    normal - disabled {
146      bind $this.entr <Key> {}
147      bind $this.entr <KeyRelease> {}
148      $this.entr config -state $sState
149      $this.entr.arrb config -state $sState
150    }
151    restricted {
152      bind $this.entr <Key> "$this.entr config -state disabled"
153      bind $this.entr <KeyRelease> "$this.entr config -state normal"
154      $this.entr config -state normal
155      $this.entr.arrb config -state normal
156      see 0
157    }
158  }
159}
160
161# name: see
162# args: iIndex: index of the value list to display
163# if index is not given, returns the index of the currently displayed
164# value, or -1 if the value is not part of the value list.
165# if index is + or -, the next resp. previous value in the value list is
166# set. for index ?, the listbox' currently selected element is taken.
167# if index is an integer, the corresponding element from the value list
168# is displayed. any defined command is evaluated, if the value in
169# the entry field has changed.
170metawidget proc Combobox see { {iIndex {}} } {
171  if { $iIndex == {} } {
172    return [lsearch -exact [$this.topl.list get 0 end] [$this.entr get]]
173  }
174
175  set iLen [llength [$this.topl.list get 0 end]]
176  set iOldIndex [my iIndex]
177
178  if { $iIndex == "?" } {
179    my iIndex [$this.topl.list curselection]
180  } elseif { $iIndex == "+" && [my iIndex] < [expr $iLen-1] } {
181    my iIndex [expr [my iIndex]+1]
182  } elseif { $iIndex == "-" && [my iIndex] > 0 } {
183    my iIndex [expr [my iIndex]-1]
184  } elseif { $iIndex >= 0 && $iIndex < $iLen } {
185    my iIndex $iIndex
186  }
187
188  if { $iOldIndex != [my iIndex] } {
189    $this.entr delete 0 end
190    $this.entr insert 0 [$this.topl.list get [my iIndex]]
191    eval [my -command]
192  }
193}
194
195metawidget command Combobox _showList _showList
196metawidget command Combobox _hideList _hideList
197
198metawidget command Combobox see       see
199
200metawidget option  Combobox -lines   -lines
201metawidget option  Combobox -entries -entries -entries
202metawidget option  Combobox -state   -state
203metawidget option  Combobox -command
204
205proc test {} {
206  pack [frame .upfr -border 0] -fill both
207  pack [label .upfr.text -text "Enter values and press Set!"] -anchor w
208  pack [entry .upfr.vals] -side left -fill x -expand 1
209  pack [button .upfr.setb -pady 0 -text Set! -command {.cbox config -entries [.upfr.vals get]} ] -side right
210
211  .upfr.vals insert end {red green blue yellow cyan magenta}
212
213  pack [combobox .cbox -command {.outp config -text [.cbox get]}] -fill x -pady 10
214
215  pack [label .outp -border 1 -relief sunken] -fill x
216  pack [radiobutton .mod1 -text "Normal"     -value 1 -command {.cbox config -state normal}] -fill x -side left
217  pack [radiobutton .mod2 -text "Restricted" -value 2 -command {.cbox config -state restricted}] -fill x -side left
218  pack [radiobutton .mod3 -text "Disabled"   -value 3 -command {.cbox config -state disabled}] -fill x -side left
219}
220
221#test
222
223
Note: See TracBrowser for help on using the repository browser.