source: trunk/gui/scripts/vtkstreamlinesviewer.tcl @ 2622

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