source: trunk/gui/scripts/analyzer.tcl @ 213

Last change on this file since 213 was 213, checked in by mmc, 18 years ago
  • Fixed up the tool tips for upload to remind the user about allowing pop ups, and to catch errors when the user uploads nothing.
  • Added a protocol version number to the filexfer applet, so Rappture can warn when the applet is out-of-date with respect to the application. (Thanks, Rick!)
File size: 36.7 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: analyzer - output area for Rappture
3#
4#  This widget acts as the output side of a Rappture application.
5#  When the input has changed, it displays a Simulate button that
6#  launches the simulation.  When a simulation is running, this
7#  area shows status.  When it is finished, the results appear
8#  in place of the button, according to the specs in the <analyze>
9#  XML data.
10# ======================================================================
11#  AUTHOR:  Michael McLennan, Purdue University
12#  Copyright (c) 2004-2005  Purdue Research Foundation
13#
14#  See the file "license.terms" for information on usage and
15#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16# ======================================================================
17package require Itk
18
19option add *Analyzer.width 3.5i widgetDefault
20option add *Analyzer.height 4i widgetDefault
21option add *Analyzer.simControl "auto" widgetDefault
22option add *Analyzer.simControlBackground "" widgetDefault
23option add *Analyzer.simControlOutline gray widgetDefault
24option add *Analyzer.simControlActiveBackground #ffffcc widgetDefault
25option add *Analyzer.simControlActiveOutline black widgetDefault
26
27option add *Analyzer.font \
28    -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
29option add *Analyzer.codeFont \
30    -*-courier-medium-r-normal-*-*-120-* widgetDefault
31option add *Analyzer.textFont \
32    -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
33option add *Analyzer.boldTextFont \
34    -*-helvetica-bold-r-normal-*-*-120-* widgetDefault
35
36itcl::class Rappture::Analyzer {
37    inherit itk::Widget
38
39    itk_option define -codefont codeFont Font ""
40    itk_option define -textfont textFont Font ""
41    itk_option define -boldtextfont boldTextFont Font ""
42    itk_option define -simcontrol simControl SimControl ""
43    itk_option define -simcontroloutline simControlOutline Background ""
44    itk_option define -simcontrolbackground simControlBackground Background ""
45    itk_option define -simcontrolactiveoutline simControlActiveOutline Background ""
46    itk_option define -simcontrolactivebackground simControlActiveBackground Background ""
47    itk_option define -holdwindow holdWindow HoldWindow ""
48
49    constructor {tool args} { # defined below }
50    destructor { # defined below }
51
52    public method simulate {args}
53    public method reset {}
54    public method load {file}
55    public method clear {}
56    public method download {option args}
57
58    protected method _plot {args}
59    protected method _reorder {comps}
60    protected method _autoLabel {xmlobj path title cntVar}
61    protected method _fixResult {}
62    protected method _fixSize {}
63    protected method _fixSimControl {}
64    protected method _simState {state args}
65    protected method _simOutput {message}
66
67    private variable _tool ""          ;# belongs to this tool
68    private variable _control "manual" ;# start mode
69    private variable _runs ""          ;# list of XML objects with results
70    private variable _pages 0          ;# number of pages for result sets
71    private variable _label2page       ;# maps output label => result set
72    private variable _lastlabel ""     ;# label of last example loaded
73    private variable _plotlist ""      ;# items currently being plotted
74
75    private common job                 ;# array var used for blt::bgexec jobs
76
77    private common icons
78    set icons(download) [image create photo -data {
79R0lGODlhFAAUAMYBAAAAAP///+js9vL1+4yhxrbD21h6sFp8slx+tV6Bt2CFumSIvmOHvWaLwGyS
80yG6UynCRwWiOw2yUyXCZzm+XzG+Wy3Oc0XKaz3We1Hqk23mj2Xqk2nmi2ICex/T3+3Od0nqm3Hag
811Xun3Iat3ZK56JK03t7n8uzy+PX4+/f5+/T4+/L3+vn7/Pj7/Pf7/Pb6+/n9/fz///r9/fn8/Pz+
82/vv9/fr8/Pz9/UGMfluegZzRp6XYqwWXC67frwCZAAKaAgOaAgOaAwWbBQabBQicCA6fDg6eDw+f
83Dw+fEA+eDxCfEF6/Xl+/X6TbpKbbpqzerK7frq3era/fr/z+/P3+/bXjsXjSbKrjotbw02bSVKvj
84olnSQYPfcJbjh5/jk1TSOV7XQm3bVIvidprmiKjqmXTgV4DjZrPuo7TupNb1zo/qc5nsf8L0s8Hz
85sar0j7L1mdD5wdH5wur+4eL91f///////////////////////////////////////////////yH5
86BAEAAH8ALAIAAgAQABAAAAfYgAUlIiAbHCEYHxcTFRIdBX8jJJOUlZQQfyKam5ycDX8ZAaKjpKMM
87fxoBLC0pHis7Rz5GOiYBCn8cATI2LC8oSFhVWEkCAQl/IQE3NTIzLj5aVlc+JwEIfxgBNDXLMD5e
88WV4+AwEHfxbaNNs1Pl1bXT4qAQZ/FAExPUo++1xfXPs+eEh5IIpJGjJjxIQBE0bMGDJpljgQFQUI
89GjNlMmY0c0bIEwIRGizAEYTNGjUo17QhkoPKn5cvnwSJ88bNGzhEmkyByfPJDzlz5AxxspMnTyix
90ijxx+TIQADs=
91}]
92}
93                                                                               
94itk::usual Analyzer {
95    keep -background -cursor foreground -font
96}
97
98# ----------------------------------------------------------------------
99# CONSTRUCTOR
100# ----------------------------------------------------------------------
101itcl::body Rappture::Analyzer::constructor {tool args} {
102    set _tool $tool
103
104    itk_option add hull.width hull.height
105    pack propagate $itk_component(hull) no
106
107    frame $itk_interior.simol -borderwidth 1 -relief flat
108    pack $itk_interior.simol -fill x
109
110    frame $itk_interior.simol.simbg -borderwidth 0
111    pack $itk_interior.simol.simbg -expand yes -fill both
112
113    itk_component add simulate {
114        button $itk_interior.simol.simbg.simulate -text "Simulate" \
115            -command [itcl::code $this simulate]
116    }
117    pack $itk_component(simulate) -side left -padx 4 -pady 4
118
119    itk_component add simstatus {
120        text $itk_interior.simol.simbg.simstatus -borderwidth 0 \
121            -highlightthickness 0 -height 1 -width 1 -wrap none \
122            -state disabled
123    } {
124        usual
125        ignore -highlightthickness
126        rename -font -textfont textFont Font
127    }
128    pack $itk_component(simstatus) -side left -expand yes -fill x
129
130    $itk_component(simstatus) tag configure popup \
131        -underline 1 -foreground blue
132
133    $itk_component(simstatus) tag bind popup \
134        <Enter> {%W configure -cursor center_ptr}
135    $itk_component(simstatus) tag bind popup \
136        <Leave> {%W configure -cursor ""}
137    $itk_component(simstatus) tag bind popup \
138        <ButtonPress> {after idle {Rappture::Tooltip::tooltip show %W}}
139
140
141    itk_component add notebook {
142        Rappture::Notebook $itk_interior.nb
143    }
144    pack $itk_interior.nb -expand yes -fill both
145
146    # ------------------------------------------------------------------
147    # ABOUT PAGE
148    # ------------------------------------------------------------------
149    set w [$itk_component(notebook) insert end about]
150
151    Rappture::Scroller $w.info -xscrollmode off -yscrollmode auto
152    pack $w.info -expand yes -fill both -padx 4 -pady 20
153    itk_component add toolinfo {
154        text $w.info.text -width 1 -height 1 -wrap word \
155            -borderwidth 0 -highlightthickness 0
156    } {
157        usual
158        ignore -borderwidth -relief
159        rename -font -textfont textFont Font
160    }
161    $w.info contents $w.info.text
162
163    # ------------------------------------------------------------------
164    # SIMULATION PAGE
165    # ------------------------------------------------------------------
166    set w [$itk_component(notebook) insert end simulate]
167    frame $w.cntls
168    pack $w.cntls -side bottom -fill x -pady 12
169    frame $w.cntls.sep -background black -height 1
170    pack $w.cntls.sep -side top -fill x
171
172    itk_component add abort {
173        button $w.cntls.abort -text "Abort" \
174            -command [itcl::code $_tool abort]
175    }
176    pack $itk_component(abort) -side left -expand yes -padx 4 -pady 4
177
178    Rappture::Scroller $w.info -xscrollmode auto -yscrollmode auto
179    pack $w.info -expand yes -fill both -padx 4 -pady 4
180    itk_component add runinfo {
181        text $w.info.text -width 1 -height 1 -wrap none \
182            -borderwidth 0 -highlightthickness 0 \
183            -state disabled
184    } {
185        usual
186        ignore -borderwidth -relief
187        rename -font -codefont codeFont Font
188    }
189    $w.info contents $w.info.text
190
191    itk_component add progress {
192        Rappture::Progress $w.progress
193    }
194
195    # ------------------------------------------------------------------
196    # ANALYZE PAGE
197    # ------------------------------------------------------------------
198    set w [$itk_component(notebook) insert end analyze]
199
200    frame $w.top
201    pack $w.top -side top -fill x -pady 8
202    label $w.top.l -text "Result:" -font $itk_option(-font)
203    pack $w.top.l -side left
204
205    itk_component add resultselector {
206        Rappture::Combobox $w.top.sel -width 10 -editable no
207    } {
208        usual
209        rename -font -textfont textFont Font
210    }
211    pack $itk_component(resultselector) -side left -expand yes -fill x
212    bind $itk_component(resultselector) <<Value>> [itcl::code $this _fixResult]
213    bind $itk_component(resultselector) <Enter> \
214        [itcl::code $this download coming]
215
216    if {[Rappture::filexfer::enabled]} {
217        itk_component add download {
218            button $w.top.dl -image $icons(download) -anchor e \
219                -borderwidth 1 -relief flat -overrelief raised \
220                -command [itcl::code $this download now $w.top.dl]
221        }
222        pack $itk_component(download) -side right -padx {4 0}
223        Rappture::Tooltip::for $itk_component(download) "Downloads the current result to a new web browser window on your desktop.  From there, you can easily print or save results.
224
225NOTE:  Your web browser must allow pop-ups from this site.  If your output does not appear, look for a 'pop-up blocked' message and enable pop-ups."
226
227        bind $itk_component(download) <Enter> \
228            [itcl::code $this download coming]
229    }
230
231    itk_component add results {
232        Rappture::Panes $w.pane
233    }
234    pack $itk_component(results) -expand yes -fill both
235    set f [$itk_component(results) pane 0]
236
237    itk_component add resultpages {
238        Rappture::Notebook $f.nb
239    }
240    pack $itk_component(resultpages) -expand yes -fill both
241
242    set f [$itk_component(results) insert end -fraction 0.1]
243    itk_component add resultset {
244        Rappture::ResultSet $f.rset \
245            -clearcommand [itcl::code $this clear] \
246            -settingscommand [itcl::code $this _plot] \
247            -promptcommand [itcl::code $this _simState]
248    }
249    pack $itk_component(resultset) -expand yes -fill both
250    bind $itk_component(resultset) <<Control>> [itcl::code $this _fixSize]
251
252    eval itk_initialize $args
253
254    $itk_component(runinfo) tag configure ERROR -foreground red
255    $itk_component(runinfo) tag configure text -font $itk_option(-textfont)
256
257    #
258    # Load up tool info on the first page.
259    #
260    $itk_component(toolinfo) tag configure title \
261        -font $itk_option(-boldtextfont)
262
263    set mesg [$tool xml get tool.title]
264    if {"" != $mesg} {
265        $itk_component(toolinfo) insert end $mesg title
266        $itk_component(toolinfo) insert end "\n\n"
267    }
268
269    set mesg [$tool xml get tool.about]
270    if {"" != $mesg} {
271        $itk_component(toolinfo) insert end $mesg
272    }
273    $itk_component(toolinfo) configure -state disabled
274    $itk_component(notebook) current about
275
276    # tool can run on "manual" (default) or "auto"
277    set cntl [$tool xml get tool.control]
278    if {"" == $cntl} {
279        set cntl [$tool xml get tool.control.type]
280    }
281    if {"" != $cntl} {
282        set _control $cntl
283    }
284
285    # reset everything to a clean state
286    reset
287}
288
289# ----------------------------------------------------------------------
290# DESTRUCTOR
291# ----------------------------------------------------------------------
292itcl::body Rappture::Analyzer::destructor {} {
293    foreach obj $_runs {
294        itcl::delete object $obj
295    }
296    after cancel [itcl::code $this simulate]
297}
298
299# ----------------------------------------------------------------------
300# USAGE: simulate ?-ifneeded?
301# USAGE: simulate ?<path1> <value1> <path2> <value2> ...?
302#
303# Kicks off the simulator by executing the tool.command associated
304# with the tool.  If any arguments are specified, they are used to
305# set parameters for the simulation.  While the simulation is running,
306# it shows status.  When the simulation is finished, it switches
307# automatically to "analyze" mode and shows the results.
308# ----------------------------------------------------------------------
309itcl::body Rappture::Analyzer::simulate {args} {
310    if {$args == "-ifneeded"} {
311        # check to see if simulation is really needed
312        $_tool sync
313        if {[$itk_component(resultset) contains [$_tool xml object]]} {
314            # not needed -- show results and return
315            $itk_component(notebook) current analyze
316            return
317        }
318        set args ""
319    }
320
321    # simulation is needed -- go to simulation page
322    $itk_component(notebook) current simulate
323
324    # no progress messages yet
325    pack forget $itk_component(progress)
326    lappend args -output [itcl::code $this _simOutput]
327
328    _simState off
329    $itk_component(runinfo) configure -state normal
330    $itk_component(runinfo) delete 1.0 end
331    $itk_component(runinfo) insert end "Running simulation...\n\n" text
332    $itk_component(runinfo) configure -state disabled
333
334    # if the hold window is set, then put up a busy cursor
335    if {$itk_option(-holdwindow) != ""} {
336        blt::busy hold $itk_option(-holdwindow)
337        raise $itk_component(hull)
338        update
339    }
340
341    # execute the job
342    foreach {status result} [eval $_tool run $args] break
343
344    # if job was aborted, then allow simulation again
345    if {$result == "ABORT"} {
346        _simState on "Aborted"
347    }
348
349    # read back the results from run.xml
350    if {$status == 0 && $result != "ABORT"} {
351        if {[regexp {=RAPPTURE-RUN=>([^\n]+)} $result match file]} {
352            set status [catch {load $file} msg]
353            if {$status != 0} {
354                global errorInfo
355                set result "$msg\n$errorInfo"
356            }
357        } else {
358            set status 1
359            set result "Can't find result file in output:\n\n$result"
360        }
361    }
362
363    # back to normal
364    if {$itk_option(-holdwindow) != ""} {
365        blt::busy release $itk_option(-holdwindow)
366    }
367    $itk_component(abort) configure -state disabled
368
369    if {$status != 0} {
370        $itk_component(runinfo) configure -state normal
371        $itk_component(runinfo) delete 1.0 end
372        $itk_component(runinfo) insert end "Problem launching job:\n\n" text
373        _simOutput $result
374        $itk_component(runinfo) configure -state disabled
375        $itk_component(runinfo) see 1.0
376    } else {
377        $itk_component(notebook) current analyze
378    }
379
380    # do this last -- after _simOutput above
381    pack forget $itk_component(progress)
382}
383
384# ----------------------------------------------------------------------
385# USAGE: reset
386#
387# Used to reset the analyzer whenever the input to a simulation has
388# changed.  Sets the mode back to "simulate", so the user has to
389# simulate again to see the output.  If the <start> option is set
390# to "auto", the simulation is invoked immediately.
391# ----------------------------------------------------------------------
392itcl::body Rappture::Analyzer::reset {} {
393    # check to see if simulation is really needed
394    $_tool sync
395    if {![$itk_component(resultset) contains [$_tool xml object]]} {
396        # if control mode is "auto", then simulate right away
397        if {[string match auto* $_control]} {
398            # auto control -- don't need button
399            pack forget $itk_interior.simol
400
401            after cancel [itcl::code $this simulate]
402            after idle [itcl::code $this simulate]
403        } else {
404            _simState on "new input parameters"
405        }
406    } else {
407        _simState off
408    }
409}
410
411# ----------------------------------------------------------------------
412# USAGE: load <file>
413#
414# Loads the data from the given <file> into the appropriate results
415# sets.  If necessary, new results sets are created to store the data.
416# ----------------------------------------------------------------------
417itcl::body Rappture::Analyzer::load {file} {
418    # only show the last result? then clear first
419    if {[$_tool xml get tool.analyzer] == "last"} {
420        clear
421    }
422
423    # try to load new results from the given file
424    set xmlobj [Rappture::library $file]
425    lappend _runs $xmlobj
426
427    # go through the analysis and find all result sets
428    set haveresults 0
429    foreach item [_reorder [$xmlobj children output]] {
430        switch -glob -- $item {
431            log* {
432                _autoLabel $xmlobj output.$item "Output Log" counters
433            }
434            string* {
435                _autoLabel $xmlobj output.$item "String" counters
436            }
437            curve* - field* {
438                _autoLabel $xmlobj output.$item "Plot" counters
439            }
440            structure* {
441                _autoLabel $xmlobj output.$item "Structure" counters
442            }
443            table* {
444                _autoLabel $xmlobj output.$item "Energy Levels" counters
445            }
446        }
447        set label [$xmlobj get output.$item.about.group]
448        if {"" == $label} {
449            set label [$xmlobj get output.$item.about.label]
450        }
451
452        set hidden [$xmlobj get output.$item.hide]
453        set hidden [expr {"" != $hidden && $hidden}]
454
455        if {"" != $label && !$hidden} {
456            set haveresults 1
457        }
458    }
459
460    # if there are any valid results, add them to the resultset
461    if {$haveresults} {
462        set size [$itk_component(resultset) size]
463        set index [$itk_component(resultset) add $xmlobj]
464
465        # add each result to a result viewer
466        foreach item [_reorder [$xmlobj children output]] {
467            set label [$xmlobj get output.$item.about.group]
468            if {"" == $label} {
469                set label [$xmlobj get output.$item.about.label]
470            }
471
472            set hidden [$xmlobj get output.$item.hide]
473            set hidden [expr {"" != $hidden && $hidden}]
474
475            if {"" != $label && !$hidden} {
476                if {![info exists _label2page($label)]} {
477                    set name "page[incr _pages]"
478                    set page [$itk_component(resultpages) insert end $name]
479                    set _label2page($label) $page
480                    Rappture::ResultViewer $page.rviewer
481                    pack $page.rviewer -expand yes -fill both -pady 4
482
483                    set end [$itk_component(resultselector) \
484                        choices index -value ---]
485                    if {$end < 0} {
486                        set end "end"
487                    }
488                    $itk_component(resultselector) choices insert $end \
489                        $name $label
490                }
491
492                # add/replace the latest result into this viewer
493                set page $_label2page($label)
494
495                if {![info exists reset($page)]} {
496                    $page.rviewer clear $index
497                    set reset($page) 1
498                }
499                $page.rviewer add $index $xmlobj output.$item
500            }
501        }
502    }
503
504    # show the first page by default
505    set max [$itk_component(resultselector) choices size]
506    for {set i 0} {$i < $max} {incr i} {
507        set first [$itk_component(resultselector) choices get -label $i]
508        if {$first != ""} {
509            set page [$itk_component(resultselector) choices get -value $i]
510            set char [string index $page 0]
511            if {$char != "@" && $char != "-"} {
512                $itk_component(resultpages) current $page
513                $itk_component(resultselector) value $first
514                break
515            }
516        }
517    }
518}
519
520# ----------------------------------------------------------------------
521# USAGE: clear
522#
523# Discards all results previously loaded into the analyzer.
524# ----------------------------------------------------------------------
525itcl::body Rappture::Analyzer::clear {} {
526    foreach obj $_runs {
527        itcl::delete object $obj
528    }
529    set _runs ""
530
531    $itk_component(resultset) clear
532    $itk_component(results) fraction end 0.1
533
534    foreach label [array names _label2page] {
535        set page $_label2page($label)
536        $page.rviewer clear
537    }
538    $itk_component(resultselector) value ""
539    $itk_component(resultselector) choices delete 0 end
540    catch {unset _label2page}
541    set _plotlist ""
542
543    if {[Rappture::filexfer::enabled]} {
544        $itk_component(resultselector) choices insert end \
545            --- "---"
546        $itk_component(resultselector) choices insert end \
547            @download "Download..."
548    }
549
550    #
551    # HACK ALERT!!
552    # The following statement should be in place, but it causes
553    # vtk to dump core.  Leave it out until we can fix the core dump.
554    # In the mean time, we leak memory...
555    #
556    #$itk_component(resultpages) delete -all
557    #set _pages 0
558
559    _simState on
560    _fixSimControl
561    reset
562}
563
564# ----------------------------------------------------------------------
565# USAGE: download coming
566# USAGE: download now ?widget?
567#
568# Spools the current result so the user can download it.
569# ----------------------------------------------------------------------
570itcl::body Rappture::Analyzer::download {option args} {
571    if {[Rappture::filexfer::enabled]} {
572        set title [$itk_component(resultselector) value]
573        set page [$itk_component(resultselector) translate $title]
574
575        switch -- $option {
576            coming {
577                #
578                # Warn result that a download is coming, in case
579                # it needs to take a screen snap.
580                #
581                if {![regexp {^(|@download|---)$} $page]} {
582                    set f [$itk_component(resultpages) page $page]
583                    $f.rviewer download coming
584                }
585            }
586            now {
587                set widget $itk_component(download)
588                if {[llength $args] > 0} {
589                    set widget [lindex $args 0]
590                    if {[catch {winfo class $widget}]} {
591                        set widget $itk_component(download)
592                    }
593                }
594                #
595                # Perform the actual download.
596                #
597                if {$page != ""} {
598                    set ext ""
599                    set f [$itk_component(resultpages) page $page]
600                    foreach {ext data} [$f.rviewer download now] break
601                    if {"" == $ext} {
602                        if {"" != $widget} {
603                            Rappture::Tooltip::cue $widget \
604                                "Can't download this result."
605                        }
606                        return
607                    }
608                    regsub -all {[\ -\/\:-\@\{-\~]} $title {} title
609                    set file "$title$ext"
610                } else {
611                    # this shouldn't happen
612                    set file error.html
613                    set data "<h1>Not Found</h1>There is no result selected."
614                }
615
616                if {[catch {Rappture::filexfer::spool $data $file} result]} {
617                    if {"no clients" == $result} {
618                        if {"" != $widget} {
619                            Rappture::Tooltip::cue $widget "Can't download this result.  Looks like you might be having trouble with the version of Java installed for your browser."
620                        }
621                    } elseif {"old client" == $result} {
622                        if {"" != $widget} {
623                            Rappture::Tooltip::cue $widget "For this to work properly, you must first restart your Web browser.  You don't need to close down this session.  Simply shut down all windows for your Web browser, then restart the browser and navigate back to this page.  You'll find it on \"my nanoHUB\" listed under \"my sessions\".  Once the browser is restarted, the download should work properly."
624                        }
625                    } elseif {"old clients" == $result} {
626                        if {"" != $widget} {
627                            Rappture::Tooltip::cue $widget "There are multiple browser pages connected to this session, and one of them has browser that needs to be restarted.\n\nWhoever didn't get the download should restart their Web browser.  You don't need to close down this session.  Simply shut down all windows for the Web browser, then restart the browser and navigate back to this page.  You'll find it on \"my nanoHUB\" listed under \"my sessions\".  Once the browser is restarted, the download should work properly."
628                        }
629                    } else {
630                        error $result "    (while spooling result \"$title\")"
631                    }
632                }
633            }
634            default {
635                error "bad option \"$option\": should be coming, now"
636            }
637        }
638    }
639}
640
641# ----------------------------------------------------------------------
642# USAGE: _plot ?<index> <options> <index> <options>...?
643#
644# Used internally to update the plot shown in the current result
645# viewer whenever the resultset settings have changed.  Causes the
646# desired results to show up on screen.
647# ----------------------------------------------------------------------
648itcl::body Rappture::Analyzer::_plot {args} {
649    set _plotlist $args
650
651    set page [$itk_component(resultselector) value]
652    set page [$itk_component(resultselector) translate $page]
653    if {"" != $page} {
654        set f [$itk_component(resultpages) page $page]
655        $f.rviewer plot clear
656        foreach {index opts} $_plotlist {
657            $f.rviewer plot add $index $opts
658        }
659    }
660}
661
662# ----------------------------------------------------------------------
663# USAGE: _reorder <compList>
664#
665# Used internally to change the order of a series of output components
666# found in the <output> section.  Moves the <log> elements to the end
667# and returns the updated list.
668# ----------------------------------------------------------------------
669itcl::body Rappture::Analyzer::_reorder {comps} {
670    set i 0
671    set max [llength $comps]
672    while {$i < $max} {
673        set c [lindex $comps $i]
674        if {[string match log* $c]} {
675            set comps [lreplace $comps $i $i]
676            lappend comps $c
677            incr max -1
678        } else {
679            incr i
680        }
681    }
682    return $comps
683}
684
685# ----------------------------------------------------------------------
686# USAGE: _autoLabel <xmlobj> <path> <title> <cntVar>
687#
688# Used internally to check for an about.label property at the <path>
689# in <xmlobj>.  If this object doesn't have a label, then one is
690# supplied using the given <title>.  The <cntVar> is an array of
691# counters in the calling scopes for titles that have been used
692# in the past.  This is used to create titles like "Plot #2" the
693# second time it is encountered.
694#
695# The <xmlobj> is updated so that the label is inserted directly in
696# the tree.
697# ----------------------------------------------------------------------
698itcl::body Rappture::Analyzer::_autoLabel {xmlobj path title cntVar} {
699    upvar $cntVar counters
700
701    set group [$xmlobj get $path.about.group]
702    set label [$xmlobj get $path.about.label]
703    if {"" == $label} {
704        # no label -- make one up using the title specified
705        if {![info exists counters($group-$title)]} {
706            set counters($group-$title) 1
707            set label $title
708        } else {
709            set label "$title (#[incr counters($group-$title)])"
710        }
711        $xmlobj put $path.about.label $label
712    } else {
713        # handle the case of two identical labels in <output>
714        if {![info exists counters($group-$label)]} {
715            set counters($group-$label) 1
716        } else {
717            set label "$label (#[incr counters($group-$label)])"
718            $xmlobj put $path.about.label $label
719        }
720    }
721    return $label
722}
723
724# ----------------------------------------------------------------------
725# USAGE: _fixResult
726#
727# Used internally to change the result page being displayed whenever
728# the user selects a page from the results combobox.
729# ----------------------------------------------------------------------
730itcl::body Rappture::Analyzer::_fixResult {} {
731    set name [$itk_component(resultselector) value]
732    set page ""
733    if {"" != $name} {
734        set page [$itk_component(resultselector) translate $name]
735    }
736    if {$page == "@download"} {
737        # put the combobox back to its last value
738        $itk_component(resultselector) component entry configure -state normal
739        $itk_component(resultselector) component entry delete 0 end
740        $itk_component(resultselector) component entry insert end $_lastlabel
741        $itk_component(resultselector) component entry configure -state disabled
742        # perform the actual download
743        download now $itk_component(resultselector)
744    } elseif {$page == "---"} {
745        # put the combobox back to its last value
746        $itk_component(resultselector) component entry configure -state normal
747        $itk_component(resultselector) component entry delete 0 end
748        $itk_component(resultselector) component entry insert end $_lastlabel
749        $itk_component(resultselector) component entry configure -state disabled
750    } else {
751        set _lastlabel $name
752        set win [winfo toplevel $itk_component(hull)]
753        blt::busy hold $win; update idletasks
754        $itk_component(resultpages) current $page
755
756        set f [$itk_component(resultpages) page $page]
757        $f.rviewer plot clear
758        eval $f.rviewer plot add $_plotlist
759        blt::busy release [winfo toplevel $itk_component(hull)]
760    }
761}
762
763# ----------------------------------------------------------------------
764# USAGE: _fixSize
765#
766# Used internally to change the size of the result set area whenever
767# a new control appears.  Adjusts the size available for the result
768# set up to some maximum.
769# ----------------------------------------------------------------------
770itcl::body Rappture::Analyzer::_fixSize {} {
771    set f [$itk_component(results) fraction end]
772    if {$f < 0.4} {
773        $itk_component(results) fraction end [expr {$f+0.15}]
774    }
775    _fixSimControl
776}
777
778# ----------------------------------------------------------------------
779# USAGE: _simState <boolean> ?<message>? ?<settings>?
780#
781# Used internally to change the "Simulation" button on or off.
782# If the <boolean> is on, then any <message> and <settings> are
783# displayed as well.  The <message> is a note to the user about
784# what will be simulated, and the <settings> are a list of
785# tool parameter settings of the form {path1 val1 path2 val2 ...}.
786# When these are in place, the next Simulate operation will use
787# these settings.  This helps fill in missing data values.
788# ----------------------------------------------------------------------
789itcl::body Rappture::Analyzer::_simState {state args} {
790    if {$state} {
791        $itk_interior.simol configure \
792            -background $itk_option(-simcontrolactiveoutline)
793        $itk_interior.simol.simbg configure \
794            -background $itk_option(-simcontrolactivebackground)
795        $itk_component(simulate) configure \
796            -highlightbackground $itk_option(-simcontrolactivebackground)
797        $itk_component(simstatus) configure \
798            -background $itk_option(-simcontrolactivebackground)
799
800        $itk_component(abort) configure -state disabled
801        $itk_component(simulate) configure -state normal \
802            -command [itcl::code $this simulate]
803
804        #
805        # If there's a special message, then put it up next to the button.
806        #
807        set mesg [lindex $args 0]
808        if {"" != $mesg} {
809            $itk_component(simstatus) configure -state normal
810            $itk_component(simstatus) delete 1.0 end
811            $itk_component(simstatus) insert end $mesg
812
813            #
814            # If there are any settings, then install them in the
815            # "Simulate" button.  Also, pop them up as a tooltip
816            # for the message.
817            #
818            set settings [lindex $args 1]
819            if {[llength $settings] > 0} {
820                $itk_component(simulate) configure \
821                    -command [eval itcl::code $this simulate $settings]
822
823                set details ""
824                foreach {path val} $settings {
825                    set str [$_tool xml get $path.about.label]
826                    if {"" == $str} {
827                        set str [$_tool xml element -as id $path]
828                    }
829                    append details "$str = $val\n"
830                }
831                set details [string trim $details]
832
833                Rappture::Tooltip::for $itk_component(simstatus) $details
834                $itk_component(simstatus) insert end " "
835                $itk_component(simstatus) insert end "(details...)" popup
836            }
837            $itk_component(simstatus) configure -state disabled
838        }
839    } else {
840        if {"" != $itk_option(-simcontrolbackground)} {
841            set simcbg $itk_option(-simcontrolbackground)
842        } else {
843            set simcbg $itk_option(-background)
844        }
845        $itk_interior.simol configure \
846            -background $itk_option(-simcontroloutline)
847        $itk_interior.simol.simbg configure -background $simcbg
848        $itk_component(simulate) configure -highlightbackground $simcbg
849        $itk_component(simstatus) configure -background $simcbg
850
851        $itk_component(simulate) configure -state disabled
852        $itk_component(abort) configure -state normal
853
854        $itk_component(simstatus) configure -state normal
855        $itk_component(simstatus) delete 1.0 end
856        $itk_component(simstatus) configure -state disabled
857        Rappture::Tooltip::for $itk_component(simstatus) ""
858    }
859}
860
861# ----------------------------------------------------------------------
862# USAGE: _simOutput <message>
863#
864# Invoked automatically whenever output comes in while running the
865# tool.  Extracts any =RAPPTURE-???=> messages from the output and
866# sends the output to the display.  For example, any
867# =RAPPTURE-PROGRESS=> message pops up the progress meter and updates
868# it to show the latest progress message.  This is useful for
869# long-running tools, to let the user know how much longer the
870# simulation will take.
871# ----------------------------------------------------------------------
872itcl::body Rappture::Analyzer::_simOutput {message} {
873    #
874    # Scan through and pick out any =RAPPTURE-PROGRESS=> messages first.
875    #
876    while {[regexp -indices \
877               {=RAPPTURE-PROGRESS=>([0-9]+) +([^\n]*)(\n|$)} $message \
878                match percent mesg]} {
879
880        foreach {i0 i1} $percent break
881        set percent [string range $message $i0 $i1]
882
883        foreach {i0 i1} $mesg break
884        set mesg [string range $message $i0 $i1]
885
886        pack $itk_component(progress) -fill x -padx 10 -pady 10
887        $itk_component(progress) settings -percent $percent -message $mesg
888
889        foreach {i0 i1} $match break
890        set message [string replace $message $i0 $i1]
891    }
892
893    #
894    # Break up the remaining lines according to =RAPPTURE-ERROR=> messages.
895    # Show errors in a special color.
896    #
897    $itk_component(runinfo) configure -state normal
898
899    while {[regexp -indices \
900               {=RAPPTURE-([a-zA-Z]+)=>([^\n]*)(\n|$)} $message \
901                match type mesg]} {
902
903        foreach {i0 i1} $match break
904        set first [string range $message 0 [expr {$i0-1}]]
905        if {[string length $first] > 0} {
906            $itk_component(runinfo) insert end $first
907            $itk_component(runinfo) insert end \n
908        }
909
910        foreach {t0 t1} $type break
911        set type [string range $message $t0 $t1]
912        foreach {m0 m1} $mesg break
913        set mesg [string range $message $m0 $m1]
914        if {[string length $mesg] > 0 && $type != "RUN"} {
915            $itk_component(runinfo) insert end $mesg $type
916            $itk_component(runinfo) insert end \n $type
917        }
918
919        set message [string range $message [expr {$i1+1}] end]
920    }
921
922    if {[string length $message] > 0} {
923        $itk_component(runinfo) insert end $message
924        if {[$itk_component(runinfo) get end-2char] != "\n"} {
925            $itk_component(runinfo) insert end "\n"
926        }
927        $itk_component(runinfo) see end
928    }
929    $itk_component(runinfo) configure -state disabled
930}
931
932# ----------------------------------------------------------------------
933# USAGE: _fixSimControl
934#
935# Used internally to add or remove the simulation control at the
936# top of the analysis area.  This is controlled by the -simcontrol
937# option.
938# ----------------------------------------------------------------------
939itcl::body Rappture::Analyzer::_fixSimControl {} {
940    switch -- $itk_option(-simcontrol) {
941        on {
942            pack $itk_interior.simol -fill x -before $itk_interior.nb
943        }
944        off {
945            pack forget $itk_interior.simol
946        }
947        auto {
948            #
949            # If we have two or more radiodials, then there is a
950            # chance of encountering a combination of parameters
951            # with no data, requiring simulation.
952            #
953            if {[$itk_component(resultset) size -controls] >= 2} {
954                pack $itk_interior.simol -fill x -before $itk_interior.nb
955            } else {
956                pack forget $itk_interior.simol
957            }
958        }
959        default {
960            error "bad value \"$itk_option(-simcontrol)\": should be on, off, auto"
961        }
962    }
963}
964
965# ----------------------------------------------------------------------
966# CONFIGURATION OPTION: -simcontrol
967#
968# Controls whether or not the Simulate button is showing.  In some
969# cases, it is not needed.
970# ----------------------------------------------------------------------
971itcl::configbody Rappture::Analyzer::simcontrol {
972    _fixSimControl
973}
Note: See TracBrowser for help on using the repository browser.