Index: branches/1.3/gui/scripts/Makefile.in
===================================================================
--- branches/1.3/gui/scripts/Makefile.in	(revision 4501)
+++ branches/1.3/gui/scripts/Makefile.in	(revision 4504)
@@ -111,4 +111,5 @@
 		$(srcdir)/tool.tcl \
 		$(srcdir)/tooltip.tcl \
+		$(srcdir)/transferfunctioneditor.tcl \
 		$(srcdir)/tuples.tcl \
 		$(srcdir)/unirect2d.tcl \
Index: branches/1.3/gui/scripts/cloud.tcl
===================================================================
--- branches/1.3/gui/scripts/cloud.tcl	(revision 4501)
+++ branches/1.3/gui/scripts/cloud.tcl	(revision 4504)
@@ -149,6 +149,10 @@
         foreach {x y z} $line break
         foreach axis {x y z} units $_units {
-            set value [Rappture::Units::convert [set $axis] \
+            if { $units == "" } {
+                set value [set $axis]
+            } else {
+                set value [Rappture::Units::convert [set $axis] \
                         -context $units -to $units -units off]
+            }
             set $axis $value;           # Set the (x/y/z) coordinate to 
                                         # converted value.
Index: branches/1.3/gui/scripts/field.tcl
===================================================================
--- branches/1.3/gui/scripts/field.tcl	(revision 4501)
+++ branches/1.3/gui/scripts/field.tcl	(revision 4504)
@@ -1,4 +1,3 @@
 # -*- mode: tcl; indent-tabs-mode: nil -*- 
-
 # ----------------------------------------------------------------------
 #  COMPONENT: field - extracts data from an XML description of a field
@@ -82,4 +81,6 @@
                                         # valid data.
     private variable _isValidComponent; #  Array of valid components found
+    private variable _alwaysConvertDX 0;
+
     constructor {xmlobj path} { 
 	# defined below 
@@ -88,5 +89,5 @@
 	# defined below 
     }
-    public method blob { cname }
+    public method blob { cname }  
     public method components {args}
     public method controls {option args}
@@ -94,4 +95,5 @@
     public method numComponents {cname}
     public method fieldlimits {}
+    public method valueLimits { cname }
     public method flowhints { cname }
     public method hints {{key ""}}
@@ -150,4 +152,5 @@
 
     private method AvsToVtk { cname contents } 
+    private method DicomToVtk { cname contents } 
     private method BuildPointsOnMesh { cname } 
     protected method GetAssociation { cname } 
@@ -318,5 +321,5 @@
     }
     if {[info exists _comp2dx($cname)]} {
-        return ""  ;# no mesh -- it's embedded in the blob data
+        return ""  ;# no mesh -- it's embedded in the value data
     }
     if {[info exists _comp2mesh($cname)]} {
@@ -362,5 +365,5 @@
     }
     if {[info exists _comp2dx($cname)]} {
-        error "method \"values\" is not implemented for dx file data"
+        error "method \"values\" is not implemented for dx data"
     }
     if {[info exists _comp2unirect2d($cname)]} {
@@ -389,5 +392,5 @@
     }
     if {[info exists _comp2dx($cname)]} {
-        return $_comp2dx($cname)  ;# return gzipped, base64-encoded DX data
+        return $_comp2dx($cname)
     }
     if {[info exists _comp2unirect2d($cname)]} {
@@ -400,4 +403,11 @@
     }
     error "can't get field blob: Unknown component \"$cname\": should be one of [join [lsort [array names _comp2dims]] {, }]"
+}
+
+itcl::body Rappture::Field::valueLimits { cname } {
+    if { [info exists _comp2limits($cname)] } {
+        return $_comp2limits($cname)
+    }
+    return ""
 }
 
@@ -520,4 +530,5 @@
     return [list $min $max]
 }
+
 
 # ----------------------------------------------------------------------
@@ -789,4 +800,6 @@
         } elseif {[$_field element $cname.ucd] != ""} {
             set type "ucd"
+        } elseif {[$_field element $cname.dicom] != ""} {
+            set type "dicom"
 	}
         set _comp2style($cname) ""
@@ -894,32 +907,38 @@
             set _dim 3
             set _comp2dims($cname) "3D"
-            if { $_viewer != "nanovis" && $_viewer != "flowvis" } {
-                set vtkdata  [$_field get -decode yes $cname.$type]
-                if { $vtkdata == "" } {
-                    puts stderr "WARNING: No data for \"$_path.$cname.$type\""
-                    continue;               # Ignore this component
-                }
-                if 0 {
-                    set f [open /tmp/$_path.$cname.dx "w"]
-                    puts -nonewline $f $vtkdata
-                    close $f
-                }
-                set vtkdata  [Rappture::DxToVtk $vtkdata]
-                if 0 {
-                    set f [open /tmp/$_path.$cname.vtk "w"]
-                    puts -nonewline $f $vtkdata
-                    close $f
-                }
+            set data [$_field get -decode no $cname.$type]
+            set contents [Rappture::encoding::decode -as zb64 $data]
+            if { $contents == "" } {
+                puts stderr "WARNING: No data for \"$_path.$cname.$type\""
+                continue;               # Ignore this component
+            }
+            set vector ""
+            if 0 {
+                set f [open /tmp/$_path.$cname.dx "w"]
+                puts -nonewline $f $contents
+                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
+            } 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 ||
+                 ($_viewer != "nanovis" && $_viewer != "flowvis") } {
                 set _type "vtk"
                 set _comp2vtk($cname) $vtkdata
             } else {
-                set contents [$_field get -decode no $cname.$type]
-                if { $contents == "" } {
-                    puts stderr "WARNING: No data for \"$_path.$cname.$type\""
-                    continue;               # Ignore this component
-                }
                 set _type "dx"
-                set _comp2dx($cname) $contents
+                set _comp2dx($cname) $data
             }
             set _comp2style($cname) [$_field get $cname.style]
@@ -928,4 +947,21 @@
                     [Rappture::FlowHints ::\#auto $_field $cname $_units]
             }
+            set _dim 3
+            incr _counter
+        } elseif { $type == "dicom"} {
+            set contents [$_field get $cname.dicom]
+            if { $contents == "" } {
+                continue;               # Ignore this component
+            }
+            set viewer [$_field get "about.view"]
+            if { $viewer != "" } {
+                set _viewer $viewer
+            }
+            set vtkdata [DicomToVtk $cname $contents]
+            if { $_viewer == "" } {
+                set _viewer [expr {($_dim == 3) ? "vtkvolume" : "vtkimage"}]
+            }
+            set _comp2vtk($cname) $vtkdata
+            set _comp2style($cname) [$_field get $cname.style]
             incr _counter
         } elseif { $type == "ucd"} {
@@ -941,4 +977,5 @@
         }
         set _isValidComponent($cname) 1
+        #puts stderr "Field $cname type is: $_type"
     }
     if { [array size _isValidComponent] == 0 } {
@@ -1508,5 +1545,4 @@
 	# sort x-coords in increasing order
 	$xv sort $yv
-	
 	set _comp2dims($cname) "1D"
 	set _comp2xy($cname) [list $xv $yv]
@@ -1641,4 +1677,49 @@
     file delete $tmpfile
     return $vtkdata
+}
+
+itcl::body Rappture::Field::DicomToVtk { cname path } {
+    package require vtk
+
+    if { ![file exists $path] } {
+        puts stderr "path \"$path\" doesn't exist."
+        return 0
+    }
+
+    if { [file isdir $path] } {
+        set files [glob -nocomplain $path/*.dcm]
+        if { [llength $files] == 0 } {
+            set files [glob -nocomplain $path/*]
+            if { [llength $files] == 0 } {
+                puts stderr "no dicom files found in \"$path\""
+                return 0
+            }
+        }
+
+        #array set data [Rappture::DicomToVtk files $files]
+        array set data [Rappture::DicomToVtk dir $path]
+    } else {
+        array set data [Rappture::DicomToVtk files [list $path]]
+    }
+
+    foreach key [array names data] {
+        if {$key == "vtkdata"} {
+            if {1} {
+                set f [open /tmp/$cname.vtk "w"]
+                fconfigure $f -translation binary -encoding binary
+                puts -nonewline $f $data(vtkdata)
+                close $f
+            }
+        } else {
+            puts stderr "$key = \"$data($key)\""
+        }
+    }
+
+    # Save viewer choice
+    set viewer $_viewer
+    ReadVtkDataSet $cname $data(vtkdata)
+    # Restore viewer choice (ReadVtkDataSet wants to set it to contour/isosurface)
+    set _viewer $viewer
+    return $data(vtkdata)
 }
 
Index: branches/1.3/gui/scripts/fieldresult.tcl
===================================================================
--- branches/1.3/gui/scripts/fieldresult.tcl	(revision 4501)
+++ branches/1.3/gui/scripts/fieldresult.tcl	(revision 4504)
@@ -156,4 +156,8 @@
 # ----------------------------------------------------------------------
 itcl::body Rappture::FieldResult::add {dataobj {settings ""}} {
+    if { ![info exists itk_component(renderer)] } { 
+        puts stderr "add: no renderer created."
+        return
+    }
     eval $itk_component(renderer) add $dataobj [list $settings]
 }
@@ -166,4 +170,8 @@
 # ----------------------------------------------------------------------
 itcl::body Rappture::FieldResult::get {} {
+    if { ![info exists itk_component(renderer)] } { 
+        puts stderr "get: no renderer created."
+        return
+    }
     return [$itk_component(renderer) get]
 }
@@ -191,4 +199,8 @@
 # ----------------------------------------------------------------------
 itcl::body Rappture::FieldResult::scale {args} {
+    if { ![info exists itk_component(renderer)] } { 
+        puts stderr "scale: no renderer created."
+        return
+    }
     eval $itk_component(renderer) scale $args
 }
@@ -205,8 +217,16 @@
 # ----------------------------------------------------------------------
 itcl::body Rappture::FieldResult::download {option args} {
+    if { ![info exists itk_component(renderer)] } { 
+        puts stderr "download: no renderer created."
+        return
+    }
     eval $itk_component(renderer) download $option $args
 }
 
 itcl::body Rappture::FieldResult::snap { w h } {
+    if { ![info exists itk_component(renderer)] } { 
+        puts stderr "snap: no renderer created."
+        return
+    }
     return [$itk_component(renderer) snap $w $h]
 }
Index: branches/1.3/gui/scripts/nanovisviewer.tcl
===================================================================
--- branches/1.3/gui/scripts/nanovisviewer.tcl	(revision 4501)
+++ branches/1.3/gui/scripts/nanovisviewer.tcl	(revision 4504)
@@ -1,4 +1,3 @@
 # -*- mode: tcl; indent-tabs-mode: nil -*- 
-
 # ----------------------------------------------------------------------
 #  COMPONENT: nanovisviewer - 3D volume rendering
@@ -76,79 +75,90 @@
     public method isconnected {}
     public method limits { tf }
-    public method overmarker { m x }
     public method parameters {title args} { 
         # do nothing 
     }
-    public method rmdupmarker { m x }
     public method scale {args}
-    public method updatetransferfuncs {}
-
-    protected method Connect {}
-    protected method CurrentDatasets {{what -all}}
-    protected method Disconnect {}
-    protected method DoResize {}
-    protected method FixLegend {}
-    protected method AdjustSetting {what {value ""}}
-    protected method InitSettings { args }
-    protected method Pan {option x y}
-    protected method Rebuild {}
-    protected method ReceiveData { args }
-    protected method ReceiveImage { args }
-    protected method ReceiveLegend { tf vmin vmax size }
-    protected method Rotate {option x y}
-    protected method SendTransferFuncs {}
-    protected method Slice {option args}
-    protected method SlicerTip {axis}
-    protected method Zoom {option}
+    public method updateTransferFunctions {}
 
     # The following methods are only used by this class.
-    private method AddIsoMarker { x y }
+
+    private method AddNewMarker { x y } 
+    private method AdjustSetting {what {value ""}}
     private method BuildCameraTab {}
     private method BuildCutplanesTab {}
     private method BuildViewTab {}
+    private method BuildVolumeComponents {}
     private method BuildVolumeTab {}
-    private method ResetColormap { color }
-    private method ComputeTransferFunc { tf }
+    private method ComputeAlphamap { cname } 
+    private method ComputeTransferFunction { cname }
+    private method Connect {}
+    private method CurrentDatasets {{what -all}}
+    private method Disconnect {}
+    private method DoResize {}
+    private method DrawLegend { cname }
+    private method EventuallyRedrawLegend { } 
     private method EventuallyResize { w h } 
-    private method EventuallyResizeLegend { } 
-    private method NameTransferFunc { dataobj comp }
+    private method FixLegend {}
+    private method GetAlphamap { cname color } 
+    private method GetColormap { cname color } 
+    private method GetDatasetsWithComponent { cname } 
+    private method GetVolumeInfo { w }
+    private method HideAllMarkers {} 
+    private method InitComponentSettings { cname } 
+    private method InitSettings { args }
+    private method NameToAlphamap { name } 
+    private method NameTransferFunction { dataobj comp }
+    private method Pan {option x y}
     private method PanCamera {}
-    private method ParseLevelsOption { tf levels }
-    private method ParseMarkersOption { tf markers }
-    private method volume { tag name }
-    private method GetVolumeInfo { w }
+    private method ParseLevelsOption { cname levels }
+    private method ParseMarkersOption { cname markers }
+    private method Rebuild {}
+    private method ReceiveData { args }
+    private method ReceiveImage { args }
+    private method ReceiveLegend { tf vmin vmax size }
+    private method RemoveMarker { x y }
+    private method ResetColormap { cname color }
+    private method Rotate {option x y}
+    private method SendTransferFunctions {}
     private method SetOrientation { side }
+    private method Slice {option args}
+    private method SlicerTip {axis}
+    private method SwitchComponent { cname } 
+    private method ToggleVolume { tag name }
+    private method Zoom {option}
+    private method ViewToQuaternion {} { 
+        return [list $_view(-qw) $_view(-qx) $_view(-qy) $_view(-qz)]
+    }
 
     private variable _arcball ""
 
     private variable _dlist ""     ;# list of data objects
-    private variable _allDataObjs
     private variable _obj2ovride   ;# maps dataobj => style override
     private variable _serverDatasets   ;# contains all the dataobj-component 
                                    ;# to volumes in the server
-    private variable _serverTfs    ;# contains all the transfer functions 
-                                   ;# in the server.
-    private variable _recvdDatasets    ;# list of data objs to send to server
-    private variable _dataset2style    ;# maps dataobj-component to transfunc
-    private variable _style2datasets   ;# maps tf back to list of 
-                                    # dataobj-components using the tf.
-
-    private variable _reset 1;		# Connection to server has been reset 
-    private variable _click        ;# info used for rotate operations
-    private variable _limits       ;# autoscale min/max for all axes
-    private variable _view         ;# view params for 3D view
-    private variable _isomarkers    ;# array of isosurface level values 0..1
+    private variable _recvdDatasets;    # list of data objs to send to server
+    private variable _dataset2style;    # maps dataobj-component to transfunc
+    private variable _style2datasets;   # maps tf back to list of 
+                                        # dataobj-components using the tf.
+
+    private variable _reset 1;		# Connection to server has been reset.
+    private variable _click;            # Info used for rotate operations.
+    private variable _limits;           # Autoscale min/max for all axes
+    private variable _view;             # View params for 3D view
+    private variable _parsedFunction
+    private variable _transferFunctionEditors
     private variable  _settings
-    # Array of transfer functions in server.  If 0 the transfer has been
-    # defined but not loaded.  If 1 the transfer function has been named
-    # and loaded.
-    private variable _activeTfs
-    private variable _first ""     ;# This is the topmost volume.
     private variable _alphamap
-
-    # This 
-    # indicates which isomarkers and transfer
-    # function to use when changing markers,
-    # opacity, or thickness.
+    private variable _widget
+
+    private variable _first "" ;        # This is the topmost volume.
+    private variable _current "";       # Currently selected component 
+    private variable _volcomponents   ; # Array of components found 
+    private variable _componentsList   ; # Array of components found 
+    private variable _cname2style
+    private variable _cname2transferFunction
+    private variable _cname2defaultcolormap
+    private variable _cname2defaultalphamap
+
     common _downloadPopup          ;# download options from popup
     private common _hardcopy
@@ -177,5 +187,5 @@
     $_dispatcher register !send_transfunc
     $_dispatcher dispatch $this !send_transfunc \
-        "[itcl::code $this SendTransferFuncs]; list"
+        "[itcl::code $this SendTransferFunctions]; list"
 
     # Rebuild event
@@ -196,37 +206,48 @@
     # 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
+        -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
-
-    set _limits(vmin) 0.0
-    set _limits(vmax) 1.0
+    $_arcball quaternion [ViewToQuaternion]
+
+    set _limits(v) [list 0.0 1.0]
     set _reset 1
 
-    array set _settings [subst {
-        $this-qw                $_view(qw)
-        $this-qx                $_view(qx)
-        $this-qy                $_view(qy)
-        $this-qz                $_view(qz)
-        $this-zoom              $_view(zoom)    
-        $this-xpan              $_view(xpan)
-        $this-ypan              $_view(ypan)
-        $this-volume            1
-        $this-xcutplane         0
-        $this-xcutposition      0
-        $this-ycutplane         0
-        $this-ycutposition      0
-        $this-zcutplane         0
-        $this-zcutposition      0
-    }]
-
+    array set _settings {
+        -axesvisible       1
+        -colormap          default
+        -cutplanesvisible  0
+        -gridvisible       0
+        -isosurfaceshading 0
+        -legendvisible     1
+        -light2side        1
+        -outlinevisible    0
+        -qw                0.853553
+        -qx                -0.353553
+        -qy                0.353553
+        -qz                0.146447
+        -thickness         350
+        -volume            1
+        -volumeopacity     0.5
+        -volumevisible     1
+        -xcutplaneposition 50
+        -xcutplanevisible  1
+        -xpan              0
+        -ycutplaneposition 50
+        -ycutplanevisible  1
+        -ypan              0
+        -zcutplaneposition 50
+        -zcutplanevisible  1
+        -zoom              1.0
+    }
+    array set _widget {
+        -volumeopacity     50
+    }
     itk_component add 3dview {
         label $itk_component(plotarea).view -image $_image(plot) \
@@ -249,5 +270,6 @@
     }
     pack $itk_component(reset) -side top -padx 2 -pady 2
-    Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level"
+    Rappture::Tooltip::for $itk_component(reset) \
+        "Reset the view to the default zoom level"
 
     itk_component add zoomin {
@@ -279,6 +301,6 @@
             -onimage [Rappture::icon volume-on] \
             -offimage [Rappture::icon volume-off] \
-            -command [itcl::code $this AdjustSetting volume] \
-            -variable [itcl::scope _settings($this-volume)]
+            -command [itcl::code $this AdjustSetting -volume] \
+            -variable [itcl::scope _settings(-volume)]
     }
     $itk_component(volume) select
@@ -286,4 +308,15 @@
         "Toggle the volume cloud on/off"
     pack $itk_component(volume) -padx 2 -pady 2
+
+    itk_component add cutplane {
+        Rappture::PushButton $f.cutplane \
+            -onimage [Rappture::icon cutbutton] \
+            -offimage [Rappture::icon cutbutton] \
+            -variable [itcl::scope _settings(-cutplanesvisible)] \
+            -command [itcl::code $this AdjustSetting -cutplanesvisible] 
+    }
+    Rappture::Tooltip::for $itk_component(cutplane) \
+        "Show/Hide cutplanes"
+    pack $itk_component(cutplane) -padx 2 -pady 2
 
     if { [catch {
@@ -298,5 +331,4 @@
 
     # Legend
-
     set _image(legend) [image create photo]
     itk_component add legend {
@@ -308,5 +340,9 @@
     }
     bind $itk_component(legend) <Configure> \
-        [itcl::code $this EventuallyResizeLegend]
+        [itcl::code $this EventuallyRedrawLegend]
+    bind $itk_component(legend) <KeyPress-Delete> \
+        [itcl::code $this RemoveMarker %x %y]
+    bind $itk_component(legend) <Enter> \
+        [list focus $itk_component(legend)]
 
     # Hack around the Tk panewindow.  The problem is that the requested 
@@ -387,6 +423,9 @@
     image delete $_image(legend)
     image delete $_image(download)
+    foreach name [array names _transferFunctionEditors] {
+        itcl::delete object $_transferFunctionEditors($cname)
+    }
     catch { blt::arcball destroy $_arcball }
-    array unset _settings $this-*
+    array unset _settings 
 }
 
@@ -420,5 +459,4 @@
     if {$pos < 0} {
         lappend _dlist $dataobj
-        set _allDataObjs($dataobj) 1
         set _obj2ovride($dataobj-color) $params(-color)
         set _obj2ovride($dataobj-width) $params(-width)
@@ -497,6 +535,6 @@
         if { $pos >= 0 } {
             set _dlist [lreplace $_dlist $pos $pos]
-            array unset _limits $dataobj*
             array unset _obj2ovride $dataobj-*
+            array unset _dataset2style $dataobj-*
             set changed 1
         }
@@ -518,28 +556,47 @@
 # ----------------------------------------------------------------------
 itcl::body Rappture::NanovisViewer::scale {args} {
-    foreach val {xmin xmax ymin ymax zmin zmax vmin vmax} {
-        set _limits($val) ""
-    }
+    array set styles {
+        -color BCGYR
+        -levels 6
+        -markers ""
+    }
+    array unset _limits 
+    array unset _volcomponents 
     foreach dataobj $args {
         if { ![$dataobj isvalid] } {
             continue;                     # Object doesn't contain valid data.
         }
+        foreach cname [$dataobj components] {
+            if { ![info exists _volcomponents($cname)] } {
+                lappend _componentsList $cname
+                array set styles [lindex [$dataobj components -style $cname] 0]
+                set cmap [ColorsToColormap $styles(-color)]
+                set _cname2defaultcolormap($cname) $cmap
+                set _settings($cname-colormap) $styles(-color)
+            }
+            lappend _volcomponents($cname) $dataobj-$cname
+            array unset limits
+            array set limits [$dataobj valueLimits $cname]
+            set _limits($cname) $limits(v)
+        }
         foreach axis {x y z v} {
             foreach { min max } [$dataobj limits $axis] break
             if {"" != $min && "" != $max} {
-                if {"" == $_limits(${axis}min)} {
-                    set _limits(${axis}min) $min
-                    set _limits(${axis}max) $max
+                if { ![info exists _limits($axis)] } {
+                    set _limits($axis) [list $min $max]
                 } else {
-                    if {$min < $_limits(${axis}min)} {
-                        set _limits(${axis}min) $min
+                    foreach {amin amax} $_limits($axis) break
+                    if {$min < $amin} {
+                        set amin $min
                     }
-                    if {$max > $_limits(${axis}max)} {
-                        set _limits(${axis}max) $max
+                    if {$max > $amax} {
+                        set amax $max
                     }
+                    set _limits($axis) [list $amin $amax]
                 }
             }
         }
     }
+    BuildVolumeComponents
 }
 
@@ -660,41 +717,9 @@
 
 # ----------------------------------------------------------------------
-# USAGE: SendTransferFuncs
-# ----------------------------------------------------------------------
-itcl::body Rappture::NanovisViewer::SendTransferFuncs {} {
-    if { $_first == "" } {
-        puts stderr "first not set"
-        return
-    }
-    # Ensure that the global opacity and thickness settings (in the slider
-    # settings widgets) are used for the active transfer-function.  Update
-    # the values in the _settings varible.
-    set opacity [expr { double($_settings($this-opacity)) * 0.01 }]
-    # Scale values between 0.00001 and 0.01000
-    set thickness [expr {double($_settings($this-thickness)) * 0.0001}]
-
-    foreach tag [CurrentDatasets] {
-        if { ![info exists _serverDatasets($tag)] || !$_serverDatasets($tag) } {
-            # The volume hasn't reached the server yet.  How did we get 
-            # here?
-            puts stderr "Don't have $tag in _serverDatasets"
-            continue
-        }
-        if { ![info exists _dataset2style($tag)] } {
-            puts stderr "don't have style for volume $tag"
-            continue;                        # How does this happen?
-        }
-        set tf $_dataset2style($tag)
-        set _settings($this-$tf-opacity) $opacity
-        set _settings($this-$tf-thickness) $thickness
-        ComputeTransferFunc $tf
-        # FIXME: Need to the send information as to what transfer functions
-        #        to update so that we only update the transfer function 
-        #        as necessary.  Right now, all transfer functions are 
-        #        updated. This makes moving the isomarker slider chunky.
-        if { ![info exists _activeTfs($tf)] || !$_activeTfs($tf) } {
-            set _activeTfs($tf) 1
-        }
-        SendCmd "volume shading transfunc $tf $tag"
+# USAGE: SendTransferFunctions
+# ----------------------------------------------------------------------
+itcl::body Rappture::NanovisViewer::SendTransferFunctions {} {
+    foreach cname [array names _volcomponents] {
+        ComputeTransferFunction $cname
     }
     FixLegend
@@ -727,23 +752,7 @@
 
 #
-# ReceiveLegend --
-#
-#       The procedure is the response from the render server to each "legend"
-#       command.  The server sends back a "legend" command invoked our
-#       the slave interpreter.  The purpose is to collect data of the image 
-#       representing the legend in the canvas.  In addition, the isomarkers
-#       of the active transfer function are displayed.
-#
-#       I don't know is this is the right place to display the isomarkers.
-#       I don't know all the different paths used to draw the plot. There's 
-#       "Rebuild", "add", etc.
-#
-itcl::body Rappture::NanovisViewer::ReceiveLegend { tf vmin vmax size } {
-    if { ![isconnected] } {
-        return
-    }
-    set bytes [ReceiveBytes $size]
-    $_image(legend) configure -data $bytes
-    ReceiveEcho <<line "<read $size bytes for [image width $_image(legend)]x[image height $_image(legend)] legend>"
+# DrawLegend --
+#
+itcl::body Rappture::NanovisViewer::DrawLegend { cname } {
     set c $itk_component(legend)
     set w [winfo width $c]
@@ -751,33 +760,38 @@
     set lx 10
     set ly [expr {$h - 1}]
-    if {"" == [$c find withtag transfunc]} {
+    if {"" == [$c find withtag colorbar]} {
         $c create image 10 10 -anchor nw \
-            -image $_image(legend) -tags transfunc
+            -image $_image(legend) -tags colorbar
         $c create text $lx $ly -anchor sw \
-            -fill $itk_option(-plotforeground) -tags "limits vmin"
+            -fill $itk_option(-plotforeground) -tags "limits text vmin"
         $c create text [expr {$w-$lx}] $ly -anchor se \
-            -fill $itk_option(-plotforeground) -tags "limits vmax"
-        $c lower transfunc
-        $c bind transfunc <ButtonRelease-1> \
-            [itcl::code $this AddIsoMarker %x %y]
-    }
-    # Display the markers used by the active transfer function.
-
-    array set limits [limits $tf]
-    $c itemconfigure vmin -text [format %g $limits(min)]
+            -fill $itk_option(-plotforeground) -tags "limits text vmax"
+        $c create text [expr {$w/2}] $ly -anchor s \
+            -fill $itk_option(-plotforeground) -tags "limits text title"
+        $c lower colorbar
+        $c bind colorbar <ButtonRelease-1> [itcl::code $this AddNewMarker %x %y]
+    }
+
+    # Display the markers used by the current transfer function.
+    HideAllMarkers
+    $_transferFunctionEditors($cname) showMarkers $_limits($cname)
+
+    foreach {min max} $_limits($cname) break
+    $c itemconfigure vmin -text [format %g $min]
     $c coords vmin $lx $ly
 
-    $c itemconfigure vmax -text [format %g $limits(max)]
+    $c itemconfigure vmax -text [format %g $max]
     $c coords vmax [expr {$w-$lx}] $ly
 
-    if { [info exists _isomarkers($tf)] } {
-        foreach m $_isomarkers($tf) {
-            $m visible yes
-        }
-    }
+    set title [$_first hints label]
+    set units [$_first hints units]
+    if { $units != "" } {
+        set title "$title ($units)"
+    }
+    $c itemconfigure title -text $title
+    $c coords title [expr {$w/2}] $ly
 
     # The colormap may have changed. Resync the slicers with the colormap.
     set datasets [CurrentDatasets -cutplanes]
-    SendCmd "volume data state $_settings($this-volume) $datasets"
 
     # Adjust the cutplane for only the first component in the topmost volume
@@ -787,11 +801,33 @@
         # Turn off cutplanes for all volumes
         SendCmd "cutplane state 0 $axis"
-        if { $_settings($this-${axis}cutplane) } {
+        if { $_settings(-${axis}cutplanevisible) } {
             # Turn on cutplane for this particular volume and set the position
             SendCmd "cutplane state 1 $axis $tag"
-            set pos [expr {0.01*$_settings($this-${axis}cutposition)}]
+            set pos [expr {0.01*$_settings(-${axis}cutplaneposition)}]
             SendCmd "cutplane position $pos $axis $tag"
         }
     }
+}
+
+#
+#
+# ReceiveLegend --
+#
+#       The procedure is the response from the render server to each "legend"
+#       command.  The server sends back a "legend" command invoked our
+#       the slave interpreter.  The purpose is to collect data of the image 
+#       representing the legend in the canvas.  In addition, the
+#       active transfer function is displayed.
+#
+#
+itcl::body Rappture::NanovisViewer::ReceiveLegend { cname vmin vmax size } {
+    if { ![isconnected] } {
+        return
+    }
+    set bytes [ReceiveBytes $size]
+    $_image(legend) configure -data $bytes
+    ReceiveEcho <<line "<read $size bytes for [image width $_image(legend)]x[image height $_image(legend)] legend>"
+
+    DrawLegend $_current
 }
 
@@ -833,18 +869,13 @@
     set dataobj [lindex $parts 0]
     set _serverDatasets($tag) 1
-    if { $_settings($this-volume) && $dataobj == $_first } {
+    if { $_settings(-volumevisible) && $dataobj == $_first } {
         SendCmd "volume state 1 $tag"
     }
-    set _limits($tag-min)  $info(min);  # Minimum value of the volume.
-    set _limits($tag-max)  $info(max);  # Maximum value of the volume.
-    set _limits(vmin)      $info(vmin); # Overall minimum value.
-    set _limits(vmax)      $info(vmax); # Overall maximum value.
+    set _limits($tag) [list $info(min)  $info(max)]
+    set _limits(v)    [list $info(vmin) $info(vmax)]
 
     unset _recvdDatasets($tag)
     if { [array size _recvdDatasets] == 0 } {
-        # The active transfer function is by default the first component of
-        # the first data object.  This assumes that the data is always
-        # successfully transferred.
-        updatetransferfuncs
+        updateTransferFunctions
     }
 }
@@ -869,13 +900,4 @@
     # generates a new call to Rebuild).   
     StartBufferingCommands
-
-    # Hide all the isomarkers. Can't remove them. Have to remember the
-    # settings since the user may have created/deleted/moved markers.
-
-    foreach tf [array names _isomarkers] {
-        foreach m $_isomarkers($tf) {
-            $m visible no
-        }
-    }
 
     if { $_width != $w || $_height != $h || $_reset } {
@@ -895,4 +917,9 @@
                     }
                     set data [$dataobj blob $cname]
+                    if 0 {
+                        set f [open "/tmp/values-$cname.txt" "w"]
+                        puts $f [$dataobj values $cname]
+                        close $f
+                    }
                 } else {
                     set data [$dataobj vtkdata $cname]
@@ -920,5 +947,5 @@
                 set _serverDatasets($tag) 0
             }
-            NameTransferFunc $dataobj $cname
+            NameTransferFunction $dataobj $cname
         }
     }
@@ -928,24 +955,29 @@
 	# Reset the camera and other view parameters
 	#
-        set _settings($this-qw)    $_view(qw)
-        set _settings($this-qx)    $_view(qx)
-        set _settings($this-qy)    $_view(qy)
-        set _settings($this-qz)    $_view(qz)
-	set _settings($this-xpan)  $_view(xpan)
-	set _settings($this-ypan)  $_view(ypan)
-	set _settings($this-zoom)  $_view(zoom)
-
-        set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+        set _settings(-qw)    $_view(-qw)
+        set _settings(-qx)    $_view(-qx)
+        set _settings(-qy)    $_view(-qy)
+        set _settings(-qz)    $_view(-qz)
+	set _settings(-xpan)  $_view(-xpan)
+	set _settings(-ypan)  $_view(-ypan)
+	set _settings(-zoom)  $_view(-zoom)
+
+        set q [ViewToQuaternion]
         $_arcball quaternion $q
         SendCmd "camera orient $q"
         SendCmd "camera reset"
 	PanCamera
-	SendCmd "camera zoom $_view(zoom)"
-        InitSettings light2side light transp isosurface grid axes 
+	SendCmd "camera zoom $_view(-zoom)"
 	
+        #cutplane state 0 all
         foreach axis {x y z} {
             # Turn off cutplanes for all volumes
             SendCmd "cutplane state 0 $axis"
         }
+
+        InitSettings -light2side -light -volumeopacity \
+            -isosurfaceshading -gridvisible -axesvisible \
+            -current
+
 	if {"" != $_first} {
 	    set axis [$_first hints updir]
@@ -960,5 +992,5 @@
     }
     # Outline seems to need to be reset every update.
-    InitSettings outline
+    InitSettings -outlinevisible -cutplanesvisible 
     # nothing to send -- activate the proper ivol
     SendCmd "volume state 0"
@@ -972,5 +1004,5 @@
         set cname [lindex [$_first components] 0]
         if { [info exists _serverDatasets($_first-$cname)] } {
-            updatetransferfuncs
+            updateTransferFunctions
         }
     }
@@ -1021,22 +1053,22 @@
     switch -- $option {
         "in" {
-            set _view(zoom) [expr {$_view(zoom)*1.25}]
-            set _settings($this-zoom) $_view(zoom)
-            SendCmd "camera zoom $_view(zoom)"
+            set _view(-zoom) [expr {$_view(-zoom)*1.25}]
+            set _settings(-zoom) $_view(-zoom)
+            SendCmd "camera zoom $_view(-zoom)"
         }
         "out" {
-            set _view(zoom) [expr {$_view(zoom)*0.8}]
-            set _settings($this-zoom) $_view(zoom)
-            SendCmd "camera zoom $_view(zoom)"
+            set _view(-zoom) [expr {$_view(-zoom)*0.8}]
+            set _settings(-zoom) $_view(-zoom)
+            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 != "" } {
@@ -1046,15 +1078,15 @@
                 }
             }
-            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 _settings($this-qw)    $_view(qw)
-            set _settings($this-qx)    $_view(qx)
-            set _settings($this-qy)    $_view(qy)
-            set _settings($this-qz)    $_view(qz)
-            set _settings($this-xpan)  $_view(xpan)
-            set _settings($this-ypan)  $_view(ypan)
-            set _settings($this-zoom)  $_view(zoom)
+            set _settings(-qw)    $_view(-qw)
+            set _settings(-qx)    $_view(-qx)
+            set _settings(-qy)    $_view(-qy)
+            set _settings(-qz)    $_view(-qz)
+            set _settings(-xpan)  $_view(-xpan)
+            set _settings(-ypan)  $_view(-ypan)
+            set _settings(-zoom)  $_view(-zoom)
         }
     }
@@ -1062,8 +1094,6 @@
 
 itcl::body Rappture::NanovisViewer::PanCamera {} {
-    #set x [expr ($_view(xpan)) / $_limits(xrange)]
-    #set y [expr ($_view(ypan)) / $_limits(yrange)]
-    set x $_view(xpan)
-    set y $_view(ypan)
+    set x $_view(-xpan)
+    set y $_view(-ypan)
     SendCmd "camera pan $x $y"
 }
@@ -1104,9 +1134,9 @@
 
                 set q [$_arcball rotate $x $y $_click(x) $_click(y)]
-                foreach { _view(qw) _view(qx) _view(qy) _view(qz) } $q break
-                set _settings($this-qw) $_view(qw)
-                set _settings($this-qx) $_view(qx)
-                set _settings($this-qy) $_view(qy)
-                set _settings($this-qz) $_view(qz)
+                foreach { _view(-qw) _view(-qx) _view(-qy) _view(-qz) } $q break
+                set _settings(-qw) $_view(-qw)
+                set _settings(-qx) $_view(-qx)
+                set _settings(-qy) $_view(-qy)
+                set _settings(-qz) $_view(-qz)
                 SendCmd "camera orient $q"
 
@@ -1141,9 +1171,9 @@
         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
-        set _settings($this-xpan) $_view(xpan)
-        set _settings($this-ypan) $_view(ypan)
+        set _settings(-xpan) $_view(-xpan)
+        set _settings(-ypan) $_view(-ypan)
         return
     }
@@ -1158,9 +1188,9 @@
         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
-        set _settings($this-xpan) $_view(xpan)
-        set _settings($this-ypan) $_view(ypan)
+        set _settings(-xpan) $_view(-xpan)
+        set _settings(-ypan) $_view(-ypan)
     }
     if { $option == "release" } {
@@ -1194,6 +1224,41 @@
     }
     switch -- $what {
-        light {
-            set val $_settings($this-light)
+        "-axesvisible" {
+            SendCmd "axis visible $_settings($what)"
+        }
+        "-colormap" {
+            set color [$itk_component(colormap) value]
+            set _settings($what) $color
+            set _settings($_current${what}) $color
+            ResetColormap $_current $color
+        }
+        "-current" {
+            set cname [$itk_component(volcomponents) value]
+            SwitchComponent $cname
+        }
+        "-cutplanesvisible" {
+            set bool $_settings($what)
+            set datasets [CurrentDatasets -cutplanes]
+            set tag [lindex $datasets 0]
+            SendCmd "cutplane visible $bool $tag"
+        }
+        "-gridvisible" {
+            SendCmd "grid visible $_settings($what)"
+        }
+        "-isosurfaceshading" {
+            SendCmd "volume shading isosurface $_settings($what)"
+        }
+        "-legendvisible" {
+            if { $_settings($what) } {
+                blt::table $itk_component(plotarea) \
+                    0,0 $itk_component(3dview) -fill both \
+                    1,0 $itk_component(legend) -fill x 
+                blt::table configure $itk_component(plotarea) r1 -resize none
+            } else {
+                blt::table forget $itk_component(legend)
+            }
+        }
+        "-light" {
+            set val $_settings($what)
             set diffuse [expr {0.01*$val}]
             set ambient [expr {1.0-$diffuse}]
@@ -1205,69 +1270,48 @@
             SendCmd "volume shading specularExp $specularExp"
         }
-        light2side {
-            set val $_settings($this-light2side)
+        "-light2side" {
+            set val $_settings($what)
             SendCmd "volume shading light2side $val"
         }
-        transp {
-            set val $_settings($this-transp)
-            set sval [expr { 0.01 * double($val) }]
-            SendCmd "volume shading opacity $sval"
-        }
-        opacity {
-            set val $_settings($this-opacity)
-            set sval [expr { 0.01 * double($val) }]
-            foreach tf [array names _activeTfs] {
-                set _settings($this-$tf-opacity) $sval
-                set _activeTfs($tf) 0
-            }
-            updatetransferfuncs
-        }
-        thickness {
-            if { [array names _activeTfs] > 0 } {
-                set val $_settings($this-thickness)
-                # Scale values between 0.00001 and 0.01000
-                set sval [expr {0.0001*double($val)}]
-                foreach tf [array names _activeTfs] {
-                    set _settings($this-$tf-thickness) $sval
-                    set _activeTfs($tf) 0
-                }
-                updatetransferfuncs
-            }
-        }
-        "outline" {
-            SendCmd "volume outline state $_settings($this-outline)"
-        }
-        "isosurface" {
-            SendCmd "volume shading isosurface $_settings($this-isosurface)"
-        }
-        "colormap" {
-            set color [$itk_component(colormap) value]
-            set _settings(colormap) $color
-            # Only set the colormap on the first volume. Ignore the others.
-            #ResetColormap $color
-        }
-        "grid" {
-            SendCmd "grid visible $_settings($this-grid)"
-        }
-        "axes" {
-            SendCmd "axis visible $_settings($this-axes)"
-        }
-        "legend" {
-            if { $_settings($this-legend) } {
-                blt::table $itk_component(plotarea) \
-                    0,0 $itk_component(3dview) -fill both \
-                    1,0 $itk_component(legend) -fill x 
-                blt::table configure $itk_component(plotarea) r1 -resize none
-            } else {
-                blt::table forget $itk_component(legend)
-            }
-        }
-        "volume" {
-            set datasets [CurrentDatasets -cutplanes] 
-            SendCmd "volume data state $_settings($this-volume) $datasets"
-        }
-        "xcutplane" - "ycutplane" - "zcutplane" {
-            set axis [string range $what 0 0]
-            set bool $_settings($this-$what)
+        "-volumeopacity" {
+            set _settings($what) [expr $_widget($what) * 0.01]
+            set _settings($_current${what}) $_settings($what)
+            foreach tag [GetDatasetsWithComponent $_current] {
+                SendCmd "volume shading opacity $_settings($what) $tag"
+            }
+            #updateTransferFunctions
+        }
+        "-outlinevisible" {
+            SendCmd "volume outline state $_settings($what)"
+        }
+        "-thickness" {
+            set val $_settings($what)
+            set _settings($_current${what}) $val
+            updateTransferFunctions
+        }
+        "-volume" {
+            # This is the global volume visibility control.  It controls the
+            # visibility of all the all volumes.  Whenever it's changed, you
+            # have to synchronize each of the local controls (see below) with
+            # this.
+            set datasets [CurrentDatasets] 
+            set bool $_settings($what)
+            SendCmd "volume data state $bool $datasets"
+            foreach cname $_componentsList {
+                set _settings($cname-volumevisible) $bool
+            }
+            set _settings(-volumevisible) $bool
+        }
+        "-volumevisible" {
+            # This is the component specific control.  It changes the 
+            # visibility of only the current component.
+            set _settings($_current${what}) $_settings($what)
+            foreach tag [GetDatasetsWithComponent $_current] {
+                SendCmd "volume data state $_settings($what) $tag"
+            }
+        }
+        "-xcutplanevisible" - "-ycutplanevisible" - "-zcutplanevisible" {
+            set axis [string range $what 1 1]
+            set bool $_settings($what)
             set datasets [CurrentDatasets -cutplanes] 
             set tag [lindex $datasets 0]
@@ -1299,19 +1343,13 @@
     set w [expr {$_width-20}]
     set h [expr {[winfo height $itk_component(legend)]-20-$lineht}]
-    if {$w > 0 && $h > 0 && [array names _activeTfs] > 0 && $_first != "" } {
-        set tag [lindex [CurrentDatasets] 0]
-        if { [info exists _dataset2style($tag)] } {
-            SendCmd "legend $_dataset2style($tag) $w $h"
-        }
-    } else {
-        # Can't do this as this will remove the items associated with the
-        # isomarkers.
-        
-        #$itk_component(legend) delete all
-    }
-}
-
-#
-# NameTransferFunc --
+    if {$w > 0 && $h > 0 && $_first != "" } {
+        if { [info exists _cname2transferFunction($_current)] } {
+            SendCmd "legend $_current $w $h"
+        }
+    }
+}
+
+#
+# NameTransferFunction --
 #
 #       Creates a transfer function name based on the <style> settings in the
@@ -1321,45 +1359,43 @@
 #       server parses the 3D data and sends back the limits via ReceiveData.]
 #
-#       FIXME: The current way we generate transfer-function names completely
-#              ignores the -markers option.  The problem is that we are forced
-#              to compute the name from an increasing complex set of values:
-#              color, levels, marker, opacity.  I think we're stuck doing it
-#              now.
-#
-itcl::body Rappture::NanovisViewer::NameTransferFunc { dataobj cname } {
+itcl::body Rappture::NanovisViewer::NameTransferFunction { dataobj cname } {
     array set styles {
         -color BCGYR
         -levels 6
-        -opacity 1.0
         -markers ""
     }
     set tag $dataobj-$cname
     array set styles [lindex [$dataobj components -style $cname] 0]
-    set tf "$styles(-color):$styles(-levels):$styles(-opacity)"
-    set _dataset2style($tag) $tf
-    lappend _style2datasets($tf) $tag
-    return $tf
-}
-
-#
-# ComputeTransferFunc --
-#
-#   Computes and sends the transfer function to the render server.  It's
-#   assumed that the volume data limits are known and that the global
-#   transfer-functions slider values have been set up.  Both parts are
-#   needed to compute the relative value (location) of the marker, and
-#   the alpha map of the transfer function.
-#
-itcl::body Rappture::NanovisViewer::ComputeTransferFunc { tf } {
-    array set styles {
-        -color BCGYR
-        -levels 6
-        -opacity 1.0
-        -markers ""
-        -alphamap ""
-    }
-
-    foreach {dataobj cname} [split [lindex $_style2datasets($tf) 0] -] break
-    array set styles [lindex [$dataobj components -style $cname] 0]
+    if { ![info exists _cname2transferFunction($cname)] } {
+        # Get the colormap right now, since it doesn't change with marker
+        # changes.
+        set cmap [ColorsToColormap $styles(-color)]
+        set wmap [list 0.0 0.0 1.0 1.0]
+        set _cname2transferFunction($cname) [list $cmap $wmap]
+        SendCmd [list transfunc define $cname $cmap $wmap]
+    }
+    SendCmd "volume shading transfunc $cname $tag"
+    if { ![info exists _transferFunctionEditors($cname)] } {
+        set _transferFunctionEditors($cname) \
+            [Rappture::TransferFunctionEditor ::\#auto $itk_component(legend) \
+                 $cname \
+                 -command [itcl::code $this updateTransferFunctions]]
+    }
+    set _dataset2style($tag) $cname
+    lappend _style2datasets($cname) $tag
+    return $cname
+}
+
+#
+# ComputeTransferFunction --
+#
+#       Computes and sends the transfer function to the render server.  It's
+#       assumed that the volume data limits are known and that the global
+#       transfer-functions slider values have been set up.  Both parts are
+#       needed to compute the relative value (location) of the marker, and
+#       the alpha map of the transfer function.
+#
+itcl::body Rappture::NanovisViewer::ComputeTransferFunction { cname } {
+    foreach {cmap wmap} $_cname2transferFunction($cname) break
 
     # We have to parse the style attributes for a volume using this
@@ -1369,86 +1405,45 @@
     # of the volumes (the first in the list) using the transfer-function as a
     # reference.
-    #
-    # FIXME: The current way we generate transfer-function names completely 
-    #        ignores the -markers option.  The problem is that we are forced 
-    #        to compute the name from an increasing complex set of values: 
-    #        color, levels, marker, opacity.  I think the cow's out of the
-    #        barn on this one.
-
-    if { ![info exists _isomarkers($tf)] } {
+    if { ![info exists _parsedFunction($cname)] } {
+        array set styles {
+            -color BCGYR
+            -levels 6
+            -markers ""
+        }
+        # Accumulate the style from all the datasets using it.
+        foreach tag [GetDatasetsWithComponent $cname] {
+            foreach {dataobj cname} [split [lindex $tag 0] -] break
+            array set styles [lindex [$dataobj components -style $cname] 0]
+        }
+        eval $_transferFunctionEditors($cname) limits $_limits($cname)
         # Have to defer creation of isomarkers until we have data limits
         if { [info exists styles(-markers)] &&
              [llength $styles(-markers)] > 0 } {
-            ParseMarkersOption $tf $styles(-markers)
+            ParseMarkersOption $cname $styles(-markers)
         } else {
-            ParseLevelsOption $tf $styles(-levels)
-        }
-        if { $styles(-alphamap) != "" } {
-            set _alphamap($cname) $styles(-alphamap)
-        }
-    }
-    set cmap [ColorsToColormap $styles(-color)]
-    set tag $this-$tf
-    if { ![info exists _settings($tag-opacity)] } {
-        set _settings($tag-opacity) $styles(-opacity)
-    }
-    set max 1.0 ;#$_settings($tag-opacity)
-
-    set isovalues {}
-    foreach m $_isomarkers($tf) {
-        lappend isovalues [$m relval]
-    }
-    # Sort the isovalues
-    set isovalues [lsort -real $isovalues]
-
-    if { ![info exists _settings($tag-thickness)]} {
-        set _settings($tag-thickness) 0.005
-    }
-    set delta $_settings($tag-thickness)
-
-    set first [lindex $isovalues 0]
-    set last [lindex $isovalues end]
-    set wmap ""
-    if { $first == "" || $first != 0.0 } {
-        lappend wmap 0.0 0.0
-    }
-    foreach x $isovalues {
-        set x1 [expr {$x-$delta-0.00001}]
-        set x2 [expr {$x-$delta}]
-        set x3 [expr {$x+$delta}]
-        set x4 [expr {$x+$delta+0.00001}]
-        if { $x1 < 0.0 } {
-            set x1 0.0
-        } elseif { $x1 > 1.0 } {
-            set x1 1.0
-        }
-        if { $x2 < 0.0 } {
-            set x2 0.0
-        } elseif { $x2 > 1.0 } {
-            set x2 1.0
-        }
-        if { $x3 < 0.0 } {
-            set x3 0.0
-        } elseif { $x3 > 1.0 } {
-            set x3 1.0
-        }
-        if { $x4 < 0.0 } {
-            set x4 0.0
-        } elseif { $x4 > 1.0 } {
-            set x4 1.0
-        }
-        # add spikes in the middle
-        lappend wmap $x1 0.0
-        lappend wmap $x2 $max
-        lappend wmap $x3 $max
-        lappend wmap $x4 0.0
-    }
-    if { $last == "" || $last != 1.0 } {
-        lappend wmap 1.0 0.0
-    }
-    if { [info exists _alphamap($cname)] } {
-        set wmap $_alphamap($cname)
-    }
-    SendCmd [list transfunc define $tf $cmap $wmap]
+            ParseLevelsOption $cname $styles(-levels)
+        }
+        
+    }
+    set wmap [ComputeAlphamap $cname]
+    set _cname2transferFunction($cname) [list $cmap $wmap]
+    SendCmd [list transfunc define $cname $cmap $wmap]
+}
+
+itcl::body Rappture::NanovisViewer::AddNewMarker { x y } {
+    if { ![info exists _transferFunctionEditors($_current)] } {
+        continue
+    }
+    # Add a new marker to the current transfer function
+    $_transferFunctionEditors($_current) newMarker $x $y normal
+    $itk_component(legend) itemconfigure labels -fill $itk_option(-plotforeground)
+}
+
+itcl::body Rappture::NanovisViewer::RemoveMarker { x y } {
+    if { ![info exists _transferFunctionEditors($_current)] } {
+        continue
+    }
+    # Add a new marker to the current transfer function
+    $_transferFunctionEditors($_current) deleteMarker $x $y 
 }
 
@@ -1498,21 +1493,20 @@
 # marker is a relative value from 0.0 to 1.0.
 #
-itcl::body Rappture::NanovisViewer::ParseLevelsOption { tf levels } {
+itcl::body Rappture::NanovisViewer::ParseLevelsOption { cname levels } {
     set c $itk_component(legend)
+    set list {}
     regsub -all "," $levels " " levels
     if {[string is int $levels]} {
         for {set i 1} { $i <= $levels } {incr i} {
-            set x [expr {double($i)/($levels+1)}]
-            set m [Rappture::IsoMarker \#auto $c $this $tf]
-            $m relval $x
-            lappend _isomarkers($tf) $m 
+            lappend list [expr {double($i)/($levels+1)}]
         }
     } else {
         foreach x $levels {
-            set m [Rappture::IsoMarker \#auto $c $this $tf]
-            $m relval $x
-            lappend _isomarkers($tf) $m 
-        }
-    }
+            lappend list $x
+        }
+    }
+    set _parsedFunction($cname) 1
+    $_transferFunctionEditors($cname) addMarkers $list
+    $itk_component(legend) itemconfigure labels -fill $itk_option(-plotforeground)
 }
 
@@ -1529,22 +1523,22 @@
 #       not be seen.
 #
-itcl::body Rappture::NanovisViewer::ParseMarkersOption { tf markers } {
+itcl::body Rappture::NanovisViewer::ParseMarkersOption { cname markers } {
     set c $itk_component(legend)
+    set list {}
+    foreach { min max } $_limits($cname) break
     regsub -all "," $markers " " markers
     foreach marker $markers {
         set n [scan $marker "%g%s" value suffix]
         if { $n == 2 && $suffix == "%" } {
-            # ${n}% : Set relative value. 
-            set value [expr {$value * 0.01}]
-            set m [Rappture::IsoMarker \#auto $c $this $tf]
-            $m relval $value
-            lappend _isomarkers($tf) $m
+            # $n% : Set relative value (0..1). 
+            lappend list [expr {$value * 0.01}]
         } else {
-            # ${n} : Set absolute value.
-            set m [Rappture::IsoMarker \#auto $c $this $tf]
-            $m absval $value
-            lappend _isomarkers($tf) $m
-        }
-    }
+            # $n : absolute value, compute relative
+            lappend list  [expr {(double($value)-$min)/($max-$min)]}
+        }
+    }
+    set _parsedFunction($cname) 1
+    $_transferFunctionEditors($cname) addMarkers $list
+    $itk_component(legend) itemconfigure labels -fill $itk_option(-plotforeground)
 }
 
@@ -1552,82 +1546,25 @@
 # USAGE: UndateTransferFuncs 
 # ----------------------------------------------------------------------
-itcl::body Rappture::NanovisViewer::updatetransferfuncs {} {
+itcl::body Rappture::NanovisViewer::updateTransferFunctions {} {
     $_dispatcher event -idle !send_transfunc
 }
 
-itcl::body Rappture::NanovisViewer::AddIsoMarker { x y } {
-    if { $_first == "" } {
-        error "active transfer function isn't set"
-    }
-    set tag [lindex [CurrentDatasets] 0]
-    set tf $_dataset2style($tag)
-    set c $itk_component(legend)
-    set m [Rappture::IsoMarker \#auto $c $this $tf]
-    set w [winfo width $c]
-    $m relval [expr {double($x-10)/($w-20)}]
-    lappend _isomarkers($tf) $m
-    updatetransferfuncs
-    return 1
-}
-
-itcl::body Rappture::NanovisViewer::rmdupmarker { marker x } {
-    set tf [$marker transferfunc]
-    set bool 0
-    if { [info exists _isomarkers($tf)] } {
-        set list {}
-        set marker [namespace tail $marker]
-        foreach m $_isomarkers($tf) {
-            set sx [$m screenpos]
-            if { $m != $marker } {
-                if { $x >= ($sx-3) && $x <= ($sx+3) } {
-                    $marker relval [$m relval]
-                    itcl::delete object $m
-                    bell
-                    set bool 1
-                    continue
-                }
-            }
-            lappend list $m
-        }
-        set _isomarkers($tf) $list
-        updatetransferfuncs
-    }
-    return $bool
-}
-
-itcl::body Rappture::NanovisViewer::overmarker { marker x } {
-    set tf [$marker transferfunc]
-    if { [info exists _isomarkers($tf)] } {
-        set marker [namespace tail $marker]
-        foreach m $_isomarkers($tf) {
-            set sx [$m screenpos]
-            if { $m != $marker } {
-                set bool [expr { $x >= ($sx-3) && $x <= ($sx+3) }]
-                $m activate $bool
-            }
-        }
-    }
-    return ""
-}
-
-itcl::body Rappture::NanovisViewer::limits { tf } {
+itcl::body Rappture::NanovisViewer::limits { cname } {
     set _limits(min) 0.0
     set _limits(max) 1.0
-    if { ![info exists _style2datasets($tf)] } {
+    if { ![info exists _style2datasets($cname)] } {
         return [array get _limits]
     }
     set min ""; set max ""
-    foreach tag $_style2datasets($tf) {
-        if { ![info exists _serverDatasets($tag)] } {
+    foreach tag [GetDatasetsWithComponent $cname] {
+        if { ![info exists _limits($tag)] } {
             continue
         }
-        if { ![info exists _limits($tag-min)] } {
-            continue
-        }
-        if { $min == "" || $min > $_limits($tag-min) } {
-            set min $_limits($tag-min)
-        }
-        if { $max == "" || $max < $_limits($tag-max) } {
-            set max $_limits($tag-max)
+        foreach {amin amax} $_limits($tag) break
+        if { $min == "" || $min > $amin } {
+            set min $amin
+        }
+        if { $max == "" || $max < $amax } {
+            set max $amax
         }
     }
@@ -1638,21 +1575,9 @@
         set _limits(max) $max
     }
-    return [array get _limits]
+    return [list $_limits(min) $_limits(max)]
 }
 
 
 itcl::body Rappture::NanovisViewer::BuildViewTab {} {
-    foreach { key value } {
-        grid            0
-        axes            1
-        outline         0
-        volume          1
-        legend          1
-        particles       1
-        lic             1
-    } {
-        set _settings($this-$key) $value
-    }
-
     set fg [option get $itk_component(hull) font Font]
     #set bfg [option get $itk_component(hull) boldFont Font]
@@ -1663,39 +1588,39 @@
     $inner configure -borderwidth 4
 
-    set ::Rappture::NanovisViewer::_settings($this-isosurface) 0
+    set ::Rappture::NanovisViewer::_settings(-isosurfaceshading) 0
     checkbutton $inner.isosurface \
         -text "Isosurface shading" \
-        -variable [itcl::scope _settings($this-isosurface)] \
-        -command [itcl::code $this AdjustSetting isosurface] \
+        -variable [itcl::scope _settings(-isosurfaceshading)] \
+        -command [itcl::code $this AdjustSetting -isosurfaceshading] \
         -font "Arial 9"
 
     checkbutton $inner.axes \
         -text "Axes" \
-        -variable [itcl::scope _settings($this-axes)] \
-        -command [itcl::code $this AdjustSetting axes] \
+        -variable [itcl::scope _settings(-axesvisible)] \
+        -command [itcl::code $this AdjustSetting -axesvisible] \
         -font "Arial 9"
 
     checkbutton $inner.grid \
         -text "Grid" \
-        -variable [itcl::scope _settings($this-grid)] \
-        -command [itcl::code $this AdjustSetting grid] \
+        -variable [itcl::scope _settings(-gridvisible)] \
+        -command [itcl::code $this AdjustSetting -gridvisible] \
         -font "Arial 9"
 
     checkbutton $inner.outline \
         -text "Outline" \
-        -variable [itcl::scope _settings($this-outline)] \
-        -command [itcl::code $this AdjustSetting outline] \
+        -variable [itcl::scope _settings(-outlinevisible)] \
+        -command [itcl::code $this AdjustSetting -outlinevisible] \
         -font "Arial 9"
 
     checkbutton $inner.legend \
         -text "Legend" \
-        -variable [itcl::scope _settings($this-legend)] \
-        -command [itcl::code $this AdjustSetting legend] \
+        -variable [itcl::scope _settings(-legendvisible)] \
+        -command [itcl::code $this AdjustSetting -legendvisible] \
         -font "Arial 9"
 
     checkbutton $inner.volume \
         -text "Volume" \
-        -variable [itcl::scope _settings($this-volume)] \
-        -command [itcl::code $this AdjustSetting volume] \
+        -variable [itcl::scope _settings(-volume)] \
+        -command [itcl::code $this AdjustSetting -volume] \
         -font "Arial 9"
 
@@ -1715,14 +1640,4 @@
 
 itcl::body Rappture::NanovisViewer::BuildVolumeTab {} {
-    foreach { key value } {
-        light2side      1
-        light           40
-        transp          50
-        opacity         100
-        thickness       350
-    } {
-        set _settings($this-$key) $value
-    }
-
     set inner [$itk_component(main) insert end \
         -title "Volume Settings" \
@@ -1730,44 +1645,41 @@
     $inner configure -borderwidth 4
 
+    set font [option get $itk_component(hull) font Font]
     set fg [option get $itk_component(hull) font Font]
     #set bfg [option get $itk_component(hull) boldFont Font]
 
     checkbutton $inner.vol -text "Show volume" -font $fg \
-        -variable [itcl::scope _settings($this-volume)] \
-        -command [itcl::code $this AdjustSetting volume]
+        -variable [itcl::scope _settings(-volumevisible)] \
+        -command [itcl::code $this AdjustSetting -volumevisible]
     label $inner.shading -text "Shading:" -font $fg
 
     checkbutton $inner.light2side -text "Two-sided lighting" -font $fg \
-        -variable [itcl::scope _settings($this-light2side)] \
-        -command [itcl::code $this AdjustSetting light2side]
+        -variable [itcl::scope _settings(-light2side)] \
+        -command [itcl::code $this AdjustSetting -light2side]
 
     label $inner.dim -text "Glow" -font $fg
     ::scale $inner.light -from 0 -to 100 -orient horizontal \
-        -variable [itcl::scope _settings($this-light)] \
+        -variable [itcl::scope _settings(-light)] \
         -width 10 \
-        -showvalue off -command [itcl::code $this AdjustSetting light]
+        -showvalue off -command [itcl::code $this AdjustSetting -light]
     label $inner.bright -text "Surface" -font $fg
 
+    # Opacity
     label $inner.fog -text "Clear" -font $fg
     ::scale $inner.transp -from 0 -to 100 -orient horizontal \
-        -variable [itcl::scope _settings($this-transp)] \
+        -variable [itcl::scope _widget(-volumeopacity)] \
         -width 10 \
-        -showvalue off -command [itcl::code $this AdjustSetting transp]
+        -showvalue off -command [itcl::code $this AdjustSetting -volumeopacity]
     label $inner.plastic -text "Opaque" -font $fg
 
-    label $inner.clear -text "Clear" -font $fg
-    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
-        -variable [itcl::scope _settings($this-opacity)] \
-        -width 10 \
-        -showvalue off -command [itcl::code $this AdjustSetting opacity]
-    label $inner.opaque -text "Opaque" -font $fg
-
+    # Tooth thickness
     label $inner.thin -text "Thin" -font $fg
     ::scale $inner.thickness -from 0 -to 1000 -orient horizontal \
-        -variable [itcl::scope _settings($this-thickness)] \
+        -variable [itcl::scope _settings(-thickness)] \
         -width 10 \
-        -showvalue off -command [itcl::code $this AdjustSetting thickness]
+        -showvalue off -command [itcl::code $this AdjustSetting -thickness]
     label $inner.thick -text "Thick" -font $fg
 
+    # Colormap 
     label $inner.colormap_l -text "Colormap" -font "Arial 9" 
     itk_component add colormap {
@@ -1778,8 +1690,19 @@
     $itk_component(colormap) value "BCGYR"
     bind $inner.colormap <<Value>> \
-        [itcl::code $this AdjustSetting colormap]
+        [itcl::code $this AdjustSetting -colormap]
+    $itk_component(colormap) value "default"
+    set _settings(-colormap) "default"
+
+    # Component
+    label $inner.volcomponents_l -text "Component" -font $font
+    itk_component add volcomponents {
+        Rappture::Combobox $inner.volcomponents -editable no
+    }
+    bind $inner.volcomponents <<Value>> \
+        [itcl::code $this AdjustSetting -current]
 
     blt::table $inner \
-        0,0 $inner.vol -cspan 4 -anchor w -pady 2 \
+        0,0 $inner.volcomponents_l -anchor e -cspan 2 \
+        0,2 $inner.volcomponents             -cspan 3 -fill x \
         1,0 $inner.shading -cspan 4 -anchor w -pady {10 2} \
         2,0 $inner.light2side -cspan 4 -anchor w -pady 2 \
@@ -1804,4 +1727,10 @@
     $inner configure -borderwidth 4
 
+    checkbutton $inner.visible \
+        -text "Show Cutplanes" \
+        -variable [itcl::scope _settings(-cutplanesvisible)] \
+        -command [itcl::code $this AdjustSetting -cutplanesvisible] \
+        -font "Arial 9"
+    
     # X-value slicer...
     itk_component add xCutButton {
@@ -1809,9 +1738,10 @@
             -onimage [Rappture::icon x-cutplane] \
             -offimage [Rappture::icon x-cutplane] \
-            -command [itcl::code $this AdjustSetting xcutplane] \
-            -variable [itcl::scope _settings($this-xcutplane)]
+            -command [itcl::code $this AdjustSetting -xcutplanevisible] \
+            -variable [itcl::scope _settings(-xcutplanevisible)]
     }
     Rappture::Tooltip::for $itk_component(xCutButton) \
         "Toggle the X cut plane on/off"
+    $itk_component(xCutButton) select
 
     itk_component add xCutScale {
@@ -1820,5 +1750,5 @@
             -borderwidth 1 -highlightthickness 0 \
             -command [itcl::code $this Slice move x] \
-            -variable [itcl::scope _settings($this-xcutposition)]
+            -variable [itcl::scope _settings(-xcutplaneposition)]
     } {
         usual
@@ -1836,9 +1766,10 @@
             -onimage [Rappture::icon y-cutplane] \
             -offimage [Rappture::icon y-cutplane] \
-            -command [itcl::code $this AdjustSetting ycutplane] \
-            -variable [itcl::scope _settings($this-ycutplane)]
+            -command [itcl::code $this AdjustSetting -ycutplanevisible] \
+            -variable [itcl::scope _settings(-ycutplanevisible)]
     }
     Rappture::Tooltip::for $itk_component(yCutButton) \
         "Toggle the Y cut plane on/off"
+    $itk_component(yCutButton) select
 
     itk_component add yCutScale {
@@ -1847,5 +1778,5 @@
             -borderwidth 1 -highlightthickness 0 \
             -command [itcl::code $this Slice move y] \
-            -variable [itcl::scope _settings($this-ycutposition)]
+            -variable [itcl::scope _settings(-ycutplaneposition)]
     } {
         usual
@@ -1863,9 +1794,10 @@
             -onimage [Rappture::icon z-cutplane] \
             -offimage [Rappture::icon z-cutplane] \
-            -command [itcl::code $this AdjustSetting zcutplane] \
-            -variable [itcl::scope _settings($this-zcutplane)]
+            -command [itcl::code $this AdjustSetting -zcutplanevisible] \
+            -variable [itcl::scope _settings(-zcutplanevisible)]
     }
     Rappture::Tooltip::for $itk_component(zCutButton) \
         "Toggle the Z cut plane on/off"
+    $itk_component(zCutButton) select
 
     itk_component add zCutScale {
@@ -1874,5 +1806,5 @@
             -borderwidth 1 -highlightthickness 0 \
             -command [itcl::code $this Slice move z] \
-            -variable [itcl::scope _settings($this-zcutposition)]
+            -variable [itcl::scope _settings(-zcutplaneposition)]
     } {
         usual
@@ -1881,5 +1813,4 @@
     $itk_component(zCutScale) set 50
     $itk_component(zCutScale) configure -state disabled
-    #$itk_component(zCutScale) configure -state disabled
     Rappture::Tooltip::for $itk_component(zCutScale) \
         "@[itcl::code $this SlicerTip z]"
@@ -1923,9 +1854,9 @@
         label $inner.${tag}label -text $tag -font "Arial 9"
         entry $inner.${tag} -font "Arial 9"  -bg white \
-            -textvariable [itcl::scope _settings($this-$tag)]
+            -textvariable [itcl::scope _settings(-$tag)]
         bind $inner.${tag} <Return> \
-            [itcl::code $this camera set ${tag}]
+            [itcl::code $this camera set -${tag}]
         bind $inner.${tag} <KP_Enter> \
-            [itcl::code $this camera set ${tag}]
+            [itcl::code $this camera set -${tag}]
         blt::table $inner \
             $row,0 $inner.${tag}label -anchor e -pady 2 \
@@ -1976,7 +1907,4 @@
 itcl::body Rappture::NanovisViewer::SlicerTip {axis} {
     set val [$itk_component(${axis}CutScale) get]
-#    set val [expr {0.01*($val-50)
-#        *($_limits(${axis}max)-$_limits(${axis}min))
-#          + 0.5*($_limits(${axis}max)+$_limits(${axis}min))}]
     return "Move the [string toupper $axis] cut plane.\nCurrently:  $axis = $val%"
 }
@@ -1999,5 +1927,5 @@
 }
 
-itcl::body Rappture::NanovisViewer::EventuallyResizeLegend {} {
+itcl::body Rappture::NanovisViewer::EventuallyRedrawLegend {} {
     if { !$_resizeLegendPending } {
         $_dispatcher event -idle !legend
@@ -2014,25 +1942,25 @@
         }
         "set" {
-            set who [lindex $args 0]
-            set x $_settings($this-$who)
+            set what [lindex $args 0]
+            set x $_settings($what)
             set code [catch { string is double $x } result]
             if { $code != 0 || !$result } {
-                set _settings($this-$who) $_view($who)
+                set _settings($what) $_view($what)
                 return
             }
-            switch -- $who {
-                "xpan" - "ypan" {
-                    set _view($who) $_settings($this-$who)
+            switch -- $what {
+                "-xpan" - "-ypan" {
+                    set _view($what) $_settings($what)
                     PanCamera
                 }
-                "qx" - "qy" - "qz" - "qw" {
-                    set _view($who) $_settings($this-$who)
-                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
+                "-qx" - "-qy" - "-qz" - "-qw" {
+                    set _view($what) $_settings($what)
+                    set q [ViewToQuaternion]
                     $_arcball quaternion $q
                     SendCmd "camera orient $q"
                 }
-                "zoom" {
-                    set _view($who) $_settings($this-$who)
-                    SendCmd "camera zoom $_view(zoom)"
+                "-zoom" {
+                    set _view($what) $_settings($what)
+                    SendCmd "camera zoom $_view($what)"
                 }
             }
@@ -2074,15 +2002,15 @@
         array set info $vol
         set name $info(name)
-        if { ![info exists _settings($this-volume-$name)] } {
-            set _settings($this-volume-$name) $info(hide)
+        if { ![info exists _settings(-volumevisible-$name)] } {
+            set _settings(-volumevisible-$name) $info(hide)
         }
         checkbutton $inner.vol$row -text $info(label) \
-            -variable [itcl::scope _settings($this-volume-$name)] \
+            -variable [itcl::scope _settings(-volumevisible-$name)] \
             -onvalue 0 -offvalue 1 \
-            -command [itcl::code $this volume $key $name] \
+            -command [itcl::code $this ToggleVolume $key $name] \
             -font "Arial 9"
         Rappture::Tooltip::for $inner.vol$row $info(description)
         blt::table $inner $row,0 $inner.vol$row -anchor w 
-        if { !$_settings($this-volume-$name) } {
+        if { !$_settings(-volume-$name) } {
             $inner.vol$row select
         } 
@@ -2095,7 +2023,7 @@
 }
 
-itcl::body Rappture::NanovisViewer::volume { tag name } {
-    set bool $_settings($this-volume-$name)
-    SendCmd "volume statue $bool $name"
+itcl::body Rappture::NanovisViewer::ToggleVolume { tag name } {
+    set bool $_settings(-volumevisible-$name)
+    SendCmd "volume state $bool $name"
 }
 
@@ -2109,17 +2037,391 @@
         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 _settings($this-xpan) $_view(xpan)
-    set _settings($this-ypan) $_view(ypan)
-    set _settings($this-zoom) $_view(zoom)
-}
-
+    set _view(-xpan) 0
+    set _view(-ypan) 0
+    set _view(-zoom) 1.0
+    set _settings(-xpan) $_view(-xpan)
+    set _settings(-ypan) $_view(-ypan)
+    set _settings(-zoom) $_view(-zoom)
+}
+
+
+#
+# InitComponentSettings --
+#
+#       Initializes the volume settings for a specific component. This
+#       should match what's used as global settings above. This
+#       is called the first time we try to switch to a given component
+#       in SwitchComponent below.
+#
+itcl::body Rappture::NanovisViewer::InitComponentSettings { cname } { 
+    # Expanding component name for key.
+    array set _settings [subst {
+        $cname-ambient           60
+        $cname-colormap          default
+        $cname-diffuse           40
+        $cname-light2side        1
+        $cname-volumeopacity     0.5
+        $cname-specularexponent  90
+        $cname-specularlevel     30
+        $cname-thickness         350
+        $cname-volumevisible     1
+    }]
+}
+
+#
+# SwitchComponent --
+#
+#       This is called when the current component is changed by the
+#       dropdown menu in the volume tab.  It synchronizes the global
+#       volume settings with the settings of the new current component.
+#
+itcl::body Rappture::NanovisViewer::SwitchComponent { cname } { 
+    if { ![info exists _settings($cname-ambient)] } {
+        InitComponentSettings $cname
+    }
+    # _settings variables change widgets, except for colormap
+    set _settings(-ambient)          $_settings($cname-ambient)
+    set _settings(-colormap)         $_settings($cname-colormap)
+    set _settings(-diffuse)          $_settings($cname-diffuse)
+    set _settings(-light2side)       $_settings($cname-light2side)
+    set _settings(-specularexponent) $_settings($cname-specularexponent)
+    set _settings(-specularlevel)    $_settings($cname-specularlevel)
+    set _settings(-thickness)        $_settings($cname-thickness)
+    set _settings(-volumeopacity)    $_settings($cname-volumeopacity)
+    set _settings(-volumevisible)    $_settings($cname-volumevisible)
+    $itk_component(colormap) value   $_settings($cname-colormap)
+    set _current $cname;                # Reset the current component
+}
+
+#
+# BuildVolumeComponents --
+#
+#       This is called from the "scale" method which is called when a
+#       new dataset is added or deleted.  It repopulates the dropdown
+#       menu of volume component names.  It sets the current component
+#       to the first component in the list (of components found).
+#       Finally, if there is only one component, don't display the
+#       label or the combobox in the volume settings tab.
+#
+itcl::body Rappture::NanovisViewer::BuildVolumeComponents {} { 
+    $itk_component(volcomponents) choices delete 0 end
+    foreach name $_componentsList {
+        $itk_component(volcomponents) choices insert end $name $name
+    }
+    set _current [lindex $_componentsList 0]
+    $itk_component(volcomponents) value $_current
+    set parent [winfo parent $itk_component(volcomponents)]
+    if { [llength $_componentsList] <= 1 } {
+        # Unpack the components label and dropdown if there's only one
+        # component. 
+        blt::table forget $parent.volcomponents_l $parent.volcomponents
+    } else {
+        # Pack the components label and dropdown into the table there's 
+        # more than one component to select. 
+        blt::table $parent \
+            0,0 $parent.volcomponents_l -anchor e -cspan 2 \
+            0,2 $parent.volcomponents -cspan 3 -fill x 
+    }
+}
+
+#
+# GetDatasetsWithComponents --
+#
+#       Returns a list of all the datasets (known by the combination of
+#       their data object and component name) that match the given 
+#       component name.  For example, this is used where we want to change 
+#       the settings of volumes that have the current component.
+#
+itcl::body Rappture::NanovisViewer::GetDatasetsWithComponent { cname } { 
+    if { ![info exists _volcomponents($cname)] } {
+        return ""
+    }
+    set list ""
+    foreach tag $_volcomponents($cname) {
+        if { ![info exists _serverDatasets($tag)] } {
+            continue
+        }
+        lappend list $tag
+    }
+    return $list
+}
+
+#
+# HideAllMarkers --
+#
+#       Hide all the markers in all the transfer functions.  Can't simply 
+#       delete and recreate markers from the <style> since the user may 
+#       have create, deleted, or moved markers.
+#
+itcl::body Rappture::NanovisViewer::HideAllMarkers {} { 
+    foreach cname [array names _transferFunctionEditors] {
+        $_transferFunctionEditors($cname) hideMarkers 
+    }
+}
+
+itcl::body Rappture::NanovisViewer::GetColormap { cname color } { 
+    if { $color == "default" } {
+        return $_cname2defaultcolormap($cname)
+    }
+    return [ColorsToColormap $color]
+}
+
+itcl::body Rappture::NanovisViewer::GetAlphamap { cname name } { 
+    if { $name == "default" } {
+        return $_cname2defaultalphamap($cname)
+    }
+    return [NameToAlphamap $name]
+}
+
+itcl::body Rappture::NanovisViewer::ResetColormap { cname color } { 
+    # Get the current transfer function
+    if { ![info exists _cname2transferFunction($cname)] } {
+        return
+    }
+    foreach { cmap wmap } $_cname2transferFunction($cname) break
+    set cmap [GetColormap $cname $color]
+    set _cname2transferFunction($cname) [list $cmap $wmap]
+    SendCmd [list transfunc define $cname $cmap $wmap]
+    EventuallyRedrawLegend
+}
+
+itcl::body Rappture::NanovisViewer::ComputeAlphamap { cname } { 
+    if { ![info exists _transferFunctionEditors($cname)] } {
+        return [list 0.0 0.0 1.0 1.0]
+    }
+    if { ![info exists _settings($cname-ambient)] } {
+        InitComponentSettings $cname
+    }
+
+    set isovalues [$_transferFunctionEditors($cname) values]
+
+    # Currently using volume shading opacity to scale opacity in
+    # the volume shader. The transfer function always sets full
+    # opacity
+    set max 1.0
+
+    # Use the component-wise thickness setting from the slider
+    # settings widget
+    # Scale values between 0.00001 and 0.01000
+    set delta [expr {double($_settings($cname-thickness)) * 0.0001}]
+    
+    set first [lindex $isovalues 0]
+    set last [lindex $isovalues end]
+    set wmap ""
+    if { $first == "" || $first != 0.0 } {
+        lappend wmap 0.0 0.0
+    }
+    foreach x $isovalues {
+        set x1 [expr {$x-$delta-0.00001}]
+        set x2 [expr {$x-$delta}]
+        set x3 [expr {$x+$delta}]
+        set x4 [expr {$x+$delta+0.00001}]
+        if { $x1 < 0.0 } {
+            set x1 0.0
+        } elseif { $x1 > 1.0 } {
+            set x1 1.0
+        }
+        if { $x2 < 0.0 } {
+            set x2 0.0
+        } elseif { $x2 > 1.0 } {
+            set x2 1.0
+        }
+        if { $x3 < 0.0 } {
+            set x3 0.0
+        } elseif { $x3 > 1.0 } {
+            set x3 1.0
+        }
+        if { $x4 < 0.0 } {
+            set x4 0.0
+        } elseif { $x4 > 1.0 } {
+            set x4 1.0
+        }
+        # add spikes in the middle
+        lappend wmap $x1 0.0
+        lappend wmap $x2 $max
+        lappend wmap $x3 $max
+        lappend wmap $x4 0.0
+    }
+    if { $last == "" || $last != 1.0 } {
+        lappend wmap 1.0 0.0
+    }
+    return $wmap
+}
+
+
+itcl::body Rappture::NanovisViewer::NameToAlphamap { name } {
+    switch -- $name {
+        "ramp-up" {
+            set wmap { 
+                0.0 0.0 
+                1.0 1.0 
+            }
+        }
+        "ramp-down" {
+            set wmap { 
+                0.0 1.0 
+                1.0 0.0 
+            }
+        }
+        "vee" {
+            set wmap { 
+                0.0 1.0 
+                0.5 0.0 
+                1.0 1.0 
+            }
+        }
+        "tent-1" {
+            set wmap { 
+                0.0 0.0 
+                0.5 1.0 
+                1.0 0.0 
+            }
+        }
+        "tent-2" {
+            set wmap { 
+                0.0 0.0 
+                0.25 1.0 
+                0.5 0.0 
+                0.75 1.0 
+                1.0 0.0 
+            }
+        }
+        "tent-3" {
+            set wmap { 
+                0.0 0.0 
+                0.16666 1.0
+                0.33333 0.0
+                0.5     1.0
+                0.66666 0.0
+                0.83333 1.0
+                1.0 0.0 
+            }
+        }
+        "tent-4" {
+            set wmap { 
+                0.0     0.0 
+                0.125   1.0
+                0.25    0.0
+                0.375   1.0
+                0.5     0.0        
+                0.625   1.0
+                0.75    0.0
+                0.875   1.0
+                1.0     0.0 
+            }
+        }
+        "sinusoid-1" {
+            set wmap {
+                0.0                     0.000 0.600 0.800 
+                0.14285714285714285     0.400 0.900 1.000 
+                0.2857142857142857      0.600 1.000 1.000 
+                0.42857142857142855     0.800 1.000 1.000 
+                0.5714285714285714      0.900 0.900 0.900 
+                0.7142857142857143      0.600 0.600 0.600 
+                0.8571428571428571      0.400 0.400 0.400 
+                1.0                     0.200 0.200 0.200
+            }
+        }
+        "sinusoid-2" {
+            set wmap { 
+                0.0                     0.900 1.000 1.000 
+                0.1111111111111111      0.800 0.983 1.000 
+                0.2222222222222222      0.700 0.950 1.000 
+                0.3333333333333333      0.600 0.900 1.000 
+                0.4444444444444444      0.500 0.833 1.000 
+                0.5555555555555556      0.400 0.750 1.000 
+                0.6666666666666666      0.300 0.650 1.000 
+                0.7777777777777778      0.200 0.533 1.000 
+                0.8888888888888888      0.100 0.400 1.000 
+                1.0                     0.000 0.250 1.000
+            }
+        }
+        "sinusoid-6" {
+            set wmap {
+                0.0                             0.200   0.100   0.000 
+                0.09090909090909091             0.400   0.187   0.000 
+                0.18181818181818182             0.600   0.379   0.210 
+                0.2727272727272727              0.800   0.608   0.480 
+                0.36363636363636365             0.850   0.688   0.595 
+                0.45454545454545453             0.950   0.855   0.808 
+                0.5454545454545454              0.800   0.993   1.000 
+                0.6363636363636364              0.600   0.973   1.000 
+                0.7272727272727273              0.400   0.940   1.000 
+                0.8181818181818182              0.200   0.893   1.000 
+                0.9090909090909091              0.000   0.667   0.800 
+                1.0                             0.000   0.480   0.600 
+            }
+        }
+        "sinusoid-10" {
+            set wmap {
+                0.0                             0.000   0.480   0.600 
+                0.09090909090909091             0.000   0.667   0.800 
+                0.18181818181818182             0.200   0.893   1.000 
+                0.2727272727272727              0.400   0.940   1.000 
+                0.36363636363636365             0.600   0.973   1.000 
+                0.45454545454545453             0.800   0.993   1.000 
+                0.5454545454545454              0.950   0.855   0.808 
+                0.6363636363636364              0.850   0.688   0.595 
+                0.7272727272727273              0.800   0.608   0.480 
+                0.8181818181818182              0.600   0.379   0.210 
+                0.9090909090909091              0.400   0.187   0.000 
+                1.0                             0.200   0.100   0.000 
+            }
+        }
+        "step-2" {
+            set wmap {
+                0.0                             0.000   0.167   1.000
+                0.09090909090909091             0.100   0.400   1.000
+                0.18181818181818182             0.200   0.600   1.000
+                0.2727272727272727              0.400   0.800   1.000
+                0.36363636363636365             0.600   0.933   1.000
+                0.45454545454545453             0.800   1.000   1.000
+                0.5454545454545454              1.000   1.000   0.800
+                0.6363636363636364              1.000   0.933   0.600
+                0.7272727272727273              1.000   0.800   0.400
+                0.8181818181818182              1.000   0.600   0.200
+                0.9090909090909091              1.000   0.400   0.100
+                1.0                             1.000   0.167   0.000
+            }
+        }
+        "step-5" {
+            set wmap {
+                0.0                             1.000   0.167   0.000
+                0.09090909090909091             1.000   0.400   0.100
+                0.18181818181818182             1.000   0.600   0.200
+                0.2727272727272727              1.000   0.800   0.400
+                0.36363636363636365             1.000   0.933   0.600
+                0.45454545454545453             1.000   1.000   0.800
+                0.5454545454545454              0.800   1.000   1.000
+                0.6363636363636364              0.600   0.933   1.000
+                0.7272727272727273              0.400   0.800   1.000
+                0.8181818181818182              0.200   0.600   1.000
+                0.9090909090909091              0.100   0.400   1.000
+                1.0                             0.000   0.167   1.000
+            }
+        }
+        "step-12" {
+            set wmap {
+                "#EE82EE"
+                "#4B0082" 
+                "blue" 
+                "#008000" 
+                "yellow" 
+                "#FFA500" 
+                "red" 
+            }
+        }
+        default {
+        }
+    }
+    return ""
+}
+
+
Index: branches/1.3/gui/scripts/transferfunctioneditor.tcl
===================================================================
--- branches/1.3/gui/scripts/transferfunctioneditor.tcl	(revision 4504)
+++ branches/1.3/gui/scripts/transferfunctioneditor.tcl	(revision 4504)
@@ -0,0 +1,353 @@
+# -*- mode: tcl; indent-tabs-mode: nil -*- 
+
+# ----------------------------------------------------------------------
+#  COMPONENT: transferfunctioneditor - Rudimentary editor for 3D volume 
+#                                      transfer functions
+#
+#  This class is used to modify transfer functions used in volume rendering 
+#  on 3D scalar/vector datasets.
+#
+# ======================================================================
+#  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
+
+itcl::class Rappture::TransferFunctionEditor {
+    private variable _nextId 0;         # Used to create unique marker names
+    private variable _values;           # Relative values for each marker.
+    private variable _limits;           # Over limits of transfer function.
+    private variable _labels;           # Label id for each marker.
+    private variable _ticks;            # Tick id for each marker.
+    private variable _canvas    ""
+    private variable _name "";		# Name of transfer function.
+    private variable _activeMotion   0
+    private variable _activePress    0
+    private variable _id2name
+    private common   _normalIcon [Rappture::icon nvlegendmark]
+    private common   _activeIcon [Rappture::icon nvlegendmark2]
+    public variable command ""
+
+    private method SetAbsoluteValue { name x } 
+    private method GetAbsoluteValue { name } 
+    private method ContinueDrag { name x y } 
+    private method EnterTick { name } 
+    private method GetOverlappingMarkers { x y } 
+    private method GetScreenPosition { name } 
+    private method LeaveTick { name } 
+    private method SetRelativeValue  { name x }
+    private method GetRelativeValue  { name }
+    private method RemoveDuplicateMarkers {name x y} 
+    private method SetScreenPosition { name } 
+    private method SetVisibility { name bool } 
+    private method StartDrag { name x y } 
+    private method StopDrag { name x y } 
+    private method Activate { name } 
+    private method Deactivate { name } 
+    private method UpdateViewer {} 
+
+    constructor {c name args} {}
+    destructor {} 
+    public method limits { min max }
+    public method names {}
+    public method name {}
+    public method values {}
+    public method absoluteValues {}
+    public method removeMarkers { list }
+    public method addMarkers { values }
+    public method newMarker { x y state }
+    public method deleteMarker { x y }
+    public method hideMarkers { {list {}} }
+    public method showMarkers { {limits {}} }
+}
+
+itcl::body Rappture::TransferFunctionEditor::constructor {c name args} { 
+    set _canvas $c
+    set _name $name
+    set _limits [list 0.0 1.0] 
+    eval configure $args
+}
+
+itcl::body Rappture::TransferFunctionEditor::limits { min max } { 
+    set _limits [list $min $max]
+}
+
+itcl::body Rappture::TransferFunctionEditor::names {} { 
+    return [lsort [array names _values]]
+}
+
+itcl::body Rappture::TransferFunctionEditor::values {} { 
+    set list {}
+    foreach name [array names _ticks] {
+	lappend list [GetRelativeValue $name]
+    }
+    return [lsort -real $list]
+}
+
+itcl::body Rappture::TransferFunctionEditor::absoluteValues {} { 
+    set list {}
+    foreach name [array names _values] {
+	lappend list [GetAbsoluteValue $name]
+    }
+    return $list
+}
+
+itcl::body Rappture::TransferFunctionEditor::deleteMarker { x y } { 
+    foreach marker [GetOverlappingMarkers $x $y] {
+        $_canvas delete $_ticks($marker)
+        $_canvas delete $_labels($marker)
+        array unset _ticks $marker
+        array unset _labels $marker
+        array unset _values $marker
+        bell
+        UpdateViewer
+    }
+}
+
+itcl::body Rappture::TransferFunctionEditor::newMarker { x y state } { 
+    foreach id [$_canvas find overlapping \
+                    [expr $x-5] [expr $y-5] [expr $x+5] [expr $y+5]] {
+	if { [info exists _id2name($id)] } {
+            puts stderr "Too close to existing marker"
+	    return;                     # Too close to existing marker
+	}
+    }
+    set name "tick[incr _nextId]"
+    set w [winfo width $_canvas]
+    set h [winfo height $_canvas]
+
+    set _ticks($name) [$_canvas create image 0 $h \
+                           -image $_normalIcon -anchor s \
+                           -tags "tick $_name $this" -state $state]
+    set _labels($name) [$_canvas create text 0 $h \
+                            -anchor n -fill white -font "Helvetica 8" \
+                            -tags "labels $this $_name" -state $state]
+    set _id2name($_ticks($name)) $name
+    $_canvas bind $_ticks($name) <Enter> [itcl::code $this EnterTick $name]
+    $_canvas bind $_ticks($name) <Leave> [itcl::code $this LeaveTick $name]
+    $_canvas bind $_ticks($name) <ButtonPress-1> \
+	[itcl::code $this StartDrag $name %x %y]
+    $_canvas bind $_ticks($name) <B1-Motion> \
+	[itcl::code $this ContinueDrag $name %x %y]
+    $_canvas bind $_ticks($name) <ButtonRelease-1> \
+	[itcl::code $this StopDrag $name %x %y]
+
+    SetRelativeValue $name [expr {double($x-10)/($w-20)}]
+    if { $state == "normal" } {
+        UpdateViewer
+    }
+    return $name
+}
+
+itcl::body Rappture::TransferFunctionEditor::destructor {} {
+    $_canvas delete $_name
+}
+
+itcl::body Rappture::TransferFunctionEditor::name {} {
+    return $_name
+}
+
+itcl::body Rappture::TransferFunctionEditor::Activate { name } {
+    if  { $_activePress || $_activeMotion } {
+        $_canvas itemconfigure $_labels($name) -state normal
+        $_canvas itemconfigure $_ticks($name) -image $_activeIcon
+        $_canvas itemconfigure title -state hidden
+    }
+}
+
+itcl::body Rappture::TransferFunctionEditor::Deactivate { name } {
+    if  { $_activePress || $_activeMotion } {
+        #puts stderr "do nothing for Deactivate"
+    } else {
+        $_canvas itemconfigure $_labels($name) -state hidden
+        $_canvas itemconfigure $_ticks($name) -image $_normalIcon
+        $_canvas itemconfigure title -state normal
+    }
+}
+
+itcl::body Rappture::TransferFunctionEditor::SetVisibility { name bool } {
+    if { $bool } {
+        $_canvas itemconfigure $_ticks($name) -state normal
+        $_canvas raise $_ticks($name)
+    } else {
+        $_canvas itemconfigure $_ticks($name) -state hidden
+    }
+}
+
+itcl::body Rappture::TransferFunctionEditor::GetScreenPosition { name } { 
+    set x [GetRelativeValue $name]
+    if { $x < 0.0 } {
+        set x 0.0
+    } elseif { $x > 1.0 } {
+        set x 1.0 
+    }
+    set low 10 
+    set w [winfo width $_canvas]
+    set high [expr {$w  - 10}]
+    set x [expr {round($x*($high - $low) + $low)}]
+    return $x
+}
+
+itcl::body Rappture::TransferFunctionEditor::SetScreenPosition { name } { 
+    set value $_values($name)
+    set x [GetScreenPosition $name]
+    set absval [GetAbsoluteValue $name]
+    set y 31
+    $_canvas itemconfigure $_labels($name) -text [format %g $absval]
+    $_canvas coords $_ticks($name) $x [expr {$y+3}]
+    $_canvas coords $_labels($name) $x [expr {$y+5}]
+}
+
+itcl::body Rappture::TransferFunctionEditor::GetAbsoluteValue { name } {
+    foreach {min max} $_limits break
+    return [expr {($_values($name) * ($max - $min)) + $min}]
+}
+
+itcl::body Rappture::TransferFunctionEditor::SetAbsoluteValue { name value } {
+    foreach {min max} $_limits break
+    set absval $value
+    set relval [expr {($absval - $min) / ($max - $min)}]
+    set _values($name) $relval
+    set y 31
+    $_canvas itemconfigure $_label -text [format %g $absval]
+    set x [GetScreenPosition $name]
+    $_canvas coords $_ticks($name) $x [expr {$y+3}]
+    $_canvas coords $_labels($name) $x [expr {$y+5}]
+    return $absval
+}
+
+itcl::body Rappture::TransferFunctionEditor::GetRelativeValue  { name } {
+    return $_values($name)
+}
+
+itcl::body Rappture::TransferFunctionEditor::SetRelativeValue  { name value } {
+    set _values($name) $value
+    set x [GetScreenPosition $name]
+    set y 31
+    set absval [GetAbsoluteValue $name]
+    $_canvas itemconfigure $_labels($name) -text [format %g $absval]
+    $_canvas coords $_ticks($name) $x [expr {$y+3}]
+    $_canvas coords $_labels($name) $x [expr {$y+5}]
+}
+
+itcl::body Rappture::TransferFunctionEditor::EnterTick { name } {
+    set _activeMotion 1
+    Activate $name
+    $_canvas raise $_ticks($name)
+}
+
+itcl::body Rappture::TransferFunctionEditor::LeaveTick { name } {
+    set _activeMotion 0
+    Deactivate $name
+}
+
+itcl::body Rappture::TransferFunctionEditor::StartDrag { name x y } {
+    $_canvas raise $_ticks($name) 
+    set _activePress 1
+    Activate $name
+    $_canvas itemconfigure limits -state hidden
+    $_canvas itemconfigure title -state hidden
+}
+
+itcl::body Rappture::TransferFunctionEditor::StopDrag { name x y } {
+    ContinueDrag $name $x $y 
+    RemoveDuplicateMarkers $name $x $y
+    set _activePress 0
+    Deactivate $name
+    $_canvas itemconfigure limits -state normal
+    $_canvas itemconfigure title -state normal
+}
+
+itcl::body Rappture::TransferFunctionEditor::ContinueDrag { name x y } {
+    set w [winfo width $_canvas]
+    SetRelativeValue $name [expr {double($x-10)/($w-20)}]
+    UpdateViewer
+    $_canvas raise $_ticks($name)
+    set _activePress 1
+    Activate $name
+    $_canvas itemconfigure limits -state hidden
+    $_canvas itemconfigure title -state hidden
+}
+
+itcl::body Rappture::TransferFunctionEditor::GetOverlappingMarkers { x y } {
+    set list {}
+    foreach id [$_canvas find overlapping $x $y $x $y] {
+	if { [info exists _id2name($id)] } {
+	    lappend list $_id2name($id)
+	}
+    }
+    return $list
+}
+
+itcl::body Rappture::TransferFunctionEditor::hideMarkers { {list {}} } {
+    if { $list == "" } {
+	set list [array names _values]
+    }
+    foreach name $list {
+	SetVisibility $name 0
+    }
+}
+
+itcl::body Rappture::TransferFunctionEditor::showMarkers { {limits {}} } {
+    if { $limits != "" } {
+	set _limits $limits
+	foreach name [array names _values] {
+	    SetScreenPosition $name 
+	}
+    }
+    foreach name [array names _values] {
+	SetVisibility $name 1
+    }
+}
+
+itcl::body Rappture::TransferFunctionEditor::RemoveDuplicateMarkers {name x y} {
+    foreach marker [GetOverlappingMarkers $x $y] {
+	if { $marker != $name } {
+            Activate $marker 
+            set markerx [GetScreenPosition $marker]
+            if { ($x < ($markerx-3)) || ($x > ($markerx+3)) } {
+                continue
+            }
+	    $_canvas delete $_ticks($marker)
+	    $_canvas delete $_labels($marker)
+	    array unset _ticks $marker
+	    array unset _labels $marker
+	    array unset _values $marker
+            bell
+	}
+    }
+}
+
+itcl::body Rappture::TransferFunctionEditor::addMarkers { values } {
+    foreach value $values {
+	set name [newMarker 0 0 hidden]
+	SetRelativeValue $name $value
+    }
+}
+
+itcl::body Rappture::TransferFunctionEditor::removeMarkers { names } {
+    if { $names == "" } {
+	set names [array names _values]
+    }
+    foreach name $names {
+	$_canvas delete $_ticks($name)
+	$_canvas delete $_labels($name)
+	array unset _ticks $name
+	array unset _labels $name
+	array unset _values $name
+    }
+    UpdateViewer
+}
+
+itcl::body Rappture::TransferFunctionEditor::UpdateViewer {} {
+    # Tell the nanovis/flowvis client to update its transfer functions
+    # now that a marker position has changed.
+    if { $command != "" } {
+	eval uplevel \#0 $command
+    }
+}
Index: branches/1.3/gui/scripts/vtkisosurfaceviewer.tcl
===================================================================
--- branches/1.3/gui/scripts/vtkisosurfaceviewer.tcl	(revision 4501)
+++ branches/1.3/gui/scripts/vtkisosurfaceviewer.tcl	(revision 4504)
@@ -141,4 +141,6 @@
     private variable _contourList
     private variable _currentLimits ""
+    private variable _widget
+
     common _downloadPopup;              # download options from popup
     private common _hardcopy
@@ -242,5 +244,5 @@
         -cutplaneedges                  0
         -cutplanelighting               1
-        -cutplaneopacity                100
+        -cutplaneopacity                1.0
         -cutplanepreinterp              1
         -cutplanesvisible               0
@@ -250,5 +252,5 @@
         -isosurfaceedges                0
         -isosurfacelighting             1
-        -isosurfaceopacity              60
+        -isosurfaceopacity              0.6
         -isosurfacevisible              1
         -isosurfacewireframe            0
@@ -269,5 +271,10 @@
         -colormap                0
         -isosurfaceopacity       0
+        -cutplaneopacity         0
         -numcontours             0
+    }
+    array set _widget {
+        -isosurfaceopacity       0
+        -cutplaneopacity         0
     }
 
@@ -483,5 +490,5 @@
     GenerateContourList
     SendCmd [list contour3d contourlist $_contourList(values)]
-    #SendCmd [list camera reset]
+    SendCmd [list camera reset]
     DrawLegend
     set _contourList(updatePending) 0
@@ -970,5 +977,4 @@
     # generates a new call to Rebuild).   
     StartBufferingCommands
-
     if { $_reset } {
         set _width $w
@@ -991,7 +997,7 @@
         InitSettings -xgrid -ygrid -zgrid -axismode \
             -axesvisible -axislabelsvisible 
-        foreach axis { x y z } {
-	    SendCmd "axis lformat $axis %g"
-	}
+        SendCmd "axis lformat all %g"
+        # Too many major ticks, so turn off minor ticks
+        SendCmd "axis minticks all 0"
         StopBufferingCommands
         SendCmd "imgflush"
@@ -1101,5 +1107,4 @@
                 set label [string toupper $axis]
 	    }
-	    # May be a space in the axis label.
 	    SendCmd [list axis name $axis $label]
         }
@@ -1413,7 +1418,6 @@
         }
         "-cutplaneopacity" {
-            set val $_settings($what)
-            set sval [expr { 0.01 * double($val) }]
-            SendCmd "cutplane opacity $sval"
+            set _settings($what) [$_widget(-cutplaneopacity) * 0.01]
+            SendCmd "cutplane opacity $_settings($what)"
         }
         "-cutplanepreinterp" {
@@ -1509,7 +1513,6 @@
         }
         "-isosurfaceopacity" {
-            set val $_settings($what)
-            set sval [expr { 0.01 * double($val) }]
-	    SendCmd "contour3d opacity $sval"
+            set _settings($what) [$_widget(-isosurfaceopacity) * 0.01]
+	    SendCmd "contour3d opacity $_settings($what)"
         }
         "-field" {
@@ -1539,4 +1542,5 @@
             SendCmd "contour3d colormode $_colorMode $_curFldName"
             SendCmd "camera reset"
+            UpdateContourList
             DrawLegend
         }
@@ -1714,8 +1718,9 @@
     label $inner.opacity_l -text "Opacity" -font "Arial 9"
     ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
-        -variable [itcl::scope _settings(-isosurfaceopacity)] \
+        -variable [itcl::scope _widget(-isosurfaceopacity)] \
         -width 10 \
         -showvalue off \
         -command [itcl::code $this AdjustSetting -isosurfaceopacity]
+    $inner.opacity set [expr $_settings(-isosurfaceeopacity) * 100.0]
 
     itk_component add field_l {
@@ -1734,6 +1739,6 @@
         Rappture::Combobox $inner.colormap -width 10 -editable 0
     }
-
     $inner.colormap choices insert end [GetColormapList]
+
     $itk_component(colormap) value "BCGYR"
     bind $inner.colormap <<Value>> \
@@ -1927,9 +1932,9 @@
     label $inner.opacity_l -text "Opacity" -font "Arial 9"
     ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
-        -variable [itcl::scope _settings(-cutplaneopacity)] \
+        -variable [itcl::scope _widget(-cutplaneopacity)] \
         -width 10 \
         -showvalue off \
         -command [itcl::code $this AdjustSetting -cutplaneopacity]
-    $inner.opacity set $_settings(-cutplaneopacity)
+    $inner.opacity set [expr $_settings(-cutplaneopacity) * 100.0]
 
     # X-value slicer...
@@ -2150,25 +2155,25 @@
     set tag $dataobj-$comp
     array set style {
-        -color BCGYR
-        -cutplanesvisible 0 
-        -edgecolor black
-        -edges 0
-        -isosurfacevisible 1
-        -levels 10
-        -lighting 1
-        -linewidth 1.0
-        -opacity 0.6
-        -outline 0
-        -wireframe 0
-        -xcutplaneposition 50
-        -xcutplanevisible 1
-        -ycutplaneposition 50
-        -ycutplanevisible 1
-        -zcutplaneposition 50
-        -zcutplanevisible 1
+        -color                  BCGYR
+        -cutplanesvisible       0 
+        -edgecolor              black
+        -edges                  0
+        -isosurfaceopacity      0.6
+        -isosurfacevisible      1
+        -levels                 10
+        -lighting               1
+        -linewidth              1.0
+        -outline                0
+        -wireframe              0
+        -xcutplaneposition      50
+        -xcutplanevisible       1
+        -ycutplaneposition      50
+        -ycutplanevisible       1
+        -zcutplaneposition      50
+        -zcutplanevisible       1
     }
     array set style [$dataobj style $comp]
     if { $dataobj != $_first || $style(-levels) == 1 } {
-        set style(-opacity) 1
+        set style(-isosurfaceopacity) 1.0
     }
 
@@ -2183,5 +2188,5 @@
 
     if { $_changed(-isosurfaceopacity) } {
-        set style(-opacity) [expr $_settings(-isosurfaceopacity) * 0.01]
+        set style(-isosurfaceopacity) $_settings(-isosurfaceopacity)
     }
     if { $_changed(-numcontours) } {
@@ -2196,7 +2201,11 @@
     }
     if { $_contourList(numLevels) != $style(-levels) } {
-        set _settings(-numcontours) $style(-levels)
-        $itk_component(numcontours) value $style(-levels)
-        set _contourList(numLevels) $style(-levels)
+        if { [llength $style(-levels)] > 1 } {
+            set _contourList(reqValues) [lsort -real $style(-levels)]
+        } else {
+            set _settings(-numcontours) $style(-levels)
+            $itk_component(numcontours) value $style(-levels)
+            set _contourList(numLevels) $style(-levels)
+        }
         EventuallyChangeContourLevels 
     }
@@ -2228,6 +2237,6 @@
     SendCmd "contour3d linecolor [Color2RGB $style(-edgecolor)] $tag"
     SendCmd "contour3d linewidth $style(-linewidth) $tag"
-    SendCmd "contour3d opacity $style(-opacity) $tag"
-    set _settings(-isosurfaceopacity) [expr $style(-opacity) * 100.0]
+    SendCmd "contour3d opacity $style(-isosurfaceopacity) $tag"
+    set _settings(-isosurfaceopacity) $style(-isosurfaceopacity)
     SetCurrentColormap $style(-color) 
     SendCmd "contour3d wireframe $style(-wireframe) $tag"
@@ -2593,15 +2602,21 @@
 itcl::body Rappture::VtkIsosurfaceViewer::GenerateContourList {} { 
     if { ![info exists _limits($_curFldName)] } {
+        puts stderr "no _curFldName"
         return ""
     }
     if { $_contourList(numLevels) < 1 } {
+        puts stderr "numLevels < 1"
         return ""
     }
-    foreach { vmin vmax } $_limits($_curFldName) break
-    set v [blt::vector create \#auto]
-    $v seq $vmin $vmax [expr $_contourList(numLevels)+2]
-    $v delete end 0
-    set values [$v range 0 end]
-    blt::vector destroy $v
+    if { [llength $_contourList(reqValues)] > 1 } {
+        set values $_contourList(reqValues)
+    } else {
+        foreach { vmin vmax } $_limits($_curFldName) break
+        set v [blt::vector create \#auto]
+        $v seq $vmin $vmax [expr $_contourList(numLevels)+2]
+        $v delete end 0
+        set values [$v range 0 end]
+        blt::vector destroy $v
+    }
     set _contourList(values) $values
 }
