source: branches/1.4/gui/scripts/periodicelement.tcl @ 5660

Last change on this file since 5660 was 5660, checked in by ldelgass, 9 years ago

Merge r5657:5659 from trunk (whitespace/style)

File size: 11.4 KB
Line 
1# -*- mode: tcl; indent-tabs-mode: nil -*-
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) <Return> \
98        [itcl::code $this _entry apply]
99    bind $itk_component(entry) <KP_Enter> \
100        [itcl::code $this _entry apply]
101    bind $itk_component(entry) <Tab> \
102        [itcl::code $this _entry apply]
103    bind $itk_component(entry) <ButtonPress> \
104        [itcl::code $this _entry click]
105
106    itk_component add ptable {
107        Rappture::PeriodicTable $itk_component(button).ptable \
108            -postcommand [itcl::code $this _dropdown post] \
109            -unpostcommand [itcl::code $this _dropdown unpost] \
110    }
111
112    bind $itk_component(ptable) <<PeriodicTableSelect>> \
113        [itcl::code $this _dropdown select]
114
115    $itk_component(button) configure -command \
116        [list $itk_component(ptable) post $itk_component(hull) left]
117
118    eval itk_initialize $args
119}
120
121# ----------------------------------------------------------------------
122# USAGE: value ?<newval>?
123#
124# Clients use this to query/set the value for this widget.  With
125# no args, it returns the current value for the widget.  If the
126# <newval> is specified, it sets the value of the widget and
127# sends a <<Value>> event.
128# ----------------------------------------------------------------------
129itcl::body Rappture::PeriodicElement::value {args} {
130    if {[llength $args] == 1} {
131        set value [lindex $args 0]
132    } elseif { [llength $args] == 0 }  {
133        set value [$itk_component(entry) get]
134    } else {
135        error "wrong # args: should be \"value ?newval?\""
136    }
137    regsub -all -- "-" $value " " value
138    if { [llength $value] > 1 } {
139        set value [lindex $value 0]
140    }
141    set name [$itk_component(ptable) get -name $value]
142    if { $name == "" } {
143        set name $_lastValue
144        bell
145    }
146    set symbol [$itk_component(ptable) get -symbol $name]
147    if { $name != $_lastValue } {
148        $itk_component(ptable) select $name
149    }
150    $itk_component(entry) configure -state normal
151    $itk_component(entry) delete 0 end
152    #$itk_component(entry) insert 0 "${symbol} - ${name}"
153    $itk_component(entry) insert 0 "${name} - ${symbol}"
154    if {!$itk_option(-editable)} {
155        $itk_component(entry) configure -state disabled
156    }
157    set _lastValue $name
158    if { [llength $args] == 1 } {
159        after 10 \
160            [list catch [list event generate $itk_component(hull) <<Value>>]]
161    }
162    return $name
163}
164
165# ----------------------------------------------------------------------
166# USAGE: element include ?<elem>...?
167# USAGE: element exclude ?<elem>...?
168# USAGE: element get ?-weight|-name|-symbol|-number|-all? ?<elem>?
169#
170# Clients use this to manipulate the list of choices in the drop-down
171# list.  Each choice is represented by a (computer-friendly) value
172# and its corresponding (human-friendly) label.  The "get" option
173# returns information about options on the list, including the value,
174# the label, or both.
175# ----------------------------------------------------------------------
176itcl::body Rappture::PeriodicElement::element {option args} {
177    eval $itk_component(ptable) $option $args
178}
179
180# ----------------------------------------------------------------------
181# USAGE: _entry apply
182# USAGE: _entry click
183#
184# Used internally to handle the dropdown list for this widget.  The
185# post/unpost options are invoked when the list is posted or unposted
186# to manage the relief of the controlling button.  The select option
187# is invoked whenever there is a selection from the list, to assign
188# the value back to the gauge.
189# ----------------------------------------------------------------------
190itcl::body Rappture::PeriodicElement::_entry {option} {
191    switch -- $option {
192        apply {
193            if {$itk_option(-editable) && $itk_option(-state) == "normal"} {
194                event generate $itk_component(hull) <<Value>>
195            }
196        }
197        click {
198            if {!$itk_option(-editable) && $itk_option(-state) == "normal"} {
199                $itk_component(button) configure -relief sunken
200                update idletasks; after 100
201                $itk_component(button) configure -relief raised
202
203                $itk_component(ptable) post $itk_component(hull) left
204            }
205        }
206        default {
207            error "bad option \"$option\": should be apply, click"
208        }
209    }
210}
211
212# ----------------------------------------------------------------------
213# USAGE: _dropdown post
214# USAGE: _dropdown unpost
215# USAGE: _dropdown select
216#
217# Used internally to handle the dropdown table for this widget.  The
218# post/unpost options are invoked when the list is posted or unposted
219# to manage the relief of the controlling button.  The select option
220# is invoked whenever there is a selection from the list, to assign
221# the value back to the gauge.
222# ----------------------------------------------------------------------
223itcl::body Rappture::PeriodicElement::_dropdown {option} {
224    switch -- $option {
225        post {
226            set value [$itk_component(entry) get]
227            if {$value != ""} {
228                $itk_component(ptable) select $value
229            }
230        }
231        unpost {
232            if {$itk_option(-editable)} {
233                focus $itk_component(entry)
234            }
235        }
236        select {
237            set value [$itk_component(ptable) get -name]
238            if {"" != $value} {
239                value $value
240            }
241        }
242        default {
243            error "bad option \"$option\": should be post, unpost, select"
244        }
245    }
246}
247
248# ----------------------------------------------------------------------
249# USAGE: _fixState
250#
251# Used internally to fix the widget state when the -editable/-state
252# options change.
253# ----------------------------------------------------------------------
254itcl::body Rappture::PeriodicElement::_fixState {} {
255    if {$itk_option(-state) == "normal"} {
256        $itk_component(button) configure -state normal
257        $itk_component(entry) configure \
258            -background $itk_option(-textbackground) \
259            -foreground $itk_option(-textforeground) \
260            -disabledbackground $itk_option(-textbackground) \
261            -disabledforeground $itk_option(-textforeground)
262    } else {
263        $itk_component(button) configure -state disabled
264        $itk_component(entry) configure \
265            -background $itk_option(-disabledbackground) \
266            -foreground $itk_option(-disabledforeground) \
267            -disabledbackground $itk_option(-disabledbackground) \
268            -disabledforeground $itk_option(-disabledforeground)
269    }
270
271    if {$itk_option(-editable)} {
272        if {$itk_option(-state) == "normal"} {
273            $itk_component(entry) configure -state normal
274        } else {
275            $itk_component(entry) configure -state disabled
276        }
277    } else {
278        $itk_component(entry) configure -state disabled
279    }
280
281    if {!$itk_option(-editable) || $itk_option(-state) != "normal"} {
282        # can't keep focus here -- move it along to the next widget
283        if {[focus] == $itk_component(entry)} {
284            focus [tk_focusNext [focus]]
285        }
286    }
287}
288
289# ----------------------------------------------------------------------
290# CONFIGURATION OPTION: -editable
291# ----------------------------------------------------------------------
292itcl::configbody Rappture::PeriodicElement::editable {
293    if {![string is boolean -strict $itk_option(-editable)]} {
294        error "bad value \"$itk_option(-editable)\": should be boolean"
295    }
296    _fixState
297}
298
299# ----------------------------------------------------------------------
300# CONFIGURATION OPTION: -state
301# ----------------------------------------------------------------------
302itcl::configbody Rappture::PeriodicElement::state {
303    set valid {normal disabled}
304    if {[lsearch -exact $valid $itk_option(-state)] < 0} {
305        error "bad value \"$itk_option(-state)\": should be [join $valid {, }]"
306    }
307    _fixState
308}
Note: See TracBrowser for help on using the repository browser.