source: branches/blt4/gui/scripts/periodicelement.tcl @ 1923

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