source: trunk/gui/scripts/periodicelement.tcl @ 3177

Last change on this file since 3177 was 3177, checked in by mmc, 12 years ago

Updated all of the copyright notices to reference the transfer to
the new HUBzero Foundation, LLC.

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-2012  HUBzero Foundation, LLC
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.