Index: branches/1.3/gui/scripts/Makefile.in
===================================================================
--- branches/1.3/gui/scripts/Makefile.in	(revision 4511)
+++ branches/1.3/gui/scripts/Makefile.in	(revision 4512)
@@ -33,4 +33,5 @@
 		$(srcdir)/controlOwner.tcl \
 		$(srcdir)/controls.tcl \
+		$(srcdir)/coverflow.tcl \
 		$(srcdir)/curve.tcl \
 		$(srcdir)/datatable.tcl \
@@ -51,4 +52,6 @@
 		$(srcdir)/field.tcl \
 		$(srcdir)/fieldresult.tcl \
+		$(srcdir)/filechoiceentry.tcl \
+		$(srcdir)/filelistentry.tcl \
 		$(srcdir)/filexfer.tcl \
 		$(srcdir)/flowdial.tcl \
@@ -69,8 +72,11 @@
 		$(srcdir)/integerentry.tcl \
 		$(srcdir)/isomarker.tcl \
+		$(srcdir)/transferfunctioneditor.tcl \
 		$(srcdir)/loader.tcl \
 		$(srcdir)/logger.tcl \
 		$(srcdir)/main.tcl \
 		$(srcdir)/mainwin.tcl \
+		$(srcdir)/map.tcl \
+		$(srcdir)/mapviewer.tcl \
 		$(srcdir)/mesh.tcl \
 		$(srcdir)/meshresult.tcl \
@@ -92,5 +98,4 @@
 		$(srcdir)/pushbutton.tcl \
 		$(srcdir)/radiodial.tcl \
-		$(srcdir)/resources.tcl \
 		$(srcdir)/resultset.tcl \
 		$(srcdir)/resultselector.tcl \
@@ -111,6 +116,6 @@
 		$(srcdir)/tool.tcl \
 		$(srcdir)/tooltip.tcl \
-		$(srcdir)/transferfunctioneditor.tcl \
 		$(srcdir)/tuples.tcl \
+		$(srcdir)/tweener.tcl \
 		$(srcdir)/unirect2d.tcl \
 		$(srcdir)/unirect3d.tcl \
@@ -137,4 +142,5 @@
 		$(srcdir)/vtkvolumeviewer.tcl \
 		$(srcdir)/vtkheightmapviewer.tcl \
+		$(srcdir)/vtkimageviewer.tcl \
 		$(srcdir)/xylegend.tcl \
 		$(srcdir)/xyprint.tcl \
Index: branches/1.3/gui/scripts/analyzer.tcl
===================================================================
--- branches/1.3/gui/scripts/analyzer.tcl	(revision 4511)
+++ branches/1.3/gui/scripts/analyzer.tcl	(revision 4512)
@@ -800,8 +800,11 @@
                         _autoLabel $xmlobj output.$item "Integer" counters
                     }
+                    mesh* {
+                        _autoLabel $xmlobj output.$item "Mesh" counters
+                    }
                     string* {
                         _autoLabel $xmlobj output.$item "String" counters
                     }
-                    histogram* - curve* - field* {
+                    histogram* - curve* - field* - map* {
                         _autoLabel $xmlobj output.$item "Plot" counters
                     }
Index: branches/1.3/gui/scripts/bugreport.tcl
===================================================================
--- branches/1.3/gui/scripts/bugreport.tcl	(revision 4511)
+++ branches/1.3/gui/scripts/bugreport.tcl	(revision 4512)
@@ -86,11 +86,15 @@
         set w [winfo reqwidth .bugreport]
         set h [winfo reqheight .bugreport]
-        #gah@purdue: temporary hack to force view of dismiss button
-        incr h 300
-        set x [expr {([winfo screenwidth .bugreport]-$w)/2}]
+
+        set rootx [winfo rootx .main]
+        set rooty [winfo rooty .main]
+        set mw [winfo reqwidth .main]
+        set mh [winfo reqheight .main]
+        
+        set x [expr { $rootx + (($mw-$w)/2) }]
         if {$x < 0} {set x 0}
-        set y [expr {([winfo screenheight .bugreport]-$h)/2}]
+        set y [expr { $rooty + (($mh-$h)/2) }]
         if {$y < 0} {set y 0}
-
+        
         wm geometry .bugreport +$x+$y
         raise .bugreport
@@ -146,7 +150,13 @@
     set w [winfo reqwidth .bugreport]
     set h [winfo reqheight .bugreport]
-    set x [expr {([winfo screenwidth .bugreport]-$w)/2}]
+
+    set rootx [winfo rootx .main]
+    set rooty [winfo rooty .main]
+    set mw [winfo reqwidth .main]
+    set mh [winfo reqheight .main]
+
+    set x [expr { $rootx + (($mw-$w)/2) }]
     if {$x < 0} {set x 0}
-    set y [expr {([winfo screenheight .bugreport]-$h)/2}]
+    set y [expr { $rooty + (($mh-$h)/2) }]
     if {$y < 0} {set y 0}
 
Index: branches/1.3/gui/scripts/controls.tcl
===================================================================
--- branches/1.3/gui/scripts/controls.tcl	(revision 4511)
+++ branches/1.3/gui/scripts/controls.tcl	(revision 4512)
@@ -139,4 +139,12 @@
         choice {
             Rappture::ChoiceEntry $w $_owner $path
+            bind $w <<Value>> [itcl::code $this _controlChanged $name]
+        }
+        filechoice {
+            Rappture::FileChoiceEntry $w $_owner $path
+            bind $w <<Value>> [itcl::code $this _controlChanged $name]
+        }
+        filelist {
+            Rappture::FileListEntry $w $_owner $path
             bind $w <<Value>> [itcl::code $this _controlChanged $name]
         }
Index: branches/1.3/gui/scripts/coverflow.tcl
===================================================================
--- branches/1.3/gui/scripts/coverflow.tcl	(revision 4512)
+++ branches/1.3/gui/scripts/coverflow.tcl	(revision 4512)
@@ -0,0 +1,624 @@
+# -*- mode: tcl; indent-tabs-mode: nil -*- 
+# ----------------------------------------------------------------------
+#  COMPONENT: Coverflow - browse through a series of images
+#
+#  This widget works like the coverflow browser on iOS.  It presents
+#  a series of images with one in the center and others off to the
+#  sides.
+# ======================================================================
+#  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
+package require BLT
+
+option add *Coverflow.width 5i widgetDefault
+option add *Coverflow.height 2i widgetDefault
+option add *Coverflow.background black widgetDefault
+option add *Coverflow.padding 20 widgetDefault
+option add *Coverflow.spacing 40 widgetDefault
+option add *Coverflow.font {Helvetica 10} widgetDefault
+option add *Coverflow.fontColor white widgetDefault
+
+itcl::class Rappture::Coverflow {
+    inherit itk::Widget
+
+    itk_option define -selectcommand selectCommand SelectCommand ""
+    itk_option define -padding padding Padding 0
+    itk_option define -spacing spacing Spacing 0
+    itk_option define -font font Font ""
+    itk_option define -fontcolor fontColor Foreground ""
+
+    constructor {args} { # defined below }
+    destructor { # defined below }
+
+    public method insert {where args}
+    public method itemconfigure {index args}
+    public method delete {args}
+    public method get {index args}
+    public method size {}
+    public method select {index args}
+
+    private method _itemForIndex {index}
+    private method _redraw {args}
+    private method _rescale {tid height}
+    private method _event {type x y}
+
+    private variable _dispatcher ""  ;# dispatcher for !events
+    private variable _tweener ""     ;# used for animations
+    private variable _items ""       ;# list of tag names for items
+    private variable _data           ;# data for coverflow items
+    private variable _counter 0      ;# for generating unique item IDs
+    private variable _current ""     ;# currently selected item
+    private variable _click ""       ;# click point from last _event call
+}
+
+itk::usual Rappture::Coverflow {
+    keep -background -cursor
+}
+
+# ----------------------------------------------------------------------
+# CONSTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::constructor {args} {
+    itk_option add hull.width hull.height
+    pack propagate $itk_component(hull) no
+
+    # create a dispatcher for events
+    Rappture::dispatcher _dispatcher
+    $_dispatcher register !redraw
+    $_dispatcher dispatch $this !redraw [itcl::code $this _redraw]
+
+    # create a tweener for animations
+    set _tweener [Rappture::Tweener ::#auto -duration 300 \
+        -command [list $_dispatcher event -idle !redraw -position %v] \
+        -finalize [list $_dispatcher event -idle !redraw]]
+
+    itk_component add area {
+        canvas $itk_interior.area
+    } {
+        keep -background -borderwidth -relief
+    }
+    pack $itk_component(area) -side left -expand yes -fill both
+
+    bind $itk_component(area) <Configure> \
+        [list $_dispatcher event -idle !redraw]
+
+    bind $itk_component(area) <ButtonPress> \
+        [itcl::code $this _event click %x %y]
+    bind $itk_component(area) <B1-Motion> \
+        [itcl::code $this _event drag %x %y]
+    bind $itk_component(area) <ButtonRelease> \
+        [itcl::code $this _event release %x %y]
+
+    eval itk_initialize $args
+}
+
+# ----------------------------------------------------------------------
+# DESTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::destructor {} {
+    itcl::delete object $_tweener
+}
+
+# ----------------------------------------------------------------------
+# USAGE: insert <index> <image> ?-option <value>...?
+#
+# Inserts a new image into the coverflow at the position <index>, which
+# is an integer starting from 0 at the left, or the keyword "end" for
+# the right.  The remaining arguments are configuration options:
+#
+#   -tag ....... unique tag name for this item
+#   -text ...... text displayed beneath the image when selected
+#   -data ...... data sent to the callback command
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::insert {where imh args} {
+    array set params $args
+    if {[info exists params(-tag)]} {
+        set tid $params(-tag)
+        unset params(-tag)
+    } else {
+        set tid "item[incr _counter]"
+    }
+
+    if {[info exists _data($tid-text)]} {
+        error "item \"$tid\" already exists -- tags must be unique"
+    }
+    set _items [linsert $_items $where $tid]
+    set _data($tid-image) $imh
+    set _data($tid-scaled) [image create photo]
+    set _data($tid-lastupdate) ""
+    set _data($tid-text) ""
+    set _data($tid-data) ""
+
+    eval itemconfigure $tid [array get params]
+
+    if {$_current eq ""} {
+        select $tid
+    }
+
+    # return the tag name for this new item
+    return $tid
+}
+
+# ----------------------------------------------------------------------
+# USAGE: itemconfigure <indexOrTag> -option <value> ...
+#
+# Used to modify an existing item.  The <indexOrTag> can be an integer
+# index for the item or a -tag name given when the item was created.
+# The remaining -option/value pairs are used to modify the values
+# associated with the item.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::itemconfigure {index args} {
+    set n [_itemForIndex $index]
+    if {$n eq ""} {
+        error "bad index \"$index\": should be integer or -tag name"
+    }
+    set tid [lindex $_items $n]
+
+    # store the new data and then redraw
+    foreach {key val} $args {
+        if {[info exists _data($tid$key)]} {
+            set _data($tid$key) $val
+
+            # make sure we redraw the flow at some point
+            $_dispatcher event -idle !redraw
+        } else {
+            error "bad option \"$key\": should be -text, -data"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: delete ?<indexOrTag> <indexOrTag>...?
+# USAGE: delete all
+#
+# Deletes one or more entries from this listbox.  With the "all"
+# keyword, it deletes all entries in the listbox.  Otherwise, it
+# deletes one or more entries as specified.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::delete {args} {
+    if {$args eq "all"} {
+        set args $_items
+    }
+    foreach index $args {
+        set n [_itemForIndex $index]
+        if {$n ne ""} {
+            set tid [lindex $_items $n]
+            set _items [lreplace $_items $n $n]
+
+            image delete $_data($tid-scaled)
+            unset _data($tid-image)
+            unset _data($tid-scaled)
+            unset _data($tid-lastupdate)
+            unset _data($tid-text)
+            unset _data($tid-data)
+
+            # if this item was selected, then clear that
+            if {$tid eq $_current} {
+                if {$n < [llength $_items]} {
+                    set _current [lindex $_items $n]
+                } else {
+                    set _current [lindex $_items end]
+                }
+            }
+
+            # make sure we redraw the list at some point
+            $_dispatcher event -idle !redraw
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: get <indexOrTag> ?-option -option...?
+#
+# Used to query information about an item.  With no extra args, it
+# returns the tag with an entry, or "" if the entry is not recognized.
+# If additional -option values are specified, then data values are
+# returned for the requested options.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::get {index args} {
+    set n [_itemForIndex $index]
+    if {$n eq ""} {
+        return ""
+    }
+    if {[llength $args] == 0} {
+        return [lindex $_items $n]
+    }
+
+    set vlist ""
+    foreach option $args {
+        if {[info exists _data($tid$option)]} {
+            lappend vlist $_data($tid$option)
+        } else {
+            error "invalid option \"$option\""
+        }
+    }
+    return $vlist
+}
+
+# ----------------------------------------------------------------------
+# USAGE: size
+#
+# Returns the number of items in the listbox.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::size {} {
+    return [llength $_items]
+}
+
+# ----------------------------------------------------------------------
+# USAGE: select <indexOrTag> ?-animate on|off?
+#
+# Makes the given item the "current" item in the coverflow.  This is
+# the item that is shown front-and-center.  If this was not already
+# the current item, then the -selectcommand is invoked with information
+# related to the selected item.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::select {index args} {
+    set n [_itemForIndex $index]
+    if {$n eq ""} {
+        error "bad index \"$index\": should be integer or -tag name"
+    }
+    set tid [lindex $_items $n]
+    if {$tid eq ""} {
+        error "bad index \"$index\": index out of range"
+    }
+
+    set animate on
+    array set params $args
+    if {[info exists params(-animate)]} {
+        set animate $params(-animate)
+    }
+
+    if {$_current ne $tid} {
+        set from [lsearch -exact $_items $_current]
+        set _current $tid
+
+        # invoke the callback to react to this selection
+        if {$itk_option(-selectcommand) ne ""} {
+            set arglist $_data($tid-image)
+            foreach opt {-text -data} {
+                lappend arglist $opt $_data($tid$opt)
+            }
+            uplevel #0 $itk_option(-selectcommand) $arglist
+        }
+
+        # animate the motion and redraw the current choice
+        if {$from >= 0 && $animate} {
+            $_tweener configure -from $from -to $n
+            $_tweener go -restart
+        } else {
+            $_dispatcher event -idle !redraw
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: _itemForIndex <indexOrTag>
+#
+# Converts the given <indexOrTag> to a valid entry name.  If the
+# <indexOrTag> is an integer, then it is interpreted as an index
+# in the range 0 to the size of the list.  Otherwise, it is treated
+# as a -tag name that may have been used when creating the item.
+#
+# Returns an integer index or "" if the item is not recognized.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::_itemForIndex {index} {
+    if {[string is integer -strict $index]} {
+        return $index
+    }
+    if {$index eq "end"} {
+        return [llength $_items]
+    }
+    set n [lsearch -exact $_items $index]
+    if {$n >= 0} {
+        return $n
+    }
+    return ""
+}
+
+# ----------------------------------------------------------------------
+# USAGE: _redraw ?-position <float>?
+#
+# Used internally to redraw all items in the list after it has changed.
+# With no args, it draws the current state with the selected image
+# shown in the middle.  The -position specifies an index, but perhaps
+# with a fractional part.  An index like 2.3 is drawn with the center
+# between images 2 and 3 -- about 1/3 of the way through the animation.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::_redraw {args} {
+    set c $itk_component(area)
+    set w [winfo width $c]
+    set h [winfo height $c]
+    $c delete all
+
+    if {$w == 1 && $h == 1} {
+        # just starting up -- forget it
+        return
+    }
+
+    # get the desired position from the args or the current position
+    set pos [lsearch $_items $_current]
+
+    array set params $args
+    if {[info exists params(-position)]} {
+        set pos $params(-position)
+    }
+
+    if {$pos < 0} { set pos 0 }
+    if {$pos >= [llength $_items]-1} { set pos [expr {[llength $_items]-1}] }
+
+    # does any image have text?  if so, make room for it along the bottom
+    set textht 0
+    foreach tid $_items {
+        if {$_data($tid-text) ne ""} {
+            set textht [font metrics $itk_option(-font) -linespace]
+            break
+        }
+    }
+
+    # figure out the height of the covers and their midpoint
+    set ih [expr {$h-2*$itk_option(-padding)-$textht}]
+    set y0 [expr {($h-$textht)/2}]
+
+    #
+    # If the position is an integer, then that image is centered
+    # in the current view.  Otherwise, we're between two images.
+    #
+    set xmid [expr {$w/2}]
+    set spacing $itk_option(-spacing)
+    set shadow 0.8
+    set shorten 0.8
+    set len 0.3
+
+    if {abs($pos-round($pos)) < 0.05} {
+        # one image right in the middle
+        set lpos [expr {round($pos)}]
+        set rpos $lpos
+
+        # find the x-coord for the left/right sides of that image
+        set tid [lindex $_items $lpos]
+        set origw [image width $_data($tid-image)]
+        set origh [image height $_data($tid-image)]
+        set iw [expr {$ih*$origw/$origh}]
+        set lx [expr {$xmid-$iw/2}]
+        set rx [expr {$xmid+$iw/2}]
+    } else {
+        # between images -- pos and pos+1
+        set lpos [expr {round(floor($pos))}]
+        set rpos [expr {$lpos+1}]
+
+        set llen [expr {$len + (1-$len)*($rpos-$pos)}]
+        set lside [expr {$shorten + (1-$shorten)*($rpos-$pos)}]
+        set lshadow [expr {$shadow*($pos-$lpos)}]
+        set rlen [expr {$len + (1-$len)*($pos-$lpos)}]
+        set rside [expr {$shorten + (1-$shorten)*($pos-$lpos)}]
+        set rshadow [expr {$shadow*($rpos-$pos)}]
+
+        # find the x-coord for the left/right sides of the two images
+        set tid [lindex $_items $lpos]
+        set origw [image width $_data($tid-image)]
+        set origh [image height $_data($tid-image)]
+        set iw0 [expr {$ih*$origw/$origh}]
+        set lx0 [expr {$xmid-$iw0/2}]
+        set rx0 [expr {$xmid+$iw0/2}]
+
+        set tid [lindex $_items $rpos]
+        set origw [image width $_data($tid-image)]
+        set origh [image height $_data($tid-image)]
+        set iw1 [expr {$ih*$origw/$origh}]
+        set lx1 [expr {$xmid-$iw1/2}]
+        set rx1 [expr {$xmid+$iw1/2}]
+
+        set lx [expr {($lx1-$lx0+$spacing)*($rpos-$pos) + $lx0-$spacing}]
+        set rx [expr {($rx1-$rx0-$spacing)*($pos-$lpos) + $rx0+$spacing}]
+    }
+
+    # scan through all images and update their scaling
+    # use -lastupdate to avoid scaling if we're in the same state
+    for {set i 0} {$i < [llength $_items]} {incr i} {
+        set tid [lindex $_items $i]
+        if {$i < $lpos} {
+            set state "left $ih"
+            if {$_data($tid-lastupdate) ne $state} {
+                _rescale $tid $ih
+                squeezer -side right -shadow $shadow -shorten $len \
+                    $_data($tid-scaled) $_data($tid-scaled)
+                set _data($tid-lastupdate) $state
+            }
+        } elseif {$i > $rpos} {
+            set state "right $ih"
+            if {$_data($tid-lastupdate) ne $state} {
+                _rescale $tid $ih
+                squeezer -side left -shadow $shadow -shorten $len \
+                    $_data($tid-scaled) $_data($tid-scaled)
+                set _data($tid-lastupdate) $state
+            }
+        } elseif {$i == $lpos && $i == $rpos} {
+            set state "center $ih"
+            if {$_data($tid-lastupdate) ne $state} {
+                _rescale $tid $ih
+                set _data($tid-lastupdate) $state
+            }
+        } elseif {$i == $lpos} {
+            set state "left $ih ~ $llen"
+            if {$_data($tid-lastupdate) ne $state} {
+                _rescale $tid $ih
+                squeezer -side right -shadow $lshadow -shorten $llen \
+                    -amount $lside $_data($tid-scaled) $_data($tid-scaled)
+                set _data($tid-lastupdate) $state
+            }
+        } elseif {$i == $rpos} {
+            set state "right $ih ~ $rlen"
+            if {$_data($tid-lastupdate) ne $state} {
+                _rescale $tid $ih
+                squeezer -side left -shadow $rshadow -shorten $rlen \
+                    -amount $rside $_data($tid-scaled) $_data($tid-scaled)
+                set _data($tid-lastupdate) $state
+            }
+        }
+    }
+
+    #
+    # Figure out the positions of the various images to the left,
+    # to the right, and in the middle.  Build up a list of items
+    # to draw.
+    #
+    set tiles ""
+
+    # start at left and lay down tiles toward the middle
+    set numOnLeft [expr {round(floor($lx/$spacing))+1}]
+    set i [expr {$lpos-$numOnLeft}]
+    if {$i < 0} { set i 0 }
+    set x0 [expr {$lx - ($lpos-$i)*$spacing}]
+    while {$i < $lpos} {
+        lappend tiles $i $x0 w
+        set x0 [expr {$x0+$spacing}]
+        incr i
+    }
+
+    # start at right and lay down tiles toward the middle
+    set numOnRight [expr {round(floor(($w-$rx)/$spacing))+1}]
+    set i [expr {$rpos+$numOnRight}]
+    if {$i >= [llength $_items]} { set i [expr {[llength $_items]-1}] }
+    set x0 [expr {$rx + ($i-$rpos)*$spacing}]
+    while {$i > $rpos} {
+        lappend tiles $i $x0 e
+        set x0 [expr {$x0-$spacing}]
+        incr i -1
+    }
+
+    # lay down the center image or images
+    if {$lpos == $rpos} {
+        # just one image in the middle
+        lappend tiles $lpos $xmid c
+    } else {
+        # two tiles in a transition
+        if {$llen > $rlen} {
+            lappend tiles $rpos $rx e $lpos $lx w
+        } else {
+            lappend tiles $lpos $lx w $rpos $rx e
+        }
+    }
+
+    # run through the list and draw all items
+    foreach {i x anchor} $tiles {
+        set tid [lindex $_items $i]
+        $c create image $x $y0 -anchor $anchor \
+            -image $_data($tid-scaled) -tags "item$i"
+    }
+
+    # if there is a single center image, show its text
+    if {$lpos == $rpos} {
+        set tid [lindex $_items $lpos]
+        if {$_data($tid-text) ne ""} {
+            $c create text $xmid [expr {$h-$itk_option(-padding)/2}] \
+                -anchor s -text $_data($tid-text) \
+                -font $itk_option(-font) -fill $itk_option(-fontcolor)
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: _rescale <tid> <height>
+#
+# Used internally to rescale a single image (associated with item ID
+# tid) to the specified <height>.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::_rescale {tid ht} {
+    set iw [image width $_data($tid-image)]
+    set ih [image height $_data($tid-image)]
+    set wd [expr {$ht*$iw/$ih}]
+    $_data($tid-scaled) configure -width $wd -height $ht
+    blt::winop resample $_data($tid-image) $_data($tid-scaled) box
+}
+
+# ----------------------------------------------------------------------
+# USAGE: _event <type> <x> <y>
+#
+# Called whenever the user clicks or interacts with the coverflow.
+# The event <type> is something like "click" or "drag".
+# ----------------------------------------------------------------------
+itcl::body Rappture::Coverflow::_event {type x y} {
+    set c $itk_component(area)
+    switch -- $type {
+        click {
+            set _click [list $x $y]
+        }
+        drag {
+            if {$_click ne "" && $_current ne ""} {
+                foreach {x0 y0} $_click break
+                set delta [expr {double($x-$x0)/$itk_option(-spacing)}]
+                set pos [lsearch -exact $_items $_current]
+                set newpos [expr {$pos+$delta}]
+                $_dispatcher event -idle !redraw -position $newpos
+
+                if {![regexp {dragged} $_click]} {
+                    lappend _click dragged
+                }
+            }
+        }
+        release {
+            if {$_click ne ""} {
+                foreach {x0 y0} $_click break
+                if {abs($x-$x0) > 3 || abs($y-$y0) > 3} {
+                    # one last drag event
+                    _event drag $x $y
+                }
+
+                if {[regexp {dragged} $_click]} {
+                    # adjust the current selection to the current pos
+                    set delta [expr {double($x-$x0)/$itk_option(-spacing)}]
+                    set pos [lsearch -exact $_items $_current]
+                    set newpos [expr {round($pos+$delta)}]
+                    if {$newpos < 0} {set newpos 0}
+                    set max [expr {[llength $_items]-1}]
+                    if {$newpos > $max} {set newpos $max}
+
+                    select $newpos -animate off
+
+                    # select may not change, so do one last proper draw
+                    $_dispatcher event -idle !redraw -position $newpos
+
+                    set _click ""
+                    return
+                }
+            }
+
+            # click in place -- see what image we clicked on
+            set found ""
+            foreach id [$c find overlapping $x $y $x $y] {
+                if {[regexp {item([0-9]+)} [$c gettags $id] match index]} {
+                    set found $index
+                }
+                # keep searching for top-most item in stack
+            }
+            if {$found ne ""} {
+                select $found
+            }
+            set _click ""
+        }
+        default {
+            error "bad option \"$type\": should be click, drag, release"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTIONS
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::Coverflow::padding {
+    $_dispatcher event -idle !redraw
+}
+itcl::configbody Rappture::Coverflow::spacing {
+    $_dispatcher event -idle !redraw
+}
+itcl::configbody Rappture::Coverflow::font {
+    $_dispatcher event -idle !redraw
+}
+itcl::configbody Rappture::Coverflow::fontcolor {
+    $_dispatcher event -idle !redraw
+}
Index: branches/1.3/gui/scripts/field.tcl
===================================================================
--- branches/1.3/gui/scripts/field.tcl	(revision 4511)
+++ branches/1.3/gui/scripts/field.tcl	(revision 4512)
@@ -321,5 +321,5 @@
     }
     if {[info exists _comp2dx($cname)]} {
-        return ""  ;# no mesh -- it's embedded in the value data
+        return ""  ;# no mesh -- it's embedded in the blob data
     }
     if {[info exists _comp2mesh($cname)]} {
@@ -405,4 +405,10 @@
 }
 
+# ----------------------------------------------------------------------
+# USAGE: valueLimits <cname>
+#
+# Returns an array for the requested component with a list {min max} 
+# representing the limits for each axis.
+# ----------------------------------------------------------------------
 itcl::body Rappture::Field::valueLimits { cname } {
     if { [info exists _comp2limits($cname)] } {
@@ -919,18 +925,13 @@
                 close $f
             }
-            # This is temporary.  I put a check for this in the DxToVtk
-            # parser.  
-            if { [string range $contents  0 3] == "<DX>" } {
-                set contents [string range $contents 4 end]
-            }
             if { [catch { Rappture::DxToVtk $contents } vtkdata] == 0 } {
                 ReadVtkDataSet $cname $vtkdata
+                if 0 {
+                    set f [open /tmp/$_path.$cname.vtk "w"]
+                    puts -nonewline $f $vtkdata
+                    close $f
+                }
             } else {
                 puts stderr "Can't parse dx data: $vtkdata"
-            }
-            if 0 {
-                set f [open /tmp/$_path.$cname.vtk "w"]
-                puts -nonewline $f $vtkdata
-                close $f
             }
             if { $_alwaysConvertDX ||
Index: branches/1.3/gui/scripts/filechoiceentry.tcl
===================================================================
--- branches/1.3/gui/scripts/filechoiceentry.tcl	(revision 4512)
+++ branches/1.3/gui/scripts/filechoiceentry.tcl	(revision 4512)
@@ -0,0 +1,321 @@
+
+# ----------------------------------------------------------------------
+#  COMPONENT: FileChoiceEntry - widget for entering a choice of strings
+#
+#  This widget represents a <choice> entry on a control panel.
+#  It is used to choose one of several mutually-exclusive strings.
+# ======================================================================
+#  AUTHOR:  Michael McLennan, Purdue University
+#  Copyright (c) 2004-2005  Purdue Research Foundation
+#
+#  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::FileChoiceEntry {
+    inherit itk::Widget
+
+    itk_option define -state state State "normal"
+    
+    private variable _rebuildPending 0
+
+    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 WhenIdle {}
+    private method DoGlob { cwd patterns }
+    private method Glob { pattern }
+
+    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 FileChoiceEntry {
+    keep -cursor -font
+    keep -foreground -background
+    keep -textforeground -textbackground
+    keep -selectbackground -selectforeground -selectborderwidth
+}
+
+# ----------------------------------------------------------------------
+# CONSTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::FileChoiceEntry::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
+    }
+    pack $itk_component(choice) -expand yes -fill both
+    bind $itk_component(choice) <<Value>> [itcl::code $this NewValue]
+
+    # First time, parse the <pattern> elements to generate notify callbacks
+    # for each template found. 
+    foreach cname [$_owner xml children -type pattern $_path] {
+        set glob [string trim [$_owner xml get $_path.$cname]]
+        # Successively replace each template with its value.
+        while { [regexp -indices {@@[^@]*@@} $glob range] } {
+            foreach {first last} $range break
+            set i1 [expr $first + 2]
+            set i2 [expr $last  - 2]
+            set cpath [string range $glob $i1 $i2]
+            set value [$_owner xml get $cpath.$cname]
+            set glob [string replace $glob $first $last $value]
+            $_owner notify add $this $cpath [itcl::code $this WhenIdle]
+        }
+    }
+    $_owner notify sync
+    eval itk_initialize $args
+    Rebuild
+}
+
+# ----------------------------------------------------------------------
+# DESTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::FileChoiceEntry::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::FileChoiceEntry::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) == $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::FileChoiceEntry::label {} {
+    set label [$_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::FileChoiceEntry::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::FileChoiceEntry::Rebuild {} {
+    set _rebuildPending 0
+    # get rid of any existing choices
+    $itk_component(choice) choices delete 0 end
+    array unset _str2val
+    #
+    # Plug in the various options for the choice.
+    #
+    set max 10
+    $_owner notify sync
+    set allfiles {}
+    foreach cname [$_owner xml children -type pattern $_path] {
+        set glob [string trim [$_owner xml get $_path.$cname]]
+        # Successively replace each template with its value.
+        while { [regexp -indices {@@[^@]*@@} $glob range] } {
+            foreach {first last} $range break
+            set i1 [expr $first + 2]
+            set i2 [expr $last  - 2]
+            set cpath [string range $glob $i1 $i2]
+            set value [$_owner xml get $cpath.current]
+            if { $value == "" } {
+                set value [$_owner xml get $cpath.default]
+            }
+            set glob [string replace $glob $first $last $value]
+        }
+        # Replace the template with the substituted value.
+        set files [Glob $glob]
+        set allfiles [concat $allfiles $files]
+    }
+    set first ""
+    set tail ""
+    foreach file $allfiles {
+        set tail [file tail $file]
+        if { $first == "" } {
+            set first $tail
+        }
+        set root [file root $tail]
+        $itk_component(choice) choices insert end $file $tail
+        set _str2val($tail) $file
+        set len [string length $tail]
+        if {$len > $max} { set max $len }
+    }
+    $itk_component(choice) configure -width $max
+    $itk_component(choice) value $tail
+}
+
+# ----------------------------------------------------------------------
+# USAGE: NewValue
+#
+# Invoked automatically whenever the value in the choice changes.
+# Sends a <<Value>> event to notify clients of the change.
+# ----------------------------------------------------------------------
+itcl::body Rappture::FileChoiceEntry::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::FileChoiceEntry::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 $path
+    if {$path == ""} {
+        set desc [$_owner xml get $_path.about.description]
+    }
+
+    if {[string length $str] > 0 && [string length $desc] > 0} {
+        append tip "\n\n$str:\n$desc"
+    }
+    return $tip
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTION: -state
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::FileChoiceEntry::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)
+}
+
+itcl::body Rappture::FileChoiceEntry::WhenIdle {} {
+    if { !$_rebuildPending } {
+        after 10 [itcl::code $this Rebuild]
+        set _rebuildPending 1
+    }
+}
+
+itcl::body Rappture::FileChoiceEntry::DoGlob { cwd patterns } {
+    set rest [lrange $patterns 1 end]
+    set pattern [file join $cwd [lindex $patterns 0]]
+    set files ""
+    if { [llength $rest] > 0 } {
+        if { [catch {
+            glob -nocomplain -type d $pattern
+        } dirs] != 0 } {
+            puts stderr "can't glob \"$pattern\": $dirs"
+            return
+        }
+        foreach d $dirs {
+            set files [concat $files [DoGlob $d $rest]]
+        }
+    } else {
+        if { [catch {
+            glob -nocomplain $pattern
+        } files] != 0 } {
+            puts stderr "can't glob \"$pattern\": $files"
+            return
+        }
+    }
+    return [lsort -dictionary $files]
+}
+
+# 
+# Glob --
+#
+#       Matches a single pattern for files. This differs from the 
+#       Tcl glob by
+#
+#       1. Only matches files, not directories.
+#       2. Doesn't stop on errors (e.g. unreadable directories).
+#
+itcl::body Rappture::FileChoiceEntry::Glob { pattern } {
+    return [DoGlob "" [file split $pattern]]
+}
+
Index: branches/1.3/gui/scripts/filelistentry.tcl
===================================================================
--- branches/1.3/gui/scripts/filelistentry.tcl	(revision 4512)
+++ branches/1.3/gui/scripts/filelistentry.tcl	(revision 4512)
@@ -0,0 +1,437 @@
+
+# ----------------------------------------------------------------------
+#  COMPONENT: FileListEntry - widget for entering a choice of strings
+#
+#  This widget represents a <choice> entry on a control panel.
+#  It is used to choose one of several mutually-exclusive strings.
+# ======================================================================
+#  AUTHOR:  Michael McLennan, Purdue University
+#  Copyright (c) 2004-2005  Purdue Research Foundation
+#
+#  See the file "license.terms" for information on usage and
+#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# ======================================================================
+package require Itk
+
+itk::usual BltTreeView {
+    keep -foreground -cursor 
+}
+itk::usual BltScrollset {
+    #empty
+}
+
+itcl::class Rappture::FileListEntry {
+    inherit itk::Widget
+
+    itk_option define -state state State "normal"
+    
+    private variable _rebuildPending 0
+    private variable _tree ""
+    private variable _owner ""    ;# thing managing this control
+    private variable _path ""     ;# path in XML to this number
+    private variable _icon ""
+
+    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 { args }
+    protected method Tooltip {}
+    protected method WhenIdle {}
+    private method DoGlob { cwd patterns }
+    private method Glob { pattern }
+}
+
+itk::usual FileListEntry {
+    keep -cursor -font
+    keep -foreground -background
+    keep -textforeground -textbackground
+    keep -selectbackground -selectforeground -selectborderwidth
+}
+
+# ----------------------------------------------------------------------
+# CONSTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::FileListEntry::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
+    set _tree [blt::tree create]
+
+    #
+    # Create the widget and configure it properly based on other
+    # hints in the XML.
+    #
+    set label [$_owner xml get $_path.about.label]
+    set desc [$_owner xml get $_path.about.description]
+    itk_component add scrollset {
+        blt::scrollset $itk_interior.ss \
+            -xscrollbar $itk_interior.ss.xs \
+            -yscrollbar $itk_interior.ss.ys \
+            -window $itk_interior.ss.tree \
+            -height 100
+    }
+    blt::tk::scrollbar $itk_interior.ss.xs
+    blt::tk::scrollbar $itk_interior.ss.ys
+    itk_component add tree {
+        blt::treeview $itk_component(scrollset).tree -linewidth 0 \
+            -alternatebackground "" \
+            -bg white -selectmode multiple \
+            -highlightthickness 0 \
+            -tree $_tree \
+            -flat yes -separator /  \
+            -selectcommand [itcl::code $this NewValue]
+    }
+    $itk_component(tree) column configure "treeView" -justify left \
+        -weight 1.0 -text "" -pad 0 -borderwidth 0 -edit no
+    pack $itk_component(scrollset) -fill both -expand yes
+
+    blt::table $itk_interior \
+        0,0 $itk_component(scrollset) -fill both  
+    bind $itk_component(tree) <<Value>> [itcl::code $this NewValue]
+
+    # Standard ButtonPress-1
+    $itk_component(tree) bind Entry <ButtonPress-1> {   
+        Rappture::FileListEntry::SetSelectionAnchor %W current yes set
+        set blt::TreeView::_private(scroll) 1
+    }
+    # Standard B1-Motion
+    $itk_component(tree) bind Entry <B1-Motion> { 
+        set blt::TreeView::_private(x) %x
+        set blt::TreeView::_private(y) %y
+        set index [%W nearest %x %y]
+        Rappture::FileListEntry::SetSelectionAnchor %W $index yes set
+    }
+    # Standard ButtonRelease-1
+    $itk_component(tree) button bind all <ButtonRelease-1> {
+        set index [%W nearest %x %y blt::TreeView::_private(who)]
+        if { [%W index current] == $index && 
+             $blt::TreeView::_private(who) == "button" } {
+            %W see -anchor nw current
+            %W toggle current
+        }
+    }
+    # Shift-ButtonPress-1
+    $itk_component(tree) bind Entry <Shift-ButtonPress-1> {     
+        Rappture::FileListEntry::SetSelectionAnchor %W current yes set
+        set blt::TreeView::_private(scroll) 1
+    }
+    # Shift-B1-Motion
+    $itk_component(tree) bind Entry <Shift-B1-Motion> { 
+        set blt::TreeView::_private(x) %x
+        set blt::TreeView::_private(y) %y
+        set index [%W nearest %x %y]
+        if { [%W cget -selectmode] == "multiple" } {
+            %W selection mark $index
+        } else {
+            Rappture::FileListEntry::SetSelectionAnchor %W $index yes set
+        }
+    }
+    # Shift-ButtonRelease-1
+    $itk_component(tree) bind Entry <Shift-ButtonRelease-1> { 
+        if { [%W cget -selectmode] == "multiple" } {
+            %W selection anchor current
+        }
+        after cancel $blt::TreeView::_private(afterId)
+        set blt::TreeView::_private(afterId) -1
+        set blt::TreeView::_private(scroll) 0
+    }
+    $itk_component(tree) bind Entry <Control-ButtonPress-1> {   
+        Rappture::FileListEntry::SetSelectionAnchor %W current no toggle
+        set blt::TreeView::_private(scroll) 1
+    }
+    $itk_component(tree) bind Entry <Control-B1-Motion> { 
+        set blt::TreeView::_private(x) %x
+        set blt::TreeView::_private(y) %y
+        set index [%W nearest %x %y]
+        if { [%W cget -selectmode] == "multiple" } {
+            %W selection mark $index
+        } else {
+            Rappture::FileListEntry::SetSelectionAnchor %W $index no toggle
+        }
+    }
+    $itk_component(tree) bind Entry <Control-ButtonRelease-1> { 
+        if { [%W cget -selectmode] == "multiple" } {
+            %W selection anchor current
+        }
+        after cancel $blt::TreeView::_private(afterId)
+        set blt::TreeView::_private(afterId) -1
+        set blt::TreeView::_private(scroll) 0
+    }
+    # First time, parse the <pattern> elements to generate notify callbacks
+    # for each template found. 
+    foreach cname [$_owner xml children -type pattern $_path] {
+        set glob [string trim [$_owner xml get $_path.$cname]]
+        # Successively replace each template with its value.
+        while { [regexp -indices {@@[^@]*@@} $glob range] } {
+            foreach {first last} $range break
+            set i1 [expr $first + 2]
+            set i2 [expr $last  - 2]
+            set cpath [string range $glob $i1 $i2]
+            set value [$_owner xml get $cpath.$cname]
+            set glob [string replace $glob $first $last $value]
+            $_owner notify add $this $cpath [itcl::code $this WhenIdle]
+        }
+    }
+    $_owner notify sync
+    eval itk_initialize $args
+
+    # if the control has an icon, plug it in
+    set str [$_owner xml get $path.about.icon]
+    if {$str != ""} {
+        set _icon [image create picture -data $str]
+    }
+    Rebuild
+}
+
+# ----------------------------------------------------------------------
+# DESTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::FileListEntry::destructor {} {
+    blt::tree destroy $_tree
+    $_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::FileListEntry::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
+        }
+        foreach id [$itk_component(tree) curselection] { 
+            set path [$_tree get $id "path" ""] 
+            set path2id($path) $id
+        }
+        set paths [split $newval ,]
+    } elseif {[llength $args] != 0} {
+        error "wrong # args: should be \"value ?-check? ?newval?\""
+    }
+
+    #
+    # Query the value and return.
+    #
+    set list {}
+    foreach id [$itk_component(tree) curselection] { 
+        set path [$_tree get $id "path" ""] 
+        if { $path != "" } {
+            lappend list $path
+        }
+    }
+    return [join $list ,]
+}
+
+# ----------------------------------------------------------------------
+# 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::FileListEntry::label {} {
+    set label [$_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::FileListEntry::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::FileListEntry::Rebuild {} {
+    set _rebuildPending 0
+
+    #
+    # Plug in the various options for the choice.
+    #
+    set max 10
+    $_owner notify sync
+    set allfiles {}
+    foreach cname [$_owner xml children -type pattern $_path] {
+        set glob [string trim [$_owner xml get $_path.$cname]]
+        # Successively replace each template with its value.
+        while { [regexp -indices {@@[^@]*@@} $glob range] } {
+            foreach {first last} $range break
+            set i1 [expr $first + 2]
+            set i2 [expr $last  - 2]
+            set cpath [string range $glob $i1 $i2]
+            set value [$_owner xml get $cpath.current]
+            if { $value == "" } {
+                set value [$_owner xml get $cpath.default]
+            }
+            set glob [string replace $glob $first $last $value]
+        }
+        # Replace the template with the substituted value.
+        set files [Glob $glob]
+        set allfiles [concat $allfiles $files]
+    }
+    set first ""
+    eval $_tree tag add unused [$_tree children root]
+    foreach file $allfiles {
+        set tail [file tail $file]
+        if { $first == "" } {
+            set first $tail
+        }
+        set tail [file root $tail]
+        set id [$_tree index root->"$tail"]
+        if { $id < 0 } {
+            set data [list path $file show 0]
+            set id [$_tree insert root -label $tail -data $data -tag ""]
+        } else {
+            $_tree tag delete unused $id
+        }
+        set len [string length $tail]
+        if {$len > $max} { set max $len }
+    }
+    $itk_component(tree) configure -icons ""
+    $itk_component(tree) entry configure all -icons ""
+    eval $_tree delete [$_tree tag nodes unused]
+    $itk_component(tree) configure -width $max
+    catch { 
+        if { ![$itk_component(tree) selection present] } {
+            $itk_component(tree) selection set [$_tree firstchild root]
+        }
+    } 
+}
+
+# ----------------------------------------------------------------------
+# USAGE: NewValue
+#
+# Invoked automatically whenever the value in the choice changes.
+# Sends a <<Value>> event to notify clients of the change.
+# ----------------------------------------------------------------------
+itcl::body Rappture::FileListEntry::NewValue { args } {
+    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::FileListEntry::Tooltip {} {
+    set tip [string trim [$_owner xml get $_path.about.description]]
+    # get the description for the current choice, if there is one
+    set path ""
+    set desc ""
+    if {$path == ""} {
+        set desc [$_owner xml get $_path.about.description]
+    }
+    set str ""
+    if {[string length $str] > 0 && [string length $desc] > 0} {
+        append tip "\n\n$str:\n$desc"
+    }
+    return $tip
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTION: -state
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::FileListEntry::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(tree) configure -state $itk_option(-state)
+}
+
+itcl::body Rappture::FileListEntry::WhenIdle {} {
+    if { !$_rebuildPending } {
+        after 10 [itcl::code $this Rebuild]
+        set _rebuildPending 1
+    }
+}
+
+proc Rappture::FileListEntry::SetSelectionAnchor { w tagOrId clear how } {
+    set index [$w index $tagOrId]
+    if { $clear } {
+        $w selection clearall
+    }
+    $w see $index
+    $w focus $index
+    $w selection $how $index
+    $w selection anchor $index
+}
+
+itcl::body Rappture::FileListEntry::DoGlob { cwd patterns } {
+    set rest [lrange $patterns 1 end]
+    set pattern [file join $cwd [lindex $patterns 0]]
+    set files ""
+    if { [llength $rest] > 0 } {
+        if { [catch {
+            glob -nocomplain -type d $pattern
+        } dirs] != 0 } {
+            puts stderr "can't glob \"$pattern\": $dirs"
+            return
+        }
+        foreach d $dirs {
+            set files [concat $files [DoGlob $d $rest]]
+        }
+    } else {
+        if { [catch {
+            glob -nocomplain $pattern
+        } files] != 0 } {
+            puts stderr "can't glob \"$pattern\": $files"
+            return
+        }
+    }
+    return $files
+}
+
+# 
+# Glob --
+#
+#       Matches a single pattern for files. This differs from the 
+#       Tcl glob by
+#
+#       1. Only matches files, not directories.
+#       2. Doesn't stop on errors (e.g. unreadable directories).
+#
+itcl::body Rappture::FileListEntry::Glob { pattern } {
+    return [DoGlob "" [file split $pattern]]
+}
+
Index: branches/1.3/gui/scripts/map.tcl
===================================================================
--- branches/1.3/gui/scripts/map.tcl	(revision 4512)
+++ branches/1.3/gui/scripts/map.tcl	(revision 4512)
@@ -0,0 +1,364 @@
+# -*- mode: tcl; indent-tabs-mode: nil -*- 
+
+# ----------------------------------------------------------------------
+#  COMPONENT: map - extracts data from an XML description of a field
+#
+#  This object represents a map of data in an XML description of
+#  simulator output.  A map is similar to a field, but a field is
+#  a quantity versus position in device.  A map is any quantity
+#  versus any other quantity.  This class simplifies the process of
+#  extracting data vectors that represent the map.
+# ======================================================================
+#  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 Itcl
+package require BLT
+
+namespace eval Rappture { 
+    # forward declaration 
+}
+
+itcl::class Rappture::Map {
+    private variable _tree "";         # Tree of information about the map.
+    private variable _isValid 0;
+    private common _nextLayer 0;        # Counter used to generate unique
+                                       # layer names.
+    private common _layerTypes
+    private common _mapTypes
+    array set _layerTypes {
+        "image"         0
+        "elevation"     1
+        "polygon"       2
+        "points"        3
+        "icon"          4
+        "line"          5
+        "label"         6
+    }
+    array set _mapTypes {
+        "geocentric"    0
+        "projected"     1
+    }
+    protected method Parse { xmlobj path }
+
+    constructor {xmlobj path} { 
+        # defined below 
+    }
+    destructor { 
+        # defined below 
+    }
+
+    public method isGeocentric {} 
+    public method layers {}
+    public method layer { layerName }
+    public method hints { args }
+    public method isvalid {} {
+        return $_isValid;
+    }
+    public method type { layerName }
+    public method earthfile {}
+}
+
+# ----------------------------------------------------------------------
+# CONSTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::Map::constructor {xmlobj path} {
+    if {![Rappture::library isvalid $xmlobj]} {
+        error "bad value \"$xmlobj\": should be LibraryObj"
+    }
+    Parse $xmlobj $path
+}
+
+# ----------------------------------------------------------------------
+# DESTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::Map::destructor {} {
+    if { $_tree != "" } {
+        blt::tree destroy $_tree
+    }
+}
+
+#
+# hints --
+#
+itcl::body Rappture::Map::hints { args } {
+    switch -- [llength $args] {
+        0 {
+            return [$_tree get root]
+        }
+        1 {
+            set field [lindex $args 0]
+            return [$_tree get root $field ""]
+        }
+        default {
+            error "wrong # args: should \"hints ?name?\""
+        }
+    }
+}
+
+#
+# Parse --
+#
+#       Parses the map description in the XML object.
+#
+itcl::body Rappture::Map::Parse { xmlobj path } {
+
+    set map [$xmlobj element -as object $path]
+
+    if { $_tree != "" } {
+        blt::tree destroy $_tree
+    }
+    set _tree [blt::tree create]
+    set parent [$_tree insert root -label "layers"]
+    set layers [$map element -as object "layers"]
+    foreach layer [$layers children -type layer] {
+        # Unique identifier for layer.
+        set name "layer[incr _nextLayer]"
+        set child [$_tree insert $parent -label $name]
+        set layerType [$layers get $layer.type] 
+        if { ![info exists _layerTypes($layerType)] } {
+            error "invalid layer type \"$layerType\": should be one of [array names _layerTypes]"
+        }
+        $_tree set $child "name" $layer
+        $_tree set $child "type" $layerType
+        foreach key { label description } {
+            $_tree set $child $key [$layers get $layer.$key] 
+        }
+        # Common settings (for all layer types) with defaults
+        foreach { key defval } { visible true } {
+            $_tree set $child $key $defval
+            set val [$layers get $layer.$key]
+            if {$val != ""} {
+                $_tree set $child $key $val
+            }
+        }
+        # These are settings for which there should be no default
+        # We want to know if they have been set by the user or not
+        # Not all layer types use these
+        foreach key { opacity content priority style } {
+            set val [$layers get $layer.$key]
+            if {$val != ""} {
+                $_tree set $child $key $val
+            }
+        }
+        $_tree set $child "driver" "debug"
+        set gdal [$layers element -as type $layer.gdal]
+        if { $gdal != "" } {
+            foreach key { url } {
+                set value [$layers get $layer.gdal.$key]
+                $_tree set $child "gdal.$key" $value
+            }
+            set file [$layers get $layer.gdal.file] 
+            if { $file != "" } {
+                # FIXME: Add test for valid file path
+                $_tree set $child "gdal.url" $file
+            }
+            $_tree set $child "driver" "gdal"
+        }
+        set ogr [$layers element -as type $layer.ogr]
+        if { $ogr != "" } {
+            foreach key { url } {
+                set value [$layers get $layer.ogr.$key]
+                $_tree set $child "ogr.$key" $value
+            }
+            set file [$layers get $layer.ogr.file] 
+            if { $file != "" } {
+                # FIXME: Add test for valid file path
+                $_tree set $child "ogr.url" $file
+            }
+            $_tree set $child "driver" "ogr"
+        }
+        set tfs [$layers element -as type $layer.tfs]
+        if { $tfs != "" } {
+            foreach key { url format } {
+                set value [$layers get $layer.tfs.$key]
+                $_tree set $child "tfs.$key" $value
+            }
+            $_tree set $child "driver" "tfs"
+        }
+        set tms [$layers element -as type $layer.tms]
+        if { $tms != "" } {
+            foreach key { url tmsType format } {
+                set value [$layers get $layer.tms.$key]
+                $_tree set $child "tms.$key" $value
+            }
+            $_tree set $child "driver" "tms"
+        }
+        set wfs [$layers element -as type $layer.wfs]
+        if { $wfs != "" } {
+            foreach key { url typename outputformat maxfeatures request_buffer } {
+                set value [$layers get $layer.wfs.$key]
+                $_tree set $child "wfs.$key" $value
+            }
+            $_tree set $child "driver" "wfs"
+        }
+        set wms [$layers element -as type $layer.wms]
+        if { $wms != "" } {
+            foreach key { url layers format transparent } {
+                set value [$layers get $layer.wms.$key]
+                $_tree set $child "wms.$key" $value
+            }
+            $_tree set $child "driver" "wms"
+        }
+        set xyz [$layers element -as type $layer.xyz]
+        if { $xyz != "" } {
+            foreach key { url } {
+                set value [$layers get $layer.xyz.$key]
+                $_tree set $child "xyz.$key" $value
+            }
+            $_tree set $child "driver" "xyz"
+        }
+    }
+    $_tree set root "label"       [$map get "about.label"]
+    $_tree set root "style"       [$map get "style"]
+ 
+    set projection [$map get "projection"]
+    set extents    [$map get "extents"]
+    if { $projection  == "" } {
+        if {$extents != ""} {
+            error "cannot specify extents without a projection"
+        }
+        set projection "global-mercator"; # Default projection.
+    }
+    # FIXME: Verify projection is valid.
+    $_tree set root "projection" $projection
+    $_tree set root "extents"    $extents
+
+    set mapType [$map get "type"]
+    if { $mapType == "" } {
+        set mapType "projected";           # Default type is "projected".
+    } 
+    if { ![info exists _mapTypes($mapType)] } {
+        error "unknown map type \"$mapType\": should be one of [array names _mapTypes]"
+    }
+    $_tree set root "type" $mapType
+
+    foreach {key path} {
+        toolId          tool.id
+        toolName        tool.name
+        toolCommand     tool.execute
+        toolTitle       tool.title
+        toolRevision    tool.version.application.revision
+    } {
+        set str [$xmlobj get $path]
+        if { "" != $str } {
+            $_tree set root $key $str
+        }
+    }
+    set _isValid 1
+}
+
+# ----------------------------------------------------------------------
+# USAGE: layers
+#
+# Returns a list of IDs for the layers in the map
+# ----------------------------------------------------------------------
+itcl::body Rappture::Map::layers {} {
+    set list {}
+    foreach node [$_tree children root->"layers"] {
+        lappend list [$_tree label $node] 
+    }
+    return $list
+}
+
+# ----------------------------------------------------------------------
+# USAGE: layer <layerName>
+#
+# Returns an array of settings for the named layer
+# ----------------------------------------------------------------------
+itcl::body Rappture::Map::layer { layerName } {
+    set id [$_tree findchild root->"layers" $layerName]
+    if { $id < 0 } {
+        error "unknown layer \"$layerName\""
+    }
+    return [$_tree get $id]
+}
+
+# ----------------------------------------------------------------------
+# USAGE: type <layerName>
+#
+# Returns the type of the named layer
+# ----------------------------------------------------------------------
+itcl::body Rappture::Map::type { layerName } {
+    set id [$_tree findchild root->"layers" $layerName]
+    if { $id < 0 } {
+        error "unknown layer \"$layerName\""
+    }
+    return [$_tree get $id "type" ""]
+}
+
+# ----------------------------------------------------------------------
+# USAGE: isGeocentric
+#
+# Returns if the map is geocentric (1) or projected (0) 
+# ---------------------------------------------------------------------- 
+itcl::body Rappture::Map::isGeocentric {} { 
+    return [expr {[hints "type"] eq "geocentric"}]
+} 
+
+itcl::body Rappture::Map::earthfile {} { 
+    array set info [$_tree get root]
+    append out "<map"
+    append out " name=\"$info(label)\""
+    append out " type=\"$info(type)\""
+    append out " version=\"2\""
+    append out ">\n"
+    # Profile is optional
+    if { [info exists info(projection)] } {
+        append out " <options>\n"
+        append out "  <profile"
+        append out " srs=\"$info(projection)\""
+        if { [info exists info(extents)] && $info(extents) != "" } {
+            foreach {x1 y1 x2 y2} $info(extents) break
+            append out " xmin=\"$x1\""
+            append out " ymin=\"$y1\""
+            append out " xmax=\"$x2\""
+            append out " ymax=\"$y2\""
+        }
+        append out "/>\n"
+        append out " </options>\n"
+    }
+    foreach node [$_tree children root->"layers"] {
+        array unset info
+        array set info [$_tree get $node]
+        set label [$_tree label $node]
+        switch -- $info(type) {
+            "image" {
+                append out " <image"
+                append out " name=\"$label\""
+                append out " driver=\"gdal\""
+                if { [info exists info(opacity)] } {
+                    append out " opacity=\"$info(opacity)\""
+                }
+                if { $info(visible) } {
+                    append out " visible=\"true\""
+                } else {
+                    append out " visible=\"false\""
+                }
+                append out ">\n"
+                append out "  <url>$info(url)</url>\n"
+                append out " </image>\n"
+            }
+            "elevation" {
+                append out " <elevation"
+                append out " name=\"$label\""
+                append out " driver=\"gdal\""
+                if { $info(visible) } {
+                    append out " visible=\"true\""
+                } else {
+                    append out " visible=\"false\""
+                }
+                append out ">\n"
+                append out "  <url>$info(url)</url>\n"
+                append out " </elevation>\n"
+            }
+            default {
+                puts stderr "Type $info(type) not implemented in earthfile"
+            }
+        }
+    }
+    append out "</map>\n"
+} 
Index: branches/1.3/gui/scripts/mapviewer.tcl
===================================================================
--- branches/1.3/gui/scripts/mapviewer.tcl	(revision 4512)
+++ branches/1.3/gui/scripts/mapviewer.tcl	(revision 4512)
@@ -0,0 +1,1972 @@
+# -*- mode: tcl; indent-tabs-mode: nil -*- 
+# ----------------------------------------------------------------------
+#  COMPONENT: mapviewer - Map object viewer
+#
+#  It connects to the GeoVis server running on a rendering farm,
+#  transmits data, and displays the results.
+# ======================================================================
+#  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
+package require BLT
+#package require Img
+
+option add *MapViewer.width 4i widgetDefault
+option add *MapViewer*cursor crosshair widgetDefault
+option add *MapViewer.height 4i widgetDefault
+option add *MapViewer.foreground black widgetDefault
+option add *MapViewer.controlBackground gray widgetDefault
+option add *MapViewer.controlDarkBackground #999999 widgetDefault
+option add *MapViewer.plotBackground black widgetDefault
+option add *MapViewer.plotForeground white widgetDefault
+option add *MapViewer.font \
+    -*-helvetica-medium-r-normal-*-12-* widgetDefault
+
+# must use this name -- plugs into Rappture::resources::load
+proc MapViewer_init_resources {} {
+    Rappture::resources::register \
+        geovis_server Rappture::MapViewer::SetServerList
+}
+
+itcl::class Rappture::MapViewer {
+    inherit Rappture::VisViewer
+
+    itk_option define -plotforeground plotForeground Foreground ""
+    itk_option define -plotbackground plotBackground Background ""
+
+    private variable _layersFrame "";	# Name of layers frame widget
+    private variable _mapsettings;      # Global map settings
+
+    constructor { hostlist args } {
+        Rappture::VisViewer::constructor $hostlist
+    } {
+        # defined below
+    }
+    destructor {
+        # defined below
+    }
+    public proc SetServerList { namelist } {
+        Rappture::VisViewer::SetServerList "geovis" $namelist
+    }
+    public method add {dataobj {settings ""}}
+    public method camera {option args}
+    public method delete {args}
+    public method disconnect {}
+    public method download {option args}
+    public method get {args}
+    public method isconnected {}
+    public method limits { colormap }
+    public method parameters {title args} { 
+        # do nothing 
+    }
+    public method scale {args}
+
+    protected method AdjustSetting {what {value ""}}
+    protected method Connect {}
+    protected method CurrentLayers {args}
+    protected method Disconnect {}
+    protected method DoResize {}
+    protected method DoRotate {}
+    protected method InitSettings { args  }
+    protected method KeyPress { key }
+    protected method KeyRelease { key }
+    protected method MouseClick { button x y }
+    protected method MouseDoubleClick { button x y }
+    protected method MouseDrag { button x y }
+    protected method MouseMotion {}
+    protected method MouseRelease { button x y }
+    protected method MouseScroll { direction }
+    protected method Pan {option x y}
+    protected method Rebuild {}
+    protected method ReceiveMapInfo { args }
+    protected method ReceiveImage { args }
+    protected method Rotate {option x y}
+    protected method Zoom {option {x 0} {y 0}}
+
+    # The following methods are only used by this class.
+    private method BuildCameraTab {}
+    private method BuildDownloadPopup { widget command } 
+    private method BuildLayerTab {}
+    private method BuildTerrainTab {}
+    private method ChangeLayerVisibility { dataobj layer }
+    private method EventuallyHandleMotionEvent { x y } 
+    private method EventuallyResize { w h } 
+    private method EventuallyRotate { dx dy } 
+    private method GetImage { args } 
+    private method GetNormalizedMouse { x y }
+    private method MapIsGeocentric {}
+    private method SetLayerStyle { dataobj layer }
+    private method SetTerrainStyle { style }
+    private method SetOpacity { dataset }
+    private method UpdateLayerControls {}
+    private method EarthFile {}
+
+    private variable _dlist "";		# list of data objects
+    private variable _obj2datasets
+    private variable _obj2ovride;	# maps dataobj => style override
+    private variable _layers;		# Contains the names of all the 
+                                   	# layer in the server.
+    private variable _click;            # info used for rotate operations
+    private variable _view;             # view params for 3D view
+    private variable _settings
+    private variable _visibility
+    private variable _style;            # Array of current component styles.
+    private variable _initialStyle;     # Array of initial component styles.
+    private variable _reset 1;          # Indicates that server was reset and
+                                        # needs to be reinitialized.
+    private variable _initCamera 1;
+    private variable _haveTerrain 0
+
+    private variable _first ""     ;# This is the topmost dataset.
+    private variable _start 0
+    private variable _title ""
+
+    common _downloadPopup          ;# download options from popup
+    private common _hardcopy
+    private variable _width 0
+    private variable _height 0
+    private variable _resizePending 0
+    private variable _rotatePending 0
+    private variable _rotateDelay 150
+    private variable _motion 
+    private variable _sendEarthFile 0
+    private variable _useServerManip 0
+}
+
+itk::usual MapViewer {
+    keep -background -foreground -cursor -font
+    keep -plotbackground -plotforeground
+}
+
+# ----------------------------------------------------------------------
+# CONSTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::constructor {hostlist args} {
+    set _serverType "geovis"
+
+    if { [catch {
+	
+    # Rebuild event
+    $_dispatcher register !rebuild
+    $_dispatcher dispatch $this !rebuild "[itcl::code $this Rebuild]; list"
+
+    # Resize event
+    $_dispatcher register !resize
+    $_dispatcher dispatch $this !resize "[itcl::code $this DoResize]; list"
+
+    # Rotate event
+    $_dispatcher register !rotate
+    $_dispatcher dispatch $this !rotate "[itcl::code $this DoRotate]; list"
+
+    # <Motion> event
+    $_dispatcher register !motion
+    $_dispatcher dispatch $this !motion "[itcl::code $this MouseMotion]; list"
+
+    #
+    # Populate parser with commands handle incoming requests
+    #
+    $_parser alias image    [itcl::code $this ReceiveImage]
+    $_parser alias map      [itcl::code $this ReceiveMapInfo]
+    $_parser alias camera   [itcl::code $this camera]
+
+    # Settings for mouse motion events: these are required
+    # to update the Lat/Long coordinate display
+    array set _motion {
+        compress        0
+        delay           100
+        enable          0
+        pending         0
+        x               0
+        y               0
+    }
+    # This array holds the Viewpoint parameters that the
+    # server sends on "camera get".
+    array set _view {
+        distance        1.0
+        heading         0.0
+        pitch           -89.9
+        srs             ""
+        verticalDatum   ""
+        x               0.0
+        y               0.0
+        z               0.0
+    }
+
+    # Note: grid types are "geodetic", "utm" and "mgrs"
+    # Currently only work in geocentric maps
+    array set _settings [subst {
+        camera-throw           0
+        coords-precision       5
+        coords-units           "latlong_decimal_degrees"
+        coords-visible         1
+        grid                   0
+        grid-type              "geodetic"
+        legend                 1
+        terrain-edges          0
+        terrain-lighting       0
+        terrain-vertscale      1.0
+        terrain-wireframe      0
+    }]
+    itk_component add view {
+        canvas $itk_component(plotarea).view \
+            -highlightthickness 0 -borderwidth 0
+    } {
+        usual
+        ignore -highlightthickness -borderwidth  -background
+    }
+
+    set c $itk_component(view)
+    #bind $c <KeyPress-Left>  [list %W xview scroll 10 units]
+    #bind $c <KeyPress-Right> [list %W xview scroll -10 units]
+    #bind $c <KeyPress-Up>    [list %W yview scroll 10 units]
+    #bind $c <KeyPress-Down>  [list %W yview scroll -10 units]
+    bind $c <Enter> "focus %W"
+    bind $c <Control-F1> [itcl::code $this ToggleConsole]
+
+    # Fix the scrollregion in case we go off screen
+    $c configure -scrollregion [$c bbox all]
+
+    set _map(id) [$c create image 0 0 -anchor nw -image $_image(plot)]
+    set _map(cwidth) -1 
+    set _map(cheight) -1 
+    set _map(zoom) 1.0
+    set _map(original) ""
+
+    set f [$itk_component(main) component controls]
+    itk_component add reset {
+        button $f.reset -borderwidth 1 -padx 1 -pady 1 \
+            -highlightthickness 0 \
+            -image [Rappture::icon reset-view] \
+            -command [itcl::code $this camera reset]
+    } {
+        usual
+        ignore -highlightthickness
+    }
+    pack $itk_component(reset) -side top -padx 2 -pady 2
+    Rappture::Tooltip::for $itk_component(reset) \
+        "Reset the view to the default zoom level"
+
+    itk_component add zoomin {
+        button $f.zin -borderwidth 1 -padx 1 -pady 1 \
+            -highlightthickness 0 \
+            -image [Rappture::icon zoom-in] \
+            -command [itcl::code $this Zoom in]
+    } {
+        usual
+        ignore -highlightthickness
+    }
+    pack $itk_component(zoomin) -side top -padx 2 -pady 2
+    Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
+
+    itk_component add zoomout {
+        button $f.zout -borderwidth 1 -padx 1 -pady 1 \
+            -highlightthickness 0 \
+            -image [Rappture::icon zoom-out] \
+            -command [itcl::code $this Zoom out]
+    } {
+        usual
+        ignore -highlightthickness
+    }
+    pack $itk_component(zoomout) -side top -padx 2 -pady 2
+    Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
+
+    BuildLayerTab
+    BuildTerrainTab
+    BuildCameraTab
+
+    # Legend
+
+    set _image(legend) [image create photo]
+    itk_component add legend {
+        canvas $itk_component(plotarea).legend -width 50 -highlightthickness 0 
+    } {
+        usual
+        ignore -highlightthickness
+        rename -background -plotbackground plotBackground Background
+    }
+
+    # Hack around the Tk panewindow.  The problem is that the requested 
+    # size of the 3d view isn't set until an image is retrieved from
+    # the server.  So the panewindow uses the tiny size.
+    set w 10000
+    pack forget $itk_component(view)
+    blt::table $itk_component(plotarea) \
+        0,0 $itk_component(view) -fill both -reqwidth $w 
+    blt::table configure $itk_component(plotarea) c1 -resize none
+
+    bind $itk_component(view) <Configure> \
+        [itcl::code $this EventuallyResize %w %h]
+
+    if {$_useServerManip} {
+        # Bindings for keyboard events
+        bind $itk_component(view) <KeyPress> \
+            [itcl::code $this KeyPress %N]
+        bind $itk_component(view) <KeyRelease> \
+            [itcl::code $this KeyRelease %N]
+
+        # Bindings for rotation via mouse
+        bind $itk_component(view) <ButtonPress-1> \
+            [itcl::code $this MouseClick 1 %x %y]
+        bind $itk_component(view) <Double-1> \
+            [itcl::code $this MouseDoubleClick 1 %x %y]
+        bind $itk_component(view) <B1-Motion> \
+            [itcl::code $this MouseDrag 1 %x %y]
+        bind $itk_component(view) <ButtonRelease-1> \
+            [itcl::code $this MouseRelease 1 %x %y]
+
+        # Bindings for panning via mouse
+        bind $itk_component(view) <ButtonPress-2> \
+            [itcl::code $this MouseClick 2 %x %y]
+        bind $itk_component(view) <Double-2> \
+            [itcl::code $this MouseDoubleClick 2 %x %y]
+        bind $itk_component(view) <B2-Motion> \
+            [itcl::code $this MouseDrag 2 %x %y]
+        bind $itk_component(view) <ButtonRelease-2> \
+            [itcl::code $this MouseRelease 2 %x %y]
+
+        bind $itk_component(view) <ButtonPress-3> \
+            [itcl::code $this MouseClick 3 %x %y]
+        bind $itk_component(view) <Double-3> \
+            [itcl::code $this MouseDoubleClick 3 %x %y]
+        bind $itk_component(view) <B3-Motion> \
+            [itcl::code $this MouseDrag 3 %x %y]
+        bind $itk_component(view) <ButtonRelease-3> \
+            [itcl::code $this MouseRelease 3 %x %y]
+
+        # Binding for mouse motion events
+        if {$_motion(enable)} {
+            bind $itk_component(view) <Motion> \
+                [itcl::code $this EventuallyHandleMotionEvent %x %y]
+        }
+    } else {
+        # Bindings for panning via mouse
+        bind $itk_component(view) <ButtonPress-1> \
+            [itcl::code $this Pan click %x %y]
+        bind $itk_component(view) <B1-Motion> \
+            [itcl::code $this Pan drag %x %y]
+        bind $itk_component(view) <ButtonRelease-1> \
+            [itcl::code $this Pan release %x %y]
+        bind $itk_component(view) <Button-1> \
+            +[itcl::code $this SendCmd "map setpos %x %y"]
+        bind $itk_component(view) <Double-1> \
+            [itcl::code $this camera go %x %y 0.4]
+
+        # Bindings for rotation via mouse
+        bind $itk_component(view) <ButtonPress-2> \
+            [itcl::code $this Rotate click %x %y]
+        bind $itk_component(view) <B2-Motion> \
+            [itcl::code $this Rotate drag %x %y]
+        bind $itk_component(view) <ButtonRelease-2> \
+            [itcl::code $this Rotate release %x %y]
+
+        # Bindings for zoom via mouse
+        bind $itk_component(view) <ButtonPress-3> \
+            [itcl::code $this Zoom click %x %y]
+        bind $itk_component(view) <B3-Motion> \
+            [itcl::code $this Zoom drag %x %y]
+        bind $itk_component(view) <ButtonRelease-3> \
+            [itcl::code $this Zoom release %x %y]
+        bind $itk_component(view) <Double-3> \
+            [itcl::code $this camera go %x %y 2.5]
+        bind $itk_component(view) <Double-3> \
+            +[itcl::code $this SendCmd "map setpos %x %y"]
+
+        # Bindings for panning via keyboard
+        bind $itk_component(view) <KeyPress-Left> \
+            [itcl::code $this Pan set 10 0]
+        bind $itk_component(view) <KeyPress-Right> \
+            [itcl::code $this Pan set -10 0]
+        bind $itk_component(view) <KeyPress-Up> \
+            [itcl::code $this Pan set 0 -10]
+        bind $itk_component(view) <KeyPress-Down> \
+            [itcl::code $this Pan set 0 10]
+
+        # Binding for mouse motion events
+        set _motion(compress) 1
+        if {$_motion(enable)} {
+            bind $itk_component(view) <Motion> \
+                [itcl::code $this EventuallyHandleMotionEvent %x %y]
+        }
+    }
+
+    bind $itk_component(view) <Shift-KeyPress-Left> \
+        [itcl::code $this Pan set 2 0]
+    bind $itk_component(view) <Shift-KeyPress-Right> \
+        [itcl::code $this Pan set -2 0]
+    bind $itk_component(view) <Shift-KeyPress-Up> \
+        [itcl::code $this Pan set 0 -2]
+    bind $itk_component(view) <Shift-KeyPress-Down> \
+        [itcl::code $this Pan set 0 2]
+
+    # Bindings for zoom via keyboard
+    bind $itk_component(view) <KeyPress-Prior> \
+        [itcl::code $this Zoom out]
+    bind $itk_component(view) <KeyPress-Next> \
+        [itcl::code $this Zoom in]
+
+    bind $itk_component(view) <Enter> "focus $itk_component(view)"
+
+    if {[string equal "x11" [tk windowingsystem]]} {
+        # Bindings for zoom via mouse
+        if {$_useServerManip} {
+            bind $itk_component(view) <4> [itcl::code $this MouseScroll up]
+            bind $itk_component(view) <5> [itcl::code $this MouseScroll down]
+        } else {
+            bind $itk_component(view) <4> [itcl::code $this Zoom out]
+            bind $itk_component(view) <5> [itcl::code $this Zoom in]
+        }
+    }
+
+    set _image(download) [image create photo]
+
+    eval itk_initialize $args
+    Connect
+} errs] != 0 } {
+	puts stderr errs=$errs
+    }
+}
+
+# ----------------------------------------------------------------------
+# DESTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::destructor {} {
+    Disconnect
+    $_dispatcher cancel !rebuild
+    $_dispatcher cancel !resize
+    $_dispatcher cancel !rotate
+    image delete $_image(plot)
+    image delete $_image(download)
+}
+
+itcl::body Rappture::MapViewer::DoResize {} {
+    set sendResize 1
+    if { $_width < 2 } {
+        set _width 500
+        set sendResize 0
+    }
+    if { $_height < 2 } {
+        set _height 500
+        set sendResize 0
+    }
+    set _start [clock clicks -milliseconds]
+    if {$sendResize} {
+        SendCmd "screen size $_width $_height"
+    }
+    set _resizePending 0
+}
+
+itcl::body Rappture::MapViewer::DoRotate {} {
+    SendCmd "camera rotate $_view(azimuth) $_view(elevation)"
+    set _rotatePending 0
+}
+
+itcl::body Rappture::MapViewer::EventuallyResize { w h } {
+    set _width $w
+    set _height $h
+    if { !$_resizePending } {
+        set _resizePending 1
+        $_dispatcher event -after 200 !resize
+    }
+}
+
+itcl::body Rappture::MapViewer::EventuallyRotate { dx dy } {
+    set _view(azimuth) $dx
+    set _view(elevation) $dy
+    if { !$_rotatePending } {
+        set _rotatePending 1
+        $_dispatcher event -after $_rotateDelay !rotate
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: add <dataobj> ?<settings>?
+#
+# Clients use this to add a data object to the plot.  The optional
+# <settings> are used to configure the plot.  Allowed settings are
+# -color, -brightness, -width, -linestyle, and -raise.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::add {dataobj {settings ""}} {
+    array set params {
+        -color auto
+        -width 1
+        -linestyle solid
+        -brightness 0
+        -raise 0
+        -description ""
+        -param ""
+        -type ""
+    }
+    array set params $settings
+    set params(-description) ""
+    set params(-param) ""
+    array set params $settings
+
+    if {$params(-color) == "auto" || $params(-color) == "autoreset"} {
+        # can't handle -autocolors yet
+        set params(-color) black
+    }
+    set pos [lsearch -exact $_dlist $dataobj]
+    if {$pos < 0} {
+        #if {[llength $_dlist] > 0} {
+        #    error "Can't add more than 1 map to mapviewer"
+        #}
+        lappend _dlist $dataobj
+    }
+    set _obj2ovride($dataobj-color) $params(-color)
+    set _obj2ovride($dataobj-width) $params(-width)
+    set _obj2ovride($dataobj-raise) $params(-raise)
+    $_dispatcher event -idle !rebuild
+}
+
+# ----------------------------------------------------------------------
+# USAGE: delete ?<dataobj1> <dataobj2> ...?
+#
+#       Clients use this to delete a dataobj from the plot.  If no dataobjs
+#       are specified, then all dataobjs are deleted.  No data objects are
+#       deleted.  They are only removed from the display list.
+#
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::delete {args} {
+    if { [llength $args] == 0} {
+        set args $_dlist
+    }
+    # Delete all specified dataobjs
+    set changed 0
+    foreach dataobj $args {
+        set pos [lsearch -exact $_dlist $dataobj]
+        if { $pos < 0 } {
+            continue;                   # Don't know anything about it.
+        }
+        # When a map is marked deleted, we hide its layers.
+        foreach layer [$dataobj layers] {
+            SendCmd "map layer visible 0 $layer"
+            set _visibility($layer) 0
+        }
+        # Remove it from the dataobj list.
+        set _dlist [lreplace $_dlist $pos $pos]
+        array unset _obj2ovride $dataobj-*
+        array unset _settings $dataobj-*
+        set changed 1
+    }
+    # If anything changed, then rebuild the plot
+    if { $changed } {
+        $_dispatcher event -idle !rebuild
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: get ?-objects?
+# USAGE: get ?-visible?
+# USAGE: get ?-image view?
+#
+# Clients use this to query the list of objects being plotted, in
+# order from bottom to top of this result.  The optional "-image"
+# flag can also request the internal images being shown.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::get {args} {
+    if {[llength $args] == 0} {
+        set args "-objects"
+    }
+
+    set op [lindex $args 0]
+    switch -- $op {
+        "-objects" {
+            # put the dataobj list in order according to -raise options
+            set dlist {}
+            foreach dataobj $_dlist {
+                if { ![$dataobj isvalid] } {
+                    continue
+                }
+                if {[info exists _obj2ovride($dataobj-raise)] && 
+                    $_obj2ovride($dataobj-raise)} {
+                    set dlist [linsert $dlist 0 $dataobj]
+                } else {
+                    lappend dlist $dataobj
+                }
+            }
+            return $dlist
+        }
+        "-visible" {
+            set dlist {}
+            foreach dataobj $_dlist {
+                if { ![$dataobj isvalid] } {
+                    continue
+                }
+                if { ![info exists _obj2ovride($dataobj-raise)] } {
+                    # No setting indicates that the object isn't visible.
+                    continue
+                }
+                # Otherwise use the -raise parameter to put the object to
+                # the front of the list.
+                if { $_obj2ovride($dataobj-raise) } {
+                    set dlist [linsert $dlist 0 $dataobj]
+                } else {
+                    lappend dlist $dataobj
+                }
+            }
+            return $dlist
+        }           
+        -image {
+            if {[llength $args] != 2} {
+                error "wrong # args: should be \"get -image view\""
+            }
+            switch -- [lindex $args end] {
+                view {
+                    return $_image(plot)
+                }
+                default {
+                    error "bad image name \"[lindex $args end]\": should be view"
+                }
+            }
+        }
+        default {
+            error "bad option \"$op\": should be -objects or -image"
+        }
+    }
+}
+
+itcl::body Rappture::MapViewer::MapIsGeocentric {} {
+    if { [info exists _mapsettings(type)] } {
+        return [expr {$_mapsettings(type) eq "geocentric"}]
+    } else {
+        return 0
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: scale ?<data1> <data2> ...?
+#
+# Sets the default limits for the overall plot according to the
+# limits of the data for all of the given <data> objects.  This
+# accounts for all objects--even those not showing on the screen.
+# Because of this, the limits are appropriate for all objects as
+# the user scans through data in the ResultSet viewer.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::scale {args} {
+    array unset _mapsettings
+    set _haveTerrain 0
+
+    # Verify that all the maps have the same global settings. For example,
+    # you can't have one map type "geocentric" and the other "projected".
+
+    foreach dataobj $args {
+        if { ![$dataobj isvalid] } {
+            continue
+        }
+        array unset hints 
+        array set hints [$dataobj hints]
+        if { ![info exists _mapsettings(label)] } {
+            set _mapsettings(label) $hints(label)
+        }
+        if { ![info exists _mapsettings(style)] } {
+            set _mapsettings(style) $hints(style)
+        }
+        if { ![info exists _mapsettings(type)] } {
+            set _mapsettings(type) $hints(type)
+        } elseif { $hints(type) != $_mapsettings(type) } {
+            error "maps \"$hints(label)\" have differing types"
+        }
+        if { ![info exists _mapsettings(projection)] } {
+            set _mapsettings(projection) $hints(projection)
+        } elseif { $hints(projection) != $_mapsettings(projection) } {
+            error "maps \"$hints(label)\" have differing projections"
+        }
+        if { $hints(extents) != "" } {
+            if { ![info exists _mapsettings(extents)] } {
+                set _mapsettings(extents) $hints(extents)
+            }
+            foreach {x1 y1 x2 y2} $hints(extents) break
+            if { ![info exists _mapsettings(x1)] || $x1 < $_mapsettings(x1) } {
+                set _mapsettings(x1) $x1
+            }
+            if { ![info exists _mapsettings(y1)] || $y1 < $_mapsettings(y1) } {
+                set _mapsettings(y1) $y1
+            }
+            if { ![info exists _mapsettings(x2)] || $x2 > $_mapsettings(x2) } {
+                set _mapsettings(x2) $x2
+            }
+            if { ![info exists _mapsettings(y2)] || $y2 > $_mapsettings(y2) } {
+                set _mapsettings(y2) $y2
+            }
+        }
+        foreach layer [$dataobj layers] {
+            if { [$dataobj type $layer] == "elevation" } {
+                set _haveTerrain 1
+                break
+            } 
+        }
+    }
+    if { $_haveTerrain } {
+        if { [$itk_component(main) exists "Terrain Settings"] } {
+            # TODO: Enable controls like vertical scale that only have
+            # an effect when terrain is present
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: download coming
+# USAGE: download controls <downloadCommand>
+# USAGE: download now
+#
+# Clients use this method to create a downloadable representation
+# of the plot.  Returns a list of the form {ext string}, where
+# "ext" is the file extension (indicating the type of data) and
+# "string" is the data itself.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::download {option args} {
+    switch $option {
+        coming {
+            if {[catch {
+                blt::winop snap $itk_component(plotarea) $_image(download)
+            }]} {
+                $_image(download) configure -width 1 -height 1
+                $_image(download) put #000000
+            }
+        }
+        controls {
+            set popup .mapviewerdownload
+            if { ![winfo exists .mapviewerdownload] } {
+                set inner [BuildDownloadPopup $popup [lindex $args 0]]
+            } else {
+                set inner [$popup component inner]
+            }
+            set _downloadPopup(image_controls) $inner.image_frame
+            set num [llength [get]]
+            set num [expr {($num == 1) ? "1 result" : "$num results"}]
+            set word [Rappture::filexfer::label downloadWord]
+            $inner.summary configure -text "$word $num in the following format:"
+            update idletasks            ;# Fix initial sizes
+            return $popup
+        }
+        now {
+            set popup .mapviewerdownload
+            if {[winfo exists .mapviewerdownload]} {
+                $popup deactivate
+            }
+            switch -- $_downloadPopup(format) {
+                "image" {
+                    return [$this GetImage [lindex $args 0]]
+                }
+            }
+            return ""
+        }
+        default {
+            error "bad option \"$option\": should be coming, controls, now"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: Connect ?<host:port>,<host:port>...?
+#
+# Clients use this method to establish a connection to a new
+# server, or to reestablish a connection to the previous server.
+# Any existing connection is automatically closed.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::Connect {} {
+    global readyForNextFrame
+    set readyForNextFrame 1
+    set _reset 1
+    set _hosts [GetServerList "geovis"]
+    if { "" == $_hosts } {
+        return 0
+    }
+    set result [VisViewer::Connect $_hosts]
+    if { $result } {
+        if { $_reportClientInfo }  {
+            # Tell the server the viewer, hub, user and session.
+            # Do this immediately on connect before buffering any commands
+            global env
+
+            set info {}
+            set user "???"
+            if { [info exists env(USER)] } {
+                set user $env(USER)
+            }
+            set session "???"
+            if { [info exists env(SESSION)] } {
+                set session $env(SESSION)
+            }
+            lappend info "hub" [exec hostname]
+            lappend info "client" "mapviewer"
+            lappend info "user" $user
+            lappend info "session" $session
+            SendCmd "clientinfo [list $info]"
+        }
+
+        set w [winfo width $itk_component(view)]
+        set h [winfo height $itk_component(view)]
+        EventuallyResize $w $h
+    }
+    return $result
+}
+
+#
+# isconnected --
+#
+#       Indicates if we are currently connected to the visualization server.
+#
+itcl::body Rappture::MapViewer::isconnected {} {
+    return [VisViewer::IsConnected]
+}
+
+#
+# disconnect --
+#
+itcl::body Rappture::MapViewer::disconnect {} {
+    Disconnect
+    set _reset 1
+}
+
+#
+# Disconnect --
+#
+#       Clients use this method to disconnect from the current rendering
+#       server.
+#
+itcl::body Rappture::MapViewer::Disconnect {} {
+    VisViewer::Disconnect
+
+    $_dispatcher cancel !rebuild
+    $_dispatcher cancel !resize
+    $_dispatcher cancel !rotate
+    $_dispatcher cancel !motion
+    # disconnected -- no more data sitting on server
+    array unset _layers
+    array unset _layersFrame 
+    global readyForNextFrame
+    set readyForNextFrame 1
+}
+
+# ----------------------------------------------------------------------
+# USAGE: ReceiveImage -bytes <size> -type <type> -token <token>
+#
+# Invoked automatically whenever the "image" command comes in from
+# the rendering server.  Indicates that binary image data with the
+# specified <size> will follow.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::ReceiveImage { args } {
+    global readyForNextFrame
+    set readyForNextFrame 1
+    array set info {
+        -token "???"
+        -bytes 0
+        -type image
+    }
+    array set info $args
+    set bytes [ReceiveBytes $info(-bytes)]
+    if { $info(-type) == "image" } {
+        $_image(plot) configure -data $bytes
+    } elseif { $info(type) == "print" } {
+        set tag $this-print-$info(-token)
+        set _hardcopy($tag) $bytes
+    }
+}
+
+#
+# ReceiveMapInfo --
+#
+itcl::body Rappture::MapViewer::ReceiveMapInfo { args } {
+    if { ![isconnected] } {
+        return
+    }
+    set option [lindex $args 0]
+    switch -- $option {
+        "coords" {
+            set len [llength $args]
+            if {$len < 4} {
+                puts stderr "Coords out of range"
+            } elseif {$len < 6} {
+                foreach { x y z } [lrange $args 1 end] break
+                puts stderr "Coords: $x $y $z"
+            } else {
+                foreach { x y z pxX pxY } [lrange $args 1 end] break
+                puts stderr "Coords($pxX,$pxY): $x $y $z"
+            }
+        }
+        "names" {
+            foreach { name } [lindex $args 1] {
+                puts stderr "layer: $name"
+            }
+        }
+        default {
+            error "unknown map option \"$option\" from server"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: Rebuild
+#
+# Called automatically whenever something changes that affects the
+# data in the widget.  Clears any existing data and rebuilds the
+# widget to display new data.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::Rebuild {} {
+    set w [winfo width $itk_component(view)]
+    set h [winfo height $itk_component(view)]
+    if { $w < 2 || $h < 2 } {
+        $_dispatcher event -idle !rebuild
+        return
+    }
+
+    # Turn on buffering of commands to the server.  We don't want to be
+    # preempted by a server disconnect/reconnect (which automatically
+    # generates a new call to Rebuild).
+    StartBufferingCommands
+
+    if { $_reset } {
+        set _width $w
+        set _height $h
+        DoResize
+
+        if { [info exists _mapsettings(type)] } {
+            # The map must be reset once before any layers are added This
+            # should not be done more than once as it is very expensive.
+            if {$_sendEarthFile} {
+                set bytes [EarthFile]
+                if {0} {
+                    set f [open "/tmp/map.earth" "w"]
+                    puts $f $bytes
+                    close $f
+                }
+                set length [string length $bytes]
+                SendCmd "map load data follows $length"
+                append _outbuf $bytes
+            } else {
+                if { $_mapsettings(type) == "geocentric" } {
+                    SendCmd "map reset geocentric"
+                }  else {
+                    set proj $_mapsettings(projection)
+                    if { $proj == "" } { 
+                        SendCmd "map reset projected global-mercator"
+                    } elseif { ![info exists _mapsettings(extents)] || $_mapsettings(extents) == "" } {
+                        SendCmd [list map reset "projected" $proj]
+                    } else {
+                        #foreach {x1 y1 x2 y2} $_mapsettings(extents) break
+                        foreach key "x1 y1 x2 y2" {
+                            set $key $_mapsettings($key)
+                        }
+                        SendCmd [list map reset "projected" $proj $x1 $y1 $x2 $y2] 
+                    }
+                }
+                # XXX: Remove these after implementing batch load of layers with reset
+                SendCmd "map layer delete base"
+            }
+
+            # Most terrain settings are global to the map and apply even
+            # if there is no elevation layer.  The exception is the 
+            # vertical scale, which only applies if there is an elevation
+            # layer
+            if { [info exists _mapsettings(style)] } {
+                SetTerrainStyle $_mapsettings(style)
+            } else {
+                InitSettings terrain-edges terrain-lighting \
+                    terrain-vertscale terrain-wireframe
+            }
+            InitSettings coords-visible
+        } else {
+            error "No map settings on reset"
+        }
+    }
+
+    set _first ""
+    set count 0
+
+    foreach dataobj [get -objects] {
+        set _obj2datasets($dataobj) ""
+        foreach layer [$dataobj layers] {
+	    array unset info
+	    array set info [$dataobj layer $layer]
+            if { ![info exists _layers($layer)] } {
+                if { $_reportClientInfo }  {
+                    set cinfo {}
+                    lappend cinfo "tool_id"       [$dataobj hints toolId]
+                    lappend cinfo "tool_name"     [$dataobj hints toolName]
+                    lappend cinfo "tool_version"  [$dataobj hints toolRevision]
+                    lappend cinfo "tool_title"    [$dataobj hints toolTitle]
+                    lappend cinfo "dataset_label" [$dataobj hints label]
+                    lappend cinfo "dataset_tag"   $layer
+                    SendCmd [list "clientinfo" $cinfo]
+                }
+                set _layers($layer) 1
+                SetLayerStyle $dataobj $layer
+            }
+            lappend _obj2datasets($dataobj) $layer
+            # FIXME: This is overriding all layers' initial visibility setting
+            if { [info exists _obj2ovride($dataobj-raise)] } {
+                SendCmd "map layer visible 1 $layer"
+                set _visibility($layer) 1
+                #SetLayerOpacity $layer
+            }
+        }
+    }
+
+    if {$_reset} {
+        if {$_initCamera} {
+            # If this is the first Rebuild, we need to
+            # set up the initial view settings if there
+            # are any
+            if { [info exists _mapsettings(camera)] } {
+                set location $_mapsettings(camera)
+                if { $location != "" } {
+                    array set _view $location
+                    camera set all
+                }
+            }
+            set _initCamera 0
+        } else {
+            # Restore view from before reconnect
+            camera set all
+        }
+    }
+
+    UpdateLayerControls
+    set _reset 0
+    global readyForNextFrame
+    set readyForNextFrame 0;            # Don't advance to the next frame
+                                        # until we get an image.
+
+    # Actually write the commands to the server socket.  If it fails, we
+    # don't care.  We're finished here.
+    blt::busy hold $itk_component(hull)
+    StopBufferingCommands
+    blt::busy release $itk_component(hull)
+}
+
+# ----------------------------------------------------------------------
+# USAGE: CurrentLayers ?-all -visible? ?dataobjs?
+#
+# Returns a list of server IDs for the current datasets being displayed.
+# This is normally a single ID, but it might be a list of IDs if the
+# current data object has multiple components.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::CurrentLayers {args} {
+    set flag [lindex $args 0]
+    switch -- $flag { 
+        "-all" {
+            if { [llength $args] > 1 } {
+                error "CurrentLayers: can't specify dataobj after \"-all\""
+            }
+            set dlist [get -objects]
+        }
+        "-visible" {
+            if { [llength $args] > 1 } {
+                set dlist {}
+                set args [lrange $args 1 end]
+                foreach dataobj $args {
+                    if { [info exists _obj2ovride($dataobj-raise)] } {
+                        lappend dlist $dataobj
+                    }
+                }
+            } else {
+                set dlist [get -visible]
+            }
+        }           
+        default {
+            set dlist $args
+        }
+    }
+    set rlist ""
+    foreach dataobj $dlist {
+        foreach layer [$dataobj layers] {
+            if { [info exists _layers($layer)] && $_layers($layer) } {
+                lappend rlist $layer
+            }
+        }
+    }
+    return $rlist
+}
+
+itcl::body Rappture::MapViewer::KeyPress {k} {
+    SendCmd "key press $k"
+}
+
+itcl::body Rappture::MapViewer::KeyRelease {k} {
+    SendCmd "key release $k"
+}
+
+itcl::body Rappture::MapViewer::GetNormalizedMouse {x y} {
+    set w [winfo width $itk_component(view)]
+    set h [winfo height $itk_component(view)]
+    set x [expr {(2.0 * double($x)/$w) - 1.0}]
+    set y [expr {(2.0 * double($y)/$h) - 1.0}]
+    return [list $x $y]
+}
+
+itcl::body Rappture::MapViewer::MouseClick {button x y} {
+    SendCmd "mouse click $button $x $y"
+}
+
+itcl::body Rappture::MapViewer::MouseDoubleClick {button x y} {
+    SendCmd "mouse dblclick $button $x $y"
+}
+
+itcl::body Rappture::MapViewer::MouseDrag {button x y} {
+    SendCmd "mouse drag $button $x $y"
+}
+
+itcl::body Rappture::MapViewer::MouseRelease {button x y} {
+    SendCmd "mouse release $button $x $y"
+}
+
+itcl::body Rappture::MapViewer::MouseMotion {} {
+    SendCmd "mouse motion $_motion(x) $_motion(y)"
+    set _motion(pending) 0
+}
+
+itcl::body Rappture::MapViewer::MouseScroll {direction} {
+    switch -- $direction {
+        "up" {
+            SendCmd "mouse scroll 1"
+        }
+        "down" {
+            SendCmd "mouse scroll -1"
+        }
+    }
+}
+
+#
+# EventuallyHandleMotionEvent --
+#
+#       This routine compresses (no button press) motion events.  It
+#       delivers a server mouse command once every 100 milliseconds (if a
+#       motion event is pending).
+#
+itcl::body Rappture::MapViewer::EventuallyHandleMotionEvent {x y} {
+    set _motion(x) $x
+    set _motion(y) $y
+    if { !$_motion(compress) } {
+        MouseMotion
+        return
+    }
+    if { !$_motion(pending) } {
+        set _motion(pending) 1
+        $_dispatcher event -after $_motion(delay) !motion
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: Zoom in
+# USAGE: Zoom out
+# USAGE: Zoom reset
+#        $this Zoom click x y
+#        $this Zoom drag x y
+#        $this Zoom release x y
+#
+# Called automatically when the user clicks on one of the zoom
+# controls for this widget.  Changes the zoom for the current view.
+# Also implements mouse zoom.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::Zoom {option {x 0} {y 0}} {
+    switch -- $option {
+        "in" {
+            # z here is normalized mouse Y delta
+            set z -0.25
+            SendCmd "camera zoom $z"
+        }
+        "out" {
+            # z here is normalized mouse Y delta
+            set z 0.25
+            SendCmd "camera zoom $z"
+        }
+        "reset" {
+            SendCmd "camera dist $_view(distance)"
+        }
+        "click" {
+            set _click(x) $x
+            set _click(y) $y
+            $itk_component(view) configure -cursor hand1
+        }
+        "drag" {
+            if { ![info exists _click(x)] } {
+                set _click(x) $x
+            }
+            if { ![info exists _click(y)] } {
+                set _click(y) $y
+            }
+            set h [winfo height $itk_component(view)]
+            set dy [expr ($_click(y) - $y)/double($h)]
+            set _click(x) $x
+            set _click(y) $y
+            if {[expr (abs($dy) > 0.0)]} {
+                SendCmd "camera zoom $dy"
+            }
+        }
+        "release" {
+            Zoom drag $x $y
+            $itk_component(view) configure -cursor ""
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: Rotate click <x> <y>
+# USAGE: Rotate drag <x> <y>
+# USAGE: Rotate release <x> <y>
+#
+# Called automatically when the user clicks/drags/releases in the
+# plot area.  Moves the plot according to the user's actions.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::Rotate {option x y} {
+    switch -- $option {
+        "click" {
+            $itk_component(view) configure -cursor fleur
+            set _click(x) $x
+            set _click(y) $y
+        }
+        "drag" {
+            if {[array size _click] == 0} {
+                Rotate click $x $y
+            } else {
+                set w [winfo width $itk_component(view)]
+                set h [winfo height $itk_component(view)]
+                if {$w <= 0 || $h <= 0} {
+                    return
+                }
+                set dx [expr ($x - $_click(x))/double($w)]
+                set dy [expr ($_click(y) - $y)/double($h)]
+                set _click(x) $x
+                set _click(y) $y
+                if {[expr (abs($dx) > 0.0 || abs($dy) > 0.0)]} {
+                    SendCmd "camera rotate $dx $dy"
+                    #EventuallyRotate $dx $dy
+                }
+            }
+        }
+        "release" {
+            Rotate drag $x $y
+            $itk_component(view) configure -cursor ""
+            catch {unset _click}
+        }
+        default {
+            error "bad option \"$option\": should be click, drag, release"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: $this Pan set x y
+#        $this Pan click x y
+#        $this Pan drag x y
+#        $this Pan release x y
+#
+# Called automatically when the user clicks on one of the zoom
+# controls for this widget.  Changes the zoom for the current view.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::Pan {option x y} {
+    switch -- $option {
+        "set" {
+            set w [winfo width $itk_component(view)]
+            set h [winfo height $itk_component(view)]
+            set x [expr $x / double($w)]
+            set y [expr $y / double($h)]
+            if {[expr (abs($x) > 0.0 || abs($y) > 0.0)]} {
+                SendCmd "camera pan $x $y"
+            }
+            return
+        }
+        "click" {
+            set _click(x) $x
+            set _click(y) $y
+            $itk_component(view) configure -cursor hand1
+        }
+        "drag" {
+            if { ![info exists _click(x)] } {
+                set _click(x) $x
+            }
+            if { ![info exists _click(y)] } {
+                set _click(y) $y
+            }
+            set w [winfo width $itk_component(view)]
+            set h [winfo height $itk_component(view)]
+            set dx [expr ($x - $_click(x))/double($w)]
+            set dy [expr ($_click(y) - $y)/double($h)]
+            set _click(x) $x
+            set _click(y) $y
+            if {[expr (abs($dx) > 0.0 || abs($dy) > 0.0)]} {
+                SendCmd "camera pan $dx $dy"
+            }
+        }
+        "release" {
+            Pan drag $x $y
+            $itk_component(view) configure -cursor ""
+        }
+        default {
+            error "unknown option \"$option\": should set, click, drag, or release"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: InitSettings <what> ?<value>?
+#
+# Used internally to update rendering settings whenever parameters
+# change in the popup settings panel.  Sends the new settings off
+# to the back end.
+# ----------------------------------------------------------------------
+itcl::body Rappture::MapViewer::InitSettings { args } {
+    foreach setting $args {
+        AdjustSetting $setting
+    }
+}
+
+#
+# AdjustSetting --
+#
+#       Changes/updates a specific setting in the widget.  There are
+#       usually user-setable option.  Commands are sent to the render
+#       server.
+#
+itcl::body Rappture::MapViewer::AdjustSetting {what {value ""}} {
+    if { ![isconnected] } {
+        return
+    }
+    switch -- $what {
+        "coords-visible" - "coords-precision" - "coords-units" {
+            set bool $_settings(coords-visible)
+            set units $_settings(coords-units)
+            set precision $_settings(coords-precision)
+            SendCmd "map posdisp $bool $units $precision"
+        }
+        "grid" - "grid-type" {
+            set bool $_settings(grid)
+            set gridType $_settings(grid-type)
+            SendCmd "map grid $bool $gridType"
+        }
+        "camera-throw" {
+            set bool $_settings($what)
+            SendCmd "camera throw $bool"
+        }
+        "terrain-edges" {
+            set bool $_settings($what)
+            SendCmd "map terrain edges $bool"
+        }
+        "terrain-lighting" {
+            set bool $_settings($what)
+            SendCmd "map terrain lighting $bool"
+        }
+        "terrain-palette" {
+            set cmap [$itk_component(terrainpalette) value]
+            #SendCmd "map terrain colormap $cmap"
+        }
+        "terrain-vertscale" {
+            set val $_settings($what)
+            SendCmd "map terrain vertscale $val"
+        }
+        "terrain-wireframe" {
+            set bool $_settings($what)
+            SendCmd "map terrain wireframe $bool"
+        }
+        default {
+            error "don't know how to fix $what"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTION: -plotbackground
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::MapViewer::plotbackground {
+    if { [isconnected] } {
+        foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
+        SendCmd "screen bgcolor $r $g $b"
+    }
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTION: -plotforeground
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::MapViewer::plotforeground {
+    if { [isconnected] } {
+        foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
+        #fix this!
+        #SendCmd "color background $r $g $b"
+    }
+}
+
+itcl::body Rappture::MapViewer::limits { dataobj } {
+    error "no limits"
+}
+
+itcl::body Rappture::MapViewer::BuildTerrainTab {} {
+
+    set fg [option get $itk_component(hull) font Font]
+    #set bfg [option get $itk_component(hull) boldFont Font]
+
+    set inner [$itk_component(main) insert end \
+        -title "Terrain Settings" \
+        -icon [Rappture::icon surface]]
+    $inner configure -borderwidth 4
+
+    checkbutton $inner.posdisp \
+        -text "Show Coordinate Readout" \
+        -variable [itcl::scope _settings(coords-visible)] \
+        -command [itcl::code $this AdjustSetting coords-visible] \
+        -font "Arial 9" -anchor w 
+
+    checkbutton $inner.grid \
+        -text "Show Graticule" \
+        -variable [itcl::scope _settings(grid)] \
+        -command [itcl::code $this AdjustSetting grid] \
+        -font "Arial 9" -anchor w 
+
+    checkbutton $inner.wireframe \
+        -text "Show Wireframe" \
+        -variable [itcl::scope _settings(terrain-wireframe)] \
+        -command [itcl::code $this AdjustSetting terrain-wireframe] \
+        -font "Arial 9" -anchor w 
+
+    checkbutton $inner.lighting \
+        -text "Enable Lighting" \
+        -variable [itcl::scope _settings(terrain-lighting)] \
+        -command [itcl::code $this AdjustSetting terrain-lighting] \
+        -font "Arial 9" -anchor w
+
+    checkbutton $inner.edges \
+        -text "Show Edges" \
+        -variable [itcl::scope _settings(terrain-edges)] \
+        -command [itcl::code $this AdjustSetting terrain-edges] \
+        -font "Arial 9" -anchor w
+
+    label $inner.palette_l -text "Palette" -font "Arial 9" -anchor w 
+    itk_component add terrainpalette {
+        Rappture::Combobox $inner.palette -width 10 -editable no
+    }
+    $inner.palette choices insert end [GetColormapList]
+
+    $itk_component(terrainpalette) value "BCGYR"
+    bind $inner.palette <<Value>> \
+        [itcl::code $this AdjustSetting terrain-palette]
+
+    label $inner.vscale_l -text "Vertical Scale" -font "Arial 9" -anchor w 
+    ::scale $inner.vscale -from 0 -to 10 -orient horizontal \
+        -variable [itcl::scope _settings(terrain-vertscale)] \
+        -width 10 \
+        -resolution 0.1 \
+        -showvalue on \
+        -command [itcl::code $this AdjustSetting terrain-vertscale]
+    $inner.vscale set $_settings(terrain-vertscale)
+
+    blt::table $inner \
+        0,0 $inner.posdisp   -cspan 2  -anchor w -pady 2 \
+        1,0 $inner.grid      -cspan 2  -anchor w -pady 2 \
+        2,0 $inner.wireframe -cspan 2  -anchor w -pady 2 \
+        3,0 $inner.lighting  -cspan 2  -anchor w -pady 2 \
+        4,0 $inner.edges     -cspan 2  -anchor w -pady 2 \
+        5,0 $inner.vscale_l  -anchor w -pady 2 \
+        5,1 $inner.vscale    -fill x   -pady 2 \
+        6,0 $inner.palette_l -anchor w -pady 2 \
+        6,1 $inner.palette   -fill x   -pady 2  
+
+    blt::table configure $inner r* c* -resize none
+    blt::table configure $inner r8 c1 -resize expand
+}
+
+itcl::body Rappture::MapViewer::BuildLayerTab {} {
+
+    set fg [option get $itk_component(hull) font Font]
+    #set bfg [option get $itk_component(hull) boldFont Font]
+
+    set inner [$itk_component(main) insert end \
+        -title "Layers" \
+        -icon [Rappture::icon layers]]
+    $inner configure -borderwidth 4
+    set f [frame $inner.layers]
+    blt::table $inner \
+        0,0 $f -fill both 
+    set _layersFrame $inner
+}
+
+itcl::body Rappture::MapViewer::BuildCameraTab {} {
+    set inner [$itk_component(main) insert end \
+        -title "Camera Settings" \
+        -icon [Rappture::icon camera]]
+    $inner configure -borderwidth 4
+
+    set row 0
+
+    set labels { x y z heading pitch distance }
+    foreach tag $labels {
+        label $inner.${tag}label -text $tag -font "Arial 9"
+        entry $inner.${tag} -font "Arial 9"  -bg white \
+            -textvariable [itcl::scope _view($tag)]
+        bind $inner.${tag} <KeyPress-Return> \
+            [itcl::code $this camera set ${tag}]
+        bind $inner.${tag} <KP_Enter> \
+            [itcl::code $this camera set ${tag}]
+        blt::table $inner \
+            $row,0 $inner.${tag}label -anchor e -pady 2 \
+            $row,1 $inner.${tag} -anchor w -pady 2
+        blt::table configure $inner r$row -resize none
+        incr row
+    }
+    set labels { srs verticalDatum }
+    foreach tag $labels {
+        label $inner.${tag}label -text $tag -font "Arial 9"
+        entry $inner.${tag} -font "Arial 9"  -bg white \
+            -textvariable [itcl::scope _view($tag)]
+        bind $inner.${tag} <KeyPress-Return> \
+            [itcl::code $this camera set ${tag}]
+        bind $inner.${tag} <KP_Enter> \
+            [itcl::code $this camera set ${tag}]
+        blt::table $inner \
+            $row,0 $inner.${tag}label -anchor e -pady 2 \
+            $row,1 $inner.${tag} -anchor w -pady 2
+        blt::table configure $inner r$row -resize none
+        incr row
+    }
+
+    if {0} {
+    button $inner.get \
+        -text "Get Camera Settings" \
+        -font "Arial 9" \
+        -command [itcl::code $this SendCmd "camera get"]
+    blt::table $inner \
+        $row,0 $inner.get -anchor w -pady 2 -cspan 2
+    blt::table configure $inner r$row -resize none
+    incr row
+
+    button $inner.set \
+        -text "Apply Camera Settings" \
+        -font "Arial 9" \
+        -command [itcl::code $this camera set all]
+    blt::table $inner \
+        $row,0 $inner.set -anchor w -pady 2 -cspan 2
+    blt::table configure $inner r$row -resize none
+    incr row
+    }
+
+    if {$_useServerManip} {
+        checkbutton $inner.throw \
+            -text "Enable Throw" \
+            -font "Arial 9" \
+            -variable [itcl::scope _settings(camera-throw)] \
+            -command [itcl::code $this AdjustSetting camera-throw]
+        blt::table $inner \
+            $row,0 $inner.throw -anchor w -pady 2 -cspan 2
+        blt::table configure $inner r$row -resize none
+        incr row
+    }
+
+    blt::table configure $inner c* r* -resize none
+    blt::table configure $inner c2 -resize expand
+    blt::table configure $inner r$row -resize expand
+}
+
+#
+#  camera -- 
+#
+# USAGE: camera get
+#        This is called by the server to transfer the
+#        current Viewpoint settings
+# USAGE: camera reset
+#        Reset the camera to the default view
+#
+itcl::body Rappture::MapViewer::camera {option args} {
+    switch -- $option { 
+        "get" {
+            # We got the camera settings from the server
+            foreach name {x y z heading pitch distance srs verticalDatum} value $args {
+                set _view($name) $value
+            }
+            puts stderr "view: $_view(x), $_view(y), $_view(z), $_view(heading), $_view(pitch), $_view(distance), $_view(srs), $_view(verticalDatum)"
+        }
+        "go" {
+            SendCmd "camera go $args"
+        }
+        "reset" {
+            array set _view {
+                x               0.0
+                y               0.0
+                z               0.0
+                heading         0.0
+                pitch           -89.9
+                distance        1.0
+                srs             ""
+                verticalDatum   ""
+            }
+            if { [info exists _mapsettings(camera)] } {
+                # Check if the tool specified a default
+                set location $_mapsettings(camera)
+                if { $location != "" } {
+                    array set _view $location
+                    set duration 0.0
+                    SendCmd [list camera set $_view(x) $_view(y) $_view(z) $_view(heading) $_view(pitch) $_view(distance) $duration $_view(srs) $_view(verticalDatum)]
+                } else {
+                    SendCmd "camera reset"
+                    # Retrieve the settings
+                    #SendCmd "camera get"
+                }
+            } else {
+                SendCmd "camera reset"
+                # Retrieve the settings
+               # SendCmd "camera get"
+            }
+        }
+        "set" {
+            set who [lindex $args 0]
+            if {$who != "all" && $who != "srs" && $who != "verticalDatum"} {
+                set val $_view($who)
+                set code [catch { string is double $val } result]
+                if { $code != 0 || !$result } {
+                    return
+                }
+            }
+            switch -- $who {
+                "distance" {
+                    SendCmd [list camera dist $_view(distance)]
+                }
+                "all" - "x" - "y" - "z" - "heading" - "pitch" - "srs" - "verticalDatum" {
+                    set duration 0.0
+                    SendCmd [list camera set $_view(x) $_view(y) $_view(z) $_view(heading) $_view(pitch) $_view(distance) $duration $_view(srs) $_view(verticalDatum)]
+                }
+            }
+        }
+    }
+}
+
+itcl::body Rappture::MapViewer::GetImage { args } {
+    if { [image width $_image(download)] > 0 && 
+         [image height $_image(download)] > 0 } {
+        set bytes [$_image(download) data -format "jpeg -quality 100"]
+        set bytes [Rappture::encoding::decode -as b64 $bytes]
+        return [list .jpg $bytes]
+    }
+    return ""
+}
+
+itcl::body Rappture::MapViewer::BuildDownloadPopup { popup command } {
+    Rappture::Balloon $popup \
+        -title "[Rappture::filexfer::label downloadWord] as..."
+    set inner [$popup component inner]
+    label $inner.summary -text "" -anchor w 
+
+    radiobutton $inner.image_button -text "Image File" \
+        -variable [itcl::scope _downloadPopup(format)] \
+        -value image 
+    Rappture::Tooltip::for $inner.image_button \
+        "Save as digital image."
+
+    button $inner.ok -text "Save" \
+        -highlightthickness 0 -pady 2 -padx 3 \
+        -command $command \
+        -compound left \
+        -image [Rappture::icon download]
+
+    button $inner.cancel -text "Cancel" \
+        -highlightthickness 0 -pady 2 -padx 3 \
+        -command [list $popup deactivate] \
+        -compound left \
+        -image [Rappture::icon cancel]
+
+    blt::table $inner \
+        0,0 $inner.summary -cspan 2  \
+        2,0 $inner.image_button -anchor w -cspan 2 -padx { 4 0 } \
+        4,1 $inner.cancel -width .9i -fill y \
+        4,0 $inner.ok -padx 2 -width .9i -fill y 
+    blt::table configure $inner r3 -height 4
+    blt::table configure $inner r4 -pady 4
+    raise $inner.image_button
+    $inner.image_button invoke
+    return $inner
+}
+
+itcl::body Rappture::MapViewer::SetTerrainStyle { style } {
+    array set settings {
+        -color white
+        -edgecolor black
+        -edges 0
+        -lighting 0
+        -linewidth 1.0
+        -vertscale 1.0
+        -wireframe 0
+    }
+    array set settings $style
+
+    SendCmd "map terrain edges $settings(-edges)"
+    set _settings(terrain-edges) $settings(-edges)
+    #SendCmd "map terrain color [Color2RGB $settings(-color)]"
+    #SendCmd "map terrain colormode constant"
+    SendCmd "map terrain lighting $settings(-lighting)"
+    set _settings(terrain-lighting) $settings(-lighting)
+    SendCmd "map terrain linecolor [Color2RGB $settings(-edgecolor)]"
+    #SendCmd "map terrain linewidth $settings(-linewidth)"
+    SendCmd "map terrain vertscale $settings(-vertscale)"
+    set _settings(terrain-vertscale) $settings(-vertscale)
+    SendCmd "map terrain wireframe $settings(-wireframe)"
+    set _settings(terrain-wireframe) $settings(-wireframe)
+}
+
+itcl::body Rappture::MapViewer::SetLayerStyle { dataobj layer } {
+    array set info [$dataobj layer $layer]
+    set _visibility($layer) 1
+
+    switch -- $info(type) {
+        "image" {
+            array set settings {
+                -min_level 0
+                -max_level 23
+                -opacity 1.0
+            }
+            if { [info exists info(style)] } {
+                array set settings $info(style)
+            }
+            if { [info exists info(opacity)] } {
+                set settings(-opacity) $info(opacity)
+            }
+            if {!$_sendEarthFile} {
+                switch -- $info(driver)  {
+                    "debug" {
+                        SendCmd [list map layer add image debug $layer]
+                    }
+                    "gdal" {
+                        SendCmd [list map layer add image gdal \
+                                     $info(gdal.url) $layer]
+                    }
+                    "tms" {
+                        SendCmd [list map layer add image tms \
+                                     $info(tms.url) $layer]
+                    }
+                    "wms" {
+                        SendCmd [list map layer add image wms \
+                                     $info(wms.url) \
+                                     $info(wms.layers) \
+                                     $info(wms.format) \
+                                     $info(wms.transparent) \
+                                     $layer]
+                    }
+                    "xyz" {
+                        SendCmd [list map layer add image xyz \
+                                     $info(xyz.url) \
+                                     $layer]
+                    }
+                }                        
+            }
+            SendCmd "map layer opacity $settings(-opacity) $layer"
+        }
+        "elevation" {
+            array set settings {
+                -min_level 0
+                -max_level 23
+            }
+            if { [info exists info(style)] } {
+                array set settings $info(style)
+            }
+            if {!$_sendEarthFile} {
+                switch -- $info(driver)  {
+                    "gdal" {
+                        SendCmd [list map layer add elevation gdal \
+                                     $info(gdal.url) $layer]
+                    }
+                    "tms" {
+                        SendCmd [list map layer add elevation tms \
+                                     $info(tms.url) $layer]
+                    }
+                }
+            }
+        }
+        "line" {
+            array set settings {
+                -color black
+                -minbias 1000
+                -opacity 1.0
+                -width 1
+            }
+            if { [info exists info(style)] } {
+                array set settings $info(style)
+            }
+            if { [info exists info(opacity)] } {
+                set settings(-opacity) $info(opacity)
+            }
+            SendCmd [list map layer add line $info(ogr.url) $layer]
+            SendCmd "map layer opacity $settings(-opacity) $layer"
+        }
+        "polygon" {
+            array set settings {
+                -color white
+                -minbias 1000
+                -opacity 1.0
+            }
+            if { [info exists info(style)] } {
+                array set settings $info(style)
+            }
+            if { [info exists info(opacity)] } {
+                set settings(-opacity) $info(opacity)
+            }
+            SendCmd [list map layer add polygon $info(ogr.url) $layer]
+            SendCmd "map layer opacity $settings(-opacity) $layer"
+        }
+        "label" {
+            array set settings {
+                -align "center-center"
+                -color black
+                -declutter 1
+                -font Arial
+                -fontsize 16.0
+                -halocolor white
+                -halowidth 2.0
+                -layout "ltr"
+                -minbias 1000
+                -opacity 1.0
+                -removedupe 1
+            }
+            if { [info exists info(style)] } {
+                array set settings $info(style)
+            }
+            if { [info exists info(opacity)] } {
+                set settings(-opacity) $info(opacity)
+            }
+            set contentExpr $info(content)
+            if {[info exists info(priority)]} {
+                set priorityExpr $info(priority)
+            } else {
+                set priorityExpr ""
+            }
+            SendCmd [list map layer add text $info(ogr.url) $contentExpr $priorityExpr $layer]
+            SendCmd "map layer opacity $settings(-opacity) $layer"
+        }
+    }
+
+    if { [info exists info(visible)] } {
+        if { !$info(visible) } {
+            set _visibility($layer) 0
+            SendCmd "map layer visible 0 $layer"
+        }
+    }
+}
+
+itcl::body Rappture::MapViewer::SetOpacity { dataset } { 
+    foreach {dataobj layer} [split $dataset -] break
+    set type [$dataobj type $layer]
+    set val $_settings(-opacity)
+    set sval [expr { 0.01 * double($val) }]
+    if { !$_obj2ovride($dataobj-raise) } {
+        # This is wrong.  Need to figure out why raise isn't set with 1
+        #set sval [expr $sval * .6]
+    }
+    SendCmd "$type opacity $sval $dataset"
+}
+
+itcl::body Rappture::MapViewer::ChangeLayerVisibility { dataobj layer } { 
+    set bool $_visibility($layer)
+    SendCmd "map layer visible $bool $layer"
+}
+
+itcl::body Rappture::MapViewer::UpdateLayerControls {} { 
+    set row 0
+    set inner $_layersFrame
+    if { [winfo exists $inner.layers] } {
+        foreach w [winfo children $inner.layers] {
+            destroy $w
+        }
+    }
+    set f $inner.layers
+    foreach dataobj [get -objects] {
+        foreach layer [$dataobj layers] {
+	    array unset info
+	    array set info [$dataobj layer $layer]
+            checkbutton $f.$layer \
+                -text $info(label) \
+                -variable [itcl::scope _visibility($layer)] \
+                -command [itcl::code $this \
+                              ChangeLayerVisibility $dataobj $layer] \
+		    -font "Arial 9" -anchor w 
+            blt::table $f $row,0 $f.$layer -anchor w -pady 2 
+            Rappture::Tooltip::for $f.$layer $info(description)
+            incr row
+	}
+    }
+    if { $row > 0 } {
+        blt::table configure $f r* c* -resize none
+        blt::table configure $f r$row c1 -resize expand
+    }
+}
+
+#
+# Generate an OSG Earth file to send to server.  This is inteneded
+# as a stopgap and testing tool until the protocol is fleshed out.
+# 
+# Note that the lighting settings are required to be "hard-coded"
+# as below for the runtime control to work.  Don't make those user
+# configurable.
+#
+# Also note: Use "true"/"false" for boolean settings.  Not sure if
+# the parser in OSG Earth accepts all of Tcl's forms of boolean vals.
+#
+itcl::body Rappture::MapViewer::EarthFile {} { 
+    append out "<map"
+    append out " name=\"$_mapsettings(label)\""
+    append out " type=\"$_mapsettings(type)\""
+    append out " version=\"2\""
+    append out ">\n"
+    append out " <options lighting=\"true\">\n"
+    # FIXME: convert color setting to hex
+    # array set style $_mapsettings(style)
+    # if {[info exists style(-color)]} {
+    #     set color "?"
+    # }
+    set color "#ffffffff"
+    append out "  <terrain lighting=\"false\" color=\"$color\"/>\n"
+    if { [info exists _mapsettings(projection)] } {
+        append out "  <profile"
+        append out " srs=\"$_mapsettings(projection)\""
+        if { [info exists _mapsettings(extents)] } {
+            append out " xmin=\"$_mapsettings(x1)\""
+            append out " ymin=\"$_mapsettings(y1)\""
+            append out " xmax=\"$_mapsettings(x2)\""
+            append out " ymax=\"$_mapsettings(y2)\""
+        }
+        append out "/>\n"
+    }
+    append out " </options>\n"
+
+    foreach dataobj [get -objects] {
+        foreach layer [$dataobj layers] {
+            set _layers($layer) 1
+            array unset info
+            array set info [$dataobj layer $layer]
+            switch -- $info(type) {
+                "image" {
+                    append out " <image"
+                    append out " name=\"$layer\""
+                    append out " driver=\"gdal\""
+                    if { [info exists info(opacity)] } {
+                        append out " opacity=\"$info(opacity)\""
+                    }
+                    if { $info(visible) } {
+                        append out " visible=\"true\""
+                    } else {
+                        append out " visible=\"false\""
+                    }
+                    append out ">\n"
+                    append out "  <url>$info(url)</url>\n"
+                    append out " </image>\n"
+                }
+                "elevation" {
+                    append out " <elevation"
+                    append out " name=\"$layer\""
+                    append out " driver=\"gdal\""
+                    if { $info(visible) } {
+                        append out " visible=\"true\""
+                    } else {
+                        append out " visible=\"false\""
+                    }
+                    append out ">\n"
+                    append out "  <url>$info(url)</url>\n"
+                    append out " </elevation>\n"
+                }
+                default {
+                    puts stderr "Type $info(type) not implemented in MapViewer::EarthFile"
+                }
+            }
+        }
+    }
+    append out "</map>\n"
+    return $out
+} 
Index: branches/1.3/gui/scripts/mesh.tcl
===================================================================
--- branches/1.3/gui/scripts/mesh.tcl	(revision 4511)
+++ branches/1.3/gui/scripts/mesh.tcl	(revision 4512)
@@ -85,4 +85,8 @@
     private method WriteTriangles { path xv yv zv triangles }
     private method WriteQuads { path xv yv zv quads }
+    private method WriteVertices { path xv yv zv vertices }
+    private method WriteLines { path xv yv zv lines }
+    private method WritePolygons { path xv yv zv polygons }
+    private method WriteTriangleStrips { path xv yv zv trianglestrips }
     private method WriteTetrahedrons { path xv yv zv tetrahedrons }
     private method WriteHexahedrons { path xv yv zv hexhedrons }
@@ -860,4 +864,140 @@
 }
 
+itcl::body Rappture::Mesh::WriteVertices { path xv yv zv vertices } {
+    set _type "vertices"
+    set _numPoints [$xv length]
+    set _numCells 0
+    set data {}
+    set lines [split $vertices \n]
+    set count 0
+    foreach { line } $lines {
+        set numIndices [llength $line]
+        if { $numIndices == 0 } {
+            continue
+        }
+	append data " $numIndices $line\n"
+	incr _numCells
+        set count [expr $count + $numIndices + 1]
+    }
+    append out "DATASET POLYDATA\n"
+    append out "POINTS $_numPoints double\n"
+    foreach x [$xv range 0 end] y [$yv range 0 end] z [$zv range 0 end] {
+	append out " $x $y $z\n"
+    }
+    append out "VERTICES $_numCells $count\n"
+    append out $data
+    set _limits(x) [$xv limits]
+    set _limits(y) [$yv limits]
+    if { $_dim == 3 } {
+        set _limits(z) [$zv limits]
+    } else {
+        set _limits(z) [list 0 0]
+    }
+    set _vtkdata $out
+    return 1
+}
+
+itcl::body Rappture::Mesh::WriteLines { path xv yv zv polylines } {
+    set _type "lines"
+    set _numPoints [$xv length]
+    set _numCells 0
+    set data {}
+    set lines [split $polylines \n]
+    set count 0
+    foreach { line } $lines {
+        set numIndices [llength $line]
+        if { $numIndices == 0 } {
+            continue
+        }
+	append data " $numIndices $line\n"
+	incr _numCells
+        set count [expr $count + $numIndices + 1]
+    }
+    append out "DATASET POLYDATA\n"
+    append out "POINTS $_numPoints double\n"
+    foreach x [$xv range 0 end] y [$yv range 0 end] z [$zv range 0 end] {
+	append out " $x $y $z\n"
+    }
+    append out "LINES $_numCells $count\n"
+    append out $data
+    set _limits(x) [$xv limits]
+    set _limits(y) [$yv limits]
+    if { $_dim == 3 } {
+        set _limits(z) [$zv limits]
+    } else {
+        set _limits(z) [list 0 0]
+    }
+    set _vtkdata $out
+    return 1
+}
+
+itcl::body Rappture::Mesh::WritePolygons { path xv yv zv polygons } {
+    set _type "polygons"
+    set _numPoints [$xv length]
+    set _numCells 0
+    set data {}
+    set lines [split $polygons \n]
+    set count 0
+    foreach { line } $lines {
+        set numIndices [llength $line]
+        if { $numIndices == 0 } {
+            continue
+        }
+	append data " $numIndices $line\n"
+	incr _numCells
+        set count [expr $count + $numIndices + 1]
+    }
+    append out "DATASET POLYDATA\n"
+    append out "POINTS $_numPoints double\n"
+    foreach x [$xv range 0 end] y [$yv range 0 end] z [$zv range 0 end] {
+	append out " $x $y $z\n"
+    }
+    append out "POLYGONS $_numCells $count\n"
+    append out $data
+    set _limits(x) [$xv limits]
+    set _limits(y) [$yv limits]
+    if { $_dim == 3 } {
+        set _limits(z) [$zv limits]
+    } else {
+        set _limits(z) [list 0 0]
+    }
+    set _vtkdata $out
+    return 1
+}
+
+itcl::body Rappture::Mesh::WriteTriangleStrips { path xv yv zv trianglestrips } {
+    set _type "trianglestrips"
+    set _numPoints [$xv length]
+    set _numCells 0
+    set data {}
+    set lines [split $trianglestrips \n]
+    set count 0
+    foreach { line } $lines {
+        set numIndices [llength $line]
+        if { $numIndices == 0 } {
+            continue
+        }
+	append data " $numIndices $line\n"
+	incr _numCells
+        set count [expr $count + $numIndices + 1]
+    }
+    append out "DATASET POLYDATA\n"
+    append out "POINTS $_numPoints double\n"
+    foreach x [$xv range 0 end] y [$yv range 0 end] z [$zv range 0 end] {
+	append out " $x $y $z\n"
+    }
+    append out "TRIANGLE_STRIPS $_numCells $count\n"
+    append out $data
+    set _limits(x) [$xv limits]
+    set _limits(y) [$yv limits]
+    if { $_dim == 3 } {
+        set _limits(z) [$zv limits]
+    } else {
+        set _limits(z) [list 0 0]
+    }
+    set _vtkdata $out
+    return 1
+}
+
 itcl::body Rappture::Mesh::WriteTetrahedrons { path xv yv zv tetras } {
     set _type "tetrahedrons"
@@ -1040,6 +1180,17 @@
     # Step 1: Verify that there's only one cell tag of any kind.
     set numCells 0
-    foreach type { cells triangles quads tetrahedrons 
-        hexahedrons wedges pyramids } {
+    foreach type { 
+        cells
+        hexahedrons 
+        lines 
+        polygons 
+        pyramids 
+        quads
+        tetrahedrons 
+        triangles 
+        trianglestrips
+        vertices 
+        wedges 
+    } {
         set data [$_xmlobj get $path.unstructured.$type]
         if { $data != "" } {
@@ -1057,6 +1208,8 @@
         return 0
     }
-    foreach type { cells triangles quads tetrahedrons 
-        hexahedrons wedges pyramids } {
+    foreach type { cells
+        vertices lines polygons trianglestrips
+        triangles quads
+        tetrahedrons hexahedrons wedges pyramids } {
         set data [$_xmlobj get $path.unstructured.$type]
         if { $data != "" } {
@@ -1299,10 +1452,20 @@
 itcl::body Rappture::Mesh::GetCellType { name } {
     array set name2type {
-        "triangle"     5
-        "quad"         9
-        "tetrahedron"  10
-        "hexahedron"   12
-        "wedge"        13
-        "pyramid"      14
+        "vertex"          1
+        "polyvertex"      2
+        "line"            3
+        "polyline"        4
+        "triangle"        5
+        "trianglestrip"   6
+        "polygon"         7
+        "pixel"           8
+        "quad"            9
+        "tetrahedron"     10
+        "voxel"           11
+        "hexahedron"      12
+        "wedge"           13
+        "pyramid"         14
+        "pentagonalprism" 15
+        "hexagonalprism"  16
     }
     if { [info exists name2type($name)] } {
@@ -1331,6 +1494,6 @@
         13      6
         14      5
-        15      0
-        16      0
+        15      10
+        16      12
     }
     if { [info exists type2indices($type)] } {
Index: branches/1.3/gui/scripts/resultviewer.tcl
===================================================================
--- branches/1.3/gui/scripts/resultviewer.tcl	(revision 4511)
+++ branches/1.3/gui/scripts/resultviewer.tcl	(revision 4512)
@@ -293,4 +293,16 @@
             }
         }
+        ::Rappture::Map {
+            if { ![$dataobj isvalid] } {
+                return;                 # Ignore invalid map objects.
+            }
+            set mode "map"
+            if {![info exists _mode2widget($mode)]} {
+                set servers [Rappture::VisViewer::GetServerList "geovis"]
+                set w $itk_interior.$mode
+                Rappture::MapViewer $w $servers
+                set _mode2widget($mode) $w
+            }
+        }
         ::Rappture::Field {
             if { ![$dataobj isvalid] } {
@@ -481,4 +493,7 @@
             set dobj [Rappture::Field ::#auto $xmlobj $path]
         }
+        map {
+            set dobj [Rappture::Map ::#auto $xmlobj $path]
+        }
         mesh {
             set dobj [Rappture::Mesh ::#auto $xmlobj $path]
Index: branches/1.3/gui/scripts/tuples.tcl
===================================================================
--- branches/1.3/gui/scripts/tuples.tcl	(revision 4511)
+++ branches/1.3/gui/scripts/tuples.tcl	(revision 4512)
@@ -70,4 +70,14 @@
                 value -default ""
             }
+
+            # FIXME: This is a band-aid.  The value can be an arbitrary
+            # string and therefore misinterpretered as an invalid list.
+            # Try to parse the value as a list and if that fails make a
+            # list out of it.  Hopefully this doesn't break run file
+            # comparisons.
+            if { [catch {llength $params(-default)}] != 0 } {
+                set params(-default) [list $params(-default)]
+            }
+
             if {[llength $args] != 0} {
                 error "wrong # args: should be \"column insert pos ?-name n? ?-label l? ?-default v?\""
Index: branches/1.3/gui/scripts/tweener.tcl
===================================================================
--- branches/1.3/gui/scripts/tweener.tcl	(revision 4512)
+++ branches/1.3/gui/scripts/tweener.tcl	(revision 4512)
@@ -0,0 +1,114 @@
+# -*- mode: tcl; indent-tabs-mode: nil -*- 
+# ----------------------------------------------------------------------
+#  COMPONENT: tweener - used for animating smooth movements
+#
+#  Each Tweener executes a command repeatedly through a series of
+#  values from one extreme to another.  For example, the command may
+#  change the size of a rectangle, and the values may go from 10 to
+#  200.  The Tweener will make that happen over a specified interval
+#  of time.  The animation can be stopped or changed at any point,
+#  and if the Tweener is destroyed, the action is cancelled.
+# ======================================================================
+#  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 Itcl
+
+itcl::class Rappture::Tweener {
+    public variable from 0        ;# value goes from this...
+    public variable to   1        ;# ...to this
+    public variable duration 500  ;# during this time interval
+    public variable steps 10      ;# with this many steps
+    public variable command ""    ;# gets executed with %v for value
+    public variable finalize ""   ;# gets executed at the end to finish up
+
+    constructor {args} { eval configure $args }
+    destructor { # defined below }
+
+    public method go {{how "-resume"}}
+    public method stop {}
+
+    private method _next {}
+
+    private variable _nstep 0      ;# current step number
+    private variable _afterid ""   ;# pending after event
+}
+										
+# ----------------------------------------------------------------------
+# DESTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::Tweener::destructor {} {
+    stop
+}
+
+# ----------------------------------------------------------------------
+# USAGE: go ?-resume|-restart?
+#
+# Causes the current animation to start running, either where it
+# left off (-resume) or fromt the beginning (-restart).
+# ----------------------------------------------------------------------
+itcl::body Rappture::Tweener::go {{how -resume}} {
+    switch -- $how {
+        -resume {
+            # leave _nstep alone
+        }
+        -restart {
+            set _nstep 0
+        }
+        default {
+            error "bad option \"$how\": should be -restart or -resume"
+        }
+    }
+    stop
+    set _afterid [after idle [itcl::code $this _next]]
+}
+
+# ----------------------------------------------------------------------
+# USAGE: stop
+#
+# Causes the animation to stop by cancelling any pending after event.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Tweener::stop {} {
+    if {"" != $_afterid} {
+	after cancel $_afterid
+        set _afterid ""
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: _next
+#
+# Used internally to advance the animation.  Executes the -command
+# option with the current value substituted in place of any %v values.
+# ----------------------------------------------------------------------
+itcl::body Rappture::Tweener::_next {} {
+    set value [expr {($to-$from)/double($steps)*$_nstep + $from}]
+    set cmd $command
+    regsub -all %v $cmd $value cmd
+    if {[catch {uplevel #0 $cmd} result]} {
+        bgerror "$result\n    (while managing tweener $this)"
+    }
+
+    if {[incr _nstep] <= $steps} {
+        set delay [expr {round($duration/double($steps))}]
+        set _afterid [after $delay [itcl::code $this _next]]
+    } elseif {[string length $finalize] > 0} {
+        set cmd $finalize
+        regsub -all %v $cmd $value cmd
+        if {[catch {uplevel #0 $cmd} result]} {
+            bgerror "$result\n    (while finalizing tweener $this)"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTION: -command
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::Tweener::command {
+    if {[string length $command] == 0} {
+        stop
+    }
+}
Index: branches/1.3/gui/scripts/visviewer.tcl
===================================================================
--- branches/1.3/gui/scripts/visviewer.tcl	(revision 4511)
+++ branches/1.3/gui/scripts/visviewer.tcl	(revision 4512)
@@ -454,6 +454,16 @@
     set _done($this) 1
     set _buffer(out) $bytes
+
+    # There's problem when the user is interacting with the GUI at the
+    # same time we're trying to write to the server.  Don't want to
+    # block because, the GUI will look like it's dead.  We can start
+    # by putting a busy window over plot so that inadvertent things like
+    # mouse movements aren't received.
+
+    blt::busy hold $itk_component(main)
     fileevent $_sid writable [itcl::code $this SendHelper]
     tkwait variable ::Rappture::VisViewer::_done($this)
+    blt::busy release $itk_component(main)
+
     set _buffer(out) ""
     if { [IsConnected] } {
Index: branches/1.3/gui/scripts/vtkimageviewer.tcl
===================================================================
--- branches/1.3/gui/scripts/vtkimageviewer.tcl	(revision 4512)
+++ branches/1.3/gui/scripts/vtkimageviewer.tcl	(revision 4512)
@@ -0,0 +1,2347 @@
+# -*- mode: tcl; indent-tabs-mode: nil -*- 
+# ----------------------------------------------------------------------
+#  COMPONENT: vtkimageviewer - Vtk image viewer
+#
+#  It connects to the Vtk server running on a rendering farm,
+#  transmits data, and displays the results.
+# ======================================================================
+#  AUTHOR:  Michael McLennan, Purdue University
+#  Copyright (c) 2004-2014  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
+package require BLT
+#package require Img
+
+option add *VtkImageViewer.width 4i widgetDefault
+option add *VtkImageViewer*cursor crosshair widgetDefault
+option add *VtkImageViewer.height 4i widgetDefault
+option add *VtkImageViewer.foreground black widgetDefault
+option add *VtkImageViewer.controlBackground gray widgetDefault
+option add *VtkImageViewer.controlDarkBackground #999999 widgetDefault
+option add *VtkImageViewer.plotBackground black widgetDefault
+option add *VtkImageViewer.plotForeground white widgetDefault
+option add *VtkImageViewer.font \
+    -*-helvetica-medium-r-normal-*-12-* widgetDefault
+
+# must use this name -- plugs into Rappture::resources::load
+proc VtkImageViewer_init_resources {} {
+    Rappture::resources::register \
+        vtkvis_server Rappture::VtkImageViewer::SetServerList
+}
+
+itcl::class Rappture::VtkImageViewer {
+    inherit Rappture::VisViewer
+
+    itk_option define -plotforeground plotForeground Foreground ""
+    itk_option define -plotbackground plotBackground Background ""
+    itk_option define -mode mode Mode "vtkimage"
+
+    constructor { hostlist args } {
+        Rappture::VisViewer::constructor $hostlist
+    } {
+        # defined below
+    }
+    destructor {
+        # defined below
+    }
+    public proc SetServerList { namelist } {
+        Rappture::VisViewer::SetServerList "vtkvis" $namelist
+    }
+    public method add {dataobj {settings ""}}
+    public method camera {option args}
+    public method delete {args}
+    public method disconnect {}
+    public method download {option args}
+    public method get {args}
+    public method isconnected {}
+    public method limits3 { dataobj }
+    public method parameters {title args} { 
+        # do nothing 
+    }
+    public method scale {args}
+
+    protected method Connect {}
+    protected method CurrentDatasets {args}
+    protected method Disconnect {}
+    protected method DoResize {}
+    protected method DoRotate {}
+    protected method AdjustSetting {what {value ""}}
+    protected method AdjustMode {}
+    protected method InitSettings { args  }
+    protected method Pan {option x y}
+    protected method Pick {x y}
+    protected method Rebuild {}
+    protected method ReceiveDataset { args }
+    protected method ReceiveImage { args }
+    protected method ReceiveLegend { colormap title min max size }
+    protected method Rotate {option x y}
+    protected method Zoom {option}
+
+    # The following methods are only used by this class.
+    private method BuildAxisTab {}
+    private method BuildCameraTab {}
+    private method BuildColormap { name }
+    private method BuildImageTab {}
+    private method BuildDownloadPopup { widget command } 
+    private method Combo { option }
+    private method DrawLegend {}
+    private method EnterLegend { x y } 
+    private method EventuallyRequestLegend {} 
+    private method EventuallyResize { w h } 
+    private method EventuallyRotate { q } 
+    private method GetImage { args } 
+    private method GetVtkData { args } 
+    private method IsValidObject { dataobj } 
+    private method LeaveLegend {}
+    private method MotionLegend { x y } 
+    private method PanCamera {}
+    private method RequestLegend {}
+    private method SetCurrentColormap { color }
+    private method SetLegendTip { x y }
+    private method SetObjectStyle { dataobj comp } 
+    private method SetOrientation { side }
+
+    private variable _arcball ""
+    private variable _dlist ""     ;    # list of data objects
+    private variable _obj2datasets
+    private variable _obj2ovride   ;    # maps dataobj => style override
+    private variable _datasets     ;    # contains all the dataobj-component 
+                                   ;    # datasets in the server
+    private variable _colormaps    ;    # contains all the colormaps
+                                   ;    # in the server.
+
+    # The name of the current colormap used.  The colormap is global to all
+    # images displayed.
+    private variable _currentColormap ""
+    private variable _currentNumIsolines -1
+
+    private variable _maxScale 100;     # This is the # of times the x-axis
+                                        # and y-axis ranges can differ before
+                                        # automatically turning on
+                                        # -stretchtofit
+
+    private variable _click        ;    # info used for rotate operations
+    private variable _limits       ;    # Holds overall limits for all dataobjs 
+                                        # using the viewer.
+    private variable _view         ;    # view params for 3D view
+    private variable _settings
+    private variable _changed
+    private variable _initialStyle "";  # First found style in dataobjects.
+    private variable _reset 1;          # Indicates if camera needs to be reset
+                                        # to starting position.
+    private variable _beforeConnect 1;  # Indicates if camera needs to be reset
+                                        # to starting position.
+
+    private variable _first ""     ;    # This is the topmost dataset.
+    private variable _start 0
+    private variable _isolines
+    private variable _contourList ""
+
+    common _downloadPopup;              # download options from popup
+    private common _hardcopy
+    private variable _width 0
+    private variable _height 0
+    private variable _legendWidth 0
+    private variable _legendHeight 0
+    private variable _resizePending 0
+    private variable _rotatePending 0
+    private variable _legendPending 0
+    private variable _fieldNames {} 
+    private variable _fields 
+    private variable _curFldName ""
+    private variable _curFldLabel ""
+    private variable _colorMode "scalar";#  Mode of colormap (vmag or scalar)
+}
+
+itk::usual VtkImageViewer {
+    keep -background -foreground -cursor -font
+    keep -plotbackground -plotforeground -mode
+}
+
+# ----------------------------------------------------------------------
+# CONSTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::constructor {hostlist args} {
+    set _serverType "vtkvis"
+
+    EnableWaitDialog 900
+    # Rebuild event
+    $_dispatcher register !rebuild
+    $_dispatcher dispatch $this !rebuild "[itcl::code $this Rebuild]; list"
+
+    # Resize event
+    $_dispatcher register !resize
+    $_dispatcher dispatch $this !resize "[itcl::code $this DoResize]; list"
+
+    # Rotate event
+    $_dispatcher register !rotate
+    $_dispatcher dispatch $this !rotate "[itcl::code $this DoRotate]; list"
+
+    # Legend event
+    $_dispatcher register !legend
+    $_dispatcher dispatch $this !legend "[itcl::code $this RequestLegend]; list"
+
+    #
+    # Populate parser with commands handle incoming requests
+    #
+    $_parser alias image [itcl::code $this ReceiveImage]
+    $_parser alias dataset [itcl::code $this ReceiveDataset]
+    $_parser alias legend [itcl::code $this ReceiveLegend]
+
+    # Create image for legend colorbar.
+    set _image(legend) [image create photo]
+
+    # Initialize the view to some default parameters.
+    array set _view {
+        qw	0.36
+        qx	0.25
+        qy	0.50
+        qz	0.70
+        zoom	1.0 
+        xpan	0
+        ypan	0
+        ortho	0
+    }
+    set _arcball [blt::arcball create 100 100]
+    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+    $_arcball quaternion $q
+
+    array set _settings {
+        axisFlymode		"static"
+        axisLabels              1
+        axisMinorTicks		1
+        axisVisible		1
+        axisXGrid		0
+        axisYGrid		0
+        axisZGrid		0
+        backingColor            white
+        backingVisible          1
+        colormapDiscrete        0
+        field			"Default"
+        legendVisible           0
+        level                   127.5
+        numColors               256
+        opacity                 100
+        outline			0
+        saveOpacity		100
+        stretchToFit		0
+        view3D                  0
+        window                  255.0
+    }
+    array set _changed {
+        opacity                 0
+        colormap                0
+    }
+    itk_component add view {
+        canvas $itk_component(plotarea).view \
+            -highlightthickness 0 -borderwidth 0
+    } {
+        usual
+        ignore -highlightthickness -borderwidth -background 
+    }
+
+    itk_component add fieldmenu {
+        menu $itk_component(plotarea).menu \
+            -relief flat \
+            -tearoff no 
+    } {
+        usual
+        ignore -background -foreground -relief -tearoff
+    }
+    set c $itk_component(view)
+    bind $c <Configure> [itcl::code $this EventuallyResize %w %h]
+    bind $c <4> [itcl::code $this Zoom in 0.25]
+    bind $c <5> [itcl::code $this Zoom out 0.25]
+    bind $c <KeyPress-Left>  [list %W xview scroll 10 units]
+    bind $c <KeyPress-Right> [list %W xview scroll -10 units]
+    bind $c <KeyPress-Up>    [list %W yview scroll 10 units]
+    bind $c <KeyPress-Down>  [list %W yview scroll -10 units]
+    bind $c <Enter> "focus %W"
+    bind $c <Control-F1> [itcl::code $this ToggleConsole]
+
+    # Fix the scrollregion in case we go off screen
+    $c configure -scrollregion [$c bbox all]
+
+    set _map(id) [$c create image 0 0 -anchor nw -image $_image(plot)]
+    set _map(cwidth) -1 
+    set _map(cheight) -1 
+    set _map(zoom) 1.0
+    set _map(original) ""
+
+    set f [$itk_component(main) component controls]
+    itk_component add reset {
+        button $f.reset -borderwidth 1 -padx 1 -pady 1 \
+            -highlightthickness 0 \
+            -image [Rappture::icon reset-view] \
+            -command [itcl::code $this Zoom reset]
+    } {
+        usual
+        ignore -highlightthickness
+    }
+    pack $itk_component(reset) -side top -padx 2 -pady { 2 0 }
+    Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level"
+
+    itk_component add zoomin {
+        button $f.zin -borderwidth 1 -padx 1 -pady 1 \
+            -highlightthickness 0 \
+            -image [Rappture::icon zoom-in] \
+            -command [itcl::code $this Zoom in]
+    } {
+        usual
+        ignore -highlightthickness
+    }
+    pack $itk_component(zoomin) -side top -padx 2 -pady { 2 0 }
+    Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
+
+    itk_component add zoomout {
+        button $f.zout -borderwidth 1 -padx 1 -pady 1 \
+            -highlightthickness 0 \
+            -image [Rappture::icon zoom-out] \
+            -command [itcl::code $this Zoom out]
+    } {
+        usual
+        ignore -highlightthickness
+    }
+    pack $itk_component(zoomout) -side top -padx 2 -pady { 2 0 }
+    Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
+
+    itk_component add mode {
+        Rappture::PushButton $f.mode \
+            -onimage [Rappture::icon surface] \
+            -offimage [Rappture::icon surface] \
+            -variable [itcl::scope _settings(view3D)] \
+            -command [itcl::code $this AdjustSetting view3D] \
+    }
+    Rappture::Tooltip::for $itk_component(mode) \
+        "Toggle the surface/contour on/off"
+    pack $itk_component(mode) -padx 2 -pady { 2 0 }
+
+    itk_component add stretchtofit {
+        Rappture::PushButton $f.stretchtofit \
+            -onimage [Rappture::icon stretchtofit] \
+            -offimage [Rappture::icon stretchtofit] \
+            -variable [itcl::scope _settings(stretchToFit)] \
+            -command [itcl::code $this AdjustSetting stretchToFit] \
+    }
+    Rappture::Tooltip::for $itk_component(stretchtofit) \
+        "Stretch plot to fit window on/off"
+    pack $itk_component(stretchtofit) -padx 2 -pady 2
+
+    if { [catch {
+        BuildImageTab
+        BuildAxisTab
+        BuildCameraTab
+    } errs] != 0 } {
+	global errorInfo
+        puts stderr "errs=$errs errorInfo=$errorInfo"
+    }
+
+    # Hack around the Tk panewindow.  The problem is that the requested 
+    # size of the 3d view isn't set until an image is retrieved from
+    # the server.  So the panewindow uses the tiny size.
+    set w 10000
+    pack forget $itk_component(view)
+    blt::table $itk_component(plotarea) \
+        0,0 $itk_component(view) -fill both -reqwidth $w 
+    blt::table configure $itk_component(plotarea) c1 -resize none
+
+    # Bindings for panning via mouse
+    bind $itk_component(view) <ButtonPress-2> \
+        [itcl::code $this Pan click %x %y]
+    bind $itk_component(view) <B2-Motion> \
+        [itcl::code $this Pan drag %x %y]
+    bind $itk_component(view) <ButtonRelease-2> \
+        [itcl::code $this Pan release %x %y]
+
+    #bind $itk_component(view) <ButtonRelease-3> \
+    #    [itcl::code $this Pick %x %y]
+
+    # Bindings for panning via keyboard
+    bind $itk_component(view) <KeyPress-Left> \
+        [itcl::code $this Pan set -10 0]
+    bind $itk_component(view) <KeyPress-Right> \
+        [itcl::code $this Pan set 10 0]
+    bind $itk_component(view) <KeyPress-Up> \
+        [itcl::code $this Pan set 0 -10]
+    bind $itk_component(view) <KeyPress-Down> \
+        [itcl::code $this Pan set 0 10]
+    bind $itk_component(view) <Shift-KeyPress-Left> \
+        [itcl::code $this Pan set -2 0]
+    bind $itk_component(view) <Shift-KeyPress-Right> \
+        [itcl::code $this Pan set 2 0]
+    bind $itk_component(view) <Shift-KeyPress-Up> \
+        [itcl::code $this Pan set 0 -2]
+    bind $itk_component(view) <Shift-KeyPress-Down> \
+        [itcl::code $this Pan set 0 2]
+
+    # Bindings for zoom via keyboard
+    bind $itk_component(view) <KeyPress-Prior> \
+        [itcl::code $this Zoom out]
+    bind $itk_component(view) <KeyPress-Next> \
+        [itcl::code $this Zoom in]
+
+    bind $itk_component(view) <Enter> "focus $itk_component(view)"
+
+    if {[string equal "x11" [tk windowingsystem]]} {
+        # Bindings for zoom via mouse
+        bind $itk_component(view) <4> [itcl::code $this Zoom out]
+        bind $itk_component(view) <5> [itcl::code $this Zoom in]
+    }
+
+    set _image(download) [image create photo]
+    eval itk_initialize $args
+    Connect
+    set _beforeConnect 0
+}
+
+# ----------------------------------------------------------------------
+# DESTRUCTOR
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::destructor {} {
+    Disconnect
+    image delete $_image(plot)
+    image delete $_image(download)
+    catch { blt::arcball destroy $_arcball }
+}
+
+itcl::body Rappture::VtkImageViewer::DoResize {} {
+    if { $_width < 2 } {
+        set _width 500
+    }
+    if { $_height < 2 } {
+        set _height 500
+    }
+    set _start [clock clicks -milliseconds]
+    SendCmd "screen size [expr $_width - 20] $_height"
+
+    set font "Arial 8"
+    set lh [font metrics $font -linespace]
+    set h [expr {$_height - 2 * ($lh + 2)}]
+    if { $h != $_legendHeight } {
+        EventuallyRequestLegend
+    } else {
+        DrawLegend
+    }
+    set _resizePending 0
+}
+
+itcl::body Rappture::VtkImageViewer::DoRotate {} {
+    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+    SendCmd "camera orient $q" 
+    set _rotatePending 0
+}
+
+itcl::body Rappture::VtkImageViewer::EventuallyRequestLegend {} {
+    if { !$_legendPending } {
+        set _legendPending 1
+        $_dispatcher event -idle !legend
+    }
+}
+
+itcl::body Rappture::VtkImageViewer::EventuallyResize { w h } {
+    set _width $w
+    set _height $h
+    $_arcball resize $w $h
+    if { !$_resizePending } {
+        set _resizePending 1
+        $_dispatcher event -after 250 !resize
+    }
+}
+
+set rotate_delay 100
+
+itcl::body Rappture::VtkImageViewer::EventuallyRotate { q } {
+    foreach { _view(qw) _view(qx) _view(qy) _view(qz) } $q break
+    if { !$_rotatePending } {
+        set _rotatePending 1
+        global rotate_delay 
+        $_dispatcher event -after $rotate_delay !rotate
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: add <dataobj> ?<settings>?
+#
+# Clients use this to add a data object to the plot.  The optional
+# <settings> are used to configure the plot.  Allowed settings are
+# -color, -brightness, -width, -linestyle, and -raise.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::add {dataobj {settings ""}} {
+    if { ![$dataobj isvalid] } {
+        return;                         # Object doesn't contain valid data.
+    }
+    array set params {
+        -color auto
+        -width 1
+        -linestyle solid
+        -brightness 0
+        -raise 0
+        -description ""
+        -param ""
+        -type ""
+    }
+    array set params $settings
+    set params(-description) ""
+    set params(-param) ""
+    array set params $settings
+
+    if {$params(-color) == "auto" || $params(-color) == "autoreset"} {
+        # can't handle -autocolors yet
+        set params(-color) white
+    }
+    set pos [lsearch -exact $_dlist $dataobj]
+    if {$pos < 0} {
+        lappend _dlist $dataobj
+    }
+    set _obj2ovride($dataobj-color) $params(-color)
+    set _obj2ovride($dataobj-width) $params(-width)
+    set _obj2ovride($dataobj-raise) $params(-raise)
+    $_dispatcher event -idle !rebuild
+}
+
+
+# ----------------------------------------------------------------------
+# USAGE: delete ?<dataobj1> <dataobj2> ...?
+#
+#       Clients use this to delete a dataobj from the plot.  If no dataobjs
+#       are specified, then all dataobjs are deleted.  No data objects are
+#       deleted.  They are only removed from the display list.
+#
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::delete {args} {
+    if { [llength $args] == 0} {
+        set args $_dlist
+    }
+    # Delete all specified dataobjs
+    set changed 0
+    foreach dataobj $args {
+        set pos [lsearch -exact $_dlist $dataobj]
+        if { $pos < 0 } {
+            continue;                   # Don't know anything about it.
+        }
+        # Remove it from the dataobj list.
+        set _dlist [lreplace $_dlist $pos $pos]
+        array unset _obj2ovride $dataobj-*
+        array unset _settings $dataobj-*
+        set changed 1
+    }
+    # If anything changed, then rebuild the plot
+    if { $changed } {
+        $_dispatcher event -idle !rebuild
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: get ?-objects?
+# USAGE: get ?-visible?
+# USAGE: get ?-image view?
+#
+# Clients use this to query the list of objects being plotted, in
+# order from bottom to top of this result.  The optional "-image"
+# flag can also request the internal images being shown.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::get {args} {
+    if {[llength $args] == 0} {
+        set args "-objects"
+    }
+    set op [lindex $args 0]
+    switch -- $op {
+        "-objects" {
+            # put the dataobj list in order according to -raise options
+            set dlist {}
+            foreach dataobj $_dlist {
+                if { ![IsValidObject $dataobj] } {
+                    continue
+                }
+                if {[info exists _obj2ovride($dataobj-raise)] && 
+                    $_obj2ovride($dataobj-raise)} {
+                    set dlist [linsert $dlist 0 $dataobj]
+                } else {
+                    lappend dlist $dataobj
+                }
+            }
+            return $dlist
+        }
+        "-visible" {
+            set dlist {}
+            foreach dataobj $_dlist {
+                if { ![IsValidObject $dataobj] } {
+                    continue
+                }
+                if { ![info exists _obj2ovride($dataobj-raise)] } {
+                    # No setting indicates that the object isn't visible.
+                    continue
+                }
+                # Otherwise use the -raise parameter to put the object to
+                # the front of the list.
+                if { $_obj2ovride($dataobj-raise) } {
+                    set dlist [linsert $dlist 0 $dataobj]
+                } else {
+                    lappend dlist $dataobj
+                }
+            }
+            return $dlist
+        }           
+        -image {
+            if {[llength $args] != 2} {
+                error "wrong # args: should be \"get -image view\""
+            }
+            switch -- [lindex $args end] {
+                view {
+                    return $_image(plot)
+                }
+                default {
+                    error "bad image name \"[lindex $args end]\": should be view"
+                }
+            }
+        }
+        default {
+            error "bad option \"$op\": should be -objects or -image"
+        }
+    }
+}
+
+# 
+# scale  --
+#
+#       This gets called either incrementally as new simulations are
+#       added or all at once as a sequence of images.
+#       This  accounts for all objects--even those not showing on the 
+#       screen.  Because of this, the limits are appropriate for all 
+#       objects as the user scans through data in the ResultSet viewer.
+#
+itcl::body Rappture::VtkImageViewer::scale {args} {
+    foreach dataobj $args {
+        if { ![$dataobj isvalid] } {
+            continue;                   # Object doesn't contain valid data.
+        }
+        foreach axis { x y } {
+            set lim [$dataobj limits $axis]
+            if { ![info exists _limits($axis)] } {
+                set _limits($axis) $lim
+                continue
+            }
+            foreach {min max} $lim break
+            foreach {amin amax} $_limits($axis) break
+            if { $amin > $min } {
+                set amin $min
+            }
+            if { $amax < $max } {
+                set amax $max
+            }
+            set _limits($axis) [list $amin $amax]
+            set units [$dataobj hints ${axis}units]
+            set found($units) 1
+        }
+        foreach { fname lim } [$dataobj fieldlimits] {
+            if { ![info exists _limits($fname)] } {
+                set _limits($fname) $lim
+                continue
+            }
+            foreach {min max} $lim break
+            foreach {fmin fmax} $_limits($fname) break
+            if { $fmin > $min } {
+                set fmin $min
+            }
+            if { $fmax < $max } {
+                set fmax $max
+            }
+            set _limits($fname) [list $fmin $fmax]
+        }
+    }
+    if { [array size found] > 1 } {
+        set _settings(stretchToFit) 1
+    } else {
+        # Check if the range of the x and y axes requires that we stretch
+        # the contour to fit the plotting area.  This can happen when the
+        # x and y scales differ greatly (> 100x)
+        foreach {xmin xmax} $_limits(x) break
+        foreach {ymin ymax} $_limits(y) break
+        if { (($xmax - $xmin) > (($ymax -$ymin) * $_maxScale)) ||
+             ((($xmax - $xmin) * $_maxScale) < ($ymax -$ymin)) } {
+            set _settings(stretchToFit) 1
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: download coming
+# USAGE: download controls <downloadCommand>
+# USAGE: download now
+#
+# Clients use this method to create a downloadable representation
+# of the plot.  Returns a list of the form {ext string}, where
+# "ext" is the file extension (indicating the type of data) and
+# "string" is the data itself.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::download {option args} {
+    switch $option {
+        coming {
+            if {[catch {
+                blt::winop snap $itk_component(plotarea) $_image(download)
+            }]} {
+                $_image(download) configure -width 1 -height 1
+                $_image(download) put #000000
+            }
+        }
+        controls {
+            set popup .vtkviewerdownload
+            if { ![winfo exists .vtkviewerdownload] } {
+                set inner [BuildDownloadPopup $popup [lindex $args 0]]
+            } else {
+                set inner [$popup component inner]
+            }
+            set _downloadPopup(image_controls) $inner.image_frame
+            set num [llength [get]]
+            set num [expr {($num == 1) ? "1 result" : "$num results"}]
+            set word [Rappture::filexfer::label downloadWord]
+            $inner.summary configure -text "$word $num in the following format:"
+            update idletasks            ;# Fix initial sizes
+            return $popup
+        }
+        now {
+            set popup .vtkviewerdownload
+            if {[winfo exists .vtkviewerdownload]} {
+                $popup deactivate
+            }
+            switch -- $_downloadPopup(format) {
+                "image" {
+                    return [$this GetImage [lindex $args 0]]
+                }
+                "vtk" {
+                    return [$this GetVtkData [lindex $args 0]]
+                }
+            }
+            return ""
+        }
+        default {
+            error "bad option \"$option\": should be coming, controls, now"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: Connect ?<host:port>,<host:port>...?
+#
+# Clients use this method to establish a connection to a new
+# server, or to reestablish a connection to the previous server.
+# Any existing connection is automatically closed.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::Connect {} {
+    global readyForNextFrame
+    set readyForNextFrame 1
+    set _reset 1
+    set _hosts [GetServerList "vtkvis"]
+    if { "" == $_hosts } {
+        return 0
+    }
+    set result [VisViewer::Connect $_hosts]
+    if { $result } {
+        if { $_reportClientInfo }  {
+            # Tell the server the viewer, hub, user and session.
+            # Do this immediately on connect before buffering any commands
+            global env
+
+            set info {}
+            set user "???"
+            if { [info exists env(USER)] } {
+                set user $env(USER)
+            }
+            set session "???"
+            if { [info exists env(SESSION)] } {
+                set session $env(SESSION)
+            }
+            lappend info "hub" [exec hostname]
+            lappend info "client" "vtkimageviewer"
+            lappend info "user" $user
+            lappend info "session" $session
+            SendCmd "clientinfo [list $info]"
+        }
+        set w [winfo width $itk_component(view)]
+        set h [winfo height $itk_component(view)]
+        EventuallyResize $w $h
+    }
+    return $result
+}
+
+#
+# isconnected --
+#
+#       Indicates if we are currently connected to the visualization server.
+#
+itcl::body Rappture::VtkImageViewer::isconnected {} {
+    return [VisViewer::IsConnected]
+}
+
+#
+# disconnect --
+#
+itcl::body Rappture::VtkImageViewer::disconnect {} {
+    Disconnect
+    set _reset 1
+}
+
+#
+# Disconnect --
+#
+#       Clients use this method to disconnect from the current rendering
+#       server.
+#
+itcl::body Rappture::VtkImageViewer::Disconnect {} {
+    VisViewer::Disconnect
+
+    $_dispatcher cancel !rebuild
+    $_dispatcher cancel !resize
+    $_dispatcher cancel !rotate
+    $_dispatcher cancel !legend
+    # disconnected -- no more data sitting on server
+    array unset _datasets 
+    array unset _data 
+    array unset _colormaps 
+    array unset _obj2datasets 
+    global readyForNextFrame
+    set readyForNextFrame 1
+}
+
+# ----------------------------------------------------------------------
+# USAGE: ReceiveImage -bytes <size> -type <type> -token <token>
+#
+# Invoked automatically whenever the "image" command comes in from
+# the rendering server.  Indicates that binary image data with the
+# specified <size> will follow.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::ReceiveImage { args } {
+    global readyForNextFrame
+    set readyForNextFrame 1
+    array set info {
+        -token "???"
+        -bytes 0
+        -type image
+    }
+    array set info $args
+    set bytes [ReceiveBytes $info(-bytes)]
+    if { $info(-type) == "image" } {
+        if 0 {
+            set f [open "last.ppm" "w"] 
+            puts $f $bytes
+            close $f
+        }
+        $_image(plot) configure -data $bytes
+        set time [clock seconds]
+        set date [clock format $time]
+        #puts stderr "$date: received image [image width $_image(plot)]x[image height $_image(plot)] image>"        
+        if { $_start > 0 } {
+            set finish [clock clicks -milliseconds]
+            #puts stderr "round trip time [expr $finish -$_start] milliseconds"
+            set _start 0
+        }
+    } elseif { $info(type) == "print" } {
+        set tag $this-print-$info(-token)
+        set _hardcopy($tag) $bytes
+    }
+}
+
+#
+# ReceiveDataset --
+#
+itcl::body Rappture::VtkImageViewer::ReceiveDataset { args } {
+    if { ![isconnected] } {
+        return
+    }
+    set option [lindex $args 0]
+    switch -- $option {
+        "scalar" {
+            set option [lindex $args 1]
+            switch -- $option {
+                "world" {
+                    foreach { x y z value tag } [lrange $args 2 end] break
+                }
+                "pixel" {
+                    foreach { x y value tag } [lrange $args 2 end] break
+                }
+            }
+        }
+        "vector" {
+            set option [lindex $args 1]
+            switch -- $option {
+                "world" {
+                    foreach { x y z vx vy vz tag } [lrange $args 2 end] break
+                }
+                "pixel" {
+                    foreach { x y vx vy vz tag } [lrange $args 2 end] break
+                }
+            }
+        }
+        "names" {
+            foreach { name } [lindex $args 1] {
+                #puts stderr "Dataset: $name"
+            }
+        }
+        default {
+            error "unknown dataset option \"$option\" from server"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: Rebuild
+#
+# Called automatically whenever something changes that affects the
+# data in the widget.  Clears any existing data and rebuilds the
+# widget to display new data.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::Rebuild {} {
+    set w [winfo width $itk_component(view)]
+    set h [winfo height $itk_component(view)]
+    if { $w < 2 || $h < 2 } {
+        $_dispatcher event -idle !rebuild
+        return
+    }
+
+    # Turn on buffering of commands to the server.  We don't want to
+    # be preempted by a server disconnect/reconnect (which automatically
+    # generates a new call to Rebuild).   
+    StartBufferingCommands
+
+    if { $_width != $w || $_height != $h || $_reset } {
+	set _width $w
+	set _height $h
+	$_arcball resize $w $h
+	DoResize
+	if { $_settings(stretchToFit) } {
+	    AdjustSetting stretchToFit
+	}
+    }
+    if { $_reset } {
+	#
+	# Reset the camera and other view parameters
+	#
+        InitSettings view3D background
+
+        # Let's see how this goes.  I think it's preferable to overloading the
+        # axis title with the exponent.
+        SendCmd "axis exp 0 0 0 1"
+
+	SendCmd "axis lrot z 90"
+	set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+	$_arcball quaternion $q 
+        if {$_settings(view3D) } {
+            if { $_view(ortho)} {
+                SendCmd "camera mode ortho"
+            } else {
+                SendCmd "camera mode persp"
+            }
+            DoRotate
+            SendCmd "camera reset"
+	}
+	PanCamera
+        StopBufferingCommands
+        SendCmd "imgflush"
+        StartBufferingCommands
+    }
+
+    set _first ""
+    # Start off with no datasets are visible.
+    SendCmd "dataset visible 0"
+    foreach dataobj [get -objects] {
+        if { [info exists _obj2ovride($dataobj-raise)] &&  $_first == "" } {
+            set _first $dataobj
+        }
+        set _obj2datasets($dataobj) ""
+        foreach comp [$dataobj components] {
+            set tag $dataobj-$comp
+            if { ![info exists _datasets($tag)] } {
+                set bytes [$dataobj vtkdata $comp]
+		if 0 { 
+                    set f [open /tmp/vtkimage.vtk "w"]
+                    puts $f $bytes
+                    close $f
+		}
+                set length [string length $bytes]
+                if { $_reportClientInfo }  {
+                    set info {}
+                    lappend info "tool_id"       [$dataobj hints toolId]
+                    lappend info "tool_name"     [$dataobj hints toolName]
+                    lappend info "tool_version"  [$dataobj hints toolRevision]
+                    lappend info "tool_title"    [$dataobj hints toolTitle]
+                    lappend info "dataset_label" [$dataobj hints label]
+                    lappend info "dataset_size"  $length
+                    lappend info "dataset_tag"   $tag
+                    SendCmd [list "clientinfo" $info]
+                }
+                SendCmd "dataset add $tag data follows $length"
+                append _outbuf $bytes
+                set _datasets($tag) 1
+                SetObjectStyle $dataobj $comp
+            }
+            lappend _obj2datasets($dataobj) $tag
+            if { [info exists _obj2ovride($dataobj-raise)] } {
+                # Setting dataset visible enables outline
+                # and image
+                SendCmd "dataset visible 1 $tag"
+            }
+        }
+    }
+    if { $_first != ""  } {
+	$itk_component(field) choices delete 0 end
+	$itk_component(fieldmenu) delete 0 end
+	array unset _fields
+        set _curFldName ""
+        foreach cname [$_first components] {
+            foreach fname [$_first fieldnames $cname] {
+                if { [info exists _fields($fname)] } {
+                    continue
+                }
+                foreach { label units components } \
+                    [$_first fieldinfo $fname] break
+                $itk_component(field) choices insert end "$fname" "$label"
+                $itk_component(fieldmenu) add radiobutton -label "$label" \
+                    -value $label -variable [itcl::scope _curFldLabel] \
+                    -selectcolor red \
+                    -activebackground $itk_option(-plotbackground) \
+                    -activeforeground $itk_option(-plotforeground) \
+                    -font "Arial 8" \
+                    -command [itcl::code $this Combo invoke]
+                set _fields($fname) [list $label $units $components]
+                if { $_curFldName == "" } {
+                    set _curFldName $fname
+                    set _curFldLabel $label
+                }
+            }
+        }
+        $itk_component(field) value $_curFldLabel
+    }
+    InitSettings stretchToFit outline
+
+    if { $_reset } {
+	SendCmd "axis tickpos outside"
+	foreach axis { x y z } {
+	    SendCmd "axis lformat $axis %g"
+	}
+        
+	foreach axis { x y z } {
+            set label [$_first hints ${axis}label]
+	    if { $label == "" } {
+		set label [string toupper $axis]
+	    }
+	    # May be a space in the axis label.
+	    SendCmd [list axis name $axis $label]
+
+	    if {$axis == "z" && [$_first hints ${axis}units] == ""} {
+		set units [lindex $_fields($_curFldName) 1]
+	    } else {
+		set units [$_first hints ${axis}units]
+	    }
+	    if { $units != "" } {
+		# May be a space in the axis units.
+		SendCmd [list axis units $axis $units]
+	    }
+	}
+	#
+	# Reset the camera and other view parameters
+	#
+	set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+	$_arcball quaternion $q 
+        if {$_settings(view3D) } {
+            if { $_view(ortho)} {
+                SendCmd "camera mode ortho"
+            } else {
+                SendCmd "camera mode persp"
+            }
+            DoRotate
+            SendCmd "camera reset"
+        }
+	PanCamera
+	InitSettings axisXGrid axisYGrid axisZGrid \
+	    axisVisible axisLabels field view3D
+        if { [array size _fields] < 2 } {
+            blt::table forget $itk_component(field) $itk_component(field_l)
+        }
+        RequestLegend
+        set _reset 0
+    }
+    global readyForNextFrame
+    set readyForNextFrame 0;		# Don't advance to the next frame
+
+    # Actually write the commands to the server socket.  If it fails, we don't
+    # care.  We're finished here.
+    blt::busy hold $itk_component(hull)
+    StopBufferingCommands
+    blt::busy release $itk_component(hull)
+}
+
+# ----------------------------------------------------------------------
+# USAGE: CurrentDatasets ?-all -visible? ?dataobjs?
+#
+# Returns a list of server IDs for the current datasets being displayed.  This
+# is normally a single ID, but it might be a list of IDs if the current data
+# object has multiple components.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::CurrentDatasets {args} {
+    set flag [lindex $args 0]
+    switch -- $flag { 
+        "-all" {
+            if { [llength $args] > 1 } {
+                error "CurrentDatasets: can't specify dataobj after \"-all\""
+            }
+            set dlist [get -objects]
+        }
+        "-visible" {
+            if { [llength $args] > 1 } {
+                set dlist {}
+                set args [lrange $args 1 end]
+                foreach dataobj $args {
+                    if { [info exists _obj2ovride($dataobj-raise)] } {
+                        lappend dlist $dataobj
+                    }
+                }
+            } else {
+                set dlist [get -visible]
+            }
+        }           
+        default {
+            set dlist $args
+        }
+    }
+    set rlist ""
+    foreach dataobj $dlist {
+        foreach comp [$dataobj components] {
+            set tag $dataobj-$comp
+            if { [info exists _datasets($tag)] && $_datasets($tag) } {
+                lappend rlist $tag
+            }
+        }
+    }
+    return $rlist
+}
+
+# ----------------------------------------------------------------------
+# USAGE: Zoom in
+# USAGE: Zoom out
+# USAGE: Zoom reset
+#
+# Called automatically when the user clicks on one of the zoom
+# controls for this widget.  Changes the zoom for the current view.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::Zoom {option} {
+    switch -- $option {
+        "in" {
+            set _view(zoom) [expr {$_view(zoom)*1.25}]
+            SendCmd "camera zoom $_view(zoom)"
+        }
+        "out" {
+            set _view(zoom) [expr {$_view(zoom)*0.8}]
+            SendCmd "camera zoom $_view(zoom)"
+        }
+        "reset" {
+            array set _view {
+                qw      0.36
+                qx      0.25
+                qy      0.50
+                qz      0.70
+                zoom    1.0
+                xpan    0
+                ypan    0 
+            }
+            if { $_first != "" } {
+                set location [$_first hints camera]
+                if { $location != "" } {
+                    array set _view $location
+                }
+            }
+            set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+            $_arcball quaternion $q
+            if {$_settings(view3D) } {
+                DoRotate
+            }
+            SendCmd "camera reset"
+        }
+    }
+}
+
+itcl::body Rappture::VtkImageViewer::PanCamera {} {
+    set x $_view(xpan)
+    set y $_view(ypan)
+    SendCmd "camera pan $x $y"
+}
+
+
+# ----------------------------------------------------------------------
+# USAGE: Rotate click <x> <y>
+# USAGE: Rotate drag <x> <y>
+# USAGE: Rotate release <x> <y>
+#
+# Called automatically when the user clicks/drags/releases in the
+# plot area.  Moves the plot according to the user's actions.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::Rotate {option x y} {
+    switch -- $option {
+        "click" {
+            $itk_component(view) configure -cursor fleur
+            set _click(x) $x
+            set _click(y) $y
+        }
+        "drag" {
+            if {[array size _click] == 0} {
+                Rotate click $x $y
+            } else {
+                set w [winfo width $itk_component(view)]
+                set h [winfo height $itk_component(view)]
+                if {$w <= 0 || $h <= 0} {
+                    return
+                }
+
+                if {[catch {
+                    # this fails sometimes for no apparent reason
+                    set dx [expr {double($x-$_click(x))/$w}]
+                    set dy [expr {double($y-$_click(y))/$h}]
+                }]} {
+                    return
+                }
+                if { $dx == 0 && $dy == 0 } {
+                    return
+                }
+                set q [$_arcball rotate $x $y $_click(x) $_click(y)]
+                EventuallyRotate $q
+                set _click(x) $x
+                set _click(y) $y
+            }
+        }
+        "release" {
+            Rotate drag $x $y
+            $itk_component(view) configure -cursor ""
+            catch {unset _click}
+        }
+        default {
+            error "bad option \"$option\": should be click, drag, release"
+        }
+    }
+}
+
+itcl::body Rappture::VtkImageViewer::Pick {x y} {
+    foreach tag [CurrentDatasets -visible] {
+        SendCmd "dataset getscalar pixel $x $y $tag"
+    } 
+}
+
+# ----------------------------------------------------------------------
+# USAGE: $this Pan click x y
+#        $this Pan drag x y
+#        $this Pan release x y
+#
+# Called automatically when the user clicks on one of the zoom
+# controls for this widget.  Changes the zoom for the current view.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::Pan {option x y} {
+    switch -- $option {
+        "set" {
+            set w [winfo width $itk_component(view)]
+            set h [winfo height $itk_component(view)]
+            set x [expr $x / double($w)]
+            set y [expr $y / double($h)]
+            set _view(xpan) [expr $_view(xpan) + $x]
+            set _view(ypan) [expr $_view(ypan) + $y]
+            PanCamera
+            return
+        }
+        "click" {
+            set _click(x) $x
+            set _click(y) $y
+            $itk_component(view) configure -cursor hand1
+        }
+        "drag" {
+            if { ![info exists _click(x)] } {
+                set _click(x) $x
+            }
+            if { ![info exists _click(y)] } {
+                set _click(y) $y
+            }
+            set w [winfo width $itk_component(view)]
+            set h [winfo height $itk_component(view)]
+            set dx [expr ($_click(x) - $x)/double($w)]
+            set dy [expr ($_click(y) - $y)/double($h)]
+            set _click(x) $x
+            set _click(y) $y
+            set _view(xpan) [expr $_view(xpan) - $dx]
+            set _view(ypan) [expr $_view(ypan) - $dy]
+            PanCamera
+        }
+        "release" {
+            Pan drag $x $y
+            $itk_component(view) configure -cursor ""
+        }
+        default {
+            error "unknown option \"$option\": should set, click, drag, or release"
+        }
+    }
+}
+
+# ----------------------------------------------------------------------
+# USAGE: InitSettings <what> ?<value>?
+#
+# Used internally to update rendering settings whenever parameters
+# change in the popup settings panel.  Sends the new settings off
+# to the back end.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::InitSettings { args } {
+    foreach spec $args {
+        if { [info exists _settings($_first-$spec)] } {
+            # Reset global setting with dataobj specific setting
+            set _settings($spec) $_settings($_first-$spec)
+        }
+        AdjustSetting $spec
+    }
+}
+
+#
+# AdjustSetting --
+#
+#       Changes/updates a specific setting in the widget.  There are
+#       usually user-setable option.  Commands are sent to the render
+#       server.
+#
+itcl::body Rappture::VtkImageViewer::AdjustSetting {what {value ""}} {
+    if { $_beforeConnect } {
+        return
+    }
+    switch -- $what {
+        "axisFlymode" {
+            set mode [$itk_component(axisflymode) value]
+            set mode [$itk_component(axisflymode) translate $mode]
+            set _settings($what) $mode
+            SendCmd "axis flymode $mode"
+        }
+        "axisLabels" {
+            set bool $_settings($what)
+            SendCmd "axis labels all $bool"
+        }
+        "axisMinorTicks" {
+            set bool $_settings($what)
+	    foreach axis { x y z } { 
+		SendCmd "axis minticks ${axis} $bool"
+	    }
+        }
+        "axisVisible" {
+            set bool $_settings($what)
+            SendCmd "axis visible all $bool"
+        }
+        "axisXGrid" - "axisYGrid" - "axisZGrid" {
+            set axis [string tolower [string range $what 4 4]]
+            set bool $_settings($what)
+            SendCmd "axis grid $axis $bool"
+        }
+        "background" {
+            set bg [$itk_component(background) value]
+	    array set fgcolors {
+		"black" "white"
+		"white" "black"
+		"grey"	"black"
+	    }
+            set fg $fgcolors($bg)
+            configure -plotbackground $bg -plotforeground $fg
+	    $itk_component(view) delete "legend"
+            SendCmd "screen bgcolor [Color2RGB $bg]"
+            SendCmd "outline color [Color2RGB $fg]"
+            SendCmd "axis color all [Color2RGB $fg]"
+	    DrawLegend
+        }
+        "backingColor" {
+            set color [$itk_component(backingcolor) value]
+	    if { $color == "none" } {
+		if { $_settings(backingVisible) } {
+		    SendCmd "image backing 0"
+		    set _settings(backingVisible) 0
+		}
+	    } else {
+		if { !$_settings(backingVisible) } {
+		    SendCmd "image backing 1"
+		    set _settings(backingVisible) 1
+		}
+		SendCmd "image color [Color2RGB $color]"
+	    }
+        }
+        "backingVisible" {
+	    set bool $_settings($what)
+            SendCmd "image backing $bool"
+        }
+        "colormap" {
+            set _changed($what) 1
+            StartBufferingCommands
+            set color [$itk_component(colormap) value]
+            set _settings($what) $color
+            SetCurrentColormap $color
+            if {$_settings(colormapDiscrete)} {
+                 SendCmd "colormap res $_settings(numColors) $color"
+            }
+            StopBufferingCommands
+	    EventuallyRequestLegend
+        }
+        "colormapDiscrete" {
+            set bool $_settings($what)
+            StartBufferingCommands
+            if {$bool} {
+                SendCmd "colormap res $_settings(numColors)"
+            } else {
+                SendCmd "colormap res default"
+            }
+            StopBufferingCommands
+            EventuallyRequestLegend
+        }
+        "field" {
+            set label [$itk_component(field) value]
+            set fname [$itk_component(field) translate $label]
+            set _settings($what) $fname
+            if { [info exists _fields($fname)] } {
+                foreach { label units components } $_fields($fname) break
+                if { $components > 1 } {
+                    set _colorMode vmag
+                } else {
+                    set _colorMode scalar
+                }
+                set _curFldName $fname
+                set _curFldLabel $label
+            } else {
+                puts stderr "unknown field \"$fname\""
+                return
+            }
+
+            # Get the new limits because the field changed.
+            SendCmd "dataset scalar $_curFldName"
+            #SendCmd "image colormode scalar $_curFldName"
+            SendCmd "camera reset"
+            DrawLegend
+        }
+        "view3D" {
+	    set bool $_settings($what)
+            set c $itk_component(view)
+            StartBufferingCommands
+            # Fix image scale: 0 for contours, 1 for images.
+            if { $bool } {
+                set _settings(opacity) $_settings(saveOpacity)
+            } else {
+                set _settings(opacity) 100
+            }
+            AdjustSetting opacity
+ 	    if { $bool } {
+		$itk_component(opacity) configure -state normal
+		$itk_component(opacity_l) configure -state normal
+                if {$_view(ortho)} {
+                    SendCmd "camera mode ortho"
+                } else {
+                    SendCmd "camera mode persp"
+                }
+                SendCmd "camera aspect native"
+	    } else {
+		$itk_component(opacity) configure -state disabled
+		$itk_component(opacity_l) configure -state disabled
+                SendCmd "camera mode image"
+                if {$_settings(stretchToFit)} {
+                    SendCmd "camera aspect window"
+                }
+            }
+            if { $bool } {
+                set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+                $_arcball quaternion $q
+                SendCmd "camera orient $q" 
+            } else {
+                bind $c <ButtonPress-1> {}
+                bind $c <B1-Motion> {}
+                bind $c <ButtonRelease-1> {}
+            }
+            SendCmd "camera reset"
+            # Fix the mouse bindings for rotation/panning and the 
+            # camera mode. Ideally we'd create a bindtag for these.
+            if { $bool } {
+                # Bindings for rotation via mouse
+                bind $c <ButtonPress-1> \
+                    [itcl::code $this Rotate click %x %y]
+                bind $c <B1-Motion> \
+                    [itcl::code $this Rotate drag %x %y]
+                bind $c <ButtonRelease-1> \
+                    [itcl::code $this Rotate release %x %y]
+            }
+            StopBufferingCommands
+        }
+        "window" {
+            set val $_settings($what)
+            SendCmd "image window $val"
+        }
+        "level" {
+            set val $_settings($what)
+            SendCmd "image level $val"
+        }
+        "legendVisible" {
+            if { !$_settings($what) } {
+		$itk_component(view) delete legend
+	    }
+	    DrawLegend
+        }
+        "opacity" {
+            set _changed($what) 1
+	    if { $_settings(view3D) } {
+                set _settings(saveOpacity) $_settings($what)
+                set val [expr $_settings($what) * 0.01]
+                SendCmd "image opacity $val"
+            } else {
+		SendCmd "image opacity 1.0"
+            }
+        }
+        "outline" {
+            set bool $_settings($what)
+            SendCmd "outline visible $bool"
+	}
+        "stretchToFit" {
+	    set bool $_settings($what)
+	    if { $bool } {
+		if { $_settings(view3D) } {
+		    SendCmd "camera aspect native"
+		} else {
+		    SendCmd "camera aspect window"
+		}
+	    } else {
+		SendCmd "camera aspect native"
+	    }
+	}
+	default {
+            error "don't know how to fix $what"
+        }
+    }
+}
+
+#
+# RequestLegend --
+#
+#       Request a new legend from the server.  The size of the legend
+#       is determined from the height of the canvas.  
+#
+# This should be called when
+#	1.  A new current colormap is set.
+#	2.  Window is resized.
+#	3.  The limits of the data have changed.  (Just need a redraw).
+#	4.  Number of isolines have changed. (Just need a redraw).
+#	5.  Legend becomes visible (Just need a redraw).
+#
+itcl::body Rappture::VtkImageViewer::RequestLegend {} {
+    set _legendPending 0
+    set font "Arial 8"
+    set w 12
+    set lineht [font metrics $font -linespace]
+    # color ramp height = (canvas height) - (min and max value lines) - 2 
+    set h [expr {$_height - 2 * ($lineht + 2)}]
+    set _legendHeight $h
+
+    set fname $_curFldName
+    if { [string match "component*" $fname] } {
+	set title ""
+    } else {
+	if { [info exists _fields($fname)] } {
+	    foreach { title units } $_fields($fname) break
+	    if { $units != "" } {
+		set title [format "%s (%s)" $title $units]
+	    }
+	} else {
+	    set title $fname
+	}
+    }
+    # If there's a title too, substract one more line
+    if { $title != "" } {
+        incr h -$lineht 
+    }
+    if { $h < 1 } {
+        return
+    }
+    # Set the legend on the first image dataset.
+    if { $_currentColormap != "" && $_currentColormap != "none" } {
+	SendCmd "legend $_currentColormap scalar $_curFldName {} $w $h 0"
+    }
+}
+
+#
+# SetCurrentColormap --
+#
+itcl::body Rappture::VtkImageViewer::SetCurrentColormap { name } {
+    # Keep track of the colormaps that we build.
+    if { $name != "none" && ![info exists _colormaps($name)] } {
+        BuildColormap $name 
+        set _colormaps($name) 1
+    }
+    set _currentColormap $name
+    SendCmd "image colormap $_currentColormap"
+}
+
+
+#
+# BuildColormap --
+#
+#       Build the designated colormap on the server.
+#
+itcl::body Rappture::VtkImageViewer::BuildColormap { name } {
+    set cmap [ColorsToColormap $name]
+    if { [llength $cmap] == 0 } {
+        set cmap "0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0"
+    }
+    set wmap "0.0 1.0 1.0 1.0"
+    SendCmd "colormap add $name { $cmap } { $wmap }"
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTION: -mode
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::VtkImageViewer::mode {
+    switch -- $itk_option(-mode) {
+	"volume" {
+	    set _settings(view3D) 1
+	}
+	"vtkimage" {
+	    set _settings(view3D) 0
+	} 
+	default {
+	    error "unknown mode settings \"$itk_option(-mode)\""
+	}
+    }
+    if { !$_reset } {
+        AdjustSetting view3D
+    }
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTION: -plotbackground
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::VtkImageViewer::plotbackground {
+    if { [isconnected] } {
+        set rgb [Color2RGB $itk_option(-plotbackground)]
+        if { !$_reset } {
+            SendCmd "screen bgcolor $rgb"
+        }
+	$itk_component(view) configure -background $itk_option(-plotbackground)
+    }
+}
+
+# ----------------------------------------------------------------------
+# CONFIGURATION OPTION: -plotforeground
+# ----------------------------------------------------------------------
+itcl::configbody Rappture::VtkImageViewer::plotforeground {
+    if { [isconnected] } {
+        set rgb [Color2RGB $itk_option(-plotforeground)]
+        if { !$_reset } {
+            SendCmd "outline color $rgb"
+            SendCmd "axis color all $rgb"
+        }
+    }
+}
+
+itcl::body Rappture::VtkImageViewer::limits3 { dataobj } {
+    lappend limits x [$dataobj limits x]
+    lappend limits y [$dataobj limits y] 
+    if { [catch { $dataobj limits $_curFldName } vlim] != 0 } {
+        set vlim [$dataobj limits v] 
+    }
+    lappend limits v $vlim
+    return $limits
+}
+
+itcl::body Rappture::VtkImageViewer::BuildImageTab {} {
+
+    set fg [option get $itk_component(hull) font Font]
+    #set bfg [option get $itk_component(hull) boldFont Font]
+
+    set inner [$itk_component(main) insert end \
+        -title "Image Settings" \
+        -icon [Rappture::icon contour2]]
+    $inner configure -borderwidth 4
+
+    checkbutton $inner.legend \
+        -text "Legend" \
+        -variable [itcl::scope _settings(legendVisible)] \
+        -command [itcl::code $this AdjustSetting legendVisible] \
+        -font "Arial 9"
+
+    checkbutton $inner.outline \
+        -text "Outline" \
+        -variable [itcl::scope _settings(outline)] \
+        -command [itcl::code $this AdjustSetting outline] \
+        -font "Arial 9"
+
+    checkbutton $inner.backing \
+        -text "Backing" \
+        -variable [itcl::scope _settings(backingVisible)] \
+        -command [itcl::code $this AdjustSetting backingVisible] \
+        -font "Arial 9"
+
+    checkbutton $inner.stretch \
+        -text "Stretch to fit" \
+        -variable [itcl::scope _settings(stretchToFit)] \
+        -command [itcl::code $this AdjustSetting stretchToFit] \
+        -font "Arial 9"
+
+    checkbutton $inner.colormapDiscrete \
+        -text "Discrete Colormap" \
+        -variable [itcl::scope _settings(colormapDiscrete)] \
+        -command [itcl::code $this AdjustSetting colormapDiscrete] \
+        -font "Arial 9"
+
+    itk_component add field_l {
+        label $inner.field_l -text "Field" -font "Arial 9" 
+    } {
+        ignore -font
+    }
+    itk_component add field {
+        Rappture::Combobox $inner.field -width 10 -editable no
+    }
+    bind $inner.field <<Value>> \
+        [itcl::code $this AdjustSetting field]
+
+    label $inner.colormap_l -text "Colormap" -font "Arial 9" 
+    itk_component add colormap {
+        Rappture::Combobox $inner.colormap -width 10 -editable no
+    }
+    $inner.colormap choices insert end [GetColormapList -includeNone]
+
+    $itk_component(colormap) value "BCGYR"
+    bind $inner.colormap <<Value>> \
+        [itcl::code $this AdjustSetting colormap]
+
+    label $inner.backingcolor_l -text "Backing Color" -font "Arial 9" 
+    itk_component add backingcolor {
+        Rappture::Combobox $inner.backingcolor -width 10 -editable no
+    }
+    $inner.backingcolor choices insert end \
+        "black"              "black"            \
+        "blue"               "blue"             \
+        "cyan"               "cyan"             \
+        "green"              "green"            \
+        "grey"               "grey"             \
+        "magenta"            "magenta"          \
+        "orange"             "orange"           \
+        "red"                "red"              \
+        "white"              "white"            \
+	"none"		     "none"
+
+    $itk_component(backingcolor) value "white"
+    bind $inner.backingcolor <<Value>> \
+	[itcl::code $this AdjustSetting backingColor]
+
+    label $inner.background_l -text "Background Color" -font "Arial 9" 
+    itk_component add background {
+        Rappture::Combobox $inner.background -width 10 -editable no
+    }
+    $inner.background choices insert end \
+        "black"              "black"            \
+        "white"              "white"            \
+        "grey"               "grey"             
+
+    $itk_component(background) value "white"
+    bind $inner.background <<Value>> [itcl::code $this AdjustSetting background]
+
+    itk_component add opacity_l {
+        label $inner.opacity_l -text "Opacity" -font "Arial 9"
+    } {
+        ignore -font
+    }
+    itk_component add opacity {
+        ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
+            -variable [itcl::scope _settings(opacity)] \
+            -showvalue off \
+            -command [itcl::code $this AdjustSetting opacity]
+    }
+
+    itk_component add window_l {
+        label $inner.window_l -text "Window" -font "Arial 9"
+    } {
+        ignore -font
+    }
+    itk_component add window {
+        ::scale $inner.window -from 0 -to 255 -orient horizontal \
+            -variable [itcl::scope _settings(window)] \
+            -showvalue off \
+            -command [itcl::code $this AdjustSetting window]
+    }
+    itk_component add level_l {
+        label $inner.level_l -text "Level" -font "Arial 9"
+    } {
+        ignore -font
+    }
+    itk_component add level {
+        ::scale $inner.level -from 0 -to 255 -orient horizontal \
+            -variable [itcl::scope _settings(level)] \
+            -showvalue off \
+            -command [itcl::code $this AdjustSetting level]
+    }
+
+    frame $inner.separator1 -height 2 -relief sunken -bd 1
+    frame $inner.separator2 -height 2 -relief sunken -bd 1
+
+    blt::table $inner \
+        0,0 $inner.field_l -anchor w -pady 2 \
+        0,1 $inner.field -anchor w -pady 2 -fill x \
+        1,0 $inner.colormap_l -anchor w -pady 2  \
+        1,1 $inner.colormap   -anchor w -pady 2 -fill x  \
+        2,0 $inner.backingcolor_l  -anchor w -pady 2  \
+        2,1 $inner.backingcolor    -anchor w -pady 2 -fill x  \
+	3,0 $inner.background_l -anchor w -pady 2 \
+	3,1 $inner.background -anchor w -pady 2  -fill x \
+        4,0 $inner.backing -anchor w -pady 2 -cspan 2 \
+        5,0 $inner.stretch    -anchor w -pady 2 -cspan 2 \
+        7,0 $inner.legend     -anchor w -pady 2 -cspan 2 \
+        8,0 $inner.colormapDiscrete -anchor w -pady 2 -cspan 2 \
+        11,0 $inner.separator1 -padx 2 -fill x -cspan 2 \
+        12,0 $inner.outline    -anchor w -pady 2 -cspan 2 \
+        13,0 $inner.separator2 -padx 2 -fill x -cspan 2 \
+        15,0 $inner.opacity_l -anchor w -pady 2 \
+        15,1 $inner.opacity   -fill x   -pady 2 \
+        16,0 $inner.window_l -anchor w -pady 2 \
+        16,1 $inner.window   -fill x   -pady 2 \
+        17,0 $inner.level_l -anchor w -pady 2 \
+        17,1 $inner.level   -fill x   -pady 2 
+
+    blt::table configure $inner r* c* -resize none
+    blt::table configure $inner r19 c1 -resize expand
+}
+
+itcl::body Rappture::VtkImageViewer::BuildAxisTab {} {
+
+    set fg [option get $itk_component(hull) font Font]
+    #set bfg [option get $itk_component(hull) boldFont Font]
+
+    set inner [$itk_component(main) insert end \
+        -title "Axis Settings" \
+        -icon [Rappture::icon axis2]]
+    $inner configure -borderwidth 4
+
+    checkbutton $inner.visible \
+        -text "Axes" \
+        -variable [itcl::scope _settings(axisVisible)] \
+        -command [itcl::code $this AdjustSetting axisVisible] \
+        -font "Arial 9"
+    checkbutton $inner.labels \
+        -text "Axis Labels" \
+        -variable [itcl::scope _settings(axisLabels)] \
+        -command [itcl::code $this AdjustSetting axisLabels] \
+        -font "Arial 9"
+    label $inner.grid_l -text "Grid" -font "Arial 9" 
+    checkbutton $inner.xgrid \
+        -text "X" \
+        -variable [itcl::scope _settings(axisXGrid)] \
+        -command [itcl::code $this AdjustSetting axisXGrid] \
+        -font "Arial 9"
+    checkbutton $inner.ygrid \
+        -text "Y" \
+        -variable [itcl::scope _settings(axisYGrid)] \
+        -command [itcl::code $this AdjustSetting axisYGrid] \
+        -font "Arial 9"
+    checkbutton $inner.zgrid \
+        -text "Z" \
+        -variable [itcl::scope _settings(axisZGrid)] \
+        -command [itcl::code $this AdjustSetting axisZGrid] \
+        -font "Arial 9"
+    checkbutton $inner.minorticks \
+        -text "Minor Ticks" \
+        -variable [itcl::scope _settings(axisMinorTicks)] \
+        -command [itcl::code $this AdjustSetting axisMinorTicks] \
+        -font "Arial 9"
+
+
+    label $inner.mode_l -text "Mode" -font "Arial 9" 
+
+    itk_component add axisflymode {
+        Rappture::Combobox $inner.mode -width 10 -editable no
+    }
+    $inner.mode choices insert end \
+        "static_triad"    "static" \
+        "closest_triad"   "closest" \
+        "furthest_triad"  "farthest" \
+        "outer_edges"     "outer"         
+    $itk_component(axisflymode) value "static"
+    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting axisFlymode]
+
+    blt::table $inner \
+        0,0 $inner.visible -anchor w -cspan 4 \
+        1,0 $inner.labels  -anchor w -cspan 4 \
+        2,0 $inner.minorticks  -anchor w -cspan 4 \
+	4,0 $inner.grid_l  -anchor w \
+        4,1 $inner.xgrid   -anchor w \
+        4,2 $inner.ygrid   -anchor w \
+        4,3 $inner.zgrid   -anchor w \
+        5,0 $inner.mode_l  -anchor w -padx { 2 0 } \
+        5,1 $inner.mode    -fill x -cspan 3 
+
+    blt::table configure $inner r* c* -resize none
+    blt::table configure $inner r7 c6 -resize expand
+    blt::table configure $inner r3 -height 0.125i
+}
+
+
+itcl::body Rappture::VtkImageViewer::BuildCameraTab {} {
+    set inner [$itk_component(main) insert end \
+        -title "Camera Settings" \
+        -icon [Rappture::icon camera]]
+    $inner configure -borderwidth 4
+
+    label $inner.view_l -text "view" -font "Arial 9"
+    set f [frame $inner.view]
+    foreach side { front back left right top bottom } {
+        button $f.$side  -image [Rappture::icon view$side] \
+            -command [itcl::code $this SetOrientation $side]
+        Rappture::Tooltip::for $f.$side "Change the view to $side"
+        pack $f.$side -side left
+    }
+
+    blt::table $inner \
+        0,0 $inner.view_l -anchor e -pady 2 \
+        0,1 $inner.view -anchor w -pady 2
+
+    set labels { qx qy qz qw xpan ypan zoom }
+    set row 1
+    foreach tag $labels {
+        label $inner.${tag}label -text $tag -font "Arial 9"
+        entry $inner.${tag} -font "Arial 9"  -bg white \
+            -textvariable [itcl::scope _view($tag)]
+        bind $inner.${tag} <Return> \
+            [itcl::code $this camera set ${tag}]
+        bind $inner.${tag} <KP_Enter> \
+            [itcl::code $this camera set ${tag}]
+        blt::table $inner \
+            $row,0 $inner.${tag}label -anchor e -pady 2 \
+            $row,1 $inner.${tag} -anchor w -pady 2
+        blt::table configure $inner r$row -resize none
+        incr row
+    }
+    checkbutton $inner.ortho \
+        -text "Orthographic Projection" \
+        -variable [itcl::scope _view(ortho)] \
+        -command [itcl::code $this camera set ortho] \
+        -font "Arial 9"
+    blt::table $inner \
+            $row,0 $inner.ortho -cspan 2 -anchor w -pady 2
+    blt::table configure $inner r$row -resize none
+    incr row
+
+    blt::table configure $inner c* r* -resize none
+    blt::table configure $inner c2 -resize expand
+    blt::table configure $inner r$row -resize expand
+}
+
+#
+#  camera -- 
+#
+itcl::body Rappture::VtkImageViewer::camera {option args} {
+    switch -- $option { 
+        "show" {
+            puts [array get _view]
+        }
+        "set" {
+            set who [lindex $args 0]
+            set x $_view($who)
+            set code [catch { string is double $x } result]
+            if { $code != 0 || !$result } {
+                return
+            }
+            switch -- $who {
+                "ortho" {
+                    if {$_view(ortho)} {
+                        SendCmd "camera mode ortho"
+                    } else {
+                        SendCmd "camera mode persp"
+                    }
+                }
+                "xpan" - "ypan" {
+                    PanCamera
+                }
+                "qx" - "qy" - "qz" - "qw" {
+                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+                    $_arcball quaternion $q
+                    EventuallyRotate $q
+                }
+                "zoom" {
+                    SendCmd "camera zoom $_view(zoom)"
+                }
+            }
+        }
+    }
+}
+
+itcl::body Rappture::VtkImageViewer::GetVtkData { args } {
+    set bytes ""
+    foreach dataobj [get] {
+        foreach comp [$dataobj components] {
+            set tag $dataobj-$comp
+            set contents [$dataobj vtkdata $comp]
+            append bytes "$contents\n"
+        }
+    }
+    return [list .vtk $bytes]
+}
+
+itcl::body Rappture::VtkImageViewer::GetImage { args } {
+    if { [image width $_image(download)] > 0 && 
+         [image height $_image(download)] > 0 } {
+        set bytes [$_image(download) data -format "jpeg -quality 100"]
+        set bytes [Rappture::encoding::decode -as b64 $bytes]
+        return [list .jpg $bytes]
+    }
+    return ""
+}
+
+itcl::body Rappture::VtkImageViewer::BuildDownloadPopup { popup command } {
+    Rappture::Balloon $popup \
+        -title "[Rappture::filexfer::label downloadWord] as..."
+    set inner [$popup component inner]
+    label $inner.summary -text "" -anchor w 
+    radiobutton $inner.vtk_button -text "VTK data file" \
+        -variable [itcl::scope _downloadPopup(format)] \
+        -font "Arial 9 " \
+        -value vtk  
+    Rappture::Tooltip::for $inner.vtk_button "Save as VTK data file."
+    radiobutton $inner.image_button -text "Image File" \
+        -variable [itcl::scope _downloadPopup(format)] \
+        -font "Arial 9 " \
+        -value image 
+    Rappture::Tooltip::for $inner.image_button \
+        "Save as digital image."
+
+    button $inner.ok -text "Save" \
+        -highlightthickness 0 -pady 2 -padx 3 \
+        -command $command \
+        -compound left \
+        -image [Rappture::icon download]
+
+    button $inner.cancel -text "Cancel" \
+        -highlightthickness 0 -pady 2 -padx 3 \
+        -command [list $popup deactivate] \
+        -compound left \
+        -image [Rappture::icon cancel]
+
+    blt::table $inner \
+        0,0 $inner.summary -cspan 2  \
+        1,0 $inner.vtk_button -anchor w -cspan 2 -padx { 4 0 } \
+        2,0 $inner.image_button -anchor w -cspan 2 -padx { 4 0 } \
+        4,1 $inner.cancel -width .9i -fill y \
+        4,0 $inner.ok -padx 2 -width .9i -fill y 
+    blt::table configure $inner r3 -height 4
+    blt::table configure $inner r4 -pady 4
+    raise $inner.image_button
+    $inner.vtk_button invoke
+    return $inner
+}
+
+#
+# SetObjectStyle --
+#
+#       Set the style of the image/contour object.  This gets calls 
+#       for each dataset once as it is loaded.  It can overridden by
+#       the user controls.
+#
+#
+itcl::body Rappture::VtkImageViewer::SetObjectStyle { dataobj comp } {
+    # Parse style string.
+    set tag $dataobj-$comp
+    array set style {
+        -color none
+        -opacity 1.0
+    }
+    set stylelist [$dataobj style $comp]
+    if { $stylelist != "" } {
+        array set style $stylelist
+    }
+    # This is too complicated.  We want to set the colormap, number of
+    # isolines and opacity for the dataset.  They can be the default values,
+    # the style hints loaded with the dataset, or set by user controls.  As
+    # datasets get loaded, they first use the defaults that are overidden
+    # by the style hints.  If the user changes the global controls, then that
+    # overrides everything else.  I don't know what it means when global
+    # controls are specified as style hints by each dataset.  It complicates
+    # the code to handle aberrant cases.
+
+    if { $_changed(opacity) } {
+        set style(-opacity) [expr $_settings(opacity) * 0.01]
+    }
+    if { $_changed(colormap) } {
+        set style(-color) $_settings(colormap)
+    }
+    if { $_currentColormap == "" } {
+        $itk_component(colormap) value $style(-color)
+    }
+    if { [info exists style(-stretchtofit)] } {
+        set _settings(stretchToFit) $style(-stretchtofit)
+        AdjustSetting stretchToFit
+    }
+    SendCmd "outline add $tag"
+    SendCmd "outline color [Color2RGB $itk_option(-plotforeground)] $tag"
+    SendCmd "outline visible $_settings(outline) $tag"
+    SendCmd "image add $tag"
+    SetCurrentColormap $style(-color) 
+    set color [$itk_component(backingcolor) value]
+    SendCmd "image color [Color2RGB $color] $tag"
+    SendCmd "image opacity $style(-opacity) $tag"
+    set _settings(opacity) [expr $style(-opacity) * 100.0]
+}
+
+itcl::body Rappture::VtkImageViewer::IsValidObject { dataobj } {
+    if {[catch {$dataobj isa Rappture::Field} valid] != 0 || !$valid} {
+        return 0
+    }
+    return 1
+}
+
+# ----------------------------------------------------------------------
+# USAGE: ReceiveLegend <colormap> <title> <min> <max> <size>
+#
+# Invoked automatically whenever the "legend" command comes in from
+# the rendering server.  Indicates that binary image data with the
+# specified <size> will follow.
+# ----------------------------------------------------------------------
+itcl::body Rappture::VtkImageViewer::ReceiveLegend { colormap title min max size } {
+    #puts stderr "ReceiveLegend colormap=$colormap title=$title range=$min,$max size=$size"
+    if { [isconnected] } {
+        set bytes [ReceiveBytes $size]
+        if { ![info exists _image(legend)] } {
+            set _image(legend) [image create photo]
+        }
+        $_image(legend) configure -data $bytes
+        #puts stderr "read $size bytes for [image width $_image(legend)]x[image height $_image(legend)] legend>"
+        if { [catch {DrawLegend} errs] != 0 } {
+	    global errorInfo
+	    puts stderr "errs=$errs errorInfo=$errorInfo"
+        }
+    }
+}
+
+#
+# DrawLegend --
+#
+#       Draws the legend in the own canvas on the right side of the plot area.
+#
+itcl::body Rappture::VtkImageViewer::DrawLegend {} {
+    set fname $_curFldName
+    set c $itk_component(view)
+    set w [winfo width $c]
+    set h [winfo height $c]
+    set font "Arial 8"
+    set lineht [font metrics $font -linespace]
+    
+    if { [string match "component*" $fname] } {
+	set title ""
+    } else {
+	if { [info exists _fields($fname)] } {
+	    foreach { title units } $_fields($fname) break
+	    if { $units != "" } {
+		set title [format "%s (%s)" $title $units]
+	    }
+	} else {
+	    set title $fname
+	}
+    }
+    set x [expr $w - 2]
+    if { !$_settings(legendVisible) } {
+	$c delete legend
+	return
+    } 
+    if { [$c find withtag "legend"] == "" } {
+	set y 2 
+	# If there's a legend title, create a text item for the title.
+        $c create text $x $y \
+	    -anchor ne \
+	    -fill $itk_option(-plotforeground) -tags "title legend" \
+	    -font $font 
+        if { $title != "" } {
+            incr y $lineht
+        }
+	$c create text $x $y \
+	    -anchor ne \
+	    -fill $itk_option(-plotforeground) -tags "vmax legend" \
+	    -font $font
+	incr y $lineht
+	$c create image $x $y \
+	    -anchor ne \
+	    -image $_image(legend) -tags "colormap legend"
+	$c create rectangle $x $y 1 1 \
+	    -fill "" -outline "" -tags "sensor legend"
+	$c create text $x [expr {$h-2}] \
+	    -anchor se \
+	    -fill $itk_option(-plotforeground) -tags "vmin legend" \
+	    -font $font
+	$c bind sensor <Enter> [itcl::code $this EnterLegend %x %y]
+	$c bind sensor <Leave> [itcl::code $this LeaveLegend]
+	$c bind sensor <Motion> [itcl::code $this MotionLegend %x %y]
+    }
+
+    set x2 $x
+    set iw [image width $_image(legend)]
+    set ih [image height $_image(legend)]
+    set x1 [expr $x2 - ($iw*12)/10]
+
+    $c bind title <ButtonPress> [itcl::code $this Combo post]
+    $c bind title <Enter> [itcl::code $this Combo activate]
+    $c bind title <Leave> [itcl::code $this Combo deactivate]
+    # Reset the item coordinates according the current size of the plot.
+    if { [info exists _limits($_curFldName)] } {
+        foreach { vmin vmax } $_limits($_curFldName) break
+	$c itemconfigure vmin -text [format %g $vmin]
+	$c itemconfigure vmax -text [format %g $vmax]
+    }
+    set y 2
+    # If there's a legend title, move the title to the correct position
+    if { $title != "" } {
+        $c itemconfigure title -text $title
+	$c coords title $x $y
+	incr y $lineht
+    }
+    $c coords vmax $x $y
+    incr y $lineht
+    $c coords colormap $x $y
+    $c coords sensor [expr $x - $iw] $y $x [expr $y + $ih]
+    $c raise sensor
+    $c coords vmin $x [expr {$h - 2}]
+}
+
+#
+# EnterLegend --
+#
+itcl::body Rappture::VtkImageViewer::EnterLegend { x y } {
+    SetLegendTip $x $y
+}
+
+#
+# MotionLegend --
+#
+itcl::body Rappture::VtkImageViewer::MotionLegend { x y } {
+    Rappture::Tooltip::tooltip cancel
+    set c $itk_component(view)
+    set cw [winfo width $c]
+    set ch [winfo height $c]
+    if { $x >= 0 && $x < $cw && $y >= 0 && $y < $ch } {
+        SetLegendTip $x $y
+    }
+}
+
+#
+# LeaveLegend --
+#
+itcl::body Rappture::VtkImageViewer::LeaveLegend { } {
+    Rappture::Tooltip::tooltip cancel
+    .rappturetooltip configure -icon ""
+}
+
+#
+# SetLegendTip --
+#
+itcl::body Rappture::VtkImageViewer::SetLegendTip { x y } {
+    set fname $_curFldName
+    set c $itk_component(view)
+    set w [winfo width $c]
+    set h [winfo height $c]
+    set font "Arial 8"
+    set lineht [font metrics $font -linespace]
+    
+    set ih [image height $_image(legend)]
+    # Subtract off the offset of the color ramp from the top of the canvas
+    set iy [expr $y - ($lineht + 2)]
+
+    if { [string match "component*" $fname] } {
+	set title ""
+    } else {
+	if { [info exists _fields($fname)] } {
+	    foreach { title units } $_fields($fname) break
+	    if { $units != "" } {
+		set title [format "%s (%s)" $title $units]
+	    }
+	} else {
+	    set title $fname
+	}
+    }
+    # If there's a legend title, increase the offset by the line height.
+    if { $title != "" } {
+        incr iy -$lineht
+    }
+
+    # Make a swatch of the selected color
+    if { [catch { $_image(legend) get 10 $iy } pixel] != 0 } {
+        return
+    }
+
+    if { ![info exists _image(swatch)] } {
+        set _image(swatch) [image create photo -width 24 -height 24]
+    }
+    set color [eval format "\#%02x%02x%02x" $pixel]
+    $_image(swatch) put black  -to 0 0 23 23 
+    $_image(swatch) put $color -to 1 1 22 22 
+
+    # Compute the value of the point
+    if { [info exists _limits($fname)] } {
+        foreach { vmin vmax } $_limits($fname) break
+        set t [expr 1.0 - (double($iy) / double($ih-1))]
+        set value [expr $t * ($vmax - $vmin) + $vmin]
+    } else {
+        set value 0.0
+    }
+    set tipx [expr $x + 15] 
+    set tipy [expr $y - 5]
+    .rappturetooltip configure -icon $_image(swatch)
+    if { [info exists _isolines($y)] } {
+        Rappture::Tooltip::text $c [format "$title %g (isoline)" $_isolines($y)]
+    } else {
+        Rappture::Tooltip::text $c [format "$title %g" $value]
+    }
+    Rappture::Tooltip::tooltip show $c +$tipx,+$tipy    
+}
+
+# ----------------------------------------------------------------------
+# 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::VtkImageViewer::Combo {option} {
+    set c $itk_component(view) 
+    switch -- $option {
+        post {
+            foreach { x1 y1 x2 y2 } [$c bbox title] break
+            set x1 [expr [winfo width $itk_component(view)] - [winfo reqwidth $itk_component(fieldmenu)]]
+            set x [expr $x1 + [winfo rootx $itk_component(view)]]
+            set y [expr $y2 + [winfo rooty $itk_component(view)]]
+            tk_popup $itk_component(fieldmenu) $x $y
+        }
+        activate {
+            $c itemconfigure title -fill red
+        }
+        deactivate {
+            $c itemconfigure title -fill $itk_option(-plotforeground) 
+        }
+        invoke {
+            $itk_component(field) value $_curFldLabel
+            AdjustSetting field
+        }
+        default {
+            error "bad option \"$option\": should be post, unpost, select"
+        }
+    }
+}
+
+itcl::body Rappture::VtkImageViewer::SetOrientation { side } { 
+    array set positions {
+        front  "0.707107 0.707107 0 0"
+        back   "0 0 0.707107 0.707107"
+        left   "0.5 0.5 -0.5 -0.5"
+        right  "0.5 0.5 0.5 0.5"
+        top    "1 0 0 0"
+        bottom "0 1 0 0"
+    }
+    foreach name { qw qx qy qz } value $positions($side) {
+        set _view($name) $value
+    } 
+    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+    $_arcball quaternion $q
+    SendCmd "camera orient $q"
+    SendCmd "camera reset"
+    set _view(xpan) 0
+    set _view(ypan) 0
+    set _view(zoom) 1.0
+}
Index: branches/1.3/gui/scripts/vtkisosurfaceviewer.tcl
===================================================================
--- branches/1.3/gui/scripts/vtkisosurfaceviewer.tcl	(revision 4511)
+++ branches/1.3/gui/scripts/vtkisosurfaceviewer.tcl	(revision 4512)
@@ -63,22 +63,7 @@
     public method scale {args}
 
-    protected method Connect {}
-    protected method CurrentDatasets {args}
-    protected method Disconnect {}
-    protected method DoResize {}
-    protected method DoRotate {}
-    protected method DoChangeContourLevels {}
-    protected method AdjustSetting {what {value ""}}
-    protected method InitSettings { args  }
-    protected method Pan {option x y}
-    protected method Pick {x y}
-    protected method Rebuild {}
-    protected method ReceiveDataset { args }
-    protected method ReceiveImage { args }
-    protected method ReceiveLegend { colormap title vmin vmax size }
-    protected method Rotate {option x y}
-    protected method Zoom {option}
-
     # The following methods are only used by this class.
+
+    private method AdjustSetting {what {value ""}}
     private method BuildAxisTab {}
     private method BuildCameraTab {}
@@ -88,24 +73,42 @@
     private method BuildIsosurfaceTab {}
     private method Combo { option }
+    private method Connect {}
+    private method CurrentDatasets {args}
+    private method Disconnect {}
+    private method DoChangeContourLevels {}
+    private method DoResize {}
+    private method DoRotate {}
     private method DrawLegend {}
     private method EnterLegend { x y } 
+    private method EventuallyChangeContourLevels {} 
+    private method EventuallyRequestLegend {} 
     private method EventuallyResize { w h } 
-    private method EventuallyChangeContourLevels {} 
     private method EventuallyRotate { q } 
-    private method EventuallyRequestLegend {} 
     private method EventuallySetCutplane { axis args } 
+    private method GenerateContourList {}
     private method GetImage { args } 
     private method GetVtkData { args } 
+    private method InitSettings { args  }
     private method IsValidObject { dataobj } 
     private method LeaveLegend {}
     private method MotionLegend { x y } 
+    private method Pan {option x y}
     private method PanCamera {}
+    private method Pick {x y}
+    private method Rebuild {}
+    private method ReceiveDataset { args }
+    private method ReceiveImage { args }
+    private method ReceiveLegend { colormap title vmin vmax size }
     private method RequestLegend {}
+    private method Rotate {option x y}
+    private method SetCurrentColormap { color }
     private method SetLegendTip { x y }
     private method SetObjectStyle { dataobj comp } 
+    private method SetOrientation { side }
     private method Slice {option args} 
-    private method SetCurrentColormap { color }
-    private method SetOrientation { side }
-    private method GenerateContourList {}
+    private method Zoom {option}
+    private method ViewToQuaternion {} { 
+        return [list $_view(-qw) $_view(-qx) $_view(-qy) $_view(-qz)]
+    }
 
     private variable _arcball ""
@@ -216,16 +219,15 @@
     # Initialize the view to some default parameters.
     array set _view {
-        qw              0.853553
-        qx              -0.353553
-        qy              0.353553
-        qz              0.146447
-        zoom            1.0 
-        xpan            0
-        ypan            0
-        ortho           0
+        -ortho           0
+        -qw              0.853553
+        -qx              -0.353553
+        -qy              0.353553
+        -qz              0.146447
+        -xpan            0
+        -ypan            0
+        -zoom            1.0 
     }
     set _arcball [blt::arcball create 100 100]
-    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
-    $_arcball quaternion $q
+    $_arcball quaternion [ViewToQuaternion]
 
     array set _contourList {
@@ -275,6 +277,6 @@
     }
     array set _widget {
-        -isosurfaceopacity       0
-        -cutplaneopacity         0
+        -isosurfaceopacity       60
+        -cutplaneopacity         100
     }
 
@@ -496,6 +498,5 @@
 
 itcl::body Rappture::VtkIsosurfaceViewer::DoRotate {} {
-    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
-    SendCmd "camera orient $q" 
+    SendCmd "camera orient [ViewToQuaternion]" 
     set _rotatePending 0
 }
@@ -521,5 +522,5 @@
 
 itcl::body Rappture::VtkIsosurfaceViewer::EventuallyRotate { q } {
-    foreach { _view(qw) _view(qx) _view(qy) _view(qz) } $q break
+    foreach { _view(-qw) _view(-qx) _view(-qy) _view(-qz) } $q break
     if { !$_rotatePending } {
         set _rotatePending 1
@@ -982,19 +983,12 @@
         $_arcball resize $w $h
         DoResize
-        #
+
         # Reset the camera and other view parameters
-        #
-        set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
-        $_arcball quaternion $q
-        if {$_view(ortho)} {
-            SendCmd "camera mode ortho"
-        } else {
-            SendCmd "camera mode persp"
-        }
+        $_arcball quaternion [ViewToQuaternion]
         DoRotate
         PanCamera
         set _first ""
         InitSettings -xgrid -ygrid -zgrid -axismode \
-            -axesvisible -axislabelsvisible 
+            -axesvisible -axislabelsvisible -ortho
         SendCmd "axis lformat all %g"
         # Too many major ticks, so turn off minor ticks
@@ -1181,20 +1175,20 @@
     switch -- $option {
         "in" {
-            set _view(zoom) [expr {$_view(zoom)*1.25}]
-            SendCmd "camera zoom $_view(zoom)"
+            set _view(-zoom) [expr {$_view(-zoom)*1.25}]
+            SendCmd "camera zoom $_view(-zoom)"
         }
         "out" {
-            set _view(zoom) [expr {$_view(zoom)*0.8}]
-            SendCmd "camera zoom $_view(zoom)"
+            set _view(-zoom) [expr {$_view(-zoom)*0.8}]
+            SendCmd "camera zoom $_view(-zoom)"
         }
         "reset" {
             array set _view {
-                qw     0.853553
-                qx     -0.353553
-                qy     0.353553
-                qz     0.146447
-                zoom   1.0
-                xpan   0
-                ypan   0
+                -qw     0.853553
+                -qx     -0.353553
+                -qy     0.353553
+                -qz     0.146447
+                -xpan   0
+                -ypan   0
+                -zoom   1.0
             }
             if { $_first != "" } {
@@ -1204,6 +1198,5 @@
                 }
             }
-            set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
-            $_arcball quaternion $q
+            $_arcball quaternion [ViewToQuaternion]
             DoRotate
             SendCmd "camera reset"
@@ -1213,6 +1206,6 @@
 
 itcl::body Rappture::VtkIsosurfaceViewer::PanCamera {} {
-    set x $_view(xpan)
-    set y $_view(ypan)
+    set x $_view(-xpan)
+    set y $_view(-ypan)
     SendCmd "camera pan $x $y"
 }
@@ -1292,6 +1285,6 @@
             set x [expr $x / double($w)]
             set y [expr $y / double($h)]
-            set _view(xpan) [expr $_view(xpan) + $x]
-            set _view(ypan) [expr $_view(ypan) + $y]
+            set _view(-xpan) [expr $_view(-xpan) + $x]
+            set _view(-ypan) [expr $_view(-ypan) + $y]
             PanCamera
             return
@@ -1315,6 +1308,6 @@
             set _click(x) $x
             set _click(y) $y
-            set _view(xpan) [expr $_view(xpan) - $dx]
-            set _view(ypan) [expr $_view(ypan) - $dy]
+            set _view(-xpan) [expr $_view(-xpan) - $dx]
+            set _view(-ypan) [expr $_view(-ypan) - $dy]
             PanCamera
         }
@@ -1358,4 +1351,23 @@
     }
     switch -- $what {
+        "-axesvisible" {
+            set bool $_settings($what)
+            SendCmd "axis visible all $bool"
+        }
+        "-axislabelsvisible" {
+            set bool $_settings($what)
+            SendCmd "axis labels all $bool"
+        }
+        "-xgrid" - "-ygrid" - "-zgrid" {
+            set axis [string tolower [string range $what 1 1]]
+            set bool $_settings($what)
+            SendCmd "axis grid $axis $bool"
+        }
+        "-axismode" {
+            set mode [$itk_component(axisMode) value]
+            set mode [$itk_component(axisMode) translate $mode]
+            set _settings($what) $mode
+            SendCmd "axis flymode $mode"
+        }
         "-background" {
             set bgcolor [$itk_component(background) value]
@@ -1370,26 +1382,19 @@
 	    DrawLegend
         }
-        "-axesvisible" {
-            set bool $_settings(-axesvisible)
-            SendCmd "axis visible all $bool"
-        }
-        "-axislabelsvisible" {
-            set bool $_settings(-axislabelsvisible)
-            SendCmd "axis labels all $bool"
-        }
-        "-xgrid" - "-ygrid" - "-zgrid" {
-            set axis [string tolower [string range $what 1 1]]
-            set bool $_settings($what)
-            SendCmd "axis grid $axis $bool"
-        }
-        "-axismode" {
-            set mode [$itk_component(axisMode) value]
-            set mode [$itk_component(axisMode) translate $mode]
-            set _settings($what) $mode
-            SendCmd "axis flymode $mode"
-        }
         "-cutplaneedges" {
             set bool $_settings($what)
             SendCmd "cutplane edges $bool"
+        }
+        "-cutplanelighting" {
+            set bool $_settings($what)
+            SendCmd "cutplane lighting $bool"
+        }
+        "-cutplaneopacity" {
+            set _settings($what) [expr $_widget($what) * 0.01]
+            SendCmd "cutplane opacity $_settings($what)"
+        }
+        "-cutplanepreinterp" {
+            set bool $_settings($what)
+            SendCmd "cutplane preinterp $bool"
         }
         "-cutplanesvisible" {
@@ -1413,39 +1418,9 @@
             SendCmd "cutplane wireframe $bool"
         }
-        "-cutplanelighting" {
-            set bool $_settings($what)
-            SendCmd "cutplane lighting $bool"
-        }
-        "-cutplaneopacity" {
-            set _settings($what) [$_widget(-cutplaneopacity) * 0.01]
-            SendCmd "cutplane opacity $_settings($what)"
-        }
-        "-cutplanepreinterp" {
-            set bool $_settings($what)
-            SendCmd "cutplane preinterp $bool"
-        }
-        "-xcutplanevisible" - "-ycutplanevisible" - "-zcutplanevisible" {
-            set axis [string tolower [string range $what 1 1]]
-            set bool $_settings($what)
-            if { $bool } {
-                $itk_component(${axis}position) configure -state normal \
-                    -troughcolor white
-            } else {
-                $itk_component(${axis}position) configure -state disabled \
-                    -troughcolor grey82
-            }
-	    SendCmd "cutplane axis $axis $bool"
-        }
-        "-xcutplaneposition" - "-ycutplaneposition" - "-zcutplaneposition" {
-            set axis [string tolower [string range $what 1 1]]
-            set pos [expr $_settings($what) * 0.01]
-            SendCmd "cutplane slice ${axis} ${pos}"
-            set _cutplanePending 0
-        }
         "-colormap" {
             set _changed($what) 1
             StartBufferingCommands
             set color [$itk_component(colormap) value]
-            set _settings(-colormap) $color
+            set _settings($what) $color
 	    if { $color == "none" } {
 		if { $_settings(-colormapvisible) } {
@@ -1463,57 +1438,4 @@
 	    EventuallyRequestLegend
         }
-        "-numcontours" {
-            set _settings($what) [$itk_component(numcontours) value]
-            if { $_contourList(numLevels) != $_settings($what) } {
-                set _contourList(numLevels) $_settings($what)
-                EventuallyChangeContourLevels
-            }
-        }
-        "-isosurfacewireframe" {
-            set bool $_settings($what)
-	    SendCmd "contour3d wireframe $bool"
-        }
-        "-isosurfacevisible" {
-            set bool $_settings($what)
-	    SendCmd "contour3d visible 0"
-            if { $bool } {
-                foreach tag [CurrentDatasets -visible] {
-                    SendCmd "contour3d visible $bool $tag"
-                }
-            }
-            if { $bool } {
-                Rappture::Tooltip::for $itk_component(contour) \
-                    "Hide the isosurface"
-            } else {
-                Rappture::Tooltip::for $itk_component(contour) \
-                    "Show the isosurface"
-            }
-        }
-        "-isosurfacelighting" {
-            set bool $_settings($what)
-	    SendCmd "contour3d lighting $bool"
-        }
-        "-isosurfaceedges" {
-            set bool $_settings($what)
-	    SendCmd "contour3d edges $bool"
-        }
-        "-outline" {
-            set bool $_settings($what)
-	    SendCmd "outline visible 0"
-            if { $bool } {
-                foreach tag [CurrentDatasets -visible] {
-                    SendCmd "outline visible $bool $tag"
-                }
-            }
-        }
-        "-isolinecolor" {
-            set color [$itk_component(isolineColor) value]
-	    set _settings($what) $color
-	    DrawLegend
-        }
-        "-isosurfaceopacity" {
-            set _settings($what) [$_widget(-isosurfaceopacity) * 0.01]
-	    SendCmd "contour3d opacity $_settings($what)"
-        }
         "-field" {
             set label [$itk_component(field) value]
@@ -1542,6 +1464,44 @@
             SendCmd "contour3d colormode $_colorMode $_curFldName"
             SendCmd "camera reset"
-            UpdateContourList
+            GenerateContourList
             DrawLegend
+        }
+        "-isolinecolor" {
+            set color [$itk_component(isolineColor) value]
+            set _settings(-isolinecolor) $color
+	    set _settings($what) $color
+	    DrawLegend
+        }
+        "-isosurfaceedges" {
+            set bool $_settings($what)
+	    SendCmd "contour3d edges $bool"
+        }
+        "-isosurfacelighting" {
+            set bool $_settings($what)
+	    SendCmd "contour3d lighting $bool"
+        }
+        "-isosurfaceopacity" {
+            set _settings($what) [expr $_widget($what) * 0.01]
+	    SendCmd "contour3d opacity $_settings($what)"
+        }
+        "-isosurfacevisible" {
+            set bool $_settings($what)
+	    SendCmd "contour3d visible 0"
+            if { $bool } {
+                foreach tag [CurrentDatasets -visible] {
+                    SendCmd "contour3d visible $bool $tag"
+                }
+            }
+            if { $bool } {
+                Rappture::Tooltip::for $itk_component(contour) \
+                    "Hide the isosurface"
+            } else {
+                Rappture::Tooltip::for $itk_component(contour) \
+                    "Show the isosurface"
+            }
+        }
+        "-isosurfacewireframe" {
+            set bool $_settings($what)
+	    SendCmd "contour3d wireframe $bool"
         }
         "-legendvisible" {
@@ -1550,4 +1510,46 @@
 	    }
 	    DrawLegend
+        }
+        "-numcontours" {
+            set _settings($what) [$itk_component(numcontours) value]
+            if { $_contourList(numLevels) != $_settings($what) } {
+                set _contourList(numLevels) $_settings($what)
+                EventuallyChangeContourLevels
+            }
+        }
+        "-ortho" {
+            set bool $_view($what)
+            if { $bool } {
+                SendCmd "camera mode ortho"
+            } else {
+                SendCmd "camera mode persp"
+            }
+        }
+        "-outline" {
+            set bool $_settings($what)
+	    SendCmd "outline visible 0"
+            if { $bool } {
+                foreach tag [CurrentDatasets -visible] {
+                    SendCmd "outline visible $bool $tag"
+                }
+            }
+        }
+        "-xcutplanevisible" - "-ycutplanevisible" - "-zcutplanevisible" {
+            set axis [string tolower [string range $what 1 1]]
+            set bool $_settings($what)
+            if { $bool } {
+                $itk_component(${axis}position) configure -state normal \
+                    -troughcolor white
+            } else {
+                $itk_component(${axis}position) configure -state disabled \
+                    -troughcolor grey82
+            }
+	    SendCmd "cutplane axis $axis $bool"
+        }
+        "-xcutplaneposition" - "-ycutplaneposition" - "-zcutplaneposition" {
+            set axis [string tolower [string range $what 1 1]]
+            set pos [expr $_settings($what) * 0.01]
+            SendCmd "cutplane slice ${axis} ${pos}"
+            set _cutplanePending 0
         }
         default {
@@ -1722,5 +1724,6 @@
         -showvalue off \
         -command [itcl::code $this AdjustSetting -isosurfaceopacity]
-    $inner.opacity set [expr $_settings(-isosurfaceeopacity) * 100.0]
+    set _widget(-isosurfaceopacity) \
+        [expr $_settings(-isosurfaceopacity) * 100.0]
 
     itk_component add field_l {
@@ -1866,5 +1869,5 @@
         label $inner.${tag}label -text $tag -font "Arial 9"
         entry $inner.${tag} -font "Arial 9"  -bg white \
-            -textvariable [itcl::scope _view($tag)]
+            -textvariable [itcl::scope _view(-$tag)]
         bind $inner.${tag} <KeyPress-Return> \
             [itcl::code $this camera set ${tag}]
@@ -1877,6 +1880,6 @@
     checkbutton $inner.ortho \
         -text "Orthographic Projection" \
-        -variable [itcl::scope _view(ortho)] \
-        -command [itcl::code $this camera set ortho] \
+        -variable [itcl::scope _view(-ortho)] \
+        -command [itcl::code $this AdjustSetting -ortho] \
         -font "Arial 9"
     blt::table $inner \
@@ -1936,5 +1939,5 @@
         -showvalue off \
         -command [itcl::code $this AdjustSetting -cutplaneopacity]
-    $inner.opacity set [expr $_settings(-cutplaneopacity) * 100.0]
+    set _widget(-cutplaneopacity) [expr $_settings(-cutplaneopacity) * 100.0]
 
     # X-value slicer...
@@ -2057,13 +2060,13 @@
         }
         "set" {
-            set who [lindex $args 0]
-            set x $_view($who)
+            set what [lindex $args 0]
+            set x $_view($what)
             set code [catch { string is double $x } result]
             if { $code != 0 || !$result } {
                 return
             }
-            switch -- $who {
-                "ortho" {
-                    if {$_view(ortho)} {
+            switch -- $what {
+                "-ortho" {
+                    if {$_view($what)} {
                         SendCmd "camera mode ortho"
                     } else {
@@ -2071,14 +2074,14 @@
                     }
                 }
-                "xpan" - "ypan" {
+                "-xpan" - "-ypan" {
                     PanCamera
                 }
-                "qx" - "qy" - "qz" - "qw" {
-                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+                "-qx" - "-qy" - "-qz" - "-qw" {
+                    set q [ViewToQuaternion]
                     $_arcball quaternion $q
                     EventuallyRotate $q
                 }
-                "zoom" {
-                    SendCmd "camera zoom $_view(zoom)"
+                "-zoom" {
+                    SendCmd "camera zoom $_view(-zoom)"
                 }
              }
@@ -2588,14 +2591,14 @@
         bottom "0.707107 0.707107 0 0"
     }
-    foreach name { qw qx qy qz } value $positions($side) {
+    foreach name { -qw -qx -qy -qz } value $positions($side) {
         set _view($name) $value
     } 
-    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+    set q [ViewToQuaternion]
     $_arcball quaternion $q
     SendCmd "camera orient $q"
     SendCmd "camera reset"
-    set _view(xpan) 0
-    set _view(ypan) 0
-    set _view(zoom) 1.0
+    set _view(-xpan) 0
+    set _view(-ypan) 0
+    set _view(-zoom) 1.0
 }
 
Index: branches/1.3/gui/scripts/vtkmeshviewer.tcl
===================================================================
--- branches/1.3/gui/scripts/vtkmeshviewer.tcl	(revision 4511)
+++ branches/1.3/gui/scripts/vtkmeshviewer.tcl	(revision 4512)
@@ -86,5 +86,5 @@
     private method EventuallyResize { w h } 
     private method EventuallyRotate { q } 
-    private method EventuallySetPolydataOpacity { args } 
+    private method EventuallySetPolydataOpacity {} 
     private method GetImage { args } 
     private method GetVtkData { args } 
@@ -111,4 +111,5 @@
     private variable _view;             # view params for 3D view
     private variable _settings
+    private variable _widget
     private variable _style;            # Array of current component styles.
     private variable _initialStyle;     # Array of initial component styles.
@@ -128,4 +129,5 @@
     private variable _polydataOpacityPending 0
     private variable _rotateDelay 150
+    private variable _opacityDelay 150
 }
 
@@ -188,5 +190,5 @@
         -polydataedges          0
         -polydatalighting       1
-        -polydataopacity        100
+        -polydataopacity        0.6
         -polydatavisible        1
         -polydatawireframe      0
@@ -204,4 +206,7 @@
         -zposition              0
     }
+    array set _widget {
+        -polydataopacity        0.6
+    }        
     itk_component add view {
         canvas $itk_component(plotarea).view \
@@ -404,13 +409,11 @@
     set _polydataOpacityPending 0
     set val $_settings(-polydataopacity)
-    set sval [expr { 0.01 * double($val) }]
-    SendCmd "polydata opacity $sval"
-}
-
-itcl::body Rappture::VtkMeshViewer::EventuallySetPolydataOpacity { val } {
-    set _settings(-polydataopacity) $val
+    SendCmd "polydata opacity $val"
+}
+
+itcl::body Rappture::VtkMeshViewer::EventuallySetPolydataOpacity {} {
     if { !$_polydataOpacityPending } {
         set _polydataOpacityPending 1
-        $_dispatcher event -after $_scaleDelay !polydataOpacity
+        $_dispatcher event -after $_opacityDelay !polydataOpacity
     }
 }
@@ -868,8 +871,7 @@
         }
         lappend _obj2datasets($dataobj) $tag
-        if { [info exists _obj2ovride($dataobj-raise)] && 
-             $_obj2ovride($dataobj-raise) } {
+        if { [info exists _obj2ovride($dataobj-raise)] } {
             SendCmd "dataset visible 1 $tag"
-            SetOpacity $tag
+            EventuallySetPolydataOpacity
         }
     }
@@ -897,4 +899,8 @@
             -polydatavisible -polydatawireframe
  
+        SendCmd "axis lformat all %g"
+        # Too many major ticks, so turn off minor ticks
+        SendCmd "axis minticks all 0"
+
         set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
         $_arcball quaternion $q 
@@ -1350,9 +1356,9 @@
     label $inner.opacity_l -text "Opacity" -font "Arial 9" -anchor w 
     ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
-        -variable [itcl::scope _settings(-polydataopacity)] \
+        -variable [itcl::scope _widget(-polydataopacity)] \
         -width 10 \
         -showvalue off \
         -command [itcl::code $this AdjustSetting -polydataopacity]
-    $inner.opacity set $_settings(-polydataopacity)
+    $inner.opacity set [expr $_settings(-polydataopacity) * 100.0]
 
     blt::table $inner \
@@ -1735,9 +1741,9 @@
         -color white
         -edgecolor black
-        -lighting 1
         -linewidth 1.0
         -outline 0
         -polydataedges 1
-        -polydataopacity 1.0
+        -polydatalighting 1
+        -polydataopacity 0.6
         -polydatavisible 1
         -polydatawireframe 0
@@ -1770,5 +1776,6 @@
     SendCmd "polydata linewidth $settings(-linewidth) $tag"
     SendCmd "polydata opacity $settings(-polydataopacity) $tag"
-    set _settings(-polydataopacity) [expr 100.0 * $settings(-polydataopacity)]
+    set _settings(-polydataopacity) $settings(-polydataopacity)
+    set _widget(-polydataopacity) [expr 100.0 * $settings(-polydataopacity)]
     SendCmd "polydata wireframe $settings(-polydatawireframe) $tag"
     set _settings(-polydatawireframe) $settings(-polydatawireframe)
