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

Last change on this file since 3534 was 3454, checked in by gah, 12 years ago

add KP_Enter to Return bindings. Implement OK handler in visviewer base class. Fix setting # of isolines while running a sequence of heightmaps/contours

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