source: trunk/gui/scripts/choiceentry.tcl @ 154

Last change on this file since 154 was 115, checked in by mmc, 19 years ago

Updated all copyright notices.

File size: 9.1 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: ChoiceEntry - widget for entering a choice of strings
3#
4#  This widget represents a <choice> entry on a control panel.
5#  It is used to choose one of several mutually-exclusive strings.
6# ======================================================================
7#  AUTHOR:  Michael McLennan, Purdue University
8#  Copyright (c) 2004-2005  Purdue Research Foundation
9#
10#  See the file "license.terms" for information on usage and
11#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12# ======================================================================
13package require Itk
14
15itcl::class Rappture::ChoiceEntry {
16    inherit itk::Widget
17
18    constructor {owner path args} { # defined below }
19    destructor { # defined below }
20
21    public method value {args}
22
23    public method label {}
24    public method tooltip {}
25
26    protected method _rebuild {}
27    protected method _newValue {}
28    protected method _tooltip {}
29
30    private variable _owner ""    ;# thing managing this control
31    private variable _path ""     ;# path in XML to this number
32}
33
34itk::usual ChoiceEntry {
35    keep -cursor -font
36    keep -foreground -background
37    keep -textforeground -textbackground
38    keep -selectbackground -selectforeground -selectborderwidth
39}
40
41# ----------------------------------------------------------------------
42# CONSTRUCTOR
43# ----------------------------------------------------------------------
44itcl::body Rappture::ChoiceEntry::constructor {owner path args} {
45    if {[catch {$owner isa Rappture::ControlOwner} valid] != 0 || !$valid} {
46        error "bad object \"$owner\": should be Rappture::ControlOwner"
47    }
48    set _owner $owner
49    set _path $path
50
51    #
52    # Create the widget and configure it properly based on other
53    # hints in the XML.
54    #
55    itk_component add choice {
56        Rappture::Combobox $itk_interior.choice -editable no
57    }
58    pack $itk_component(choice) -expand yes -fill both
59    bind $itk_component(choice) <<Value>> [itcl::code $this _newValue]
60
61    eval itk_initialize $args
62
63    _rebuild
64}
65
66# ----------------------------------------------------------------------
67# DESTRUCTOR
68# ----------------------------------------------------------------------
69itcl::body Rappture::ChoiceEntry::destructor {} {
70    $_owner notify remove $this
71}
72
73# ----------------------------------------------------------------------
74# USAGE: value ?-check? ?<newval>?
75#
76# Clients use this to query/set the value for this widget.  With
77# no args, it returns the current value for the widget.  If the
78# <newval> is specified, it sets the value of the widget and
79# sends a <<Value>> event.  If the -check flag is included, the
80# new value is not actually applied, but just checked for correctness.
81# ----------------------------------------------------------------------
82itcl::body Rappture::ChoiceEntry::value {args} {
83    set onlycheck 0
84    set i [lsearch -exact $args -check]
85    if {$i >= 0} {
86        set onlycheck 1
87        set args [lreplace $args $i $i]
88    }
89
90    if {[llength $args] == 1} {
91        if {$onlycheck} {
92            # someday we may add validation...
93            return
94        }
95        set newval [lindex $args 0]
96        $itk_component(choice) value $newval
97        return $newval
98
99    } elseif {[llength $args] != 0} {
100        error "wrong # args: should be \"value ?-check? ?newval?\""
101    }
102
103    #
104    # Query the value and return.
105    #
106    return [$itk_component(choice) value]
107}
108
109# ----------------------------------------------------------------------
110# USAGE: label
111#
112# Clients use this to query the label associated with this widget.
113# Reaches into the XML and pulls out the appropriate label string.
114# ----------------------------------------------------------------------
115itcl::body Rappture::ChoiceEntry::label {} {
116    set label [$_owner xml get $_path.about.label]
117    if {"" == $label} {
118        set label "Number"
119    }
120    return $label
121}
122
123# ----------------------------------------------------------------------
124# USAGE: tooltip
125#
126# Clients use this to query the tooltip associated with this widget.
127# Reaches into the XML and pulls out the appropriate description
128# string.  Returns the string that should be used with the
129# Rappture::Tooltip facility.
130# ----------------------------------------------------------------------
131itcl::body Rappture::ChoiceEntry::tooltip {} {
132    # query tooltip on-demand based on current choice
133    return "@[itcl::code $this _tooltip]"
134}
135
136# ----------------------------------------------------------------------
137# USAGE: _rebuild
138#
139# Used internally to rebuild the contents of this choice widget
140# whenever something that it depends on changes.  Scans through the
141# information in the XML spec and builds a list of choices for the
142# widget.
143# ----------------------------------------------------------------------
144itcl::body Rappture::ChoiceEntry::_rebuild {} {
145    # get rid of any existing choices
146    $itk_component(choice) choices delete 0 end
147
148    #
149    # Plug in the various options for the choice.
150    #
151    set max 10
152    foreach cname [$_owner xml children -type option $_path] {
153        set path [string trim [$_owner xml get $_path.$cname.path]]
154        if {"" != $path} {
155            # look for the input element controlling this path
156            set found 0
157            foreach cntl [Rappture::entities [$_owner xml object] "input"] {
158                set len [string length $cntl]
159                if {[string equal -length $len $cntl $path]} {
160                    set found 1
161                    break
162                }
163            }
164            if {$found} {
165                #
166                # Choice comes from a list of matching entities at
167                # a particular XML path.  Use the <label> as a template
168                # for each item on the path.
169                #
170                $_owner notify add $this $cntl [itcl::code $this _rebuild]
171
172                set label [string trim [$_owner xml get $_path.$cname.about.label]]
173                if {"" == $label} {
174                    set label "%type #%n"
175                }
176
177                set ppath [Rappture::LibraryObj::path2list $path]
178                set leading [join [lrange $ppath 0 end-1] .]
179                set tail [lindex $ppath end]
180                set n 1
181                foreach ccname [$_owner xml children $leading] {
182                    if {[string match $tail $ccname]} {
183                        set subst(%n) $n
184                        set subst(%type) [$_owner xml element -as type $leading.$ccname]
185                        set subst(%id) [$_owner xml element -as id $leading.$ccname]
186                        foreach detail [$_owner xml children $leading.$ccname] {
187                            set subst(%$detail) [$_owner xml get $leading.$ccname.$detail]
188                        }
189                        set str [string map [array get subst] $label]
190                        $itk_component(choice) choices insert end \
191                            $leading.$ccname $str
192                        incr n
193                    }
194                }
195                $itk_component(choice) value ""
196            } else {
197                puts "can't find controlling entity for path \"$path\""
198            }
199        } else {
200            #
201            # Choice is an ordinary LABEL.
202            # Add the label as-is into the list of choices.
203            #
204            set str [string trim [$_owner xml get $_path.$cname.about.label]]
205            if {"" != $str} {
206                $itk_component(choice) choices insert end $_path.$cname $str
207                set len [string length $str]
208                if {$len > $max} { set max $len }
209            }
210        }
211    }
212    $itk_component(choice) configure -width $max
213
214    #
215    # Assign the default value to this widget, if there is one.
216    #
217    set str [$_owner xml get $_path.default]
218    if {"" != $str} { $itk_component(choice) value $str }
219}
220
221# ----------------------------------------------------------------------
222# USAGE: _newValue
223#
224# Invoked automatically whenever the value in the choice changes.
225# Sends a <<Value>> event to notify clients of the change.
226# ----------------------------------------------------------------------
227itcl::body Rappture::ChoiceEntry::_newValue {} {
228    event generate $itk_component(hull) <<Value>>
229}
230
231# ----------------------------------------------------------------------
232# USAGE: _tooltip
233#
234# Returns the tooltip for this widget, given the current choice in
235# the selector.  This is normally called by the Rappture::Tooltip
236# facility whenever it is about to pop up a tooltip for this widget.
237# ----------------------------------------------------------------------
238itcl::body Rappture::ChoiceEntry::_tooltip {} {
239    set tip [string trim [$_owner xml get $_path.about.description]]
240
241    # get the description for the current choice, if there is one
242    set str [$itk_component(choice) value]
243    set path [$itk_component(choice) translate $str]
244
245    if {"" != $str} {
246        append tip "\n\n$str:"
247
248        if {$path != ""} {
249            set desc [$_owner xml get $path.description]
250            if {[string length $desc] > 0} {
251                append tip "\n$desc"
252            }
253        }
254    }
255    return $tip
256}
Note: See TracBrowser for help on using the repository browser.