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

Last change on this file since 3847 was 3847, checked in by gah, 8 years ago

added code for computing bonds: seems to add more bonds than pymol or vmd

File size: 95.0 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 "hub" [exec hostname]
843            lappend info "client" "vtkviewer"
844            lappend info "user" $user
845            lappend info "session" $session
846            SendCmd "clientinfo [list $info]"
847        }
848
849        set w [winfo width $itk_component(view)]
850        set h [winfo height $itk_component(view)]
851        EventuallyResize $w $h
852    }
853    return $result
854}
855
856#
857# isconnected --
858#
859#       Indicates if we are currently connected to the visualization server.
860#
861itcl::body Rappture::VtkViewer::isconnected {} {
862    return [VisViewer::IsConnected]
863}
864
865#
866# disconnect --
867#
868itcl::body Rappture::VtkViewer::disconnect {} {
869    Disconnect
870    set _reset 1
871}
872
873#
874# Disconnect --
875#
876#       Clients use this method to disconnect from the current rendering
877#       server.
878#
879itcl::body Rappture::VtkViewer::Disconnect {} {
880    VisViewer::Disconnect
881
882    # disconnected -- no more data sitting on server
883    array unset _datasets
884    array unset _data
885    array unset _colormaps
886    global readyForNextFrame
887    set readyForNextFrame 1
888}
889
890# ----------------------------------------------------------------------
891# USAGE: ReceiveImage -bytes <size> -type <type> -token <token>
892#
893# Invoked automatically whenever the "image" command comes in from
894# the rendering server.  Indicates that binary image data with the
895# specified <size> will follow.
896# ----------------------------------------------------------------------
897itcl::body Rappture::VtkViewer::ReceiveImage { args } {
898    global readyForNextFrame
899    set readyForNextFrame 1
900    array set info {
901        -token "???"
902        -bytes 0
903        -type image
904    }
905    array set info $args
906    set bytes [ReceiveBytes $info(-bytes)]
907    if { $info(-type) == "image" } {
908        if 0 {
909            set f [open "last.ppm" "w"]
910            fconfigure $f -encoding binary
911            puts -nonewline $f $bytes
912            close $f
913        }
914        $_image(plot) configure -data $bytes
915        set time [clock seconds]
916        set date [clock format $time]
917        if { $_start > 0 } {
918            set finish [clock clicks -milliseconds]
919            set _start 0
920        }
921    } elseif { $info(type) == "print" } {
922        set tag $this-print-$info(-token)
923        set _hardcopy($tag) $bytes
924    }
925}
926
927#
928# ReceiveDataset --
929#
930itcl::body Rappture::VtkViewer::ReceiveDataset { args } {
931    if { ![isconnected] } {
932        return
933    }
934    set option [lindex $args 0]
935    switch -- $option {
936        "scalar" {
937            set option [lindex $args 1]
938            switch -- $option {
939                "world" {
940                    foreach { x y z value tag } [lrange $args 2 end] break
941                }
942                "pixel" {
943                    foreach { x y value tag } [lrange $args 2 end] break
944                }
945            }
946        }
947        "vector" {
948            set option [lindex $args 1]
949            switch -- $option {
950                "world" {
951                    foreach { x y z vx vy vz tag } [lrange $args 2 end] break
952                }
953                "pixel" {
954                    foreach { x y vx vy vz tag } [lrange $args 2 end] break
955                }
956            }
957        }
958        "names" {
959            foreach { name } [lindex $args 1] {
960                #puts stderr "Dataset: $name"
961            }
962        }
963        default {
964            error "unknown dataset option \"$option\" from server"
965        }
966    }
967}
968
969# ----------------------------------------------------------------------
970# USAGE: Rebuild
971#
972# Called automatically whenever something changes that affects the
973# data in the widget.  Clears any existing data and rebuilds the
974# widget to display new data.
975# ----------------------------------------------------------------------
976itcl::body Rappture::VtkViewer::Rebuild {} {
977
978    set w [winfo width $itk_component(view)]
979    set h [winfo height $itk_component(view)]
980    if { $w < 2 || $h < 2 } {
981        $_dispatcher event -idle !rebuild
982        return
983    }
984
985    # Turn on buffering of commands to the server.  We don't want to
986    # be preempted by a server disconnect/reconnect (which automatically
987    # generates a new call to Rebuild).   
988    StartBufferingCommands
989
990    if { $_reset } {
991        set _width $w
992        set _height $h
993        $_arcball resize $w $h
994        DoResize
995        FixSettings axis-xgrid axis-ygrid axis-zgrid axis-mode \
996            axis-visible axis-labels
997
998        if { $_havePolydata } {
999            FixSettings polydata-edges polydata-lighting polydata-opacity \
1000                polydata-visible polydata-wireframe
1001        }
1002        StopBufferingCommands
1003        SendCmd "imgflush"
1004        StartBufferingCommands
1005    }
1006
1007    set _limits(zmin) ""
1008    set _limits(zmax) ""
1009    set _first ""
1010    SendCmd "dataset visible 0"
1011    set count 0
1012    foreach dataobj [get -objects] {
1013        if { [info exists _obj2ovride($dataobj-raise)] &&  $_first == "" } {
1014            set _first $dataobj
1015        }
1016        set _obj2datasets($dataobj) ""
1017        foreach comp [$dataobj components] {
1018            set tag $dataobj-$comp
1019            if { ![info exists _datasets($tag)] } {
1020                set bytes [$dataobj data $comp]
1021                if { $bytes == "" } {
1022                    continue
1023                }
1024                set length [string length $bytes]
1025                if { $_reportClientInfo }  {
1026                    set info {}
1027                    lappend info "tool_id"       [$dataobj hints toolId]
1028                    lappend info "tool_name"     [$dataobj hints toolName]
1029                    lappend info "tool_version"  [$dataobj hints toolRevision]
1030                    lappend info "tool_title"    [$dataobj hints toolTitle]
1031                    lappend info "dataset_label" [$dataobj hints label]
1032                    lappend info "dataset_size"  $length
1033                    lappend info "dataset_tag"   $tag
1034                    SendCmd [list "clientinfo" $info]
1035                }
1036                SendCmd "dataset add $tag data follows $length"
1037                append _outbuf $bytes
1038                set _datasets($tag) 1
1039                SetObjectStyle $dataobj $comp
1040            }
1041            lappend _obj2datasets($dataobj) $tag
1042            if { [info exists _obj2ovride($dataobj-raise)] } {
1043                SendCmd "dataset visible 1 $tag"
1044                SetOpacity $tag
1045            }
1046        }
1047    }
1048    if {"" != $_first} {
1049        set location [$_first hints camera]
1050        if { $location != "" } {
1051            array set view $location
1052        }
1053
1054        foreach axis { x y z } {
1055            set label [$_first hints ${axis}label]
1056            if { $label != "" } {
1057                SendCmd "axis name $axis $label"
1058            }
1059            set units [$_first hints ${axis}units]
1060            if { $units != "" } {
1061                SendCmd "axis units $axis $units"
1062            }
1063        }
1064    }
1065    if { $_reset } {
1066        set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1067        $_arcball quaternion $q
1068        SendCmd "camera reset"
1069        if { $_view(ortho)} {
1070            SendCmd "camera mode ortho"
1071        } else {
1072            SendCmd "camera mode persp"
1073        }
1074        DoRotate
1075        PanCamera
1076        Zoom reset
1077    }
1078
1079    if { $_haveMolecules } {
1080        #FixSettings molecule-representation
1081    }
1082    set _reset 0
1083    global readyForNextFrame
1084    set readyForNextFrame 0;            # Don't advance to the next frame
1085                                        # until we get an image.
1086
1087    # Actually write the commands to the server socket.  If it fails, we don't
1088    # care.  We're finished here.
1089    blt::busy hold $itk_component(hull)
1090    StopBufferingCommands
1091    blt::busy release $itk_component(hull)
1092}
1093
1094# ----------------------------------------------------------------------
1095# USAGE: CurrentDatasets ?-all -visible? ?dataobjs?
1096#
1097# Returns a list of server IDs for the current datasets being displayed.  This
1098# is normally a single ID, but it might be a list of IDs if the current data
1099# object has multiple components.
1100# ----------------------------------------------------------------------
1101itcl::body Rappture::VtkViewer::CurrentDatasets {args} {
1102    set flag [lindex $args 0]
1103    switch -- $flag {
1104        "-all" {
1105            if { [llength $args] > 1 } {
1106                error "CurrentDatasets: can't specify dataobj after \"-all\""
1107            }
1108            set dlist [get -objects]
1109        }
1110        "-visible" {
1111            if { [llength $args] > 1 } {
1112                set dlist {}
1113                set args [lrange $args 1 end]
1114                foreach dataobj $args {
1115                    if { [info exists _obj2ovride($dataobj-raise)] } {
1116                        lappend dlist $dataobj
1117                    }
1118                }
1119            } else {
1120                set dlist [get -visible]
1121            }
1122        }           
1123        default {
1124            set dlist $args
1125        }
1126    }
1127    set rlist ""
1128    foreach dataobj $dlist {
1129        foreach comp [$dataobj components] {
1130            set tag $dataobj-$comp
1131            if { [info exists _datasets($tag)] && $_datasets($tag) } {
1132                lappend rlist $tag
1133            }
1134        }
1135    }
1136    return $rlist
1137}
1138
1139# ----------------------------------------------------------------------
1140# USAGE: Zoom in
1141# USAGE: Zoom out
1142# USAGE: Zoom reset
1143#
1144# Called automatically when the user clicks on one of the zoom
1145# controls for this widget.  Changes the zoom for the current view.
1146# ----------------------------------------------------------------------
1147itcl::body Rappture::VtkViewer::Zoom {option} {
1148    switch -- $option {
1149        "in" {
1150            set _view(zoom) [expr {$_view(zoom)*1.25}]
1151            SendCmd "camera zoom $_view(zoom)"
1152        }
1153        "out" {
1154            set _view(zoom) [expr {$_view(zoom)*0.8}]
1155            SendCmd "camera zoom $_view(zoom)"
1156        }
1157        "reset" {
1158            array set _view {
1159                qw      0.853553
1160                qx      -0.353553
1161                qy      0.353553
1162                qz      0.146447
1163                zoom    1.0
1164                xpan    0
1165                ypan    0
1166            }
1167            if { $_first != "" } {
1168                set location [$_first hints camera]
1169                if { $location != "" } {
1170                    array set _view $location
1171                }
1172            }
1173            set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1174            $_arcball quaternion $q
1175            DoRotate
1176            SendCmd "camera reset"
1177        }
1178    }
1179}
1180
1181itcl::body Rappture::VtkViewer::PanCamera {} {
1182    set x $_view(xpan)
1183    set y $_view(ypan)
1184    SendCmd "camera pan $x $y"
1185}
1186
1187# ----------------------------------------------------------------------
1188# USAGE: Rotate click <x> <y>
1189# USAGE: Rotate drag <x> <y>
1190# USAGE: Rotate release <x> <y>
1191#
1192# Called automatically when the user clicks/drags/releases in the
1193# plot area.  Moves the plot according to the user's actions.
1194# ----------------------------------------------------------------------
1195itcl::body Rappture::VtkViewer::Rotate {option x y} {
1196    switch -- $option {
1197        "click" {
1198            $itk_component(view) configure -cursor fleur
1199            set _click(x) $x
1200            set _click(y) $y
1201        }
1202        "drag" {
1203            if {[array size _click] == 0} {
1204                Rotate click $x $y
1205            } else {
1206                set w [winfo width $itk_component(view)]
1207                set h [winfo height $itk_component(view)]
1208                if {$w <= 0 || $h <= 0} {
1209                    return
1210                }
1211
1212                if {[catch {
1213                    # this fails sometimes for no apparent reason
1214                    set dx [expr {double($x-$_click(x))/$w}]
1215                    set dy [expr {double($y-$_click(y))/$h}]
1216                }]} {
1217                    return
1218                }
1219                if { $dx == 0 && $dy == 0 } {
1220                    return
1221                }
1222                set q [$_arcball rotate $x $y $_click(x) $_click(y)]
1223                EventuallyRotate $q
1224                set _click(x) $x
1225                set _click(y) $y
1226            }
1227        }
1228        "release" {
1229            Rotate drag $x $y
1230            $itk_component(view) configure -cursor ""
1231            catch {unset _click}
1232        }
1233        default {
1234            error "bad option \"$option\": should be click, drag, release"
1235        }
1236    }
1237}
1238
1239itcl::body Rappture::VtkViewer::Pick {x y} {
1240    foreach tag [CurrentDatasets -visible] {
1241        SendCmd "dataset getscalar pixel $x $y $tag"
1242    }
1243}
1244
1245# ----------------------------------------------------------------------
1246# USAGE: $this Pan click x y
1247#        $this Pan drag x y
1248#        $this Pan release x y
1249#
1250# Called automatically when the user clicks on one of the zoom
1251# controls for this widget.  Changes the zoom for the current view.
1252# ----------------------------------------------------------------------
1253itcl::body Rappture::VtkViewer::Pan {option x y} {
1254    switch -- $option {
1255        "set" {
1256            set w [winfo width $itk_component(view)]
1257            set h [winfo height $itk_component(view)]
1258            set x [expr $x / double($w)]
1259            set y [expr $y / double($h)]
1260            set _view(xpan) [expr $_view(xpan) + $x]
1261            set _view(ypan) [expr $_view(ypan) + $y]
1262            PanCamera
1263            return
1264        }
1265        "click" {
1266            set _click(x) $x
1267            set _click(y) $y
1268            $itk_component(view) configure -cursor hand1
1269        }
1270        "drag" {
1271            if { ![info exists _click(x)] } {
1272                set _click(x) $x
1273            }
1274            if { ![info exists _click(y)] } {
1275                set _click(y) $y
1276            }
1277            set w [winfo width $itk_component(view)]
1278            set h [winfo height $itk_component(view)]
1279            set dx [expr ($_click(x) - $x)/double($w)]
1280            set dy [expr ($_click(y) - $y)/double($h)]
1281            set _click(x) $x
1282            set _click(y) $y
1283            set _view(xpan) [expr $_view(xpan) - $dx]
1284            set _view(ypan) [expr $_view(ypan) - $dy]
1285            PanCamera
1286        }
1287        "release" {
1288            Pan drag $x $y
1289            $itk_component(view) configure -cursor ""
1290        }
1291        default {
1292            error "unknown option \"$option\": should set, click, drag, or release"
1293        }
1294    }
1295}
1296
1297# ----------------------------------------------------------------------
1298# USAGE: FixSettings <what> ?<value>?
1299#
1300# Used internally to update rendering settings whenever parameters
1301# change in the popup settings panel.  Sends the new settings off
1302# to the back end.
1303# ----------------------------------------------------------------------
1304itcl::body Rappture::VtkViewer::FixSettings { args } {
1305    foreach setting $args {
1306        AdjustSetting $setting
1307    }
1308}
1309
1310#
1311# AdjustSetting --
1312#
1313#       Changes/updates a specific setting in the widget.  There are
1314#       usually user-setable option.  Commands are sent to the render
1315#       server.
1316#
1317itcl::body Rappture::VtkViewer::AdjustSetting {what {value ""}} {
1318    if { ![isconnected] } {
1319        return
1320    }
1321    switch -- $what {
1322        "polydata-opacity" {
1323            foreach dataset [CurrentDatasets -visible $_first] {
1324                foreach { dataobj comp } [split $dataset -] break
1325                if { [$dataobj type $comp] == "polydata" } {
1326                    SetOpacity $dataset
1327                }
1328            }
1329        }
1330        "polydata-wireframe" {
1331            set bool $_settings(polydata-wireframe)
1332            foreach dataset [CurrentDatasets -visible $_first] {
1333                foreach { dataobj comp } [split $dataset -] break
1334                set type [$dataobj type $comp]
1335                if { $type == "polydata" } {
1336                    SendCmd "$type wireframe $bool $dataset"
1337                }
1338            }
1339        }
1340        "polydata-visible" {
1341            set bool $_settings(polydata-visible)
1342            foreach dataset [CurrentDatasets -visible $_first] {
1343                foreach { dataobj comp } [split $dataset -] break
1344                set type [$dataobj type $comp]
1345                if { $type == "polydata" } {
1346                    SendCmd "$type visible $bool $dataset"
1347                }
1348            }
1349        }
1350        "polydata-lighting" {
1351            set bool $_settings(polydata-lighting)
1352            foreach dataset [CurrentDatasets -visible $_first] {
1353                foreach { dataobj comp } [split $dataset -] break
1354                set type [$dataobj type $comp]
1355                if { $type == "polydata" } {
1356                    SendCmd "$type lighting $bool $dataset"
1357                }
1358            }
1359        }
1360        "polydata-edges" {
1361            set bool $_settings(polydata-edges)
1362            foreach dataset [CurrentDatasets -visible $_first] {
1363                foreach { dataobj comp } [split $dataset -] break
1364                set type [$dataobj type $comp]
1365                if { $type == "polydata" } {
1366                    SendCmd "$type edges $bool $dataset"
1367                }
1368            }
1369        }
1370        "polydata-palette" {
1371            set palette [$itk_component(meshpalette) value]
1372            set _settings(polydata-palette) $palette
1373            foreach dataset [CurrentDatasets -visible $_first] {
1374                foreach {dataobj comp} [split $dataset -] break
1375                set type [$dataobj type $comp]
1376                if { $type == "polydata" } {
1377                    ChangeColormap $dataobj $comp $palette
1378                    # FIXME: fill in current selected fieldname
1379                    #SendCmd "polydata colormode scalar {} $dataset"
1380                }
1381            }
1382            set _legendPending 1
1383        }
1384        "molecule-opacity" {
1385            set val $_settings(molecule-opacity)
1386            set sval [expr { 0.01 * double($val) }]
1387            foreach dataset [CurrentDatasets -visible $_first] {
1388                foreach { dataobj comp } [split $dataset -] break
1389                if { [$dataobj type $comp] == "molecule" } {
1390                    SetOpacity $dataset
1391                }
1392            }
1393        }
1394        "molecule-wireframe" {
1395            set bool $_settings(molecule-wireframe)
1396            foreach dataset [CurrentDatasets -visible $_first] {
1397                foreach { dataobj comp } [split $dataset -] break
1398                set type [$dataobj type $comp]
1399                if { $type == "molecule" } {
1400                    SendCmd "molecule wireframe $bool $dataset"
1401                }
1402            }
1403        }
1404        "molecule-visible" {
1405            set bool $_settings(molecule-visible)
1406            foreach dataset [CurrentDatasets -visible $_first] {
1407                foreach { dataobj comp } [split $dataset -] break
1408                set type [$dataobj type $comp]
1409                if { $type == "molecule" } {
1410                    SendCmd "molecule visible $bool $dataset"
1411                }
1412            }
1413        }
1414        "molecule-lighting" {
1415            set bool $_settings(molecule-lighting)
1416            foreach dataset [CurrentDatasets -visible $_first] {
1417                foreach { dataobj comp } [split $dataset -] break
1418                set type [$dataobj type $comp]
1419                if { $type == "molecule" } {
1420                    SendCmd "molecule lighting $bool $dataset"
1421                }
1422            }
1423        }
1424        "molecule-edges" {
1425            set bool $_settings(molecule-edges)
1426            foreach dataset [CurrentDatasets -visible $_first] {
1427                foreach { dataobj comp } [split $dataset -] break
1428                set type [$dataobj type $comp]
1429                if { $type == "molecule" } {
1430                    SendCmd "molecule edges $bool $dataset"
1431                }
1432            }
1433        }
1434        "molecule-palette" {
1435            set palette [$itk_component(moleculepalette) value]
1436            set _moelculeSettings(palette) $palette
1437            foreach dataset [CurrentDatasets -visible $_first] {
1438                foreach {dataobj comp} [split $dataset -] break
1439                set type [$dataobj type $comp]
1440                if { $type == "molecule" } {
1441                    ChangeColormap $dataobj $comp $palette
1442                    if { $palette == "elementDefault" } {
1443                        SendCmd "molecule colormode by_elements element $dataset"
1444                    } else {
1445                        # FIXME: Set the chosen scalar field name here
1446                        SendCmd "molecule colormode scalar {} $dataset"
1447                    }
1448                }
1449            }
1450            set _legendPending 1
1451        }
1452        "molecule-representation" {
1453            set value [$itk_component(representation) value]
1454            set value [$itk_component(representation) translate $value]
1455            switch -- $value {
1456                "ballandstick" {
1457                    set _settings(molecule-rscale) covalent
1458                    set _settings(molecule-atoms-visible) 1
1459                    set _settings(molecule-bonds-visible) 1
1460                    set _settings(molecule-bondstyle) cylinder
1461                    set _settings(molecule-atomscale) 0.3
1462                    set _settings(molecule-bondscale) 0.075
1463                }
1464                "balls" - "spheres" {
1465                    set _settings(molecule-rscale) covalent
1466                    set _settings(molecule-atoms-visible) 1
1467                    set _settings(molecule-bonds-visible) 0
1468                    set _settings(molecule-bondstyle) cylinder
1469                    set _settings(molecule-atomscale) 0.3
1470                    set _settings(molecule-bondscale) 0.075
1471                }
1472                "sticks" {
1473                    set _settings(molecule-rscale) none
1474                    set _settings(molecule-atoms-visible) 1
1475                    set _settings(molecule-bonds-visible) 1
1476                    set _settings(molecule-bondstyle) cylinder
1477                    set _settings(molecule-atomscale) 0.075
1478                    set _settings(molecule-bondscale) 0.075
1479                }
1480                "spacefilling" {
1481                    set _settings(molecule-rscale) van_der_waals
1482                    set _settings(molecule-atoms-visible) 1
1483                    set _settings(molecule-bonds-visible) 0
1484                    set _settings(molecule-bondstyle) cylinder
1485                    set _settings(molecule-atomscale) 1.0
1486                    set _settings(molecule-bondscale) 0.075
1487                }
1488                "rods"  {
1489                    set _settings(molecule-rscale) none
1490                    set _settings(molecule-atoms-visible) 1
1491                    set _settings(molecule-bonds-visible) 1
1492                    set _settings(molecule-bondstyle) cylinder
1493                    set _settings(molecule-atomscale) 0.1
1494                    set _settings(molecule-bondscale) 0.1
1495                }
1496                "wireframe" - "lines" {
1497                    set _settings(molecule-rscale) none
1498                    set _settings(molecule-atoms-visible) 0
1499                    set _settings(molecule-bonds-visible) 1
1500                    set _settings(molecule-bondstyle) cylinder
1501                    set _settings(molecule-atomscale) 1.0
1502                    set _settings(molecule-bondscale) 1.0
1503                }
1504                default {
1505                    error "unknown representation $value"
1506                }
1507            }
1508            $itk_component(rscale) value [$itk_component(rscale) label $_settings(molecule-rscale)]
1509            switch -- $value {
1510                "ballandstick" - "balls" - "spheres" {
1511                    $itk_component(rscale) configure -state normal
1512                }
1513                default {
1514                    $itk_component(rscale) configure -state disabled
1515                }
1516            }
1517            foreach dataset [CurrentDatasets -all] {
1518                foreach {dataobj comp} [split $dataset -] break
1519                set type [$dataobj type $comp]
1520                if { $type == "molecule" } {
1521                    SendCmd [subst {molecule rscale $_settings(molecule-rscale) $dataset
1522molecule ascale $_settings(molecule-atomscale) $dataset
1523molecule bscale $_settings(molecule-bondscale) $dataset
1524molecule bstyle $_settings(molecule-bondstyle) $dataset
1525molecule atoms $_settings(molecule-atoms-visible) $dataset
1526molecule bonds $_settings(molecule-bonds-visible) $dataset}]
1527                }
1528            }
1529        }
1530        "molecule-rscale" {
1531            set value [$itk_component(rscale) value]
1532            set value [$itk_component(rscale) translate $value]
1533            set _settings(molecule-rscale) $value
1534            foreach dataset [CurrentDatasets -visible $_first] {
1535                foreach {dataobj comp} [split $dataset -] break
1536                set type [$dataobj type $comp]
1537                if { $type == "molecule" } {
1538                    SendCmd [subst {molecule rscale $_settings(molecule-rscale) $dataset}]
1539                }
1540            }
1541        }
1542        "molecule-labels" {
1543            set bool $_settings(molecule-labels)
1544            foreach dataset [CurrentDatasets -visible $_first] {
1545               foreach { dataobj comp } [split $dataset -] break
1546               set type [$dataobj type $comp]
1547               if { $type == "molecule" } {
1548                   SendCmd "molecule labels $bool $dataset"
1549               }
1550            }
1551        }
1552        "axis-visible" {
1553            set bool $_axis(visible)
1554            SendCmd "axis visible all $bool"
1555        }
1556        "axis-labels" {
1557            set bool $_axis(labels)
1558            SendCmd "axis labels all $bool"
1559        }
1560        "axis-xgrid" {
1561            set bool $_axis(xgrid)
1562            SendCmd "axis grid x $bool"
1563        }
1564        "axis-ygrid" {
1565            set bool $_axis(ygrid)
1566            SendCmd "axis grid y $bool"
1567        }
1568        "axis-zgrid" {
1569            set bool $_axis(zgrid)
1570            SendCmd "axis grid z $bool"
1571        }
1572        "axis-mode" {
1573            set mode [$itk_component(axismode) value]
1574            set mode [$itk_component(axismode) translate $mode]
1575            SendCmd "axis flymode $mode"
1576        }
1577        "axis-xcutaway" - "axis-ycutaway" - "axis-zcutaway" {
1578            set axis [string range $what 5 5]
1579            set bool $_axis(${axis}cutaway)
1580            if { $bool } {
1581                set pos [expr $_axis(${axis}position) * 0.01]
1582                set dir $_axis(${axis}direction)
1583                $itk_component(${axis}CutScale) configure -state normal \
1584                    -troughcolor white
1585                SendCmd "renderer clipplane $axis $pos $dir"
1586            } else {
1587                $itk_component(${axis}CutScale) configure -state disabled \
1588                    -troughcolor grey82
1589                SendCmd "renderer clipplane $axis 1 -1"
1590            }
1591        }
1592        "axis-xposition" - "axis-yposition" - "axis-zposition" -
1593        "axis-xdirection" - "axis-ydirection" - "axis-zdirection" {
1594            set axis [string range $what 5 5]
1595            #set dir $_axis(${axis}direction)
1596            set pos [expr $_axis(${axis}position) * 0.01]
1597            SendCmd "renderer clipplane ${axis} $pos -1"
1598        }
1599        default {
1600            error "don't know how to fix $what"
1601        }
1602    }
1603}
1604
1605#
1606# RequestLegend --
1607#
1608#       Request a new legend from the server.  The size of the legend
1609#       is determined from the height of the canvas.  It will be rotated
1610#       to be vertical when drawn.
1611#
1612itcl::body Rappture::VtkViewer::RequestLegend {} {
1613    set font "Arial 8"
1614    set lineht [font metrics $font -linespace]
1615    set c $itk_component(legend)
1616    set w 12
1617    set h [expr {$_height - 2 * ($lineht + 2)}]
1618    if { $h < 1} {
1619        return
1620    }
1621    # Set the legend on the first dataset.
1622    foreach dataset [CurrentDatasets -visible] {
1623        foreach {dataobj comp} [split $dataset -] break
1624        if { [info exists _dataset2style($dataset)] } {
1625            SendCmd "legend $_dataset2style($dataset) vmag {} {} $w $h 0"
1626            break;
1627        }
1628    }
1629}
1630
1631#
1632# ChangeColormap --
1633#
1634itcl::body Rappture::VtkViewer::ChangeColormap {dataobj comp color} {
1635    set tag $dataobj-$comp
1636    if { ![info exist _style($tag)] } {
1637        error "no initial colormap"
1638    }
1639    array set style $_style($tag)
1640    set style(-color) $color
1641    set _style($tag) [array get style]
1642    SetColormap $dataobj $comp
1643}
1644
1645#
1646# SetColormap --
1647#
1648itcl::body Rappture::VtkViewer::SetColormap { dataobj comp } {
1649    array set style {
1650        -color BCGYR
1651        -levels 6
1652        -opacity 1.0
1653    }
1654    if {[$dataobj type $comp] == "molecule"} {
1655        set style(-color) elementDefault
1656    }
1657    set tag $dataobj-$comp
1658    if { ![info exists _initialStyle($tag)] } {
1659        # Save the initial component style.
1660        set _initialStyle($tag) [$dataobj style $comp]
1661    }
1662
1663    # Override defaults with initial style defined in xml.
1664    array set style $_initialStyle($tag)
1665
1666    if { ![info exists _style($tag)] } {
1667        set _style($tag) [array get style]
1668    }
1669    # Override initial style with current style.
1670    array set style $_style($tag)
1671
1672    if { $style(-color) == "elementDefault" } {
1673        set name "$style(-color)"
1674    } else {
1675        set name "$style(-color):$style(-levels):$style(-opacity)"
1676    }
1677    if { ![info exists _colormaps($name)] } {
1678        BuildColormap $name [array get style]
1679        set _colormaps($name) 1
1680    }
1681    if { ![info exists _dataset2style($tag)] ||
1682         $_dataset2style($tag) != $name } {
1683        set _dataset2style($tag) $name
1684        switch -- [$dataobj type $comp] {
1685            "polydata" {
1686                SendCmd "polydata colormap $name $tag"
1687            }
1688            "glyphs" {
1689                SendCmd "glyphs colormap $name $tag"
1690            }
1691            "molecule" {
1692                SendCmd "molecule colormap $name $tag"
1693            }
1694        }
1695    }
1696}
1697
1698#
1699# BuildColormap --
1700#
1701itcl::body Rappture::VtkViewer::BuildColormap { name styles } {
1702    if { $name ==  "elementDefault" } {
1703        return
1704    }
1705    array set style $styles
1706    set cmap [ColorsToColormap $style(-color)]
1707    if { [llength $cmap] == 0 } {
1708        set cmap "0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0"
1709    }
1710    if { ![info exists _settings(polydata-opacity)] } {
1711        set _settings(polydata-opacity) $style(-opacity)
1712    }
1713    set max $_settings(polydata-opacity)
1714
1715    set wmap "0.0 1.0 1.0 1.0"
1716    SendCmd "colormap add $name { $cmap } { $wmap }"
1717}
1718
1719# ----------------------------------------------------------------------
1720# CONFIGURATION OPTION: -plotbackground
1721# ----------------------------------------------------------------------
1722itcl::configbody Rappture::VtkViewer::plotbackground {
1723    if { [isconnected] } {
1724        foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
1725        SendCmd "screen bgcolor $r $g $b"
1726    }
1727}
1728
1729# ----------------------------------------------------------------------
1730# CONFIGURATION OPTION: -plotforeground
1731# ----------------------------------------------------------------------
1732itcl::configbody Rappture::VtkViewer::plotforeground {
1733    if { [isconnected] } {
1734        foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
1735        #fix this!
1736        #SendCmd "color background $r $g $b"
1737    }
1738}
1739
1740itcl::body Rappture::VtkViewer::limits { dataobj } {
1741    foreach comp [$dataobj components] {
1742        set tag $dataobj-$comp
1743        if { ![info exists _limits($tag)] } {
1744            set data [$dataobj data $comp]
1745            if { $data == "" } {
1746                continue
1747            }
1748            set tmpfile file[pid].vtk
1749            set f [open "$tmpfile" "w"]
1750            fconfigure $f -translation binary -encoding binary
1751            puts $f $data
1752            close $f
1753            set reader [vtkDataSetReader $tag-xvtkDataSetReader]
1754            $reader SetFileName $tmpfile
1755set debug 0
1756            if {$debug} {
1757                # Only needed for debug output below
1758                $reader ReadAllNormalsOn
1759                $reader ReadAllTCoordsOn
1760                $reader ReadAllScalarsOn
1761                $reader ReadAllColorScalarsOn
1762                $reader ReadAllVectorsOn
1763                $reader ReadAllTensorsOn
1764                $reader ReadAllFieldsOn
1765            }
1766            $reader Update
1767            file delete $tmpfile
1768            set output [$reader GetOutput]
1769            set _limits($tag) [$output GetBounds]
1770            if {$debug} {
1771                puts stderr "\#scalars=[$reader GetNumberOfScalarsInFile]"
1772                puts stderr "\#vectors=[$reader GetNumberOfVectorsInFile]"
1773                puts stderr "\#tensors=[$reader GetNumberOfTensorsInFile]"
1774                puts stderr "\#normals=[$reader GetNumberOfNormalsInFile]"
1775                puts stderr "\#tcoords=[$reader GetNumberOfTCoordsInFile]"
1776                puts stderr "\#fielddata=[$reader GetNumberOfFieldDataInFile]"
1777                puts stderr "fielddataname=[$reader GetFieldDataNameInFile 0]"
1778                set pointData [$output GetPointData]
1779                if { $pointData != ""} {
1780                    puts stderr "point \#arrays=[$pointData GetNumberOfArrays]"
1781                    puts stderr "point \#components=[$pointData GetNumberOfComponents]"
1782                    puts stderr "point \#tuples=[$pointData GetNumberOfTuples]"
1783                    puts stderr "point scalars=[$pointData GetScalars]"
1784                    puts stderr "point vectors=[$pointData GetVectors]"
1785                }
1786                set cellData [$output GetCellData]
1787                if { $cellData != ""} {
1788                    puts stderr "cell \#arrays=[$cellData GetNumberOfArrays]"
1789                    puts stderr "cell \#components=[$cellData GetNumberOfComponents]"
1790                    puts stderr "cell \#tuples=[$cellData GetNumberOfTuples]"
1791                    puts stderr "cell scalars=[$cellData GetScalars]"
1792                    puts stderr "cell vectors=[$cellData GetVectors]"
1793                }
1794                set fieldData [$output GetFieldData]
1795                if { $fieldData != ""} {
1796                    puts stderr "field \#arrays=[$fieldData GetNumberOfArrays]"
1797                    puts stderr "field \#components=[$fieldData GetNumberOfComponents]"
1798                    puts stderr "field \#tuples=[$fieldData GetNumberOfTuples]"
1799                }
1800            }
1801            rename $output ""
1802            rename $reader ""
1803        }
1804        foreach { xMin xMax yMin yMax zMin zMax} $_limits($tag) break
1805        if {![info exists limits(xmin)] || $limits(xmin) > $xMin} {
1806            set limits(xmin) $xMin
1807        }
1808        if {![info exists limits(xmax)] || $limits(xmax) < $xMax} {
1809            set limits(xmax) $xMax
1810        }
1811        if {![info exists limits(ymin)] || $limits(ymin) > $yMin} {
1812            set limits(ymin) $xMin
1813        }
1814        if {![info exists limits(ymax)] || $limits(ymax) < $yMax} {
1815            set limits(ymax) $yMax
1816        }
1817        if {![info exists limits(zmin)] || $limits(zmin) > $zMin} {
1818            set limits(zmin) $zMin
1819        }
1820        if {![info exists limits(zmax)] || $limits(zmax) < $zMax} {
1821            set limits(zmax) $zMax
1822        }
1823    }
1824    return [array get limits]
1825}
1826
1827itcl::body Rappture::VtkViewer::BuildPolydataTab {} {
1828
1829    set fg [option get $itk_component(hull) font Font]
1830    #set bfg [option get $itk_component(hull) boldFont Font]
1831
1832    set inner [$itk_component(main) insert end \
1833        -title "Mesh Settings" \
1834        -icon [Rappture::icon mesh]]
1835    $inner configure -borderwidth 4
1836
1837    checkbutton $inner.mesh \
1838        -text "Show Mesh" \
1839        -variable [itcl::scope _settings(polydata-visible)] \
1840        -command [itcl::code $this AdjustSetting polydata-visible] \
1841        -font "Arial 9" -anchor w
1842
1843    checkbutton $inner.wireframe \
1844        -text "Show Wireframe" \
1845        -variable [itcl::scope _settings(polydata-wireframe)] \
1846        -command [itcl::code $this AdjustSetting polydata-wireframe] \
1847        -font "Arial 9" -anchor w
1848
1849    checkbutton $inner.lighting \
1850        -text "Enable Lighting" \
1851        -variable [itcl::scope _settings(polydata-lighting)] \
1852        -command [itcl::code $this AdjustSetting polydata-lighting] \
1853        -font "Arial 9" -anchor w
1854
1855    checkbutton $inner.edges \
1856        -text "Show Edges" \
1857        -variable [itcl::scope _settings(polydata-edges)] \
1858        -command [itcl::code $this AdjustSetting polydata-edges] \
1859        -font "Arial 9" -anchor w
1860
1861    label $inner.palette_l -text "Palette" -font "Arial 9" -anchor w
1862    itk_component add meshpalette {
1863        Rappture::Combobox $inner.palette -width 10 -editable no
1864    }
1865    $inner.palette choices insert end \
1866        "BCGYR"              "BCGYR"            \
1867        "BGYOR"              "BGYOR"            \
1868        "blue"               "blue"             \
1869        "blue-to-brown"      "blue-to-brown"    \
1870        "blue-to-orange"     "blue-to-orange"   \
1871        "blue-to-grey"       "blue-to-grey"     \
1872        "green-to-magenta"   "green-to-magenta" \
1873        "greyscale"          "greyscale"        \
1874        "nanohub"            "nanohub"          \
1875        "rainbow"            "rainbow"          \
1876        "spectral"           "spectral"         \
1877        "ROYGB"              "ROYGB"            \
1878        "RYGCB"              "RYGCB"            \
1879        "brown-to-blue"      "brown-to-blue"    \
1880        "grey-to-blue"       "grey-to-blue"     \
1881        "orange-to-blue"     "orange-to-blue"   
1882
1883    $itk_component(meshpalette) value "BCGYR"
1884    bind $inner.palette <<Value>> \
1885        [itcl::code $this AdjustSetting polydata-palette]
1886
1887    label $inner.opacity_l -text "Opacity" -font "Arial 9" -anchor w
1888    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
1889        -variable [itcl::scope _settings(polydata-opacity)] \
1890        -width 10 \
1891        -showvalue off \
1892        -command [itcl::code $this AdjustSetting polydata-opacity]
1893    $inner.opacity set $_settings(polydata-opacity)
1894
1895    blt::table $inner \
1896        0,0 $inner.mesh      -cspan 2  -anchor w -pady 2 \
1897        1,0 $inner.wireframe -cspan 2  -anchor w -pady 2 \
1898        2,0 $inner.lighting  -cspan 2  -anchor w -pady 2 \
1899        3,0 $inner.edges     -cspan 2  -anchor w -pady 2 \
1900        4,0 $inner.opacity_l -anchor w -pady 2 \
1901        4,1 $inner.opacity   -fill x   -pady 2 \
1902        5,0 $inner.palette_l -anchor w -pady 2 \
1903        5,1 $inner.palette   -fill x   -pady 2 
1904
1905    blt::table configure $inner r* c* -resize none
1906    blt::table configure $inner r7 c1 -resize expand
1907}
1908
1909itcl::body Rappture::VtkViewer::BuildAxisTab {} {
1910
1911    set fg [option get $itk_component(hull) font Font]
1912    #set bfg [option get $itk_component(hull) boldFont Font]
1913
1914    set inner [$itk_component(main) insert end \
1915        -title "Axis Settings" \
1916        -icon [Rappture::icon axis1]]
1917    $inner configure -borderwidth 4
1918
1919    checkbutton $inner.visible \
1920        -text "Show Axes" \
1921        -variable [itcl::scope _axis(visible)] \
1922        -command [itcl::code $this AdjustSetting axis-visible] \
1923        -font "Arial 9"
1924
1925    checkbutton $inner.labels \
1926        -text "Show Axis Labels" \
1927        -variable [itcl::scope _axis(labels)] \
1928        -command [itcl::code $this AdjustSetting axis-labels] \
1929        -font "Arial 9"
1930
1931    checkbutton $inner.gridx \
1932        -text "Show X Grid" \
1933        -variable [itcl::scope _axis(xgrid)] \
1934        -command [itcl::code $this AdjustSetting axis-xgrid] \
1935        -font "Arial 9"
1936    checkbutton $inner.gridy \
1937        -text "Show Y Grid" \
1938        -variable [itcl::scope _axis(ygrid)] \
1939        -command [itcl::code $this AdjustSetting axis-ygrid] \
1940        -font "Arial 9"
1941    checkbutton $inner.gridz \
1942        -text "Show Z Grid" \
1943        -variable [itcl::scope _axis(zgrid)] \
1944        -command [itcl::code $this AdjustSetting axis-zgrid] \
1945        -font "Arial 9"
1946
1947    label $inner.mode_l -text "Mode" -font "Arial 9"
1948
1949    itk_component add axismode {
1950        Rappture::Combobox $inner.mode -width 10 -editable no
1951    }
1952    $inner.mode choices insert end \
1953        "static_triad"    "static" \
1954        "closest_triad"   "closest" \
1955        "furthest_triad"  "furthest" \
1956        "outer_edges"     "outer"         
1957    $itk_component(axismode) value "static"
1958    bind $inner.mode <<Value>> [itcl::code $this AdjustSetting axis-mode]
1959
1960    blt::table $inner \
1961        0,0 $inner.visible -anchor w -cspan 2 \
1962        1,0 $inner.labels  -anchor w -cspan 2 \
1963        2,0 $inner.gridx   -anchor w -cspan 2 \
1964        3,0 $inner.gridy   -anchor w -cspan 2 \
1965        4,0 $inner.gridz   -anchor w -cspan 2 \
1966        5,0 $inner.mode_l  -anchor w -cspan 2 -padx { 2 0 } \
1967        6,0 $inner.mode    -fill x   -cspan 2
1968
1969    blt::table configure $inner r* c* -resize none
1970    blt::table configure $inner r7 c1 -resize expand
1971}
1972
1973itcl::body Rappture::VtkViewer::BuildCameraTab {} {
1974    set inner [$itk_component(main) insert end \
1975        -title "Camera Settings" \
1976        -icon [Rappture::icon camera]]
1977    $inner configure -borderwidth 4
1978
1979    label $inner.view_l -text "view" -font "Arial 9"
1980    set f [frame $inner.view]
1981    foreach side { front back left right top bottom } {
1982        button $f.$side  -image [Rappture::icon view$side] \
1983            -command [itcl::code $this SetOrientation $side]
1984        Rappture::Tooltip::for $f.$side "Change the view to $side"
1985        pack $f.$side -side left
1986    }
1987
1988    blt::table $inner \
1989        0,0 $inner.view_l -anchor e -pady 2 \
1990        0,1 $inner.view -anchor w -pady 2
1991
1992    set labels { qx qy qz qw xpan ypan zoom }
1993    set row 1
1994    foreach tag $labels {
1995        label $inner.${tag}label -text $tag -font "Arial 9"
1996        entry $inner.${tag} -font "Arial 9"  -bg white \
1997            -textvariable [itcl::scope _view($tag)]
1998        bind $inner.${tag} <KeyPress-Return> \
1999            [itcl::code $this camera set ${tag}]
2000        blt::table $inner \
2001            $row,0 $inner.${tag}label -anchor e -pady 2 \
2002            $row,1 $inner.${tag} -anchor w -pady 2
2003        blt::table configure $inner r$row -resize none
2004        incr row
2005    }
2006    checkbutton $inner.ortho \
2007        -text "Orthographic Projection" \
2008        -variable [itcl::scope _view(ortho)] \
2009        -command [itcl::code $this camera set ortho] \
2010        -font "Arial 9"
2011    blt::table $inner \
2012            $row,0 $inner.ortho -cspan 2 -anchor w -pady 2
2013    blt::table configure $inner r$row -resize none
2014    incr row
2015
2016    blt::table configure $inner c* r* -resize none
2017    blt::table configure $inner c2 -resize expand
2018    blt::table configure $inner r$row -resize expand
2019}
2020
2021itcl::body Rappture::VtkViewer::BuildCutawayTab {} {
2022
2023    set fg [option get $itk_component(hull) font Font]
2024   
2025    set inner [$itk_component(main) insert end \
2026        -title "Cutaway Along Axis" \
2027        -icon [Rappture::icon cutbutton]]
2028
2029    $inner configure -borderwidth 4
2030
2031    # X-value slicer...
2032    itk_component add xCutButton {
2033        Rappture::PushButton $inner.xbutton \
2034            -onimage [Rappture::icon x-cutplane] \
2035            -offimage [Rappture::icon x-cutplane] \
2036            -command [itcl::code $this AdjustSetting axis-xcutaway] \
2037            -variable [itcl::scope _axis(xcutaway)]
2038    }
2039    Rappture::Tooltip::for $itk_component(xCutButton) \
2040        "Toggle the X-axis cutaway on/off"
2041
2042    itk_component add xCutScale {
2043        ::scale $inner.xval -from 100 -to 0 \
2044            -width 10 -orient vertical -showvalue yes \
2045            -borderwidth 1 -highlightthickness 0 \
2046            -command [itcl::code $this Slice move x] \
2047            -variable [itcl::scope _axis(xposition)]
2048    } {
2049        usual
2050        ignore -borderwidth -highlightthickness
2051    }
2052    # Set the default cutaway value before disabling the scale.
2053    $itk_component(xCutScale) set 100
2054    $itk_component(xCutScale) configure -state disabled
2055    Rappture::Tooltip::for $itk_component(xCutScale) \
2056        "@[itcl::code $this Slice tooltip x]"
2057
2058    itk_component add xDirButton {
2059        Rappture::PushButton $inner.xdir \
2060            -onimage [Rappture::icon arrow-down] \
2061            -onvalue -1 \
2062            -offimage [Rappture::icon arrow-up] \
2063            -offvalue 1 \
2064            -command [itcl::code $this AdjustSetting axis-xdirection] \
2065            -variable [itcl::scope _axis(xdirection)]
2066    }
2067    set _axis(xdirection) -1
2068    Rappture::Tooltip::for $itk_component(xDirButton) \
2069        "Toggle the direction of the X-axis cutaway"
2070
2071    # Y-value slicer...
2072    itk_component add yCutButton {
2073        Rappture::PushButton $inner.ybutton \
2074            -onimage [Rappture::icon y-cutplane] \
2075            -offimage [Rappture::icon y-cutplane] \
2076            -command [itcl::code $this AdjustSetting axis-ycutaway] \
2077            -variable [itcl::scope _axis(ycutaway)]
2078    }
2079    Rappture::Tooltip::for $itk_component(yCutButton) \
2080        "Toggle the Y-axis cutaway on/off"
2081
2082    itk_component add yCutScale {
2083        ::scale $inner.yval -from 100 -to 0 \
2084            -width 10 -orient vertical -showvalue yes \
2085            -borderwidth 1 -highlightthickness 0 \
2086            -command [itcl::code $this Slice move y] \
2087            -variable [itcl::scope _axis(yposition)]
2088    } {
2089        usual
2090        ignore -borderwidth -highlightthickness
2091    }
2092    Rappture::Tooltip::for $itk_component(yCutScale) \
2093        "@[itcl::code $this Slice tooltip y]"
2094    # Set the default cutaway value before disabling the scale.
2095    $itk_component(yCutScale) set 100
2096    $itk_component(yCutScale) configure -state disabled
2097
2098    itk_component add yDirButton {
2099        Rappture::PushButton $inner.ydir \
2100            -onimage [Rappture::icon arrow-down] \
2101            -onvalue -1 \
2102            -offimage [Rappture::icon arrow-up] \
2103            -offvalue 1 \
2104            -command [itcl::code $this AdjustSetting axis-ydirection] \
2105            -variable [itcl::scope _axis(ydirection)]
2106    }
2107    Rappture::Tooltip::for $itk_component(yDirButton) \
2108        "Toggle the direction of the Y-axis cutaway"
2109    set _axis(ydirection) -1
2110
2111    # Z-value slicer...
2112    itk_component add zCutButton {
2113        Rappture::PushButton $inner.zbutton \
2114            -onimage [Rappture::icon z-cutplane] \
2115            -offimage [Rappture::icon z-cutplane] \
2116            -command [itcl::code $this AdjustSetting axis-zcutaway] \
2117            -variable [itcl::scope _axis(zcutaway)]
2118    }
2119    Rappture::Tooltip::for $itk_component(zCutButton) \
2120        "Toggle the Z-axis cutaway on/off"
2121
2122    itk_component add zCutScale {
2123        ::scale $inner.zval -from 100 -to 0 \
2124            -width 10 -orient vertical -showvalue yes \
2125            -borderwidth 1 -highlightthickness 0 \
2126            -command [itcl::code $this Slice move z] \
2127            -variable [itcl::scope _axis(zposition)]
2128    } {
2129        usual
2130        ignore -borderwidth -highlightthickness
2131    }
2132    $itk_component(zCutScale) set 100
2133    $itk_component(zCutScale) configure -state disabled
2134    #$itk_component(zCutScale) configure -state disabled
2135    Rappture::Tooltip::for $itk_component(zCutScale) \
2136        "@[itcl::code $this Slice tooltip z]"
2137
2138    itk_component add zDirButton {
2139        Rappture::PushButton $inner.zdir \
2140            -onimage [Rappture::icon arrow-down] \
2141            -onvalue -1 \
2142            -offimage [Rappture::icon arrow-up] \
2143            -offvalue 1 \
2144            -command [itcl::code $this AdjustSetting axis-zdirection] \
2145            -variable [itcl::scope _axis(zdirection)]
2146    }
2147    set _axis(zdirection) -1
2148    Rappture::Tooltip::for $itk_component(zDirButton) \
2149        "Toggle the direction of the Z-axis cutaway"
2150
2151    blt::table $inner \
2152        0,0 $itk_component(xCutButton)  -anchor e -padx 2 -pady 2 \
2153        1,0 $itk_component(xCutScale)   -fill y \
2154        0,1 $itk_component(yCutButton)  -anchor e -padx 2 -pady 2 \
2155        1,1 $itk_component(yCutScale)   -fill y \
2156        0,2 $itk_component(zCutButton)  -anchor e -padx 2 -pady 2 \
2157        1,2 $itk_component(zCutScale)   -fill y \
2158
2159    blt::table configure $inner r* c* -resize none
2160    blt::table configure $inner r1 c3 -resize expand
2161}
2162
2163itcl::body Rappture::VtkViewer::BuildMoleculeTab {} {
2164    set fg [option get $itk_component(hull) font Font]
2165
2166    set inner [$itk_component(main) insert end \
2167        -title "Molecule Settings" \
2168        -icon [Rappture::icon molecule]]
2169    $inner configure -borderwidth 4
2170
2171    checkbutton $inner.molecule \
2172        -text "Show Molecule" \
2173        -variable [itcl::scope _settings(molecule-visible)] \
2174        -command [itcl::code $this AdjustSetting molecule-visible] \
2175        -font "Arial 9"
2176
2177    checkbutton $inner.label \
2178        -text "Show Atom Labels" \
2179        -variable [itcl::scope _settings(molecule-labels)] \
2180        -command [itcl::code $this AdjustSetting molecule-labels] \
2181        -font "Arial 9"
2182
2183    checkbutton $inner.wireframe \
2184        -text "Show Wireframe" \
2185        -variable [itcl::scope _settings(molecule-wireframe)] \
2186        -command [itcl::code $this AdjustSetting molecule-wireframe] \
2187        -font "Arial 9"
2188
2189    checkbutton $inner.lighting \
2190        -text "Enable Lighting" \
2191        -variable [itcl::scope _settings(molecule-lighting)] \
2192        -command [itcl::code $this AdjustSetting molecule-lighting] \
2193        -font "Arial 9"
2194
2195    checkbutton $inner.edges \
2196        -text "Show Edges" \
2197        -variable [itcl::scope _settings(molecule-edges)] \
2198        -command [itcl::code $this AdjustSetting molecule-edges] \
2199        -font "Arial 9"
2200
2201    label $inner.rep_l -text "Molecule Representation" \
2202        -font "Arial 9"
2203
2204    itk_component add representation {
2205        Rappture::Combobox $inner.rep -width 20 -editable no
2206    }
2207    $inner.rep choices insert end \
2208        "ballandstick"  "Ball and Stick" \
2209        "spheres"       "Spheres"        \
2210        "sticks"        "Sticks"         \
2211        "rods"          "Rods"           \
2212        "wireframe"     "Wireframe"      \
2213        "spacefilling"  "Space Filling"
2214
2215    bind $inner.rep <<Value>> \
2216        [itcl::code $this AdjustSetting molecule-representation]
2217    $inner.rep value "Ball and Stick"
2218
2219    label $inner.rscale_l -text "Atom Radii" \
2220        -font "Arial 9"
2221
2222    itk_component add rscale {
2223        Rappture::Combobox $inner.rscale -width 20 -editable no
2224    }
2225    $inner.rscale choices insert end \
2226        "atomic"        "Atomic"   \
2227        "covalent"      "Covalent" \
2228        "van_der_waals" "VDW"      \
2229        "none"          "Constant"
2230
2231    bind $inner.rscale <<Value>> \
2232        [itcl::code $this AdjustSetting molecule-rscale]
2233    $inner.rscale value "Covalent"
2234
2235    label $inner.palette_l -text "Palette" -font "Arial 9"
2236    itk_component add moleculepalette {
2237        Rappture::Combobox $inner.palette -width 10 -editable no
2238    }
2239    $inner.palette choices insert end \
2240        "elementDefault"     "elementDefault"   \
2241        "BCGYR"              "BCGYR"            \
2242        "BGYOR"              "BGYOR"            \
2243        "blue"               "blue"             \
2244        "blue-to-brown"      "blue-to-brown"    \
2245        "blue-to-orange"     "blue-to-orange"   \
2246        "blue-to-grey"       "blue-to-grey"     \
2247        "green-to-magenta"   "green-to-magenta" \
2248        "greyscale"          "greyscale"        \
2249        "nanohub"            "nanohub"          \
2250        "rainbow"            "rainbow"          \
2251        "spectral"           "spectral"         \
2252        "ROYGB"              "ROYGB"            \
2253        "RYGCB"              "RYGCB"            \
2254        "brown-to-blue"      "brown-to-blue"    \
2255        "grey-to-blue"       "grey-to-blue"     \
2256        "orange-to-blue"     "orange-to-blue"   
2257
2258    $itk_component(moleculepalette) value "elementDefault"
2259    bind $inner.palette <<Value>> \
2260        [itcl::code $this AdjustSetting molecule-palette]
2261
2262    checkbutton $inner.labels -text "Show labels on atoms" \
2263        -command [itcl::code $this labels update] \
2264        -variable [itcl::scope _settings(molecule-labels)] \
2265        -font "Arial 9"
2266    Rappture::Tooltip::for $inner.labels \
2267        "Display atom symbol and serial number."
2268
2269    checkbutton $inner.rock -text "Rock molecule back and forth" \
2270        -variable [itcl::scope _settings(molecule-rock)] \
2271        -font "Arial 9"
2272    Rappture::Tooltip::for $inner.rock \
2273        "Rotate the object back and forth around the y-axis."
2274
2275    checkbutton $inner.cell -text "Parallelepiped" \
2276        -font "Arial 9"
2277    $inner.cell select
2278
2279    label $inner.atomscale_l -text "Atom Scale" -font "Arial 9"
2280    ::scale $inner.atomscale -width 15 -font "Arial 7" \
2281        -from 0.025 -to 2.0 -resolution 0.025 -label "" \
2282        -showvalue true -orient horizontal \
2283        -command [itcl::code $this EventuallySetAtomScale] \
2284        -variable [itcl::scope _settings(molecule-atomscale)]
2285    $inner.atomscale set $_settings(molecule-atomscale)
2286    Rappture::Tooltip::for $inner.atomscale \
2287        "Adjust relative scale of atoms (spheres or balls)."
2288
2289    label $inner.bondscale_l -text "Bond Scale" -font "Arial 9"
2290    ::scale $inner.bondscale -width 15 -font "Arial 7" \
2291        -from 0.005 -to 0.3 -resolution 0.005 -label "" \
2292        -showvalue true -orient horizontal \
2293        -command [itcl::code $this EventuallySetBondScale] \
2294        -variable [itcl::scope _settings(molecule-bondscale)]
2295    Rappture::Tooltip::for $inner.bondscale \
2296        "Adjust scale of bonds (sticks)."
2297    $inner.bondscale set $_settings(molecule-bondscale)
2298
2299    label $inner.opacity_l -text "Opacity" -font "Arial 9"
2300    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
2301        -variable [itcl::scope _settings(molecule-opacity)] \
2302        -width 15 -font "Arial 7" \
2303        -showvalue on \
2304        -command [itcl::code $this EventuallySetMoleculeOpacity]
2305
2306    label $inner.quality_l -text "Quality" -font "Arial 9"
2307    ::scale $inner.quality -width 15 -font "Arial 7" \
2308        -from 0.0 -to 10.0 -resolution 0.1 -label "" \
2309        -showvalue true -orient horizontal \
2310        -command [itcl::code $this EventuallySetMoleculeQuality] \
2311        -variable [itcl::scope _settings(molecule-quality)]
2312    Rappture::Tooltip::for $inner.quality \
2313        "Adjust tesselation quality"
2314    $inner.quality set $_settings(molecule-quality)
2315
2316    blt::table $inner \
2317        0,0 $inner.molecule     -anchor w -pady {1 0} \
2318        1,0 $inner.label        -anchor w -pady {1 0} \
2319        2,0 $inner.edges        -anchor w -pady {1 0} \
2320        3,0 $inner.rep_l        -anchor w -pady { 2 0 } \
2321        4,0 $inner.rep          -fill x    -pady 2 \
2322        5,0 $inner.rscale_l     -anchor w -pady { 2 0 } \
2323        6,0 $inner.rscale       -fill x    -pady 2 \
2324        7,0 $inner.palette_l    -anchor w  -pady 0 \
2325        8,0 $inner.palette      -fill x    -padx 2 \
2326        9,0 $inner.atomscale_l  -anchor w -pady {3 0} \
2327        10,0 $inner.atomscale   -fill x    -padx 2 \
2328        11,0 $inner.bondscale_l -anchor w -pady {3 0} \
2329        12,0 $inner.bondscale   -fill x   -padx 2 \
2330        13,0 $inner.opacity_l   -anchor w -pady {3 0} \
2331        14,0 $inner.opacity     -fill x    -padx 2 \
2332        15,0 $inner.quality_l   -anchor w -pady {3 0} \
2333        16,0 $inner.quality     -fill x    -padx 2
2334   
2335    blt::table configure $inner r* -resize none
2336    blt::table configure $inner r17 -resize expand
2337}
2338
2339#
2340#  camera --
2341#
2342itcl::body Rappture::VtkViewer::camera {option args} {
2343    switch -- $option {
2344        "show" {
2345            puts [array get _view]
2346        }
2347        "set" {
2348            set who [lindex $args 0]
2349            set x $_view($who)
2350            set code [catch { string is double $x } result]
2351            if { $code != 0 || !$result } {
2352                return
2353            }
2354            switch -- $who {
2355                "ortho" {
2356                    if {$_view(ortho)} {
2357                        SendCmd "camera mode ortho"
2358                    } else {
2359                        SendCmd "camera mode persp"
2360                    }
2361                }
2362                "xpan" - "ypan" {
2363                    PanCamera
2364                }
2365                "qx" - "qy" - "qz" - "qw" {
2366                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
2367                    $_arcball quaternion $q
2368                    EventuallyRotate $q
2369                }
2370                "zoom" {
2371                    SendCmd "camera zoom $_view(zoom)"
2372                }
2373            }
2374        }
2375    }
2376}
2377
2378itcl::body Rappture::VtkViewer::GetVtkData { args } {
2379    set bytes ""
2380    foreach dataobj [get] {
2381        foreach comp [$dataobj components] {
2382            set tag $dataobj-$comp
2383            set contents [$dataobj data $comp]
2384            append bytes "$contents\n"
2385        }
2386    }
2387    return [list .vtk $bytes]
2388}
2389
2390itcl::body Rappture::VtkViewer::GetImage { args } {
2391    if { [image width $_image(download)] > 0 &&
2392         [image height $_image(download)] > 0 } {
2393        set bytes [$_image(download) data -format "jpeg -quality 100"]
2394        set bytes [Rappture::encoding::decode -as b64 $bytes]
2395        return [list .jpg $bytes]
2396    }
2397    return ""
2398}
2399
2400itcl::body Rappture::VtkViewer::BuildDownloadPopup { popup command } {
2401    Rappture::Balloon $popup \
2402        -title "[Rappture::filexfer::label downloadWord] as..."
2403    set inner [$popup component inner]
2404    label $inner.summary -text "" -anchor w
2405    radiobutton $inner.vtk_button -text "VTK data file" \
2406        -variable [itcl::scope _downloadPopup(format)] \
2407        -font "Helvetica 9 " \
2408        -value vtk 
2409    Rappture::Tooltip::for $inner.vtk_button "Save as VTK data file."
2410    radiobutton $inner.image_button -text "Image File" \
2411        -variable [itcl::scope _downloadPopup(format)] \
2412        -value image
2413    Rappture::Tooltip::for $inner.image_button \
2414        "Save as digital image."
2415
2416    button $inner.ok -text "Save" \
2417        -highlightthickness 0 -pady 2 -padx 3 \
2418        -command $command \
2419        -compound left \
2420        -image [Rappture::icon download]
2421
2422    button $inner.cancel -text "Cancel" \
2423        -highlightthickness 0 -pady 2 -padx 3 \
2424        -command [list $popup deactivate] \
2425        -compound left \
2426        -image [Rappture::icon cancel]
2427
2428    blt::table $inner \
2429        0,0 $inner.summary -cspan 2  \
2430        1,0 $inner.vtk_button -anchor w -cspan 2 -padx { 4 0 } \
2431        2,0 $inner.image_button -anchor w -cspan 2 -padx { 4 0 } \
2432        4,1 $inner.cancel -width .9i -fill y \
2433        4,0 $inner.ok -padx 2 -width .9i -fill y
2434    blt::table configure $inner r3 -height 4
2435    blt::table configure $inner r4 -pady 4
2436    raise $inner.image_button
2437    $inner.vtk_button invoke
2438    return $inner
2439}
2440
2441itcl::body Rappture::VtkViewer::SetObjectStyle { dataobj comp } {
2442    # Parse style string.
2443    set tag $dataobj-$comp
2444    set type [$dataobj type $comp]
2445    set style [$dataobj style $comp]
2446    if { $dataobj != $_first } {
2447        set settings(-wireframe) 1
2448    }
2449    switch -- $type {
2450        "glyphs" {
2451            array set settings {
2452                -color \#FFFFFF
2453                -gscale 1
2454                -edges 0
2455                -edgecolor black
2456                -linewidth 1.0
2457                -opacity 1.0
2458                -wireframe 0
2459                -lighting 1
2460                -visible 1
2461            }
2462            set shape [$dataobj shape $comp]
2463            array set settings $style
2464            SendCmd "glyphs add $shape $tag"
2465            SendCmd "glyphs normscale 0 $tag"
2466            SendCmd "glyphs gscale $settings(-gscale) $tag"
2467            SendCmd "glyphs wireframe $settings(-wireframe) $tag"
2468            SendCmd "glyphs color [Color2RGB $settings(-color)] $tag"
2469            #SendCmd "glyphs colormode constant {} $tag"
2470            SendCmd "glyphs gorient 0 {} $tag"
2471            SendCmd "glyphs smode vcomp {} $tag"
2472            SendCmd "glyphs opacity $settings(-opacity) $tag"
2473            SendCmd "glyphs visible $settings(-visible) $tag"
2474            set _settings(glyphs-wireframe) $settings(-wireframe)
2475        }
2476        "molecule" {
2477            SendCmd "molecule add $tag"
2478            SendCmd "molecule ascale $_settings(molecule-atomscale) $tag"
2479            SendCmd "molecule bscale $_settings(molecule-bondscale) $tag"
2480            SendCmd "molecule bstyle $_settings(molecule-bondstyle) $tag"
2481            SendCmd "molecule atoms $_settings(molecule-atoms-visible) $tag"
2482            SendCmd "molecule bonds $_settings(molecule-bonds-visible) $tag"
2483            set _haveMolecules 1
2484        }
2485        "polydata" {
2486            array set settings {
2487                -color \#FFFFFF
2488                -edges 1
2489                -edgecolor black
2490                -linewidth 1.0
2491                -opacity 1.0
2492                -wireframe 0
2493                -lighting 1
2494                -visible 1
2495            }
2496            array set settings $style
2497            SendCmd "polydata add $tag"
2498            SendCmd "polydata visible $settings(-visible) $tag"
2499            set _settings(polydata-visible) $settings(-visible)
2500            SendCmd "polydata edges $settings(-edges) $tag"
2501            set _settings(polydata-edges) $settings(-edges)
2502            SendCmd "polydata color [Color2RGB $settings(-color)] $tag"
2503            #SendCmd "polydata colormode constant {} $tag"
2504            SendCmd "polydata lighting $settings(-lighting) $tag"
2505            set _settings(polydata-lighting) $settings(-lighting)
2506            SendCmd "polydata linecolor [Color2RGB $settings(-edgecolor)] $tag"
2507            SendCmd "polydata linewidth $settings(-linewidth) $tag"
2508            SendCmd "polydata opacity $settings(-opacity) $tag"
2509            set _settings(polydata-opacity) [expr 100.0 * $settings(-opacity)]
2510            SendCmd "polydata wireframe $settings(-wireframe) $tag"
2511            set _settings(polydata-wireframe) $settings(-wireframe)
2512            set havePolyData 1
2513        }
2514    }
2515    SetColormap $dataobj $comp
2516}
2517
2518itcl::body Rappture::VtkViewer::IsValidObject { dataobj } {
2519    if {[catch {$dataobj isa Rappture::Drawing} valid] != 0 || !$valid} {
2520        return 0
2521    }
2522    return 1
2523}
2524
2525# ----------------------------------------------------------------------
2526# USAGE: ReceiveLegend <colormap> <title> <vmin> <vmax> <size>
2527#
2528# Invoked automatically whenever the "legend" command comes in from
2529# the rendering server.  Indicates that binary image data with the
2530# specified <size> will follow.
2531# ----------------------------------------------------------------------
2532itcl::body Rappture::VtkViewer::ReceiveLegend { colormap title vmin vmax size } {
2533    set _limits(vmin) $vmin
2534    set _limits(vmax) $vmax
2535    set _title $title
2536    if { [IsConnected] } {
2537        set bytes [ReceiveBytes $size]
2538        if { ![info exists _image(legend)] } {
2539            set _image(legend) [image create photo]
2540        }
2541        $_image(legend) configure -data $bytes
2542        DrawLegend
2543    }
2544}
2545
2546#
2547# DrawLegend --
2548#
2549#       Draws the legend in it's own canvas which resides to the right
2550#       of the contour plot area.
2551#
2552itcl::body Rappture::VtkViewer::DrawLegend {} {
2553    set c $itk_component(view)
2554    set w [winfo width $c]
2555    set h [winfo height $c]
2556    set font "Arial 8"
2557    set lineht [font metrics $font -linespace]
2558   
2559    if { $_settings(legend) } {
2560        set x [expr $w - 2]
2561        if { [$c find withtag "legend"] == "" } {
2562            $c create image $x [expr {$lineht+2}] \
2563                -anchor ne \
2564                -image $_image(legend) -tags "colormap legend"
2565            $c create text $x 2 \
2566                -anchor ne \
2567                -fill $itk_option(-plotforeground) -tags "vmax legend" \
2568                -font $font
2569            $c create text $x [expr {$h-2}] \
2570                -anchor se \
2571                -fill $itk_option(-plotforeground) -tags "vmin legend" \
2572                -font $font
2573            #$c bind colormap <Enter> [itcl::code $this EnterLegend %x %y]
2574            $c bind colormap <Leave> [itcl::code $this LeaveLegend]
2575            $c bind colormap <Motion> [itcl::code $this MotionLegend %x %y]
2576        }
2577        # Reset the item coordinates according the current size of the plot.
2578        $c coords colormap $x [expr {$lineht+2}]
2579        if { $_limits(vmin) != "" } {
2580            $c itemconfigure vmin -text [format %g $_limits(vmin)]
2581        }
2582        if { $_limits(vmax) != "" } {
2583            $c itemconfigure vmax -text [format %g $_limits(vmax)]
2584        }
2585        $c coords vmin $x [expr {$h-2}]
2586        $c coords vmax $x 2
2587    }
2588}
2589
2590#
2591# EnterLegend --
2592#
2593itcl::body Rappture::VtkViewer::EnterLegend { x y } {
2594    SetLegendTip $x $y
2595}
2596
2597#
2598# MotionLegend --
2599#
2600itcl::body Rappture::VtkViewer::MotionLegend { x y } {
2601    Rappture::Tooltip::tooltip cancel
2602    set c $itk_component(view)
2603    SetLegendTip $x $y
2604}
2605
2606#
2607# LeaveLegend --
2608#
2609itcl::body Rappture::VtkViewer::LeaveLegend { } {
2610    Rappture::Tooltip::tooltip cancel
2611    .rappturetooltip configure -icon ""
2612}
2613
2614#
2615# SetLegendTip --
2616#
2617itcl::body Rappture::VtkViewer::SetLegendTip { x y } {
2618    set c $itk_component(view)
2619    set w [winfo width $c]
2620    set h [winfo height $c]
2621    set font "Arial 8"
2622    set lineht [font metrics $font -linespace]
2623   
2624    set imgHeight [image height $_image(legend)]
2625    set coords [$c coords colormap]
2626    set imgX [expr $w - [image width $_image(legend)] - 2]
2627    set imgY [expr $y - $lineht - 2]
2628
2629    # Make a swatch of the selected color
2630    if { [catch { $_image(legend) get 10 $imgY } pixel] != 0 } {
2631        return
2632    }
2633    if { ![info exists _image(swatch)] } {
2634        set _image(swatch) [image create photo -width 24 -height 24]
2635    }
2636    set color [eval format "\#%02x%02x%02x" $pixel]
2637    $_image(swatch) put black  -to 0 0 23 23
2638    $_image(swatch) put $color -to 1 1 22 22
2639    .rappturetooltip configure -icon $_image(swatch)
2640
2641    # Compute the value of the point
2642    set t [expr 1.0 - (double($imgY) / double($imgHeight-1))]
2643    set value [expr $t * ($_limits(vmax) - $_limits(vmin)) + $_limits(vmin)]
2644    set tipx [expr $x + 15]
2645    set tipy [expr $y - 5]
2646    Rappture::Tooltip::text $c "$_title $value"
2647    Rappture::Tooltip::tooltip show $c +$tipx,+$tipy   
2648}
2649
2650# ----------------------------------------------------------------------
2651# USAGE: Slice move x|y|z <newval>
2652#
2653# Called automatically when the user drags the slider to move the
2654# cut plane that slices 3D data.  Gets the current value from the
2655# slider and moves the cut plane to the appropriate point in the
2656# data set.
2657# ----------------------------------------------------------------------
2658itcl::body Rappture::VtkViewer::Slice {option args} {
2659    switch -- $option {
2660        "move" {
2661            set axis [lindex $args 0]
2662            set oldval $_axis(${axis}position)
2663            set newval [lindex $args 1]
2664            if {[llength $args] != 2} {
2665                error "wrong # args: should be \"Slice move x|y|z newval\""
2666            }
2667            set newpos [expr {0.01*$newval}]
2668            SendCmd "renderer clipplane $axis $newpos -1"
2669        }
2670        "tooltip" {
2671            set axis [lindex $args 0]
2672            set val [$itk_component(${axis}CutScale) get]
2673            return "Move the [string toupper $axis] cut plane.\nCurrently:  $axis = $val%"
2674        }
2675        default {
2676            error "bad option \"$option\": should be axis, move, or tooltip"
2677        }
2678    }
2679}
2680
2681itcl::body Rappture::VtkViewer::SetOrientation { side } {
2682    array set positions {
2683        front "1 0 0 0"
2684        back  "0 0 1 0"
2685        left  "0.707107 0 -0.707107 0"
2686        right "0.707107 0 0.707107 0"
2687        top   "0.707107 -0.707107 0 0"
2688        bottom "0.707107 0.707107 0 0"
2689    }
2690    foreach name { qw qx qy qz } value $positions($side) {
2691        set _view($name) $value
2692    }
2693    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
2694    $_arcball quaternion $q
2695    SendCmd "camera orient $q"
2696    SendCmd "camera reset"
2697    set _view(xpan) 0
2698    set _view(ypan) 0
2699    set _view(zoom) 1.0
2700}
2701
2702itcl::body Rappture::VtkViewer::SetOpacity { dataset } {
2703    foreach {dataobj comp} [split $dataset -] break
2704    set type [$dataobj type $comp]
2705    set val $_settings($type-opacity)
2706    set sval [expr { 0.01 * double($val) }]
2707    if { !$_obj2ovride($dataobj-raise) } {
2708        # This is wrong.  Need to figure out why raise isn't set with 1
2709        #set sval [expr $sval * .6]
2710    }
2711    SendCmd "$type opacity $sval $dataset"
2712}
Note: See TracBrowser for help on using the repository browser.