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

Last change on this file since 1536 was 1342, checked in by gah, 15 years ago

preliminary HQ output from molvisviewer; unexpand tabs; all jpeg generation at 100%

File size: 10.5 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 choices {option args}
44
45    protected method _entry {option}
46    protected method _dropdown {option}
47    protected method _fixState {}
48
49    blt::bitmap define ComboboxArrow {
50        #define arrow_width 8
51        #define arrow_height 4
52        static unsigned char arrow_bits[] = {
53           0xfe, 0x7c, 0x38, 0x10};
54    }
55}
56                                                                               
57itk::usual Combobox {
58    keep -cursor -font
59    keep -foreground -background
60    keep -textforeground -textbackground
61    keep -selectbackground -selectforeground -selectborderwidth
62}
63
64# ----------------------------------------------------------------------
65# CONSTRUCTOR
66# ----------------------------------------------------------------------
67itcl::body Rappture::Combobox::constructor {args} {
68    itk_option add hull.borderwidth hull.relief
69
70    itk_component add button {
71        button $itk_interior.btn -bitmap ComboboxArrow -padx 0 \
72            -borderwidth 1 -relief raised -highlightthickness 0
73    } {
74        usual
75        ignore -highlightthickness -highlightbackground -highlightcolor
76        ignore -borderwidth -relief
77    }
78    pack $itk_component(button) -side right -fill y
79
80    itk_component add entry {
81        entry $itk_interior.entry -borderwidth 0 -relief flat
82    } {
83        usual
84        keep -width
85        rename -highlightbackground -textbackground textBackground Background
86        rename -background -textbackground textBackground Background
87        rename -foreground -textforeground textForeground Foreground
88        rename -disabledbackground -textbackground textBackground Background
89        rename -disabledforeground -textforeground textForeground Foreground
90        ignore -borderwidth -relief
91    }
92    pack $itk_component(entry) -side left -expand yes -fill both
93
94    bind $itk_component(entry) <KeyPress-Return> \
95        [itcl::code $this _entry apply]
96    bind $itk_component(entry) <ButtonPress> \
97        [itcl::code $this _entry click]
98
99    itk_component add ddlist {
100        Rappture::Dropdownlist $itk_component(button).ddlist \
101            -postcommand [itcl::code $this _dropdown post] \
102            -unpostcommand [itcl::code $this _dropdown unpost] \
103    }
104
105    bind $itk_component(ddlist) <<DropdownlistSelect>> \
106        [itcl::code $this _dropdown select]
107
108    $itk_component(button) configure -command \
109        [list $itk_component(ddlist) post $itk_component(hull) left]
110
111    eval itk_initialize $args
112}
113
114# ----------------------------------------------------------------------
115# USAGE: value ?<newval>?
116#
117# Clients use this to query/set the value for this widget.  With
118# no args, it returns the current value for the widget.  If the
119# <newval> is specified, it sets the value of the widget and
120# sends a <<Value>> event.
121# ----------------------------------------------------------------------
122itcl::body Rappture::Combobox::value {args} {
123    if {[llength $args] == 1} {
124        set newval [lindex $args 0]
125
126        $itk_component(entry) configure -state normal
127        $itk_component(entry) delete 0 end
128        $itk_component(entry) insert 0 $newval
129        if {!$itk_option(-editable)} {
130            $itk_component(entry) configure -state disabled
131        }
132
133        after 10 [list catch [list event generate $itk_component(hull) <<Value>>]]
134    } elseif {[llength $args] != 0} {
135        error "wrong # args: should be \"value ?newval?\""
136    }
137    return [$itk_component(entry) get]
138}
139
140# ----------------------------------------------------------------------
141# USAGE: translate <value>
142#
143# Clients use this to translate a value from the entry part of the
144# combobox to one of the underlying values in the combobox.  If the
145# <value> string matches one of the labels for the choices, this
146# method returns the corresponding value.  Otherwise, it returns "".
147# ----------------------------------------------------------------------
148itcl::body Rappture::Combobox::translate {value} {
149    foreach {val label} [choices get -both] {
150        if {$label == $value} {
151            return $val
152        }
153    }
154    return ""
155}
156
157# ----------------------------------------------------------------------
158# USAGE: choices insert <pos> ?<value1> <label1> ...?
159# USAGE: choices delete <first> ?<last>?
160# USAGE: choices get ?-value|-label|-both? ?<index>?
161# USAGE: choices index <value>
162#
163# Clients use this to manipulate the list of choices in the drop-down
164# list.  Each choice is represented by a (computer-friendly) value
165# and its corresponding (human-friendly) label.  The "get" option
166# returns information about options on the list, including the value,
167# the label, or both.
168# ----------------------------------------------------------------------
169itcl::body Rappture::Combobox::choices {option args} {
170    eval $itk_component(ddlist) $option $args
171}
172
173# ----------------------------------------------------------------------
174# USAGE: _entry apply
175# USAGE: _entry click
176#
177# Used internally to handle the dropdown list for this combobox.  The
178# post/unpost options are invoked when the list is posted or unposted
179# to manage the relief of the controlling button.  The select option
180# is invoked whenever there is a selection from the list, to assign
181# the value back to the gauge.
182# ----------------------------------------------------------------------
183itcl::body Rappture::Combobox::_entry {option} {
184    switch -- $option {
185        apply {
186            if {$itk_option(-editable) && $itk_option(-state) == "normal"} {
187                event generate $itk_component(hull) <<Value>>
188            }
189        }
190        click {
191            if {!$itk_option(-editable) && $itk_option(-state) == "normal"} {
192                $itk_component(button) configure -relief sunken
193                update idletasks; after 100
194                $itk_component(button) configure -relief raised
195
196                $itk_component(ddlist) post $itk_component(hull) left
197            }
198        }
199        default {
200            error "bad option \"$option\": should be apply, click"
201        }
202    }
203}
204
205# ----------------------------------------------------------------------
206# USAGE: _dropdown post
207# USAGE: _dropdown unpost
208# USAGE: _dropdown select
209#
210# Used internally to handle the dropdown list for this combobox.  The
211# post/unpost options are invoked when the list is posted or unposted
212# to manage the relief of the controlling button.  The select option
213# is invoked whenever there is a selection from the list, to assign
214# the value back to the gauge.
215# ----------------------------------------------------------------------
216itcl::body Rappture::Combobox::_dropdown {option} {
217    switch -- $option {
218        post {
219            set value [$itk_component(entry) get]
220            set i [$itk_component(ddlist) index -label $value]
221            if {$i >= 0} {
222                $itk_component(ddlist) select clear 0 end
223                $itk_component(ddlist) select set $i
224            }
225        }
226        unpost {
227            if {$itk_option(-editable)} {
228                focus $itk_component(entry)
229            }
230        }
231        select {
232            set val [$itk_component(ddlist) current -label]
233            if {"" != $val} {
234                value $val
235            }
236        }
237        default {
238            error "bad option \"$option\": should be post, unpost, select"
239        }
240    }
241}
242
243# ----------------------------------------------------------------------
244# USAGE: _fixState
245#
246# Used internally to fix the widget state when the -editable/-state
247# options change.
248# ----------------------------------------------------------------------
249itcl::body Rappture::Combobox::_fixState {} {
250    if {$itk_option(-state) == "normal"} {
251        $itk_component(button) configure -state normal
252        $itk_component(entry) configure \
253            -background $itk_option(-textbackground) \
254            -foreground $itk_option(-textforeground) \
255            -disabledbackground $itk_option(-textbackground) \
256            -disabledforeground $itk_option(-textforeground)
257    } else {
258        $itk_component(button) configure -state disabled
259        $itk_component(entry) configure \
260            -background $itk_option(-disabledbackground) \
261            -foreground $itk_option(-disabledforeground) \
262            -disabledbackground $itk_option(-disabledbackground) \
263            -disabledforeground $itk_option(-disabledforeground)
264    }
265
266    if {$itk_option(-editable)} {
267        if {$itk_option(-state) == "normal"} {
268            $itk_component(entry) configure -state normal
269        } else {
270            $itk_component(entry) configure -state disabled
271        }
272    } else {
273        $itk_component(entry) configure -state disabled
274    }
275
276    if {!$itk_option(-editable) || $itk_option(-state) != "normal"} {
277        # can't keep focus here -- move it along to the next widget
278        if {[focus] == $itk_component(entry)} {
279            focus [tk_focusNext [focus]]
280        }
281    }
282}
283
284# ----------------------------------------------------------------------
285# CONFIGURATION OPTION: -editable
286# ----------------------------------------------------------------------
287itcl::configbody Rappture::Combobox::editable {
288    if {![string is boolean -strict $itk_option(-editable)]} {
289        error "bad value \"$itk_option(-editable)\": should be boolean"
290    }
291    _fixState
292}
293
294# ----------------------------------------------------------------------
295# CONFIGURATION OPTION: -state
296# ----------------------------------------------------------------------
297itcl::configbody Rappture::Combobox::state {
298    set valid {normal disabled}
299    if {[lsearch -exact $valid $itk_option(-state)] < 0} {
300        error "bad value \"$itk_option(-state)\": should be [join $valid {, }]"
301    }
302    _fixState
303}
Note: See TracBrowser for help on using the repository browser.