source: tags/1.3.5/gui/scripts/vtkviewer.tcl @ 4754

Last change on this file since 4754 was 4754, checked in by ldelgass, 7 years ago

merge r4668:4669 from trunk

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