Index: /trunk/configure
===================================================================
--- /trunk/configure	(revision 6371)
+++ /trunk/configure	(revision 6372)
@@ -10225,5 +10225,5 @@
 
 
-ac_config_files="$ac_config_files Makefile packages/Makefile src/Makefile src/core/Makefile src/core2/Makefile src/objects/Makefile src/objects/RpHash.h gui/Makefile gui/apps/Makefile gui/apps/about gui/apps/copy_rappture_examples gui/apps/encodedata gui/apps/rappture gui/apps/rappture-csh.env gui/apps/rappture.env gui/apps/rappture.use gui/apps/rerun gui/apps/simsim gui/apps/xmldiff gui/pkgIndex.tcl gui/scripts/Makefile gui/src/Makefile builder/Makefile builder/pkgIndex.tcl builder/scripts/Makefile tester/Makefile tester/pkgIndex.tcl tester/scripts/Makefile lang/Makefile lang/java/Makefile lang/java/rappture/Makefile lang/perl/Makefile lang/perl/Makefile.PL lang/python/Makefile lang/python/setup.py lang/matlab/Makefile lang/octave/Makefile lang/octave/octave2/Makefile lang/octave/octave3/Makefile lang/R/Makefile lang/ruby/Makefile lang/ruby/build.rb lang/tcl/Makefile lang/tcl/pkgIndex.tcl lang/tcl/scripts/Makefile lang/tcl/src/Makefile lang/tcl/tests/Makefile lib/Makefile examples/3D/Makefile examples/Makefile examples/app-fermi/2.0/Makefile examples/app-fermi/Makefile examples/app-fermi/cee/Makefile examples/app-fermi/fortran/Makefile examples/app-fermi/java/Makefile examples/app-fermi/matlab/Makefile examples/app-fermi/matlab/compiled/Makefile examples/app-fermi/matlab/uncompiled/Makefile examples/app-fermi/octave/octave2/Makefile examples/app-fermi/octave/octave3/Makefile examples/app-fermi/octave/Makefile examples/app-fermi/perl/Makefile examples/app-fermi/python/Makefile examples/app-fermi/ruby/Makefile examples/app-fermi/tcl/Makefile examples/app-fermi/wrapper/Makefile examples/app-fermi/wrapper/cee/Makefile examples/app-fermi/wrapper/perl/Makefile examples/app-fermi/wrapper/python/Makefile examples/app-fermi/wrapper/tcl/Makefile examples/app-fermi/R/Makefile examples/c-example/Makefile examples/canvas/Makefile examples/demo.bash examples/flow/Makefile examples/flow/demo1/Makefile examples/flow/demo2/Makefile examples/flow/demo3/Makefile examples/graph/Makefile examples/mapviewer/Makefile examples/mapviewer/camera/Makefile examples/mapviewer/colorramp/Makefile examples/mapviewer/common/Makefile examples/mapviewer/feature/Makefile examples/mapviewer/gdal/Makefile examples/mapviewer/layers/Makefile examples/mapviewer/ogr/Makefile examples/mapviewer/placard/Makefile examples/mapviewer/select/Makefile examples/mapviewer/tms/Makefile examples/mapviewer/wms/Makefile examples/mapviewer/xyz/Makefile examples/objects/Makefile examples/objects/axis/Makefile examples/objects/curve/Makefile examples/objects/dxWriter/Makefile examples/objects/floatBuffer/Makefile examples/objects/histogram/Makefile examples/objects/library/Makefile examples/objects/number/Makefile examples/objects/path/Makefile examples/objects/plot/Makefile examples/objects/scatter/Makefile examples/objects/string/Makefile examples/objects/tree/Makefile examples/objects/xmlparser/Makefile examples/zoo/Makefile examples/zoo/binary/Makefile examples/zoo/boolean/Makefile examples/zoo/choice/Makefile examples/zoo/curve/Makefile examples/zoo/drawing/Makefile examples/zoo/enable/Makefile examples/zoo/field/Makefile examples/zoo/group/Makefile examples/zoo/histogram/Makefile examples/zoo/image/Makefile examples/zoo/image/docs/Makefile examples/zoo/image/examples/Makefile examples/zoo/integer/Makefile examples/zoo/integer2/Makefile examples/zoo/loader/Makefile examples/zoo/loader/examples/Makefile examples/zoo/log/Makefile examples/zoo/mesh/Makefile examples/zoo/note/Makefile examples/zoo/note/docs/Makefile examples/zoo/number/Makefile examples/zoo/number2/Makefile examples/zoo/parallelepiped/Makefile examples/zoo/periodicelement/Makefile examples/zoo/phase/Makefile examples/zoo/sequence/Makefile examples/zoo/sequence/examples/Makefile examples/zoo/string/Makefile examples/zoo/structure/Makefile examples/zoo/structure/examples/Makefile examples/zoo/table/Makefile video/Makefile video/pkgIndex.tcl oldtest/Makefile oldtest/src/Makefile puq/Makefile puq/puq.sh"
+ac_config_files="$ac_config_files Makefile packages/Makefile src/Makefile src/core/Makefile src/core2/Makefile src/objects/Makefile src/objects/RpHash.h gui/Makefile gui/apps/Makefile gui/apps/about gui/apps/copy_rappture_examples gui/apps/encodedata gui/apps/rappture gui/apps/rappture-csh.env gui/apps/rappture.env gui/apps/rappture.use gui/apps/rerun gui/apps/simsim gui/apps/xmldiff gui/pkgIndex.tcl gui/scripts/Makefile gui/src/Makefile builder/Makefile builder/pkgIndex.tcl builder/scripts/Makefile tester/Makefile tester/pkgIndex.tcl tester/scripts/Makefile lang/Makefile lang/java/Makefile lang/java/rappture/Makefile lang/perl/Makefile lang/perl/Makefile.PL lang/python/Makefile lang/python/setup.py lang/matlab/Makefile lang/octave/Makefile lang/octave/octave2/Makefile lang/octave/octave3/Makefile lang/R/Makefile lang/ruby/Makefile lang/ruby/build.rb lang/tcl/Makefile lang/tcl/pkgIndex.tcl lang/tcl/scripts/Makefile lang/tcl/src/Makefile lang/tcl/tests/Makefile lib/Makefile examples/3D/Makefile examples/Makefile examples/app-fermi/2.0/Makefile examples/app-fermi/Makefile examples/app-fermi/cee/Makefile examples/app-fermi/fortran/Makefile examples/app-fermi/java/Makefile examples/app-fermi/matlab/Makefile examples/app-fermi/matlab/compiled/Makefile examples/app-fermi/matlab/uncompiled/Makefile examples/app-fermi/octave/octave2/Makefile examples/app-fermi/octave/octave3/Makefile examples/app-fermi/octave/Makefile examples/app-fermi/perl/Makefile examples/app-fermi/python/Makefile examples/app-fermi/ruby/Makefile examples/app-fermi/tcl/Makefile examples/app-fermi/wrapper/Makefile examples/app-fermi/wrapper/cee/Makefile examples/app-fermi/wrapper/perl/Makefile examples/app-fermi/wrapper/python/Makefile examples/app-fermi/wrapper/tcl/Makefile examples/app-fermi/R/Makefile examples/c-example/Makefile examples/canvas/Makefile examples/demo.bash examples/flow/Makefile examples/flow/demo1/Makefile examples/flow/demo2/Makefile examples/flow/demo3/Makefile examples/graph/Makefile examples/mapviewer/Makefile examples/mapviewer/camera/Makefile examples/mapviewer/colorramp/Makefile examples/mapviewer/common/Makefile examples/mapviewer/feature/Makefile examples/mapviewer/gdal/Makefile examples/mapviewer/layers/Makefile examples/mapviewer/ogr/Makefile examples/mapviewer/placard/Makefile examples/mapviewer/select/Makefile examples/mapviewer/tms/Makefile examples/mapviewer/wms/Makefile examples/mapviewer/xyz/Makefile examples/objects/Makefile examples/objects/axis/Makefile examples/objects/curve/Makefile examples/objects/dxWriter/Makefile examples/objects/floatBuffer/Makefile examples/objects/histogram/Makefile examples/objects/library/Makefile examples/objects/number/Makefile examples/objects/path/Makefile examples/objects/plot/Makefile examples/objects/scatter/Makefile examples/objects/string/Makefile examples/objects/tree/Makefile examples/objects/xmlparser/Makefile examples/zoo/Makefile examples/zoo/binary/Makefile examples/zoo/boolean/Makefile examples/zoo/choice/Makefile examples/zoo/curve/Makefile examples/zoo/drawing/Makefile examples/zoo/enable/Makefile examples/zoo/field/Makefile examples/zoo/group/Makefile examples/zoo/histogram/Makefile examples/zoo/image/Makefile examples/zoo/image/docs/Makefile examples/zoo/image/examples/Makefile examples/zoo/integer/Makefile examples/zoo/integer2/Makefile examples/zoo/loader/Makefile examples/zoo/loader/examples/Makefile examples/zoo/log/Makefile examples/zoo/mesh/Makefile examples/zoo/multichoice/Makefile examples/zoo/note/Makefile examples/zoo/note/docs/Makefile examples/zoo/number/Makefile examples/zoo/number2/Makefile examples/zoo/parallelepiped/Makefile examples/zoo/periodicelement/Makefile examples/zoo/phase/Makefile examples/zoo/sequence/Makefile examples/zoo/sequence/examples/Makefile examples/zoo/string/Makefile examples/zoo/structure/Makefile examples/zoo/structure/examples/Makefile examples/zoo/table/Makefile video/Makefile video/pkgIndex.tcl oldtest/Makefile oldtest/src/Makefile puq/Makefile puq/puq.sh"
 
 cat >confcache <<\_ACEOF
@@ -11045,4 +11045,5 @@
     "examples/zoo/log/Makefile") CONFIG_FILES="$CONFIG_FILES examples/zoo/log/Makefile" ;;
     "examples/zoo/mesh/Makefile") CONFIG_FILES="$CONFIG_FILES examples/zoo/mesh/Makefile" ;;
+    "examples/zoo/multichoice/Makefile") CONFIG_FILES="$CONFIG_FILES examples/zoo/multichoice/Makefile" ;;
     "examples/zoo/note/Makefile") CONFIG_FILES="$CONFIG_FILES examples/zoo/note/Makefile" ;;
     "examples/zoo/note/docs/Makefile") CONFIG_FILES="$CONFIG_FILES examples/zoo/note/docs/Makefile" ;;
Index: /trunk/configure.in
===================================================================
--- /trunk/configure.in	(revision 6371)
+++ /trunk/configure.in	(revision 6372)
@@ -603,4 +603,5 @@
     examples/zoo/log/Makefile
     examples/zoo/mesh/Makefile
+    examples/zoo/multichoice/Makefile
     examples/zoo/note/Makefile
     examples/zoo/note/docs/Makefile
Index: /trunk/examples/zoo/Makefile.in
===================================================================
--- /trunk/examples/zoo/Makefile.in	(revision 6371)
+++ /trunk/examples/zoo/Makefile.in	(revision 6372)
@@ -30,4 +30,5 @@
 		log \
 		mesh \
+		multichoice \
 		note \
 		number \
Index: /trunk/examples/zoo/multichoice/Makefile.in
===================================================================
--- /trunk/examples/zoo/multichoice/Makefile.in	(revision 6372)
+++ /trunk/examples/zoo/multichoice/Makefile.in	(revision 6372)
@@ -0,0 +1,37 @@
+
+bindir          = @bindir@
+datadir		= @datadir@
+datarootdir	= @datarootdir@
+exec_prefix     = @exec_prefix@
+includedir      = @includedir@
+libdir          = @libdir@
+mandir          = @mandir@
+srcdir		= @srcdir@
+prefix          = @prefix@
+
+INSTALL		= @INSTALL@
+MKDIR_P		= @MKDIR_P@
+VPATH		= $(srcdir)
+RM		= rm -f
+
+FILES		= \
+		$(srcdir)/choice.gif \
+		$(srcdir)/multichoice.tcl \
+		$(srcdir)/tool.xml
+
+destdir		= $(prefix)/examples/zoo/multichoice
+
+.PHONY: all install clean distclean
+
+all: 
+
+install: all
+	$(MKDIR_P) -m 0755 $(destdir)
+	for i in $(FILES) ; do \
+	  $(INSTALL) -m 0444  $$i $(destdir) ; \
+	done
+
+clean:
+
+distclean: clean
+	$(RM) Makefile *~
Index: /trunk/examples/zoo/multichoice/multichoice.tcl
===================================================================
--- /trunk/examples/zoo/multichoice/multichoice.tcl	(revision 6372)
+++ /trunk/examples/zoo/multichoice/multichoice.tcl	(revision 6372)
@@ -0,0 +1,21 @@
+# ----------------------------------------------------------------------
+#  EXAMPLE: Rappture <multichoice> elements
+# ======================================================================
+#  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 Rappture
+
+# open the XML file containing the run parameters
+set driver [Rappture::library [lindex $argv 0]]
+
+$driver put output.multichoice(outs).about.label "Echo of multichoice"
+set multichoice [$driver get input.multichoice(countries).current]
+$driver put output.multichoice(outs).current $multichoice
+
+# save the updated XML describing the run...
+Rappture::result $driver
+exit 0
Index: /trunk/examples/zoo/multichoice/tool.xml
===================================================================
--- /trunk/examples/zoo/multichoice/tool.xml	(revision 6372)
+++ /trunk/examples/zoo/multichoice/tool.xml	(revision 6372)
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<run>
+<tool>
+  <title>multichoice</title>
+  <about>Example of a Rappture &lt;multichoice&gt; object.
+
+MultiChoices are a set of combinable options.
+The description appears in a tooltip when you hover over the choice control with your mouse.
+
+When you click the Simulate button, the input choices will be used to generate the output choices.  An output multichoice is constant, just like a number, boolean, etc.
+  </about>
+  <command>
+    tclsh @tool/multichoice.tcl @driver
+  </command>
+</tool>
+<input>
+  <multichoice id="countries">
+    <about>
+      <label>African Countries</label>
+      <description>Choose the countries to analyze.</description>
+    </about>
+    <option>
+      <about>
+        <label>South Africa</label>
+        <description>South Africa</description>
+      </about>
+      <value>ZAF</value>
+    </option>
+    <option>
+      <about>
+        <label>Zimbabwe</label>
+        <description>Zimbabwe</description>
+      </about>
+      <value>ZWE</value>
+    </option>
+    <option>
+      <about>
+        <label>Swaziland</label>
+        <description>Swaziland</description>
+      </about>
+      <value>SWZ</value>
+    </option>
+    <default>Zimbabwe</default>
+  </multichoice>
+</input>
+</run>
Index: /trunk/gui/scripts/Makefile.in
===================================================================
--- /trunk/gui/scripts/Makefile.in	(revision 6371)
+++ /trunk/gui/scripts/Makefile.in	(revision 6372)
@@ -83,4 +83,5 @@
 		$(srcdir)/meshresult.tcl \
 		$(srcdir)/molvisviewer.tcl \
+		$(srcdir)/multichoiceentry.tcl \
 		$(srcdir)/nanovisviewer.tcl \
 		$(srcdir)/note.tcl \
Index: /trunk/gui/scripts/combobox.tcl
===================================================================
--- /trunk/gui/scripts/combobox.tcl	(revision 6371)
+++ /trunk/gui/scripts/combobox.tcl	(revision 6372)
@@ -175,7 +175,9 @@
 
 # ----------------------------------------------------------------------
-# USAGE: getValue <value>
-#
-# Clients use this to translate a value to a label.
+# USAGE: current
+#
+# Clients use this to retrieve a label from the entry widget and return
+# its value, if one exists. If no value exists for the label, then the
+# label is returned.
 # ----------------------------------------------------------------------
 itcl::body Rappture::Combobox::current {} {
Index: /trunk/gui/scripts/combochecks.tcl
===================================================================
--- /trunk/gui/scripts/combochecks.tcl	(revision 6371)
+++ /trunk/gui/scripts/combochecks.tcl	(revision 6372)
@@ -19,4 +19,5 @@
 option add *Combochecks.relief sunken widgetDefault
 option add *Combochecks.width 10 widgetDefault
+option add *Combochecks.editable yes widgetDefault
 option add *Combochecks.textBackground white widgetDefault
 option add *Combochecks.textForeground black widgetDefault
@@ -28,17 +29,20 @@
     inherit itk::Widget
 
+    itk_option define -editable editable Editable ""
     itk_option define -state state State "normal"
     itk_option define -width width Width 0
     itk_option define -disabledbackground disabledBackground DisabledBackground ""
     itk_option define -disabledforeground disabledForeground DisabledForeground ""
+    itk_option define -interactcommand interactCommand InteractCommand ""
 
     constructor {args} { # defined below }
 
     public method value {args}
-    public method current {}
+    public method translate {value {defValue ""}}
+    public method label {value}
     public method choices {option args}
 
     protected method _entry {option}
-    protected method _fixDisplay {}
+    protected method _dropdown {option}
     protected method _fixState {}
 
@@ -57,4 +61,5 @@
     keep -foreground -background
     keep -textforeground -textbackground
+    keep -selectbackground -selectforeground -selectborderwidth
 }
 
@@ -95,8 +100,11 @@
 
     itk_component add ddlist {
-        Rappture::Dropdownchecks $itk_component(button).ddlist
-    }
+        Rappture::Dropdownchecks $itk_component(button).ddlist \
+            -postcommand [itcl::code $this _dropdown post] \
+            -unpostcommand [itcl::code $this _dropdown unpost] \
+    }
+
     bind $itk_component(ddlist) <<DropdownchecksSelect>> \
-        [itcl::code $this _fixDisplay]
+        [itcl::code $this _dropdown select]
 
     $itk_component(button) configure -command \
@@ -115,33 +123,59 @@
 # ----------------------------------------------------------------------
 itcl::body Rappture::Combochecks::value {args} {
-    switch -- [llength $args] {
-        0 {
-            # return a list of checked optons
-            set max [$itk_component(ddlist) size]
-            set rlist ""
-            foreach val [$itk_component(ddlist) get -value] {
-                if {[$itk_component(ddlist) state $val]} {
-                    lappend rlist $val
-                }
-            }
-            return $rlist
-        }
-        1 {
-            set newval [lindex $args 0]
-
-            $itk_component(ddlist) reset
-            foreach part $newval {
-                $itk_component(ddlist) state $part 1
-            }
-            _fixDisplay
-
-            after 10 [list catch \
-                [list event generate $itk_component(hull) <<Value>>]]
-
-        }
-        default {
-            error "wrong # args: should be \"value ?newval?\""
-        }
-    }
+    if {[llength $args] == 1} {
+        set newval [lindex $args 0]
+
+        # FIXME: not sure if I need to update the ddlist just in case
+        # user calls value() without manipulating the ddlist
+        $itk_component(ddlist) reset
+        foreach part $newval {
+            set part [translate $part]
+            $itk_component(ddlist) state $part 1
+        }
+
+        $itk_component(entry) configure -state normal
+        $itk_component(entry) delete 0 end
+        $itk_component(entry) insert end [join $newval {, }]
+        if {!$itk_option(-editable)} {
+            $itk_component(entry) configure -state disabled
+        }
+
+        after 10 [list catch \
+            [list event generate $itk_component(hull) <<Value>>]]
+    } elseif {[llength $args] != 0} {
+        error "wrong # args: should be \"value ?newval?\""
+    }
+    return [$itk_component(entry) get]
+}
+
+# ----------------------------------------------------------------------
+# USAGE: translate <value>
+#
+# Clients use this to translate a value from the entry part of the
+# combobox to one of the underlying values in the combobox.  If the
+# <value> string matches one of the labels for the choices, this
+# method returns the corresponding value.  Otherwise, it returns "".
+# ----------------------------------------------------------------------
+itcl::body Rappture::Combochecks::translate {value {defValue ""}} {
+    foreach {val label} [choices get -both] {
+        if {$label eq $value} {
+            return $val
+        }
+    }
+    return $defValue
+}
+
+# ----------------------------------------------------------------------
+# USAGE: label <value>
+#
+# Clients use this to translate a value to a label.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Combochecks::label { myValue } {
+    foreach {val label} [choices get -both] {
+        if {$myValue == $val} {
+            return $label
+        }
+    }
+    return ""
 }
 
@@ -167,44 +201,78 @@
 # USAGE: _entry click
 #
+# Used internally to handle the entry widget for this combobox.  The
+# click option is invoked when the user click on the entry widget and
+# performs a post operation on the dropdown list. The apply option
+# is invoked when the user presses the Return key to set the value of
+# the entry widget or selects a value. It generates a Value signal.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Combochecks::_entry {option} {
+    switch -- $option {
+        apply {
+            if {$itk_option(-editable) && $itk_option(-state) == "normal"} {
+                event generate $itk_component(hull) <<Value>>
+                if {[string length $itk_option(-interactcommand)] > 0} {
+                    uplevel #0 $itk_option(-interactcommand)
+                }
+            }
+        }
+        click {
+            if {!$itk_option(-editable) && $itk_option(-state) == "normal"} {
+                $itk_component(button) configure -relief sunken
+                update idletasks; after 100
+                $itk_component(button) configure -relief raised
+
+                $itk_component(ddlist) post $itk_component(hull) left
+            }
+        }
+        default {
+            error "bad option \"$option\": should be apply, click"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: _dropdown post
+# USAGE: _dropdown unpost
+# USAGE: _dropdown select
+#
 # Used internally to handle the dropdown list for this combobox.  The
 # post/unpost options are invoked when the list is posted or unposted
 # to manage the relief of the controlling button.  The select option
 # is invoked whenever there is a selection from the list, to assign
-# the value back to the gauge.
-# ----------------------------------------------------------------------
-itcl::body Rappture::Combochecks::_entry {option} {
+# the value back to the entry.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Combochecks::_dropdown {option} {
     switch -- $option {
-        apply {
-            if {$itk_option(-state) == "normal"} {
-                event generate $itk_component(hull) <<Value>>
-            }
-        }
-        click {
-            if {$itk_option(-state) == "normal"} {
-                $itk_component(button) configure -relief sunken
-                update idletasks; after 100
-                $itk_component(button) configure -relief raised
-
-                $itk_component(ddlist) post $itk_component(hull) left
+        post {
+#            set value [$itk_component(entry) get]
+#            set i [$itk_component(ddlist) index -label $value]
+#            if {$i >= 0} {
+#                $itk_component(ddlist) select clear 0 end
+#                $itk_component(ddlist) select set $i
+#            }
+        }
+        unpost {
+            if {$itk_option(-editable)} {
+                focus $itk_component(entry)
+            }
+        }
+        select {
+            set newval [$itk_component(ddlist) current -label]
+            set val [$itk_component(entry) get]
+            if {$newval ne "" && $newval ne $val} {
+                value $newval
+                if {[string length $itk_option(-interactcommand)] > 0} {
+                    uplevel #0 $itk_option(-interactcommand)
+                }
+            }
+            if {$newval eq ""} {
+                value $val
             }
         }
         default {
-            error "bad option \"$option\": should be apply, click"
-        }
-    }
-}
-
-# ----------------------------------------------------------------------
-# USAGE: _fixDisplay
-#
-# Used internally to handle the dropdown list for this combobox.
-# Invoked whenever there is a selection from the list, to assign
-# the value back to the entry.
-# ----------------------------------------------------------------------
-itcl::body Rappture::Combochecks::_fixDisplay {} {
-    $itk_component(entry) configure -state normal
-    $itk_component(entry) delete 0 end
-    $itk_component(entry) insert end [join [value] {, }]
-    $itk_component(entry) configure -state disabled
+            error "bad option \"$option\": should be post, unpost, select"
+        }
+    }
 }
 
@@ -212,6 +280,6 @@
 # USAGE: _fixState
 #
-# Used internally to fix the widget state when the -state option
-# changes.
+# Used internally to fix the widget state when the -editable/-state
+# options change.
 # ----------------------------------------------------------------------
 itcl::body Rappture::Combochecks::_fixState {} {
@@ -232,5 +300,15 @@
     }
 
-    if {$itk_option(-state) != "normal"} {
+    if {$itk_option(-editable)} {
+        if {$itk_option(-state) == "normal"} {
+            $itk_component(entry) configure -state normal
+        } else {
+            $itk_component(entry) configure -state disabled
+        }
+    } else {
+        $itk_component(entry) configure -state disabled
+    }
+
+    if {!$itk_option(-editable) || $itk_option(-state) != "normal"} {
         # can't keep focus here -- move it along to the next widget
         if {[focus] == $itk_component(entry)} {
@@ -238,4 +316,14 @@
         }
     }
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTION: -editable
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::Combochecks::editable {
+    if {![string is boolean -strict $itk_option(-editable)]} {
+        error "bad value \"$itk_option(-editable)\": should be boolean"
+    }
+    _fixState
 }
 
Index: /trunk/gui/scripts/controlOwner.tcl
===================================================================
--- /trunk/gui/scripts/controlOwner.tcl	(revision 6371)
+++ /trunk/gui/scripts/controlOwner.tcl	(revision 6372)
@@ -67,4 +67,5 @@
         integer current
         loader current
+        multichoice current
         note contents
         number current
Index: /trunk/gui/scripts/controls.tcl
===================================================================
--- /trunk/gui/scripts/controls.tcl	(revision 6371)
+++ /trunk/gui/scripts/controls.tcl	(revision 6372)
@@ -154,4 +154,8 @@
         loader {
             Rappture::Loader $w $_owner $path -tool [$_owner tool]
+            bind $w <<Value>> [itcl::code $this _controlChanged $name]
+        }
+        multichoice {
+            Rappture::MultiChoiceEntry $w $_owner $path
             bind $w <<Value>> [itcl::code $this _controlChanged $name]
         }
Index: /trunk/gui/scripts/dropdownchecks.tcl
===================================================================
--- /trunk/gui/scripts/dropdownchecks.tcl	(revision 6371)
+++ /trunk/gui/scripts/dropdownchecks.tcl	(revision 6372)
@@ -38,4 +38,5 @@
     public method state {value {newval ""}}
     public method reset {}
+    public method current {{what -value}}
 
     private variable _dispatcher "" ;# dispatcher for !events
@@ -280,4 +281,31 @@
         set _states($val) 0
     }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: current ?-value|-label|-both?
+#
+# Clients use this to query the current selections from the listbox/canvas.
+# Returns a list of values, labels, or list of lists of both, according
+# to the option.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Dropdownchecks::current {{what -value}} {
+    set rlist ""
+    set l  [llength $_values]
+    for {set i 0} {$i < $l} {incr i} {
+        set val [lindex $_values $i]
+        if {$_states($val)} {
+            switch -- $what {
+                -value { lappend rlist [lindex $_values $i] }
+                -label { lappend rlist [lindex $_labels $i] }
+                -both  { lappend rlist [list [lindex $_values $i] \
+                                             [lindex $_labels $i]] }
+                default {
+                    error "bad option \"$what\": should be -value, -label, -both"
+                }
+            }
+        }
+    }
+    return $rlist
 }
 
Index: /trunk/gui/scripts/multichoiceentry.tcl
===================================================================
--- /trunk/gui/scripts/multichoiceentry.tcl	(revision 6372)
+++ /trunk/gui/scripts/multichoiceentry.tcl	(revision 6372)
@@ -0,0 +1,327 @@
+# -*- mode: tcl; indent-tabs-mode: nil -*-
+# ----------------------------------------------------------------------
+#  COMPONENT: MultiChoiceEntry - widget for entering a choice of strings
+#
+#  This widget represents a <multichoice> 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::MultiChoiceEntry {
+    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 MultiChoiceEntry {
+    keep -cursor -font
+    keep -foreground -background
+    keep -textforeground -textbackground
+    keep -selectbackground -selectforeground -selectborderwidth
+}
+
+# ----------------------------------------------------------------------
+# CONSTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::MultiChoiceEntry::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::Combochecks $itk_interior.choice -editable no \
+            -interactcommand [itcl::code $this _log]
+    }
+    pack $itk_component(choice) -expand yes -fill both
+    bind $itk_component(choice) <<Value>> [itcl::code $this _newValue]
+
+    eval itk_initialize $args
+
+    _rebuild
+}
+
+# ----------------------------------------------------------------------
+# DESTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::MultiChoiceEntry::destructor {} {
+    $_owner notify remove $this
+}
+
+# ----------------------------------------------------------------------
+# USAGE: value ?-check? ?<newval>?
+#
+# Clients use this to query/set the value for this widget.  With
+# no args, it returns the current value for the widget.  If the
+# <newval> is specified, it sets the value of the widget and
+# sends a <<Value>> event.  If the -check flag is included, the
+# new value is not actually applied, but just checked for correctness.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MultiChoiceEntry::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 result ""
+    set str [$itk_component(choice) value]
+    regsub -all {, } $str {,} str
+    foreach lbl [split $str {,}] {
+        if {[info exists _str2val($lbl)]} {
+            set lbl $_str2val($lbl)
+        }
+        lappend result $lbl
+    }
+    return [join $result {, }]
+}
+
+# ----------------------------------------------------------------------
+# 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::MultiChoiceEntry::label {} {
+    set label [string trim [$_owner xml get $_path.about.label]]
+    if {"" == $label} {
+        set label "MultiChoice"
+    }
+    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::MultiChoiceEntry::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::MultiChoiceEntry::_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 <label> as a template
+                # for each item on the path.
+                #
+                $_owner notify add $this $cntl [itcl::code $this _rebuild]
+
+                set label \
+                    [string trim [$_owner xml get $_path.$cname.about.label]]
+                if {"" == $label} {
+                    set label "%type #%n"
+                }
+
+                set ppath [Rappture::LibraryObj::path2list $path]
+                set leading [join [lrange $ppath 0 end-1] .]
+                set tail [lindex $ppath end]
+                set n 1
+                foreach ccname [$_owner xml children $leading] {
+                    if {[string match $tail $ccname]} {
+                        set subst(%n) $n
+                        set subst(%type) [$_owner xml element -as type $leading.$ccname]
+                        set subst(%id) [$_owner xml element -as id $leading.$ccname]
+                        foreach detail [$_owner xml children $leading.$ccname] {
+                            set subst(%$detail) \
+                                [$_owner xml get $leading.$ccname.$detail]
+                        }
+                        set str [string map [array get subst] $label]
+                        $itk_component(choice) choices insert end \
+                            $leading.$ccname $str
+                        incr n
+                    }
+                }
+                $itk_component(choice) value ""
+            } else {
+                puts "can't find controlling entity for path \"$path\""
+            }
+        } else {
+            #
+            # Choice is an ordinary LABEL.
+            # Add the label as-is into the list of choices.
+            #
+            set val [string trim [$_owner xml get $_path.$cname.value]]
+            set str [string trim [$_owner xml get $_path.$cname.about.label]]
+            if {"" == $val} {
+                set val $str
+            }
+            if {"" != $str} {
+                set _str2val($str) $val
+                $itk_component(choice) choices insert end $_path.$cname $str
+                set len [string length $str]
+                if {$len > $max} { set max $len }
+            }
+        }
+    }
+    $itk_component(choice) configure -width $max
+
+    #
+    # Assign the default value to this widget, if there is one.
+    #
+    set defvallist [$_owner xml get $_path.default]
+    if {"" != $defvallist} {
+        set v {}
+        foreach defval [split $defvallist {,}] {
+            set defval [string trim $defval]
+            if {[info exists _str2val($defval)]} {
+                lappend v $defval
+            } else {
+                foreach str [array names _str2val] {
+                    if {$_str2val($str) == $defval} {
+                        lappend v $str
+                        break
+                    }
+                }
+            }
+        }
+        if {[llength $v] > 0} {
+            $itk_component(choice) value $v
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: _newValue
+#
+# Invoked automatically whenever the value in the choice changes.
+# Sends a <<Value>> event to notify clients of the change.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MultiChoiceEntry::_newValue {} {
+    event generate $itk_component(hull) <<Value>>
+}
+
+# ----------------------------------------------------------------------
+# USAGE: _tooltip
+#
+# Returns the tooltip for this widget, given the current choice in
+# the selector.  This is normally called by the Rappture::Tooltip
+# facility whenever it is about to pop up a tooltip for this widget.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MultiChoiceEntry::_tooltip {} {
+    set tip [string trim [$_owner xml get $_path.about.description]]
+
+    # get the description for the current choice, if there is one
+    set str [$itk_component(choice) value]
+    set path [$itk_component(choice) translate $str]
+    set desc ""
+    if {$path != ""} {
+        set desc [string trim [$_owner xml get $path.about.description]]
+    }
+
+    if {[string length $str] > 0 && [string length $desc] > 0} {
+        append tip "\n\n$str:\n$desc"
+    }
+    return $tip
+}
+
+# ----------------------------------------------------------------------
+# USAGE: _log
+#
+# Used internally to send info to the logging mechanism.  Calls the
+# Rappture::Logger mechanism to log the change to this input.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MultiChoiceEntry::_log {} {
+    Rappture::Logger::log input $_path [$itk_component(choice) value]
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTION: -state
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::MultiChoiceEntry::state {
+    set valid {normal disabled}
+    if {[lsearch -exact $valid $itk_option(-state)] < 0} {
+        error "bad value \"$itk_option(-state)\": should be [join $valid {, }]"
+    }
+    $itk_component(choice) configure -state $itk_option(-state)
+}
Index: /trunk/gui/scripts/page.tcl
===================================================================
--- /trunk/gui/scripts/page.tcl	(revision 6371)
+++ /trunk/gui/scripts/page.tcl	(revision 6372)
@@ -176,5 +176,5 @@
                 set type [$obj element -as type]
                 switch -- $type {
-                    number - integer - boolean - choice {
+                    number - integer - boolean - choice - multichoice {
                         Rappture::ResultViewer $w -width 0 -height 0
                         pack $w -fill x -padx 4 -pady 4
Index: /trunk/gui/scripts/resultviewer.tcl
===================================================================
--- /trunk/gui/scripts/resultviewer.tcl	(revision 6371)
+++ /trunk/gui/scripts/resultviewer.tcl	(revision 6372)
@@ -26,5 +26,5 @@
 
     constructor {args} {
-	# defined below
+        # defined below
     }
     destructor {
@@ -395,5 +395,5 @@
                     }
                 }
-                boolean - choice {
+                boolean - choice - multichoice {
                     set mode "value"
                     if {![info exists _mode2widget($mode)]} {
@@ -549,5 +549,5 @@
             set dobj [$xmlobj element -as object $path]
         }
-        number - integer - boolean - choice {
+        number - integer - boolean - choice - multichoice {
             set dobj [$xmlobj element -as object $path]
         }
Index: /trunk/lang/tcl/scripts/Makefile.in
===================================================================
--- /trunk/lang/tcl/scripts/Makefile.in	(revision 6371)
+++ /trunk/lang/tcl/scripts/Makefile.in	(revision 6372)
@@ -57,4 +57,5 @@
 		image \
 		integer \
+		multichoice \
 		note \
 		number \
Index: /trunk/lang/tcl/scripts/objects/multichoice/multichoice.rp
===================================================================
--- /trunk/lang/tcl/scripts/objects/multichoice/multichoice.rp	(revision 6372)
+++ /trunk/lang/tcl/scripts/objects/multichoice/multichoice.rp	(revision 6372)
@@ -0,0 +1,81 @@
+# ----------------------------------------------------------------------
+#  RAPPTURE OBJECT: multichoice
+#
+#  A set of non mutually-exclusive choices, as in Model A and/or Model B.
+#  Usually used as an input to a simulation.
+#
+# ======================================================================
+#  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.
+# ======================================================================
+
+object multichoice -extends base {
+    palettes "Inputs"
+
+    help http://rappture.org/wiki/rp_xml_ele_multichoice
+
+    attr options -title "Options" -type choices -path option -tooltip "List of choices that will appear on the drop-down menu in your program."
+
+    attr default -title "Default Value" -type string -path default -only input -tooltip "Sets the value that this input has when the program first starts.  This value is used by default unless the user explicitly changes it."
+
+    check options {
+        if {[llength $attr(options)] < 2} {
+            return [list warning "Should have at least two options for this multichoice, or it's not really a choice at all."]
+        }
+    }
+
+    check default {
+        if {[llength $attr(options)] > 0} {
+            if {[string length [string trim $attr(default)]] == 0} {
+                return [list error "Must have a default value for this multichoice."]
+            }
+
+            # make sure that the default is really a choice
+            set found 0
+            set alldefvals [split $attr(default) ","]
+            foreach defval $alldefvals {
+                set defval [string trim $defval]
+                foreach rec $attr(options) {
+                    set label [string trim [lindex $rec 0]]
+                    set value [string trim [lindex $rec 1]]
+                    if {$defval eq $label || $defval eq $value} {
+                        incr found
+                        break
+                    }
+                }
+            }
+            if {$found != [llength $alldefvals]} {
+                return [list error "Default value must be labels or values from one of the current choices."]
+            }
+        }
+    }
+
+    storage {
+        private variable _val   ;# current choice
+    }
+
+    import xml {xmlobj path} {
+        attr import $xmlobj $path
+        import_string [$xmlobj get $path.current]
+    }
+
+    export xml {xmlobj path} {
+        $xmlobj put $path $_val
+    }
+
+    import string {val} {
+        set _val $val
+    }
+
+    export string {var} {
+        upvar $var v
+        set v $_val
+    }
+
+    compare {
+        return [string compare $_val $_val2]
+    }
+}
