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

Last change on this file since 5092 was 5092, checked in by ldelgass, 5 years ago

Add update in Rebuild to allow initial canvas size to be set. We don't want to
do this in the constructor since that can cause an error when the add method is
called before the constructor returns.

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