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

Last change on this file since 1159 was 1159, checked in by dkearney, 16 years ago

updated driver to allow the user to revisualize old run files just as rerun did. if driver can find the tool.xml file and where the application is installed, it can also allow the user to run new simulations after preloading old simulations.

Finally figured out where the current tags in group objects were coming from. controlOwner was adjusted to stop putting current tags in things. this only seemed to happen when the application also contained a loader, because we were doing an xml copy of nodes.

rewrote rerun to be a small wrapper around the "driver -load" command. rerun is now a script like rappture, it is populated with rappture's install directory from configure, so configure.in was updated. added some stuff for finding mcc in the configure.in script for a future commit

changed Rappture::Analyzer to accept -notebookpage configure flag so we can specify which page of the analyzer notebook should be currently showing. also inside of the analyzer, changed behavior of simstatus to allow us to still show a message even if the simulation button is disabled. this is helpful because we can tell the user why the simulation button is grayed out. one example of this is the case when we load old run.xml files, but cannot find a tool.xml file. the user cannot run a simulation, even if they change an input, because we can't figure out where the app is installed. now we can tell the user, why they cannot run the simulation.

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