source: trunk/gui/scripts/combobox.tcl @ 1588

Last change on this file since 1588 was 1588, checked in by gah, 14 years ago

don't use: broken xyresult print

File size: 11.3 KB
Line 
1
2# ----------------------------------------------------------------------
3#  COMPONENT: combobox - entry widget with a drop-down list of values
4#
5#  This widget is a typical combobox, an entry widget with a drop-down
6#  list of values.  If the -editable option is turned off, then the
7#  value can be set only from the drop-down list.  Otherwise, the
8#  drop-down is treated as a list of preset choices, but the user can
9#  type anything in the entry area.
10# ======================================================================
11#  AUTHOR:  Michael McLennan, Purdue University
12#  Copyright (c) 2004-2005  Purdue Research Foundation
13#
14#  See the file "license.terms" for information on usage and
15#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16# ======================================================================
17package require Itk
18package require BLT
19
20option add *Combobox.borderWidth 2 widgetDefault
21option add *Combobox.relief sunken widgetDefault
22option add *Combobox.width 10 widgetDefault
23option add *Combobox.editable yes widgetDefault
24option add *Combobox.textBackground white widgetDefault
25option add *Combobox.textForeground black widgetDefault
26option add *Combobox.disabledBackground white widgetDefault
27option add *Combobox.disabledForeground gray widgetDefault
28option add *Combobox.font -*-helvetica-medium-r-normal-*-12-* widgetDefault
29
30itcl::class Rappture::Combobox {
31    inherit itk::Widget
32
33    itk_option define -editable editable Editable ""
34    itk_option define -state state State "normal"
35    itk_option define -width width Width 0
36    itk_option define -disabledbackground disabledBackground DisabledBackground ""
37    itk_option define -disabledforeground disabledForeground DisabledForeground ""
38
39    constructor {args} { # defined below }
40
41    public method value {args}
42    public method translate {value}
43    public method label {value}
44    public method current {}
45    public method choices {option args}
46
47    protected method _entry {option}
48    protected method _dropdown {option}
49    protected method _fixState {}
50
51    blt::bitmap define ComboboxArrow {
52        #define arrow_width 8
53        #define arrow_height 4
54        static unsigned char arrow_bits[] = {
55           0xfe, 0x7c, 0x38, 0x10};
56    }
57    private variable _value2label
58    private variable _label2value
59}
60                                                                               
61itk::usual Combobox {
62    keep -cursor -font
63    keep -foreground -background
64    keep -textforeground -textbackground
65    keep -selectbackground -selectforeground -selectborderwidth
66}
67
68# ----------------------------------------------------------------------
69# CONSTRUCTOR
70# ----------------------------------------------------------------------
71itcl::body Rappture::Combobox::constructor {args} {
72    itk_option add hull.borderwidth hull.relief
73
74    itk_component add button {
75        button $itk_interior.btn -bitmap ComboboxArrow -padx 0 \
76            -borderwidth 1 -relief raised -highlightthickness 0
77    } {
78        usual
79        ignore -highlightthickness -highlightbackground -highlightcolor
80        ignore -borderwidth -relief
81    }
82    pack $itk_component(button) -side right -fill y
83
84    itk_component add entry {
85        entry $itk_interior.entry -borderwidth 0 -relief flat
86    } {
87        usual
88        keep -width
89        rename -highlightbackground -textbackground textBackground Background
90        rename -background -textbackground textBackground Background
91        rename -foreground -textforeground textForeground Foreground
92        rename -disabledbackground -textbackground textBackground Background
93        rename -disabledforeground -textforeground textForeground Foreground
94        ignore -borderwidth -relief
95    }
96    pack $itk_component(entry) -side left -expand yes -fill both
97
98    bind $itk_component(entry) <KeyPress-Return> \
99        [itcl::code $this _entry apply]
100    bind $itk_component(entry) <ButtonPress> \
101        [itcl::code $this _entry click]
102
103    itk_component add ddlist {
104        Rappture::Dropdownlist $itk_component(button).ddlist \
105            -postcommand [itcl::code $this _dropdown post] \
106            -unpostcommand [itcl::code $this _dropdown unpost] \
107    }
108
109    bind $itk_component(ddlist) <<DropdownlistSelect>> \
110        [itcl::code $this _dropdown select]
111
112    $itk_component(button) configure -command \
113        [list $itk_component(ddlist) post $itk_component(hull) left]
114
115    eval itk_initialize $args
116}
117
118# ----------------------------------------------------------------------
119# USAGE: value ?<newval>?
120#
121# Clients use this to query/set the value for this widget.  With
122# no args, it returns the current value for the widget.  If the
123# <newval> is specified, it sets the value of the widget and
124# sends a <<Value>> event.
125# ----------------------------------------------------------------------
126itcl::body Rappture::Combobox::value {args} {
127    if {[llength $args] == 1} {
128        set newval [lindex $args 0]
129
130        $itk_component(entry) configure -state normal
131        $itk_component(entry) delete 0 end
132        $itk_component(entry) insert 0 $newval
133        if {!$itk_option(-editable)} {
134            $itk_component(entry) configure -state disabled
135        }
136
137        after 10 [list catch [list event generate $itk_component(hull) <<Value>>]]
138    } elseif {[llength $args] != 0} {
139        error "wrong # args: should be \"value ?newval?\""
140    }
141    return [$itk_component(entry) get]
142}
143
144# ----------------------------------------------------------------------
145# USAGE: translate <value>
146#
147# Clients use this to translate a value from the entry part of the
148# combobox to one of the underlying values in the combobox.  If the
149# <value> string matches one of the labels for the choices, this
150# method returns the corresponding value.  Otherwise, it returns "".
151# ----------------------------------------------------------------------
152itcl::body Rappture::Combobox::translate {value} {
153    foreach {val label} [choices get -both] {
154        if {$label == $value} {
155            return $val
156        }
157    }
158    return ""
159}
160
161# ----------------------------------------------------------------------
162# USAGE: label <value>
163#
164# Clients use this to translate a value to a label.
165# ----------------------------------------------------------------------
166itcl::body Rappture::Combobox::label { myValue } {
167    foreach {val label} [choices get -both] {
168        if {$myValue == $val} {
169            return $label
170        }
171    }
172    return ""
173}
174
175# ----------------------------------------------------------------------
176# USAGE: getValue <value>
177#
178# Clients use this to translate a value to a label.
179# ----------------------------------------------------------------------
180itcl::body Rappture::Combobox::current {} {
181    return [translate [$itk_component(entry) get]]
182}
183
184# ----------------------------------------------------------------------
185# USAGE: choices insert <pos> ?<value1> <label1> ...?
186# USAGE: choices delete <first> ?<last>?
187# USAGE: choices get ?-value|-label|-both? ?<index>?
188# USAGE: choices index <value>
189#
190# Clients use this to manipulate the list of choices in the drop-down
191# list.  Each choice is represented by a (computer-friendly) value
192# and its corresponding (human-friendly) label.  The "get" option
193# returns information about options on the list, including the value,
194# the label, or both.
195# ----------------------------------------------------------------------
196itcl::body Rappture::Combobox::choices {option args} {
197    eval $itk_component(ddlist) $option $args
198}
199
200# ----------------------------------------------------------------------
201# USAGE: _entry apply
202# USAGE: _entry click
203#
204# Used internally to handle the dropdown list for this combobox.  The
205# post/unpost options are invoked when the list is posted or unposted
206# to manage the relief of the controlling button.  The select option
207# is invoked whenever there is a selection from the list, to assign
208# the value back to the gauge.
209# ----------------------------------------------------------------------
210itcl::body Rappture::Combobox::_entry {option} {
211    switch -- $option {
212        apply {
213            if {$itk_option(-editable) && $itk_option(-state) == "normal"} {
214                event generate $itk_component(hull) <<Value>>
215            }
216        }
217        click {
218            if {!$itk_option(-editable) && $itk_option(-state) == "normal"} {
219                $itk_component(button) configure -relief sunken
220                update idletasks; after 100
221                $itk_component(button) configure -relief raised
222
223                $itk_component(ddlist) post $itk_component(hull) left
224            }
225        }
226        default {
227            error "bad option \"$option\": should be apply, click"
228        }
229    }
230}
231
232# ----------------------------------------------------------------------
233# USAGE: _dropdown post
234# USAGE: _dropdown unpost
235# USAGE: _dropdown select
236#
237# Used internally to handle the dropdown list for this combobox.  The
238# post/unpost options are invoked when the list is posted or unposted
239# to manage the relief of the controlling button.  The select option
240# is invoked whenever there is a selection from the list, to assign
241# the value back to the gauge.
242# ----------------------------------------------------------------------
243itcl::body Rappture::Combobox::_dropdown {option} {
244    switch -- $option {
245        post {
246            set value [$itk_component(entry) get]
247            set i [$itk_component(ddlist) index -label $value]
248            if {$i >= 0} {
249                $itk_component(ddlist) select clear 0 end
250                $itk_component(ddlist) select set $i
251            }
252        }
253        unpost {
254            if {$itk_option(-editable)} {
255                focus $itk_component(entry)
256            }
257        }
258        select {
259            set val [$itk_component(ddlist) current -label]
260            if {"" != $val} {
261                value $val
262            }
263        }
264        default {
265            error "bad option \"$option\": should be post, unpost, select"
266        }
267    }
268}
269
270# ----------------------------------------------------------------------
271# USAGE: _fixState
272#
273# Used internally to fix the widget state when the -editable/-state
274# options change.
275# ----------------------------------------------------------------------
276itcl::body Rappture::Combobox::_fixState {} {
277    if {$itk_option(-state) == "normal"} {
278        $itk_component(button) configure -state normal
279        $itk_component(entry) configure \
280            -background $itk_option(-textbackground) \
281            -foreground $itk_option(-textforeground) \
282            -disabledbackground $itk_option(-textbackground) \
283            -disabledforeground $itk_option(-textforeground)
284    } else {
285        $itk_component(button) configure -state disabled
286        $itk_component(entry) configure \
287            -background $itk_option(-disabledbackground) \
288            -foreground $itk_option(-disabledforeground) \
289            -disabledbackground $itk_option(-disabledbackground) \
290            -disabledforeground $itk_option(-disabledforeground)
291    }
292
293    if {$itk_option(-editable)} {
294        if {$itk_option(-state) == "normal"} {
295            $itk_component(entry) configure -state normal
296        } else {
297            $itk_component(entry) configure -state disabled
298        }
299    } else {
300        $itk_component(entry) configure -state disabled
301    }
302
303    if {!$itk_option(-editable) || $itk_option(-state) != "normal"} {
304        # can't keep focus here -- move it along to the next widget
305        if {[focus] == $itk_component(entry)} {
306            focus [tk_focusNext [focus]]
307        }
308    }
309}
310
311# ----------------------------------------------------------------------
312# CONFIGURATION OPTION: -editable
313# ----------------------------------------------------------------------
314itcl::configbody Rappture::Combobox::editable {
315    if {![string is boolean -strict $itk_option(-editable)]} {
316        error "bad value \"$itk_option(-editable)\": should be boolean"
317    }
318    _fixState
319}
320
321# ----------------------------------------------------------------------
322# CONFIGURATION OPTION: -state
323# ----------------------------------------------------------------------
324itcl::configbody Rappture::Combobox::state {
325    set valid {normal disabled}
326    if {[lsearch -exact $valid $itk_option(-state)] < 0} {
327        error "bad value \"$itk_option(-state)\": should be [join $valid {, }]"
328    }
329    _fixState
330}
Note: See TracBrowser for help on using the repository browser.