Changeset 1349


Ignore:
Timestamp:
Mar 20, 2009, 6:54:23 PM (16 years ago)
Author:
gah
Message:

my first cut at flowvisviewer client based on work by dsk

Location:
trunk/gui/scripts
Files:
10 added
3 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/gui/scripts/flowvisviewer.tcl

    r1343 r1349  
    11
    22# ----------------------------------------------------------------------
    3 #  COMPONENT: flowvisviewer - 3D vector field rendering
    4 #
    5 #  This widget performs vector field rendering on 3D scalar/vector datasets.
    6 #  It connects to the Nanovis server running on a rendering farm,
    7 #  transmits data, and displays the results.
     3#  COMPONENT: flowvisviewer - 3D flow rendering
     4#
     5#
     6# This widget performs volume and flow rendering on 3D scalar/vector datasets.
     7# It connects to the Flowvis server running on a rendering farm, transmits
     8# data, and displays the results.
     9#
    810# ======================================================================
    9 #  AUTHOR:  Derrick Kearney, Purdue University
    10 #  Copyright (c) 2005-2009  Purdue Research Foundation
    11 #
    12 #  See the file "license.terms" for information on usage and
    13 #  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
     11#  AUTHOR:  Michael McLennan, Purdue University
     12#  Copyright (c) 2004-2005  Purdue Research Foundation
     13#
     14# See the file "license.terms" for information on usage and redistribution of
     15# this file, and for a DISCLAIMER OF ALL WARRANTIES.
    1416# ======================================================================
    15 
    1617package require Itk
    1718package require BLT
     
    1920
    2021option add *FlowvisViewer.width 4i widgetDefault
     22option add *FlowvisViewer*cursor crosshair widgetDefault
    2123option add *FlowvisViewer.height 4i widgetDefault
    2224option add *FlowvisViewer.foreground black widgetDefault
     
    2527option add *FlowvisViewer.plotBackground black widgetDefault
    2628option add *FlowvisViewer.plotForeground white widgetDefault
    27 option add *FlowvisViewer.plotOutline white widgetDefault
     29#FIXME: why is plot outline gray? not white?
     30option add *FlowvisViewer.plotOutline gray widgetDefault
    2831option add *FlowvisViewer.font \
    2932    -*-helvetica-medium-r-normal-*-12-* widgetDefault
    30 option add *FlowvisViewer.boldFont \
    31     -*-helvetica-bold-r-normal-*-12-* widgetDefault
    3233
    3334# must use this name -- plugs into Rappture::resources::load
    3435proc FlowvisViewer_init_resources {} {
    3536    Rappture::resources::register \
    36         nanovis_server Rappture::FlowvisViewer::SetServerList
     37        nanovis_server Rappture::FlowvisViewer::SetServerList
    3738}
    3839
     
    4546
    4647    constructor { hostlist args } {
    47         Rappture::VisViewer::constructor $hostlist
     48        Rappture::VisViewer::constructor $hostlist
    4849    } {
    49         # defined below
     50        # defined below
    5051    }
    5152    destructor {
    52         # defined below
    53     }
    54 
     53        # defined below
     54    }
    5555    public proc SetServerList { namelist } {
    56         Rappture::VisViewer::SetServerList "nanovis" $namelist
     56        Rappture::VisViewer::SetServerList "nanovis" $namelist
    5757    }
    5858    public method add {dataobj {settings ""}}
     
    6262    public method download {option args}
    6363    public method parameters {title args} {
    64         # do nothing
     64        # do nothing
    6565    }
    6666    public method isconnected {}
     67
     68    public method GetLimits { tf }
     69    public method UpdateTransferFunctions {}
     70    public method RemoveDuplicateIsoMarker { m x }
     71    public method OverIsoMarker { m x }
     72
     73    public method drawer {what who}
     74    public method camera {option args}
    6775
    6876    protected method Connect {}
    6977    protected method Disconnect {}
    7078
     79    protected method SendCmd {string}
    7180    protected method _send {string}
    72     protected method _send_dataobjs {}
    73     protected method ReceiveImage {option size}
    74     protected method ReceiveFile {option size}
    75     private method ReceiveLegend {tf vmin vmax size}
    76     protected method _receive_echo {channel {data ""}}
    77 
    78     protected method _rebuild {}
    79     protected method _currentVolumeIds {{what -all}}
    80     protected method _zoom {option}
    81     protected method _pan {option x y}
    82     protected method _rotate {option x y}
    83     protected method _slice {option args}
    84     protected method _slicertip {axis}
    85 
    86     protected method _flow {option args}
    87     protected method _play {}
    88     protected method _pause {}
    89 
    90     protected method _state {comp}
    91     protected method _fixSettings {what {value ""}}
    92     protected method _getTransfuncData {dataobj comp}
    93 
     81    protected method SendDataObjs {}
     82    protected method SendTransferFunctions {}
     83
     84    protected method ReceiveImage { args }
     85    protected method ReceiveLegend { ivol vmin vmax size }
     86    protected method ReceiveData { args }
     87
     88    protected method Rebuild {}
     89    protected method CurrentVolumeIds {{what -all}}
     90    protected method Zoom {option}
     91    protected method Pan {option x y}
     92    protected method Rotate {option x y}
     93    protected method Slice {option args}
     94    protected method SlicerTip {axis}
     95
     96    protected method Flow {option args}
     97    protected method Play {}
     98    protected method Pause {}
     99    public method flow {option}
     100    public method record {option}
     101
     102    protected method State {comp}
     103    protected method FixSettings {what {value ""}}
     104    protected method FixLegend {}
     105
     106    # The following methods are only used by this class.
     107    private method NameTransferFunction { ivol }
     108    private method ComputeTransferFunction { tf }
     109    private method AddIsoMarker { x y }
     110    private method ParseMarkersOption { tf ivol markers }
     111    private method ParseLevelsOption { tf ivol levels }
     112    private method BuildCutplanesDrawer {}
     113    private method BuildSettingsDrawer {}
     114    private method BuildCameraDrawer {}
     115    private method PanCamera {}
    94116
    95117    private variable outbuf_       ;# buffer for outgoing commands
    96118
    97119    private variable dlist_ ""     ;# list of data objects
    98     private variable obj2style_    ;# maps dataobj => style settings
     120    private variable all_data_objs_
     121    private variable id2style_     ;# maps id => style settings
    99122    private variable obj2ovride_   ;# maps dataobj => style override
    100     private variable obj2id_       ;# maps dataobj => heightmap ID in server
    101     private variable id2obj_       ;# maps heightmap ID => dataobj in server
     123    private variable obj2id_       ;# maps dataobj => volume ID in server
     124    private variable id2obj_       ;# maps dataobj => volume ID in server
    102125    private variable sendobjs_ ""  ;# list of data objs to send to server
    103     private variable receiveIds_   ;# list of data responses from the server
    104     private variable click_        ;# info used for _rotate operations
     126    private variable receiveIds_   ;# list of data objs to send to server
     127    private variable obj2styles_   ;# maps id => style settings
     128    private variable style2ids_    ;# maps id => style settings
     129
     130    private variable click_        ;# info used for Rotate operations
    105131    private variable limits_       ;# autoscale min/max for all axes
    106132    private variable view_         ;# view params for 3D view
    107 
    108     private common settings_       ;# Array used for checkbuttons and radiobuttons
     133    private variable isomarkers_    ;# array of isosurface level values 0..1
     134    private common   settings_
    109135    private variable activeTf_ ""  ;# The currently active transfer function.
    110 
    111     common _downloadPopup          ;# download options from popup
    112 
    113     private variable _afterId ""   ;# current "after" event for play op
    114     private common _play           ;# options for "play" operation
    115     set _play(speed) 10
     136    private variable flow_
     137    # This
     138    # indicates which isomarkers and transfer
     139    # function to use when changing markers,
     140    # opacity, or thickness.
     141    common downloadPopup_          ;# download options from popup
     142
     143    private variable drawer_
     144    private common hardcopy_
    116145}
    117146
     
    124153# CONSTRUCTOR
    125154# ----------------------------------------------------------------------
    126 itcl::body Rappture::FlowvisViewer::constructor {hostlist args} {
     155itcl::body Rappture::FlowvisViewer::constructor { hostlist args } {
     156
     157    # Draw legend event
     158    $_dispatcher register !legend
     159    $_dispatcher dispatch $this !legend "[itcl::code $this FixLegend]; list"
    127160    # Send dataobjs event
    128161    $_dispatcher register !send_dataobjs
    129162    $_dispatcher dispatch $this !send_dataobjs \
    130         "[itcl::code $this _send_dataobjs]; list"
     163        "[itcl::code $this SendDataObjs]; list"
     164    # Send transfer functions event
     165    $_dispatcher register !send_transfunc
     166    $_dispatcher dispatch $this !send_transfunc \
     167        "[itcl::code $this SendTransferFunctions]; list"
    131168    # Rebuild event
    132169    $_dispatcher register !rebuild
    133     $_dispatcher dispatch $this !rebuild "[itcl::code $this _rebuild]; list"
    134 
    135     array set _downloadPopup {
    136         format jpg
    137     }
    138 
     170    $_dispatcher dispatch $this !rebuild "[itcl::code $this Rebuild]; list"
     171
     172    $_dispatcher register !play
     173    $_dispatcher dispatch $this !play "[itcl::code $this flow next]; list"
     174   
    139175    set outbuf_ ""
    140 
     176    set flow_(state) "stopped"
     177    array set downloadPopup_ {
     178        format jpg
     179    }
     180    array set play_ {
     181    }
    141182    #
    142183    # Populate parser with commands handle incoming requests
    143184    #
    144185    $_parser alias image [itcl::code $this ReceiveImage]
    145     $_parser alias file [itcl::code $this ReceiveFile]
     186    $_parser alias legend [itcl::code $this ReceiveLegend]
     187    $_parser alias data [itcl::code $this ReceiveData]
    146188
    147189    # Initialize the view to some default parameters.
     
    151193        psi     0
    152194        zoom    1.0
    153         dx      0
    154         dy      0
     195        pan-x   0
     196        pan-y   0
    155197    }
    156198    set obj2id_(count) 0
    157 
    158     itk_component add zoom {
    159         frame $itk_component(controls).zoom
     199    set id2obj_(count) 0
     200    set limits_(vmin) 0.0
     201    set limits_(vmax) 1.0
     202    set settings_($this-theta) $view_(theta)
     203    set settings_($this-phi)   $view_(phi)
     204    set settings_($this-psi)   $view_(psi)
     205    set settings_($this-pan-x) $view_(pan-x)
     206    set settings_($this-pan-y) $view_(pan-y)
     207    set settings_($this-zoom)  $view_(zoom)
     208    set settings_($this-speed) 10
     209
     210    itk_component add reset {
     211        button $itk_component(controls).reset \
     212            -borderwidth 1 -padx 1 -pady 1 \
     213            -image [Rappture::icon reset-view] \
     214            -command [itcl::code $this Zoom reset]
    160215    } {
    161         usual
    162         rename -background -controlbackground controlBackground Background
    163     }
    164     pack $itk_component(zoom) -side top
    165 
    166     itk_component add reset {
    167         button $itk_component(zoom).reset \
     216        usual
     217        ignore -borderwidth
     218        rename -highlightbackground -controlbackground controlBackground Background
     219    }
     220    pack $itk_component(reset) -side top -padx 2 -pady 1
     221    Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level"
     222
     223    itk_component add zoomin {
     224        button $itk_component(controls).zin \
     225            -borderwidth 1 -padx 1 -pady 1 \
     226            -image [Rappture::icon zoom-in] \
     227            -command [itcl::code $this Zoom in]
     228    } {
     229        usual
     230        ignore -borderwidth
     231        rename -highlightbackground -controlbackground controlBackground Background
     232    }
     233    pack $itk_component(zoomin) -side top -padx 1 -pady 1
     234    Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
     235
     236    itk_component add zoomout {
     237        button $itk_component(controls).zout \
     238            -borderwidth 1 -padx 1 -pady 1 \
     239            -image [Rappture::icon zoom-out] \
     240            -command [itcl::code $this Zoom out]
     241    } {
     242        usual
     243        ignore -borderwidth
     244        rename -highlightbackground -controlbackground controlBackground Background
     245    }
     246    pack $itk_component(zoomout) -side top -padx 2 -pady 1
     247    Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
     248
     249    itk_component add settingsButton {
     250        label $itk_component(controls).settingsbutton \
    168251            -borderwidth 1 -padx 1 -pady 1 \
    169             -image [Rappture::icon reset-view] \
    170             -command [itcl::code $this _zoom reset]
     252            -relief "raised" -image [Rappture::icon wrench]
    171253    } {
    172254        usual
    173255        ignore -borderwidth
    174         rename -highlightbackground -controlbackground controlBackground Background
    175     }
    176     pack $itk_component(reset) -side left -padx {4 1} -pady 2
    177     Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level"
    178 
    179     itk_component add zoomin {
    180         button $itk_component(zoom).zin \
     256        rename -highlightbackground -controlbackground controlBackground \
     257            Background
     258    }
     259    pack $itk_component(settingsButton) -padx 2 -pady 1 \
     260        -ipadx 1 -ipady 1
     261    Rappture::Tooltip::for $itk_component(settingsButton) \
     262        "Configure settings"
     263    bind $itk_component(settingsButton) <ButtonPress> \
     264        [itcl::code $this drawer toggle settings]
     265    pack $itk_component(settingsButton) -side bottom \
     266        -padx 2 -pady 2 -anchor e
     267
     268    BuildSettingsDrawer
     269
     270    itk_component add cutplanesButton {
     271        label $itk_component(controls).cutplanesbutton \
    181272            -borderwidth 1 -padx 1 -pady 1 \
    182             -image [Rappture::icon zoom-in] \
    183             -command [itcl::code $this _zoom in]
     273            -relief "raised" -image [Rappture::icon cutbutton]
    184274    } {
    185275        usual
    186276        ignore -borderwidth
    187         rename -highlightbackground -controlbackground controlBackground Background
    188     }
    189     pack $itk_component(zoomin) -side left -padx 1 -pady 2
    190     Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
    191 
    192     itk_component add zoomout {
    193         button $itk_component(zoom).zout \
     277        rename -highlightbackground -controlbackground controlBackground \
     278            Background
     279    }
     280    Rappture::Tooltip::for $itk_component(cutplanesButton) \
     281        "Set cutplanes"
     282    bind $itk_component(cutplanesButton) <ButtonPress> \
     283        [itcl::code $this drawer toggle cutplanes]
     284    pack $itk_component(cutplanesButton) -side bottom \
     285        -padx 2 -pady { 0 2 } -ipadx 1 -ipady 1
     286
     287    BuildCutplanesDrawer
     288
     289    itk_component add cameraButton {
     290        label $itk_component(controls).camerabutton \
    194291            -borderwidth 1 -padx 1 -pady 1 \
    195             -image [Rappture::icon zoom-out] \
    196             -command [itcl::code $this _zoom out]
     292            -relief "raised" -image [Rappture::icon camera]
    197293    } {
    198294        usual
    199295        ignore -borderwidth
    200         rename -highlightbackground -controlbackground controlBackground Background
    201     }
    202     pack $itk_component(zoomout) -side left -padx {1 4} -pady 2
    203     Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
    204 
    205     #
    206     # Create slicer controls...
    207     #
    208     itk_component add slicers {
    209         frame $itk_component(controls).slicers
    210     } {
    211         usual
    212         rename -background -controlbackground controlBackground Background
    213     }
    214     pack $itk_component(slicers) -side bottom -padx 4 -pady 2
    215     grid rowconfigure $itk_component(slicers) 1 -weight 1
    216     #
    217     # X-value slicer...
    218     #
    219     itk_component add xslice {
    220         label $itk_component(slicers).xslice \
    221             -borderwidth 1 -relief raised -padx 1 -pady 1 \
    222             -image [Rappture::icon x-cutplane]
    223     } {
    224         usual
    225         ignore -borderwidth
    226         rename -highlightbackground -controlbackground controlBackground Background
    227     }
    228     bind $itk_component(xslice) <ButtonPress> \
    229         [itcl::code $this _slice axis x toggle]
    230     Rappture::Tooltip::for $itk_component(xslice) \
    231         "Toggle the X cut plane on/off"
    232     grid $itk_component(xslice) -row 1 -column 0 -sticky ew -padx 1
    233 
    234     itk_component add xslicer {
    235         ::scale $itk_component(slicers).xval -from 100 -to 0 \
    236             -width 10 -orient vertical -showvalue off \
    237             -borderwidth 1 -highlightthickness 0 \
    238             -command [itcl::code $this _slice move x]
    239     } {
    240         usual
    241         ignore -borderwidth
    242         ignore -highlightthickness
    243         rename -highlightbackground -controlbackground controlBackground Background
    244         rename -troughcolor -controldarkbackground controlDarkBackground Background
    245     }
    246     $itk_component(xslicer) set 50
    247     $itk_component(xslicer) configure -state disabled
    248     grid $itk_component(xslicer) -row 2 -column 0 -padx 1
    249     Rappture::Tooltip::for $itk_component(xslicer) \
    250         "@[itcl::code $this _slicertip x]"
    251 
    252     #
    253     # Y-value slicer...
    254     #
    255     itk_component add yslice {
    256         label $itk_component(slicers).yslice \
    257             -borderwidth 1 -relief raised -padx 1 -pady 1 \
    258             -image [Rappture::icon y-cutplane]
    259     } {
    260         usual
    261         ignore -borderwidth
    262         rename -highlightbackground -controlbackground controlBackground Background
    263     }
    264     bind $itk_component(yslice) <ButtonPress> \
    265         [itcl::code $this _slice axis y toggle]
    266     Rappture::Tooltip::for $itk_component(yslice) \
    267         "Toggle the Y cut plane on/off"
    268     grid $itk_component(yslice) -row 1 -column 1 -sticky ew -padx 1
    269 
    270     itk_component add yslicer {
    271         ::scale $itk_component(slicers).yval -from 100 -to 0 \
    272             -width 10 -orient vertical -showvalue off \
    273             -borderwidth 1 -highlightthickness 0 \
    274             -command [itcl::code $this _slice move y]
    275     } {
    276         usual
    277         ignore -borderwidth
    278         ignore -highlightthickness
    279         rename -highlightbackground -controlbackground controlBackground Background
    280         rename -troughcolor -controldarkbackground controlDarkBackground Background
    281     }
    282     $itk_component(yslicer) set 50
    283     $itk_component(yslicer) configure -state disabled
    284     grid $itk_component(yslicer) -row 2 -column 1 -padx 1
    285     Rappture::Tooltip::for $itk_component(yslicer) \
    286         "@[itcl::code $this _slicertip y]"
    287 
    288     #
    289     # Z-value slicer...
    290     #
    291     itk_component add zslice {
    292         label $itk_component(slicers).zslice \
    293             -borderwidth 1 -relief raised -padx 1 -pady 1 \
    294             -image [Rappture::icon z-cutplane]
    295     } {
    296         usual
    297         ignore -borderwidth
    298         rename -highlightbackground -controlbackground controlBackground Background
    299     }
    300     grid $itk_component(zslice) -row 1 -column 2 -sticky ew -padx 1
    301     bind $itk_component(zslice) <ButtonPress> \
    302         [itcl::code $this _slice axis z toggle]
    303     Rappture::Tooltip::for $itk_component(zslice) \
    304         "Toggle the Z cut plane on/off"
    305 
    306     itk_component add zslicer {
    307         ::scale $itk_component(slicers).zval -from 100 -to 0 \
    308             -width 10 -orient vertical -showvalue off \
    309             -borderwidth 1 -highlightthickness 0 \
    310             -command [itcl::code $this _slice move z]
    311     } {
    312         usual
    313         ignore -borderwidth
    314         ignore -highlightthickness
    315         rename -highlightbackground -controlbackground controlBackground Background
    316         rename -troughcolor -controldarkbackground controlDarkBackground Background
    317     }
    318     $itk_component(zslicer) set 50
    319     $itk_component(zslicer) configure -state disabled
    320     grid $itk_component(zslicer) -row 2 -column 2 -padx 1
    321     Rappture::Tooltip::for $itk_component(zslicer) \
    322         "@[itcl::code $this _slicertip z]"
     296        rename -highlightbackground -controlbackground controlBackground \
     297            Background
     298    }
     299    Rappture::Tooltip::for $itk_component(cameraButton) \
     300        "Camera settings"
     301    bind $itk_component(cameraButton) <ButtonPress> \
     302        [itcl::code $this drawer toggle camera]
     303    pack $itk_component(cameraButton) -side bottom \
     304        -padx 2 -pady 1 -ipadx 1 -ipady 1
     305
     306    BuildCameraDrawer
    323307
    324308    #
     
    326310    #
    327311    itk_component add volume {
    328         label $itk_component(slicers).volume \
    329             -borderwidth 1 -relief sunken -padx 1 -pady 1 \
    330             -text "Volume"
     312        label $itk_component(controls).volume \
     313            -borderwidth 1 -relief sunken -padx 1 -pady 1 \
     314            -text "Volume" \
     315            -image [Rappture::icon playback-record]
     316    } {
     317        usual
     318        ignore -borderwidth
     319        rename -highlightbackground -controlbackground controlBackground Background
     320    }
     321    bind $itk_component(volume) <ButtonPress> \
     322        [itcl::code $this Slice volume toggle]
     323    Rappture::Tooltip::for $itk_component(volume) \
     324        "Toggle the volume cloud on/off"
     325    pack $itk_component(volume) -padx 1 -pady 1
     326
     327    # Legend
     328
     329    set _image(legend) [image create photo]
     330    itk_component add legend {
     331        canvas $itk_component(area).legend -height 50 -highlightthickness 0
     332    } {
     333        usual
     334        ignore -highlightthickness
     335        rename -background -plotbackground plotBackground Background
     336    }
     337    pack $itk_component(legend) -side bottom -fill x
     338    bind $itk_component(legend) <Configure> \
     339        [list $_dispatcher event -idle !legend]
     340
     341   
     342    # Create flow controls...
     343
     344    itk_component add flowctrl {
     345        frame $itk_interior.flowctrl
    331346    } {
    332347        usual
    333         ignore -borderwidth
    334         rename -highlightbackground -controlbackground controlBackground Background
    335     }
    336     bind $itk_component(volume) <ButtonPress> \
    337         [itcl::code $this _slice volume toggle]
    338     Rappture::Tooltip::for $itk_component(volume) \
    339         "Toggle the volume cloud on/off"
    340     grid $itk_component(volume) -row 0 -column 0 -columnspan 3 \
    341         -sticky ew -padx 1 -pady 2
    342 
    343     #
    344     # Settings panel...
    345     #
    346     itk_component add settings {
    347         button $itk_component(controls).settings -text "Settings..." \
    348             -borderwidth 1 -relief flat -overrelief raised \
    349             -padx 2 -pady 1 \
    350             -command [list $itk_component(controls).panel activate $itk_component(controls).settings left]
     348        rename -background -controlbackground controlBackground Background
     349    }
     350    pack $itk_component(flowctrl) -side top -padx 4 -pady 0 -fill x
     351
     352    # flow record button...
     353    itk_component add rewind {
     354        button $itk_component(flowctrl).reset \
     355            -borderwidth 1 -padx 1 -pady 1 \
     356            -image [Rappture::icon flow-rewind] \
     357            -command [itcl::code $this flow rewind]
    351358    } {
    352         usual
    353         ignore -borderwidth
    354         rename -background -controlbackground controlBackground Background
    355         rename -highlightbackground -controlbackground controlBackground Background
    356     }
    357     pack $itk_component(settings) -side top
    358 
    359     Rappture::Balloon $itk_component(controls).panel -title "Settings"
    360     set inner [$itk_component(controls).panel component inner]
    361     frame $inner.scales
    362     pack $inner.scales -side top -fill x
    363     grid columnconfigure $inner.scales 1 -weight 1
    364     set fg [option get $itk_component(hull) font Font]
    365     set bfg [option get $itk_component(hull) boldFont Font]
    366 
    367     label $inner.scales.diml -text "Dim" -font $fg
    368     grid $inner.scales.diml -row 0 -column 0 -sticky e
    369     ::scale $inner.scales.light -from 0 -to 100 -orient horizontal \
    370         -showvalue off -command [itcl::code $this _fixSettings light]
    371     grid $inner.scales.light -row 0 -column 1 -sticky ew
    372     label $inner.scales.brightl -text "Bright" -font $fg
    373     grid $inner.scales.brightl -row 0 -column 2 -sticky w
    374     $inner.scales.light set 20
    375 
    376     label $inner.scales.fogl -text "Fog" -font $fg
    377     grid $inner.scales.fogl -row 1 -column 0 -sticky e
    378     ::scale $inner.scales.transp -from 0 -to 100 -orient horizontal \
    379         -showvalue off -command [itcl::code $this _fixSettings transp]
    380     grid $inner.scales.transp -row 1 -column 1 -sticky ew
    381     label $inner.scales.plasticl -text "Plastic" -font $fg
    382     grid $inner.scales.plasticl -row 1 -column 2 -sticky w
    383     $inner.scales.transp set 20
    384 
    385     label $inner.scales.zerol -text "Clear" -font $fg
    386     grid $inner.scales.zerol -row 2 -column 0 -sticky e
    387     ::scale $inner.scales.opacity -from 0 -to 100 -orient horizontal \
    388         -showvalue off -command [itcl::code $this _fixSettings opacity]
    389     grid $inner.scales.opacity -row 2 -column 1 -sticky ew
    390     label $inner.scales.onel -text "Opaque" -font $fg
    391     grid $inner.scales.onel -row 2 -column 2 -sticky w
    392     $inner.scales.opacity set 100
    393 
    394     label $inner.scales.thinl -text "Thin" -font $fg
    395     grid $inner.scales.thinl -row 3 -column 0 -sticky e
    396     ::scale $inner.scales.thickness -from 0 -to 1000 -orient horizontal \
    397         -showvalue off -command [itcl::code $this _fixSettings thickness]
    398     grid $inner.scales.thickness -row 3 -column 1 -sticky ew
    399     label $inner.scales.thickl -text "Thick" -font $fg
    400     grid $inner.scales.thickl -row 3 -column 2 -sticky w
    401     $inner.scales.thickness set 350
    402 
    403     set ::Rappture::FlowvisViewer::settings_($this-isosurface) 0
    404     ::checkbutton $inner.scales.isosurface \
    405         -text "Isosurface shading" \
    406         -variable ::Rappture::FlowvisViewer::settings_($this-isosurface) \
    407         -command [itcl::code $this _fixSettings isosurface]
    408     grid $inner.scales.isosurface -row 4 -column 0 -columnspan 2 -sticky w
    409 
    410     set ::Rappture::FlowvisViewer::settings_($this-axes) 1
    411     ::checkbutton $inner.scales.axes \
    412         -text "Axes" \
    413         -variable ::Rappture::FlowvisViewer::settings_($this-axes) \
    414         -command [itcl::code $this _fixSettings axes]
    415     grid $inner.scales.axes -row 5 -column 0 -columnspan 2 -sticky w
    416 
    417     set ::Rappture::FlowvisViewer::settings_($this-grid) 0
    418     ::checkbutton $inner.scales.grid \
    419         -text "Grid" \
    420         -variable ::Rappture::FlowvisViewer::settings_($this-grid) \
    421         -command [itcl::code $this _fixSettings grid]
    422     grid $inner.scales.grid -row 6 -column 0 -columnspan 2 -sticky w
    423 
    424     set ::Rappture::FlowvisViewer::settings_($this-outline) 1
    425     ::checkbutton $inner.scales.outline \
    426         -text "Outline" \
    427         -variable ::Rappture::FlowvisViewer::settings_($this-outline) \
    428         -command [itcl::code $this _fixSettings outline]
    429     grid $inner.scales.outline -row 7 -column 0 -columnspan 2 -sticky w
    430 
    431     set ::Rappture::FlowvisViewer::settings_($this-particlevis) 1
    432     ::checkbutton $inner.scales.particlevis \
    433         -text "Particle Visible" \
    434         -variable ::Rappture::FlowvisViewer::settings_($this-particlevis) \
    435         -command [itcl::code $this _fixSettings particlevis]
    436     grid $inner.scales.particlevis -row 8 -column 0 -columnspan 2 -sticky w
    437 
    438     set ::Rappture::FlowvisViewer::settings_($this-lic) 1
    439     ::checkbutton $inner.scales.lic \
    440         -text "Lic" \
    441         -variable ::Rappture::FlowvisViewer::settings_($this-lic) \
    442         -command [itcl::code $this _fixSettings lic]
    443     grid $inner.scales.lic -row 9 -column 0 -columnspan 2 -sticky w
    444 
    445 # how do we know when to make something an itk component?
    446 
    447     label $inner.scales.framecntlabel -text "# Frames" -font $fg
    448     grid $inner.scales.framecntlabel -row 10 -column 0 -sticky e
    449     Rappture::Spinint $inner.scales.framecnt
    450     $inner.scales.framecnt value 100
    451     grid $inner.scales.framecnt -row 10 -column 1 -sticky w
    452 
    453     label $inner.scales.speedl -text "Flow Speed:" -font $bfg
    454     grid $inner.scales.speedl -row 11 -column 0 -sticky e
    455     frame $inner.scales.speed
    456     grid $inner.scales.speed -row 11 -column 1 -sticky ew
    457     label $inner.scales.speed.slowl -text "Slower" -font $fg
    458     pack $inner.scales.speed.slowl -side left
    459     ::scale $inner.scales.speed.value -from 100 -to 1 \
    460         -showvalue 0 -orient horizontal \
    461         -variable ::Rappture::FlowvisViewer::_play(speed)
    462     pack $inner.scales.speed.value -side left
    463     label $inner.scales.speed.fastl -text "Faster" -font $fg
    464     pack $inner.scales.speed.fastl -side left
    465 
    466     #
    467     # Create flow controls...
    468     #
    469     itk_component add flowctrl {
    470         frame $itk_component(controls).flowctrl
     359        usual
     360        ignore -borderwidth
     361        rename -highlightbackground -controlbackground controlBackground Background
     362    }
     363    Rappture::Tooltip::for $itk_component(rewind) \
     364        "Rewind the flow sequence to the beginning"
     365    pack $itk_component(rewind) -padx 1 -side left
     366
     367    # flow stop button...
     368    itk_component add stop {
     369        button $itk_component(flowctrl).stop \
     370            -borderwidth 1 -padx 1 -pady 1 \
     371            -image [Rappture::icon flow-stop] \
     372            -command [itcl::code $this flow stop]
    471373    } {
    472         usual
    473         rename -background -controlbackground controlBackground Background
    474     }
    475     pack $itk_component(flowctrl) -side top -padx 4 -pady 0
    476     grid rowconfigure $itk_component(flowctrl) 1 -weight 1
    477 
    478     #
    479     # flow record button...
    480     #
    481     itk_component add record {
    482         label $itk_component(flowctrl).record \
    483             -borderwidth 1 -relief raised -padx 1 -pady 1 \
    484             -image [Rappture::icon playback-record]
    485     } {
    486         usual
    487         ignore -borderwidth
    488         rename -highlightbackground -controlbackground controlBackground Background
    489     }
    490     bind $itk_component(record) <ButtonPress> \
    491         [itcl::code $this _flow movie record toggle]
    492     Rappture::Tooltip::for $itk_component(record) \
    493         "Record flow visualization"
    494     grid $itk_component(record) -row 1 -column 0 -padx 1
    495 
    496     #
    497     # flow stop button...
    498     #
    499     itk_component add stop {
    500         label $itk_component(flowctrl).stop \
    501             -borderwidth 1 -relief sunken -padx 1 -pady 1 \
    502             -image [Rappture::icon playback-stop]
    503     } {
    504         usual
    505         ignore -borderwidth
    506         rename -highlightbackground -controlbackground controlBackground Background
    507     }
    508     bind $itk_component(stop) <ButtonPress> \
    509         [itcl::code $this _flow movie stop toggle]
     374        usual
     375        ignore -borderwidth
     376        rename -highlightbackground -controlbackground controlBackground Background
     377    }
    510378    Rappture::Tooltip::for $itk_component(stop) \
    511         "Stop flow visualization"
    512     grid $itk_component(stop) -row 1 -column 1 -padx 1
     379        "Stop flow visualization"
     380    pack $itk_component(stop) -padx 1 -side left
    513381
    514382    #
     
    516384    #
    517385    itk_component add play {
    518         label $itk_component(flowctrl).play \
    519             -borderwidth 1 -relief raised -padx 1 -pady 1 \
    520             -image [Rappture::icon playback-start]
     386        button $itk_component(flowctrl).play \
     387            -borderwidth 1 -padx 1 -pady 1 \
     388            -image [Rappture::icon flow-play] \
     389            -command [itcl::code $this flow toggle]
    521390    } {
    522         usual
    523         ignore -borderwidth
    524         rename -highlightbackground -controlbackground controlBackground Background
    525     }
    526     bind $itk_component(play) <ButtonPress> \
    527         [itcl::code $this _flow movie play toggle]
     391        usual
     392        ignore -borderwidth
     393        rename -highlightbackground -controlbackground controlBackground Background
     394    }
     395    set fg [option get $itk_component(hull) font Font]
     396
    528397    Rappture::Tooltip::for $itk_component(play) \
    529         "Play/Pause flow visualization"
    530     grid $itk_component(play) -row 1 -column 2 -padx 1
     398        "Play/Pause flow visualization"
     399    pack $itk_component(play) -padx 1 -side left
     400
     401    # how do we know when to make something an itk component?
     402
     403    ::scale $itk_component(flowctrl).value -from 100 -to 1 \
     404        -showvalue 0 -orient horizontal -width 12 -length 150 \
     405        -variable [itcl::scope settings_(speed)]
     406    pack $itk_component(flowctrl).value -side right
     407
     408    itk_component add speedlabel {
     409        label $itk_component(flowctrl).speedl -text "Flow Rate:" -font $fg
     410    } {
     411        usual
     412        rename -background -controlbackground controlBackground Background
     413    }
     414    pack $itk_component(speedlabel)  -side right
     415
     416    Rappture::Spinint $itk_component(flowctrl).framecnt
     417    $itk_component(flowctrl).framecnt value 100
     418    pack $itk_component(flowctrl).framecnt  -side right
     419    label $itk_component(flowctrl).framecntlabel -text "# Frames" -font $fg
     420    pack $itk_component(flowctrl).framecntlabel  -side right
     421
    531422
    532423    # Bindings for rotation via mouse
    533424    bind $itk_component(3dview) <ButtonPress-1> \
    534         [itcl::code $this _rotate click %x %y]
     425        [itcl::code $this Rotate click %x %y]
    535426    bind $itk_component(3dview) <B1-Motion> \
    536         [itcl::code $this _rotate drag %x %y]
     427        [itcl::code $this Rotate drag %x %y]
    537428    bind $itk_component(3dview) <ButtonRelease-1> \
    538         [itcl::code $this _rotate release %x %y]
     429        [itcl::code $this Rotate release %x %y]
    539430    bind $itk_component(3dview) <Configure> \
    540         [itcl::code $this _send "screen %w %h"]
     431        [itcl::code $this SendCmd "screen %w %h"]
    541432
    542433    # Bindings for panning via mouse
    543434    bind $itk_component(3dview) <ButtonPress-2> \
    544         [itcl::code $this _pan click %x %y]
     435        [itcl::code $this Pan click %x %y]
    545436    bind $itk_component(3dview) <B2-Motion> \
    546         [itcl::code $this _pan drag %x %y]
     437        [itcl::code $this Pan drag %x %y]
    547438    bind $itk_component(3dview) <ButtonRelease-2> \
    548         [itcl::code $this _pan release %x %y]
     439        [itcl::code $this Pan release %x %y]
    549440
    550441    # Bindings for panning via keyboard
    551442    bind $itk_component(3dview) <KeyPress-Left> \
    552         [itcl::code $this _pan set -10 0]
     443        [itcl::code $this Pan set -10 0]
    553444    bind $itk_component(3dview) <KeyPress-Right> \
    554         [itcl::code $this _pan set 10 0]
     445        [itcl::code $this Pan set 10 0]
    555446    bind $itk_component(3dview) <KeyPress-Up> \
    556         [itcl::code $this _pan set 0 -10]
     447        [itcl::code $this Pan set 0 -10]
    557448    bind $itk_component(3dview) <KeyPress-Down> \
    558         [itcl::code $this _pan set 0 10]
     449        [itcl::code $this Pan set 0 10]
    559450    bind $itk_component(3dview) <Shift-KeyPress-Left> \
    560         [itcl::code $this _pan set -2 0]
     451        [itcl::code $this Pan set -2 0]
    561452    bind $itk_component(3dview) <Shift-KeyPress-Right> \
    562         [itcl::code $this _pan set 2 0]
     453        [itcl::code $this Pan set 2 0]
    563454    bind $itk_component(3dview) <Shift-KeyPress-Up> \
    564         [itcl::code $this _pan set 0 -2]
     455        [itcl::code $this Pan set 0 -2]
    565456    bind $itk_component(3dview) <Shift-KeyPress-Down> \
    566         [itcl::code $this _pan set 0 2]
     457        [itcl::code $this Pan set 0 2]
    567458
    568459    # Bindings for zoom via keyboard
    569460    bind $itk_component(3dview) <KeyPress-Prior> \
    570         [itcl::code $this _zoom out]
     461        [itcl::code $this Zoom out]
    571462    bind $itk_component(3dview) <KeyPress-Next> \
    572         [itcl::code $this _zoom in]
     463        [itcl::code $this Zoom in]
    573464
    574465    bind $itk_component(3dview) <Enter> "focus $itk_component(3dview)"
    575466
    576467    if {[string equal "x11" [tk windowingsystem]]} {
    577         # Bindings for zoom via mouse
    578         bind $itk_component(3dview) <4> [itcl::code $this _zoom out]
    579         bind $itk_component(3dview) <5> [itcl::code $this _zoom in]
     468        # Bindings for zoom via mouse
     469        bind $itk_component(3dview) <4> [itcl::code $this Zoom out]
     470        bind $itk_component(3dview) <5> [itcl::code $this Zoom in]
    580471    }
    581472
     
    594485    $_dispatcher cancel !rebuild
    595486    $_dispatcher cancel !send_dataobjs
     487    $_dispatcher cancel !send_transfunc
    596488    image delete $_image(plot)
     489    image delete $_image(legend)
    597490    image delete $_image(download)
     491    array unset settings_ $this-*
    598492}
    599493
     
    607501itcl::body Rappture::FlowvisViewer::add {dataobj {settings ""}} {
    608502    array set params {
    609         -color auto
    610         -width 1
    611         -linestyle solid
    612         -brightness 0
    613         -raise 0
    614         -description ""
    615         -param ""
     503        -color auto
     504        -width 1
     505        -linestyle solid
     506        -brightness 0
     507        -raise 0
     508        -description ""
     509        -param ""
    616510    }
    617511    foreach {opt val} $settings {
    618         if {![info exists params($opt)]} {
    619             error "bad setting \"$opt\": should be [join [lsort [array names params]] {, }]"
    620         }
    621         set params($opt) $val
     512        if {![info exists params($opt)]} {
     513            error "bad setting \"$opt\": should be [join [lsort [array names params]] {, }]"
     514        }
     515        set params($opt) $val
    622516    }
    623517    if {$params(-color) == "auto" || $params(-color) == "autoreset"} {
    624         # can't handle -autocolors yet
    625         set params(-color) black
     518        # can't handle -autocolors yet
     519        set params(-color) black
    626520    }
    627521
    628522    set pos [lsearch -exact $dataobj $dlist_]
    629523    if {$pos < 0} {
    630         lappend dlist_ $dataobj
    631         set obj2ovride_($dataobj-color) $params(-color)
    632         set obj2ovride_($dataobj-width) $params(-width)
    633         set obj2ovride_($dataobj-raise) $params(-raise)
    634         $_dispatcher event -idle !rebuild
     524        lappend dlist_ $dataobj
     525        set all_data_objs_($dataobj) 1
     526        set obj2ovride_($dataobj-color) $params(-color)
     527        set obj2ovride_($dataobj-width) $params(-width)
     528        set obj2ovride_($dataobj-raise) $params(-raise)
     529        $_dispatcher event -idle !rebuild
    635530    }
    636531}
     
    646541itcl::body Rappture::FlowvisViewer::get {args} {
    647542    if {[llength $args] == 0} {
    648         set args "-objects"
     543        set args "-objects"
    649544    }
    650545
     
    652547    switch -- $op {
    653548      -objects {
    654         # put the dataobj list in order according to -raise options
    655         set dlist $dlist_
    656         foreach obj $dlist {
    657             if { [info exists obj2ovride_($obj-raise)] &&
    658                  $obj2ovride_($obj-raise)} {
    659                 set i [lsearch -exact $dlist $obj]
    660                 if {$i >= 0} {
    661                     set dlist [lreplace $dlist $i $i]
    662                     lappend dlist $obj
    663                 }
    664             }
    665         }
    666         return $dlist
     549        # put the dataobj list in order according to -raise options
     550        set dlist $dlist_
     551        foreach obj $dlist {
     552            if {[info exists obj2ovride_($obj-raise)] && $obj2ovride_($obj-raise)} {
     553                set i [lsearch -exact $dlist $obj]
     554                if {$i >= 0} {
     555                    set dlist [lreplace $dlist $i $i]
     556                    lappend dlist $obj
     557                }
     558            }
     559        }
     560        return $dlist
    667561      }
    668562      -image {
    669         if {[llength $args] != 2} {
    670             error "wrong # args: should be \"get -image 3dview|legend\""
    671         }
    672         switch -- [lindex $args end] {
    673             3dview {
    674                 return $_image(plot)
    675             }
    676             default {
    677                 error "bad image name \"[lindex $args end]\": should be 3dview or legend"
    678             }
    679         }
     563        if {[llength $args] != 2} {
     564            error "wrong # args: should be \"get -image 3dview|legend\""
     565        }
     566        switch -- [lindex $args end] {
     567            3dview {
     568                return $_image(plot)
     569            }
     570            legend {
     571                return $_image(legend)
     572            }
     573            default {
     574                error "bad image name \"[lindex $args end]\": should be 3dview or legend"
     575            }
     576        }
    680577      }
    681578      default {
    682         error "bad option \"$op\": should be -objects or -image"
     579        error "bad option \"$op\": should be -objects or -image"
    683580      }
    684581    }
     
    688585# USAGE: delete ?<dataobj1> <dataobj2> ...?
    689586#
    690 # Clients use this to delete a dataobj from the plot.  If no dataobjs
    691 # are specified, then all dataobjs are deleted.
     587#       Clients use this to delete a dataobj from the plot.  If no dataobjs
     588#       are specified, then all dataobjs are deleted.  No data objects are
     589#       deleted.  They are only removed from the display list.
     590#
    692591# ----------------------------------------------------------------------
    693592itcl::body Rappture::FlowvisViewer::delete {args} {
    694593    if {[llength $args] == 0} {
    695         set args $dlist_
    696     }
    697 
    698     # delete all specified dataobjs
     594        set args $dlist_
     595    }
     596    # Delete all specified dataobjs
    699597    set changed 0
    700598    foreach dataobj $args {
    701         set pos [lsearch -exact $dlist_ $dataobj]
    702         if {$pos >= 0} {
    703             set dlist_ [lreplace $dlist_ $pos $pos]
    704             foreach key [array names obj2ovride_ $dataobj-*] {
    705                 unset obj2ovride_($key)
    706             }
    707             set changed 1
    708         }
    709     }
    710 
    711     # if anything changed, then rebuild the plot
     599        set pos [lsearch -exact $dlist_ $dataobj]
     600        if { $pos >= 0 } {
     601            set dlist_ [lreplace $dlist_ $pos $pos]
     602            foreach key [array names obj2ovride_ $dataobj-*] {
     603                unset obj2ovride_($key)
     604            }
     605            set changed 1
     606        }
     607    }
     608    # If anything changed, then rebuild the plot
    712609    if {$changed} {
    713         $_dispatcher event -idle !rebuild
     610        $_dispatcher event -idle !rebuild
    714611    }
    715612}
     
    726623itcl::body Rappture::FlowvisViewer::scale {args} {
    727624    foreach val {xmin xmax ymin ymax zmin zmax vmin vmax} {
    728         set limits_($val) ""
     625        set limits_($val) ""
    729626    }
    730627    foreach obj $args {
    731         foreach axis {x y z v} {
    732             foreach {min max} [$obj limits $axis] break
    733             if {"" != $min && "" != $max} {
    734                 if {"" == $limits_(${axis}min)} {
    735                     set limits_(${axis}min) $min
    736                     set limits_(${axis}max) $max
    737                 } else {
    738                     if {$min < $limits_(${axis}min)} {
    739                         set limits_(${axis}min) $min
    740                     }
    741                     if {$max > $limits_(${axis}max)} {
    742                         set limits_(${axis}max) $max
    743                     }
    744                 }
    745             }
    746         }
     628        foreach axis {x y z v} {
     629
     630            foreach { min max } [$obj limits $axis] break
     631
     632            if {"" != $min && "" != $max} {
     633                if {"" == $limits_(${axis}min)} {
     634                    set limits_(${axis}min) $min
     635                    set limits_(${axis}max) $max
     636                } else {
     637                    if {$min < $limits_(${axis}min)} {
     638                        set limits_(${axis}min) $min
     639                    }
     640                    if {$max > $limits_(${axis}max)} {
     641                        set limits_(${axis}max) $max
     642                    }
     643                }
     644            }
     645        }
    747646    }
    748647}
     
    760659itcl::body Rappture::FlowvisViewer::download {option args} {
    761660    switch $option {
    762         coming {
    763             if {[catch {
    764                 blt::winop snap $itk_component(area) $_image(download)
    765             }]} {
    766                 $_image(download) configure -width 1 -height 1
    767                 $_image(download) put #000000
    768             }
    769         }
    770         controls {
    771             # no controls for this download yet
    772             return ""
    773         }
    774         now {
    775             switch -- $_downloadPopup(format) {
    776                 jpg {
    777                     # Get the image data (as base64) and decode it back to
    778                     # binary.  This is better than writing to temporary files.
    779                     # When we switch to the BLT picture image it won't be
    780                     # necessary to decode the image data.
    781                     set bytes [$_image(download) data \
    782                                   -format "jpeg -quality 100"]
    783                     set bytes [Rappture::encoding::decode -as b64 $bytes]
    784                     return [list .jpg $bytes]
    785                 }
    786             }
    787         }
    788         default {
    789             error "bad option \"$option\": should be coming, controls, now"
    790         }
     661        coming {
     662            if {[catch {blt::winop snap $itk_component(area) $_image(download)}]} {
     663                $_image(download) configure -width 1 -height 1
     664                $_image(download) put #000000
     665            }
     666        }
     667        controls {
     668            # no controls for this download yet
     669            return ""
     670        }
     671        now {
     672            # Doing an image base64 encode/decode has to be better than
     673            # writing the image to a file and reading it back in.
     674            set data [$_image(plot) data -format jpeg]
     675            set data [Rappture::encoding::decode -as b64 $data]
     676            return [list .jpg $data]
     677        }
     678        default {
     679            error "bad option \"$option\": should be coming, controls, now"
     680        }
    791681    }
    792682}
     
    800690# ----------------------------------------------------------------------
    801691itcl::body Rappture::FlowvisViewer::Connect {} {
    802     Disconnect
    803692    set _hosts [GetServerList "nanovis"]
    804693    if { "" == $_hosts } {
    805         return 0
     694        return 0
    806695    }
    807696    set result [VisViewer::Connect $_hosts]
     697    if { $result } {
     698        set w [winfo width $itk_component(3dview)]
     699        set h [winfo height $itk_component(3dview)]
     700        SendCmd "screen $w $h"
     701    }
    808702    return $result
    809703}
     
    818712}
    819713
    820 # ----------------------------------------------------------------------
    821 # USAGE: Disconnect
    822 #
    823 # Clients use this method to disconnect from the current rendering
    824 # server.
    825 # ----------------------------------------------------------------------
     714#
     715# Disconnect --
     716#
     717#       Clients use this method to disconnect from the current rendering
     718#       server.
     719#
    826720itcl::body Rappture::FlowvisViewer::Disconnect {} {
    827721    VisViewer::Disconnect
    828722
     723    # disconnected -- no more data sitting on server
    829724    set outbuf_ ""
    830     # disconnected -- no more data sitting on server
    831725    catch {unset obj2id_}
    832726    array unset id2obj_
    833727    set obj2id_(count) 0
    834     set id2obj_(cound) 0
     728    set id2obj_(count) 0
    835729    set sendobjs_ ""
    836730}
    837731
    838 #
    839 # _send
     732itcl::body Rappture::FlowvisViewer::_send {string} {
     733    SendCmd $string
     734}
     735#
     736# SendCmd
    840737#
    841738#       Send commands off to the rendering server.  If we're currently
     
    843740#       sent later.
    844741#
    845 itcl::body Rappture::FlowvisViewer::_send {string} {
     742itcl::body Rappture::FlowvisViewer::SendCmd {string} {
    846743    if {[llength $sendobjs_] > 0} {
    847         append outbuf_ $string "\n"
     744        append outbuf_ $string "\n"
    848745    } else {
    849         if {[SendBytes $string]} {
    850             foreach line [split $string \n] {
    851                 SendEcho >>line $line
    852             }
    853         }
    854     }
    855 }
    856 
    857 # ----------------------------------------------------------------------
    858 # USAGE: _send_dataobjs
     746        foreach line [split $string \n] {
     747            SendEcho >>line $line
     748        }
     749        SendBytes $string
     750    }
     751}
     752
     753# ----------------------------------------------------------------------
     754# USAGE: SendDataObjs
    859755#
    860756# Used internally to send a series of volume objects off to the
     
    862758# between so the interface doesn't lock up.
    863759# ----------------------------------------------------------------------
    864 itcl::body Rappture::FlowvisViewer::_send_dataobjs {} {
     760itcl::body Rappture::FlowvisViewer::SendDataObjs {} {
    865761    blt::busy hold $itk_component(hull); update idletasks
    866 
    867     # Reset the overall limits
    868     if { $sendobjs_ != "" } {
    869         set limits_(vmin) ""
    870         set limits_(vmax) ""
    871     }
    872762    foreach dataobj $sendobjs_ {
    873         foreach comp [$dataobj components] {
    874             set data [$dataobj values $comp]
    875 
    876             # tell the engine to expect some data
    877             set nbytes [string length $data]
    878             if { ![SendBytes "flow data follows $nbytes"] } {
    879                 return
    880             }
    881             if { ![SendBytes $data] } {
    882                 return
    883             }
    884             set id $obj2id_(count)
    885             incr obj2id_(count)
    886             set id2obj_($id) [list $dataobj $comp]
    887             set obj2id_($dataobj-$comp) $id
    888             set receiveIds_($id) 1
    889         }
     763        foreach comp [$dataobj components] {
     764            # Send the data as one huge base64-encoded mess -- yuck!
     765            set data [$dataobj values $comp]
     766            set nbytes [string length $data]
     767            if { ![SendBytes "flow data follows $nbytes"] } {
     768                return
     769            }
     770            if { ![SendBytes $data] } {
     771                return
     772            }
     773            set ivol $obj2id_(count)
     774            incr obj2id_(count)
     775
     776            set id2obj_($ivol) [list $dataobj $comp]
     777            set obj2id_($dataobj-$comp) $ivol
     778            NameTransferFunction $ivol
     779            set receiveIds_($ivol) 1
     780        }
    890781    }
    891782    set sendobjs_ ""
     
    894785    # activate the proper volume
    895786    set first [lindex [get] 0]
    896     if {"" != $first} {
    897         set axis [$first hints updir]
    898         if {"" != $axis} {
    899             _send "up $axis"
    900         }
    901     }
    902 
    903 # FIXME: does vectorid command turn off other vectors?
     787    if { "" != $first } {
     788        set axis [$first hints updir]
     789        if {"" != $axis} {
     790            SendCmd "up $axis"
     791        }
     792        # The active transfer function is by default the first component of
     793        # the first data object.  This assumes that the data is always
     794        # successfully transferred.
     795        set comp [lindex [$first components] 0]
     796        set activeTf_ $id2style_($obj2id_($first-$comp))
     797    }
    904798    foreach key [array names obj2id_ *-*] {
    905         _send "flow vectorid $obj2id_($key)"
     799        set state [string match $first-* $key]
     800        set ivol $obj2id_($key)
     801        SendCmd "volume state $state $ivol"
    906802    }
    907803
    908804    # sync the state of slicers
    909     set vols [_currentVolumeIds -cutplanes]
     805    set vols [CurrentVolumeIds -cutplanes]
    910806    foreach axis {x y z} {
    911         _send "cutplane state [_state ${axis}slice] $axis $vols"
    912         set pos [expr {0.01*[$itk_component(${axis}slicer) get]}]
    913         _send "cutplane position $pos $axis $vols"
    914     }
    915 
     807        SendCmd "cutplane state [State ${axis}CutButton] $axis $vols"
     808        set pos [expr {0.01*[$itk_component(${axis}CutScale) get]}]
     809        SendCmd "cutplane position $pos $axis $vols"
     810    }
     811    SendCmd "volume data state [State volume] $vols"
     812
     813    if 0 {
     814    # Add this when we fix grid for volumes
     815    SendCmd "volume axis label x \"\""
     816    SendCmd "volume axis label y \"\""
     817    SendCmd "volume axis label z \"\""
     818    SendCmd "grid axisname x X eV"
     819    SendCmd "grid axisname y Y eV"
     820    SendCmd "grid axisname z Z eV"
     821    }
    916822    # if there are any commands in the buffer, send them now that we're done
    917823    SendBytes $outbuf_
     
    920826
    921827# ----------------------------------------------------------------------
     828# USAGE: SendTransferFunctions
     829# ----------------------------------------------------------------------
     830itcl::body Rappture::FlowvisViewer::SendTransferFunctions {} {
     831    if { $activeTf_ == "" } {
     832        return
     833    }
     834    set tf $activeTf_
     835    set first [lindex [get] 0]
     836
     837    # Insure that the global opacity and thickness settings (in the slider
     838    # settings widgets) are used for the active transfer-function.  Update the
     839    # values in the settings_ varible.
     840    set inner $itk_component(settingsFrame)
     841    set value [$inner.opacity get]
     842    set opacity [expr { double($value) * 0.01 }]
     843    set settings_($this-$tf-opacity) $opacity
     844    set value [$inner.thickness get]
     845    # Scale values between 0.00001 and 0.01000
     846    set thickness [expr {double($value) * 0.0001}]
     847    set settings_($this-$tf-thickness) $thickness
     848
     849    if { ![info exists $obj2styles_($first)] } {
     850        foreach tf $obj2styles_($first) {
     851            ComputeTransferFunction $tf
     852        }
     853        FixLegend
     854    }
     855}
     856
     857# ----------------------------------------------------------------------
    922858# USAGE: ReceiveImage -bytes <size>
    923859#
     
    926862# specified <size> will follow.
    927863# ----------------------------------------------------------------------
    928 itcl::body Rappture::FlowvisViewer::ReceiveImage {option size} {
    929     if {[IsConnected]} {
    930         set bytes [ReceiveBytes $size]
     864set counter 0
     865itcl::body Rappture::FlowvisViewer::ReceiveImage { args } {
     866    if {![isconnected]} {
     867        return
     868    }
     869    array set info {
     870        -type image
     871    }
     872    array set info $args
     873    set bytes [ReceiveBytes $info(-bytes)]
     874    ReceiveEcho <<line "<read $info(-bytes) bytes"
     875    if { $info(-type) == "image" } {
     876        ReceiveEcho "for [image width $_image(plot)]x[image height $_image(plot)] image>"       
    931877        $_image(plot) configure -data $bytes
    932         ReceiveEcho <<line "<read $size bytes for [image width $_image(plot)]x[image height $_image(plot)] image>"
    933     }
    934 }
    935 
    936 # ----------------------------------------------------------------------
    937 # USAGE: ReceiveFile -bytes <size>
    938 #
    939 # Invoked automatically whenever the "file" command comes in from
    940 # the rendering server.  Indicates that binary file data with the
    941 # specified <size> will follow.
    942 # ----------------------------------------------------------------------
    943 itcl::body Rappture::FlowvisViewer::ReceiveFile {option size} {
    944     if {[IsConnected]} {
    945         set bytes [ReceiveBytes $size]
    946         ReceiveEcho <<line "<read $size bytes for file>"
    947 
    948         # raise the record button back up.
    949         $itk_component(record) configure -relief raised
    950 
    951         # FIXME: manually download file???
    952         set mesg [Rappture::filexfer::download $bytes "flowmovie.mpeg"]
    953     }
    954 }
    955 
    956 # ----------------------------------------------------------------------
    957 # USAGE: _rebuild
    958 #
    959 # Called automatically whenever something changes that affects the
    960 # data in the widget.  Clears any existing data and rebuilds the
    961 # widget to display new data.
    962 # ----------------------------------------------------------------------
    963 itcl::body Rappture::FlowvisViewer::_rebuild {} {
     878    } elseif { $info(type) == "movie" } {
     879        set tag $this-movie-$info(-token)
     880        set hardcopy_($tag) $bytes
     881    }
     882}
     883
     884#
     885# ReceiveLegend --
     886#
     887#       The procedure is the response from the render server to each "legend"
     888#       command.  The server sends back a "legend" command invoked our
     889#       the slave interpreter.  The purpose is to collect data of the image
     890#       representing the legend in the canvas.  In addition, the isomarkers
     891#       of the active transfer function are displayed.
     892#
     893#       I don't know is this is the right place to display the isomarkers.
     894#       I don't know all the different paths used to draw the plot. There's
     895#       "Rebuild", "add", etc.
     896#
     897itcl::body Rappture::FlowvisViewer::ReceiveLegend { tf vmin vmax size } {
     898    if { ![isconnected] } {
     899        return
     900    }
     901    set bytes [ReceiveBytes $size]
     902    $_image(legend) configure -data $bytes
     903    ReceiveEcho <<line "<read $size bytes for [image width $_image(legend)]x[image height $_image(legend)] legend>"
     904
     905    set c $itk_component(legend)
     906    set w [winfo width $c]
     907    set h [winfo height $c]
     908    #foreach { dataobj comp } $id2obj_($ivol) break
     909    set lx 10
     910    set ly [expr {$h - 1}]
     911    if {"" == [$c find withtag transfunc]} {
     912        $c create image 10 10 -anchor nw \
     913            -image $_image(legend) -tags transfunc
     914        $c create text $lx $ly -anchor sw \
     915            -fill $itk_option(-plotforeground) -tags "limits vmin"
     916        $c create text [expr {$w-$lx}] $ly -anchor se \
     917            -fill $itk_option(-plotforeground) -tags "limits vmax"
     918        $c lower transfunc
     919        $c bind transfunc <ButtonRelease-1> \
     920            [itcl::code $this AddIsoMarker %x %y]
     921    }
     922    # Display the markers used by the active transfer function.
     923    #set tf $activeTf_
     924
     925    array set limits [GetLimits $tf]
     926    $c itemconfigure vmin -text [format %.2g $limits(min)]
     927    $c coords vmin $lx $ly
     928
     929    $c itemconfigure vmax -text [format %.2g $limits(max)]
     930    $c coords vmax [expr {$w-$lx}] $ly
     931
     932    if { [info exists isomarkers_($tf)] } {
     933        foreach m $isomarkers_($tf) {
     934            $m Show
     935        }
     936    }
     937}
     938
     939#
     940# ReceiveData --
     941#
     942#       The procedure is the response from the render server to each "data
     943#       follows" command.  The server sends back a "data" command invoked our
     944#       the # slave interpreter.  The purpose is to collect the min/max of the
     945#       volume sent # to the render server.  Since the client (flowvisviewer)
     946#       doesn't parse 3D # data formats, we rely on the server (flowvis) to
     947#       tell us what the limits # are.  Once we've received the limits to all
     948#       the data we've sent (tracked by # receiveIds_) we can then determine
     949#       what the transfer functions are for these # volumes.
     950#
     951#       Note: There is a considerable tradeoff in having the server report
     952#             back what the data limits are.  It means that much of the code
     953#             having to do with transfer-functions has to wait for the data
     954#             to come back, since the isomarkers are calculated based upon
     955#             the data limits.  The client code is much messier because of
     956#             this.  The alternative is to parse any of the 3D formats on the
     957#             client side.
     958#
     959itcl::body Rappture::FlowvisViewer::ReceiveData { args } {
     960    if { ![isconnected] } {
     961        return
     962    }
     963    # Arguments from server are name value pairs. Stuff them in an array.
     964    array set info $args
     965
     966    set ivol $info(id);         # Id of volume created by server.
     967
     968    set limits_($ivol-min) $info(min);  # Minimum value of the volume.
     969    set limits_($ivol-max) $info(max);  # Maximum value of the volume.
     970    set limits_(vmin)      $info(vmin); # Overall minimum value.
     971    set limits_(vmax)      $info(vmax); # Overall maximum value.
     972
     973    unset receiveIds_($ivol)
     974    if { [array size receiveIds_] == 0 } {
     975        UpdateTransferFunctions
     976    }
     977}
     978
     979#
     980# Rebuild --
     981#
     982# Called automatically whenever something changes that affects the data
     983# in the widget.  Clears any existing data and rebuilds the widget to
     984# display new data. 
     985#
     986itcl::body Rappture::FlowvisViewer::Rebuild {} {
     987
     988    # Hide all the isomarkers. Can't remove them. Have to remember the
     989    # settings since the user may have created/deleted/moved markers.
     990
     991    foreach tf [array names isomarkers_] {
     992        foreach m $isomarkers_($tf) {
     993            $m Hide
     994        }
     995    }
     996
    964997    # in the midst of sending data? then bail out
    965998    if {[llength $sendobjs_] > 0} {
    966         return
    967     }
     999        return
     1000    }
     1001
    9681002    # Find any new data that needs to be sent to the server.  Queue this up on
    9691003    # the sendobjs_ list, and send it out a little at a time.  Do this first,
    9701004    # before we rebuild the rest.
    9711005    foreach dataobj [get] {
    972         set comp [lindex [$dataobj components] 0]
    973         if {![info exists obj2id_($dataobj-$comp)]} {
    974             set i [lsearch -exact $sendobjs_ $dataobj]
    975             if {$i < 0} {
    976                 lappend sendobjs_ $dataobj
    977             }
    978         }
    979     }
    980     if {[llength $sendobjs_] > 0} {
    981         # Send off new data objects
    982         $_dispatcher event -idle !send_dataobjs
    983     } else {
    984         # Nothing to send -- activate the proper volume
    985         set first [lindex [get] 0]
    986         if {"" != $first} {
    987             set axis [$first hints updir]
    988             if {"" != $axis} {
    989                 _send "up $axis"
    990             }
    991         }
    992         foreach key [array names obj2id_ *-*] {
    993             set state [string match $first-* $key]
    994             _send "flow vectorid $obj2id_($key)"
    995         }
    996     }
    997 
    998     # Reset the screen size.
     1006        set comp [lindex [$dataobj components] 0]
     1007        if {![info exists obj2id_($dataobj-$comp)]} {
     1008            set i [lsearch -exact $sendobjs_ $dataobj]
     1009            if {$i < 0} {
     1010                lappend sendobjs_ $dataobj
     1011            }
     1012        }
     1013    }
    9991014    set w [winfo width $itk_component(3dview)]
    10001015    set h [winfo height $itk_component(3dview)]
    1001     _send "screen $w $h"
    1002 
     1016    SendCmd "screen $w $h"
     1017
     1018    #
    10031019    # Reset the camera and other view parameters
     1020    #
    10041021    set xyz [Euler2XYZ $view_(theta) $view_(phi) $view_(psi)]
    1005     _send "camera angle $xyz"
    1006     _send "camera zoom $view_(zoom)"
    1007 
    1008     # _fixSettings wireframe
    1009     _fixSettings light
    1010     _fixSettings transp
    1011     _fixSettings isosurface
    1012     _fixSettings grid
    1013     _fixSettings axes
    1014     _fixSettings outline
    1015     # _fixSettings contourlines
    1016 }
    1017 
    1018 # ----------------------------------------------------------------------
    1019 # USAGE: _currentVolumeIds ?-cutplanes?
     1022    SendCmd "camera angle $xyz"
     1023    PanCamera
     1024    SendCmd "camera zoom $view_(zoom)"
     1025
     1026    set settings_($this-theta) $view_(theta)
     1027    set settings_($this-phi)   $view_(phi)
     1028    set settings_($this-psi)   $view_(psi)
     1029    set settings_($this-pan-x) $view_(pan-x)
     1030    set settings_($this-pan-y) $view_(pan-y)
     1031    set settings_($this-zoom)  $view_(zoom)
     1032
     1033    FixSettings light
     1034    FixSettings transp
     1035    FixSettings isosurface
     1036    FixSettings grid
     1037    FixSettings axes
     1038    FixSettings outline
     1039
     1040    if {[llength $sendobjs_] > 0} {
     1041        # send off new data objects
     1042        $_dispatcher event -idle !send_dataobjs
     1043        return
     1044    }
     1045
     1046    # nothing to send -- activate the proper ivol
     1047    set first [lindex [get] 0]
     1048    if {"" != $first} {
     1049        set axis [$first hints updir]
     1050        if {"" != $axis} {
     1051            SendCmd "up $axis"
     1052        }
     1053        foreach key [array names obj2id_ *-*] {
     1054            set state [string match $first-* $key]
     1055            SendCmd "volume state $state $obj2id_($key)"
     1056        }
     1057        #
     1058        # The obj2id_ and id2style_ arrays may or may not have the right
     1059        # information.  It's possible for the server to know about volumes
     1060        # that the client has assumed it's deleted.  We could add checks.
     1061        # But this problem needs to be fixed not bandaided.
     1062        set comp [lindex [$first components] 0]
     1063        set ivol $obj2id_($first-$comp)
     1064
     1065        foreach comp [$first components] {
     1066            foreach ivol $obj2id_($first-$comp) {
     1067            NameTransferFunction $ivol
     1068            }
     1069        }
     1070    }
     1071
     1072    # sync the state of slicers
     1073    set vols [CurrentVolumeIds -cutplanes]
     1074    foreach axis {x y z} {
     1075        SendCmd "cutplane state [State ${axis}CutButton] $axis $vols"
     1076        set pos [expr {0.01*[$itk_component(${axis}CutScale) get]}]
     1077        SendCmd "cutplane position $pos $axis $vols"
     1078    }
     1079    SendCmd "volume data state [State volume] $vols"
     1080    $_dispatcher event -idle !legend
     1081}
     1082
     1083# ----------------------------------------------------------------------
     1084# USAGE: CurrentVolumeIds ?-cutplanes?
    10201085#
    10211086# Returns a list of volume server IDs for the current volume being
     
    10231088# of IDs if the current data object has multiple components.
    10241089# ----------------------------------------------------------------------
    1025 itcl::body Rappture::FlowvisViewer::_currentVolumeIds {{what -all}} {
     1090itcl::body Rappture::FlowvisViewer::CurrentVolumeIds {{what -all}} {
    10261091    set rlist ""
    10271092
    10281093    set first [lindex [get] 0]
    1029     foreach key [array names _obj2id *-*] {
    1030         if {[string match $first-* $key]} {
    1031             array set style {
    1032                 -cutplanes 1
    1033             }
    1034             foreach {dataobj comp} [split $key -] break
    1035             array set style [lindex [$dataobj components -style $comp] 0]
    1036 
    1037             if {$what != "-cutplanes" || $style(-cutplanes)} {
    1038                 lappend rlist $_obj2id($key)
    1039             }
    1040         }
     1094    foreach key [array names obj2id_ *-*] {
     1095        if {[string match $first-* $key]} {
     1096            array set style {
     1097                -cutplanes 1
     1098            }
     1099            foreach {dataobj comp} [split $key -] break
     1100            array set style [lindex [$dataobj components -style $comp] 0]
     1101
     1102            if {$what != "-cutplanes" || $style(-cutplanes)} {
     1103                lappend rlist $obj2id_($key)
     1104            }
     1105        }
    10411106    }
    10421107    return $rlist
     
    10441109
    10451110# ----------------------------------------------------------------------
    1046 # USAGE: _zoom in
    1047 # USAGE: _zoom out
    1048 # USAGE: _zoom reset
     1111# USAGE: Zoom in
     1112# USAGE: Zoom out
     1113# USAGE: Zoom reset
    10491114#
    10501115# Called automatically when the user clicks on one of the zoom
    10511116# controls for this widget.  Changes the zoom for the current view.
    10521117# ----------------------------------------------------------------------
    1053 itcl::body Rappture::FlowvisViewer::_zoom {option} {
     1118itcl::body Rappture::FlowvisViewer::Zoom {option} {
    10541119    switch -- $option {
    10551120        "in" {
    10561121            set view_(zoom) [expr {$view_(zoom)*1.25}]
     1122            set settings_($this-zoom) $view_(zoom)
    10571123        }
    10581124        "out" {
    10591125            set view_(zoom) [expr {$view_(zoom)*0.8}]
     1126            set settings_($this-zoom) $view_(zoom)
    10601127        }
    1061         "reset" {
     1128        "reset" {
    10621129            array set view_ {
    10631130                theta   45
    10641131                phi     45
    10651132                psi     0
    1066                 zoom    1.0
    1067                 dx      0
    1068                 dy      0
     1133                zoom    1.0
     1134                pan-x   0
     1135                pan-y   0
    10691136            }
    1070             set xyz [Euler2XYZ $view_(theta) $view_(phi) $view_(psi)]
    1071             _send "camera angle $xyz"
    1072             _send "camera pan $view_(dx) $view_(dy)"
    1073         }
    1074     }
    1075     _send "camera zoom $view_(zoom)"
    1076 }
    1077 
    1078 # ----------------------------------------------------------------------
    1079 # USAGE: $this _pan click x y
    1080 #        $this _pan drag x y
    1081 #        $this _pan release x y
     1137            set first [lindex [get] 0]
     1138            if { $first != "" } {
     1139                set location [$first hints camera]
     1140                if { $location != "" } {
     1141                    array set view_ $location
     1142                }
     1143            }
     1144            set xyz [Euler2XYZ $view_(theta) $view_(phi) $view_(psi)]
     1145            SendCmd "camera angle $xyz"
     1146            PanCamera
     1147            set settings_($this-theta) $view_(theta)
     1148            set settings_($this-phi)   $view_(phi)
     1149            set settings_($this-psi)   $view_(psi)
     1150            set settings_($this-pan-x) $view_(pan-x)
     1151            set settings_($this-pan-y) $view_(pan-y)
     1152            set settings_($this-zoom)  $view_(zoom)
     1153        }
     1154    }
     1155    SendCmd "camera zoom $view_(zoom)"
     1156}
     1157
     1158itcl::body Rappture::FlowvisViewer::PanCamera {} {
     1159    #set x [expr ($view_(pan-x)) / $limits_(xrange)]
     1160    #set y [expr ($view_(pan-y)) / $limits_(yrange)]
     1161    set x $view_(pan-x)
     1162    set y $view_(pan-y)
     1163    SendCmd "camera pan $x $y"
     1164}
     1165
     1166# ----------------------------------------------------------------------
     1167# USAGE: Rotate click <x> <y>
     1168# USAGE: Rotate drag <x> <y>
     1169# USAGE: Rotate release <x> <y>
     1170#
     1171# Called automatically when the user clicks/drags/releases in the
     1172# plot area.  Moves the plot according to the user's actions.
     1173# ----------------------------------------------------------------------
     1174itcl::body Rappture::FlowvisViewer::Rotate {option x y} {
     1175    switch -- $option {
     1176        click {
     1177            $itk_component(3dview) configure -cursor fleur
     1178            set click_(x) $x
     1179            set click_(y) $y
     1180            set click_(theta) $view_(theta)
     1181            set click_(phi) $view_(phi)
     1182        }
     1183        drag {
     1184            if {[array size click_] == 0} {
     1185                Rotate click $x $y
     1186            } else {
     1187                set w [winfo width $itk_component(3dview)]
     1188                set h [winfo height $itk_component(3dview)]
     1189                if {$w <= 0 || $h <= 0} {
     1190                    return
     1191                }
     1192
     1193                if {[catch {
     1194                    # this fails sometimes for no apparent reason
     1195                    set dx [expr {double($x-$click_(x))/$w}]
     1196                    set dy [expr {double($y-$click_(y))/$h}]
     1197                }]} {
     1198                    return
     1199                }
     1200
     1201                #
     1202                # Rotate the camera in 3D
     1203                #
     1204                if {$view_(psi) > 90 || $view_(psi) < -90} {
     1205                    # when psi is flipped around, theta moves backwards
     1206                    set dy [expr {-$dy}]
     1207                }
     1208                set theta [expr {$view_(theta) - $dy*180}]
     1209                while {$theta < 0} { set theta [expr {$theta+180}] }
     1210                while {$theta > 180} { set theta [expr {$theta-180}] }
     1211
     1212                if {abs($theta) >= 30 && abs($theta) <= 160} {
     1213                    set phi [expr {$view_(phi) - $dx*360}]
     1214                    while {$phi < 0} { set phi [expr {$phi+360}] }
     1215                    while {$phi > 360} { set phi [expr {$phi-360}] }
     1216                    set psi $view_(psi)
     1217                } else {
     1218                    set phi $view_(phi)
     1219                    set psi [expr {$view_(psi) - $dx*360}]
     1220                    while {$psi < -180} { set psi [expr {$psi+360}] }
     1221                    while {$psi > 180} { set psi [expr {$psi-360}] }
     1222                }
     1223
     1224                set view_(theta)        $theta
     1225                set view_(phi)          $phi
     1226                set view_(psi)          $psi
     1227                set xyz [Euler2XYZ $theta $phi $psi]
     1228                set settings_($this-theta) $view_(theta)
     1229                set settings_($this-phi)   $view_(phi)
     1230                set settings_($this-psi)   $view_(psi)
     1231                SendCmd "camera angle $xyz"
     1232                set click_(x) $x
     1233                set click_(y) $y
     1234            }
     1235        }
     1236        release {
     1237            Rotate drag $x $y
     1238            $itk_component(3dview) configure -cursor ""
     1239            catch {unset click_}
     1240        }
     1241        default {
     1242            error "bad option \"$option\": should be click, drag, release"
     1243        }
     1244    }
     1245}
     1246
     1247# ----------------------------------------------------------------------
     1248# USAGE: $this Pan click x y
     1249#        $this Pan drag x y
     1250#        $this Pan release x y
    10821251#
    10831252# Called automatically when the user clicks on one of the zoom
    10841253# controls for this widget.  Changes the zoom for the current view.
    10851254# ----------------------------------------------------------------------
    1086 itcl::body Rappture::FlowvisViewer::_pan {option x y} {
     1255itcl::body Rappture::FlowvisViewer::Pan {option x y} {
    10871256    # Experimental stuff
    10881257    set w [winfo width $itk_component(3dview)]
    10891258    set h [winfo height $itk_component(3dview)]
    10901259    if { $option == "set" } {
    1091         set x [expr $x / double($w)]
    1092         set y [expr $y / double($h)]
    1093         set view_(dx) [expr $view_(dx) + $x]
    1094         set view_(dy) [expr $view_(dy) + $y]
    1095         _send "camera pan $view_(dx) $view_(dy)"
    1096         return
     1260        set x [expr $x / double($w)]
     1261        set y [expr $y / double($h)]
     1262        set view_(pan-x) [expr $view_(pan-x) + $x]
     1263        set view_(pan-y) [expr $view_(pan-y) + $y]
     1264        PanCamera
     1265        set settings_($this-pan-x) $view_(pan-x)
     1266        set settings_($this-pan-y) $view_(pan-y)
     1267        return
    10971268    }
    10981269    if { $option == "click" } {
    1099         set click_(x) $x
    1100         set click_(y) $y
    1101         $itk_component(3dview) configure -cursor hand1
     1270        set click_(x) $x
     1271        set click_(y) $y
     1272        $itk_component(3dview) configure -cursor hand1
    11021273    }
    11031274    if { $option == "drag" || $option == "release" } {
    1104         set dx [expr ($click_(x) - $x)/double($w)]
    1105         set dy [expr ($click_(y) - $y)/double($h)]
    1106         set click_(x) $x
    1107         set click_(y) $y
    1108         set view_(dx) [expr $view_(dx) - $dx]
    1109         set view_(dy) [expr $view_(dy) - $dy]
    1110         _send "camera pan $view_(dx) $view_(dy)"
     1275        set dx [expr ($click_(x) - $x)/double($w)]
     1276        set dy [expr ($click_(y) - $y)/double($h)]
     1277        set click_(x) $x
     1278        set click_(y) $y
     1279        set view_(pan-x) [expr $view_(pan-x) - $dx]
     1280        set view_(pan-y) [expr $view_(pan-y) - $dy]
     1281        PanCamera
     1282        set settings_($this-pan-x) $view_(pan-x)
     1283        set settings_($this-pan-y) $view_(pan-y)
    11111284    }
    11121285    if { $option == "release" } {
    1113         $itk_component(3dview) configure -cursor ""
    1114     }
    1115 }
    1116 
    1117 # ----------------------------------------------------------------------
    1118 # USAGE: _rotate click <x> <y>
    1119 # USAGE: _rotate drag <x> <y>
    1120 # USAGE: _rotate release <x> <y>
    1121 #
    1122 # Called automatically when the user clicks/drags/releases in the
    1123 # plot area.  Moves the plot according to the user's actions.
    1124 # ----------------------------------------------------------------------
    1125 itcl::body Rappture::FlowvisViewer::_rotate {option x y} {
    1126     switch -- $option {
    1127         click {
    1128             $itk_component(3dview) configure -cursor fleur
    1129             array set click_ [subst {
    1130                 x       $x
    1131                 y       $y
    1132                 theta   $view_(theta)
    1133                 phi     $view_(phi)
    1134             }]
    1135         }
    1136         drag {
    1137             if {[array size click_] == 0} {
    1138                 _rotate click $x $y
    1139             } else {
    1140                 set w [winfo width $itk_component(3dview)]
    1141                 set h [winfo height $itk_component(3dview)]
    1142                 if {$w <= 0 || $h <= 0} {
    1143                     return
    1144                 }
    1145 
    1146                 if {[catch {
    1147                     # this fails sometimes for no apparent reason
    1148                     set dx [expr {double($x-$click_(x))/$w}]
    1149                     set dy [expr {double($y-$click_(y))/$h}]
    1150                 }] != 0 } {
    1151                     return
    1152                 }
    1153 
    1154                 #
    1155                 # Rotate the camera in 3D
    1156                 #
    1157                 if {$view_(psi) > 90 || $view_(psi) < -90} {
    1158                     # when psi is flipped around, theta moves backwards
    1159                     set dy [expr {-$dy}]
    1160                 }
    1161                 set theta [expr {$view_(theta) - $dy*180}]
    1162                 while {$theta < 0} { set theta [expr {$theta+180}] }
    1163                 while {$theta > 180} { set theta [expr {$theta-180}] }
    1164 
    1165                 if {abs($theta) >= 30 && abs($theta) <= 160} {
    1166                     set phi [expr {$view_(phi) - $dx*360}]
    1167                     while {$phi < 0} { set phi [expr {$phi+360}] }
    1168                     while {$phi > 360} { set phi [expr {$phi-360}] }
    1169                     set psi $view_(psi)
    1170                 } else {
    1171                     set phi $view_(phi)
    1172                     set psi [expr {$view_(psi) - $dx*360}]
    1173                     while {$psi < -180} { set psi [expr {$psi+360}] }
    1174                     while {$psi > 180} { set psi [expr {$psi-360}] }
    1175                 }
    1176 
    1177                 set view_(theta)        $theta
    1178                 set view_(phi)          $phi
    1179                 set view_(psi)          $psi
    1180                 set xyz [Euler2XYZ $view_(theta) $view_(phi) $view_(psi)]
    1181                 _send "camera angle $xyz"
    1182                 set click_(x) $x
    1183                 set click_(y) $y
    1184             }
    1185         }
    1186         release {
    1187             _rotate drag $x $y
    1188             $itk_component(3dview) configure -cursor ""
    1189             catch {unset click_}
    1190         }
    1191         default {
    1192             error "bad option \"$option\": should be click, drag, release"
    1193         }
    1194     }
    1195 }
    1196 
    1197 # ----------------------------------------------------------------------
    1198 # USAGE: _slice axis x|y|z ?on|off|toggle?
    1199 # USAGE: _slice move x|y|z <newval>
    1200 # USAGE: _slice volume ?on|off|toggle?
     1286        $itk_component(3dview) configure -cursor ""
     1287    }
     1288}
     1289
     1290# ----------------------------------------------------------------------
     1291# USAGE: Slice axis x|y|z ?on|off|toggle?
     1292# USAGE: Slice move x|y|z <newval>
     1293# USAGE: Slice volume ?on|off|toggle?
    12011294#
    12021295# Called automatically when the user drags the slider to move the
     
    12051298# data set.
    12061299# ----------------------------------------------------------------------
    1207 itcl::body Rappture::FlowvisViewer::_slice {option args} {
     1300itcl::body Rappture::FlowvisViewer::Slice {option args} {
    12081301    switch -- $option {
    1209         axis {
    1210             if {[llength $args] < 1 || [llength $args] > 2} {
    1211                 error "wrong # args: should be \"_slice axis x|y|z ?on|off|toggle?\""
     1302        axis {
     1303            if {[llength $args] < 1 || [llength $args] > 2} {
     1304                error "wrong # args: should be \"Slice axis x|y|z ?on|off|toggle?\""
     1305            }
     1306            set axis [lindex $args 0]
     1307            set op [lindex $args 1]
     1308            if {$op == ""} {
     1309                set op "on"
    12121310            }
    1213             set axis [lindex $args 0]
    1214             set op [lindex $args 1]
    1215             if {$op == ""} { set op "on" }
    1216 
    1217             set current [_state ${axis}slice]
    1218             if {$op == "toggle"} {
    1219                 if {$current == "on"} { set op "off" } else { set op "on" }
    1220             }
    1221             if {$op} {
    1222                 $itk_component(${axis}slicer) configure -state normal
    1223                 _send "cutplane state 1 $axis [_currentVolumeIds -cutplanes]"
    1224                 $itk_component(${axis}slice) configure -relief sunken
    1225             } else {
    1226                 $itk_component(${axis}slicer) configure -state disabled
    1227                 _send "cutplane state 0 $axis [_currentVolumeIds -cutplanes]"
    1228                 $itk_component(${axis}slice) configure -relief raised
    1229             }
    1230         }
    1231         move {
    1232             if {[llength $args] != 2} {
    1233                 error "wrong # args: should be \"_slice move x|y|z newval\""
    1234             }
    1235             set axis [lindex $args 0]
    1236             set newval [lindex $args 1]
    1237 
    1238             set newpos [expr {0.01*$newval}]
     1311            set current [State ${axis}CutButton]
     1312            if {$op == "toggle"} {
     1313                if {$current == "on"} {
     1314                    set op "off"
     1315                } else {
     1316                    set op "on"
     1317                }
     1318            }
     1319            if {$op} {
     1320                $itk_component(${axis}CutButton) configure \
     1321                    -image [Rappture::icon ${axis}-cutplane-on] \
     1322                    -relief sunken
     1323                SendCmd "cutplane state 1 $axis [CurrentVolumeIds -cutplanes]"
     1324                $itk_component(${axis}CutScale) configure -state normal
     1325            } else {
     1326                $itk_component(${axis}CutButton) configure \
     1327                    -image [Rappture::icon ${axis}-cutplane-off] \
     1328                    -relief raised
     1329                SendCmd "cutplane state 0 $axis [CurrentVolumeIds -cutplanes]"
     1330                $itk_component(${axis}CutScale) configure -state disabled
     1331            }
     1332        }
     1333        move {
     1334            if {[llength $args] != 2} {
     1335                error "wrong # args: should be \"Slice move x|y|z newval\""
     1336            }
     1337            set axis [lindex $args 0]
     1338            set newval [lindex $args 1]
     1339
     1340            set newpos [expr {0.01*$newval}]
    12391341#            set newval [expr {0.01*($newval-50)
    12401342#                *($limits_(${axis}max)-$limits_(${axis}min))
    12411343#                  + 0.5*($limits_(${axis}max)+$limits_(${axis}min))}]
    12421344
    1243             # show the current value in the readout
    1244             #puts "readout: $axis = $newval"
    1245 
    1246             set ids [_currentVolumeIds -cutplanes]
    1247             _send "cutplane position $newpos $axis $ids"
    1248         }
    1249         volume {
    1250             if {[llength $args] > 1} {
    1251                 error "wrong # args: should be \"_slice volume ?on|off|toggle?\""
    1252             }
    1253             set op [lindex $args 0]
    1254             if {$op == ""} { set op "on" }
    1255 
    1256             set current [_state volume]
    1257             if {$op == "toggle"} {
    1258                 if {$current == "on"} { set op "off" } else { set op "on" }
    1259             }
    1260 
    1261             if {$op} {
    1262                 _send "volume data state on [_currentVolumeIds]"
    1263                 $itk_component(volume) configure -relief sunken
    1264             } else {
    1265                 _send "volume data state off [_currentVolumeIds]"
    1266                 $itk_component(volume) configure -relief raised
    1267             }
    1268         }
    1269         default {
    1270             error "bad option \"$option\": should be axis, move, or volume"
    1271         }
    1272     }
    1273 }
    1274 
    1275 # ----------------------------------------------------------------------
    1276 # USAGE: _slicertip <axis>
     1345            # show the current value in the readout
     1346            #puts "readout: $axis = $newval"
     1347
     1348            set ids [CurrentVolumeIds -cutplanes]
     1349            SendCmd "cutplane position $newpos $axis $ids"
     1350        }
     1351        volume {
     1352            if {[llength $args] > 1} {
     1353                error "wrong # args: should be \"Slice volume ?on|off|toggle?\""
     1354            }
     1355            set op [lindex $args 0]
     1356            if {$op == ""} { set op "on" }
     1357
     1358            set current $settings_($this-volume)
     1359            if {$op == "toggle"} {
     1360                if {$current} {
     1361                    set op "off"
     1362                } else {
     1363                    set op "on"
     1364                }
     1365            }
     1366           
     1367            if {$op} {
     1368                SendCmd "volume data state on [CurrentVolumeIds]"
     1369                $itk_component(volume) configure -relief sunken
     1370                set settings_($this-volume) 1
     1371            } else {
     1372                SendCmd "volume data state off [CurrentVolumeIds]"
     1373                $itk_component(volume) configure -relief raised
     1374                set settings_($this-volume) 0
     1375            }
     1376        }
     1377        default {
     1378            error "bad option \"$option\": should be axis, move, or volume"
     1379        }
     1380    }
     1381}
     1382
     1383# ----------------------------------------------------------------------
     1384# USAGE: SlicerTip <axis>
    12771385#
    12781386# Used internally to generate a tooltip for the x/y/z slicer controls.
    12791387# Returns a message that includes the current slicer value.
    12801388# ----------------------------------------------------------------------
    1281 itcl::body Rappture::FlowvisViewer::_slicertip {axis} {
    1282     set val [$itk_component(${axis}slicer) get]
     1389itcl::body Rappture::FlowvisViewer::SlicerTip {axis} {
     1390    set val [$itk_component(${axis}CutScale) get]
    12831391#    set val [expr {0.01*($val-50)
    12841392#        *($limits_(${axis}max)-$limits_(${axis}min))
     
    12881396
    12891397# ----------------------------------------------------------------------
    1290 # USAGE: _flow movie record|stop|play ?on|off|toggle?
     1398# USAGE: Flow movie record|stop|play ?on|off|toggle?
    12911399#
    12921400# Called when the user clicks on the record, stop or play buttons
    12931401# for flow visualization.
    12941402# ----------------------------------------------------------------------
    1295 itcl::body Rappture::FlowvisViewer::_flow {option args} {
     1403itcl::body Rappture::FlowvisViewer::Flow {option args} {
    12961404    switch -- $option {
    1297         movie {
    1298             if {[llength $args] < 1 || [llength $args] > 2} {
    1299                 error "wrong # args: should be \"_flow movie record|stop|play ?on|off|toggle?\""
    1300             }
    1301             set action [lindex $args 0]
    1302             set op [lindex $args 1]
    1303             if {$op == ""} { set op "on" }
    1304 
    1305             set current [_state $action]
    1306             if {$op == "toggle"} {
    1307                 if {$current == "on"} {
    1308                     set op "off"
    1309                 } else {
    1310                     set op "on"
    1311                 }
    1312             }
    1313             set cmds ""
    1314             switch -- $action {
    1315                 record {
    1316                     if { [$itk_component(record) cget -relief] != "sunken" } {
    1317                         $itk_component(record) configure -relief sunken
     1405        movie {
     1406            if {[llength $args] < 1 || [llength $args] > 2} {
     1407                error "wrong # args: should be \"Flow movie record|stop|play ?on|off|toggle?\""
     1408            }
     1409            set action [lindex $args 0]
     1410            set op [lindex $args 1]
     1411            if {$op == ""} { set op "on" }
     1412
     1413            set current [State $action]
     1414            if {$op == "toggle"} {
     1415                if {$current == "on"} {
     1416                    set op "off"
     1417                } else {
     1418                    set op "on"
     1419                }
     1420            }
     1421            set cmds ""
     1422            switch -- $action {
     1423                record {
     1424                    if { [$itk_component(rewind) cget -relief] != "sunken" } {
     1425                        $itk_component(rewind) configure -relief sunken
    13181426                        $itk_component(stop) configure -relief raised
    13191427                        $itk_component(play) configure -relief raised
    1320                         set inner \
    1321                             [$itk_component(controls).panel component inner]
    1322                         set frames [$inner.scales.framecnt value]
     1428                        set inner $itk_component(settingsFrame)
     1429                        set frames [$inner.framecnt value]
     1430                        set settings_(numframes) $frames
    13231431                        set cmds "flow capture $frames"
    13241432                        _send $cmds
    13251433                    }
    1326                 }
    1327                 stop {
     1434                }
     1435                stop {
    13281436                    if { [$itk_component(stop) cget -relief] != "sunken" } {
    1329                         $itk_component(record) configure -relief raised
     1437                        $itk_component(rewind) configure -relief raised
    13301438                        $itk_component(stop) configure -relief sunken
    13311439                        $itk_component(play) configure -relief raised
     
    13341442                        _send $cmds
    13351443                    }
    1336                 }
    1337                 play {
     1444                }
     1445                play {
    13381446                    if { [$itk_component(play) cget -relief] != "sunken" } {
    1339                         $itk_component(record) configure -relief raised
     1447                        $itk_component(rewind) configure -relief raised
     1448                        $itk_component(stop) configure -relief raised
     1449                        $itk_component(play) configure \
     1450                            -image [Rappture::icon flow-pause] \
     1451                            -relief sunken
     1452                        bind $itk_component(play) <ButtonPress> \
     1453                            [itcl::code $this _pause]
     1454                        flow next
     1455                    }
     1456                }
     1457                default {
     1458                    error "bad option \"$option\": should be one of record|stop|play"
     1459                }
     1460
     1461            }
     1462        }
     1463        default {
     1464            error "bad option \"$option\": should be movie"
     1465        }
     1466    }
     1467}
     1468
     1469# ----------------------------------------------------------------------
     1470# USAGE: Play
     1471#
     1472# ----------------------------------------------------------------------
     1473itcl::body Rappture::FlowvisViewer::Play {} {
     1474    SendCmd "flow play"
     1475    set delay [expr {int(ceil(pow($settings_(speed)/10.0+2,2.0)*15))}]
     1476    $_dispatcher event -after $delay !play
     1477}
     1478
     1479# ----------------------------------------------------------------------
     1480# USAGE: Pause
     1481#
     1482# Invoked when the user hits the "pause" button to stop playing the
     1483# current sequence of frames as a movie.
     1484# ----------------------------------------------------------------------
     1485itcl::body Rappture::FlowvisViewer::Pause {} {
     1486    $_dispatcher cancel !play
     1487
     1488    # Toggle the button to "play" mode
     1489    $itk_component(play) configure \
     1490        -image [Rappture::icon flow-start] \
     1491        -relief raised
     1492    bind $itk_component(play) <ButtonPress> \
     1493        [itcl::code $this Flow movie play toggle]
     1494}
     1495
     1496# ----------------------------------------------------------------------
     1497# USAGE: State <component>
     1498#
     1499# Used internally to determine the state of a toggle button.
     1500# The <component> is the itk component name of the button.
     1501# Returns on/off for the state of the button.
     1502# ----------------------------------------------------------------------
     1503itcl::body Rappture::FlowvisViewer::State {comp} {
     1504    if {[$itk_component(${comp}) cget -relief] == "sunken"} {
     1505        return "on"
     1506    }
     1507    return "off"
     1508}
     1509
     1510# ----------------------------------------------------------------------
     1511# USAGE: FixSettings <what> ?<value>?
     1512#
     1513# Used internally to update rendering settings whenever parameters
     1514# change in the popup settings panel.  Sends the new settings off
     1515# to the back end.
     1516# ----------------------------------------------------------------------
     1517itcl::body Rappture::FlowvisViewer::FixSettings {what {value ""}} {
     1518    switch -- $what {
     1519        light {
     1520            if {[isconnected]} {
     1521                set val $settings_($this-light)
     1522                set sval [expr {0.1*$val}]
     1523                SendCmd "volume shading diffuse $sval"
     1524                set sval [expr {sqrt($val+1.0)}]
     1525                SendCmd "volume shading specular $sval"
     1526            }
     1527        }
     1528        transp {
     1529            if {[isconnected]} {
     1530                set val $settings_($this-transp)
     1531                set sval [expr {0.2*$val+1}]
     1532                SendCmd "volume shading opacity $sval"
     1533            }
     1534        }
     1535        opacity {
     1536            if {[isconnected] && $activeTf_ != "" } {
     1537                set val $settings_($this-opacity)
     1538                set sval [expr { 0.01 * double($val) }]
     1539                set tf $activeTf_
     1540                set settings_($this-$tf-opacity) $sval
     1541                UpdateTransferFunctions
     1542            }
     1543        }
     1544
     1545        thickness {
     1546            if {[isconnected] && $activeTf_ != "" } {
     1547                set val $settings_($this-thickness)
     1548                # Scale values between 0.00001 and 0.01000
     1549                set sval [expr {0.0001*double($val)}]
     1550                set tf $activeTf_
     1551                set settings_($this-$tf-thickness) $sval
     1552                UpdateTransferFunctions
     1553            }
     1554        }
     1555        "outline" {
     1556            if {[isconnected]} {
     1557                SendCmd "volume outline state $settings_($this-outline)"
     1558            }
     1559        }
     1560        "isosurface" {
     1561            if {[isconnected]} {
     1562                SendCmd "volume shading isosurface $settings_($this-isosurface)"
     1563            }
     1564        }
     1565        "grid" {
     1566            if { [isconnected] } {
     1567                SendCmd "grid visible $settings_($this-grid)"
     1568            }
     1569        }
     1570        "axes" {
     1571            if { [isconnected] } {
     1572                SendCmd "axis visible $settings_($this-axes)"
     1573            }
     1574        }
     1575        "legend" {
     1576            if { $settings_($this-legend) } {
     1577                pack $itk_component(legend) -side bottom -fill x
     1578            } else {
     1579                pack forget $itk_component(legend)
     1580            }
     1581            FixLegend
     1582        }
     1583        "volume" {
     1584            Slice volume $settings_($this-volume)
     1585        }
     1586        "particles" {
     1587        }
     1588        default {
     1589            error "don't know how to fix $what"
     1590        }
     1591    }
     1592}
     1593
     1594# ----------------------------------------------------------------------
     1595# USAGE: FixLegend
     1596#
     1597# Used internally to update the legend area whenever it changes size
     1598# or when the field changes.  Asks the server to send a new legend
     1599# for the current field.
     1600# ----------------------------------------------------------------------
     1601itcl::body Rappture::FlowvisViewer::FixLegend {} {
     1602    set lineht [font metrics $itk_option(-font) -linespace]
     1603    set w [expr {[winfo width $itk_component(legend)]-20}]
     1604    set h [expr {[winfo height $itk_component(legend)]-20-$lineht}]
     1605    if {$w > 0 && $h > 0 && "" != $activeTf_} {
     1606        SendCmd "legend $activeTf_ $w $h"
     1607    } else {
     1608    # Can't do this as this will remove the items associated with the
     1609    # isomarkers.
     1610
     1611    #$itk_component(legend) delete all
     1612    }
     1613}
     1614
     1615#
     1616# NameTransferFunction --
     1617#
     1618#       Creates a transfer function name based on the <style> settings in the
     1619#       library run.xml file. This placeholder will be used later to create
     1620#       and send the actual transfer function once the data info has been sent
     1621#       to us by the render server. [We won't know the volume limits until the
     1622#       server parses the 3D data and sends back the limits via ReceiveData.]
     1623#
     1624#       FIXME: The current way we generate transfer-function names completely
     1625#              ignores the -markers option.  The problem is that we are forced
     1626#              to compute the name from an increasing complex set of values:
     1627#              color, levels, marker, opacity.  I think we're stuck doing it
     1628#              now.
     1629#
     1630itcl::body Rappture::FlowvisViewer::NameTransferFunction { ivol } {
     1631    array set style {
     1632        -color rainbow
     1633        -levels 6
     1634        -opacity 1.0
     1635    }
     1636    foreach {dataobj comp} $id2obj_($ivol) break
     1637    array set style [lindex [$dataobj components -style $comp] 0]
     1638    set tf "$style(-color):$style(-levels):$style(-opacity)"
     1639
     1640    set id2style_($ivol) $tf
     1641    lappend obj2styles_($dataobj) $tf
     1642    lappend style2ids_($tf) $ivol
     1643}
     1644
     1645#
     1646# ComputeTransferFunction --
     1647#
     1648#   Computes and sends the transfer function to the render server.  It's
     1649#   assumed that the volume data limits are known and that the global
     1650#   transfer-functions slider values have be setup.  Both parts are
     1651#   needed to compute the relative value (location) of the marker, and
     1652#   the alpha map of the transfer function.
     1653#
     1654itcl::body Rappture::FlowvisViewer::ComputeTransferFunction { tf } {
     1655    array set style {
     1656        -color rainbow
     1657        -levels 6
     1658        -opacity 1.0
     1659    }
     1660    set dataobj ""; set comp ""
     1661    foreach ivol $style2ids_($tf) {
     1662        if { [info exists id2obj_($ivol)] } {
     1663            foreach {dataobj comp} $id2obj_($ivol) break
     1664            break
     1665        }
     1666    }
     1667    if { $dataobj == "" } {
     1668        return 0
     1669    }
     1670    array set style [lindex [$dataobj components -style $comp] 0]
     1671
     1672
     1673    # We have to parse the style attributes for a volume using this
     1674    # transfer-function *once*.  This sets up the initial isomarkers for the
     1675    # transfer function.  The user may add/delete markers, so we have to
     1676    # maintain a list of markers for each transfer-function.  We use the one
     1677    # of the volumes (the first in the list) using the transfer-function as a
     1678    # reference.
     1679    #
     1680    # FIXME: The current way we generate transfer-function names completely
     1681    #        ignores the -markers option.  The problem is that we are forced
     1682    #        to compute the name from an increasing complex set of values:
     1683    #        color, levels, marker, opacity.  I think the cow's out of the
     1684    #        barn on this one.
     1685
     1686    if { ![info exists isomarkers_($tf)] } {
     1687        # Have to defer creation of isomarkers until we have data limits
     1688        if { [info exists style(-markers)] } {
     1689            ParseMarkersOption $tf $ivol $style(-markers)
     1690        } else {
     1691            ParseLevelsOption $tf $ivol $style(-levels)
     1692        }
     1693    }
     1694    if {$style(-color) == "rainbow"} {
     1695        set style(-color) "white:yellow:green:cyan:blue:magenta"
     1696    }
     1697    set clist [split $style(-color) :]
     1698    set cmap "0.0 [Color2RGB white] "
     1699    for {set i 0} {$i < [llength $clist]} {incr i} {
     1700        set x [expr {double($i+1)/([llength $clist]+1)}]
     1701        set color [lindex $clist $i]
     1702        append cmap "$x [Color2RGB $color] "
     1703    }
     1704    append cmap "1.0 [Color2RGB $color]"
     1705
     1706    set tag $this-$tf
     1707    if { ![info exists settings_($tag-opacity)] } {
     1708        set settings_($tag-opacity) $style(-opacity)
     1709    }
     1710    set max $settings_($tag-opacity)
     1711
     1712    set isovalues {}
     1713    foreach m $isomarkers_($tf) {
     1714        lappend isovalues [$m GetRelativeValue]
     1715    }
     1716    # Sort the isovalues
     1717    set isovalues [lsort -real $isovalues]
     1718
     1719    if { ![info exists settings_($tag-thickness)]} {
     1720        set settings_($tag-thickness) 0.05
     1721    }
     1722    set delta $settings_($tag-thickness)
     1723
     1724    set first [lindex $isovalues 0]
     1725    set last [lindex $isovalues end]
     1726    set wmap ""
     1727    if { $first == "" || $first != 0.0 } {
     1728        lappend wmap 0.0 0.0
     1729    }
     1730    foreach x $isovalues {
     1731        set x1 [expr {$x-$delta-0.00001}]
     1732        set x2 [expr {$x-$delta}]
     1733        set x3 [expr {$x+$delta}]
     1734        set x4 [expr {$x+$delta+0.00001}]
     1735        if { $x1 < 0.0 } {
     1736            set x1 0.0
     1737        } elseif { $x1 > 1.0 } {
     1738            set x1 1.0
     1739        }
     1740        if { $x2 < 0.0 } {
     1741            set x2 0.0
     1742        } elseif { $x2 > 1.0 } {
     1743            set x2 1.0
     1744        }
     1745        if { $x3 < 0.0 } {
     1746            set x3 0.0
     1747        } elseif { $x3 > 1.0 } {
     1748            set x3 1.0
     1749        }
     1750        if { $x4 < 0.0 } {
     1751            set x4 0.0
     1752        } elseif { $x4 > 1.0 } {
     1753            set x4 1.0
     1754        }
     1755        # add spikes in the middle
     1756        lappend wmap $x1 0.0
     1757        lappend wmap $x2 $max
     1758        lappend wmap $x3 $max
     1759        lappend wmap $x4 0.0
     1760    }
     1761    if { $last == "" || $last != 1.0 } {
     1762        lappend wmap 1.0 0.0
     1763    }
     1764    SendBytes "transfunc define $tf { $cmap } { $wmap }\n"
     1765    return [SendBytes "volume shading transfunc $tf $style2ids_($tf)\n"]
     1766}
     1767
     1768# ----------------------------------------------------------------------
     1769# CONFIGURATION OPTION: -plotbackground
     1770# ----------------------------------------------------------------------
     1771itcl::configbody Rappture::FlowvisViewer::plotbackground {
     1772    if { [isconnected] } {
     1773        foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
     1774        #fix this!
     1775        #SendCmd "color background $r $g $b"
     1776    }
     1777}
     1778
     1779# ----------------------------------------------------------------------
     1780# CONFIGURATION OPTION: -plotforeground
     1781# ----------------------------------------------------------------------
     1782itcl::configbody Rappture::FlowvisViewer::plotforeground {
     1783    if { [isconnected] } {
     1784        foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
     1785        #fix this!
     1786        #SendCmd "color background $r $g $b"
     1787    }
     1788}
     1789
     1790# ----------------------------------------------------------------------
     1791# CONFIGURATION OPTION: -plotoutline
     1792# ----------------------------------------------------------------------
     1793itcl::configbody Rappture::FlowvisViewer::plotoutline {
     1794    # Must check if we are connected because this routine is called from the
     1795    # class body when the -plotoutline itk_option is defined.  At that point
     1796    # the FlowvisViewer class constructor hasn't been called, so we can't
     1797    # start sending commands to visualization server.
     1798    if { [isconnected] } {
     1799        if {"" == $itk_option(-plotoutline)} {
     1800            SendCmd "volume outline state off"
     1801        } else {
     1802            SendCmd "volume outline state on"
     1803            SendCmd "volume outline color [Color2RGB $itk_option(-plotoutline)]"
     1804        }
     1805    }
     1806}
     1807
     1808#
     1809# The -levels option takes a single value that represents the number
     1810# of evenly distributed markers based on the current data range. Each
     1811# marker is a relative value from 0.0 to 1.0.
     1812#
     1813itcl::body Rappture::FlowvisViewer::ParseLevelsOption { tf ivol levels } {
     1814    set c $itk_component(legend)
     1815    regsub -all "," $levels " " levels
     1816    if {[string is int $levels]} {
     1817        for {set i 1} { $i <= $levels } {incr i} {
     1818            set x [expr {double($i)/($levels+1)}]
     1819            set m [IsoMarker \#auto $c $this $tf]
     1820            $m SetRelativeValue $x
     1821            lappend isomarkers_($tf) $m
     1822        }
     1823    } else {
     1824        foreach x $levels {
     1825            set m [IsoMarker \#auto $c $this $tf]
     1826            $m SetRelativeValue $x
     1827            lappend isomarkers_($tf) $m
     1828        }
     1829    }
     1830}
     1831
     1832#
     1833# The -markers option takes a list of zero or more values (the values
     1834# may be separated either by spaces or commas) that have the following
     1835# format:
     1836#
     1837#   N%  Percent of current total data range.  Converted to
     1838#       to a relative value between 0.0 and 1.0.
     1839#   N   Absolute value of marker.  If the marker is outside of
     1840#       the current range, it will be displayed on the outer
     1841#       edge of the legends, but it range it represents will
     1842#       not be seen.
     1843#
     1844itcl::body Rappture::FlowvisViewer::ParseMarkersOption { tf ivol markers } {
     1845    set c $itk_component(legend)
     1846    regsub -all "," $markers " " markers
     1847    foreach marker $markers {
     1848        set n [scan $marker "%g%s" value suffix]
     1849        if { $n == 2 && $suffix == "%" } {
     1850            # ${n}% : Set relative value.
     1851            set value [expr {$value * 0.01}]
     1852            set m [IsoMarker \#auto $c $this $tf]
     1853            $m SetRelativeValue $value
     1854            lappend isomarkers_($tf) $m
     1855        } else {
     1856            # ${n} : Set absolute value.
     1857            set m [IsoMarker \#auto $c $this $tf]
     1858            $m SetAbsoluteValue $value
     1859            lappend isomarkers_($tf) $m
     1860        }
     1861    }
     1862}
     1863
     1864# ----------------------------------------------------------------------
     1865# USAGE: UndateTransferFunctions
     1866# ----------------------------------------------------------------------
     1867itcl::body Rappture::FlowvisViewer::UpdateTransferFunctions {} {
     1868    $_dispatcher event -idle !send_transfunc
     1869}
     1870
     1871itcl::body Rappture::FlowvisViewer::AddIsoMarker { x y } {
     1872    if { $activeTf_ == "" } {
     1873        error "active transfer function isn't set"
     1874    }
     1875    set tf $activeTf_
     1876    set c $itk_component(legend)
     1877    set m [IsoMarker \#auto $c $this $tf]
     1878    set w [winfo width $c]
     1879    $m SetRelativeValue [expr {double($x-10)/($w-20)}]
     1880    lappend isomarkers_($tf) $m
     1881    UpdateTransferFunctions
     1882    return 1
     1883}
     1884
     1885itcl::body Rappture::FlowvisViewer::RemoveDuplicateIsoMarker { marker x } {
     1886    set tf [$marker GetTransferFunction]
     1887    set bool 0
     1888    if { [info exists isomarkers_($tf)] } {
     1889        set list {}
     1890        set marker [namespace tail $marker]
     1891        foreach m $isomarkers_($tf) {
     1892            set sx [$m GetScreenPosition]
     1893            if { $m != $marker } {
     1894                if { $x >= ($sx-3) && $x <= ($sx+3) } {
     1895                    $marker SetRelativeValue [$m GetRelativeValue]
     1896                    itcl::delete object $m
     1897                    bell
     1898                    set bool 1
     1899                    continue
     1900                }
     1901            }
     1902            lappend list $m
     1903        }
     1904        set isomarkers_($tf) $list
     1905        UpdateTransferFunctions
     1906    }
     1907    return $bool
     1908}
     1909
     1910itcl::body Rappture::FlowvisViewer::OverIsoMarker { marker x } {
     1911    set tf [$marker GetTransferFunction]
     1912    if { [info exists isomarkers_($tf)] } {
     1913        set marker [namespace tail $marker]
     1914        foreach m $isomarkers_($tf) {
     1915            set sx [$m GetScreenPosition]
     1916            if { $m != $marker } {
     1917                set bool [expr { $x >= ($sx-3) && $x <= ($sx+3) }]
     1918                $m Activate $bool
     1919            }
     1920        }
     1921    }
     1922    return ""
     1923}
     1924
     1925itcl::body Rappture::FlowvisViewer::GetLimits { tf } {
     1926    set limits_(min) ""
     1927    set limits_(max) ""
     1928    foreach ivol $style2ids_($tf) {
     1929        if { ![info exists limits_($ivol-min)] } {
     1930            error "can't find $ivol limits"
     1931        }
     1932        if { $limits_(min) == "" || $limits_(min) > $limits_($ivol-min) } {
     1933            set limits_(min) $limits_($ivol-min)
     1934        }
     1935        if { $limits_(max) == "" || $limits_(max) < $limits_($ivol-max) } {
     1936            set limits_(max) $limits_($ivol-max)
     1937        }
     1938    }
     1939    return [array get limits_]
     1940}
     1941
     1942
     1943#
     1944# flow --
     1945#
     1946# Called when the user clicks on the stop or play buttons
     1947# for flow visualization.
     1948#
     1949#       $this flow start
     1950#       $this flow stop
     1951#       $this flow toggle
     1952#       $this flow rewind
     1953#       $this flow pause
     1954#       $this flow next
     1955#
     1956itcl::body Rappture::FlowvisViewer::flow {option} {
     1957    switch -- $option {
     1958        "stop" {
     1959            if { $flow_(state) != "stopped" } {
     1960                # Reset the play button to off
     1961                $itk_component(play) configure -image [Rappture::icon flow-play]
     1962                $_dispatcher cancel !play
     1963                SendCmd "flow reset"
     1964                set flow_(state) "stopped"
     1965            }
     1966        }
     1967        "pause" {
     1968            if { $flow_(state) == "playing" } {
     1969                # Reset the play button to pause
     1970                # Convert to the play button.
     1971                $itk_component(play) configure -image [Rappture::icon flow-play]
     1972                $_dispatcher cancel !play
     1973                set flow_(state) "paused"
     1974            }
     1975        }
     1976        "start" {
     1977            if { $flow_(state) != "playing" } {
     1978                # Starts the "flow next" requests to the server.
     1979                # Convert to the pause button.
     1980                $itk_component(play) configure \
     1981                    -image [Rappture::icon flow-pause]
     1982                flow next
     1983                set flow_(state) "playing"
     1984            }
     1985        }
     1986        "toggle" {
     1987            if { $flow_(state) == "playing" } {
     1988                flow pause
     1989            } else {
     1990                flow start
     1991            }
     1992        }
     1993        "rewind" {
     1994            if  { $flow_(state) != "stopped"  } {
     1995                SendCmd "flow reset"
     1996            }
     1997        }
     1998        "next" {
     1999            # This operation should not be called by public routines.
     2000            SendCmd "flow play"
     2001            set delay [expr {int(ceil(pow($settings_(speed)/10.0+2,2.0)*15))}]
     2002            $_dispatcher event -after $delay !play
     2003        }
     2004        default {
     2005            error "bad option \"$option\": should be start, stop, toggle, or reset."
     2006        }
     2007    }
     2008}
     2009
     2010#
     2011# record --
     2012#
     2013# Called when the user clicks on the record, stop or play buttons
     2014# for flow visualization.
     2015#
     2016#       $this record on
     2017#       $this record off
     2018#       $this record toggle
     2019#
     2020#
     2021itcl::body Rappture::FlowvisViewer::record {option} {
     2022    switch -- $option {
     2023        movie {
     2024            if {[llength $args] < 1 || [llength $args] > 2} {
     2025                error "wrong # args: should be \"Flow movie record|stop|play ?on|off|toggle?\""
     2026            }
     2027            set action [lindex $args 0]
     2028            set op [lindex $args 1]
     2029            if {$op == ""} { set op "on" }
     2030
     2031            set current [State $action]
     2032            if {$op == "toggle"} {
     2033                if {$current == "on"} {
     2034                    set op "off"
     2035                } else {
     2036                    set op "on"
     2037                }
     2038            }
     2039            set cmds ""
     2040            switch -- $action {
     2041                record {
     2042                    if { [$itk_component(rewind) cget -relief] != "sunken" } {
     2043                        $itk_component(rewind) configure -relief sunken
     2044                        $itk_component(stop) configure -relief raised
     2045                        $itk_component(play) configure -relief raised
     2046                        set inner $itk_component(settingsFrame)
     2047                        set frames [$inner.framecnt value]
     2048                        set cmds "flow capture $frames"
     2049                        _send $cmds
     2050                    }
     2051                }
     2052                stop {
     2053                    if { [$itk_component(stop) cget -relief] != "sunken" } {
     2054                        $itk_component(rewind) configure -relief raised
     2055                        $itk_component(stop) configure -relief sunken
     2056                        $itk_component(play) configure -relief raised
     2057                        _pause
     2058                        set cmds "flow reset"
     2059                        _send $cmds
     2060                    }
     2061                }
     2062                play {
     2063                    if { [$itk_component(play) cget -relief] != "sunken" } {
     2064                        $itk_component(rewind) configure -relief raised
    13402065                        $itk_component(stop) configure -relief raised
    13412066                        $itk_component(play) configure \
     
    13442069                        bind $itk_component(play) <ButtonPress> \
    13452070                            [itcl::code $this _pause]
    1346                         _play
     2071                        Play
    13472072                    }
    1348                 }
    1349                 default {
    1350                     error "bad option \"$option\": should be one of record|stop|play"
    1351                 }
    1352 
     2073                }
     2074                default {
     2075                    error "bad option \"$option\": should be one of record|stop|play"
     2076                }
     2077
     2078            }
     2079        }
     2080        default {
     2081            error "bad option \"$option\": should be movie"
     2082        }
     2083    }
     2084}
     2085
     2086
     2087itcl::body Rappture::FlowvisViewer::drawer { what who } {
     2088    if { [info exists drawer_(current)] && $who != $drawer_(current) } {
     2089        drawer deactivate $drawer_(current)
     2090    }
     2091    switch -- ${what} {
     2092        "activate" {
     2093            $itk_component(drawer) add $itk_component($who) -sticky nsew
     2094            after idle [list focus $itk_component($who)]
     2095            if { ![info exists drawer_($who)] } {
     2096                set rw [winfo reqwidth $itk_component($who)]
     2097                set w [winfo width $itk_component(drawer)]
     2098                set x [expr $w - $rw]
     2099                $itk_component(drawer) sash place 0 $x 0
     2100                set drawer_($who) 1
     2101            } else {
     2102                set w [winfo width $itk_component(drawer)]
     2103                puts stderr "w of drawer is $w"
     2104                puts stderr "w of last($who) is $drawer_($who-lastx)"
     2105                set x [expr $w - $drawer_($who-lastx) - 10]
     2106                puts stderr "setting sash to $x for $who"
     2107                $itk_component(drawer) sash place 0 $x 0
     2108                $itk_component(drawer) paneconfigure $itk_component($who) \
     2109                    -width $drawer_($who-lastx)
     2110                $itk_component(3dview) configure -width $x
     2111            }
     2112            set drawer_(current) $who
     2113            $itk_component(${who}Button) configure -relief sunken -bd 1
     2114        }
     2115        "deactivate" {
     2116            # Save the current width of the drawer.
     2117            puts stderr "component=$who"
     2118            set width [winfo width $itk_component($who)]
     2119            set reqwidth [winfo reqwidth $itk_component($who)]
     2120            if { $reqwidth < $width } {
     2121                set width $reqwidth
     2122            }
     2123            set x [lindex [$itk_component(drawer) sash coord 0] 0]
     2124            puts stderr "sashx=$x"
     2125            set drawer_($who-lastx) $width
     2126            $itk_component(drawer) forget $itk_component($who)
     2127            $itk_component(${who}Button) configure -relief raised -bd 1
     2128            unset drawer_(current)
     2129        }
     2130        "toggle" {
     2131            set slaves [$itk_component(drawer) panes]
     2132            if { [lsearch $slaves $itk_component($who)] >= 0 } {
     2133                drawer deactivate $who
     2134            } else {
     2135                drawer activate $who
    13532136            }
    13542137        }
    1355         default {
    1356             error "bad option \"$option\": should be movie"
     2138        "resize" {
     2139            set bbox [$itk_component(${who}Canvas) bbox all]
     2140            set wid [winfo width $itk_component(${who}Frame)]
     2141            $itk_component(${who}Canvas) configure -width $wid \
     2142                -scrollregion $bbox -yscrollincrement 0.1i
    13572143        }
    13582144    }
    13592145}
    13602146
    1361 # ----------------------------------------------------------------------
    1362 # USAGE: _play
    1363 #
    1364 # ----------------------------------------------------------------------
    1365 itcl::body Rappture::FlowvisViewer::_play {} {
    1366     set cmds {flow play}
    1367     _send $cmds
    1368     set delay [expr {int(ceil(pow($_play(speed)/10.0+2,2.0)*15))}]
    1369     set _afterId [after $delay [itcl::code $this _play]]
    1370 }
    1371 
    1372 # ----------------------------------------------------------------------
    1373 # USAGE: _pause
    1374 #
    1375 # Invoked when the user hits the "pause" button to stop playing the
    1376 # current sequence of frames as a movie.
    1377 # ----------------------------------------------------------------------
    1378 itcl::body Rappture::FlowvisViewer::_pause {} {
    1379     if {"" != $_afterId} {
    1380         catch {after cancel $_afterId}
    1381         set _afterId ""
    1382     }
    1383 
    1384     # toggle the button to "play" mode
    1385     $itk_component(play) configure \
    1386         -image [Rappture::icon playback-start] \
    1387         -relief raised
    1388     bind $itk_component(play) <ButtonPress> \
    1389         [itcl::code $this _flow movie play toggle]
    1390 
    1391 }
    1392 
    1393 # ----------------------------------------------------------------------
    1394 # USAGE: _state <component>
    1395 #
    1396 # Used internally to determine the state of a toggle button.
    1397 # The <component> is the itk component name of the button.
    1398 # Returns on/off for the state of the button.
    1399 # ----------------------------------------------------------------------
    1400 itcl::body Rappture::FlowvisViewer::_state {comp} {
    1401     if {[$itk_component($comp) cget -relief] == "sunken"} {
    1402         return "on"
    1403     }
    1404     return "off"
    1405 }
    1406 
    1407 # ----------------------------------------------------------------------
    1408 # USAGE: _fixSettings <what> ?<value>?
    1409 #
    1410 # Used internally to update rendering settings whenever parameters
    1411 # change in the popup settings panel.  Sends the new settings off
    1412 # to the back end.
    1413 # ----------------------------------------------------------------------
    1414 itcl::body Rappture::FlowvisViewer::_fixSettings { what {value ""} } {
    1415     set inner [$itk_component(controls).panel component inner]
    1416     switch -- $what {
    1417         light {
    1418             if {[isconnected]} {
    1419                 set val [$inner.scales.light get]
    1420                 set sval [expr {0.1*$val}]
    1421                 _send "volume shading diffuse $sval"
    1422 
    1423                 set sval [expr {sqrt($val+1.0)}]
    1424                 _send "volume shading specular $sval"
     2147itcl::body Rappture::FlowvisViewer::BuildSettingsDrawer {} {
     2148    foreach { key value } {
     2149        grid            0
     2150        axes            1
     2151        outline         1
     2152        volume          1
     2153        legend          1
     2154        particles       1
     2155        lic             1
     2156        light           40
     2157        transp          50
     2158        opacity         100
     2159        thickness       350
     2160    } {
     2161        set settings_($this-$key) $value
     2162    }
     2163    itk_component add settings {
     2164        Rappture::Scroller $itk_component(drawer).settings \
     2165            -xscrollmode auto -yscrollmode auto \
     2166            -highlightthickness 0
     2167    }
     2168
     2169    itk_component add settingsCanvas {
     2170        canvas $itk_component(settings).canvas -highlightthickness 0
     2171    } {
     2172        ignore -highlightthickness
     2173    }
     2174    $itk_component(settings) contents $itk_component(settingsCanvas)
     2175
     2176    itk_component add settingsFrame {
     2177        frame $itk_component(settingsCanvas).frame \
     2178            -highlightthickness 0
     2179    } {
     2180        ignore -highlightthickness
     2181    }
     2182    $itk_component(settingsCanvas) create window 0 0 \
     2183        -anchor nw -window $itk_component(settingsFrame)
     2184    bind $itk_component(settingsFrame) <Configure> \
     2185        [itcl::code $this drawer resize settings]
     2186
     2187    set inner $itk_component(settingsFrame)
     2188
     2189    label $inner.title -text "View Settings" -font "Arial 10 bold"
     2190    label $inner.volset -text "Volume Settings" -font "Arial 10 bold"
     2191
     2192    set fg [option get $itk_component(hull) font Font]
     2193    #set bfg [option get $itk_component(hull) boldFont Font]
     2194
     2195    label $inner.dim -text "Dim" -font $fg
     2196    ::scale $inner.light -from 0 -to 100 -orient horizontal \
     2197        -variable [itcl::scope settings_($this-light)] \
     2198        -width 10 \
     2199        -showvalue off -command [itcl::code $this FixSettings light]
     2200    label $inner.bright -text "Bright" -font $fg
     2201
     2202    label $inner.fog -text "Fog" -font $fg
     2203    ::scale $inner.transp -from 0 -to 100 -orient horizontal \
     2204        -variable [itcl::scope settings_($this-transp)] \
     2205        -width 10 \
     2206        -showvalue off -command [itcl::code $this FixSettings transp]
     2207    label $inner.plastic -text "Plastic" -font $fg
     2208
     2209    label $inner.clear -text "Clear" -font $fg
     2210    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
     2211        -variable [itcl::scope settings_($this-opacity)] \
     2212        -width 10 \
     2213        -showvalue off -command [itcl::code $this FixSettings opacity]
     2214    label $inner.opaque -text "Opaque" -font $fg
     2215
     2216    label $inner.thin -text "Thin" -font $fg
     2217    ::scale $inner.thickness -from 0 -to 1000 -orient horizontal \
     2218        -variable [itcl::scope settings_($this-thickness)] \
     2219        -width 10 \
     2220        -showvalue off -command [itcl::code $this FixSettings thickness]
     2221    label $inner.thick -text "Thick" -font $fg
     2222
     2223    set ::Rappture::FlowvisViewer::settings_($this-isosurface) 0
     2224    checkbutton $inner.isosurface \
     2225        -text "Isosurface shading" \
     2226        -variable [itcl::scope settings_($this-isosurface)] \
     2227        -command [itcl::code $this FixSettings isosurface] \
     2228        -font "Arial 9"
     2229
     2230    checkbutton $inner.axes \
     2231        -text "Axes" \
     2232        -variable [itcl::scope settings_($this-axes)] \
     2233        -command [itcl::code $this FixSettings axes] \
     2234        -font "Arial 9"
     2235
     2236    checkbutton $inner.grid \
     2237        -text "Grid" \
     2238        -variable [itcl::scope settings_($this-grid)] \
     2239        -command [itcl::code $this FixSettings grid] \
     2240        -font "Arial 9"
     2241
     2242    checkbutton $inner.outline \
     2243        -text "Outline" \
     2244        -variable [itcl::scope settings_($this-outline)] \
     2245        -command [itcl::code $this FixSettings outline] \
     2246        -font "Arial 9"
     2247
     2248    checkbutton $inner.legend \
     2249        -text "Legend" \
     2250        -variable [itcl::scope settings_($this-legend)] \
     2251        -command [itcl::code $this FixSettings legend] \
     2252        -font "Arial 9"
     2253
     2254    checkbutton $inner.volume \
     2255        -text "Volume" \
     2256        -variable [itcl::scope settings_($this-volume)] \
     2257        -command [itcl::code $this FixSettings volume] \
     2258        -font "Arial 9"
     2259
     2260    checkbutton $inner.particles \
     2261        -text "Particles" \
     2262        -variable [itcl::scope settings_($this-particles)] \
     2263        -command [itcl::code $this FixSettings particles] \
     2264        -font "Arial 9"
     2265
     2266    checkbutton $inner.lic \
     2267        -text "Lic" \
     2268        -variable [itcl::scope settings_($this-lic)] \
     2269        -command [itcl::code $this FixSettings lic] \
     2270        -font "Arial 9"
     2271
     2272    blt::table $inner \
     2273        0,0 $inner.title -anchor w  -columnspan 4 \
     2274        1,1 $inner.axes  -columnspan 2 -anchor w \
     2275        2,1 $inner.grid  -columnspan 2 -anchor w \
     2276        3,1 $inner.outline  -columnspan 2 -anchor w \
     2277        4,1 $inner.volume  -columnspan 2 -anchor w \
     2278        1,3 $inner.legend  -columnspan 2 -anchor w \
     2279        2,3 $inner.particles  -columnspan 2 -anchor w \
     2280        3,3 $inner.lic  -columnspan 1 -anchor w \
     2281        9,0 $inner.volset -anchor w  -columnspan 4 \
     2282        11,1 $inner.dim  -anchor e \
     2283        11,2 $inner.light -columnspan 2 \
     2284        11,4 $inner.bright -anchor w \
     2285        12,1 $inner.fog -anchor e \
     2286        12,2 $inner.transp -columnspan 2 \
     2287        12,4 $inner.plastic -anchor w \
     2288        13,1 $inner.clear -anchor e \
     2289        13,2 $inner.opacity -columnspan 2 \
     2290        13,4 $inner.opaque -anchor w \
     2291        14,1 $inner.thin -anchor e \
     2292        14,2 $inner.thickness -columnspan 2 \
     2293        14,4 $inner.thick -anchor w \
     2294
     2295    blt::table configure $inner c0 -resize expand -width 4
     2296}
     2297
     2298itcl::body Rappture::FlowvisViewer::BuildCutplanesDrawer {} {
     2299    itk_component add cutplanes {
     2300        Rappture::Scroller $itk_component(drawer).cutplanes \
     2301            -xscrollmode auto -yscrollmode auto \
     2302            -highlightthickness 0
     2303    }
     2304
     2305    #
     2306    # Create slicer controls...
     2307    #
     2308    itk_component add cutplanesCanvas {
     2309        canvas $itk_component(cutplanes).canvas -highlightthickness 0
     2310    } {
     2311        ignore -highlightthickness
     2312    }
     2313    $itk_component(cutplanes) contents $itk_component(cutplanesCanvas)
     2314
     2315    itk_component add cutplanesFrame {
     2316        frame $itk_component(cutplanesCanvas).frame \
     2317            -highlightthickness 0
     2318    }  {
     2319        ignore -highlightthickness
     2320    }
     2321    $itk_component(cutplanesCanvas) create window 0 0 \
     2322        -anchor nw -window $itk_component(cutplanesFrame)
     2323    bind $itk_component(cutplanesFrame) <Configure> \
     2324        [itcl::code $this drawer resize cutplanes]
     2325
     2326    set inner $itk_component(cutplanesFrame)
     2327
     2328    label $inner.title -text "Cutplanes" -font "Arial 10 bold"
     2329
     2330    # X-value slicer...
     2331    itk_component add xCutButton {
     2332        label $itk_component(cutplanes).xbutton \
     2333            -borderwidth 1 -relief raised -padx 1 -pady 1 \
     2334            -image [Rappture::icon x-cutplane-off] \
     2335            -highlightthickness 0
     2336    } {
     2337        usual
     2338        ignore -borderwidth -highlightthickness
     2339        rename -highlightbackground -controlbackground \
     2340            controlBackground Background
     2341    }
     2342    bind $itk_component(xCutButton) <ButtonPress> \
     2343        [itcl::code $this Slice axis x toggle]
     2344    Rappture::Tooltip::for $itk_component(xCutButton) \
     2345        "Toggle the X cut plane on/off"
     2346
     2347    itk_component add xCutScale {
     2348        ::scale $itk_component(cutplanes).xval -from 100 -to 0 \
     2349            -width 10 -orient vertical -showvalue off \
     2350            -borderwidth 1 -highlightthickness 0 \
     2351            -command [itcl::code $this Slice move x]
     2352    } {
     2353        usual
     2354        ignore -borderwidth
     2355        ignore -highlightthickness
     2356        rename -highlightbackground -controlbackground \
     2357            controlBackground Background
     2358        rename -troughcolor -controldarkbackground \
     2359            controlDarkBackground Background
     2360    }
     2361    $itk_component(xCutScale) set 50
     2362    #$itk_component(xCutScale) configure -state disabled
     2363    Rappture::Tooltip::for $itk_component(xCutScale) \
     2364        "@[itcl::code $this SlicerTip x]"
     2365
     2366    # Y-value slicer...
     2367    itk_component add yCutButton {
     2368        label $itk_component(cutplanes).ybutton \
     2369            -borderwidth 1 -relief raised -padx 1 -pady 1 \
     2370            -image [Rappture::icon y-cutplane-off] \
     2371            -highlightthickness 0
     2372    } {
     2373        usual
     2374        ignore -borderwidth -highlightthickness       
     2375        rename -highlightbackground -controlbackground \
     2376            controlBackground Background
     2377    }
     2378    bind $itk_component(yCutButton) <ButtonPress> \
     2379        [itcl::code $this Slice axis y toggle]
     2380    Rappture::Tooltip::for $itk_component(yCutButton) \
     2381        "Toggle the Y cut plane on/off"
     2382
     2383    itk_component add yCutScale {
     2384        ::scale $itk_component(cutplanes).yval -from 100 -to 0 \
     2385            -width 10 -orient vertical -showvalue off \
     2386            -borderwidth 1 -highlightthickness 0 \
     2387            -command [itcl::code $this Slice move y]
     2388    } {
     2389        usual
     2390        ignore -borderwidth
     2391        ignore -highlightthickness
     2392        rename -highlightbackground -controlbackground controlBackground Background
     2393        rename -troughcolor -controldarkbackground controlDarkBackground Background
     2394    }
     2395    $itk_component(yCutScale) set 50
     2396    #$itk_component(yCutScale) configure -state disabled
     2397    Rappture::Tooltip::for $itk_component(yCutScale) \
     2398        "@[itcl::code $this SlicerTip y]"
     2399
     2400    # Z-value slicer...
     2401    itk_component add zCutButton {
     2402        label $itk_component(cutplanes).zbutton \
     2403            -borderwidth 1 -relief raised -padx 1 -pady 1 \
     2404            -image [Rappture::icon z-cutplane-off] \
     2405            -highlightthickness 0
     2406    } {
     2407        usual
     2408        ignore -borderwidth -highlightthickness       
     2409        rename -highlightbackground -controlbackground controlBackground Background
     2410    }
     2411    bind $itk_component(zCutButton) <ButtonPress> \
     2412        [itcl::code $this Slice axis z toggle]
     2413    Rappture::Tooltip::for $itk_component(zCutButton) \
     2414        "Toggle the Z cut plane on/off"
     2415
     2416    itk_component add zCutScale {
     2417        ::scale $itk_component(cutplanes).zval -from 100 -to 0 \
     2418            -width 10 -orient vertical -showvalue off \
     2419            -borderwidth 1 -highlightthickness 0 \
     2420            -command [itcl::code $this Slice move z]
     2421    } {
     2422        usual
     2423        ignore -borderwidth
     2424        ignore -highlightthickness
     2425        rename -highlightbackground -controlbackground controlBackground Background
     2426        rename -troughcolor -controldarkbackground controlDarkBackground Background
     2427    }
     2428    $itk_component(zCutScale) set 50
     2429    #$itk_component(zCutScale) configure -state disabled
     2430    Rappture::Tooltip::for $itk_component(zCutScale) \
     2431        "@[itcl::code $this SlicerTip z]"
     2432
     2433    blt::table $inner \
     2434        0,0 $inner.title -anchor w  -columnspan 4 \
     2435        3,1 $itk_component(xCutButton) \
     2436        3,2 $itk_component(yCutButton) \
     2437        3,3 $itk_component(zCutButton) \
     2438        2,1 $itk_component(xCutScale) \
     2439        2,2 $itk_component(yCutScale) \
     2440        2,3 $itk_component(zCutScale) \
     2441
     2442    blt::table configure $inner c0 -resize expand -width 4
     2443}
     2444
     2445itcl::body Rappture::FlowvisViewer::BuildCameraDrawer {} {
     2446
     2447    itk_component add camera {
     2448        Rappture::Scroller $itk_component(drawer).camerascrl \
     2449            -xscrollmode auto -yscrollmode auto \
     2450            -highlightthickness 0
     2451    }
     2452
     2453    itk_component add cameraCanvas {
     2454        canvas $itk_component(camera).canvas -highlightthickness 0
     2455    } {
     2456        ignore -highlightthickness
     2457    }
     2458    $itk_component(camera) contents $itk_component(cameraCanvas)
     2459
     2460    itk_component add cameraFrame {
     2461        frame $itk_component(cameraCanvas).frame \
     2462            -highlightthickness 0
     2463    }
     2464    $itk_component(cameraCanvas) create window 0 0 \
     2465        -anchor nw -window $itk_component(cameraFrame)
     2466    bind $itk_component(cameraFrame) <Configure> \
     2467        [itcl::code $this drawer resize camera]
     2468
     2469    set inner $itk_component(cameraFrame)
     2470
     2471    label $inner.title -text "Camera Settings" -font "Arial 10 bold"
     2472
     2473    set labels { phi theta psi pan-x pan-y zoom }
     2474    blt::table $inner \
     2475        0,0 $inner.title -anchor w  -columnspan 4
     2476    set row 1
     2477    foreach tag $labels {
     2478        label $inner.${tag}label -text $tag -font "Arial 9"
     2479        entry $inner.${tag} -font "Arial 9"  -bg white \
     2480            -textvariable [itcl::scope settings_($this-$tag)]
     2481        bind $inner.${tag} <KeyPress-Return> \
     2482            [itcl::code $this camera set ${tag}]
     2483        blt::table $inner \
     2484            $row,1 $inner.${tag}label -anchor e \
     2485            $row,2 $inner.${tag} -anchor w
     2486        incr row
     2487    }
     2488    bind $inner.title <Shift-ButtonPress> \
     2489        [itcl::code $this camera show]
     2490    blt::table configure $inner c0 -resize expand -width 4
     2491    blt::table configure $inner c1 c2 -resize none
     2492    blt::table configure $inner c3 -resize expand
     2493
     2494}
     2495
     2496
     2497
     2498#  camera --
     2499itcl::body Rappture::FlowvisViewer::camera {option args} {
     2500    switch -- $option {
     2501        "show" {
     2502            puts [array get view_]
     2503        }
     2504        "set" {
     2505            set who [lindex $args 0]
     2506            set x $settings_($this-$who)
     2507            set code [catch { string is double $x } result]
     2508            if { $code != 0 || !$result } {
     2509                set settings_($this-$who) $view_($who)
     2510                return
     2511            }
     2512            switch -- $who {
     2513                "pan-x" - "pan-y" {
     2514                    set view_($who) $settings_($this-$who)
     2515                    PanCamera
     2516                }
     2517                "phi" - "theta" - "psi" {
     2518                    set view_($who) $settings_($this-$who)
     2519                    set xyz [Euler2XYZ $view_(theta) $view_(phi) $view_(psi)]
     2520                    _send "camera angle $xyz"
     2521                }
     2522                "zoom" {
     2523                    set view_($who) $settings_($this-$who)
     2524                    _send "camera zoom $view_(zoom)"
     2525                }
    14252526            }
    14262527        }
    1427         transp {
    1428             if {[isconnected]} {
    1429                 set val [$inner.scales.transp get]
    1430                 set sval [expr {0.2*$val+1}]
    1431                 _send "volume shading opacity $sval"
    1432             }
    1433         }
    1434         opacity {
    1435             if {[isconnected] && $activeTf_ != "" } {
    1436                 set val [$inner.scales.opacity get]
    1437                 set sval [expr { 0.01 * double($val) }]
    1438                 set tf $activeTf_
    1439                 set settings_($this-$tf-opacity) $sval
    1440                 UpdateTransferFunctions
    1441             }
    1442         }
    1443 
    1444         thickness {
    1445             if {[isconnected] && $activeTf_ != "" } {
    1446                 set val [$inner.scales.thickness get]
    1447                 # Scale values between 0.00001 and 0.01000
    1448                 set sval [expr {0.0001*double($val)}]
    1449                 set tf $activeTf_
    1450                 set settings_($this-$tf-thickness) $sval
    1451                 UpdateTransferFunctions
    1452             }
    1453         }
    1454         "outline" {
    1455             if {[isconnected]} {
    1456                 _send "volume outline state $settings_($this-outline)"
    1457             }
    1458         }
    1459         "isosurface" {
    1460             if {[isconnected]} {
    1461                 _send "volume shading isosurface $settings_($this-isosurface)"
    1462             }
    1463         }
    1464         "grid" {
    1465             if { [IsConnected] } {
    1466                 _send "grid visible $settings_($this-grid)"
    1467             }
    1468         }
    1469         "particlevis" {
    1470             if { [IsConnected] } {
    1471                 _send "flow particle visible $settings_($this-particlevis)"
    1472             }
    1473         }
    1474         "lic" {
    1475             if { [IsConnected] } {
    1476                 _send "flow lic $settings_($this-lic)"
    1477             }
    1478         }
    1479         "axes" {
    1480             if { [IsConnected] } {
    1481                 _send "axis visible $settings_($this-axes)"
    1482             }
    1483         }
    1484         default {
    1485             error "don't know how to fix $what: should be grid, axes, contourlines, or legend"
    1486         }
    1487     }
    1488 }
    1489 
    1490 # ----------------------------------------------------------------------
    1491 # USAGE: _getTransfuncData <dataobj> <comp>
    1492 #
    1493 # Used internally to compute the colormap and alpha map used to define
    1494 # a transfer function for the specified component in a data object.
    1495 # Returns: name {v r g b ...} {v w ...}
    1496 # ----------------------------------------------------------------------
    1497 itcl::body Rappture::FlowvisViewer::_getTransfuncData {dataobj comp} {
    1498     array set style {
    1499         -color rainbow
    1500         -levels 6
    1501         -opacity 0.5
    1502     }
    1503     array set style [lindex [$dataobj components -style $comp] 0]
    1504     set sname "$style(-color):$style(-levels):$style(-opacity)"
    1505 
    1506     if {$style(-color) == "rainbow"} {
    1507         set style(-color) "white:yellow:green:cyan:blue:magenta"
    1508     }
    1509     set clist [split $style(-color) :]
    1510     set color white
    1511     set cmap "0.0 [Color2RGB $color] "
    1512     set range [expr $limits_(vmax) - $limits_(vmin)]
    1513     for {set i 0} {$i < [llength $clist]} {incr i} {
    1514         set xval [expr {double($i+1)/([llength $clist]+1)}]
    1515         set color [lindex $clist $i]
    1516         append cmap "$xval [Color2RGB $color] "
    1517     }
    1518     append cmap "1.0 [Color2RGB $color] "
    1519 
    1520     set opacity $style(-opacity)
    1521     set levels $style(-levels)
    1522     set wmap {}
    1523     if {[string is int $levels]} {
    1524         lappend wmap 0.0 0.0
    1525         set delta [expr {0.125/($levels+1)}]
    1526         for {set i 1} {$i <= $levels} {incr i} {
    1527             # add spikes in the middle
    1528             set xval [expr {double($i)/($levels+1)}]
    1529             lappend wmap [expr {$xval-$delta-0.01}] 0.0
    1530             lappend wmap [expr {$xval-$delta}] $opacity
    1531             lappend wmap [expr {$xval+$delta}] $opacity
    1532             lappend wmap [expr {$xval+$delta+0.01}] 0.0
    1533         }
    1534         lappend wmap 1.0 0.0
    1535     } else {
    1536         lappend wmap 0.0 0.0
    1537         set delta 0.05
    1538         foreach xval [split $levels ,] {
    1539             lappend wmap [expr {$xval-$delta}] 0.0
    1540             lappend $xval $opacity
    1541             lappend [expr {$xval+$delta}] 0.0
    1542         }
    1543         lappend wmap 1.0 0.0
    1544     }
    1545     return [list $sname $cmap $wmap]
    1546 }
    1547 
    1548 # ----------------------------------------------------------------------
    1549 # CONFIGURATION OPTION: -plotbackground
    1550 # ----------------------------------------------------------------------
    1551 itcl::configbody Rappture::FlowvisViewer::plotbackground {
    1552     foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
    1553     #fix this!
    1554     #_send "color background $r $g $b"
    1555 }
    1556 
    1557 # ----------------------------------------------------------------------
    1558 # CONFIGURATION OPTION: -plotforeground
    1559 # ----------------------------------------------------------------------
    1560 itcl::configbody Rappture::FlowvisViewer::plotforeground {
    1561     foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
    1562     #fix this!
    1563     #_send "color background $r $g $b"
    1564 }
    1565 
    1566 # ----------------------------------------------------------------------
    1567 # CONFIGURATION OPTION: -plotoutline
    1568 # ----------------------------------------------------------------------
    1569 itcl::configbody Rappture::FlowvisViewer::plotoutline {
    1570     if {[IsConnected]} {
    1571         _send "grid linecolor [Color2RGB $itk_option(-plotoutline)]"
    1572     }
    1573 }
     2528    }
     2529}
  • trunk/gui/scripts/heightmapviewer.tcl

    r1343 r1349  
    6969    protected method _send {string}
    7070    protected method _send_dataobjs {}
    71     protected method ReceiveImage {option size}
     71    protected method ReceiveImage { args }
    7272    private method _ReceiveLegend {tf vmin vmax size}
    7373    private method _BuildSettingsDrawer {}
     
    100100    private common settings_      ;# Array used for checkbuttons and radiobuttons
    101101    private variable initialized_
     102    private common hardcopy_
    102103}
    103104
     
    360361# flag can also request the internal images being shown.
    361362# ----------------------------------------------------------------------
    362 itcl::body Rappture::HeightmapViewer::get {args} {
     363itcl::body Rappture::HeightmapViewer::get { args } {
    363364    if {[llength $args] == 0} {
    364365        set args "-objects"
     
    410411# are specified, then all dataobjs are deleted.
    411412# ----------------------------------------------------------------------
    412 itcl::body Rappture::HeightmapViewer::delete {args} {
     413itcl::body Rappture::HeightmapViewer::delete { args } {
    413414    if {[llength $args] == 0} {
    414415        set args $dlist_
     
    443444# the user scans through data in the ResultSet viewer.
    444445# ----------------------------------------------------------------------
    445 itcl::body Rappture::HeightmapViewer::scale {args} {
     446itcl::body Rappture::HeightmapViewer::scale { args } {
    446447    foreach val {xmin xmax ymin ymax zmin zmax vmin vmax} {
    447448        set limits_($val) ""
     
    649650# specified <size> will follow.
    650651# ----------------------------------------------------------------------
    651 itcl::body Rappture::HeightmapViewer::ReceiveImage {option size} {
    652     if {[IsConnected]} {
    653         set bytes [ReceiveBytes $size]
     652itcl::body Rappture::HeightmapViewer::ReceiveImage { args } {
     653    if {![IsConnected]} {
     654        return
     655    }
     656    array set info {
     657        -type image
     658    }
     659    array set info $args
     660    set bytes [ReceiveBytes $info(-bytes)]
     661    ReceiveEcho <<line "<read $info(-bytes) bytes"
     662    if { $info(-type) == "image" } {
    654663        $_image(plot) configure -data $bytes
    655         ReceiveEcho <<line "<read $size bytes for [image width $_image(plot)]x[image height $_image(plot)] image>"
     664        ReceiveEcho <<line "<read for [image width $_image(plot)]x[image height $_image(plot)] image>"
     665    } elseif { $info(type) == "print" } {
     666        set tag $this-print-$info(-token)
     667        set hardcopy_($tag) $bytes
    656668    }
    657669}
  • trunk/gui/scripts/molvisviewer.tcl

    r1346 r1349  
    16471647    #  3) user cancels the operation.
    16481648    tkwait variable $var
     1649
     1650    # Clean up.
    16491651    $_dispatcher cancel !pngtimeout
    16501652    WaitIcon stop $inner.icon
     
    16531655    destroy $popup
    16541656    update
     1657
    16551658    if { $hardcopy_($this-$token) != "" } {
    16561659        return [list .png $hardcopy_($this-$token)]
  • trunk/gui/scripts/nanovisviewer.tcl

    r1343 r1349  
    7373    protected method _SendTransferFunctions {}
    7474
    75     protected method _ReceiveImage {option size}
     75    protected method _ReceiveImage { args }
    7676    protected method _ReceiveLegend { ivol vmin vmax size }
    7777    protected method _ReceiveData { args }
    78     protected method _ReceivePrint { option size }
    7978
    8079    protected method _rebuild {}
     
    124123    # opacity, or thickness.
    125124    #common _downloadPopup          ;# download options from popup
     125    private common _hardcopy
    126126}
    127127
     
    239239        label $itk_component(slicers).xslice \
    240240            -borderwidth 1 -relief raised -padx 1 -pady 1 \
    241             -image [Rappture::icon x-cutplane]
     241            -image [Rappture::icon x-cutplane-off]
    242242    } {
    243243        usual
     
    275275        label $itk_component(slicers).yslice \
    276276            -borderwidth 1 -relief raised -padx 1 -pady 1 \
    277             -image [Rappture::icon y-cutplane]
     277            -image [Rappture::icon y-cutplane-off]
    278278    } {
    279279        usual
     
    311311        label $itk_component(slicers).zslice \
    312312            -borderwidth 1 -relief raised -padx 1 -pady 1 \
    313             -image [Rappture::icon z-cutplane]
     313            -image [Rappture::icon z-cutplane-off]
    314314    } {
    315315        usual
     
    895895
    896896# ----------------------------------------------------------------------
    897 # USAGE: _ReceiveImage -bytes <size>
     897# USAGE: _ReceiveImage -bytes <size> -type <type> -token <token>
    898898#
    899899# Invoked automatically whenever the "image" command comes in from
     
    902902# ----------------------------------------------------------------------
    903903set counter 0
    904 itcl::body Rappture::NanovisViewer::_ReceiveImage {option size} {
    905     if { [isconnected] } {
    906         global counter
    907         incr counter
    908         set bytes [ReceiveBytes $size]
     904itcl::body Rappture::NanovisViewer::_ReceiveImage { args } {
     905    if { ![isconnected] } {
     906        return
     907    }
     908    global counter
     909    incr counter
     910    array set info {
     911        -token "???"
     912        -bytes 0
     913        -type image
     914    }
     915    array set info $args
     916    set bytes [ReceiveBytes $info(-bytes)]
     917    ReceiveEcho <<line "<read $info(-bytes) bytes for [image width $_image(plot)]x[image height $_image(plot)] image>"
     918    if { $info(-type) == "image" } {
    909919        $_image(plot) configure -data $bytes
    910         ReceiveEcho <<line "<read $size bytes for [image width $_image(plot)]x[image height $_image(plot)] image>"
     920    } elseif { $info(type) == "print" } {
     921        set tag $this-print-$info(-token)
     922        set _hardcopy($tag) $bytes
    911923    }
    912924}
     
    10091021
    10101022# ----------------------------------------------------------------------
    1011 # USAGE: _ReceivePrint -bytes <size>
    1012 #
    1013 # Invoked automatically whenever the "image" command comes in from
    1014 # the rendering server.  Indicates that binary image data with the
    1015 # specified <size> will follow.
    1016 # ----------------------------------------------------------------------
    1017 itcl::body Rappture::NanovisViewer::_ReceivePrint {option size} {
    1018     if { [isconnected] } {
    1019         set bytes [ReceiveBytes $size]
    1020         set f [open /tmp/junk "w"]
    1021         puts $f $bytes
    1022         close $f
    1023         $_image(download) configure -data $bytes
    1024         update
    1025         puts stderr "<read $size bytes for [image width $_image(download)]x[image height $_image(download)] image>"
    1026     }
    1027 }
    1028 
    1029 # ----------------------------------------------------------------------
    10301023# USAGE: _rebuild
    10311024#
     
    13261319            }
    13271320            if {$op} {
     1321                $itk_component(${axis}slice) configure \
     1322                    -image [Rappture::icon ${axis}-cutplane-on] \
     1323                    -relief sunken
    13281324                $itk_component(${axis}slicer) configure -state normal
    13291325                _send "cutplane state 1 $axis [_currentVolumeIds -cutplanes]"
    1330                 $itk_component(${axis}slice) configure -relief sunken
    13311326            } else {
     1327                $itk_component(${axis}slice) configure \
     1328                    -image [Rappture::icon ${axis}-cutplane-off] \
     1329                    -relief raised
    13321330                $itk_component(${axis}slicer) configure -state disabled
    13331331                _send "cutplane state 0 $axis [_currentVolumeIds -cutplanes]"
    1334                 $itk_component(${axis}slice) configure -relief raised
    13351332            }
    13361333        }
Note: See TracChangeset for help on using the changeset viewer.