source: branches/1.3/gui/scripts/visviewer.tcl @ 4260

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

Remove duplicate entry

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