source: trunk/gui/scripts/vtkviewer.tcl @ 3833

Last change on this file since 3833 was 3833, checked in by ldelgass, 11 years ago

Fix clients to use vtkvis 1.5 protocol

File size: 94.4 KB
Line 
1# -*- mode: tcl; indent-tabs-mode: nil -*-
2
3# ----------------------------------------------------------------------
4#  COMPONENT: vtkviewer - Vtk drawing object viewer
5#
6#  It connects to the Vtk server running on a rendering farm,
7#  transmits data, and displays the results.
8# ======================================================================
9#  AUTHOR:  Michael McLennan, Purdue University
10#  Copyright (c) 2004-2012  HUBzero Foundation, LLC
11#
12#  See the file "license.terms" for information on usage and
13#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14# ======================================================================
15package require Itk
16package require BLT
17#package require Img
18
19option add *VtkViewer.width 4i widgetDefault
20option add *VtkViewer*cursor crosshair widgetDefault
21option add *VtkViewer.height 4i widgetDefault
22option add *VtkViewer.foreground black widgetDefault
23option add *VtkViewer.controlBackground gray widgetDefault
24option add *VtkViewer.controlDarkBackground #999999 widgetDefault
25option add *VtkViewer.plotBackground black widgetDefault
26option add *VtkViewer.plotForeground white widgetDefault
27option add *VtkViewer.font \
28    -*-helvetica-medium-r-normal-*-12-* widgetDefault
29
30# must use this name -- plugs into Rappture::resources::load
31proc VtkViewer_init_resources {} {
32    Rappture::resources::register \
33        vtkvis_server Rappture::VtkViewer::SetServerList
34}
35
36itcl::class Rappture::VtkViewer {
37    inherit Rappture::VisViewer
38
39    itk_option define -plotforeground plotForeground Foreground ""
40    itk_option define -plotbackground plotBackground Background ""
41
42    constructor { hostlist args } {
43        Rappture::VisViewer::constructor $hostlist
44    } {
45        # defined below
46    }
47    destructor {
48        # defined below
49    }
50    public proc SetServerList { namelist } {
51        Rappture::VisViewer::SetServerList "vtkvis" $namelist
52    }
53    public method add {dataobj {settings ""}}
54    public method camera {option args}
55    public method delete {args}
56    public method disconnect {}
57    public method download {option args}
58    public method get {args}
59    public method isconnected {}
60    public method limits { colormap }
61    public method parameters {title args} {
62        # do nothing
63    }
64    public method scale {args}
65
66    protected method Connect {}
67    protected method CurrentDatasets {args}
68    protected method Disconnect {}
69    protected method DoResize {}
70    protected method DoRotate {}
71    protected method AdjustSetting {what {value ""}}
72    protected method FixSettings { args  }
73    protected method Pan {option x y}
74    protected method Pick {x y}
75    protected method Rebuild {}
76    protected method ReceiveDataset { args }
77    protected method ReceiveImage { args }
78    protected method ReceiveLegend { colormap title vmin vmax size }
79    protected method Rotate {option x y}
80    protected method Zoom {option}
81
82    # The following methods are only used by this class.
83    private method BuildAxisTab {}
84    private method BuildCameraTab {}
85    private method BuildColormap { name styles }
86    private method BuildCutawayTab {}
87    private method BuildDownloadPopup { widget command }
88    private method BuildMoleculeTab {}
89    private method BuildPolydataTab {}
90    private method ChangeColormap { dataobj comp color }
91    private method DrawLegend {}
92    private method EnterLegend { x y }
93    private method EventuallySetAtomScale { args }
94    private method EventuallySetBondScale { args }
95    private method EventuallySetMoleculeOpacity { args }
96    private method EventuallySetMoleculeQuality { args }
97    private method EventuallySetPolydataOpacity { args }
98    private method EventuallyResize { w h }
99    private method EventuallyRotate { q }
100    private method GetImage { args }
101    private method GetVtkData { args }
102    private method IsValidObject { dataobj }
103    private method LeaveLegend {}
104    private method MotionLegend { x y }
105    private method PanCamera {}
106    private method RequestLegend {}
107    private method SetAtomScale {}
108    private method SetBondScale {}
109    private method SetColormap { dataobj comp }
110    private method SetLegendTip { x y }
111    private method SetMoleculeOpacity {}
112    private method SetMoleculeQuality {}
113    private method SetObjectStyle { dataobj comp }
114    private method SetOpacity { dataset }
115    private method SetOrientation { side }
116    private method SetPolydataOpacity {}
117    private method Slice {option args}
118
119    private variable _arcball ""
120    private variable _dlist "";         # list of data objects
121    private variable _obj2datasets
122    private variable _obj2ovride;       # maps dataobj => style override
123    private variable _datasets;         # contains all the dataobj-component
124                                        # datasets in the server
125    private variable _colormaps;        # contains all the colormaps
126                                        # in the server.
127    private variable _dataset2style;    # maps dataobj-component to transfunc
128    private variable _style2datasets;   # maps tf back to list of
129                                        # dataobj-components using the tf.
130    private variable _click;            # info used for rotate operations
131    private variable _limits;           # autoscale min/max for all axes
132    private variable _view;             # view params for 3D view
133    private variable _settings
134    private variable _style;            # Array of current component styles.
135    private variable _initialStyle;     # Array of initial component styles.
136    private variable _axis
137    private variable _reset 1;          # Indicates that server was reset and
138                                        # needs to be reinitialized.
139    private variable _haveGlyphs 0
140    private variable _haveMolecules 0
141    private variable _havePolydata 0
142
143    private variable _first ""     ;# This is the topmost dataset.
144    private variable _start 0
145    private variable _title ""
146
147    common _downloadPopup          ;# download options from popup
148    private common _hardcopy
149    private variable _width 0
150    private variable _height 0
151    private variable _resizePending 0
152    private variable _rotatePending 0
153    private variable _atomScalePending 0
154    private variable _bondScalePending 0
155    private variable _moleculeOpacityPending 0
156    private variable _moleculeQualityPending 0
157    private variable _polydataOpacityPending 0
158    private variable _glyphsOpacityPending 0
159    private variable _updatePending 0;
160    private variable _rotateDelay 150
161    private variable _scaleDelay 100
162}
163
164itk::usual VtkViewer {
165    keep -background -foreground -cursor -font
166    keep -plotbackground -plotforeground
167}
168
169# ----------------------------------------------------------------------
170# CONSTRUCTOR
171# ----------------------------------------------------------------------
172itcl::body Rappture::VtkViewer::constructor {hostlist args} {
173    package require vtk
174    set _serverType "vtkvis"
175
176    # Rebuild event
177    $_dispatcher register !rebuild
178    $_dispatcher dispatch $this !rebuild "[itcl::code $this Rebuild]; list"
179
180    # Resize event
181    $_dispatcher register !resize
182    $_dispatcher dispatch $this !resize "[itcl::code $this DoResize]; list"
183
184    # Update state event
185    $_dispatcher register !update
186    $_dispatcher dispatch $this !update "[itcl::code $this DoUpdate]; list"
187
188    # Rotate event
189    $_dispatcher register !rotate
190    $_dispatcher dispatch $this !rotate "[itcl::code $this DoRotate]; list"
191
192    # Atom scale event
193    $_dispatcher register !atomscale
194    $_dispatcher dispatch $this !atomscale \
195        "[itcl::code $this SetAtomScale]; list"
196
197    # Bond scale event
198    $_dispatcher register !bondscale
199    $_dispatcher dispatch $this !bondscale \
200        "[itcl::code $this SetBondScale]; list"
201
202    # Molecule opacity event
203    $_dispatcher register !moleculeOpacity
204    $_dispatcher dispatch $this !moleculeOpacity \
205        "[itcl::code $this SetMoleculeOpacity]; list"
206
207    # Molecule quality event
208    $_dispatcher register !moleculeQuality
209    $_dispatcher dispatch $this !moleculeQuality \
210        "[itcl::code $this SetMoleculeQuality]; list"
211
212    # Polydata opacity event
213    $_dispatcher register !polydataOpacity
214    $_dispatcher dispatch $this !polydataOpacity \
215        "[itcl::code $this SetPolydataOpacity]; list"
216    #
217    # Populate parser with commands handle incoming requests
218    #
219    $_parser alias image    [itcl::code $this ReceiveImage]
220    $_parser alias dataset  [itcl::code $this ReceiveDataset]
221    $_parser alias legend   [itcl::code $this ReceiveLegend]
222
223    # Initialize the view to some default parameters.
224    array set _view {
225        qw              0.853553
226        qx              -0.353553
227        qy              0.353553
228        qz              0.146447
229        zoom            1.0
230        xpan            0
231        ypan            0
232        ortho           0
233    }
234    set _arcball [blt::arcball create 100 100]
235    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
236    $_arcball quaternion $q
237
238    set _limits(zmin) 0.0
239    set _limits(zmax) 1.0
240
241    array set _axis [subst {
242        xgrid           0
243        ygrid           0
244        zgrid           0
245        xcutaway        0
246        ycutaway        0
247        zcutaway        0
248        xposition       0
249        yposition       0
250        zposition       0
251        xdirection      -1
252        ydirection      -1
253        zdirection      -1
254        visible         1
255        labels          1
256    }]
257    array set _settings [subst {
258        legend                  1
259        glyphs-opacity          100
260        glyphs-wireframe        0
261        polydata-edges          0
262        polydata-lighting       1
263        polydata-opacity        100
264        polydata-palette        rainbow
265        polydata-visible        1
266        polydata-wireframe      0
267        molecule-atomscale      0.3
268        molecule-bondscale      0.075
269        molecule-atoms-visible  1
270        molecule-bonds-visible  1
271        molecule-edges          0
272        molecule-labels         0
273        molecule-lighting       1
274        molecule-opacity        100
275        molecule-palette        elementDefault
276        molecule-quality        1.0
277        molecule-representation "Ball and Stick"
278        molecule-rscale         "covalent"
279        molecule-visible        1
280        molecule-wireframe      0
281    }]
282    itk_component add view {
283        canvas $itk_component(plotarea).view \
284            -highlightthickness 0 -borderwidth 0
285    } {
286        usual
287        ignore -highlightthickness -borderwidth  -background
288    }
289
290    set c $itk_component(view)
291    bind $c <Configure> [itcl::code $this EventuallyResize %w %h]
292    bind $c <4> [itcl::code $this Zoom in 0.25]
293    bind $c <5> [itcl::code $this Zoom out 0.25]
294    bind $c <KeyPress-Left>  [list %W xview scroll 10 units]
295    bind $c <KeyPress-Right> [list %W xview scroll -10 units]
296    bind $c <KeyPress-Up>    [list %W yview scroll 10 units]
297    bind $c <KeyPress-Down>  [list %W yview scroll -10 units]
298    bind $c <Enter> "focus %W"
299    bind $c <Control-F1> [itcl::code $this ToggleConsole]
300
301    # Fix the scrollregion in case we go off screen
302    $c configure -scrollregion [$c bbox all]
303
304    set _map(id) [$c create image 0 0 -anchor nw -image $_image(plot)]
305    set _map(cwidth) -1
306    set _map(cheight) -1
307    set _map(zoom) 1.0
308    set _map(original) ""
309
310    set f [$itk_component(main) component controls]
311    itk_component add reset {
312        button $f.reset -borderwidth 1 -padx 1 -pady 1 \
313            -highlightthickness 0 \
314            -image [Rappture::icon reset-view] \
315            -command [itcl::code $this Zoom reset]
316    } {
317        usual
318        ignore -highlightthickness
319    }
320    pack $itk_component(reset) -side top -padx 2 -pady 2
321    Rappture::Tooltip::for $itk_component(reset) \
322        "Reset the view to the default zoom level"
323
324    itk_component add zoomin {
325        button $f.zin -borderwidth 1 -padx 1 -pady 1 \
326            -highlightthickness 0 \
327            -image [Rappture::icon zoom-in] \
328            -command [itcl::code $this Zoom in]
329    } {
330        usual
331        ignore -highlightthickness
332    }
333    pack $itk_component(zoomin) -side top -padx 2 -pady 2
334    Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
335
336    itk_component add zoomout {
337        button $f.zout -borderwidth 1 -padx 1 -pady 1 \
338            -highlightthickness 0 \
339            -image [Rappture::icon zoom-out] \
340            -command [itcl::code $this Zoom out]
341    } {
342        usual
343        ignore -highlightthickness
344    }
345    pack $itk_component(zoomout) -side top -padx 2 -pady 2
346    Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
347
348    BuildAxisTab
349    #BuildCutawayTab
350    BuildCameraTab
351
352    # Legend
353
354    set _image(legend) [image create photo]
355    itk_component add legend {
356        canvas $itk_component(plotarea).legend -width 50 -highlightthickness 0
357    } {
358        usual
359        ignore -highlightthickness
360        rename -background -plotbackground plotBackground Background
361    }
362
363    # Hack around the Tk panewindow.  The problem is that the requested
364    # size of the 3d view isn't set until an image is retrieved from
365    # the server.  So the panewindow uses the tiny size.
366    set w 10000
367    pack forget $itk_component(view)
368    blt::table $itk_component(plotarea) \
369        0,0 $itk_component(view) -fill both -reqwidth $w
370    blt::table configure $itk_component(plotarea) c1 -resize none
371
372    # Bindings for rotation via mouse
373    bind $itk_component(view) <ButtonPress-1> \
374        [itcl::code $this Rotate click %x %y]
375    bind $itk_component(view) <B1-Motion> \
376        [itcl::code $this Rotate drag %x %y]
377    bind $itk_component(view) <ButtonRelease-1> \
378        [itcl::code $this Rotate release %x %y]
379    bind $itk_component(view) <Configure> \
380        [itcl::code $this EventuallyResize %w %h]
381
382    # Bindings for panning via mouse
383    bind $itk_component(view) <ButtonPress-2> \
384        [itcl::code $this Pan click %x %y]
385    bind $itk_component(view) <B2-Motion> \
386        [itcl::code $this Pan drag %x %y]
387    bind $itk_component(view) <ButtonRelease-2> \
388        [itcl::code $this Pan release %x %y]
389
390    #bind $itk_component(view) <ButtonRelease-3> \
391    #    [itcl::code $this Pick %x %y]
392
393    # Bindings for panning via keyboard
394    bind $itk_component(view) <KeyPress-Left> \
395        [itcl::code $this Pan set -10 0]
396    bind $itk_component(view) <KeyPress-Right> \
397        [itcl::code $this Pan set 10 0]
398    bind $itk_component(view) <KeyPress-Up> \
399        [itcl::code $this Pan set 0 -10]
400    bind $itk_component(view) <KeyPress-Down> \
401        [itcl::code $this Pan set 0 10]
402    bind $itk_component(view) <Shift-KeyPress-Left> \
403        [itcl::code $this Pan set -2 0]
404    bind $itk_component(view) <Shift-KeyPress-Right> \
405        [itcl::code $this Pan set 2 0]
406    bind $itk_component(view) <Shift-KeyPress-Up> \
407        [itcl::code $this Pan set 0 -2]
408    bind $itk_component(view) <Shift-KeyPress-Down> \
409        [itcl::code $this Pan set 0 2]
410
411    # Bindings for zoom via keyboard
412    bind $itk_component(view) <KeyPress-Prior> \
413        [itcl::code $this Zoom out]
414    bind $itk_component(view) <KeyPress-Next> \
415        [itcl::code $this Zoom in]
416
417    bind $itk_component(view) <Enter> "focus $itk_component(view)"
418
419    if {[string equal "x11" [tk windowingsystem]]} {
420        # Bindings for zoom via mouse
421        bind $itk_component(view) <4> [itcl::code $this Zoom out]
422        bind $itk_component(view) <5> [itcl::code $this Zoom in]
423    }
424
425    set _image(download) [image create photo]
426
427    eval itk_initialize $args
428    Connect
429}
430
431# ----------------------------------------------------------------------
432# DESTRUCTOR
433# ----------------------------------------------------------------------
434itcl::body Rappture::VtkViewer::destructor {} {
435    Disconnect
436    $_dispatcher cancel !rebuild
437    $_dispatcher cancel !resize
438    $_dispatcher cancel !rotate
439    image delete $_image(plot)
440    image delete $_image(download)
441    catch { blt::arcball destroy $_arcball }
442}
443
444itcl::body Rappture::VtkViewer::DoResize {} {
445    if { $_width < 2 } {
446        set _width 500
447    }
448    if { $_height < 2 } {
449        set _height 500
450    }
451    set _start [clock clicks -milliseconds]
452    SendCmd "screen size $_width $_height"
453
454    set _resizePending 0
455}
456
457itcl::body Rappture::VtkViewer::DoRotate {} {
458    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
459    SendCmd "camera orient $q"
460    set _rotatePending 0
461}
462
463itcl::body Rappture::VtkViewer::EventuallyResize { w h } {
464    set _width $w
465    set _height $h
466    $_arcball resize $w $h
467    if { !$_resizePending } {
468        set _resizePending 1
469        $_dispatcher event -after 200 !resize
470    }
471}
472
473itcl::body Rappture::VtkViewer::EventuallyRotate { q } {
474    foreach { _view(qw) _view(qx) _view(qy) _view(qz) } $q break
475    if { !$_rotatePending } {
476        set _rotatePending 1
477        $_dispatcher event -after $_rotateDelay !rotate
478    }
479}
480
481itcl::body Rappture::VtkViewer::SetAtomScale {} {
482    SendCmd "molecule ascale $_settings(molecule-atomscale)"
483    set _atomScalePending 0
484}
485
486itcl::body Rappture::VtkViewer::SetBondScale {} {
487    SendCmd "molecule bscale $_settings(molecule-bondscale)"
488    set _bondScalePending 0
489}
490
491itcl::body Rappture::VtkViewer::SetMoleculeOpacity {} {
492    set _moleculeOpacityPending 0
493    foreach dataset [CurrentDatasets -visible $_first] {
494        foreach { dataobj comp } [split $dataset -] break
495        if { [$dataobj type $comp] == "molecule" } {
496            SetOpacity $dataset
497        }
498    }
499}
500
501itcl::body Rappture::VtkViewer::SetMoleculeQuality {} {
502    SendCmd [subst {molecule aquality $_settings(molecule-quality)
503molecule bquality $_settings(molecule-quality)}]
504    set _moleculeQualityPending 0
505}
506
507itcl::body Rappture::VtkViewer::SetPolydataOpacity {} {
508    set _polydataOpacityPending 0
509    foreach dataset [CurrentDatasets -visible $_first] {
510        foreach { dataobj comp } [split $dataset -] break
511        if { [$dataobj type $comp] == "polydata" } {
512            SetOpacity $dataset
513        }
514    }
515}
516
517itcl::body Rappture::VtkViewer::EventuallySetAtomScale { args } {
518    if { !$_atomScalePending } {
519        set _atomScalePending 1
520        $_dispatcher event -after $_scaleDelay !atomscale
521    }
522}
523
524itcl::body Rappture::VtkViewer::EventuallySetBondScale { args } {
525    if { !$_bondScalePending } {
526        set _bondScalePending 1
527        $_dispatcher event -after $_scaleDelay !bondscale
528    }
529}
530
531itcl::body Rappture::VtkViewer::EventuallySetMoleculeOpacity { args } {
532    if { !$_moleculeOpacityPending } {
533        set _moleculeOpacityPending 1
534        $_dispatcher event -after $_scaleDelay !moleculeOpacity
535    }
536}
537
538itcl::body Rappture::VtkViewer::EventuallySetMoleculeQuality { args } {
539    if { !$_moleculeQualityPending } {
540        set _moleculeQualityPending 1
541        $_dispatcher event -after $_scaleDelay !moleculeQuality
542    }
543}
544
545itcl::body Rappture::VtkViewer::EventuallySetPolydataOpacity { args } {
546    if { !$_polydataOpacityPending } {
547        set _polydataOpacityPending 1
548        $_dispatcher event -after $_scaleDelay !polydataOpacity
549    }
550}
551
552# ----------------------------------------------------------------------
553# USAGE: add <dataobj> ?<settings>?
554#
555# Clients use this to add a data object to the plot.  The optional
556# <settings> are used to configure the plot.  Allowed settings are
557# -color, -brightness, -width, -linestyle, and -raise.
558# ----------------------------------------------------------------------
559itcl::body Rappture::VtkViewer::add {dataobj {settings ""}} {
560    array set params {
561        -color auto
562        -width 1
563        -linestyle solid
564        -brightness 0
565        -raise 0
566        -description ""
567        -param ""
568        -type ""
569    }
570    array set params $settings
571    set params(-description) ""
572    set params(-param) ""
573    array set params $settings
574
575    if {$params(-color) == "auto" || $params(-color) == "autoreset"} {
576        # can't handle -autocolors yet
577        set params(-color) black
578    }
579    set pos [lsearch -exact $_dlist $dataobj]
580    if {$pos < 0} {
581        lappend _dlist $dataobj
582    }
583    set _obj2ovride($dataobj-color) $params(-color)
584    set _obj2ovride($dataobj-width) $params(-width)
585    set _obj2ovride($dataobj-raise) $params(-raise)
586    $_dispatcher event -idle !rebuild
587}
588
589# ----------------------------------------------------------------------
590# USAGE: delete ?<dataobj1> <dataobj2> ...?
591#
592#       Clients use this to delete a dataobj from the plot.  If no dataobjs
593#       are specified, then all dataobjs are deleted.  No data objects are
594#       deleted.  They are only removed from the display list.
595#
596# ----------------------------------------------------------------------
597itcl::body Rappture::VtkViewer::delete {args} {
598    if { [llength $args] == 0} {
599        set args $_dlist
600    }
601    # Delete all specified dataobjs
602    set changed 0
603    foreach dataobj $args {
604        set pos [lsearch -exact $_dlist $dataobj]
605        if { $pos < 0 } {
606            continue;                   # Don't know anything about it.
607        }
608        # Remove it from the dataobj list.
609        set _dlist [lreplace $_dlist $pos $pos]
610        array unset _obj2ovride $dataobj-*
611        array unset _settings $dataobj-*
612        set changed 1
613    }
614    # If anything changed, then rebuild the plot
615    if { $changed } {
616        $_dispatcher event -idle !rebuild
617    }
618}
619
620# ----------------------------------------------------------------------
621# USAGE: get ?-objects?
622# USAGE: get ?-visible?
623# USAGE: get ?-image view?
624#
625# Clients use this to query the list of objects being plotted, in
626# order from bottom to top of this result.  The optional "-image"
627# flag can also request the internal images being shown.
628# ----------------------------------------------------------------------
629itcl::body Rappture::VtkViewer::get {args} {
630    if {[llength $args] == 0} {
631        set args "-objects"
632    }
633
634    set op [lindex $args 0]
635    switch -- $op {
636        "-objects" {
637            # put the dataobj list in order according to -raise options
638            set dlist {}
639            foreach dataobj $_dlist {
640                if { ![IsValidObject $dataobj] } {
641                    continue
642                }
643                if {[info exists _obj2ovride($dataobj-raise)] &&
644                    $_obj2ovride($dataobj-raise)} {
645                    set dlist [linsert $dlist 0 $dataobj]
646                } else {
647                    lappend dlist $dataobj
648                }
649            }
650            return $dlist
651        }
652        "-visible" {
653            set dlist {}
654            foreach dataobj $_dlist {
655                if { ![IsValidObject $dataobj] } {
656                    continue
657                }
658                if { ![info exists _obj2ovride($dataobj-raise)] } {
659                    # No setting indicates that the object isn't visible.
660                    continue
661                }
662                # Otherwise use the -raise parameter to put the object to
663                # the front of the list.
664                if { $_obj2ovride($dataobj-raise) } {
665                    set dlist [linsert $dlist 0 $dataobj]
666                } else {
667                    lappend dlist $dataobj
668                }
669            }
670            return $dlist
671        }           
672        -image {
673            if {[llength $args] != 2} {
674                error "wrong # args: should be \"get -image view\""
675            }
676            switch -- [lindex $args end] {
677                view {
678                    return $_image(plot)
679                }
680                default {
681                    error "bad image name \"[lindex $args end]\": should be view"
682                }
683            }
684        }
685        default {
686            error "bad option \"$op\": should be -objects or -image"
687        }
688    }
689}
690
691# ----------------------------------------------------------------------
692# USAGE: scale ?<data1> <data2> ...?
693#
694# Sets the default limits for the overall plot according to the
695# limits of the data for all of the given <data> objects.  This
696# accounts for all objects--even those not showing on the screen.
697# Because of this, the limits are appropriate for all objects as
698# the user scans through data in the ResultSet viewer.
699# ----------------------------------------------------------------------
700itcl::body Rappture::VtkViewer::scale {args} {
701    foreach dataobj $args {
702        foreach comp [$dataobj components] {
703            set type [$dataobj type $comp]
704            switch -- $type {
705                "polydata" {
706                    set _havePolydata 1
707                }
708                "glyphs" {
709                    set _haveGlyphs 1
710                }
711                "molecule" {
712                    set _haveMolecules 1
713                }
714            }
715        }
716        array set bounds [limits $dataobj]
717        if {![info exists _limits(xmin)] || $_limits(xmin) > $bounds(xmin)} {
718            set _limits(xmin) $bounds(xmin)
719        }
720        if {![info exists _limits(xmax)] || $_limits(xmax) < $bounds(xmax)} {
721            set _limits(xmax) $bounds(xmax)
722        }
723
724        if {![info exists _limits(ymin)] || $_limits(ymin) > $bounds(ymin)} {
725            set _limits(ymin) $bounds(ymin)
726        }
727        if {![info exists _limits(ymax)] || $_limits(ymax) < $bounds(ymax)} {
728            set _limits(ymax) $bounds(ymax)
729        }
730
731        if {![info exists _limits(zmin)] || $_limits(zmin) > $bounds(zmin)} {
732            set _limits(zmin) $bounds(zmin)
733        }
734        if {![info exists _limits(zmax)] || $_limits(zmax) < $bounds(zmax)} {
735            set _limits(zmax) $bounds(zmax)
736        }
737    }
738    if { $_havePolydata } {
739        if { ![$itk_component(main) exists "Mesh Settings"] } {
740            if { [catch { BuildPolydataTab } errs ]  != 0 } {
741                puts stderr "errs=$errs"
742            }
743        }
744    }
745    if { $_haveMolecules } {
746        if { ![$itk_component(main) exists "Molecule Settings"]} {
747            if { [catch { BuildMoleculeTab } errs ]  != 0 } {
748                global errorInfo
749                puts stderr "errs=$errs\nerrorInfo=$errorInfo"
750            }
751        }
752    }
753}
754
755# ----------------------------------------------------------------------
756# USAGE: download coming
757# USAGE: download controls <downloadCommand>
758# USAGE: download now
759#
760# Clients use this method to create a downloadable representation
761# of the plot.  Returns a list of the form {ext string}, where
762# "ext" is the file extension (indicating the type of data) and
763# "string" is the data itself.
764# ----------------------------------------------------------------------
765itcl::body Rappture::VtkViewer::download {option args} {
766    switch $option {
767        coming {
768            if {[catch {
769                blt::winop snap $itk_component(plotarea) $_image(download)
770            }]} {
771                $_image(download) configure -width 1 -height 1
772                $_image(download) put #000000
773            }
774        }
775        controls {
776            set popup .vtkviewerdownload
777            if { ![winfo exists .vtkviewerdownload] } {
778                set inner [BuildDownloadPopup $popup [lindex $args 0]]
779            } else {
780                set inner [$popup component inner]
781            }
782            set _downloadPopup(image_controls) $inner.image_frame
783            set num [llength [get]]
784            set num [expr {($num == 1) ? "1 result" : "$num results"}]
785            set word [Rappture::filexfer::label downloadWord]
786            $inner.summary configure -text "$word $num in the following format:"
787            update idletasks            ;# Fix initial sizes
788            return $popup
789        }
790        now {
791            set popup .vtkviewerdownload
792            if {[winfo exists .vtkviewerdownload]} {
793                $popup deactivate
794            }
795            switch -- $_downloadPopup(format) {
796                "image" {
797                    return [$this GetImage [lindex $args 0]]
798                }
799                "vtk" {
800                    return [$this GetVtkData [lindex $args 0]]
801                }
802            }
803            return ""
804        }
805        default {
806            error "bad option \"$option\": should be coming, controls, now"
807        }
808    }
809}
810
811# ----------------------------------------------------------------------
812# USAGE: Connect ?<host:port>,<host:port>...?
813#
814# Clients use this method to establish a connection to a new
815# server, or to reestablish a connection to the previous server.
816# Any existing connection is automatically closed.
817# ----------------------------------------------------------------------
818itcl::body Rappture::VtkViewer::Connect {} {
819    global readyForNextFrame
820    set readyForNextFrame 1
821    set _hosts [GetServerList "vtkvis"]
822    if { "" == $_hosts } {
823        return 0
824    }
825    set result [VisViewer::Connect $_hosts]
826    if { $result } {
827        if { $_reportClientInfo }  {
828            # Tell the server the viewer, hub, user and session.
829            # Do this immediately on connect before buffing any commands
830            global env
831
832            set info {}
833            set user "???"
834            if { [info exists env(USER)] } {
835                set user $env(USER)
836            }
837            set session "???"
838            if { [info exists env(SESSION)] } {
839                set session $env(SESSION)
840            }
841            lappend info "hub" [exec hostname]
842            lappend info "client" "vtkviewer"
843            lappend info "user" $user
844            lappend info "session" $session
845            SendCmd "clientinfo [list $info]"
846        }
847
848        set w [winfo width $itk_component(view)]
849        set h [winfo height $itk_component(view)]
850        EventuallyResize $w $h
851    }
852    return $result
853}
854
855#
856# isconnected --
857#
858#       Indicates if we are currently connected to the visualization server.
859#
860itcl::body Rappture::VtkViewer::isconnected {} {
861    return [VisViewer::IsConnected]
862}
863
864#
865# disconnect --
866#
867itcl::body Rappture::VtkViewer::disconnect {} {
868    Disconnect
869    set _reset 1
870}
871
872#
873# Disconnect --
874#
875#       Clients use this method to disconnect from the current rendering
876#       server.
877#
878itcl::body Rappture::VtkViewer::Disconnect {} {
879    VisViewer::Disconnect
880
881    # disconnected -- no more data sitting on server
882    array unset _datasets
883    array unset _data
884    array unset _colormaps
885    global readyForNextFrame
886    set readyForNextFrame 1
887}
888
889# ----------------------------------------------------------------------
890# USAGE: ReceiveImage -bytes <size> -type <type> -token <token>
891#
892# Invoked automatically whenever the "image" command comes in from
893# the rendering server.  Indicates that binary image data with the
894# specified <size> will follow.
895# ----------------------------------------------------------------------
896itcl::body Rappture::VtkViewer::ReceiveImage { args } {
897    global readyForNextFrame
898    set readyForNextFrame 1
899    array set info {
900        -token "???"
901        -bytes 0
902        -type image
903    }
904    array set info $args
905    set bytes [ReceiveBytes $info(-bytes)]
906    if { $info(-type) == "image" } {
907        if 0 {
908            set f [open "last.ppm" "w"]
909            puts $f $bytes
910            close $f
911        }
912        $_image(plot) configure -data $bytes
913        set time [clock seconds]
914        set date [clock format $time]
915        if { $_start > 0 } {
916            set finish [clock clicks -milliseconds]
917            set _start 0
918        }
919    } elseif { $info(type) == "print" } {
920        set tag $this-print-$info(-token)
921        set _hardcopy($tag) $bytes
922    }
923}
924
925#
926# ReceiveDataset --
927#
928itcl::body Rappture::VtkViewer::ReceiveDataset { args } {
929    if { ![isconnected] } {
930        return
931    }
932    set option [lindex $args 0]
933    switch -- $option {
934        "scalar" {
935            set option [lindex $args 1]
936            switch -- $option {
937                "world" {
938                    foreach { x y z value tag } [lrange $args 2 end] break
939                }
940                "pixel" {
941                    foreach { x y value tag } [lrange $args 2 end] break
942                }
943            }
944        }
945        "vector" {
946            set option [lindex $args 1]
947            switch -- $option {
948                "world" {
949                    foreach { x y z vx vy vz tag } [lrange $args 2 end] break
950                }
951                "pixel" {
952                    foreach { x y vx vy vz tag } [lrange $args 2 end] break
953                }
954            }
955        }
956        "names" {
957            foreach { name } [lindex $args 1] {
958                #puts stderr "Dataset: $name"
959            }
960        }
961        default {
962            error "unknown dataset option \"$option\" from server"
963        }
964    }
965}
966
967# ----------------------------------------------------------------------
968# USAGE: Rebuild
969#
970# Called automatically whenever something changes that affects the
971# data in the widget.  Clears any existing data and rebuilds the
972# widget to display new data.
973# ----------------------------------------------------------------------
974itcl::body Rappture::VtkViewer::Rebuild {} {
975
976    set w [winfo width $itk_component(view)]
977    set h [winfo height $itk_component(view)]
978    if { $w < 2 || $h < 2 } {
979        $_dispatcher event -idle !rebuild
980        return
981    }
982
983    # Turn on buffering of commands to the server.  We don't want to
984    # be preempted by a server disconnect/reconnect (which automatically
985    # generates a new call to Rebuild).   
986    StartBufferingCommands
987
988    if { $_reset } {
989        set _width $w
990        set _height $h
991        $_arcball resize $w $h
992        DoResize
993        FixSettings axis-xgrid axis-ygrid axis-zgrid axis-mode \
994            axis-visible axis-labels
995
996        if { $_havePolydata } {
997            FixSettings polydata-edges polydata-lighting polydata-opacity \
998                polydata-visible polydata-wireframe
999        }
1000        StopBufferingCommands
1001        SendCmd "imgflush"
1002        StartBufferingCommands
1003    }
1004
1005    set _limits(zmin) ""
1006    set _limits(zmax) ""
1007    set _first ""
1008    SendCmd "dataset visible 0"
1009    set count 0
1010    foreach dataobj [get -objects] {
1011        if { [info exists _obj2ovride($dataobj-raise)] &&  $_first == "" } {
1012            set _first $dataobj
1013        }
1014        set _obj2datasets($dataobj) ""
1015        foreach comp [$dataobj components] {
1016            set tag $dataobj-$comp
1017            if { ![info exists _datasets($tag)] } {
1018                set bytes [$dataobj data $comp]
1019                if { $bytes == "" } {
1020                    continue
1021                }
1022                set length [string length $bytes]
1023                if { $_reportClientInfo }  {
1024                    set info {}
1025                    lappend info "tool_id"       [$dataobj hints toolId]
1026                    lappend info "tool_name"     [$dataobj hints toolName]
1027                    lappend info "tool_version"  [$dataobj hints toolRevision]
1028                    lappend info "tool_title"    [$dataobj hints toolTitle]
1029                    lappend info "dataset_label" [$dataobj hints label]
1030                    lappend info "dataset_size"  $length
1031                    lappend info "dataset_tag"   $tag
1032                    SendCmd [list "clientinfo" $info]
1033                }
1034                SendCmd "dataset add $tag data follows $length"
1035                append _outbuf $bytes
1036                set _datasets($tag) 1
1037                SetObjectStyle $dataobj $comp
1038            }
1039            lappend _obj2datasets($dataobj) $tag
1040            if { [info exists _obj2ovride($dataobj-raise)] } {
1041                SendCmd "dataset visible 1 $tag"
1042                SetOpacity $tag
1043            }
1044        }
1045    }
1046    if {"" != $_first} {
1047        set location [$_first hints camera]
1048        if { $location != "" } {
1049            array set view $location
1050        }
1051
1052        foreach axis { x y z } {
1053            set label [$_first hints ${axis}label]
1054            if { $label != "" } {
1055                SendCmd "axis name $axis $label"
1056            }
1057            set units [$_first hints ${axis}units]
1058            if { $units != "" } {
1059                SendCmd "axis units $axis $units"
1060            }
1061        }
1062    }
1063    if { $_reset } {
1064        set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1065        $_arcball quaternion $q
1066        SendCmd "camera reset"
1067        if { $_view(ortho)} {
1068            SendCmd "camera mode ortho"
1069        } else {
1070            SendCmd "camera mode persp"
1071        }
1072        DoRotate
1073        PanCamera
1074        Zoom reset
1075    }
1076
1077    SendCmd "dataset maprange visible"
1078
1079    if { $_haveMolecules } {
1080        #FixSettings molecule-representation
1081    }
1082    set _reset 0
1083    global readyForNextFrame
1084    set readyForNextFrame 0;            # Don't advance to the next frame
1085                                        # until we get an image.
1086
1087    # Actually write the commands to the server socket.  If it fails, we don't
1088    # care.  We're finished here.
1089    blt::busy hold $itk_component(hull)
1090    StopBufferingCommands
1091    blt::busy release $itk_component(hull)
1092}
1093
1094# ----------------------------------------------------------------------
1095# USAGE: CurrentDatasets ?-all -visible? ?dataobjs?
1096#
1097# Returns a list of server IDs for the current datasets being displayed.  This
1098# is normally a single ID, but it might be a list of IDs if the current data
1099# object has multiple components.
1100# ----------------------------------------------------------------------
1101itcl::body Rappture::VtkViewer::CurrentDatasets {args} {
1102    set flag [lindex $args 0]
1103    switch -- $flag {
1104        "-all" {
1105            if { [llength $args] > 1 } {
1106                error "CurrentDatasets: can't specify dataobj after \"-all\""
1107            }
1108            set dlist [get -objects]
1109        }
1110        "-visible" {
1111            if { [llength $args] > 1 } {
1112                set dlist {}
1113                set args [lrange $args 1 end]
1114                foreach dataobj $args {
1115                    if { [info exists _obj2ovride($dataobj-raise)] } {
1116                        lappend dlist $dataobj
1117                    }
1118                }
1119            } else {
1120                set dlist [get -visible]
1121            }
1122        }           
1123        default {
1124            set dlist $args
1125        }
1126    }
1127    set rlist ""
1128    foreach dataobj $dlist {
1129        foreach comp [$dataobj components] {
1130            set tag $dataobj-$comp
1131            if { [info exists _datasets($tag)] && $_datasets($tag) } {
1132                lappend rlist $tag
1133            }
1134        }
1135    }
1136    return $rlist
1137}
1138
1139# ----------------------------------------------------------------------
1140# USAGE: Zoom in
1141# USAGE: Zoom out
1142# USAGE: Zoom reset
1143#
1144# Called automatically when the user clicks on one of the zoom
1145# controls for this widget.  Changes the zoom for the current view.
1146# ----------------------------------------------------------------------
1147itcl::body Rappture::VtkViewer::Zoom {option} {
1148    switch -- $option {
1149        "in" {
1150            set _view(zoom) [expr {$_view(zoom)*1.25}]
1151            SendCmd "camera zoom $_view(zoom)"
1152        }
1153        "out" {
1154            set _view(zoom) [expr {$_view(zoom)*0.8}]
1155            SendCmd "camera zoom $_view(zoom)"
1156        }
1157        "reset" {
1158            array set _view {
1159                qw      0.853553
1160                qx      -0.353553
1161                qy      0.353553
1162                qz      0.146447
1163                zoom    1.0
1164                xpan    0
1165                ypan    0
1166            }
1167            if { $_first != "" } {
1168                set location [$_first hints camera]
1169                if { $location != "" } {
1170                    array set _view $location
1171                }
1172            }
1173            set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1174            $_arcball quaternion $q
1175            DoRotate
1176            SendCmd "camera reset"
1177        }
1178    }
1179}
1180
1181itcl::body Rappture::VtkViewer::PanCamera {} {
1182    set x $_view(xpan)
1183    set y $_view(ypan)
1184    SendCmd "camera pan $x $y"
1185}
1186
1187# ----------------------------------------------------------------------
1188# USAGE: Rotate click <x> <y>
1189# USAGE: Rotate drag <x> <y>
1190# USAGE: Rotate release <x> <y>
1191#
1192# Called automatically when the user clicks/drags/releases in the
1193# plot area.  Moves the plot according to the user's actions.
1194# ----------------------------------------------------------------------
1195itcl::body Rappture::VtkViewer::Rotate {option x y} {
1196    switch -- $option {
1197        "click" {
1198            $itk_component(view) configure -cursor fleur
1199            set _click(x) $x
1200            set _click(y) $y
1201        }
1202        "drag" {
1203            if {[array size _click] == 0} {
1204                Rotate click $x $y
1205            } else {
1206                set w [winfo width $itk_component(view)]
1207                set h [winfo height $itk_component(view)]
1208                if {$w <= 0 || $h <= 0} {
1209                    return
1210                }
1211
1212                if {[catch {
1213                    # this fails sometimes for no apparent reason
1214                    set dx [expr {double($x-$_click(x))/$w}]
1215                    set dy [expr {double($y-$_click(y))/$h}]
1216                }]} {
1217                    return
1218                }
1219                if { $dx == 0 && $dy == 0 } {
1220                    return
1221                }
1222                set q [$_arcball rotate $x $y $_click(x) $_click(y)]
1223                EventuallyRotate $q
1224                set _click(x) $x
1225                set _click(y) $y
1226            }
1227        }
1228        "release" {
1229            Rotate drag $x $y
1230            $itk_component(view) configure -cursor ""
1231            catch {unset _click}
1232        }
1233        default {
1234            error "bad option \"$option\": should be click, drag, release"
1235        }
1236    }
1237}
1238
1239itcl::body Rappture::VtkViewer::Pick {x y} {
1240    foreach tag [CurrentDatasets -visible] {
1241        SendCmd "dataset getscalar pixel $x $y $tag"
1242    }
1243}
1244
1245# ----------------------------------------------------------------------
1246# USAGE: $this Pan click x y
1247#        $this Pan drag x y
1248#        $this Pan release x y
1249#
1250# Called automatically when the user clicks on one of the zoom
1251# controls for this widget.  Changes the zoom for the current view.
1252# ----------------------------------------------------------------------
1253itcl::body Rappture::VtkViewer::Pan {option x y} {
1254    switch -- $option {
1255        "set" {
1256            set w [winfo width $itk_component(view)]
1257            set h [winfo height $itk_component(view)]
1258            set x [expr $x / double($w)]
1259            set y [expr $y / double($h)]
1260            set _view(xpan) [expr $_view(xpan) + $x]
1261            set _view(ypan) [expr $_view(ypan) + $y]
1262            PanCamera
1263            return
1264        }
1265        "click" {
1266            set _click(x) $x
1267            set _click(y) $y
1268            $itk_component(view) configure -cursor hand1
1269        }
1270        "drag" {
1271            if { ![info exists _click(x)] } {
1272                set _click(x) $x
1273            }
1274            if { ![info exists _click(y)] } {
1275                set _click(y) $y
1276            }
1277            set w [winfo width $itk_component(view)]
1278            set h [winfo height $itk_component(view)]
1279            set dx [expr ($_click(x) - $x)/double($w)]
1280            set dy [expr ($_click(y) - $y)/double($h)]
1281            set _click(x) $x
1282            set _click(y) $y
1283            set _view(xpan) [expr $_view(xpan) - $dx]
1284            set _view(ypan) [expr $_view(ypan) - $dy]
1285            PanCamera
1286        }
1287        "release" {
1288            Pan drag $x $y
1289            $itk_component(view) configure -cursor ""
1290        }
1291        default {
1292            error "unknown option \"$option\": should set, click, drag, or release"
1293        }
1294    }
1295}
1296
1297# ----------------------------------------------------------------------
1298# USAGE: FixSettings <what> ?<value>?
1299#
1300# Used internally to update rendering settings whenever parameters
1301# change in the popup settings panel.  Sends the new settings off
1302# to the back end.
1303# ----------------------------------------------------------------------
1304itcl::body Rappture::VtkViewer::FixSettings { args } {
1305    foreach setting $args {
1306        AdjustSetting $setting
1307    }
1308}
1309
1310#
1311# AdjustSetting --
1312#
1313#       Changes/updates a specific setting in the widget.  There are
1314#       usually user-setable option.  Commands are sent to the render
1315#       server.
1316#
1317itcl::body Rappture::VtkViewer::AdjustSetting {what {value ""}} {
1318    if { ![isconnected] } {
1319        return
1320    }
1321    switch -- $what {
1322        "polydata-opacity" {
1323            foreach dataset [CurrentDatasets -visible $_first] {
1324                foreach { dataobj comp } [split $dataset -] break
1325                if { [$dataobj type $comp] == "polydata" } {
1326                    SetOpacity $dataset
1327                }
1328            }
1329        }
1330        "polydata-wireframe" {
1331            set bool $_settings(polydata-wireframe)
1332            foreach dataset [CurrentDatasets -visible $_first] {
1333                foreach { dataobj comp } [split $dataset -] break
1334                set type [$dataobj type $comp]
1335                if { $type == "polydata" } {
1336                    SendCmd "$type wireframe $bool $dataset"
1337                }
1338            }
1339        }
1340        "polydata-visible" {
1341            set bool $_settings(polydata-visible)
1342            foreach dataset [CurrentDatasets -visible $_first] {
1343                foreach { dataobj comp } [split $dataset -] break
1344                set type [$dataobj type $comp]
1345                if { $type == "polydata" } {
1346                    SendCmd "$type visible $bool $dataset"
1347                }
1348            }
1349        }
1350        "polydata-lighting" {
1351            set bool $_settings(polydata-lighting)
1352            foreach dataset [CurrentDatasets -visible $_first] {
1353                foreach { dataobj comp } [split $dataset -] break
1354                set type [$dataobj type $comp]
1355                if { $type == "polydata" } {
1356                    SendCmd "$type lighting $bool $dataset"
1357                }
1358            }
1359        }
1360        "polydata-edges" {
1361            set bool $_settings(polydata-edges)
1362            foreach dataset [CurrentDatasets -visible $_first] {
1363                foreach { dataobj comp } [split $dataset -] break
1364                set type [$dataobj type $comp]
1365                if { $type == "polydata" } {
1366                    SendCmd "$type edges $bool $dataset"
1367                }
1368            }
1369        }
1370        "polydata-palette" {
1371            set palette [$itk_component(meshpalette) value]
1372            set _settings(polydata-palette) $palette
1373            foreach dataset [CurrentDatasets -visible $_first] {
1374                foreach {dataobj comp} [split $dataset -] break
1375                set type [$dataobj type $comp]
1376                if { $type == "polydata" } {
1377                    ChangeColormap $dataobj $comp $palette
1378                    # FIXME: fill in current selected fieldname
1379                    #SendCmd "polydata colormode scalar {} $dataset"
1380                }
1381            }
1382            set _legendPending 1
1383        }
1384        "molecule-opacity" {
1385            set val $_settings(molecule-opacity)
1386            set sval [expr { 0.01 * double($val) }]
1387            foreach dataset [CurrentDatasets -visible $_first] {
1388                foreach { dataobj comp } [split $dataset -] break
1389                if { [$dataobj type $comp] == "molecule" } {
1390                    SetOpacity $dataset
1391                }
1392            }
1393        }
1394        "molecule-wireframe" {
1395            set bool $_settings(molecule-wireframe)
1396            foreach dataset [CurrentDatasets -visible $_first] {
1397                foreach { dataobj comp } [split $dataset -] break
1398                set type [$dataobj type $comp]
1399                if { $type == "molecule" } {
1400                    SendCmd "molecule wireframe $bool $dataset"
1401                }
1402            }
1403        }
1404        "molecule-visible" {
1405            set bool $_settings(molecule-visible)
1406            foreach dataset [CurrentDatasets -visible $_first] {
1407                foreach { dataobj comp } [split $dataset -] break
1408                set type [$dataobj type $comp]
1409                if { $type == "molecule" } {
1410                    SendCmd "molecule visible $bool $dataset"
1411                }
1412            }
1413        }
1414        "molecule-lighting" {
1415            set bool $_settings(molecule-lighting)
1416            foreach dataset [CurrentDatasets -visible $_first] {
1417                foreach { dataobj comp } [split $dataset -] break
1418                set type [$dataobj type $comp]
1419                if { $type == "molecule" } {
1420                    SendCmd "molecule lighting $bool $dataset"
1421                }
1422            }
1423        }
1424        "molecule-edges" {
1425            set bool $_settings(molecule-edges)
1426            foreach dataset [CurrentDatasets -visible $_first] {
1427                foreach { dataobj comp } [split $dataset -] break
1428                set type [$dataobj type $comp]
1429                if { $type == "molecule" } {
1430                    SendCmd "molecule edges $bool $dataset"
1431                }
1432            }
1433        }
1434        "molecule-palette" {
1435            set palette [$itk_component(moleculepalette) value]
1436            set _moelculeSettings(palette) $palette
1437            foreach dataset [CurrentDatasets -visible $_first] {
1438                foreach {dataobj comp} [split $dataset -] break
1439                set type [$dataobj type $comp]
1440                if { $type == "molecule" } {
1441                    ChangeColormap $dataobj $comp $palette
1442                    if { $palette == "elementDefault" } {
1443                        SendCmd "molecule colormode by_elements element $dataset"
1444                    } else {
1445                        # FIXME: Set the chosen scalar field name here
1446                        SendCmd "molecule colormode scalar {} $dataset"
1447                    }
1448                }
1449            }
1450            set _legendPending 1
1451        }
1452        "molecule-representation" {
1453            set value [$itk_component(representation) value]
1454            set value [$itk_component(representation) translate $value]
1455            switch -- $value {
1456                "ballandstick" {
1457                    set _settings(molecule-rscale) covalent
1458                    set _settings(molecule-atoms-visible) 1
1459                    set _settings(molecule-bonds-visible) 1
1460                    set bstyle cylinder
1461                    set _settings(molecule-atomscale) 0.3
1462                    set _settings(molecule-bondscale) 0.075
1463                }
1464                "balls" - "spheres" {
1465                    set _settings(molecule-rscale) covalent
1466                    set _settings(molecule-atoms-visible) 1
1467                    set _settings(molecule-bonds-visible) 0
1468                    set bstyle cylinder
1469                    set _settings(molecule-atomscale) 0.3
1470                    set _settings(molecule-bondscale) 0.075
1471                }
1472                "sticks" {
1473                    set _settings(molecule-rscale) none
1474                    set _settings(molecule-atoms-visible) 1
1475                    set _settings(molecule-bonds-visible) 1
1476                    set bstyle cylinder
1477                    set _settings(molecule-atomscale) 0.075
1478                    set _settings(molecule-bondscale) 0.075
1479                }
1480                "spacefilling" {
1481                    set _settings(molecule-rscale) van_der_waals
1482                    set _settings(molecule-atoms-visible) 1
1483                    set _settings(molecule-bonds-visible) 0
1484                    set bstyle cylinder
1485                    set _settings(molecule-atomscale) 1.0
1486                    set _settings(molecule-bondscale) 0.075
1487                }
1488                "rods"  {
1489                    set _settings(molecule-rscale) none
1490                    set _settings(molecule-atoms-visible) 1
1491                    set _settings(molecule-bonds-visible) 1
1492                    set bstyle cylinder
1493                    set _settings(molecule-atomscale) 0.1
1494                    set _settings(molecule-bondscale) 0.1
1495                }
1496                "wireframe" - "lines" {
1497                    set _settings(molecule-rscale) none
1498                    set _settings(molecule-atoms-visible) 0
1499                    set _settings(molecule-bonds-visible) 1
1500                    set bstyle line
1501                    set _settings(molecule-atomscale) 1.0
1502                    set _settings(molecule-bondscale) 1.0
1503                }
1504                default {
1505                    error "unknown representation $value"
1506                }
1507            }
1508            $itk_component(rscale) value [$itk_component(rscale) label $_settings(molecule-rscale)]
1509            switch -- $value {
1510                "ballandstick" - "balls" - "spheres" {
1511                    $itk_component(rscale) configure -state normal
1512                }
1513                default {
1514                    $itk_component(rscale) configure -state disabled
1515                }
1516            }
1517            foreach dataset [CurrentDatasets -visible $_first] {
1518                foreach {dataobj comp} [split $dataset -] break
1519                set type [$dataobj type $comp]
1520                if { $type == "molecule" } {
1521                    SendCmd [subst {molecule rscale $_settings(molecule-rscale) $dataset
1522molecule ascale $_settings(molecule-atomscale) $dataset
1523molecule bscale $_settings(molecule-bondscale) $dataset
1524molecule bstyle $bstyle $dataset
1525molecule atoms $_settings(molecule-atoms-visible) $dataset
1526molecule bonds $_settings(molecule-bonds-visible) $dataset}]
1527                }
1528            }
1529        }
1530        "molecule-rscale" {
1531            set value [$itk_component(rscale) value]
1532            set value [$itk_component(rscale) translate $value]
1533            set _settings(molecule-rscale) $value
1534            foreach dataset [CurrentDatasets -visible $_first] {
1535                foreach {dataobj comp} [split $dataset -] break
1536                set type [$dataobj type $comp]
1537                if { $type == "molecule" } {
1538                    SendCmd [subst {molecule rscale $_settings(molecule-rscale) $dataset}]
1539                }
1540            }
1541        }
1542        "molecule-labels" {
1543            set bool $_settings(molecule-labels)
1544            foreach dataset [CurrentDatasets -visible $_first] {
1545               foreach { dataobj comp } [split $dataset -] break
1546               set type [$dataobj type $comp]
1547               if { $type == "molecule" } {
1548                   SendCmd "molecule labels $bool $dataset"
1549               }
1550            }
1551        }
1552        "axis-visible" {
1553            set bool $_axis(visible)
1554            SendCmd "axis visible all $bool"
1555        }
1556        "axis-labels" {
1557            set bool $_axis(labels)
1558            SendCmd "axis labels all $bool"
1559        }
1560        "axis-xgrid" {
1561            set bool $_axis(xgrid)
1562            SendCmd "axis grid x $bool"
1563        }
1564        "axis-ygrid" {
1565            set bool $_axis(ygrid)
1566            SendCmd "axis grid y $bool"
1567        }
1568        "axis-zgrid" {
1569            set bool $_axis(zgrid)
1570            SendCmd "axis grid z $bool"
1571        }
1572        "axis-mode" {
1573            set mode [$itk_component(axismode) value]
1574            set mode [$itk_component(axismode) translate $mode]
1575            SendCmd "axis flymode $mode"
1576        }
1577        "axis-xcutaway" - "axis-ycutaway" - "axis-zcutaway" {
1578            set axis [string range $what 5 5]
1579            set bool $_axis(${axis}cutaway)
1580            if { $bool } {
1581                set pos [expr $_axis(${axis}position) * 0.01]
1582                set dir $_axis(${axis}direction)
1583                $itk_component(${axis}CutScale) configure -state normal \
1584                    -troughcolor white
1585                SendCmd "renderer clipplane $axis $pos $dir"
1586            } else {
1587                $itk_component(${axis}CutScale) configure -state disabled \
1588                    -troughcolor grey82
1589                SendCmd "renderer clipplane $axis 1 -1"
1590            }
1591        }
1592        "axis-xposition" - "axis-yposition" - "axis-zposition" -
1593        "axis-xdirection" - "axis-ydirection" - "axis-zdirection" {
1594            set axis [string range $what 5 5]
1595            #set dir $_axis(${axis}direction)
1596            set pos [expr $_axis(${axis}position) * 0.01]
1597            SendCmd "renderer clipplane ${axis} $pos -1"
1598        }
1599        default {
1600            error "don't know how to fix $what"
1601        }
1602    }
1603}
1604
1605#
1606# RequestLegend --
1607#
1608#       Request a new legend from the server.  The size of the legend
1609#       is determined from the height of the canvas.  It will be rotated
1610#       to be vertical when drawn.
1611#
1612itcl::body Rappture::VtkViewer::RequestLegend {} {
1613    set font "Arial 8"
1614    set lineht [font metrics $font -linespace]
1615    set c $itk_component(legend)
1616    set w 12
1617    set h [expr {$_height - 2 * ($lineht + 2)}]
1618    if { $h < 1} {
1619        return
1620    }
1621    # Set the legend on the first dataset.
1622    foreach dataset [CurrentDatasets -visible] {
1623        foreach {dataobj comp} [split $dataset -] break
1624        if { [info exists _dataset2style($dataset)] } {
1625            SendCmd "legend $_dataset2style($dataset) vmag {} {} $w $h 0"
1626            break;
1627        }
1628    }
1629}
1630
1631#
1632# ChangeColormap --
1633#
1634itcl::body Rappture::VtkViewer::ChangeColormap {dataobj comp color} {
1635    set tag $dataobj-$comp
1636    if { ![info exist _style($tag)] } {
1637        error "no initial colormap"
1638    }
1639    array set style $_style($tag)
1640    set style(-color) $color
1641    set _style($tag) [array get style]
1642    SetColormap $dataobj $comp
1643}
1644
1645#
1646# SetColormap --
1647#
1648itcl::body Rappture::VtkViewer::SetColormap { dataobj comp } {
1649    array set style {
1650        -color BCGYR
1651        -levels 6
1652        -opacity 1.0
1653    }
1654    if {[$dataobj type $comp] == "molecule"} {
1655        set style(-color) elementDefault
1656    }
1657    set tag $dataobj-$comp
1658    if { ![info exists _initialStyle($tag)] } {
1659        # Save the initial component style.
1660        set _initialStyle($tag) [$dataobj style $comp]
1661    }
1662
1663    # Override defaults with initial style defined in xml.
1664    array set style $_initialStyle($tag)
1665
1666    if { ![info exists _style($tag)] } {
1667        set _style($tag) [array get style]
1668    }
1669    # Override initial style with current style.
1670    array set style $_style($tag)
1671
1672    if { $style(-color) == "elementDefault" } {
1673        set name "$style(-color)"
1674    } else {
1675        set name "$style(-color):$style(-levels):$style(-opacity)"
1676    }
1677    if { ![info exists _colormaps($name)] } {
1678        BuildColormap $name [array get style]
1679        set _colormaps($name) 1
1680    }
1681    if { ![info exists _dataset2style($tag)] ||
1682         $_dataset2style($tag) != $name } {
1683        set _dataset2style($tag) $name
1684        switch -- [$dataobj type $comp] {
1685            "polydata" {
1686                SendCmd "polydata colormap $name $tag"
1687            }
1688            "glyphs" {
1689                SendCmd "glyphs colormap $name $tag"
1690            }
1691            "molecule" {
1692                SendCmd "molecule colormap $name $tag"
1693            }
1694        }
1695    }
1696}
1697
1698#
1699# BuildColormap --
1700#
1701itcl::body Rappture::VtkViewer::BuildColormap { name styles } {
1702    if { $name ==  "elementDefault" } {
1703        return
1704    }
1705    array set style $styles
1706    set cmap [ColorsToColormap $style(-color)]
1707    if { [llength $cmap] == 0 } {
1708        set cmap "0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0"
1709    }
1710    if { ![info exists _settings(polydata-opacity)] } {
1711        set _settings(polydata-opacity) $style(-opacity)
1712    }
1713    set max $_settings(polydata-opacity)
1714
1715    set wmap "0.0 1.0 1.0 1.0"
1716    SendCmd "colormap add $name { $cmap } { $wmap }"
1717}
1718
1719# ----------------------------------------------------------------------
1720# CONFIGURATION OPTION: -plotbackground
1721# ----------------------------------------------------------------------
1722itcl::configbody Rappture::VtkViewer::plotbackground {
1723    if { [isconnected] } {
1724        foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
1725        SendCmd "screen bgcolor $r $g $b"
1726    }
1727}
1728
1729# ----------------------------------------------------------------------
1730# CONFIGURATION OPTION: -plotforeground
1731# ----------------------------------------------------------------------
1732itcl::configbody Rappture::VtkViewer::plotforeground {
1733    if { [isconnected] } {
1734        foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
1735        #fix this!
1736        #SendCmd "color background $r $g $b"
1737    }
1738}
1739
1740itcl::body Rappture::VtkViewer::limits { dataobj } {
1741    foreach comp [$dataobj components] {
1742        set tag $dataobj-$comp
1743        if { ![info exists _limits($tag)] } {
1744            set data [$dataobj data $comp]
1745            if { $data == "" } {
1746                continue
1747            }
1748            set tmpfile file[pid].vtk
1749            set f [open "$tmpfile" "w"]
1750            fconfigure $f -translation binary -encoding binary
1751            puts $f $data
1752            close $f
1753            set reader [vtkDataSetReader $tag-xvtkDataSetReader]
1754            $reader SetFileName $tmpfile
1755set debug 0
1756            if {$debug} {
1757                # Only needed for debug output below
1758                $reader ReadAllNormalsOn
1759                $reader ReadAllTCoordsOn
1760                $reader ReadAllScalarsOn
1761                $reader ReadAllColorScalarsOn
1762                $reader ReadAllVectorsOn
1763                $reader ReadAllTensorsOn
1764                $reader ReadAllFieldsOn
1765            }
1766            $reader Update
1767            file delete $tmpfile
1768            set output [$reader GetOutput]
1769            set _limits($tag) [$output GetBounds]
1770            if {$debug} {
1771                puts stderr "\#scalars=[$reader GetNumberOfScalarsInFile]"
1772                puts stderr "\#vectors=[$reader GetNumberOfVectorsInFile]"
1773                puts stderr "\#tensors=[$reader GetNumberOfTensorsInFile]"
1774                puts stderr "\#normals=[$reader GetNumberOfNormalsInFile]"
1775                puts stderr "\#tcoords=[$reader GetNumberOfTCoordsInFile]"
1776                puts stderr "\#fielddata=[$reader GetNumberOfFieldDataInFile]"
1777                puts stderr "fielddataname=[$reader GetFieldDataNameInFile 0]"
1778                set pointData [$output GetPointData]
1779                if { $pointData != ""} {
1780                    puts stderr "point \#arrays=[$pointData GetNumberOfArrays]"
1781                    puts stderr "point \#components=[$pointData GetNumberOfComponents]"
1782                    puts stderr "point \#tuples=[$pointData GetNumberOfTuples]"
1783                    puts stderr "point scalars=[$pointData GetScalars]"
1784                    puts stderr "point vectors=[$pointData GetVectors]"
1785                }
1786                set cellData [$output GetCellData]
1787                if { $cellData != ""} {
1788                    puts stderr "cell \#arrays=[$cellData GetNumberOfArrays]"
1789                    puts stderr "cell \#components=[$cellData GetNumberOfComponents]"
1790                    puts stderr "cell \#tuples=[$cellData GetNumberOfTuples]"
1791                    puts stderr "cell scalars=[$cellData GetScalars]"
1792                    puts stderr "cell vectors=[$cellData GetVectors]"
1793                }
1794                set fieldData [$output GetFieldData]
1795                if { $fieldData != ""} {
1796                    puts stderr "field \#arrays=[$fieldData GetNumberOfArrays]"
1797                    puts stderr "field \#components=[$fieldData GetNumberOfComponents]"
1798                    puts stderr "field \#tuples=[$fieldData GetNumberOfTuples]"
1799                }
1800            }
1801            rename $output ""
1802            rename $reader ""
1803        }
1804        foreach { xMin xMax yMin yMax zMin zMax} $_limits($tag) break
1805        if {![info exists limits(xmin)] || $limits(xmin) > $xMin} {
1806            set limits(xmin) $xMin
1807        }
1808        if {![info exists limits(xmax)] || $limits(xmax) < $xMax} {
1809            set limits(xmax) $xMax
1810        }
1811        if {![info exists limits(ymin)] || $limits(ymin) > $yMin} {
1812            set limits(ymin) $xMin
1813        }
1814        if {![info exists limits(ymax)] || $limits(ymax) < $yMax} {
1815            set limits(ymax) $yMax
1816        }
1817        if {![info exists limits(zmin)] || $limits(zmin) > $zMin} {
1818            set limits(zmin) $zMin
1819        }
1820        if {![info exists limits(zmax)] || $limits(zmax) < $zMax} {
1821            set limits(zmax) $zMax
1822        }
1823    }
1824    return [array get limits]
1825}
1826
1827itcl::body Rappture::VtkViewer::BuildPolydataTab {} {
1828
1829    set fg [option get $itk_component(hull) font Font]
1830    #set bfg [option get $itk_component(hull) boldFont Font]
1831
1832    set inner [$itk_component(main) insert end \
1833        -title "Mesh Settings" \
1834        -icon [Rappture::icon mesh]]
1835    $inner configure -borderwidth 4
1836
1837    checkbutton $inner.mesh \
1838        -text "Show Mesh" \
1839        -variable [itcl::scope _settings(polydata-visible)] \
1840        -command [itcl::code $this AdjustSetting polydata-visible] \
1841        -font "Arial 9" -anchor w
1842
1843    checkbutton $inner.wireframe \
1844        -text "Show Wireframe" \
1845        -variable [itcl::scope _settings(polydata-wireframe)] \
1846        -command [itcl::code $this AdjustSetting polydata-wireframe] \
1847        -font "Arial 9" -anchor w
1848
1849    checkbutton $inner.lighting \
1850        -text "Enable Lighting" \
1851        -variable [itcl::scope _settings(polydata-lighting)] \
1852        -command [itcl::code $this AdjustSetting polydata-lighting] \
1853        -font "Arial 9" -anchor w
1854
1855    checkbutton $inner.edges \
1856        -text "Show Edges" \
1857        -variable [itcl::scope _settings(polydata-edges)] \
1858        -command [itcl::code $this AdjustSetting polydata-edges] \
1859        -font "Arial 9" -anchor w
1860
1861    label $inner.palette_l -text "Palette" -font "Arial 9" -anchor w
1862    itk_component add meshpalette {
1863        Rappture::Combobox $inner.palette -width 10 -editable no
1864    }
1865    $inner.palette choices insert end \
1866        "BCGYR"              "BCGYR"            \
1867        "BGYOR"              "BGYOR"            \
1868        "blue"               "blue"             \
1869        "blue-to-brown"      "blue-to-brown"    \
1870        "blue-to-orange"     "blue-to-orange"   \
1871        "blue-to-grey"       "blue-to-grey"     \
1872        "green-to-magenta"   "green-to-magenta" \
1873        "greyscale"          "greyscale"        \
1874        "nanohub"            "nanohub"          \
1875        "rainbow"            "rainbow"          \
1876        "spectral"           "spectral"         \
1877        "ROYGB"              "ROYGB"            \
1878        "RYGCB"              "RYGCB"            \
1879        "brown-to-blue"      "brown-to-blue"    \
1880        "grey-to-blue"       "grey-to-blue"     \
1881        "orange-to-blue"     "orange-to-blue"   
1882
1883    $itk_component(meshpalette) value "BCGYR"
1884    bind $inner.palette <<Value>> \
1885        [itcl::code $this AdjustSetting polydata-palette]
1886
1887    label $inner.opacity_l -text "Opacity" -font "Arial 9" -anchor w
1888    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
1889        -variable [itcl::scope _settings(polydata-opacity)] \
1890        -width 10 \
1891        -showvalue off \
1892        -command [itcl::code $this AdjustSetting polydata-opacity]
1893    $inner.opacity set $_settings(polydata-opacity)
1894
1895    blt::table $inner \
1896        0,0 $inner.mesh      -cspan 2  -anchor w -pady 2 \
1897        1,0 $inner.wireframe -cspan 2  -anchor w -pady 2 \
1898        2,0 $inner.lighting  -cspan 2  -anchor w -pady 2 \
1899        3,0 $inner.edges     -cspan 2  -anchor w -pady 2 \
1900        4,0 $inner.opacity_l -anchor w -pady 2 \
1901        4,1 $inner.opacity   -fill x   -pady 2 \
1902        5,0 $inner.palette_l -anchor w -pady 2 \
1903        5,1 $inner.palette   -fill x   -pady 2 
1904
1905    blt::table configure $inner r* c* -resize none
1906    blt::table configure $inner r7 c1 -resize expand
1907}
1908
1909itcl::body Rappture::VtkViewer::BuildAxisTab {} {
1910
1911    set fg [option get $itk_component(hull) font Font]
1912    #set bfg [option get $itk_component(hull) boldFont Font]
1913
1914    set inner [$itk_component(main) insert end \
1915        -title "Axis Settings" \
1916        -icon [Rappture::icon axis1]]
1917    $inner configure -borderwidth 4
1918
1919    checkbutton $inner.visible \
1920        -text "Show Axes" \
1921        -variable [itcl::scope _axis(visible)] \
1922        -command [itcl::code $this AdjustSetting axis-visible] \
1923        -font "Arial 9"
1924
1925    checkbutton $inner.labels \
1926        -text "Show Axis Labels" \
1927        -variable [itcl::scope _axis(labels)] \
1928        -command [itcl::code $this AdjustSetting axis-labels] \
1929        -font "Arial 9"
1930
1931    checkbutton $inner.gridx \
1932        -text "Show X Grid" \
1933        -variable [itcl::scope _axis(xgrid)] \
1934        -command [itcl::code $this AdjustSetting axis-xgrid] \
1935        -font "Arial 9"
1936    checkbutton $inner.gridy \
1937        -text "Show Y Grid" \
1938        -variable [itcl::scope _axis(ygrid)] \
1939        -command [itcl::code $this AdjustSetting axis-ygrid] \
1940        -font "Arial 9"
1941    checkbutton $inner.gridz \
1942        -text "Show Z Grid" \
1943        -variable [itcl::scope _axis(zgrid)] \
1944        -command [itcl::code $this AdjustSetting axis-zgrid] \
1945        -font "Arial 9"
1946
1947    label $inner.mode_l -text "Mode" -font "Arial 9"
1948
1949    itk_component add axismode {
1950        Rappture::Combobox $inner.mode -width 10 -editable no
1951    }
1952    $inner.mode choices insert end \
1953        "static_triad"    "static" \
1954        "closest_triad"   "closest" \
1955        "furthest_triad"  "furthest" \
1956        "outer_edges"     "outer"         
1957    $itk_component(axismode) value "static"
1958    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting axis-mode]
1959
1960    blt::table $inner \
1961        0,0 $inner.visible -anchor w -cspan 2 \
1962        1,0 $inner.labels  -anchor w -cspan 2 \
1963        2,0 $inner.gridx   -anchor w -cspan 2 \
1964        3,0 $inner.gridy   -anchor w -cspan 2 \
1965        4,0 $inner.gridz   -anchor w -cspan 2 \
1966        5,0 $inner.mode_l  -anchor w -cspan 2 -padx { 2 0 } \
1967        6,0 $inner.mode    -fill x   -cspan 2
1968
1969    blt::table configure $inner r* c* -resize none
1970    blt::table configure $inner r7 c1 -resize expand
1971}
1972
1973itcl::body Rappture::VtkViewer::BuildCameraTab {} {
1974    set inner [$itk_component(main) insert end \
1975        -title "Camera Settings" \
1976        -icon [Rappture::icon camera]]
1977    $inner configure -borderwidth 4
1978
1979    label $inner.view_l -text "view" -font "Arial 9"
1980    set f [frame $inner.view]
1981    foreach side { front back left right top bottom } {
1982        button $f.$side  -image [Rappture::icon view$side] \
1983            -command [itcl::code $this SetOrientation $side]
1984        Rappture::Tooltip::for $f.$side "Change the view to $side"
1985        pack $f.$side -side left
1986    }
1987
1988    blt::table $inner \
1989        0,0 $inner.view_l -anchor e -pady 2 \
1990        0,1 $inner.view -anchor w -pady 2
1991
1992    set labels { qx qy qz qw xpan ypan zoom }
1993    set row 1
1994    foreach tag $labels {
1995        label $inner.${tag}label -text $tag -font "Arial 9"
1996        entry $inner.${tag} -font "Arial 9"  -bg white \
1997            -textvariable [itcl::scope _view($tag)]
1998        bind $inner.${tag} <KeyPress-Return> \
1999            [itcl::code $this camera set ${tag}]
2000        blt::table $inner \
2001            $row,0 $inner.${tag}label -anchor e -pady 2 \
2002            $row,1 $inner.${tag} -anchor w -pady 2
2003        blt::table configure $inner r$row -resize none
2004        incr row
2005    }
2006    checkbutton $inner.ortho \
2007        -text "Orthographic Projection" \
2008        -variable [itcl::scope _view(ortho)] \
2009        -command [itcl::code $this camera set ortho] \
2010        -font "Arial 9"
2011    blt::table $inner \
2012            $row,0 $inner.ortho -cspan 2 -anchor w -pady 2
2013    blt::table configure $inner r$row -resize none
2014    incr row
2015
2016    blt::table configure $inner c* r* -resize none
2017    blt::table configure $inner c2 -resize expand
2018    blt::table configure $inner r$row -resize expand
2019}
2020
2021itcl::body Rappture::VtkViewer::BuildCutawayTab {} {
2022
2023    set fg [option get $itk_component(hull) font Font]
2024   
2025    set inner [$itk_component(main) insert end \
2026        -title "Cutaway Along Axis" \
2027        -icon [Rappture::icon cutbutton]]
2028
2029    $inner configure -borderwidth 4
2030
2031    # X-value slicer...
2032    itk_component add xCutButton {
2033        Rappture::PushButton $inner.xbutton \
2034            -onimage [Rappture::icon x-cutplane] \
2035            -offimage [Rappture::icon x-cutplane] \
2036            -command [itcl::code $this AdjustSetting axis-xcutaway] \
2037            -variable [itcl::scope _axis(xcutaway)]
2038    }
2039    Rappture::Tooltip::for $itk_component(xCutButton) \
2040        "Toggle the X-axis cutaway on/off"
2041
2042    itk_component add xCutScale {
2043        ::scale $inner.xval -from 100 -to 0 \
2044            -width 10 -orient vertical -showvalue yes \
2045            -borderwidth 1 -highlightthickness 0 \
2046            -command [itcl::code $this Slice move x] \
2047            -variable [itcl::scope _axis(xposition)]
2048    } {
2049        usual
2050        ignore -borderwidth -highlightthickness
2051    }
2052    # Set the default cutaway value before disabling the scale.
2053    $itk_component(xCutScale) set 100
2054    $itk_component(xCutScale) configure -state disabled
2055    Rappture::Tooltip::for $itk_component(xCutScale) \
2056        "@[itcl::code $this Slice tooltip x]"
2057
2058    itk_component add xDirButton {
2059        Rappture::PushButton $inner.xdir \
2060            -onimage [Rappture::icon arrow-down] \
2061            -onvalue -1 \
2062            -offimage [Rappture::icon arrow-up] \
2063            -offvalue 1 \
2064            -command [itcl::code $this AdjustSetting axis-xdirection] \
2065            -variable [itcl::scope _axis(xdirection)]
2066    }
2067    set _axis(xdirection) -1
2068    Rappture::Tooltip::for $itk_component(xDirButton) \
2069        "Toggle the direction of the X-axis cutaway"
2070
2071    # Y-value slicer...
2072    itk_component add yCutButton {
2073        Rappture::PushButton $inner.ybutton \
2074            -onimage [Rappture::icon y-cutplane] \
2075            -offimage [Rappture::icon y-cutplane] \
2076            -command [itcl::code $this AdjustSetting axis-ycutaway] \
2077            -variable [itcl::scope _axis(ycutaway)]
2078    }
2079    Rappture::Tooltip::for $itk_component(yCutButton) \
2080        "Toggle the Y-axis cutaway on/off"
2081
2082    itk_component add yCutScale {
2083        ::scale $inner.yval -from 100 -to 0 \
2084            -width 10 -orient vertical -showvalue yes \
2085            -borderwidth 1 -highlightthickness 0 \
2086            -command [itcl::code $this Slice move y] \
2087            -variable [itcl::scope _axis(yposition)]
2088    } {
2089        usual
2090        ignore -borderwidth -highlightthickness
2091    }
2092    Rappture::Tooltip::for $itk_component(yCutScale) \
2093        "@[itcl::code $this Slice tooltip y]"
2094    # Set the default cutaway value before disabling the scale.
2095    $itk_component(yCutScale) set 100
2096    $itk_component(yCutScale) configure -state disabled
2097
2098    itk_component add yDirButton {
2099        Rappture::PushButton $inner.ydir \
2100            -onimage [Rappture::icon arrow-down] \
2101            -onvalue -1 \
2102            -offimage [Rappture::icon arrow-up] \
2103            -offvalue 1 \
2104            -command [itcl::code $this AdjustSetting axis-ydirection] \
2105            -variable [itcl::scope _axis(ydirection)]
2106    }
2107    Rappture::Tooltip::for $itk_component(yDirButton) \
2108        "Toggle the direction of the Y-axis cutaway"
2109    set _axis(ydirection) -1
2110
2111    # Z-value slicer...
2112    itk_component add zCutButton {
2113        Rappture::PushButton $inner.zbutton \
2114            -onimage [Rappture::icon z-cutplane] \
2115            -offimage [Rappture::icon z-cutplane] \
2116            -command [itcl::code $this AdjustSetting axis-zcutaway] \
2117            -variable [itcl::scope _axis(zcutaway)]
2118    }
2119    Rappture::Tooltip::for $itk_component(zCutButton) \
2120        "Toggle the Z-axis cutaway on/off"
2121
2122    itk_component add zCutScale {
2123        ::scale $inner.zval -from 100 -to 0 \
2124            -width 10 -orient vertical -showvalue yes \
2125            -borderwidth 1 -highlightthickness 0 \
2126            -command [itcl::code $this Slice move z] \
2127            -variable [itcl::scope _axis(zposition)]
2128    } {
2129        usual
2130        ignore -borderwidth -highlightthickness
2131    }
2132    $itk_component(zCutScale) set 100
2133    $itk_component(zCutScale) configure -state disabled
2134    #$itk_component(zCutScale) configure -state disabled
2135    Rappture::Tooltip::for $itk_component(zCutScale) \
2136        "@[itcl::code $this Slice tooltip z]"
2137
2138    itk_component add zDirButton {
2139        Rappture::PushButton $inner.zdir \
2140            -onimage [Rappture::icon arrow-down] \
2141            -onvalue -1 \
2142            -offimage [Rappture::icon arrow-up] \
2143            -offvalue 1 \
2144            -command [itcl::code $this AdjustSetting axis-zdirection] \
2145            -variable [itcl::scope _axis(zdirection)]
2146    }
2147    set _axis(zdirection) -1
2148    Rappture::Tooltip::for $itk_component(zDirButton) \
2149        "Toggle the direction of the Z-axis cutaway"
2150
2151    blt::table $inner \
2152        0,0 $itk_component(xCutButton)  -anchor e -padx 2 -pady 2 \
2153        1,0 $itk_component(xCutScale)   -fill y \
2154        0,1 $itk_component(yCutButton)  -anchor e -padx 2 -pady 2 \
2155        1,1 $itk_component(yCutScale)   -fill y \
2156        0,2 $itk_component(zCutButton)  -anchor e -padx 2 -pady 2 \
2157        1,2 $itk_component(zCutScale)   -fill y \
2158
2159    blt::table configure $inner r* c* -resize none
2160    blt::table configure $inner r1 c3 -resize expand
2161}
2162
2163itcl::body Rappture::VtkViewer::BuildMoleculeTab {} {
2164    set fg [option get $itk_component(hull) font Font]
2165
2166    set inner [$itk_component(main) insert end \
2167        -title "Molecule Settings" \
2168        -icon [Rappture::icon molecule]]
2169    $inner configure -borderwidth 4
2170
2171    checkbutton $inner.molecule \
2172        -text "Show Molecule" \
2173        -variable [itcl::scope _settings(molecule-visible)] \
2174        -command [itcl::code $this AdjustSetting molecule-visible] \
2175        -font "Arial 9"
2176
2177    checkbutton $inner.label \
2178        -text "Show Atom Labels" \
2179        -variable [itcl::scope _settings(molecule-labels)] \
2180        -command [itcl::code $this AdjustSetting molecule-labels] \
2181        -font "Arial 9"
2182
2183    checkbutton $inner.wireframe \
2184        -text "Show Wireframe" \
2185        -variable [itcl::scope _settings(molecule-wireframe)] \
2186        -command [itcl::code $this AdjustSetting molecule-wireframe] \
2187        -font "Arial 9"
2188
2189    checkbutton $inner.lighting \
2190        -text "Enable Lighting" \
2191        -variable [itcl::scope _settings(molecule-lighting)] \
2192        -command [itcl::code $this AdjustSetting molecule-lighting] \
2193        -font "Arial 9"
2194
2195    checkbutton $inner.edges \
2196        -text "Show Edges" \
2197        -variable [itcl::scope _settings(molecule-edges)] \
2198        -command [itcl::code $this AdjustSetting molecule-edges] \
2199        -font "Arial 9"
2200
2201    label $inner.rep_l -text "Molecule Representation" \
2202        -font "Arial 9"
2203
2204    itk_component add representation {
2205        Rappture::Combobox $inner.rep -width 20 -editable no
2206    }
2207    $inner.rep choices insert end \
2208        "ballandstick"  "Ball and Stick" \
2209        "spheres"       "Spheres"        \
2210        "sticks"        "Sticks"         \
2211        "rods"          "Rods"           \
2212        "wireframe"     "Wireframe"      \
2213        "spacefilling"  "Space Filling"
2214
2215    bind $inner.rep <<Value>> \
2216        [itcl::code $this AdjustSetting molecule-representation]
2217    $inner.rep value "Ball and Stick"
2218
2219    label $inner.rscale_l -text "Atom Radii" \
2220        -font "Arial 9"
2221
2222    itk_component add rscale {
2223        Rappture::Combobox $inner.rscale -width 20 -editable no
2224    }
2225    $inner.rscale choices insert end \
2226        "atomic"        "Atomic"   \
2227        "covalent"      "Covalent" \
2228        "van_der_waals" "VDW"      \
2229        "none"          "Constant"
2230
2231    bind $inner.rscale <<Value>> \
2232        [itcl::code $this AdjustSetting molecule-rscale]
2233    $inner.rscale value "Covalent"
2234
2235    label $inner.palette_l -text "Palette" -font "Arial 9"
2236    itk_component add moleculepalette {
2237        Rappture::Combobox $inner.palette -width 10 -editable no
2238    }
2239    $inner.palette choices insert end \
2240        "elementDefault"     "elementDefault"   \
2241        "BCGYR"              "BCGYR"            \
2242        "BGYOR"              "BGYOR"            \
2243        "blue"               "blue"             \
2244        "blue-to-brown"      "blue-to-brown"    \
2245        "blue-to-orange"     "blue-to-orange"   \
2246        "blue-to-grey"       "blue-to-grey"     \
2247        "green-to-magenta"   "green-to-magenta" \
2248        "greyscale"          "greyscale"        \
2249        "nanohub"            "nanohub"          \
2250        "rainbow"            "rainbow"          \
2251        "spectral"           "spectral"         \
2252        "ROYGB"              "ROYGB"            \
2253        "RYGCB"              "RYGCB"            \
2254        "brown-to-blue"      "brown-to-blue"    \
2255        "grey-to-blue"       "grey-to-blue"     \
2256        "orange-to-blue"     "orange-to-blue"   
2257
2258    $itk_component(moleculepalette) value "elementDefault"
2259    bind $inner.palette <<Value>> \
2260        [itcl::code $this AdjustSetting molecule-palette]
2261
2262    checkbutton $inner.labels -text "Show labels on atoms" \
2263        -command [itcl::code $this labels update] \
2264        -variable [itcl::scope _settings(molecule-labels)] \
2265        -font "Arial 9"
2266    Rappture::Tooltip::for $inner.labels \
2267        "Display atom symbol and serial number."
2268
2269    checkbutton $inner.rock -text "Rock molecule back and forth" \
2270        -variable [itcl::scope _settings(molecule-rock)] \
2271        -font "Arial 9"
2272    Rappture::Tooltip::for $inner.rock \
2273        "Rotate the object back and forth around the y-axis."
2274
2275    checkbutton $inner.cell -text "Parallelepiped" \
2276        -font "Arial 9"
2277    $inner.cell select
2278
2279    label $inner.atomscale_l -text "Atom Scale" -font "Arial 9"
2280    ::scale $inner.atomscale -width 15 -font "Arial 7" \
2281        -from 0.025 -to 2.0 -resolution 0.025 -label "" \
2282        -showvalue true -orient horizontal \
2283        -command [itcl::code $this EventuallySetAtomScale] \
2284        -variable [itcl::scope _settings(molecule-atomscale)]
2285    $inner.atomscale set $_settings(molecule-atomscale)
2286    Rappture::Tooltip::for $inner.atomscale \
2287        "Adjust relative scale of atoms (spheres or balls)."
2288
2289    label $inner.bondscale_l -text "Bond Scale" -font "Arial 9"
2290    ::scale $inner.bondscale -width 15 -font "Arial 7" \
2291        -from 0.005 -to 0.3 -resolution 0.005 -label "" \
2292        -showvalue true -orient horizontal \
2293        -command [itcl::code $this EventuallySetBondScale] \
2294        -variable [itcl::scope _settings(molecule-bondscale)]
2295    Rappture::Tooltip::for $inner.bondscale \
2296        "Adjust scale of bonds (sticks)."
2297    $inner.bondscale set $_settings(molecule-bondscale)
2298
2299    label $inner.opacity_l -text "Opacity" -font "Arial 9"
2300    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
2301        -variable [itcl::scope _settings(molecule-opacity)] \
2302        -width 15 -font "Arial 7" \
2303        -showvalue on \
2304        -command [itcl::code $this EventuallySetMoleculeOpacity]
2305
2306    label $inner.quality_l -text "Quality" -font "Arial 9"
2307    ::scale $inner.quality -width 15 -font "Arial 7" \
2308        -from 0.0 -to 10.0 -resolution 0.1 -label "" \
2309        -showvalue true -orient horizontal \
2310        -command [itcl::code $this EventuallySetMoleculeQuality] \
2311        -variable [itcl::scope _settings(molecule-quality)]
2312    Rappture::Tooltip::for $inner.quality \
2313        "Adjust tesselation quality"
2314    $inner.quality set $_settings(molecule-quality)
2315
2316    blt::table $inner \
2317        0,0 $inner.molecule     -anchor w -pady {1 0} \
2318        1,0 $inner.label        -anchor w -pady {1 0} \
2319        2,0 $inner.edges        -anchor w -pady {1 0} \
2320        3,0 $inner.rep_l        -anchor w -pady { 2 0 } \
2321        4,0 $inner.rep          -fill x    -pady 2 \
2322        5,0 $inner.rscale_l     -anchor w -pady { 2 0 } \
2323        6,0 $inner.rscale       -fill x    -pady 2 \
2324        7,0 $inner.palette_l    -anchor w  -pady 0 \
2325        8,0 $inner.palette      -fill x    -padx 2 \
2326        9,0 $inner.atomscale_l  -anchor w -pady {3 0} \
2327        10,0 $inner.atomscale   -fill x    -padx 2 \
2328        11,0 $inner.bondscale_l -anchor w -pady {3 0} \
2329        12,0 $inner.bondscale   -fill x   -padx 2 \
2330        13,0 $inner.opacity_l   -anchor w -pady {3 0} \
2331        14,0 $inner.opacity     -fill x    -padx 2 \
2332        15,0 $inner.quality_l   -anchor w -pady {3 0} \
2333        16,0 $inner.quality     -fill x    -padx 2
2334   
2335    blt::table configure $inner r* -resize none
2336    blt::table configure $inner r17 -resize expand
2337}
2338
2339#
2340#  camera --
2341#
2342itcl::body Rappture::VtkViewer::camera {option args} {
2343    switch -- $option {
2344        "show" {
2345            puts [array get _view]
2346        }
2347        "set" {
2348            set who [lindex $args 0]
2349            set x $_view($who)
2350            set code [catch { string is double $x } result]
2351            if { $code != 0 || !$result } {
2352                return
2353            }
2354            switch -- $who {
2355                "ortho" {
2356                    if {$_view(ortho)} {
2357                        SendCmd "camera mode ortho"
2358                    } else {
2359                        SendCmd "camera mode persp"
2360                    }
2361                }
2362                "xpan" - "ypan" {
2363                    PanCamera
2364                }
2365                "qx" - "qy" - "qz" - "qw" {
2366                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
2367                    $_arcball quaternion $q
2368                    EventuallyRotate $q
2369                }
2370                "zoom" {
2371                    SendCmd "camera zoom $_view(zoom)"
2372                }
2373            }
2374        }
2375    }
2376}
2377
2378itcl::body Rappture::VtkViewer::GetVtkData { args } {
2379    set bytes ""
2380    foreach dataobj [get] {
2381        foreach comp [$dataobj components] {
2382            set tag $dataobj-$comp
2383            set contents [$dataobj data $comp]
2384            append bytes "$contents\n"
2385        }
2386    }
2387    return [list .vtk $bytes]
2388}
2389
2390itcl::body Rappture::VtkViewer::GetImage { args } {
2391    if { [image width $_image(download)] > 0 &&
2392         [image height $_image(download)] > 0 } {
2393        set bytes [$_image(download) data -format "jpeg -quality 100"]
2394        set bytes [Rappture::encoding::decode -as b64 $bytes]
2395        return [list .jpg $bytes]
2396    }
2397    return ""
2398}
2399
2400itcl::body Rappture::VtkViewer::BuildDownloadPopup { popup command } {
2401    Rappture::Balloon $popup \
2402        -title "[Rappture::filexfer::label downloadWord] as..."
2403    set inner [$popup component inner]
2404    label $inner.summary -text "" -anchor w
2405    radiobutton $inner.vtk_button -text "VTK data file" \
2406        -variable [itcl::scope _downloadPopup(format)] \
2407        -font "Helvetica 9 " \
2408        -value vtk 
2409    Rappture::Tooltip::for $inner.vtk_button "Save as VTK data file."
2410    radiobutton $inner.image_button -text "Image File" \
2411        -variable [itcl::scope _downloadPopup(format)] \
2412        -value image
2413    Rappture::Tooltip::for $inner.image_button \
2414        "Save as digital image."
2415
2416    button $inner.ok -text "Save" \
2417        -highlightthickness 0 -pady 2 -padx 3 \
2418        -command $command \
2419        -compound left \
2420        -image [Rappture::icon download]
2421
2422    button $inner.cancel -text "Cancel" \
2423        -highlightthickness 0 -pady 2 -padx 3 \
2424        -command [list $popup deactivate] \
2425        -compound left \
2426        -image [Rappture::icon cancel]
2427
2428    blt::table $inner \
2429        0,0 $inner.summary -cspan 2  \
2430        1,0 $inner.vtk_button -anchor w -cspan 2 -padx { 4 0 } \
2431        2,0 $inner.image_button -anchor w -cspan 2 -padx { 4 0 } \
2432        4,1 $inner.cancel -width .9i -fill y \
2433        4,0 $inner.ok -padx 2 -width .9i -fill y
2434    blt::table configure $inner r3 -height 4
2435    blt::table configure $inner r4 -pady 4
2436    raise $inner.image_button
2437    $inner.vtk_button invoke
2438    return $inner
2439}
2440
2441itcl::body Rappture::VtkViewer::SetObjectStyle { dataobj comp } {
2442    # Parse style string.
2443    set tag $dataobj-$comp
2444    set type [$dataobj type $comp]
2445    set style [$dataobj style $comp]
2446    if { $dataobj != $_first } {
2447        set settings(-wireframe) 1
2448    }
2449    switch -- $type {
2450        "glyphs" {
2451            array set settings {
2452                -color \#FFFFFF
2453                -gscale 1
2454                -edges 0
2455                -edgecolor black
2456                -linewidth 1.0
2457                -opacity 1.0
2458                -wireframe 0
2459                -lighting 1
2460                -visible 1
2461            }
2462            set shape [$dataobj shape $comp]
2463            array set settings $style
2464            SendCmd "glyphs add $shape $tag"
2465            SendCmd "glyphs normscale 0 $tag"
2466            SendCmd "glyphs gscale $settings(-gscale) $tag"
2467            SendCmd "glyphs wireframe $settings(-wireframe) $tag"
2468            SendCmd "glyphs color [Color2RGB $settings(-color)] $tag"
2469            #SendCmd "glyphs colormode constant {} $tag"
2470            SendCmd "glyphs gorient 0 {} $tag"
2471            SendCmd "glyphs smode vcomp {} $tag"
2472            SendCmd "glyphs opacity $settings(-opacity) $tag"
2473            SendCmd "glyphs visible $settings(-visible) $tag"
2474            set _settings(glyphs-wireframe) $settings(-wireframe)
2475        }
2476        "molecule" {
2477            SendCmd "molecule add $tag"
2478            set _haveMolecules 1
2479        }
2480        "polydata" {
2481            array set settings {
2482                -color \#FFFFFF
2483                -edges 1
2484                -edgecolor black
2485                -linewidth 1.0
2486                -opacity 1.0
2487                -wireframe 0
2488                -lighting 1
2489                -visible 1
2490            }
2491            array set settings $style
2492            SendCmd "polydata add $tag"
2493            SendCmd "polydata visible $settings(-visible) $tag"
2494            set _settings(polydata-visible) $settings(-visible)
2495            SendCmd "polydata edges $settings(-edges) $tag"
2496            set _settings(polydata-edges) $settings(-edges)
2497            SendCmd "polydata color [Color2RGB $settings(-color)] $tag"
2498            #SendCmd "polydata colormode constant {} $tag"
2499            SendCmd "polydata lighting $settings(-lighting) $tag"
2500            set _settings(polydata-lighting) $settings(-lighting)
2501            SendCmd "polydata linecolor [Color2RGB $settings(-edgecolor)] $tag"
2502            SendCmd "polydata linewidth $settings(-linewidth) $tag"
2503            SendCmd "polydata opacity $settings(-opacity) $tag"
2504            set _settings(polydata-opacity) [expr 100.0 * $settings(-opacity)]
2505            SendCmd "polydata wireframe $settings(-wireframe) $tag"
2506            set _settings(polydata-wireframe) $settings(-wireframe)
2507            set havePolyData 1
2508        }
2509    }
2510    SetColormap $dataobj $comp
2511}
2512
2513itcl::body Rappture::VtkViewer::IsValidObject { dataobj } {
2514    if {[catch {$dataobj isa Rappture::Drawing} valid] != 0 || !$valid} {
2515        return 0
2516    }
2517    return 1
2518}
2519
2520# ----------------------------------------------------------------------
2521# USAGE: ReceiveLegend <colormap> <title> <vmin> <vmax> <size>
2522#
2523# Invoked automatically whenever the "legend" command comes in from
2524# the rendering server.  Indicates that binary image data with the
2525# specified <size> will follow.
2526# ----------------------------------------------------------------------
2527itcl::body Rappture::VtkViewer::ReceiveLegend { colormap title vmin vmax size } {
2528    set _limits(vmin) $vmin
2529    set _limits(vmax) $vmax
2530    set _title $title
2531    if { [IsConnected] } {
2532        set bytes [ReceiveBytes $size]
2533        if { ![info exists _image(legend)] } {
2534            set _image(legend) [image create photo]
2535        }
2536        $_image(legend) configure -data $bytes
2537        DrawLegend
2538    }
2539}
2540
2541#
2542# DrawLegend --
2543#
2544#       Draws the legend in it's own canvas which resides to the right
2545#       of the contour plot area.
2546#
2547itcl::body Rappture::VtkViewer::DrawLegend {} {
2548    set c $itk_component(view)
2549    set w [winfo width $c]
2550    set h [winfo height $c]
2551    set font "Arial 8"
2552    set lineht [font metrics $font -linespace]
2553   
2554    if { $_settings(legend) } {
2555        set x [expr $w - 2]
2556        if { [$c find withtag "legend"] == "" } {
2557            $c create image $x [expr {$lineht+2}] \
2558                -anchor ne \
2559                -image $_image(legend) -tags "colormap legend"
2560            $c create text $x 2 \
2561                -anchor ne \
2562                -fill $itk_option(-plotforeground) -tags "vmax legend" \
2563                -font $font
2564            $c create text $x [expr {$h-2}] \
2565                -anchor se \
2566                -fill $itk_option(-plotforeground) -tags "vmin legend" \
2567                -font $font
2568            #$c bind colormap <Enter> [itcl::code $this EnterLegend %x %y]
2569            $c bind colormap <Leave> [itcl::code $this LeaveLegend]
2570            $c bind colormap <Motion> [itcl::code $this MotionLegend %x %y]
2571        }
2572        # Reset the item coordinates according the current size of the plot.
2573        $c coords colormap $x [expr {$lineht+2}]
2574        if { $_limits(vmin) != "" } {
2575            $c itemconfigure vmin -text [format %g $_limits(vmin)]
2576        }
2577        if { $_limits(vmax) != "" } {
2578            $c itemconfigure vmax -text [format %g $_limits(vmax)]
2579        }
2580        $c coords vmin $x [expr {$h-2}]
2581        $c coords vmax $x 2
2582    }
2583}
2584
2585#
2586# EnterLegend --
2587#
2588itcl::body Rappture::VtkViewer::EnterLegend { x y } {
2589    SetLegendTip $x $y
2590}
2591
2592#
2593# MotionLegend --
2594#
2595itcl::body Rappture::VtkViewer::MotionLegend { x y } {
2596    Rappture::Tooltip::tooltip cancel
2597    set c $itk_component(view)
2598    SetLegendTip $x $y
2599}
2600
2601#
2602# LeaveLegend --
2603#
2604itcl::body Rappture::VtkViewer::LeaveLegend { } {
2605    Rappture::Tooltip::tooltip cancel
2606    .rappturetooltip configure -icon ""
2607}
2608
2609#
2610# SetLegendTip --
2611#
2612itcl::body Rappture::VtkViewer::SetLegendTip { x y } {
2613    set c $itk_component(view)
2614    set w [winfo width $c]
2615    set h [winfo height $c]
2616    set font "Arial 8"
2617    set lineht [font metrics $font -linespace]
2618   
2619    set imgHeight [image height $_image(legend)]
2620    set coords [$c coords colormap]
2621    set imgX [expr $w - [image width $_image(legend)] - 2]
2622    set imgY [expr $y - $lineht - 2]
2623
2624    # Make a swatch of the selected color
2625    if { [catch { $_image(legend) get 10 $imgY } pixel] != 0 } {
2626        return
2627    }
2628    if { ![info exists _image(swatch)] } {
2629        set _image(swatch) [image create photo -width 24 -height 24]
2630    }
2631    set color [eval format "\#%02x%02x%02x" $pixel]
2632    $_image(swatch) put black  -to 0 0 23 23
2633    $_image(swatch) put $color -to 1 1 22 22
2634    .rappturetooltip configure -icon $_image(swatch)
2635
2636    # Compute the value of the point
2637    set t [expr 1.0 - (double($imgY) / double($imgHeight-1))]
2638    set value [expr $t * ($_limits(vmax) - $_limits(vmin)) + $_limits(vmin)]
2639    set tipx [expr $x + 15]
2640    set tipy [expr $y - 5]
2641    Rappture::Tooltip::text $c "$_title $value"
2642    Rappture::Tooltip::tooltip show $c +$tipx,+$tipy   
2643}
2644
2645# ----------------------------------------------------------------------
2646# USAGE: Slice move x|y|z <newval>
2647#
2648# Called automatically when the user drags the slider to move the
2649# cut plane that slices 3D data.  Gets the current value from the
2650# slider and moves the cut plane to the appropriate point in the
2651# data set.
2652# ----------------------------------------------------------------------
2653itcl::body Rappture::VtkViewer::Slice {option args} {
2654    switch -- $option {
2655        "move" {
2656            set axis [lindex $args 0]
2657            set oldval $_axis(${axis}position)
2658            set newval [lindex $args 1]
2659            if {[llength $args] != 2} {
2660                error "wrong # args: should be \"Slice move x|y|z newval\""
2661            }
2662            set newpos [expr {0.01*$newval}]
2663            SendCmd "renderer clipplane $axis $newpos -1"
2664        }
2665        "tooltip" {
2666            set axis [lindex $args 0]
2667            set val [$itk_component(${axis}CutScale) get]
2668            return "Move the [string toupper $axis] cut plane.\nCurrently:  $axis = $val%"
2669        }
2670        default {
2671            error "bad option \"$option\": should be axis, move, or tooltip"
2672        }
2673    }
2674}
2675
2676itcl::body Rappture::VtkViewer::SetOrientation { side } {
2677    array set positions {
2678        front "1 0 0 0"
2679        back  "0 0 1 0"
2680        left  "0.707107 0 -0.707107 0"
2681        right "0.707107 0 0.707107 0"
2682        top   "0.707107 -0.707107 0 0"
2683        bottom "0.707107 0.707107 0 0"
2684    }
2685    foreach name { qw qx qy qz } value $positions($side) {
2686        set _view($name) $value
2687    }
2688    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
2689    $_arcball quaternion $q
2690    SendCmd "camera orient $q"
2691    SendCmd "camera reset"
2692    set _view(xpan) 0
2693    set _view(ypan) 0
2694    set _view(zoom) 1.0
2695}
2696
2697itcl::body Rappture::VtkViewer::SetOpacity { dataset } {
2698    foreach {dataobj comp} [split $dataset -] break
2699    set type [$dataobj type $comp]
2700    set val $_settings($type-opacity)
2701    set sval [expr { 0.01 * double($val) }]
2702    if { !$_obj2ovride($dataobj-raise) } {
2703        # This is wrong.  Need to figure out why raise isn't set with 1
2704        #set sval [expr $sval * .6]
2705    }
2706    SendCmd "$type opacity $sval $dataset"
2707}
Note: See TracBrowser for help on using the repository browser.