# -*- mode: tcl; indent-tabs-mode: nil -*- # ---------------------------------------------------------------------- # COMPONENT: ChoiceEntry - widget for entering a choice of strings # # This widget represents a entry on a control panel. # It is used to choose one of several mutually-exclusive strings. # ====================================================================== # AUTHOR: Michael McLennan, Purdue University # Copyright (c) 2004-2012 HUBzero Foundation, LLC # # See the file "license.terms" for information on usage and # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. # ====================================================================== package require Itk itcl::class Rappture::ChoiceEntry { inherit itk::Widget itk_option define -state state State "normal" constructor {owner path args} { # defined below } destructor { # defined below } public method value {args} public method label {} public method tooltip {} protected method _rebuild {} protected method _newValue {} protected method _tooltip {} protected method _log {} private variable _owner "" ;# thing managing this control private variable _path "" ;# path in XML to this number private variable _str2val ;# maps option label => option value } itk::usual ChoiceEntry { keep -cursor -font keep -foreground -background keep -textforeground -textbackground keep -selectbackground -selectforeground -selectborderwidth } # ---------------------------------------------------------------------- # CONSTRUCTOR # ---------------------------------------------------------------------- itcl::body Rappture::ChoiceEntry::constructor {owner path args} { if {[catch {$owner isa Rappture::ControlOwner} valid] != 0 || !$valid} { error "bad object \"$owner\": should be Rappture::ControlOwner" } set _owner $owner set _path $path # # Create the widget and configure it properly based on other # hints in the XML. # itk_component add choice { Rappture::Combobox $itk_interior.choice -editable no \ -interactcommand [itcl::code $this _log] } pack $itk_component(choice) -expand yes -fill both bind $itk_component(choice) <> [itcl::code $this _newValue] eval itk_initialize $args _rebuild } # ---------------------------------------------------------------------- # DESTRUCTOR # ---------------------------------------------------------------------- itcl::body Rappture::ChoiceEntry::destructor {} { $_owner notify remove $this } # ---------------------------------------------------------------------- # USAGE: value ?-check? ?? # # Clients use this to query/set the value for this widget. With # no args, it returns the current value for the widget. If the # is specified, it sets the value of the widget and # sends a <> event. If the -check flag is included, the # new value is not actually applied, but just checked for correctness. # ---------------------------------------------------------------------- itcl::body Rappture::ChoiceEntry::value {args} { set onlycheck 0 set i [lsearch -exact $args -check] if {$i >= 0} { set onlycheck 1 set args [lreplace $args $i $i] } if {[llength $args] == 1} { if {$onlycheck} { # someday we may add validation... return } set newval [lindex $args 0] if {[info exists _str2val($newval)]} { # this is a label -- use it directly $itk_component(choice) value $newval set newval $_str2val($newval) ;# report the actual value } else { # this is a value -- search for corresponding label foreach str [array names _str2val] { if {$_str2val($str) eq $newval} { $itk_component(choice) value $str break } } } return $newval } elseif {[llength $args] != 0} { error "wrong # args: should be \"value ?-check? ?newval?\"" } # # Query the value and return. # set str [$itk_component(choice) value] if {[info exists _str2val($str)]} { return $_str2val($str) } return $str } # ---------------------------------------------------------------------- # USAGE: label # # Clients use this to query the label associated with this widget. # Reaches into the XML and pulls out the appropriate label string. # ---------------------------------------------------------------------- itcl::body Rappture::ChoiceEntry::label {} { set label [string trim [$_owner xml get $_path.about.label]] if {"" == $label} { set label "Choice" } return $label } # ---------------------------------------------------------------------- # USAGE: tooltip # # Clients use this to query the tooltip associated with this widget. # Reaches into the XML and pulls out the appropriate description # string. Returns the string that should be used with the # Rappture::Tooltip facility. # ---------------------------------------------------------------------- itcl::body Rappture::ChoiceEntry::tooltip {} { # query tooltip on-demand based on current choice return "@[itcl::code $this _tooltip]" } # ---------------------------------------------------------------------- # USAGE: _rebuild # # Used internally to rebuild the contents of this choice widget # whenever something that it depends on changes. Scans through the # information in the XML spec and builds a list of choices for the # widget. # ---------------------------------------------------------------------- itcl::body Rappture::ChoiceEntry::_rebuild {} { # get rid of any existing choices $itk_component(choice) choices delete 0 end catch {unset _str2val} # # Plug in the various options for the choice. # set max 10 foreach cname [$_owner xml children -type option $_path] { set path [string trim [$_owner xml get $_path.$cname.path]] if {"" != $path} { # look for the input element controlling this path set found 0 foreach cntl [Rappture::entities [$_owner xml object] "input"] { set len [string length $cntl] if {[string equal -length $len $cntl $path]} { set found 1 break } } if {$found} { # # Choice comes from a list of matching entities at # a particular XML path. Use the