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

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

adding ability to specify runfiles to be either loaded or included with the
results of the current simulation. loading a runfile will simply call the tool object's load function within analyzer and the runfile will be loaded as a previous simulation result. including a runfile involves copying the results (everything under output) from the runfile into the current run.xml file and all of the results are shown as one single simulation.

This behavior is demonstrated in the zoo's loadrun example.

File size: 40.2 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    # look for all output.load children and load them first
434    # each run.xml is loaded as a previous simulation.
435    foreach item [$xmlobj children -type run output.load] {
436        set loadfile [$xmlobj get output.load.$item]
437        set loadobj [Rappture::library $loadfile]
438        load $loadobj
439    }
440
441    foreach item [$xmlobj children -type run output.include] {
442        set id [$xmlobj element -as id output.include.$item]
443        set inclfile [$xmlobj get output.include.$item]
444        set inclobj [Rappture::library $inclfile]
445        foreach c [$inclobj children output] {
446            switch -glob -- $c {
447                # we don't want to include these tags
448                include* - time* - status* - user* {
449                    continue
450                }
451                default {
452                    set oldid [$inclobj element -as id output.$c]
453                    set oldtype [$inclobj element -as type output.$c]
454                    set newcomp "$oldtype\($id-$oldid\)"
455                    $xmlobj copy output.$newcomp from $inclobj output.$c
456                }
457            }
458        }
459    }
460
461    lappend _runs $xmlobj
462
463    # go through the analysis and find all result sets
464    set haveresults 0
465    foreach item [_reorder [$xmlobj children output]] {
466        switch -glob -- $item {
467            log* {
468                _autoLabel $xmlobj output.$item "Output Log" counters
469            }
470            number* {
471                _autoLabel $xmlobj output.$item "Number" counters
472            }
473            integer* {
474                _autoLabel $xmlobj output.$item "Integer" counters
475            }
476            string* {
477                _autoLabel $xmlobj output.$item "String" counters
478            }
479            histogram* - curve* - field* {
480                _autoLabel $xmlobj output.$item "Plot" counters
481            }
482            structure* {
483                _autoLabel $xmlobj output.$item "Structure" counters
484            }
485            table* {
486                _autoLabel $xmlobj output.$item "Energy Levels" counters
487            }
488            sequence* {
489                _autoLabel $xmlobj output.$item "Sequence" counters
490            }
491        }
492        set label [$xmlobj get output.$item.about.group]
493        if {"" == $label} {
494            set label [$xmlobj get output.$item.about.label]
495        }
496
497        set hidden [$xmlobj get output.$item.hide]
498        set hidden [expr {"" != $hidden && $hidden}]
499
500        if {"" != $label && !$hidden} {
501            set haveresults 1
502        }
503    }
504
505    # if there are any valid results, add them to the resultset
506    if {$haveresults} {
507        set index [$itk_component(resultset) add $xmlobj]
508
509        # add each result to a result viewer
510        foreach item [_reorder [$xmlobj children output]] {
511            set label [$xmlobj get output.$item.about.group]
512            if {"" == $label} {
513                set label [$xmlobj get output.$item.about.label]
514            }
515
516            set hidden [$xmlobj get output.$item.hide]
517            set hidden [expr {"" != $hidden && $hidden}]
518
519            if {"" != $label && !$hidden} {
520                if {![info exists _label2page($label)]} {
521                    set name "page[incr _pages]"
522                    set page [$itk_component(resultpages) insert end $name]
523                    set _label2page($label) $page
524                    set _label2desc($label) \
525                        [$xmlobj get output.$item.about.description]
526                    Rappture::ResultViewer $page.rviewer
527                    pack $page.rviewer -expand yes -fill both -pady 4
528
529                    set end [$itk_component(resultselector) \
530                        choices index -value ---]
531                    if {$end < 0} {
532                        set end "end"
533                    }
534                    $itk_component(resultselector) choices insert $end \
535                        $name $label
536                }
537
538                # add/replace the latest result into this viewer
539                set page $_label2page($label)
540
541                if {![info exists reset($page)]} {
542                    $page.rviewer clear $index
543                    set reset($page) 1
544                }
545                $page.rviewer add $index $xmlobj output.$item
546            }
547        }
548    }
549
550    # show the first page by default
551    set max [$itk_component(resultselector) choices size]
552    for {set i 0} {$i < $max} {incr i} {
553        set first [$itk_component(resultselector) choices get -label $i]
554        if {$first != ""} {
555            set page [$itk_component(resultselector) choices get -value $i]
556            set char [string index $page 0]
557            if {$char != "@" && $char != "-"} {
558                $itk_component(resultpages) current $page
559                $itk_component(resultselector) value $first
560                set _lastlabel $first
561                break
562            }
563        }
564    }
565}
566
567# ----------------------------------------------------------------------
568# USAGE: clear
569#
570# Discards all results previously loaded into the analyzer.
571# ----------------------------------------------------------------------
572itcl::body Rappture::Analyzer::clear {} {
573    foreach obj $_runs {
574        itcl::delete object $obj
575    }
576    set _runs ""
577
578    $itk_component(resultset) clear
579
580    # reset the size of the controls area
581    set ht [winfo height $itk_component(results)]
582    set cntlht [$itk_component(resultset) size -controlarea]
583    set frac [expr {double($cntlht)/$ht}]
584    $itk_component(results) fraction end $frac
585
586    foreach label [array names _label2page] {
587        set page $_label2page($label)
588        $page.rviewer clear
589    }
590    $itk_component(resultselector) value ""
591    $itk_component(resultselector) choices delete 0 end
592    catch {unset _label2page}
593    catch {unset _label2desc}
594    set _plotlist ""
595
596    $itk_component(resultselector) choices insert end --- "---"
597    $itk_component(resultselector) choices insert end \
598        @download [Rappture::filexfer::label download]
599    set _lastlabel ""
600
601    #
602    # HACK ALERT!!
603    # The following statement should be in place, but it causes
604    # vtk to dump core.  Leave it out until we can fix the core dump.
605    # In the mean time, we leak memory...
606    #
607    #$itk_component(resultpages) delete -all
608    #set _pages 0
609
610    _simState on
611    _fixSimControl
612    reset
613}
614
615# ----------------------------------------------------------------------
616# USAGE: download coming
617# USAGE: download controls <downloadCommand>
618# USAGE: download start ?widget?
619# USAGE: download now ?widget?
620#
621# Spools the current result so the user can download it.
622# ----------------------------------------------------------------------
623itcl::body Rappture::Analyzer::download {option args} {
624    set title [$itk_component(resultselector) value]
625    set page [$itk_component(resultselector) translate $title]
626
627    switch -- $option {
628        coming {
629            #
630            # Warn result that a download is coming, in case
631            # it needs to take a screen snap.
632            #
633            if {![regexp {^(|@download|---)$} $page]} {
634                set f [$itk_component(resultpages) page $page]
635                $f.rviewer download coming
636            }
637        }
638        controls {
639            # no controls for this download yet
640            return ""
641        }
642        start {
643            set widget $itk_component(download)
644            if {[llength $args] > 0} {
645                set widget [lindex $args 0]
646                if {[catch {winfo class $widget}]} {
647                    set widget $itk_component(download)
648                }
649            }
650            #
651            # See if this download has any controls.  If so, then
652            # post them now and let the user continue the download
653            # after selecting a file format.
654            #
655            if {$page != ""} {
656                set ext ""
657                set f [$itk_component(resultpages) page $page]
658                set popup [$f.rviewer download controls \
659                    [itcl::code $this download now $widget]]
660
661                if {"" != $popup} {
662                    $popup activate $widget below
663                } else {
664                    download now $widget
665                }
666            } else {
667                # this shouldn't happen
668                set file error.html
669                set data "<h1>Not Found</h1>There is no result selected."
670            }
671        }
672        now {
673            set widget $itk_component(download)
674            if {[llength $args] > 0} {
675                set widget [lindex $args 0]
676                if {[catch {winfo class $widget}]} {
677                    set widget $itk_component(download)
678                }
679            }
680            #
681            # Perform the actual download.
682            #
683            if {$page != ""} {
684                set ext ""
685                set f [$itk_component(resultpages) page $page]
686                foreach {ext data} [$f.rviewer download now] break
687                if {"" == $ext} {
688                    if {"" != $widget} {
689                        Rappture::Tooltip::cue $widget \
690                            "Can't download this result."
691                    }
692                    return
693                }
694                regsub -all {[\ -\/\:-\@\{-\~]} $title {} title
695                set file "$title$ext"
696            } else {
697                # this shouldn't happen
698                set file error.html
699                set data "<h1>Not Found</h1>There is no result selected."
700            }
701
702            set mesg [Rappture::filexfer::download $data $file]
703            if {[string length $mesg] > 0} {
704                Rappture::Tooltip::cue $widget $mesg
705            }
706        }
707        default {
708            error "bad option \"$option\": should be coming, controls, now, start"
709        }
710    }
711}
712
713# ----------------------------------------------------------------------
714# USAGE: _plot ?<index> <options> <index> <options>...?
715#
716# Used internally to update the plot shown in the current result
717# viewer whenever the resultset settings have changed.  Causes the
718# desired results to show up on screen.
719# ----------------------------------------------------------------------
720itcl::body Rappture::Analyzer::_plot {args} {
721    set _plotlist $args
722
723    set page [$itk_component(resultselector) value]
724    set page [$itk_component(resultselector) translate $page]
725    if {"" != $page} {
726        set f [$itk_component(resultpages) page $page]
727        $f.rviewer plot clear
728        foreach {index opts} $_plotlist {
729            $f.rviewer plot add $index $opts
730        }
731    }
732}
733
734# ----------------------------------------------------------------------
735# USAGE: _reorder <compList>
736#
737# Used internally to change the order of a series of output components
738# found in the <output> section.  Moves the <log> elements to the end
739# and returns the updated list.
740# ----------------------------------------------------------------------
741itcl::body Rappture::Analyzer::_reorder {comps} {
742    set i 0
743    set max [llength $comps]
744    while {$i < $max} {
745        set c [lindex $comps $i]
746        if {[string match log* $c]} {
747            set comps [lreplace $comps $i $i]
748            lappend comps $c
749            incr max -1
750        } else {
751            incr i
752        }
753    }
754    return $comps
755}
756
757# ----------------------------------------------------------------------
758# USAGE: _autoLabel <xmlobj> <path> <title> <cntVar>
759#
760# Used internally to check for an about.label property at the <path>
761# in <xmlobj>.  If this object doesn't have a label, then one is
762# supplied using the given <title>.  The <cntVar> is an array of
763# counters in the calling scopes for titles that have been used
764# in the past.  This is used to create titles like "Plot #2" the
765# second time it is encountered.
766#
767# The <xmlobj> is updated so that the label is inserted directly in
768# the tree.
769# ----------------------------------------------------------------------
770itcl::body Rappture::Analyzer::_autoLabel {xmlobj path title cntVar} {
771    upvar $cntVar counters
772
773    set group [$xmlobj get $path.about.group]
774    set label [$xmlobj get $path.about.label]
775    if {"" == $label} {
776        # no label -- make one up using the title specified
777        if {![info exists counters($group-$title)]} {
778            set counters($group-$title) 1
779            set label $title
780        } else {
781            set label "$title (#[incr counters($group-$title)])"
782        }
783        $xmlobj put $path.about.label $label
784    } else {
785        # handle the case of two identical labels in <output>
786        if {![info exists counters($group-$label)]} {
787            set counters($group-$label) 1
788        } else {
789            set label "$label (#[incr counters($group-$label)])"
790            $xmlobj put $path.about.label $label
791        }
792    }
793    return $label
794}
795
796# ----------------------------------------------------------------------
797# USAGE: _fixResult
798#
799# Used internally to change the result page being displayed whenever
800# the user selects a page from the results combobox.
801# ----------------------------------------------------------------------
802itcl::body Rappture::Analyzer::_fixResult {} {
803    set name [$itk_component(resultselector) value]
804    set page ""
805    if {"" != $name} {
806        set page [$itk_component(resultselector) translate $name]
807    }
808    if {$page == "@download"} {
809        # put the combobox back to its last value
810        $itk_component(resultselector) component entry configure -state normal
811        $itk_component(resultselector) component entry delete 0 end
812        $itk_component(resultselector) component entry insert end $_lastlabel
813        $itk_component(resultselector) component entry configure -state disabled
814        # perform the actual download
815        download start $itk_component(resultselector)
816    } elseif {$page == "---"} {
817        # put the combobox back to its last value
818        $itk_component(resultselector) component entry configure -state normal
819        $itk_component(resultselector) component entry delete 0 end
820        $itk_component(resultselector) component entry insert end $_lastlabel
821        $itk_component(resultselector) component entry configure -state disabled
822    } elseif {$page != ""} {
823        set _lastlabel $name
824        set win [winfo toplevel $itk_component(hull)]
825        blt::busy hold $win; update idletasks
826        $itk_component(resultpages) current $page
827
828        set f [$itk_component(resultpages) page $page]
829        $f.rviewer plot clear
830        eval $f.rviewer plot add $_plotlist
831        blt::busy release [winfo toplevel $itk_component(hull)]
832    }
833}
834
835# ----------------------------------------------------------------------
836# USAGE: _fixSize
837#
838# Used internally to change the size of the result set area whenever
839# a new control appears.  Adjusts the size available for the result
840# set up to some maximum.
841# ----------------------------------------------------------------------
842itcl::body Rappture::Analyzer::_fixSize {} {
843    set ht [winfo height $itk_component(results)]
844    if {$ht <= 1} { set ht [winfo reqheight $itk_component(results)] }
845    set cntlht [$itk_component(resultset) size -controlarea]
846    set frac [expr {double($cntlht)/$ht}]
847
848    if {$frac < 0.4} {
849        $itk_component(results) fraction end $frac
850    }
851    _fixSimControl
852}
853
854# ----------------------------------------------------------------------
855# USAGE: _simState <boolean> ?<message>? ?<settings>?
856#
857# Used internally to change the "Simulation" button on or off.
858# If the <boolean> is on, then any <message> and <settings> are
859# displayed as well.  If the <boolean> is off, then only display
860# the message. The <message> is a note to the user about
861# what will be simulated, and the <settings> are a list of
862# tool parameter settings of the form {path1 val1 path2 val2 ...}.
863# When these are in place, the next Simulate operation will use
864# these settings.  This helps fill in missing data values.
865# ----------------------------------------------------------------------
866itcl::body Rappture::Analyzer::_simState {state args} {
867    if {$state} {
868        $itk_interior.simol configure \
869            -background $itk_option(-simcontrolactiveoutline)
870        $itk_interior.simol.simbg configure \
871            -background $itk_option(-simcontrolactivebackground)
872        $itk_component(simulate) configure \
873            -highlightbackground $itk_option(-simcontrolactivebackground)
874        $itk_component(simstatus) configure \
875            -background $itk_option(-simcontrolactivebackground)
876
877        $itk_component(abort) configure -state disabled
878        $itk_component(simulate) configure -state normal \
879            -command [itcl::code $this simulate]
880
881        #
882        # If there's a special message, then put it up next to the button.
883        #
884        set mesg [lindex $args 0]
885        if {"" != $mesg} {
886            $itk_component(simstatus) configure -state normal
887            $itk_component(simstatus) delete 1.0 end
888            $itk_component(simstatus) insert end $mesg
889
890            #
891            # If there are any settings, then install them in the
892            # "Simulate" button.  Also, pop them up as a tooltip
893            # for the message.
894            #
895            set settings [lindex $args 1]
896            if {[llength $settings] > 0} {
897                $itk_component(simulate) configure \
898                    -command [eval itcl::code $this simulate $settings]
899
900                set details ""
901                foreach {path val} $settings {
902                    set str [$_tool xml get $path.about.label]
903                    if {"" == $str} {
904                        set str [$_tool xml element -as id $path]
905                    }
906                    append details "$str = $val\n"
907                }
908                set details [string trim $details]
909
910                Rappture::Tooltip::for $itk_component(simstatus) $details
911                $itk_component(simstatus) insert end " "
912                $itk_component(simstatus) insert end "(details...)" popup
913            }
914            $itk_component(simstatus) configure -state disabled
915        }
916    } else {
917        if {"" != $itk_option(-simcontrolbackground)} {
918            set simcbg $itk_option(-simcontrolbackground)
919        } else {
920            set simcbg $itk_option(-background)
921        }
922        $itk_interior.simol configure \
923            -background $itk_option(-simcontroloutline)
924        $itk_interior.simol.simbg configure -background $simcbg
925        $itk_component(simulate) configure -highlightbackground $simcbg
926        $itk_component(simstatus) configure -background $simcbg
927
928        $itk_component(simulate) configure -state disabled
929        $itk_component(abort) configure -state normal
930
931        $itk_component(simstatus) configure -state normal
932        $itk_component(simstatus) delete 1.0 end
933        set mesg [lindex $args 0]
934        if {"" != $mesg} {
935            $itk_component(simstatus) insert end $mesg
936        }
937        $itk_component(simstatus) configure -state disabled
938    }
939}
940
941# ----------------------------------------------------------------------
942# USAGE: _simOutput <message>
943#
944# Invoked automatically whenever output comes in while running the
945# tool.  Extracts any =RAPPTURE-???=> messages from the output and
946# sends the output to the display.  For example, any
947# =RAPPTURE-PROGRESS=> message pops up the progress meter and updates
948# it to show the latest progress message.  This is useful for
949# long-running tools, to let the user know how much longer the
950# simulation will take.
951# ----------------------------------------------------------------------
952itcl::body Rappture::Analyzer::_simOutput {message} {
953    #
954    # Scan through and pick out any =RAPPTURE-PROGRESS=> messages first.
955    #
956    while {[regexp -indices \
957               {=RAPPTURE-PROGRESS=> *([-+]?[0-9]+) +([^\n]*)(\n|$)} $message \
958                match percent mesg]} {
959
960        foreach {i0 i1} $percent break
961        set percent [string range $message $i0 $i1]
962
963        foreach {i0 i1} $mesg break
964        set mesg [string range $message $i0 $i1]
965
966        pack $itk_component(progress) -fill x -padx 10 -pady 10
967        $itk_component(progress) settings -percent $percent -message $mesg
968
969        foreach {i0 i1} $match break
970        set message [string replace $message $i0 $i1]
971    }
972
973    #
974    # Break up the remaining lines according to =RAPPTURE-ERROR=> messages.
975    # Show errors in a special color.
976    #
977    $itk_component(runinfo) configure -state normal
978
979    while {[regexp -indices \
980               {=RAPPTURE-([a-zA-Z]+)=>([^\n]*)(\n|$)} $message \
981                match type mesg]} {
982
983        foreach {i0 i1} $match break
984        set first [string range $message 0 [expr {$i0-1}]]
985        if {[string length $first] > 0} {
986            $itk_component(runinfo) insert end $first
987            $itk_component(runinfo) insert end \n
988        }
989
990        foreach {t0 t1} $type break
991        set type [string range $message $t0 $t1]
992        foreach {m0 m1} $mesg break
993        set mesg [string range $message $m0 $m1]
994        if {[string length $mesg] > 0 && $type != "RUN"} {
995            $itk_component(runinfo) insert end $mesg $type
996            $itk_component(runinfo) insert end \n $type
997        }
998
999        set message [string range $message [expr {$i1+1}] end]
1000    }
1001
1002    if {[string length $message] > 0} {
1003        $itk_component(runinfo) insert end $message
1004        if {[$itk_component(runinfo) get end-2char] != "\n"} {
1005            $itk_component(runinfo) insert end "\n"
1006        }
1007        $itk_component(runinfo) see end
1008    }
1009    $itk_component(runinfo) configure -state disabled
1010}
1011
1012# ----------------------------------------------------------------------
1013# USAGE: _resultTooltip
1014#
1015# Used internally to build the tooltip string displayed for the
1016# result selector.  If the current page has an associated description,
1017# then it is displayed beneath the result.
1018#
1019# Returns the string for the tooltip.
1020# ----------------------------------------------------------------------
1021itcl::body Rappture::Analyzer::_resultTooltip {} {
1022    set tip ""
1023    set name [$itk_component(resultselector) value]
1024    if {[info exists _label2desc($name)] &&
1025         [string length $_label2desc($name)] > 0} {
1026        append tip "$_label2desc($name)\n\n"
1027    }
1028    if {[array size _label2page] > 1} {
1029        append tip "Use this control to display other output results."
1030    }
1031    return $tip
1032}
1033
1034# ----------------------------------------------------------------------
1035# USAGE: _fixSimControl
1036#
1037# Used internally to add or remove the simulation control at the
1038# top of the analysis area.  This is controlled by the -simcontrol
1039# option.
1040# ----------------------------------------------------------------------
1041itcl::body Rappture::Analyzer::_fixSimControl {} {
1042    switch -- $itk_option(-simcontrol) {
1043        on {
1044            pack $itk_interior.simol -fill x -before $itk_interior.nb
1045        }
1046        off {
1047            pack forget $itk_interior.simol
1048        }
1049        auto {
1050            #
1051            # If we have two or more radiodials, then there is a
1052            # chance of encountering a combination of parameters
1053            # with no data, requiring simulation.
1054            #
1055            if {[$itk_component(resultset) size -controls] >= 2} {
1056                pack $itk_interior.simol -fill x -before $itk_interior.nb
1057            } else {
1058                pack forget $itk_interior.simol
1059            }
1060        }
1061        default {
1062            error "bad value \"$itk_option(-simcontrol)\": should be on, off, auto"
1063        }
1064    }
1065}
1066
1067# ----------------------------------------------------------------------
1068# USAGE: _fixNotebook
1069#
1070# Used internally to switch the active notebook page
1071# ----------------------------------------------------------------------
1072itcl::body Rappture::Analyzer::_fixNotebook {} {
1073    switch -- $itk_option(-notebookpage) {
1074        about {
1075            $itk_component(notebook) current about
1076        }
1077        simulate {
1078            $itk_component(notebook) current simulate
1079        }
1080        analyze {
1081            $itk_component(notebook) current analyze
1082        }
1083        default {
1084            error "bad value \"$itk_option(-notebookpage)\": should be about, simulate, analyze"
1085        }
1086    }
1087}
1088
1089# ----------------------------------------------------------------------
1090# CONFIGURATION OPTION: -simcontrol
1091#
1092# Controls whether or not the Simulate button is showing.  In some
1093# cases, it is not needed.
1094# ----------------------------------------------------------------------
1095itcl::configbody Rappture::Analyzer::simcontrol {
1096    _fixSimControl
1097}
1098
1099# ----------------------------------------------------------------------
1100# CONFIGURATION OPTION: -notebookpage
1101#
1102# Controls which page of the analyzer notebook is shown. It is
1103# particularly needed when using rerun, when you don't want to
1104# "simulate -ifneeded" because an actual simulation might be
1105# kicked off due to differences between tool.xml and run.xml
1106# ----------------------------------------------------------------------
1107itcl::configbody Rappture::Analyzer::notebookpage {
1108    _fixNotebook
1109}
Note: See TracBrowser for help on using the repository browser.