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

Last change on this file since 3394 was 3330, checked in by gah, 11 years ago

merge (by hand) with Rappture1.2 branch

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