source: trunk/gui/scripts/vtkheightmapviewer.tcl @ 2749

Last change on this file since 2749 was 2749, checked in by ldelgass, 12 years ago

Set default cutplane slice to center (ratio=0.5) to match slider default

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