source: trunk/gui/scripts/geoviewer.tcl @ 4198

Last change on this file since 4198 was 4198, checked in by ldelgass, 11 years ago

Remove unused event, fixes for drawing(3d) styles

File size: 54.3 KB
Line 
1# -*- mode: tcl; indent-tabs-mode: nil -*-
2
3# ----------------------------------------------------------------------
4#  COMPONENT: geoviewer - Map object viewer
5#
6#  It connects to the GeoVis server running on a rendering farm,
7#  transmits data, and displays the results.
8# ======================================================================
9#  AUTHOR:  Michael McLennan, Purdue University
10#  Copyright (c) 2004-2012  HUBzero Foundation, LLC
11#
12#  See the file "license.terms" for information on usage and
13#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14# ======================================================================
15package require Itk
16package require BLT
17#package require Img
18
19option add *GeoViewer.width 4i widgetDefault
20option add *GeoViewer*cursor crosshair widgetDefault
21option add *GeoViewer.height 4i widgetDefault
22option add *GeoViewer.foreground black widgetDefault
23option add *GeoViewer.controlBackground gray widgetDefault
24option add *GeoViewer.controlDarkBackground #999999 widgetDefault
25option add *GeoViewer.plotBackground black widgetDefault
26option add *GeoViewer.plotForeground white widgetDefault
27option add *GeoViewer.font \
28    -*-helvetica-medium-r-normal-*-12-* widgetDefault
29
30# must use this name -- plugs into Rappture::resources::load
31proc GeoViewer_init_resources {} {
32    Rappture::resources::register \
33        geovis_server Rappture::GeoViewer::SetServerList
34}
35
36itcl::class Rappture::GeoViewer {
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 "geovis" $namelist
52    }
53    public method add {dataobj {settings ""}}
54    public method camera {option args}
55    public method delete {args}
56    public method disconnect {}
57    public method download {option args}
58    public method get {args}
59    public method isconnected {}
60    public method limits { colormap }
61    public method parameters {title args} {
62        # do nothing
63    }
64    public method scale {args}
65
66    protected method Connect {}
67    protected method CurrentDatasets {args}
68    protected method Disconnect {}
69    protected method DoResize {}
70    protected method DoRotate {}
71    protected method AdjustSetting {what {value ""}}
72    protected method FixSettings { args  }
73    protected method KeyPress { key }
74    protected method KeyRelease { key }
75    protected method MouseClick { button x y }
76    protected method MouseDoubleClick { button x y }
77    protected method MouseDrag { button x y }
78    protected method MouseMotion { x y }
79    protected method MouseRelease { button x y }
80    protected method MouseScroll { direction }
81    protected method Pan {option x y}
82    protected method Pick {x y}
83    protected method Rebuild {}
84    protected method ReceiveDataset { args }
85    protected method ReceiveImage { args }
86    protected method Rotate {option x y}
87    protected method Zoom {option}
88
89    # The following methods are only used by this class.
90    private method BuildCameraTab {}
91    private method BuildDownloadPopup { widget command }
92    private method BuildPolydataTab {}
93    private method EventuallySetPolydataOpacity { args }
94    private method EventuallyResize { w h }
95    private method EventuallyRotate { q }
96    private method GetImage { args }
97    private method IsValidObject { dataobj }
98    private method PanCamera {}
99    private method SetObjectStyle { dataobj comp }
100    private method SetOpacity { dataset }
101    private method SetOrientation { side }
102    private method SetPolydataOpacity {}
103
104    private variable _arcball ""
105    private variable _dlist "";         # list of data objects
106    private variable _obj2datasets
107    private variable _obj2ovride;       # maps dataobj => style override
108    private variable _datasets;         # contains all the dataobj-component
109                                        # datasets in the server
110    private variable _click;            # info used for rotate operations
111    private variable _limits;           # autoscale min/max for all axes
112    private variable _view;             # view params for 3D view
113    private variable _settings
114    private variable _style;            # Array of current component styles.
115    private variable _initialStyle;     # Array of initial component styles.
116    private variable _reset 1;          # Indicates that server was reset and
117                                        # needs to be reinitialized.
118    private variable _havePolydata 0
119
120    private variable _first ""     ;# This is the topmost dataset.
121    private variable _start 0
122    private variable _title ""
123
124    common _downloadPopup          ;# download options from popup
125    private common _hardcopy
126    private variable _width 0
127    private variable _height 0
128    private variable _resizePending 0
129    private variable _rotatePending 0
130    private variable _polydataOpacityPending 0
131    private variable _rotateDelay 150
132    private variable _scaleDelay 100
133}
134
135itk::usual GeoViewer {
136    keep -background -foreground -cursor -font
137    keep -plotbackground -plotforeground
138}
139
140# ----------------------------------------------------------------------
141# CONSTRUCTOR
142# ----------------------------------------------------------------------
143itcl::body Rappture::GeoViewer::constructor {hostlist args} {
144    set _serverType "geovis"
145
146    # Rebuild event
147    $_dispatcher register !rebuild
148    $_dispatcher dispatch $this !rebuild "[itcl::code $this Rebuild]; list"
149
150    # Resize event
151    $_dispatcher register !resize
152    $_dispatcher dispatch $this !resize "[itcl::code $this DoResize]; list"
153
154    # Rotate event
155    $_dispatcher register !rotate
156    $_dispatcher dispatch $this !rotate "[itcl::code $this DoRotate]; list"
157
158    # Polydata opacity event
159    $_dispatcher register !polydataOpacity
160    $_dispatcher dispatch $this !polydataOpacity \
161        "[itcl::code $this SetPolydataOpacity]; list"
162    #
163    # Populate parser with commands handle incoming requests
164    #
165    $_parser alias image    [itcl::code $this ReceiveImage]
166    $_parser alias dataset  [itcl::code $this ReceiveDataset]
167
168    # Initialize the view to some default parameters.
169    array set _view {
170        qw              0.853553
171        qx              -0.353553
172        qy              0.353553
173        qz              0.146447
174        zoom            1.0
175        xpan            0
176        ypan            0
177    }
178    set _arcball [blt::arcball create 100 100]
179    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
180    $_arcball quaternion $q
181
182    set _limits(zmin) 0.0
183    set _limits(zmax) 1.0
184
185    array set _settings [subst {
186        legend                  1
187        polydata-lighting       1
188        polydata-opacity        100
189        polydata-texture        1
190        polydata-visible        1
191        polydata-wireframe      0
192    }]
193    itk_component add view {
194        canvas $itk_component(plotarea).view \
195            -highlightthickness 0 -borderwidth 0
196    } {
197        usual
198        ignore -highlightthickness -borderwidth  -background
199    }
200
201    set c $itk_component(view)
202    bind $c <Configure> [itcl::code $this EventuallyResize %w %h]
203    bind $c <4> [itcl::code $this Zoom in 0.25]
204    bind $c <5> [itcl::code $this Zoom out 0.25]
205    bind $c <KeyPress-Left>  [list %W xview scroll 10 units]
206    bind $c <KeyPress-Right> [list %W xview scroll -10 units]
207    bind $c <KeyPress-Up>    [list %W yview scroll 10 units]
208    bind $c <KeyPress-Down>  [list %W yview scroll -10 units]
209    bind $c <Enter> "focus %W"
210    bind $c <Control-F1> [itcl::code $this ToggleConsole]
211
212    # Fix the scrollregion in case we go off screen
213    $c configure -scrollregion [$c bbox all]
214
215    set _map(id) [$c create image 0 0 -anchor nw -image $_image(plot)]
216    set _map(cwidth) -1
217    set _map(cheight) -1
218    set _map(zoom) 1.0
219    set _map(original) ""
220
221    set f [$itk_component(main) component controls]
222    itk_component add reset {
223        button $f.reset -borderwidth 1 -padx 1 -pady 1 \
224            -highlightthickness 0 \
225            -image [Rappture::icon reset-view] \
226            -command [itcl::code $this Zoom reset]
227    } {
228        usual
229        ignore -highlightthickness
230    }
231    pack $itk_component(reset) -side top -padx 2 -pady 2
232    Rappture::Tooltip::for $itk_component(reset) \
233        "Reset the view to the default zoom level"
234
235    itk_component add zoomin {
236        button $f.zin -borderwidth 1 -padx 1 -pady 1 \
237            -highlightthickness 0 \
238            -image [Rappture::icon zoom-in] \
239            -command [itcl::code $this Zoom in]
240    } {
241        usual
242        ignore -highlightthickness
243    }
244    pack $itk_component(zoomin) -side top -padx 2 -pady 2
245    Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
246
247    itk_component add zoomout {
248        button $f.zout -borderwidth 1 -padx 1 -pady 1 \
249            -highlightthickness 0 \
250            -image [Rappture::icon zoom-out] \
251            -command [itcl::code $this Zoom out]
252    } {
253        usual
254        ignore -highlightthickness
255    }
256    pack $itk_component(zoomout) -side top -padx 2 -pady 2
257    Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
258
259    BuildCameraTab
260
261    # Legend
262
263    set _image(legend) [image create photo]
264    itk_component add legend {
265        canvas $itk_component(plotarea).legend -width 50 -highlightthickness 0
266    } {
267        usual
268        ignore -highlightthickness
269        rename -background -plotbackground plotBackground Background
270    }
271
272    # Hack around the Tk panewindow.  The problem is that the requested
273    # size of the 3d view isn't set until an image is retrieved from
274    # the server.  So the panewindow uses the tiny size.
275    set w 10000
276    pack forget $itk_component(view)
277    blt::table $itk_component(plotarea) \
278        0,0 $itk_component(view) -fill both -reqwidth $w
279    blt::table configure $itk_component(plotarea) c1 -resize none
280
281    # Bindings for keyboard events
282    bind $itk_component(view) <KeyPress> \
283        [itcl::code $this KeyPress %N]
284    bind $itk_component(view) <KeyRelease> \
285        [itcl::code $this KeyRelease %N]
286
287    # Bindings for rotation via mouse
288    bind $itk_component(view) <ButtonPress-1> \
289        [itcl::code $this MouseClick 1 %x %y]
290        #[itcl::code $this Rotate click %x %y]
291    bind $itk_component(view) <Double-1> \
292        [itcl::code $this MouseDoubleClick 1 %x %y]
293    bind $itk_component(view) <B1-Motion> \
294        [itcl::code $this MouseDrag 1 %x %y]
295        #[itcl::code $this Rotate drag %x %y]
296    bind $itk_component(view) <ButtonRelease-1> \
297        [itcl::code $this MouseRelease 1 %x %y]
298        #[itcl::code $this Rotate release %x %y]
299    bind $itk_component(view) <Configure> \
300        [itcl::code $this EventuallyResize %w %h]
301
302    # Bindings for panning via mouse
303    bind $itk_component(view) <ButtonPress-2> \
304        [itcl::code $this MouseClick 2 %x %y]
305        #[itcl::code $this Pan click %x %y]
306    bind $itk_component(view) <Double-2> \
307        [itcl::code $this MouseDoubleClick 2 %x %y]
308    bind $itk_component(view) <B2-Motion> \
309        [itcl::code $this MouseDrag 2 %x %y]
310        #[itcl::code $this Pan drag %x %y]
311    bind $itk_component(view) <ButtonRelease-2> \
312        [itcl::code $this MouseRelease 2 %x %y]
313        #[itcl::code $this Pan release %x %y]
314
315    bind $itk_component(view) <ButtonPress-3> \
316        [itcl::code $this MouseClick 3 %x %y]
317    bind $itk_component(view) <Double-3> \
318        [itcl::code $this MouseDoubleClick 3 %x %y]
319    bind $itk_component(view) <B3-Motion> \
320        [itcl::code $this MouseDrag 3 %x %y]
321    bind $itk_component(view) <ButtonRelease-3> \
322        [itcl::code $this MouseRelease 3 %x %y]
323
324    bind $itk_component(view) <Motion> \
325        [itcl::code $this MouseMotion %x %y]
326
327    #bind $itk_component(view) <ButtonRelease-3> \
328    #    [itcl::code $this Pick %x %y]
329
330    # Bindings for panning via keyboard
331    bind $itk_component(view) <KeyPress-Left> \
332        [itcl::code $this Pan set -10 0]
333    bind $itk_component(view) <KeyPress-Right> \
334        [itcl::code $this Pan set 10 0]
335    bind $itk_component(view) <KeyPress-Up> \
336        [itcl::code $this Pan set 0 -10]
337    bind $itk_component(view) <KeyPress-Down> \
338        [itcl::code $this Pan set 0 10]
339    bind $itk_component(view) <Shift-KeyPress-Left> \
340        [itcl::code $this Pan set -2 0]
341    bind $itk_component(view) <Shift-KeyPress-Right> \
342        [itcl::code $this Pan set 2 0]
343    bind $itk_component(view) <Shift-KeyPress-Up> \
344        [itcl::code $this Pan set 0 -2]
345    bind $itk_component(view) <Shift-KeyPress-Down> \
346        [itcl::code $this Pan set 0 2]
347
348    # Bindings for zoom via keyboard
349    bind $itk_component(view) <KeyPress-Prior> \
350        [itcl::code $this Zoom out]
351    bind $itk_component(view) <KeyPress-Next> \
352        [itcl::code $this Zoom in]
353
354    bind $itk_component(view) <Enter> "focus $itk_component(view)"
355
356    if {[string equal "x11" [tk windowingsystem]]} {
357        # Bindings for zoom via mouse
358        #bind $itk_component(view) <4> [itcl::code $this Zoom out]
359        #bind $itk_component(view) <5> [itcl::code $this Zoom in]
360        bind $itk_component(view) <4> [itcl::code $this MouseScroll up]
361        bind $itk_component(view) <5> [itcl::code $this MouseScroll down]
362
363    }
364
365    set _image(download) [image create photo]
366
367    eval itk_initialize $args
368    Connect
369}
370
371# ----------------------------------------------------------------------
372# DESTRUCTOR
373# ----------------------------------------------------------------------
374itcl::body Rappture::GeoViewer::destructor {} {
375    Disconnect
376    $_dispatcher cancel !rebuild
377    $_dispatcher cancel !resize
378    $_dispatcher cancel !rotate
379    image delete $_image(plot)
380    image delete $_image(download)
381    catch { blt::arcball destroy $_arcball }
382}
383
384itcl::body Rappture::GeoViewer::DoResize {} {
385    set sendResize 1
386    if { $_width < 2 } {
387        set _width 500
388        set sendResize 0
389    }
390    if { $_height < 2 } {
391        set _height 500
392        set sendResize 0
393    }
394    set _start [clock clicks -milliseconds]
395    if {$sendResize} {
396        SendCmd "screen size $_width $_height"
397    }
398    set _resizePending 0
399}
400
401itcl::body Rappture::GeoViewer::DoRotate {} {
402    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
403    SendCmd "camera orient $q"
404    set _rotatePending 0
405}
406
407itcl::body Rappture::GeoViewer::EventuallyResize { w h } {
408    set _width $w
409    set _height $h
410    $_arcball resize $w $h
411    if { !$_resizePending } {
412        set _resizePending 1
413        $_dispatcher event -after 200 !resize
414    }
415}
416
417itcl::body Rappture::GeoViewer::EventuallyRotate { q } {
418    foreach { _view(qw) _view(qx) _view(qy) _view(qz) } $q break
419    if { !$_rotatePending } {
420        set _rotatePending 1
421        $_dispatcher event -after $_rotateDelay !rotate
422    }
423}
424
425itcl::body Rappture::GeoViewer::SetPolydataOpacity {} {
426    set _polydataOpacityPending 0
427    foreach dataset [CurrentDatasets -visible $_first] {
428        foreach { dataobj comp } [split $dataset -] break
429        if { [$dataobj type $comp] == "polydata" } {
430            SetOpacity $dataset
431        }
432    }
433}
434
435itcl::body Rappture::GeoViewer::EventuallySetPolydataOpacity { args } {
436    if { !$_polydataOpacityPending } {
437        set _polydataOpacityPending 1
438        $_dispatcher event -after $_scaleDelay !polydataOpacity
439    }
440}
441
442# ----------------------------------------------------------------------
443# USAGE: add <dataobj> ?<settings>?
444#
445# Clients use this to add a data object to the plot.  The optional
446# <settings> are used to configure the plot.  Allowed settings are
447# -color, -brightness, -width, -linestyle, and -raise.
448# ----------------------------------------------------------------------
449itcl::body Rappture::GeoViewer::add {dataobj {settings ""}} {
450    array set params {
451        -color auto
452        -width 1
453        -linestyle solid
454        -brightness 0
455        -raise 0
456        -description ""
457        -param ""
458        -type ""
459    }
460    array set params $settings
461    set params(-description) ""
462    set params(-param) ""
463    array set params $settings
464
465    if {$params(-color) == "auto" || $params(-color) == "autoreset"} {
466        # can't handle -autocolors yet
467        set params(-color) black
468    }
469    set pos [lsearch -exact $_dlist $dataobj]
470    if {$pos < 0} {
471        lappend _dlist $dataobj
472    }
473    set _obj2ovride($dataobj-color) $params(-color)
474    set _obj2ovride($dataobj-width) $params(-width)
475    set _obj2ovride($dataobj-raise) $params(-raise)
476    $_dispatcher event -idle !rebuild
477}
478
479# ----------------------------------------------------------------------
480# USAGE: delete ?<dataobj1> <dataobj2> ...?
481#
482#       Clients use this to delete a dataobj from the plot.  If no dataobjs
483#       are specified, then all dataobjs are deleted.  No data objects are
484#       deleted.  They are only removed from the display list.
485#
486# ----------------------------------------------------------------------
487itcl::body Rappture::GeoViewer::delete {args} {
488    if { [llength $args] == 0} {
489        set args $_dlist
490    }
491    # Delete all specified dataobjs
492    set changed 0
493    foreach dataobj $args {
494        set pos [lsearch -exact $_dlist $dataobj]
495        if { $pos < 0 } {
496            continue;                   # Don't know anything about it.
497        }
498        # Remove it from the dataobj list.
499        set _dlist [lreplace $_dlist $pos $pos]
500        array unset _obj2ovride $dataobj-*
501        array unset _settings $dataobj-*
502        set changed 1
503    }
504    # If anything changed, then rebuild the plot
505    if { $changed } {
506        $_dispatcher event -idle !rebuild
507    }
508}
509
510# ----------------------------------------------------------------------
511# USAGE: get ?-objects?
512# USAGE: get ?-visible?
513# USAGE: get ?-image view?
514#
515# Clients use this to query the list of objects being plotted, in
516# order from bottom to top of this result.  The optional "-image"
517# flag can also request the internal images being shown.
518# ----------------------------------------------------------------------
519itcl::body Rappture::GeoViewer::get {args} {
520    if {[llength $args] == 0} {
521        set args "-objects"
522    }
523
524    set op [lindex $args 0]
525    switch -- $op {
526        "-objects" {
527            # put the dataobj list in order according to -raise options
528            set dlist {}
529            foreach dataobj $_dlist {
530                if { ![IsValidObject $dataobj] } {
531                    continue
532                }
533                if {[info exists _obj2ovride($dataobj-raise)] &&
534                    $_obj2ovride($dataobj-raise)} {
535                    set dlist [linsert $dlist 0 $dataobj]
536                } else {
537                    lappend dlist $dataobj
538                }
539            }
540            return $dlist
541        }
542        "-visible" {
543            set dlist {}
544            foreach dataobj $_dlist {
545                if { ![IsValidObject $dataobj] } {
546                    continue
547                }
548                if { ![info exists _obj2ovride($dataobj-raise)] } {
549                    # No setting indicates that the object isn't visible.
550                    continue
551                }
552                # Otherwise use the -raise parameter to put the object to
553                # the front of the list.
554                if { $_obj2ovride($dataobj-raise) } {
555                    set dlist [linsert $dlist 0 $dataobj]
556                } else {
557                    lappend dlist $dataobj
558                }
559            }
560            return $dlist
561        }           
562        -image {
563            if {[llength $args] != 2} {
564                error "wrong # args: should be \"get -image view\""
565            }
566            switch -- [lindex $args end] {
567                view {
568                    return $_image(plot)
569                }
570                default {
571                    error "bad image name \"[lindex $args end]\": should be view"
572                }
573            }
574        }
575        default {
576            error "bad option \"$op\": should be -objects or -image"
577        }
578    }
579}
580
581# ----------------------------------------------------------------------
582# USAGE: scale ?<data1> <data2> ...?
583#
584# Sets the default limits for the overall plot according to the
585# limits of the data for all of the given <data> objects.  This
586# accounts for all objects--even those not showing on the screen.
587# Because of this, the limits are appropriate for all objects as
588# the user scans through data in the ResultSet viewer.
589# ----------------------------------------------------------------------
590itcl::body Rappture::GeoViewer::scale {args} {
591    foreach dataobj $args {
592        foreach comp [$dataobj components] {
593            set type [$dataobj type $comp]
594            switch -- $type {
595                "polydata" {
596                    set _havePolydata 1
597                }
598            }
599        }
600        array set bounds [limits $dataobj]
601        if {![info exists _limits(xmin)] || $_limits(xmin) > $bounds(xmin)} {
602            set _limits(xmin) $bounds(xmin)
603        }
604        if {![info exists _limits(xmax)] || $_limits(xmax) < $bounds(xmax)} {
605            set _limits(xmax) $bounds(xmax)
606        }
607
608        if {![info exists _limits(ymin)] || $_limits(ymin) > $bounds(ymin)} {
609            set _limits(ymin) $bounds(ymin)
610        }
611        if {![info exists _limits(ymax)] || $_limits(ymax) < $bounds(ymax)} {
612            set _limits(ymax) $bounds(ymax)
613        }
614
615        if {![info exists _limits(zmin)] || $_limits(zmin) > $bounds(zmin)} {
616            set _limits(zmin) $bounds(zmin)
617        }
618        if {![info exists _limits(zmax)] || $_limits(zmax) < $bounds(zmax)} {
619            set _limits(zmax) $bounds(zmax)
620        }
621    }
622    if { $_havePolydata } {
623        if { ![$itk_component(main) exists "Mesh Settings"] } {
624            if { [catch { BuildPolydataTab } errs ]  != 0 } {
625                puts stderr "errs=$errs"
626            }
627        }
628    }
629}
630
631# ----------------------------------------------------------------------
632# USAGE: download coming
633# USAGE: download controls <downloadCommand>
634# USAGE: download now
635#
636# Clients use this method to create a downloadable representation
637# of the plot.  Returns a list of the form {ext string}, where
638# "ext" is the file extension (indicating the type of data) and
639# "string" is the data itself.
640# ----------------------------------------------------------------------
641itcl::body Rappture::GeoViewer::download {option args} {
642    switch $option {
643        coming {
644            if {[catch {
645                blt::winop snap $itk_component(plotarea) $_image(download)
646            }]} {
647                $_image(download) configure -width 1 -height 1
648                $_image(download) put #000000
649            }
650        }
651        controls {
652            set popup .geoviewerdownload
653            if { ![winfo exists .geoviewerdownload] } {
654                set inner [BuildDownloadPopup $popup [lindex $args 0]]
655            } else {
656                set inner [$popup component inner]
657            }
658            set _downloadPopup(image_controls) $inner.image_frame
659            set num [llength [get]]
660            set num [expr {($num == 1) ? "1 result" : "$num results"}]
661            set word [Rappture::filexfer::label downloadWord]
662            $inner.summary configure -text "$word $num in the following format:"
663            update idletasks            ;# Fix initial sizes
664            return $popup
665        }
666        now {
667            set popup .geoviewerdownload
668            if {[winfo exists .geoviewerdownload]} {
669                $popup deactivate
670            }
671            switch -- $_downloadPopup(format) {
672                "image" {
673                    return [$this GetImage [lindex $args 0]]
674                }
675            }
676            return ""
677        }
678        default {
679            error "bad option \"$option\": should be coming, controls, now"
680        }
681    }
682}
683
684# ----------------------------------------------------------------------
685# USAGE: Connect ?<host:port>,<host:port>...?
686#
687# Clients use this method to establish a connection to a new
688# server, or to reestablish a connection to the previous server.
689# Any existing connection is automatically closed.
690# ----------------------------------------------------------------------
691itcl::body Rappture::GeoViewer::Connect {} {
692    global readyForNextFrame
693    set readyForNextFrame 1
694    set _hosts [GetServerList "geovis"]
695    if { "" == $_hosts } {
696        return 0
697    }
698    set result [VisViewer::Connect $_hosts]
699    if { $result } {
700        if { $_reportClientInfo }  {
701            # Tell the server the viewer, hub, user and session.
702            # Do this immediately on connect before buffering any commands
703            global env
704
705            set info {}
706            set user "???"
707            if { [info exists env(USER)] } {
708                set user $env(USER)
709            }
710            set session "???"
711            if { [info exists env(SESSION)] } {
712                set session $env(SESSION)
713            }
714            lappend info "hub" [exec hostname]
715            lappend info "client" "geoviewer"
716            lappend info "user" $user
717            lappend info "session" $session
718            SendCmd "clientinfo [list $info]"
719        }
720
721        set w [winfo width $itk_component(view)]
722        set h [winfo height $itk_component(view)]
723        EventuallyResize $w $h
724    }
725    return $result
726}
727
728#
729# isconnected --
730#
731#       Indicates if we are currently connected to the visualization server.
732#
733itcl::body Rappture::GeoViewer::isconnected {} {
734    return [VisViewer::IsConnected]
735}
736
737#
738# disconnect --
739#
740itcl::body Rappture::GeoViewer::disconnect {} {
741    Disconnect
742    set _reset 1
743}
744
745#
746# Disconnect --
747#
748#       Clients use this method to disconnect from the current rendering
749#       server.
750#
751itcl::body Rappture::GeoViewer::Disconnect {} {
752    VisViewer::Disconnect
753
754    # disconnected -- no more data sitting on server
755    array unset _datasets
756    global readyForNextFrame
757    set readyForNextFrame 1
758}
759
760# ----------------------------------------------------------------------
761# USAGE: ReceiveImage -bytes <size> -type <type> -token <token>
762#
763# Invoked automatically whenever the "image" command comes in from
764# the rendering server.  Indicates that binary image data with the
765# specified <size> will follow.
766# ----------------------------------------------------------------------
767itcl::body Rappture::GeoViewer::ReceiveImage { args } {
768    global readyForNextFrame
769    set readyForNextFrame 1
770    array set info {
771        -token "???"
772        -bytes 0
773        -type image
774    }
775    array set info $args
776    set bytes [ReceiveBytes $info(-bytes)]
777    if { $info(-type) == "image" } {
778        if 0 {
779            set f [open "last.ppm" "w"]
780            fconfigure $f -encoding binary
781            puts -nonewline $f $bytes
782            close $f
783        }
784        $_image(plot) configure -data $bytes
785        set time [clock seconds]
786        set date [clock format $time]
787        if { $_start > 0 } {
788            set finish [clock clicks -milliseconds]
789            set _start 0
790        }
791    } elseif { $info(type) == "print" } {
792        set tag $this-print-$info(-token)
793        set _hardcopy($tag) $bytes
794    }
795}
796
797#
798# ReceiveDataset --
799#
800itcl::body Rappture::GeoViewer::ReceiveDataset { args } {
801    if { ![isconnected] } {
802        return
803    }
804    set option [lindex $args 0]
805    switch -- $option {
806        "coords" {
807            foreach { x y z } [lrange $args 1 end] break
808            puts stderr "Coords: $x $y $z"
809        }
810        "scalar" {
811            set option [lindex $args 1]
812            switch -- $option {
813                "world" {
814                    foreach { x y z value tag } [lrange $args 2 end] break
815                }
816                "pixel" {
817                    foreach { x y value tag } [lrange $args 2 end] break
818                }
819            }
820        }
821        "vector" {
822            set option [lindex $args 1]
823            switch -- $option {
824                "world" {
825                    foreach { x y z vx vy vz tag } [lrange $args 2 end] break
826                }
827                "pixel" {
828                    foreach { x y vx vy vz tag } [lrange $args 2 end] break
829                }
830            }
831        }
832        "names" {
833            foreach { name } [lindex $args 1] {
834                #puts stderr "Dataset: $name"
835            }
836        }
837        default {
838            error "unknown dataset option \"$option\" from server"
839        }
840    }
841}
842
843# ----------------------------------------------------------------------
844# USAGE: Rebuild
845#
846# Called automatically whenever something changes that affects the
847# data in the widget.  Clears any existing data and rebuilds the
848# widget to display new data.
849# ----------------------------------------------------------------------
850itcl::body Rappture::GeoViewer::Rebuild {} {
851
852    set w [winfo width $itk_component(view)]
853    set h [winfo height $itk_component(view)]
854    if { $w < 2 || $h < 2 } {
855        $_dispatcher event -idle !rebuild
856        return
857    }
858
859    # Turn on buffering of commands to the server.  We don't want to
860    # be preempted by a server disconnect/reconnect (which automatically
861    # generates a new call to Rebuild).   
862    StartBufferingCommands
863
864    if { $_reset } {
865        set _width $w
866        set _height $h
867        $_arcball resize $w $h
868        DoResize
869        #FixSettings ?
870
871        if { $_havePolydata } {
872            FixSettings polydata-edges polydata-lighting polydata-opacity \
873                polydata-visible polydata-wireframe
874        }
875        StopBufferingCommands
876        SendCmd "imgflush"
877        StartBufferingCommands
878    }
879
880    set _limits(zmin) ""
881    set _limits(zmax) ""
882    set _first ""
883    #SendCmd "dataset visible 0"
884    set count 0
885    foreach dataobj [get -objects] {
886        if { [info exists _obj2ovride($dataobj-raise)] &&  $_first == "" } {
887            set _first $dataobj
888        }
889        set _obj2datasets($dataobj) ""
890        foreach comp [$dataobj components] {
891            set tag $dataobj-$comp
892            if { ![info exists _datasets($tag)] } {
893                set bytes [$dataobj data $comp]
894                if { $bytes == "" } {
895                    continue
896                }
897                set length [string length $bytes]
898                if { $_reportClientInfo }  {
899                    set info {}
900                    lappend info "tool_id"       [$dataobj hints toolId]
901                    lappend info "tool_name"     [$dataobj hints toolName]
902                    lappend info "tool_version"  [$dataobj hints toolRevision]
903                    lappend info "tool_title"    [$dataobj hints toolTitle]
904                    lappend info "dataset_label" [$dataobj hints label]
905                    lappend info "dataset_size"  $length
906                    lappend info "dataset_tag"   $tag
907                    SendCmd [list "clientinfo" $info]
908                }
909                SendCmd "dataset add $tag data follows $length"
910                append _outbuf $bytes
911                set _datasets($tag) 1
912                SetObjectStyle $dataobj $comp
913            }
914            lappend _obj2datasets($dataobj) $tag
915            if { [info exists _obj2ovride($dataobj-raise)] } {
916                SendCmd "dataset visible 1 $tag"
917                SetOpacity $tag
918            }
919        }
920    }
921    if {"" != $_first} {
922        set location [$_first hints camera]
923        if { $location != "" } {
924            array set view $location
925        }
926    }
927    if { $_reset } {
928        set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
929        $_arcball quaternion $q
930        SendCmd "camera reset"
931        DoRotate
932        PanCamera
933        Zoom reset
934    }
935
936    set _reset 0
937    global readyForNextFrame
938    set readyForNextFrame 0;            # Don't advance to the next frame
939                                        # until we get an image.
940
941    # Actually write the commands to the server socket.  If it fails, we don't
942    # care.  We're finished here.
943    blt::busy hold $itk_component(hull)
944    StopBufferingCommands
945    blt::busy release $itk_component(hull)
946}
947
948# ----------------------------------------------------------------------
949# USAGE: CurrentDatasets ?-all -visible? ?dataobjs?
950#
951# Returns a list of server IDs for the current datasets being displayed.  This
952# is normally a single ID, but it might be a list of IDs if the current data
953# object has multiple components.
954# ----------------------------------------------------------------------
955itcl::body Rappture::GeoViewer::CurrentDatasets {args} {
956    set flag [lindex $args 0]
957    switch -- $flag {
958        "-all" {
959            if { [llength $args] > 1 } {
960                error "CurrentDatasets: can't specify dataobj after \"-all\""
961            }
962            set dlist [get -objects]
963        }
964        "-visible" {
965            if { [llength $args] > 1 } {
966                set dlist {}
967                set args [lrange $args 1 end]
968                foreach dataobj $args {
969                    if { [info exists _obj2ovride($dataobj-raise)] } {
970                        lappend dlist $dataobj
971                    }
972                }
973            } else {
974                set dlist [get -visible]
975            }
976        }           
977        default {
978            set dlist $args
979        }
980    }
981    set rlist ""
982    foreach dataobj $dlist {
983        foreach comp [$dataobj components] {
984            set tag $dataobj-$comp
985            if { [info exists _datasets($tag)] && $_datasets($tag) } {
986                lappend rlist $tag
987            }
988        }
989    }
990    return $rlist
991}
992
993itcl::body Rappture::GeoViewer::KeyPress {k} {
994    SendCmd "key press $k"
995}
996
997itcl::body Rappture::GeoViewer::KeyRelease {k} {
998    SendCmd "key release $k"
999}
1000
1001itcl::body Rappture::GeoViewer::MouseClick {button x y} {
1002    if {0} {
1003    set w [winfo width $itk_component(view)]
1004    set h [winfo height $itk_component(view)]
1005    set x [expr {(2.0 * double($x)/$w) - 1.0}]
1006    set y [expr {(2.0 * double($y)/$h) - 1.0}]
1007    }
1008    SendCmd "mouse click $button $x $y"
1009}
1010
1011itcl::body Rappture::GeoViewer::MouseDoubleClick {button x y} {
1012    if {0} {
1013    set w [winfo width $itk_component(view)]
1014    set h [winfo height $itk_component(view)]
1015    set x [expr {(2.0 * double($x)/$w) - 1.0}]
1016    set y [expr {(2.0 * double($y)/$h) - 1.0}]
1017    }
1018    SendCmd "mouse dblclick $button $x $y"
1019}
1020
1021itcl::body Rappture::GeoViewer::MouseDrag {button x y} {
1022    if {0} {
1023    set w [winfo width $itk_component(view)]
1024    set h [winfo height $itk_component(view)]
1025    set x [expr {(2.0 * double($x)/$w) - 1.0}]
1026    set y [expr {(2.0 * double($y)/$h) - 1.0}]
1027    }
1028    SendCmd "mouse drag $button $x $y"
1029}
1030
1031itcl::body Rappture::GeoViewer::MouseRelease {button x y} {
1032    if {0} {
1033    set w [winfo width $itk_component(view)]
1034    set h [winfo height $itk_component(view)]
1035    set x [expr {(2.0 * double($x)/$w) - 1.0}]
1036    set y [expr {(2.0 * double($y)/$h) - 1.0}]
1037    }
1038    SendCmd "mouse release $button $x $y"
1039}
1040
1041itcl::body Rappture::GeoViewer::MouseMotion {x y} {
1042    if {0} {
1043    set w [winfo width $itk_component(view)]
1044    set h [winfo height $itk_component(view)]
1045    set x [expr {(2.0 * double($x)/$w) - 1.0}]
1046    set y [expr {(2.0 * double($y)/$h) - 1.0}]
1047    }
1048    SendCmd "mouse motion $x $y"
1049}
1050
1051itcl::body Rappture::GeoViewer::MouseScroll {direction} {
1052    switch -- $direction {
1053        "up" {
1054            SendCmd "mouse scroll 1"
1055        }
1056        "down" {
1057            SendCmd "mouse scroll -1"
1058        }
1059    }
1060}
1061
1062# ----------------------------------------------------------------------
1063# USAGE: Zoom in
1064# USAGE: Zoom out
1065# USAGE: Zoom reset
1066#
1067# Called automatically when the user clicks on one of the zoom
1068# controls for this widget.  Changes the zoom for the current view.
1069# ----------------------------------------------------------------------
1070itcl::body Rappture::GeoViewer::Zoom {option} {
1071    switch -- $option {
1072        "in" {
1073            set _view(zoom) [expr {$_view(zoom)*1.25}]
1074            #SendCmd "camera zoom $_view(zoom)"
1075            set z -0.25
1076            SendCmd "camera zoom $z"
1077        }
1078        "out" {
1079            set _view(zoom) [expr {$_view(zoom)*0.8}]
1080            #SendCmd "camera zoom $_view(zoom)"
1081            set z 0.25
1082            SendCmd "camera zoom $z"
1083        }
1084        "reset" {
1085            array set _view {
1086                qw      0.853553
1087                qx      -0.353553
1088                qy      0.353553
1089                qz      0.146447
1090                zoom    1.0
1091                xpan    0
1092                ypan    0
1093            }
1094            if { $_first != "" } {
1095                set location [$_first hints camera]
1096                if { $location != "" } {
1097                    array set _view $location
1098                }
1099            }
1100            set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1101            $_arcball quaternion $q
1102            DoRotate
1103            SendCmd "camera reset"
1104        }
1105    }
1106}
1107
1108itcl::body Rappture::GeoViewer::PanCamera {} {
1109    set x $_view(xpan)
1110    set y $_view(ypan)
1111    SendCmd "camera pan $x $y"
1112}
1113
1114# ----------------------------------------------------------------------
1115# USAGE: Rotate click <x> <y>
1116# USAGE: Rotate drag <x> <y>
1117# USAGE: Rotate release <x> <y>
1118#
1119# Called automatically when the user clicks/drags/releases in the
1120# plot area.  Moves the plot according to the user's actions.
1121# ----------------------------------------------------------------------
1122itcl::body Rappture::GeoViewer::Rotate {option x y} {
1123    switch -- $option {
1124        "click" {
1125            $itk_component(view) configure -cursor fleur
1126            set _click(x) $x
1127            set _click(y) $y
1128        }
1129        "drag" {
1130            if {[array size _click] == 0} {
1131                Rotate click $x $y
1132            } else {
1133                set w [winfo width $itk_component(view)]
1134                set h [winfo height $itk_component(view)]
1135                if {$w <= 0 || $h <= 0} {
1136                    return
1137                }
1138
1139                if {[catch {
1140                    # this fails sometimes for no apparent reason
1141                    set dx [expr {double($x-$_click(x))/$w}]
1142                    set dy [expr {double($y-$_click(y))/$h}]
1143                }]} {
1144                    return
1145                }
1146                if { $dx == 0 && $dy == 0 } {
1147                    return
1148                }
1149                set q [$_arcball rotate $x $y $_click(x) $_click(y)]
1150                EventuallyRotate $q
1151                set _click(x) $x
1152                set _click(y) $y
1153            }
1154        }
1155        "release" {
1156            Rotate drag $x $y
1157            $itk_component(view) configure -cursor ""
1158            catch {unset _click}
1159        }
1160        default {
1161            error "bad option \"$option\": should be click, drag, release"
1162        }
1163    }
1164}
1165
1166itcl::body Rappture::GeoViewer::Pick {x y} {
1167    foreach tag [CurrentDatasets -visible] {
1168        SendCmd "dataset getscalar pixel $x $y $tag"
1169    }
1170}
1171
1172# ----------------------------------------------------------------------
1173# USAGE: $this Pan click x y
1174#        $this Pan drag x y
1175#        $this Pan release x y
1176#
1177# Called automatically when the user clicks on one of the zoom
1178# controls for this widget.  Changes the zoom for the current view.
1179# ----------------------------------------------------------------------
1180itcl::body Rappture::GeoViewer::Pan {option x y} {
1181    switch -- $option {
1182        "set" {
1183            set w [winfo width $itk_component(view)]
1184            set h [winfo height $itk_component(view)]
1185            set x [expr $x / double($w)]
1186            set y [expr $y / double($h)]
1187            set _view(xpan) [expr $_view(xpan) + $x]
1188            set _view(ypan) [expr $_view(ypan) + $y]
1189            PanCamera
1190            return
1191        }
1192        "click" {
1193            set _click(x) $x
1194            set _click(y) $y
1195            $itk_component(view) configure -cursor hand1
1196        }
1197        "drag" {
1198            if { ![info exists _click(x)] } {
1199                set _click(x) $x
1200            }
1201            if { ![info exists _click(y)] } {
1202                set _click(y) $y
1203            }
1204            set w [winfo width $itk_component(view)]
1205            set h [winfo height $itk_component(view)]
1206            set dx [expr ($_click(x) - $x)/double($w)]
1207            set dy [expr ($_click(y) - $y)/double($h)]
1208            set _click(x) $x
1209            set _click(y) $y
1210            set _view(xpan) [expr $_view(xpan) - $dx]
1211            set _view(ypan) [expr $_view(ypan) - $dy]
1212            PanCamera
1213        }
1214        "release" {
1215            Pan drag $x $y
1216            $itk_component(view) configure -cursor ""
1217        }
1218        default {
1219            error "unknown option \"$option\": should set, click, drag, or release"
1220        }
1221    }
1222}
1223
1224# ----------------------------------------------------------------------
1225# USAGE: FixSettings <what> ?<value>?
1226#
1227# Used internally to update rendering settings whenever parameters
1228# change in the popup settings panel.  Sends the new settings off
1229# to the back end.
1230# ----------------------------------------------------------------------
1231itcl::body Rappture::GeoViewer::FixSettings { args } {
1232    foreach setting $args {
1233        AdjustSetting $setting
1234    }
1235}
1236
1237#
1238# AdjustSetting --
1239#
1240#       Changes/updates a specific setting in the widget.  There are
1241#       usually user-setable option.  Commands are sent to the render
1242#       server.
1243#
1244itcl::body Rappture::GeoViewer::AdjustSetting {what {value ""}} {
1245    if { ![isconnected] } {
1246        return
1247    }
1248    switch -- $what {
1249        "polydata-opacity" {
1250            foreach dataset [CurrentDatasets -visible $_first] {
1251                foreach { dataobj comp } [split $dataset -] break
1252                if { [$dataobj type $comp] == "polydata" } {
1253                    SetOpacity $dataset
1254                }
1255            }
1256        }
1257        "polydata-wireframe" {
1258            set bool $_settings(polydata-wireframe)
1259            foreach dataset [CurrentDatasets -visible $_first] {
1260                foreach { dataobj comp } [split $dataset -] break
1261                set type [$dataobj type $comp]
1262                if { $type == "polydata" } {
1263                    SendCmd "$type wireframe $bool $dataset"
1264                }
1265            }
1266        }
1267        "polydata-visible" {
1268            set bool $_settings(polydata-visible)
1269            foreach dataset [CurrentDatasets -visible $_first] {
1270                foreach { dataobj comp } [split $dataset -] break
1271                set type [$dataobj type $comp]
1272                if { $type == "polydata" } {
1273                    SendCmd "$type visible $bool $dataset"
1274                }
1275            }
1276        }
1277        "polydata-lighting" {
1278            set bool $_settings(polydata-lighting)
1279            foreach dataset [CurrentDatasets -visible $_first] {
1280                foreach { dataobj comp } [split $dataset -] break
1281                set type [$dataobj type $comp]
1282                if { $type == "polydata" } {
1283                    SendCmd "$type lighting $bool $dataset"
1284                }
1285            }
1286        }
1287        "polydata-edges" {
1288            set bool $_settings(polydata-edges)
1289            foreach dataset [CurrentDatasets -visible $_first] {
1290                foreach { dataobj comp } [split $dataset -] break
1291                set type [$dataobj type $comp]
1292                if { $type == "polydata" } {
1293                    SendCmd "$type edges $bool $dataset"
1294                }
1295            }
1296        }
1297        default {
1298            error "don't know how to fix $what"
1299        }
1300    }
1301}
1302
1303# ----------------------------------------------------------------------
1304# CONFIGURATION OPTION: -plotbackground
1305# ----------------------------------------------------------------------
1306itcl::configbody Rappture::GeoViewer::plotbackground {
1307    if { [isconnected] } {
1308        foreach {r g b} [Color2RGB $itk_option(-plotbackground)] break
1309        SendCmd "screen bgcolor $r $g $b"
1310    }
1311}
1312
1313# ----------------------------------------------------------------------
1314# CONFIGURATION OPTION: -plotforeground
1315# ----------------------------------------------------------------------
1316itcl::configbody Rappture::GeoViewer::plotforeground {
1317    if { [isconnected] } {
1318        foreach {r g b} [Color2RGB $itk_option(-plotforeground)] break
1319        #fix this!
1320        #SendCmd "color background $r $g $b"
1321    }
1322}
1323
1324itcl::body Rappture::GeoViewer::limits { dataobj } {
1325    foreach comp [$dataobj components] {
1326        set tag $dataobj-$comp
1327        if { ![info exists _limits($tag)] } {
1328            set data [$dataobj data $comp]
1329            if { $data == "" } {
1330                continue
1331            }
1332        }
1333
1334        foreach { xMin xMax yMin yMax zMin zMax} $_limits($tag) break
1335        if {![info exists limits(xmin)] || $limits(xmin) > $xMin} {
1336            set limits(xmin) $xMin
1337        }
1338        if {![info exists limits(xmax)] || $limits(xmax) < $xMax} {
1339            set limits(xmax) $xMax
1340        }
1341        if {![info exists limits(ymin)] || $limits(ymin) > $yMin} {
1342            set limits(ymin) $xMin
1343        }
1344        if {![info exists limits(ymax)] || $limits(ymax) < $yMax} {
1345            set limits(ymax) $yMax
1346        }
1347        if {![info exists limits(zmin)] || $limits(zmin) > $zMin} {
1348            set limits(zmin) $zMin
1349        }
1350        if {![info exists limits(zmax)] || $limits(zmax) < $zMax} {
1351            set limits(zmax) $zMax
1352        }
1353    }
1354    return [array get limits]
1355}
1356
1357itcl::body Rappture::GeoViewer::BuildPolydataTab {} {
1358
1359    set fg [option get $itk_component(hull) font Font]
1360    #set bfg [option get $itk_component(hull) boldFont Font]
1361
1362    set inner [$itk_component(main) insert end \
1363        -title "Mesh Settings" \
1364        -icon [Rappture::icon mesh]]
1365    $inner configure -borderwidth 4
1366
1367    checkbutton $inner.mesh \
1368        -text "Show Mesh" \
1369        -variable [itcl::scope _settings(polydata-visible)] \
1370        -command [itcl::code $this AdjustSetting polydata-visible] \
1371        -font "Arial 9" -anchor w
1372
1373    checkbutton $inner.wireframe \
1374        -text "Show Wireframe" \
1375        -variable [itcl::scope _settings(polydata-wireframe)] \
1376        -command [itcl::code $this AdjustSetting polydata-wireframe] \
1377        -font "Arial 9" -anchor w
1378
1379    checkbutton $inner.lighting \
1380        -text "Enable Lighting" \
1381        -variable [itcl::scope _settings(polydata-lighting)] \
1382        -command [itcl::code $this AdjustSetting polydata-lighting] \
1383        -font "Arial 9" -anchor w
1384
1385    checkbutton $inner.edges \
1386        -text "Show Edges" \
1387        -variable [itcl::scope _settings(polydata-edges)] \
1388        -command [itcl::code $this AdjustSetting polydata-edges] \
1389        -font "Arial 9" -anchor w
1390
1391    label $inner.palette_l -text "Palette" -font "Arial 9" -anchor w
1392    itk_component add meshpalette {
1393        Rappture::Combobox $inner.palette -width 10 -editable no
1394    }
1395    $inner.palette choices insert end \
1396        "BCGYR"              "BCGYR"            \
1397        "BGYOR"              "BGYOR"            \
1398        "blue"               "blue"             \
1399        "blue-to-brown"      "blue-to-brown"    \
1400        "blue-to-orange"     "blue-to-orange"   \
1401        "blue-to-grey"       "blue-to-grey"     \
1402        "green-to-magenta"   "green-to-magenta" \
1403        "greyscale"          "greyscale"        \
1404        "nanohub"            "nanohub"          \
1405        "rainbow"            "rainbow"          \
1406        "spectral"           "spectral"         \
1407        "ROYGB"              "ROYGB"            \
1408        "RYGCB"              "RYGCB"            \
1409        "brown-to-blue"      "brown-to-blue"    \
1410        "grey-to-blue"       "grey-to-blue"     \
1411        "orange-to-blue"     "orange-to-blue"   
1412
1413    $itk_component(meshpalette) value "BCGYR"
1414    bind $inner.palette <<Value>> \
1415        [itcl::code $this AdjustSetting polydata-palette]
1416
1417    label $inner.opacity_l -text "Opacity" -font "Arial 9" -anchor w
1418    ::scale $inner.opacity -from 0 -to 100 -orient horizontal \
1419        -variable [itcl::scope _settings(polydata-opacity)] \
1420        -width 10 \
1421        -showvalue off \
1422        -command [itcl::code $this AdjustSetting polydata-opacity]
1423    $inner.opacity set $_settings(polydata-opacity)
1424
1425    blt::table $inner \
1426        0,0 $inner.mesh      -cspan 2  -anchor w -pady 2 \
1427        1,0 $inner.wireframe -cspan 2  -anchor w -pady 2 \
1428        2,0 $inner.lighting  -cspan 2  -anchor w -pady 2 \
1429        3,0 $inner.edges     -cspan 2  -anchor w -pady 2 \
1430        4,0 $inner.opacity_l -anchor w -pady 2 \
1431        4,1 $inner.opacity   -fill x   -pady 2 \
1432        5,0 $inner.palette_l -anchor w -pady 2 \
1433        5,1 $inner.palette   -fill x   -pady 2 
1434
1435    blt::table configure $inner r* c* -resize none
1436    blt::table configure $inner r7 c1 -resize expand
1437}
1438
1439itcl::body Rappture::GeoViewer::BuildCameraTab {} {
1440    set inner [$itk_component(main) insert end \
1441        -title "Camera Settings" \
1442        -icon [Rappture::icon camera]]
1443    $inner configure -borderwidth 4
1444
1445    label $inner.view_l -text "view" -font "Arial 9"
1446    set f [frame $inner.view]
1447    foreach side { front back left right top bottom } {
1448        button $f.$side  -image [Rappture::icon view$side] \
1449            -command [itcl::code $this SetOrientation $side]
1450        Rappture::Tooltip::for $f.$side "Change the view to $side"
1451        pack $f.$side -side left
1452    }
1453
1454    blt::table $inner \
1455        0,0 $inner.view_l -anchor e -pady 2 \
1456        0,1 $inner.view -anchor w -pady 2
1457
1458    set labels { qx qy qz qw xpan ypan zoom }
1459    set row 1
1460    foreach tag $labels {
1461        label $inner.${tag}label -text $tag -font "Arial 9"
1462        entry $inner.${tag} -font "Arial 9"  -bg white \
1463            -textvariable [itcl::scope _view($tag)]
1464        bind $inner.${tag} <KeyPress-Return> \
1465            [itcl::code $this camera set ${tag}]
1466        blt::table $inner \
1467            $row,0 $inner.${tag}label -anchor e -pady 2 \
1468            $row,1 $inner.${tag} -anchor w -pady 2
1469        blt::table configure $inner r$row -resize none
1470        incr row
1471    }
1472
1473    blt::table configure $inner c* r* -resize none
1474    blt::table configure $inner c2 -resize expand
1475    blt::table configure $inner r$row -resize expand
1476}
1477
1478#
1479#  camera --
1480#
1481itcl::body Rappture::GeoViewer::camera {option args} {
1482    switch -- $option {
1483        "show" {
1484            puts [array get _view]
1485        }
1486        "set" {
1487            set who [lindex $args 0]
1488            set x $_view($who)
1489            set code [catch { string is double $x } result]
1490            if { $code != 0 || !$result } {
1491                return
1492            }
1493            switch -- $who {
1494                "xpan" - "ypan" {
1495                    PanCamera
1496                }
1497                "qx" - "qy" - "qz" - "qw" {
1498                    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1499                    $_arcball quaternion $q
1500                    EventuallyRotate $q
1501                }
1502                "zoom" {
1503                    SendCmd "camera zoom $_view(zoom)"
1504                }
1505            }
1506        }
1507    }
1508}
1509
1510itcl::body Rappture::GeoViewer::GetImage { args } {
1511    if { [image width $_image(download)] > 0 &&
1512         [image height $_image(download)] > 0 } {
1513        set bytes [$_image(download) data -format "jpeg -quality 100"]
1514        set bytes [Rappture::encoding::decode -as b64 $bytes]
1515        return [list .jpg $bytes]
1516    }
1517    return ""
1518}
1519
1520itcl::body Rappture::GeoViewer::BuildDownloadPopup { popup command } {
1521    Rappture::Balloon $popup \
1522        -title "[Rappture::filexfer::label downloadWord] as..."
1523    set inner [$popup component inner]
1524    label $inner.summary -text "" -anchor w
1525
1526    radiobutton $inner.image_button -text "Image File" \
1527        -variable [itcl::scope _downloadPopup(format)] \
1528        -value image
1529    Rappture::Tooltip::for $inner.image_button \
1530        "Save as digital image."
1531
1532    button $inner.ok -text "Save" \
1533        -highlightthickness 0 -pady 2 -padx 3 \
1534        -command $command \
1535        -compound left \
1536        -image [Rappture::icon download]
1537
1538    button $inner.cancel -text "Cancel" \
1539        -highlightthickness 0 -pady 2 -padx 3 \
1540        -command [list $popup deactivate] \
1541        -compound left \
1542        -image [Rappture::icon cancel]
1543
1544    blt::table $inner \
1545        0,0 $inner.summary -cspan 2  \
1546        2,0 $inner.image_button -anchor w -cspan 2 -padx { 4 0 } \
1547        4,1 $inner.cancel -width .9i -fill y \
1548        4,0 $inner.ok -padx 2 -width .9i -fill y
1549    blt::table configure $inner r3 -height 4
1550    blt::table configure $inner r4 -pady 4
1551    raise $inner.image_button
1552    $inner.image_button invoke
1553    return $inner
1554}
1555
1556itcl::body Rappture::GeoViewer::SetObjectStyle { dataobj comp } {
1557    # Parse style string.
1558    set tag $dataobj-$comp
1559    set type [$dataobj type $comp]
1560    set style [$dataobj style $comp]
1561    if { $dataobj != $_first } {
1562        set settings(-wireframe) 1
1563    }
1564    switch -- $type {
1565        "polydata" {
1566            array set settings {
1567                -color \#FFFFFF
1568                -edges 1
1569                -edgecolor black
1570                -linewidth 1.0
1571                -opacity 1.0
1572                -wireframe 0
1573                -lighting 1
1574                -visible 1
1575            }
1576            array set settings $style
1577            SendCmd "polydata add $tag"
1578            SendCmd "polydata visible $settings(-visible) $tag"
1579            set _settings(polydata-visible) $settings(-visible)
1580            SendCmd "polydata edges $settings(-edges) $tag"
1581            set _settings(polydata-edges) $settings(-edges)
1582            SendCmd "polydata color [Color2RGB $settings(-color)] $tag"
1583            #SendCmd "polydata colormode constant {} $tag"
1584            SendCmd "polydata lighting $settings(-lighting) $tag"
1585            set _settings(polydata-lighting) $settings(-lighting)
1586            SendCmd "polydata linecolor [Color2RGB $settings(-edgecolor)] $tag"
1587            SendCmd "polydata linewidth $settings(-linewidth) $tag"
1588            SendCmd "polydata opacity $settings(-opacity) $tag"
1589            set _settings(polydata-opacity) [expr 100.0 * $settings(-opacity)]
1590            SendCmd "polydata wireframe $settings(-wireframe) $tag"
1591            set _settings(polydata-wireframe) $settings(-wireframe)
1592            set havePolyData 1
1593        }
1594    }
1595    SetColormap $dataobj $comp
1596}
1597
1598itcl::body Rappture::GeoViewer::IsValidObject { dataobj } {
1599    return 1
1600}
1601
1602itcl::body Rappture::GeoViewer::SetOrientation { side } {
1603    array set positions {
1604        front "1 0 0 0"
1605        back  "0 0 1 0"
1606        left  "0.707107 0 -0.707107 0"
1607        right "0.707107 0 0.707107 0"
1608        top   "0.707107 -0.707107 0 0"
1609        bottom "0.707107 0.707107 0 0"
1610    }
1611    foreach name { qw qx qy qz } value $positions($side) {
1612        set _view($name) $value
1613    }
1614    set q [list $_view(qw) $_view(qx) $_view(qy) $_view(qz)]
1615    $_arcball quaternion $q
1616    SendCmd "camera orient $q"
1617    #SendCmd "camera reset"
1618    set _view(xpan) 0
1619    set _view(ypan) 0
1620    set _view(zoom) 1.0
1621}
1622
1623itcl::body Rappture::GeoViewer::SetOpacity { dataset } {
1624    foreach {dataobj comp} [split $dataset -] break
1625    set type [$dataobj type $comp]
1626    set val $_settings($type-opacity)
1627    set sval [expr { 0.01 * double($val) }]
1628    if { !$_obj2ovride($dataobj-raise) } {
1629        # This is wrong.  Need to figure out why raise isn't set with 1
1630        #set sval [expr $sval * .6]
1631    }
1632    SendCmd "$type opacity $sval $dataset"
1633}
Note: See TracBrowser for help on using the repository browser.