source: branches/r9/gui/scripts/visviewer.tcl @ 4348

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

Add method to VisViewer? to get list of pre-defined colormap names. There was
an issue with the name "blue" since it could also be used for a constant color,
but the named "blue" was actually a white-to-blue ramp, so it is now named
"white-to-blue". Also, some work on expanded color settings for glyph viewer.

File size: 38.6 KB
Line 
1# -*- mode: tcl; indent-tabs-mode: nil -*-
2
3# ----------------------------------------------------------------------
4#  VisViewer -
5#
6#  This class is the base class for the various visualization viewers
7#  that use the nanoserver render farm.
8#
9# ======================================================================
10#  AUTHOR:  Michael McLennan, Purdue University
11#  Copyright (c) 2004-2012  HUBzero Foundation, LLC
12#
13#  See the file "license.terms" for information on usage and
14#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15# ======================================================================
16
17itcl::class ::Rappture::VisViewer {
18    inherit itk::Widget
19
20    itk_option define -sendcommand sendCommand SendCommand ""
21    itk_option define -receivecommand receiveCommand ReceiveCommand ""
22
23    private common _servers         ;# array of visualization server lists
24    set _servers(geovis)  "localhost:2015"
25    set _servers(nanovis) "localhost:2000"
26    set _servers(pymol)   "localhost:2020"
27    set _servers(vmdmds)  "localhost:2018"
28    set _servers(vtkvis)  "localhost:2010"
29
30    protected variable _serverType "???";# Type of server.
31    protected variable _sid ""      ;   # socket connection to server
32    private common _done            ;   # Used to indicate status of send.
33    private variable _buffer        ;   # buffer for incoming/outgoing commands
34    private variable _initialized
35    private variable _isOpen 0
36    private variable _afterId -1
37    private variable _icon 0
38
39    # Number of milliseconds to wait before idle timeout.  If greater than
40    # 0, automatically disconnect from the visualization server when idle
41    # timeout is reached.
42    private variable _idleTimeout 43200000; # 12 hours
43    #private variable _idleTimeout 5000;    # 5 seconds
44    #private variable _idleTimeout 0;       # No timeout
45
46    protected variable _maxConnects 100
47    protected variable _outbuf       ;    # buffer for outgoing commands
48    protected variable _buffering 0
49
50    private variable _logging 0
51
52    protected variable _dispatcher "";  # dispatcher for !events
53    protected variable _hosts ""    ;   # list of hosts for server
54    protected variable _parser ""   ;   # interpreter for incoming commands
55    protected variable _image
56    protected variable _hostname
57    protected variable _numConnectTries 0
58    protected variable _debugConsole 0
59    protected variable _reportClientInfo 1
60    protected variable _waitTimeout 0
61
62    constructor { servers args } {
63        # defined below
64    }
65    destructor {
66        # defined below
67    }
68    # Used internally only.
69    private method Shuffle { servers }
70    private method ReceiveHelper {}
71    private method ServerDown {}
72    private method SendHelper {}
73    private method SendHelper.old {}
74    private method WaitDialog { state }
75
76    protected method ToggleConsole {}
77    private method DebugConsole {}
78    private method BuildConsole {}
79    private method HideConsole {}
80    private method TraceComm { channel {data {}} }
81    private method SendDebugCommand {}
82
83    protected method CheckConnection {}
84    protected method Color2RGB { color }
85    protected method ColorsToColormap { colors }
86    protected method Connect { servers }
87    protected method Disconnect {}
88    protected method EnableWaitDialog { timeout }
89    protected method Euler2XYZ { theta phi psi }
90    protected method Flush {}
91    protected method GetColormapList { args }
92    protected method HandleError { args }
93    protected method HandleOk { args }
94    protected method IsConnected {}
95    protected method ReceiveBytes { nbytes }
96    protected method ReceiveEcho { channel {data ""} }
97    protected method SendBytes { bytes }
98    protected method SendCmd {string}
99    protected method SendCmdNoWait {string}
100    protected method SendEcho { channel {data ""} }
101    protected method StartBufferingCommands {}
102    protected method StartWaiting {}
103    protected method StopBufferingCommands {}
104    protected method StopWaiting {}
105
106    private method Waiting { option widget }
107
108    private proc CheckNameList { namelist }  {
109        foreach host $namelist {
110            set pattern {^[a-zA-Z0-9\.]+:[0-9]}
111            if { ![regexp $pattern $host match] } {
112                error "bad visualization server address \"$host\": should be host:port,host:port,..."
113            }
114        }
115    }
116    public proc GetServerList { type } {
117        return $_servers($type)
118    }
119    public proc SetServerList { type namelist } {
120        # Convert the comma separated list into a Tcl list.  OGRE also adds
121        # a trailing comma that we want to ignore.
122        regsub -all "," $namelist " " namelist
123        CheckNameList $namelist
124        set _servers($type) $namelist
125    }
126    public proc RemoveServerFromList { type server } {
127        if { ![info exists _servers($type)] } {
128            error "unknown server type \"$type\""
129        }
130        set i [lsearch $_servers($type) $server]
131        if { $i < 0 } {
132            return
133        }
134        set _servers($type) [lreplace $_servers($type) $i $i]
135    }
136    public proc SetPymolServerList { namelist } {
137        SetServerList "pymol" $namelist
138    }
139    public proc SetNanovisServerList { namelist } {
140        SetServerList "nanovis" $namelist
141    }
142    public proc SetVtkServerList { namelist } {
143        SetServerList "vtk" $namelist
144    }
145}
146
147itk::usual Panedwindow {
148    keep -background -cursor
149}
150
151# ----------------------------------------------------------------------
152# CONSTRUCTOR
153# ----------------------------------------------------------------------
154itcl::body Rappture::VisViewer::constructor { servers args } {
155
156    Rappture::dispatcher _dispatcher
157    $_dispatcher register !serverDown
158    $_dispatcher dispatch $this !serverDown "[itcl::code $this ServerDown]; list"
159    $_dispatcher register !timeout
160    $_dispatcher dispatch $this !timeout "[itcl::code $this Disconnect]; list"
161
162    $_dispatcher register !waiting
163
164    CheckNameList $servers
165    set _buffer(in) ""
166    set _buffer(out) ""
167    #
168    # Create a parser to handle incoming requests
169    #
170    set _parser [interp create -safe]
171    foreach cmd [$_parser eval {info commands}] {
172        $_parser hide $cmd
173    }
174    # Add default handlers for "ok" acknowledgement and server errors.
175    $_parser alias ok       [itcl::code $this HandleOk]
176    $_parser alias viserror [itcl::code $this HandleError]
177
178    #
179    # Set up the widgets in the main body
180    #
181    option add hull.width hull.height
182    pack propagate $itk_component(hull) no
183
184    itk_component add main {
185        Rappture::SidebarFrame $itk_interior.main -resizeframe 1
186    }
187    pack $itk_component(main) -expand yes -fill both
188    set f [$itk_component(main) component frame]
189
190    itk_component add plotarea {
191        frame $f.plotarea -highlightthickness 0 -background black
192    } {
193        ignore -background
194    }
195    pack $itk_component(plotarea) -fill both -expand yes
196    set _image(plot) [image create photo]
197
198    global env
199    if { [info exists env(VISRECORDER)] } {
200        set _logging 1
201        if { [file exists /tmp/recording.log] } {
202            file delete /tmp/recording.log
203        }
204    }
205    eval itk_initialize $args
206}
207
208#
209# destructor --
210#
211itcl::body Rappture::VisViewer::destructor {} {
212    $_dispatcher cancel !timeout
213    interp delete $_parser
214    array unset _done $this
215}
216
217#
218# Shuffle --
219#
220#   Shuffle the list of server hosts.
221#
222itcl::body Rappture::VisViewer::Shuffle { hosts } {
223    set randomHosts {}
224    set ticks [clock clicks]
225    expr {srand($ticks)}
226    for { set i [llength $hosts] } { $i > 0 } { incr i -1 } {
227        set index [expr {round(rand()*$i - 0.5)}]
228        if { $index == $i } {
229            set index [expr $i - 1]
230        }
231        lappend randomHosts [lindex $hosts $index]
232        set hosts [lreplace $hosts $index $index]
233    }
234    return $randomHosts
235}
236
237#
238# ServerDown --
239#
240#    Used internally to let the user know when the connection to the
241#    visualization server has been lost.  Puts up a tip encouraging the
242#    user to press any control to reconnect.
243#
244itcl::body Rappture::VisViewer::ServerDown {} {
245    if { [info exists itk_component(plotarea)] } {
246        set x [expr {[winfo rootx $itk_component(plotarea)]+10}]
247        set y [expr {[winfo rooty $itk_component(plotarea)]+10}]
248    } else {
249        set x 0; set y 0
250    }
251    Rappture::Tooltip::cue @$x,$y "Lost connection to visualization server.  This happens sometimes when there are too many users and the system runs out of memory.\n\nTo reconnect, reset the view or press any other control.  Your picture should come right back up."
252}
253
254#
255# Connect --
256#
257#    Connect to the visualization server (e.g. nanovis, pymolproxy).
258#    Creates an event callback that is triggered when we are idle
259#    (no I/O with the server) for some specified time.
260#
261itcl::body Rappture::VisViewer::Connect { servers } {
262    blt::busy hold $itk_component(hull) -cursor watch
263
264    if { $_numConnectTries > $_maxConnects } {
265        blt::busy release $itk_component(hull)
266        set x [expr {[winfo rootx $itk_component(hull)]+10}]
267        set y [expr {[winfo rooty $itk_component(hull)]+10}]
268        Rappture::Tooltip::cue @$x,$y "Exceeded maximum number of connection attmepts to any $_serverType visualization server. Please contact support."
269        return 0;
270    }
271    foreach server [Shuffle $servers] {
272        puts stderr "connecting to $server..."
273        foreach {hostname port} [split $server ":"] break
274        if { [catch {socket $hostname $port} _sid] != 0 } {
275            set _sid ""
276            RemoveServerFromList $_serverType $server
277            continue
278        }
279        incr _numConnectTries
280        set _hostname $server
281        fconfigure $_sid -translation binary -encoding binary
282       
283        # Read back the server identification string.
284        if { [gets $_sid data] <= 0 } {
285            set _sid ""
286            puts stderr "reading from server data=($data)"
287            RemoveServerFromList $_serverType $server
288            continue
289        }
290        puts stderr "Render server is $data"
291        # We're connected. Cancel any pending serverDown events and
292        # release the busy window over the hull.
293        $_dispatcher cancel !serverDown
294        if { $_idleTimeout > 0 } {
295            $_dispatcher event -after $_idleTimeout !timeout
296        }
297        blt::busy release $itk_component(hull)
298        fconfigure $_sid -buffering line
299        fileevent $_sid readable [itcl::code $this ReceiveHelper]
300        return 1
301    }
302    blt::busy release $itk_component(hull)
303    set x [expr {[winfo rootx $itk_component(hull)]+10}]
304    set y [expr {[winfo rooty $itk_component(hull)]+10}]
305    Rappture::Tooltip::cue @$x,$y "Can't connect to any $_serverType visualization server.  This may be a network problem.  Wait a few moments and try resetting the view."
306    return 0
307}
308
309#
310# Disconnect --
311#
312#    Clients use this method to disconnect from the current rendering
313#    server.  Cancel any pending idle timeout events.
314#
315itcl::body Rappture::VisViewer::Disconnect {} {
316    after cancel $_afterId
317    $_dispatcher cancel !timeout
318    catch {close $_sid}
319    set _sid ""
320    set _buffer(in) ""
321    set _outbuf ""
322}
323
324#
325# IsConnected --
326#
327#    Indicates if we are currently connected to a server.
328#
329itcl::body Rappture::VisViewer::IsConnected {} {
330    if { $_sid == "" } {
331        return 0
332    }
333    if { [eof $_sid] } {
334        set _sid ""
335        return 0
336    }
337    return 1
338}
339
340#
341# CheckConection --
342#
343#   This routine is called whenever we're about to send/receive data on
344#   the socket connection to the visualization server.  If we're connected,
345#   then reset the timeout event.  Otherwise try to reconnect to the
346#   visualization server.
347#
348itcl::body Rappture::VisViewer::CheckConnection {} {
349    $_dispatcher cancel !timeout
350    if { $_idleTimeout > 0 } {
351        $_dispatcher event -after $_idleTimeout !timeout
352    }
353    if { [IsConnected] } {
354        return 1
355    }
356    if { $_sid != "" } {
357        fileevent $_sid writable ""
358    }
359    # If we aren't connected, assume it's because the connection to the
360    # visualization server broke. Try to open a connection and trigger a
361    # rebuild.
362    $_dispatcher cancel !serverDown
363    set x [expr {[winfo rootx $itk_component(plotarea)]+10}]
364    set y [expr {[winfo rooty $itk_component(plotarea)]+10}]
365    Rappture::Tooltip::cue @$x,$y "Connecting..."
366    set code [catch { Connect } ok]
367    if { $code == 0 && $ok} {
368        $_dispatcher event -idle !rebuild
369        Rappture::Tooltip::cue hide
370    } else {
371        Rappture::Tooltip::cue @$x,$y "Can't connect to any $_serverType visualization server.  This may be a network problem.  Wait a few moments and try resetting the view."
372        return 0
373    }
374    return 1
375}
376
377#
378# Flush --
379#
380#    Flushes the socket.
381#
382itcl::body Rappture::VisViewer::Flush {} {
383    if { [CheckConnection] } {
384        flush $_sid
385    }
386}
387
388
389#
390# SendHelper --
391#
392#   Helper routine called from a file event to send data when the
393#   connection is writable (i.e. not blocked).  Sets a magic variable
394#   _done($this) when we're done.
395#
396itcl::body Rappture::VisViewer::SendHelper {} {
397    if { ![CheckConnection] } {
398        return 0
399    }
400    puts -nonewline $_sid $_buffer(out)
401    flush $_sid
402    set _done($this) 1;                 # Success
403}
404
405#
406# SendHelper.old --
407#
408#   Helper routine called from a file event to send data when the
409#   connection is writable (i.e. not blocked).  Sends data in chunks of 8k
410#   (or less).  Sets magic variable _done($this) to indicate that we're
411#   either finished (success) or could not send bytes to the server
412#   (failure).
413#
414itcl::body Rappture::VisViewer::SendHelper.old {} {
415    if { ![CheckConnection] } {
416        return 0
417    }
418    set bytesLeft [string length $_buffer(out)]
419    if { $bytesLeft > 0} {
420        set chunk [string range $_buffer(out) 0 8095]
421        set _buffer(out)  [string range $_buffer(out) 8096 end]
422        incr bytesLeft -8096
423        set code [catch {
424            if { $bytesLeft > 0 } {
425                puts -nonewline $_sid $chunk
426            } else {
427                puts $_sid $chunk
428            }
429        } err]
430        if { $code != 0 } {
431            puts stderr "error sending data to $_sid: $err"
432            Disconnect
433            set _done($this) 0;     # Failure
434        }
435    } else {
436        set _done($this) 1;     # Success
437    }
438}
439
440#
441# SendBytes --
442#
443#   Send a a string to the visualization server.
444#
445itcl::body Rappture::VisViewer::SendBytes { bytes } {
446    SendEcho >>line $bytes
447    if { ![CheckConnection] } {
448        return 0
449    }
450    StartWaiting
451    # Even though the data is sent in only 1 "puts", we need to verify that
452    # the server is ready first.  Wait for the socket to become writable
453    # before sending anything.
454    set _done($this) 1
455    set _buffer(out) $bytes
456    if {1} {
457        # Let's try this approach: allow a write to block so we don't
458        # re-enter SendBytes
459        SendHelper
460    } else {
461        # This can cause us to re-enter SendBytes during the tkwait, which
462        # is not safe because the _buffer will be clobbered
463        fileevent $_sid writable [itcl::code $this SendHelper]
464        tkwait variable ::Rappture::VisViewer::_done($this)
465    }
466    set _buffer(out) ""
467    if { [IsConnected] } {
468        # The connection may have closed while we were writing to the
469        # server.  This can happen if what we sent the server caused it to
470        # barf.
471        fileevent $_sid writable ""
472        flush $_sid
473    }
474    return $_done($this)
475}
476
477#
478# StartWaiting --
479#
480#    Read some number of bytes from the visualization server.
481#
482
483itcl::body Rappture::VisViewer::StartWaiting {} {
484    if { $_waitTimeout > 0 } {
485        after cancel $_afterId
486        set _afterId [after $_waitTimeout [itcl::code $this WaitDialog on]]
487    }
488}
489
490itcl::body Rappture::VisViewer::StopWaiting {} {
491    if { $_waitTimeout > 0 } {
492        WaitDialog off
493    }
494}
495
496itcl::body Rappture::VisViewer::EnableWaitDialog { value } {
497    set _waitTimeout $value
498}
499
500#
501# ReceiveBytes --
502#
503#    Read some number of bytes from the visualization server.
504#
505itcl::body Rappture::VisViewer::ReceiveBytes { size } {
506    if { ![CheckConnection] } {
507        return 0
508    }
509    set bytes [read $_sid $size]
510    ReceiveEcho <<line "<read $size bytes"
511    StopWaiting
512    return $bytes
513}
514
515#
516# ReceiveHelper --
517#
518#   Helper routine called from a file event when the connection is readable
519#   (i.e. a command response has been sent by the rendering server.  Reads
520#   the incoming command and executes it in a safe interpreter to handle
521#   the action.
522#
523#       Note: This routine currently only handles command responses from
524#         the visualization server.  It doesn't handle non-blocking
525#         reads from the visualization server.
526#
527#       nv>image -bytes 100000      yes
528#       ...following 100000 bytes...    no
529#
530#   Note: All commands from the render server are on one line.
531#         This is because the render server can send anything
532#         as an error message (restricted again to one line).
533#
534itcl::body Rappture::VisViewer::ReceiveHelper {} {
535    if { ![CheckConnection] } {
536        return 0
537    }
538    set n [gets $_sid line]
539
540    if { $n < 0 } {
541        Disconnect
542        return 0
543    }
544    set line [string trim $line]
545    if { $line == "" } {
546        return
547    }
548    if { [string compare -length 3 $line "nv>"] == 0 } {
549        ReceiveEcho <<line $line
550        append _buffer(in) [string range $line 3 end]
551        append _buffer(in) "\n"
552        if {[info complete $_buffer(in)]} {
553            set request $_buffer(in)
554            set _buffer(in) ""
555            if { [catch {$_parser eval $request} err]  != 0 } {
556                global errorInfo
557                puts stderr "err=$err errorInfo=$errorInfo"
558            }
559        }
560    } elseif { [string compare -length 21 $line "NanoVis Server Error:"] == 0 ||
561               [string compare -length 20 $line "VtkVis Server Error:"] == 0} {
562        # this shows errors coming back from the engine
563        ReceiveEcho <<error $line
564        puts stderr "Render Server Error: $line\n"
565    } else {
566        # this shows errors coming back from the engine
567        ReceiveEcho <<error $line
568        puts stderr "Garbled message: $line\n"
569    }
570}
571
572#
573# Color2RGB --
574#
575#   Converts a color name to a list of r,g,b values needed for the engine.
576#   Each r/g/b component is scaled in the # range 0-1.
577#
578itcl::body Rappture::VisViewer::Color2RGB {color} {
579    foreach {r g b} [winfo rgb $itk_component(hull) $color] break
580    set r [expr {$r/65535.0}]
581    set g [expr {$g/65535.0}]
582    set b [expr {$b/65535.0}]
583    return [list $r $g $b]
584}
585
586#
587# Euler2XYZ --
588#
589#   Converts euler angles for the camera placement the to angles of
590#   rotation about the x/y/z axes, used by the engine.  Returns a list:
591#   {xangle, yangle, zangle}.
592#
593itcl::body Rappture::VisViewer::Euler2XYZ {theta phi psi} {
594    set xangle [expr {$theta-90.0}]
595    set yangle [expr {180.0-$phi}]
596    set zangle $psi
597    return [list $xangle $yangle $zangle]
598}
599
600#
601# SendEcho --
602#
603#     Used internally to echo sent data to clients interested in this
604#     widget.  If the -sendcommand opti on is set, then it is invoked in
605#     the global scope with the <channel> and <data> values as arguments.
606#     Otherwise, this does nothing.
607#
608itcl::body Rappture::VisViewer::SendEcho {channel {data ""}} {
609    if { $_logging }  {
610        set f [open "/tmp/recording.log" "a"]
611        puts $f $data
612        close $f
613    }
614    #puts stderr ">>($data)"
615    if {[string length $itk_option(-sendcommand)] > 0} {
616        uplevel #0 $itk_option(-sendcommand) [list $channel $data]
617    }
618}
619
620#
621# ReceiveEcho --
622#
623#     Echoes received data to clients interested in this widget.  If the
624#     -receivecommand option is set, then it is invoked in the global scope
625#     with the <channel> and <data> values as arguments.  Otherwise, this
626#     does nothing.
627#
628itcl::body Rappture::VisViewer::ReceiveEcho {channel {data ""}} {
629    #puts stderr "<<line $data"
630    if {[string length $itk_option(-receivecommand)] > 0} {
631        uplevel #0 $itk_option(-receivecommand) [list $channel $data]
632    }
633}
634
635itcl::body Rappture::VisViewer::WaitDialog { state } {
636    after cancel $_afterId
637    set _afterId -1
638    if { $state } {
639        if { [winfo exists $itk_component(plotarea).view.splash] } {
640            return
641        }
642        set inner [frame $itk_component(plotarea).view.splash]
643        $inner configure -relief raised -bd 2
644        label $inner.text1 -text "Working...\nPlease wait." \
645            -font "Arial 10"
646        label $inner.icon
647        pack $inner -expand yes -anchor c
648        blt::table $inner \
649            0,0 $inner.text1 -anchor w \
650            0,1 $inner.icon
651        Waiting start $inner.icon
652    } else {
653        if { ![winfo exists $itk_component(plotarea).view.splash] } {
654            return
655        }
656        Waiting stop $itk_component(plotarea).view.splash
657        destroy $itk_component(plotarea).view.splash
658    }
659}
660
661itcl::body Rappture::VisViewer::Waiting { option widget } {
662    switch -- $option {
663        "start" {
664            $_dispatcher dispatch $this !waiting \
665                "[itcl::code $this Waiting "next" $widget] ; list"
666            set _icon 0
667            $widget configure -image [Rappture::icon bigroller${_icon}]
668            $_dispatcher event -after 150 !waiting
669        }
670        "next" {
671            incr _icon
672            if { $_icon >= 8 } {
673                set _icon 0
674            }
675            $widget configure -image [Rappture::icon bigroller${_icon}]
676            $_dispatcher event -after 150 !waiting
677        }
678        "stop" {
679            $_dispatcher cancel !waiting
680        }
681    }
682}
683
684#
685# HideConsole --
686#
687#    Hide the debug console by withdrawing its toplevel window.
688#
689itcl::body Rappture::VisViewer::HideConsole {} {
690    set _debugConsole 0
691    DebugConsole
692}
693
694#
695# BuildConsole --
696#
697#    Create and pack the widgets that make up the debug console: a text
698#    widget to display the communication and an entry widget to type
699#    in commands to send to the render server.
700#
701itcl::body Rappture::VisViewer::BuildConsole {} {
702    toplevel .renderconsole
703    wm protocol .renderconsole WM_DELETE_WINDOW [itcl::code $this HideConsole]
704    set f .renderconsole
705    frame $f.send
706    pack $f.send -side bottom -fill x
707    label $f.send.l -text "Send:"
708    pack $f.send.l -side left
709    itk_component add command {
710        entry $f.send.e -background white
711    } {
712        ignore -background
713    }
714    pack $f.send.e -side left -expand yes -fill x
715    bind $f.send.e <Return> [itcl::code $this SendDebugCommand]
716    bind $f.send.e <KP_Enter> [itcl::code $this SendDebugCommand]
717    scrollbar $f.sb -orient vertical -command "$f.comm yview"
718    pack $f.sb -side right -fill y
719    itk_component add trace {
720        text $f.comm -wrap char -yscrollcommand "$f.sb set" -background white
721    } {
722        ignore -background
723    }
724    pack $f.comm -expand yes -fill both
725    bind $f.comm <Control-F1> [itcl::code $this ToggleConsole]
726    bind $f.comm <Enter> [list focus %W]
727    bind $f.send.e <Control-F1> [itcl::code $this ToggleConsole]
728
729    $itk_component(trace) tag configure error -foreground red \
730        -font -*-courier-medium-o-normal-*-*-120-*
731    $itk_component(trace) tag configure incoming -foreground blue
732}
733
734#
735# ToggleConsole --
736#
737#    This is used by derived classes to turn on/off debuging.  It's
738#    up the to derived class to decide how to turn on/off debugging.
739#
740itcl::body Rappture::VisViewer::ToggleConsole {} {
741    if { $_debugConsole } {
742        set _debugConsole 0
743    } else {
744        set _debugConsole 1
745    }
746    DebugConsole
747}
748
749#
750# DebugConsole --
751#
752#    Based on the value of the variable _debugConsole, turns on/off
753#    debugging. This is done by setting/unsetting a procedure that
754#    is called whenever new characters are received or sent on the
755#    socket to the render server.  Additionally, the debug console
756#    is created if necessary and hidden/shown.
757#
758itcl::body Rappture::VisViewer::DebugConsole {} {
759    if { ![winfo exists .renderconsole] } {
760        BuildConsole
761    }
762    if { $_debugConsole } {
763        $this configure -sendcommand [itcl::code $this TraceComm]
764        $this configure -receivecommand [itcl::code $this TraceComm]
765        wm deiconify .renderconsole
766    } else {
767        $this configure -sendcommand ""
768        $this configure -receivecommand ""
769        wm withdraw .renderconsole
770    }
771}
772
773# ----------------------------------------------------------------------
774# USAGE: TraceComm <channel> <data>
775#
776# Invoked automatically whenever there is communication between
777# the rendering widget and the server.  Eavesdrops on the communication
778# and posts the commands in a text viewer.
779# ----------------------------------------------------------------------
780itcl::body Rappture::VisViewer::TraceComm {channel {data ""}} {
781    $itk_component(trace) configure -state normal
782    switch -- $channel {
783        closed {
784            $itk_component(trace) insert end "--CLOSED--\n" error
785        }
786        <<line {
787            $itk_component(trace) insert end $data incoming "\n" incoming
788        }
789        >>line {
790            $itk_component(trace) insert end $data outgoing "\n" outgoing
791        }
792        error {
793            $itk_component(trace) insert end $data error "\n" error
794        }
795        default {
796            $itk_component(trace) insert end "$data\n"
797        }
798    }
799    $itk_component(trace) configure -state disabled
800    $itk_component(trace) see end
801}
802
803# ----------------------------------------------------------------------
804# USAGE: SendDebugCommand
805#
806# Invoked automatically whenever the user enters a command and
807# presses <Return>.  Sends the command along to the rendering
808# widget.
809# ----------------------------------------------------------------------
810itcl::body Rappture::VisViewer::SendDebugCommand {} {
811    set cmd [$itk_component(command) get]
812    append cmd "\n"
813    SendBytes $cmd
814    $itk_component(command) delete 0 end
815}
816
817#
818# HandleOk --
819#
820#       This handles the "ok" response from the server that acknowledges
821#       the reception of a server command, but does not produce an image.
822#       It may pass an argument such as "-token 9" that could be used to
823#       determine how many commands have been processed by the server.
824#
825itcl::body Rappture::VisViewer::HandleOk { args } {
826    if { $_waitTimeout > 0 } {
827        StopWaiting
828    }
829}
830
831#
832# HandleError --
833#
834#       This handles the "viserror" response from the server that reports
835#       that a client-initiated error has occurred on the server.
836#
837itcl::body Rappture::VisViewer::HandleError { args } {
838    array set info {
839        -token "???"
840        -bytes 0
841        -type "???"
842    }
843    array set info $args
844    set bytes [ReceiveBytes $info(-bytes)]
845    if { $info(-type) == "error" } {
846        set popup $itk_component(hull).error
847        if { ![winfo exists $popup] } {
848            Rappture::Balloon $popup \
849                -title "Render Server Error"
850            set inner [$popup component inner]
851            label $inner.summary -text "" -anchor w
852
853            Rappture::Scroller $inner.scrl \
854                -xscrollmode auto -yscrollmode auto
855            text $inner.scrl.text \
856                -font "Arial 9 " -background white -relief sunken -bd 1 \
857                -height 5 -wrap word -width 60
858            $inner.scrl contents $inner.scrl.text
859            button $inner.ok -text "Dismiss" -command [list $popup deactivate] \
860                -font "Arial 9"
861            blt::table $inner \
862                0,0 $inner.scrl -fill both \
863                1,0 $inner.ok
864            $inner.scrl.text tag configure normal -font "Arial 9"
865            $inner.scrl.text tag configure italic -font "Arial 9 italic"
866            $inner.scrl.text tag configure bold -font "Arial 10 bold"
867            $inner.scrl.text tag configure code -font "Courier 10 bold"
868        } else {
869            $popup deactivate
870        }
871        update
872        set inner [$popup component inner]
873        $inner.scrl.text delete 0.0 end
874       
875        $inner.scrl.text configure -state normal
876        $inner.scrl.text insert end "The following error was reported by the render server:\n\n" bold
877        $inner.scrl.text insert end $bytes code
878        $inner.scrl.text configure -state disabled
879        update
880        $popup activate $itk_component(hull) below
881    } else {
882        ReceiveEcho <<error $bytes
883        puts stderr "Render server error:\n$bytes"
884    }
885}
886
887itcl::body Rappture::VisViewer::GetColormapList { args } {
888    array set opts {
889        -includeDefault 0
890        -includeElementDefault 0
891        -includeNone 0
892    }
893    if {[llength $args] > 0} {
894        foreach opt $args {
895            set opts($opt) 1
896        }
897    }
898    set colormaps [list]
899    if {$opts(-includeDefault)} {
900        lappend colormaps "default" "default"
901    }
902    if {$opts(-includeElementDefault)} {
903        lappend colormaps "elementDefault" "elementDefault"
904    }
905    lappend colormaps \
906        "BCGYR"              "BCGYR"            \
907        "BGYOR"              "BGYOR"            \
908        "blue-to-brown"      "blue-to-brown"    \
909        "blue-to-orange"     "blue-to-orange"   \
910        "blue-to-grey"       "blue-to-grey"     \
911        "green-to-magenta"   "green-to-magenta" \
912        "greyscale"          "greyscale"        \
913        "nanohub"            "nanohub"          \
914        "rainbow"            "rainbow"          \
915        "spectral"           "spectral"         \
916        "ROYGB"              "ROYGB"            \
917        "RYGCB"              "RYGCB"            \
918        "white-to-blue"      "white-to-blue"    \
919        "brown-to-blue"      "brown-to-blue"    \
920        "grey-to-blue"       "grey-to-blue"     \
921        "orange-to-blue"     "orange-to-blue"
922    if {$opts(-includeNone)} {
923        lappend colormaps "none" "none"
924    }
925    return $colormaps
926}
927
928itcl::body Rappture::VisViewer::ColorsToColormap { colors } {
929    switch -- $colors {
930        "grey-to-blue" {
931            return {
932                0.0                      0.200 0.200 0.200
933                0.14285714285714285      0.400 0.400 0.400
934                0.2857142857142857       0.600 0.600 0.600
935                0.42857142857142855      0.900 0.900 0.900
936                0.5714285714285714       0.800 1.000 1.000
937                0.7142857142857143       0.600 1.000 1.000
938                0.8571428571428571       0.400 0.900 1.000
939                1.0                      0.000 0.600 0.800
940            }
941        }
942        "blue-to-grey" {
943            return {
944                0.0                     0.000 0.600 0.800
945                0.14285714285714285     0.400 0.900 1.000
946                0.2857142857142857      0.600 1.000 1.000
947                0.42857142857142855     0.800 1.000 1.000
948                0.5714285714285714      0.900 0.900 0.900
949                0.7142857142857143      0.600 0.600 0.600
950                0.8571428571428571      0.400 0.400 0.400
951                1.0                     0.200 0.200 0.200
952            }
953        }
954        "white-to-blue" {
955            return {
956                0.0                     0.900 1.000 1.000
957                0.1111111111111111      0.800 0.983 1.000
958                0.2222222222222222      0.700 0.950 1.000
959                0.3333333333333333      0.600 0.900 1.000
960                0.4444444444444444      0.500 0.833 1.000
961                0.5555555555555556      0.400 0.750 1.000
962                0.6666666666666666      0.300 0.650 1.000
963                0.7777777777777778      0.200 0.533 1.000
964                0.8888888888888888      0.100 0.400 1.000
965                1.0                     0.000 0.250 1.000
966            }
967        }
968        "brown-to-blue" {
969            return {
970                0.0                             0.200   0.100   0.000
971                0.09090909090909091             0.400   0.187   0.000
972                0.18181818181818182             0.600   0.379   0.210
973                0.2727272727272727              0.800   0.608   0.480
974                0.36363636363636365             0.850   0.688   0.595
975                0.45454545454545453             0.950   0.855   0.808
976                0.5454545454545454              0.800   0.993   1.000
977                0.6363636363636364              0.600   0.973   1.000
978                0.7272727272727273              0.400   0.940   1.000
979                0.8181818181818182              0.200   0.893   1.000
980                0.9090909090909091              0.000   0.667   0.800
981                1.0                             0.000   0.480   0.600
982            }
983        }
984        "blue-to-brown" {
985            return {
986                0.0                             0.000   0.480   0.600
987                0.09090909090909091             0.000   0.667   0.800
988                0.18181818181818182             0.200   0.893   1.000
989                0.2727272727272727              0.400   0.940   1.000
990                0.36363636363636365             0.600   0.973   1.000
991                0.45454545454545453             0.800   0.993   1.000
992                0.5454545454545454              0.950   0.855   0.808
993                0.6363636363636364              0.850   0.688   0.595
994                0.7272727272727273              0.800   0.608   0.480
995                0.8181818181818182              0.600   0.379   0.210
996                0.9090909090909091              0.400   0.187   0.000
997                1.0                             0.200   0.100   0.000
998            }
999        }
1000        "blue-to-orange" {
1001            return {
1002                0.0                             0.000   0.167   1.000
1003                0.09090909090909091             0.100   0.400   1.000
1004                0.18181818181818182             0.200   0.600   1.000
1005                0.2727272727272727              0.400   0.800   1.000
1006                0.36363636363636365             0.600   0.933   1.000
1007                0.45454545454545453             0.800   1.000   1.000
1008                0.5454545454545454              1.000   1.000   0.800
1009                0.6363636363636364              1.000   0.933   0.600
1010                0.7272727272727273              1.000   0.800   0.400
1011                0.8181818181818182              1.000   0.600   0.200
1012                0.9090909090909091              1.000   0.400   0.100
1013                1.0                             1.000   0.167   0.000
1014            }
1015        }
1016        "orange-to-blue" {
1017            return {
1018                0.0                             1.000   0.167   0.000
1019                0.09090909090909091             1.000   0.400   0.100
1020                0.18181818181818182             1.000   0.600   0.200
1021                0.2727272727272727              1.000   0.800   0.400
1022                0.36363636363636365             1.000   0.933   0.600
1023                0.45454545454545453             1.000   1.000   0.800
1024                0.5454545454545454              0.800   1.000   1.000
1025                0.6363636363636364              0.600   0.933   1.000
1026                0.7272727272727273              0.400   0.800   1.000
1027                0.8181818181818182              0.200   0.600   1.000
1028                0.9090909090909091              0.100   0.400   1.000
1029                1.0                             0.000   0.167   1.000
1030            }
1031        }
1032        "rainbow" {
1033            set clist {
1034                "#EE82EE"
1035                "#4B0082"
1036                "blue"
1037                "#008000"
1038                "yellow"
1039                "#FFA500"
1040                "red"
1041            }
1042        }
1043        "BGYOR" {
1044            set clist {
1045                "blue"
1046                "#008000"
1047                "yellow"
1048                "#FFA500"
1049                "red"
1050            }
1051        }
1052        "ROYGB" {
1053            set clist {
1054                "red"
1055                "#FFA500"
1056                "yellow"
1057                "#008000"
1058                "blue"
1059            }
1060        }
1061        "RYGCB" {
1062            set clist {
1063                "red"
1064                "yellow"
1065                "green"
1066                "cyan"
1067                "blue"
1068            }
1069        }
1070        "BCGYR" {
1071            set clist {
1072                "blue"
1073                "cyan"
1074                "green"
1075                "yellow"
1076                "red"
1077            }
1078        }
1079        "spectral" {
1080            return {
1081                0.0 0.150 0.300 1.000
1082                0.1 0.250 0.630 1.000
1083                0.2 0.450 0.850 1.000
1084                0.3 0.670 0.970 1.000
1085                0.4 0.880 1.000 1.000
1086                0.5 1.000 1.000 0.750
1087                0.6 1.000 0.880 0.600
1088                0.7 1.000 0.680 0.450
1089                0.8 0.970 0.430 0.370
1090                0.9 0.850 0.150 0.196
1091                1.0 0.650 0.000 0.130
1092            }
1093        }
1094        "green-to-magenta" {
1095            return {
1096                0.0 0.000 0.316 0.000
1097                0.06666666666666667 0.000 0.526 0.000
1098                0.13333333333333333 0.000 0.737 0.000
1099                0.2 0.000 0.947 0.000
1100                0.26666666666666666 0.316 1.000 0.316
1101                0.3333333333333333 0.526 1.000 0.526
1102                0.4 0.737 1.000 0.737
1103                0.4666666666666667 1.000 1.000 1.000
1104                0.5333333333333333 1.000 0.947 1.000
1105                0.6 1.000 0.737 1.000
1106                0.6666666666666666 1.000 0.526 1.000
1107                0.7333333333333333 1.000 0.316 1.000
1108                0.8 0.947 0.000 0.947
1109                0.8666666666666667 0.737 0.000 0.737
1110                0.9333333333333333 0.526 0.000 0.526
1111                1.0 0.316 0.000 0.316
1112            }
1113        }
1114        "greyscale" {
1115            return {
1116                0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0
1117            }
1118        }
1119        "nanohub" {
1120            set clist "white yellow green cyan blue magenta"
1121        }
1122        default {
1123            set clist [split $colors ":"]
1124        }
1125    }
1126    set cmap {}
1127    if { [llength $clist] == 1 } {
1128        set rgb [Color2RGB $clist]
1129        append cmap "0.0 $rgb 1.0 $rgb"
1130    } else {
1131        for {set i 0} {$i < [llength $clist]} {incr i} {
1132            set x [expr {double($i)/([llength $clist]-1)}]
1133            set color [lindex $clist $i]
1134            append cmap "$x [Color2RGB $color] "
1135        }
1136    }
1137    #regsub -all "\n" $cmap " " cmap
1138    return $cmap
1139}
1140
1141
1142#
1143# StartBufferingCommands --
1144#
1145itcl::body Rappture::VisViewer::StartBufferingCommands { } {
1146    incr _buffering
1147    if { $_buffering == 1 } {
1148        set _outbuf ""
1149    }
1150}
1151
1152#
1153# StopBufferingCommands --
1154#
1155itcl::body Rappture::VisViewer::StopBufferingCommands { } {
1156    incr _buffering -1
1157    if { $_buffering == 0 } {
1158        SendBytes $_outbuf
1159        set _outbuf ""
1160    }
1161}
1162
1163#
1164# SendCmd
1165#
1166#       Send commands off to the rendering server.  If we're currently
1167#       sending data objects to the server, buffer the commands to be
1168#       sent later.
1169#
1170itcl::body Rappture::VisViewer::SendCmd {string} {
1171    if { $_buffering } {
1172        append _outbuf $string "\n"
1173    } else {
1174        SendBytes "$string\n"
1175    }
1176}
1177
1178#
1179# SendCmdNoWait
1180#
1181#       Send commands off to the rendering server.  If we're currently
1182#       sending data objects to the server, buffer the commands to be
1183#       sent later.
1184#
1185itcl::body Rappture::VisViewer::SendCmdNoWait {string} {
1186    if { $_buffering } {
1187        append _outbuf $string "\n"
1188    } else {
1189        SendBytes "$string\n"
1190    }
1191}
Note: See TracBrowser for help on using the repository browser.