source: trunk/gui/scripts/vtkglyphviewer.tcl @ 4151

Last change on this file since 4151 was 4151, checked in by ldelgass, 10 years ago

Add style options to vtk glyph viewer for e.g. setting shape for glyphing non-
vector data. Also disable writing debug vtk file.

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