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

Last change on this file since 43 was 43, checked in by mmc, 19 years ago
  • Added a new Rappture.result() function to the Python library. This makes it easy to finalize results. See examples/graph for example use.
  • Added examples/graph to illustrate a simple tool with a string and two numbers for input.
  • Fixed the XY graph to show crosshairs and pop-up info when you mouse over particular points.
  • Fixed Rappture::exec so that it doesn't add stray newlines when a program has lots (more than 8k) of output.
  • Fixed the analyzer to recognize the <tool><analyzer> tag. When set to "last", this automatically clears the last result. Handy for programs like SPICE, where you don't compare much, but keep running one new simulation after another.
  • Fixed <string> entries to enable the Simulate button after each editing keystroke.
File size: 28.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
13#  Purdue Research Foundation, West Lafayette, IN
14# ======================================================================
15package require Itk
16
17option add *Analyzer.width 5i widgetDefault
18option add *Analyzer.height 5i widgetDefault
19option add *Analyzer.simControl "auto" widgetDefault
20option add *Analyzer.simControlBackground "" widgetDefault
21option add *Analyzer.simControlOutline gray widgetDefault
22option add *Analyzer.simControlActiveBackground #ffffcc widgetDefault
23option add *Analyzer.simControlActiveOutline black widgetDefault
24
25option add *Analyzer.font \
26    -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
27option add *Analyzer.textFont \
28    -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
29option add *Analyzer.boldTextFont \
30    -*-helvetica-bold-r-normal-*-*-120-* widgetDefault
31
32itcl::class Rappture::Analyzer {
33    inherit itk::Widget
34
35    itk_option define -textfont textFont Font ""
36    itk_option define -boldtextfont boldTextFont Font ""
37    itk_option define -simcontrol simControl SimControl ""
38    itk_option define -simcontroloutline simControlOutline Background ""
39    itk_option define -simcontrolbackground simControlBackground Background ""
40    itk_option define -simcontrolactiveoutline simControlActiveOutline Background ""
41    itk_option define -simcontrolactivebackground simControlActiveBackground Background ""
42    itk_option define -holdwindow holdWindow HoldWindow ""
43
44    constructor {tool args} { # defined below }
45    destructor { # defined below }
46
47    public method simulate {args}
48    public method reset {}
49    public method load {file}
50    public method clear {}
51
52    protected method _plot {args}
53    protected method _reorder {comps}
54    protected method _autoLabel {xmlobj path title cntVar}
55    protected method _fixResult {}
56    protected method _fixSize {}
57    protected method _fixSimControl {}
58    protected method _simState {state args}
59    protected method _simOutput {message}
60
61    private variable _tool ""          ;# belongs to this tool
62    private variable _control "manual" ;# start mode
63    private variable _runs ""          ;# list of XML objects with results
64    private variable _pages 0          ;# number of pages for result sets
65    private variable _label2page       ;# maps output label => result set
66    private variable _plotlist ""      ;# items currently being plotted
67
68    private common job                 ;# array var used for blt::bgexec jobs
69}
70                                                                               
71itk::usual Analyzer {
72    keep -background -cursor foreground -font
73}
74
75# ----------------------------------------------------------------------
76# CONSTRUCTOR
77# ----------------------------------------------------------------------
78itcl::body Rappture::Analyzer::constructor {tool args} {
79    set _tool $tool
80
81    itk_option add hull.width hull.height
82    pack propagate $itk_component(hull) no
83
84    frame $itk_interior.simol -borderwidth 1 -relief flat
85    pack $itk_interior.simol -fill x
86
87    frame $itk_interior.simol.simbg -borderwidth 0
88    pack $itk_interior.simol.simbg -expand yes -fill both
89
90    itk_component add simulate {
91        button $itk_interior.simol.simbg.simulate -text "Simulate" \
92            -command [itcl::code $this simulate]
93    }
94    pack $itk_component(simulate) -side left -padx 4 -pady 4
95
96    itk_component add simstatus {
97        text $itk_interior.simol.simbg.simstatus -borderwidth 0 \
98            -highlightthickness 0 -height 1 -width 1 -wrap none \
99            -state disabled
100    } {
101        usual
102        ignore -highlightthickness
103        rename -font -textfont textFont Font
104    }
105    pack $itk_component(simstatus) -side left -expand yes -fill x
106
107    $itk_component(simstatus) tag configure popup \
108        -underline 1 -foreground blue
109
110    $itk_component(simstatus) tag bind popup \
111        <Enter> {%W configure -cursor center_ptr}
112    $itk_component(simstatus) tag bind popup \
113        <Leave> {%W configure -cursor ""}
114    $itk_component(simstatus) tag bind popup \
115        <ButtonPress> {after idle {Rappture::Tooltip::tooltip show %W}}
116
117
118    itk_component add notebook {
119        Rappture::Notebook $itk_interior.nb
120    }
121    pack $itk_interior.nb -expand yes -fill both
122
123    # ------------------------------------------------------------------
124    # ABOUT PAGE
125    # ------------------------------------------------------------------
126    set w [$itk_component(notebook) insert end about]
127
128    Rappture::Scroller $w.info -xscrollmode off -yscrollmode auto
129    pack $w.info -expand yes -fill both -padx 4 -pady 20
130    itk_component add toolinfo {
131        text $w.info.text -width 1 -height 1 -wrap word \
132            -borderwidth 0 -highlightthickness 0
133    } {
134        usual
135        ignore -borderwidth -relief
136        rename -font -textfont textFont Font
137    }
138    $w.info contents $w.info.text
139
140    # ------------------------------------------------------------------
141    # SIMULATION PAGE
142    # ------------------------------------------------------------------
143    set w [$itk_component(notebook) insert end simulate]
144    frame $w.cntls
145    pack $w.cntls -side bottom -fill x -pady 12
146    frame $w.cntls.sep -background black -height 1
147    pack $w.cntls.sep -side top -fill x
148
149    itk_component add abort {
150        button $w.cntls.abort -text "Abort" \
151            -command [itcl::code $_tool abort]
152    }
153    pack $itk_component(abort) -side left -expand yes -padx 4 -pady 4
154
155    Rappture::Scroller $w.info -xscrollmode off -yscrollmode auto
156    pack $w.info -expand yes -fill both -padx 4 -pady 4
157    itk_component add runinfo {
158        text $w.info.text -width 1 -height 1 -wrap word \
159            -borderwidth 0 -highlightthickness 0 \
160            -state disabled
161    } {
162        usual
163        ignore -borderwidth -relief
164        rename -font -textfont textFont Font
165    }
166    $w.info contents $w.info.text
167
168    $itk_component(runinfo) tag configure ERROR -foreground red
169
170    itk_component add progress {
171        Rappture::Progress $w.progress
172    }
173
174    # ------------------------------------------------------------------
175    # ANALYZE PAGE
176    # ------------------------------------------------------------------
177    set w [$itk_component(notebook) insert end analyze]
178
179    frame $w.top
180    pack $w.top -side top -fill x -pady 8
181    label $w.top.l -text "Result:" -font $itk_option(-font)
182    pack $w.top.l -side left
183
184    itk_component add resultselector {
185        Rappture::Combobox $w.top.sel -width 50 -editable no
186    } {
187        usual
188        rename -font -textfont textFont Font
189    }
190    pack $itk_component(resultselector) -side left -expand yes -fill x
191    bind $itk_component(resultselector) <<Value>> [itcl::code $this _fixResult]
192
193    itk_component add results {
194        Rappture::Panes $w.pane
195    }
196    pack $itk_component(results) -expand yes -fill both
197    set f [$itk_component(results) pane 0]
198
199    itk_component add resultpages {
200        Rappture::Notebook $f.nb
201    }
202    pack $itk_component(resultpages) -expand yes -fill both
203
204    set f [$itk_component(results) insert end -fraction 0.1]
205    itk_component add resultset {
206        Rappture::ResultSet $f.rset \
207            -clearcommand [itcl::code $this clear] \
208            -settingscommand [itcl::code $this _plot] \
209            -promptcommand [itcl::code $this _simState]
210    }
211    pack $itk_component(resultset) -expand yes -fill both
212    bind $itk_component(resultset) <<Control>> [itcl::code $this _fixSize]
213
214    eval itk_initialize $args
215
216    #
217    # Load up tool info on the first page.
218    #
219    $itk_component(toolinfo) tag configure title \
220        -font $itk_option(-boldtextfont)
221
222    set mesg [$tool xml get tool.title]
223    if {"" != $mesg} {
224        $itk_component(toolinfo) insert end $mesg title
225        $itk_component(toolinfo) insert end "\n\n"
226    }
227
228    set mesg [$tool xml get tool.about]
229    if {"" != $mesg} {
230        $itk_component(toolinfo) insert end $mesg
231    }
232    $itk_component(toolinfo) configure -state disabled
233    $itk_component(notebook) current about
234
235    # tool can run on "manual" (default) or "auto"
236    set cntl [$tool xml get tool.control]
237    if {"" == $cntl} {
238        set cntl [$tool xml get tool.control.type]
239    }
240    if {"" != $cntl} {
241        set _control $cntl
242    }
243
244    # reset everything to a clean state
245    reset
246}
247
248# ----------------------------------------------------------------------
249# DESTRUCTOR
250# ----------------------------------------------------------------------
251itcl::body Rappture::Analyzer::destructor {} {
252    foreach obj $_runs {
253        itcl::delete object $obj
254    }
255    after cancel [itcl::code $this simulate]
256}
257
258# ----------------------------------------------------------------------
259# USAGE: simulate ?-ifneeded?
260# USAGE: simulate ?<path1> <value1> <path2> <value2> ...?
261#
262# Kicks off the simulator by executing the tool.command associated
263# with the tool.  If any arguments are specified, they are used to
264# set parameters for the simulation.  While the simulation is running,
265# it shows status.  When the simulation is finished, it switches
266# automatically to "analyze" mode and shows the results.
267# ----------------------------------------------------------------------
268itcl::body Rappture::Analyzer::simulate {args} {
269    if {$args == "-ifneeded"} {
270        # check to see if simulation is really needed
271        $_tool sync
272        if {[$itk_component(resultset) contains [$_tool xml object]]} {
273            # not needed -- show results and return
274            $itk_component(notebook) current analyze
275            return
276        }
277        set args ""
278    }
279
280    # simulation is needed -- go to simulation page
281    $itk_component(notebook) current simulate
282
283    # no progress messages yet
284    pack forget $itk_component(progress)
285    lappend args -output [itcl::code $this _simOutput]
286
287    _simState off
288    $itk_component(runinfo) configure -state normal
289    $itk_component(runinfo) delete 1.0 end
290    $itk_component(runinfo) insert end "Running simulation...\n\n"
291    $itk_component(runinfo) configure -state disabled
292
293    # if the hold window is set, then put up a busy cursor
294    if {$itk_option(-holdwindow) != ""} {
295        blt::busy hold $itk_option(-holdwindow)
296        raise $itk_component(hull)
297        update
298    }
299
300    # execute the job
301    foreach {status result} [eval $_tool run $args] break
302
303    # if job was aborted, then allow simulation again
304    if {$result == "ABORT"} {
305        _simState on "Aborted"
306    }
307
308    # read back the results from run.xml
309    if {$status == 0 && $result != "ABORT"} {
310        if {[regexp {=RAPPTURE-RUN=>([^\n]+)} $result match file]} {
311            set status [catch {load $file} msg]
312            if {$status != 0} {
313                global errorInfo
314                set result "$msg\n$errorInfo"
315            }
316        } else {
317            set status 1
318            set result "Can't find result file in output:\n\n$result"
319        }
320    }
321
322    # back to normal
323    if {$itk_option(-holdwindow) != ""} {
324        blt::busy release $itk_option(-holdwindow)
325    }
326    $itk_component(abort) configure -state disabled
327
328    if {$status != 0} {
329        $itk_component(runinfo) configure -state normal
330        $itk_component(runinfo) delete 1.0 end
331        $itk_component(runinfo) insert end "Problem launching job:\n\n"
332        _simOutput $result
333        $itk_component(runinfo) configure -state disabled
334        $itk_component(runinfo) see 1.0
335    } else {
336        $itk_component(notebook) current analyze
337    }
338}
339
340# ----------------------------------------------------------------------
341# USAGE: reset
342#
343# Used to reset the analyzer whenever the input to a simulation has
344# changed.  Sets the mode back to "simulate", so the user has to
345# simulate again to see the output.  If the <start> option is set
346# to "auto", the simulation is invoked immediately.
347# ----------------------------------------------------------------------
348itcl::body Rappture::Analyzer::reset {} {
349    # check to see if simulation is really needed
350    $_tool sync
351    if {![$itk_component(resultset) contains [$_tool xml object]]} {
352        # if control mode is "auto", then simulate right away
353        if {[string match auto* $_control]} {
354            # auto control -- don't need button
355            pack forget $itk_interior.simol
356
357            after cancel [itcl::code $this simulate]
358            after idle [itcl::code $this simulate]
359        } else {
360            _simState on "new input parameters"
361        }
362    } else {
363        _simState off
364    }
365}
366
367# ----------------------------------------------------------------------
368# USAGE: load <file>
369#
370# Loads the data from the given <file> into the appropriate results
371# sets.  If necessary, new results sets are created to store the data.
372# ----------------------------------------------------------------------
373itcl::body Rappture::Analyzer::load {file} {
374    # only show the last result? then clear first
375    if {[$_tool xml get tool.analyzer] == "last"} {
376        clear
377    }
378
379    # try to load new results from the given file
380    set xmlobj [Rappture::library $file]
381    lappend _runs $xmlobj
382
383    # go through the analysis and find all result sets
384    set haveresults 0
385    foreach item [_reorder [$xmlobj children output]] {
386        switch -glob -- $item {
387            log* {
388                _autoLabel $xmlobj output.$item "Output Log" counters
389            }
390            curve* - field* {
391                _autoLabel $xmlobj output.$item "Plot" counters
392            }
393            structure* {
394                _autoLabel $xmlobj output.$item "Structure" counters
395            }
396            table* {
397                _autoLabel $xmlobj output.$item "Energy Levels" counters
398            }
399        }
400        set label [$xmlobj get output.$item.about.group]
401        if {"" == $label} {
402            set label [$xmlobj get output.$item.about.label]
403        }
404
405        set hidden [$xmlobj get output.$item.hide]
406        set hidden [expr {"" != $hidden && $hidden}]
407
408        if {"" != $label && !$hidden} {
409            set haveresults 1
410        }
411    }
412
413    # if there are any valid results, add them to the resultset
414    if {$haveresults} {
415        set size [$itk_component(resultset) size]
416        set index [$itk_component(resultset) add $xmlobj]
417
418        # add each result to a result viewer
419        foreach item [_reorder [$xmlobj children output]] {
420            set label [$xmlobj get output.$item.about.group]
421            if {"" == $label} {
422                set label [$xmlobj get output.$item.about.label]
423            }
424
425            set hidden [$xmlobj get output.$item.hide]
426            set hidden [expr {"" != $hidden && $hidden}]
427
428            if {"" != $label && !$hidden} {
429                if {![info exists _label2page($label)]} {
430                    set name "page[incr _pages]"
431                    set page [$itk_component(resultpages) insert end $name]
432                    set _label2page($label) $page
433                    Rappture::ResultViewer $page.rviewer
434                    pack $page.rviewer -expand yes -fill both -pady 4
435
436                    $itk_component(resultselector) choices insert end \
437                        $name $label
438                }
439
440                # add/replace the latest result into this viewer
441                set page $_label2page($label)
442
443                if {![info exists reset($page)]} {
444                    $page.rviewer clear $index
445                    set reset($page) 1
446                }
447                $page.rviewer add $index $xmlobj output.$item
448            }
449        }
450    }
451
452    # if there is only one result page, take down the selector
453    set w [$itk_component(notebook) page analyze]
454    if {[$itk_component(resultselector) choices size] <= 1} {
455        pack forget $w.top
456    } else {
457        pack $w.top -before $itk_component(results) -side top -fill x
458    }
459
460    # show the first page by default
461    set first [$itk_component(resultselector) choices get -label 0]
462    if {$first != ""} {
463        set page [$itk_component(resultselector) choices get -value 0]
464        $itk_component(resultpages) current $page
465        $itk_component(resultselector) value $first
466    }
467}
468
469# ----------------------------------------------------------------------
470# USAGE: clear
471#
472# Discards all results previously loaded into the analyzer.
473# ----------------------------------------------------------------------
474itcl::body Rappture::Analyzer::clear {} {
475    foreach obj $_runs {
476        itcl::delete object $obj
477    }
478    set _runs ""
479
480    $itk_component(resultset) clear
481    $itk_component(results) fraction end 0.1
482
483    foreach label [array names _label2page] {
484        set page $_label2page($label)
485        $page.rviewer clear
486    }
487    $itk_component(resultselector) value ""
488    $itk_component(resultselector) choices delete 0 end
489    catch {unset _label2page}
490    set _plotlist ""
491
492    #
493    # HACK ALERT!!
494    # The following statement should be in place, but it causes
495    # vtk to dump core.  Leave it out until we can fix the core dump.
496    # In the mean time, we leak memory...
497    #
498    #$itk_component(resultpages) delete -all
499    #set _pages 0
500
501    _simState on
502    _fixSimControl
503    reset
504}
505
506# ----------------------------------------------------------------------
507# USAGE: _plot ?<index> <options> <index> <options>...?
508#
509# Used internally to update the plot shown in the current result
510# viewer whenever the resultset settings have changed.  Causes the
511# desired results to show up on screen.
512# ----------------------------------------------------------------------
513itcl::body Rappture::Analyzer::_plot {args} {
514    set _plotlist $args
515
516    set page [$itk_component(resultselector) value]
517    set page [$itk_component(resultselector) translate $page]
518    if {"" != $page} {
519        set f [$itk_component(resultpages) page $page]
520        $f.rviewer plot clear
521        foreach {index opts} $_plotlist {
522            $f.rviewer plot add $index $opts
523        }
524    }
525}
526
527# ----------------------------------------------------------------------
528# USAGE: _reorder <compList>
529#
530# Used internally to change the order of a series of output components
531# found in the <output> section.  Moves the <log> elements to the end
532# and returns the updated list.
533# ----------------------------------------------------------------------
534itcl::body Rappture::Analyzer::_reorder {comps} {
535    set i 0
536    set max [llength $comps]
537    while {$i < $max} {
538        set c [lindex $comps $i]
539        if {[string match log* $c]} {
540            set comps [lreplace $comps $i $i]
541            lappend comps $c
542            incr max -1
543        } else {
544            incr i
545        }
546    }
547    return $comps
548}
549
550# ----------------------------------------------------------------------
551# USAGE: _autoLabel <xmlobj> <path> <title> <cntVar>
552#
553# Used internally to check for an about.label property at the <path>
554# in <xmlobj>.  If this object doesn't have a label, then one is
555# supplied using the given <title>.  The <cntVar> is an array of
556# counters in the calling scopes for titles that have been used
557# in the past.  This is used to create titles like "Plot #2" the
558# second time it is encountered.
559#
560# The <xmlobj> is updated so that the label is inserted directly in
561# the tree.
562# ----------------------------------------------------------------------
563itcl::body Rappture::Analyzer::_autoLabel {xmlobj path title cntVar} {
564    upvar $cntVar counters
565
566    set group [$xmlobj get $path.about.group]
567    set label [$xmlobj get $path.about.label]
568    if {"" == $label} {
569        # no label -- make one up using the title specified
570        if {![info exists counters($group-$title)]} {
571            set counters($group-$title) 1
572            set label $title
573        } else {
574            set label "$title (#[incr counters($group-$title)])"
575        }
576        $xmlobj put $path.about.label $label
577    } else {
578        # handle the case of two identical labels in <output>
579        if {![info exists counters($group-$label)]} {
580            set counters($group-$label) 1
581        } else {
582            set label "$label (#[incr counters($group-$label)])"
583            $xmlobj put $path.about.label $label
584        }
585    }
586    return $label
587}
588
589# ----------------------------------------------------------------------
590# USAGE: _fixResult
591#
592# Used internally to change the result page being displayed whenever
593# the user selects a page from the results combobox.
594# ----------------------------------------------------------------------
595itcl::body Rappture::Analyzer::_fixResult {} {
596    set page [$itk_component(resultselector) value]
597    set page [$itk_component(resultselector) translate $page]
598    if {$page != ""} {
599        $itk_component(resultpages) current $page
600
601        set f [$itk_component(resultpages) page $page]
602        $f.rviewer plot clear
603        eval $f.rviewer plot add $_plotlist
604    }
605}
606
607# ----------------------------------------------------------------------
608# USAGE: _fixSize
609#
610# Used internally to change the size of the result set area whenever
611# a new control appears.  Adjusts the size available for the result
612# set up to some maximum.
613# ----------------------------------------------------------------------
614itcl::body Rappture::Analyzer::_fixSize {} {
615    set f [$itk_component(results) fraction end]
616    if {$f < 0.4} {
617        $itk_component(results) fraction end [expr {$f+0.15}]
618    }
619    _fixSimControl
620}
621
622# ----------------------------------------------------------------------
623# USAGE: _simState <boolean> ?<message>? ?<settings>?
624#
625# Used internally to change the "Simulation" button on or off.
626# If the <boolean> is on, then any <message> and <settings> are
627# displayed as well.  The <message> is a note to the user about
628# what will be simulated, and the <settings> are a list of
629# tool parameter settings of the form {path1 val1 path2 val2 ...}.
630# When these are in place, the next Simulate operation will use
631# these settings.  This helps fill in missing data values.
632# ----------------------------------------------------------------------
633itcl::body Rappture::Analyzer::_simState {state args} {
634    if {$state} {
635        $itk_interior.simol configure \
636            -background $itk_option(-simcontrolactiveoutline)
637        $itk_interior.simol.simbg configure \
638            -background $itk_option(-simcontrolactivebackground)
639        $itk_component(simulate) configure \
640            -highlightbackground $itk_option(-simcontrolactivebackground)
641        $itk_component(simstatus) configure \
642            -background $itk_option(-simcontrolactivebackground)
643
644        $itk_component(abort) configure -state disabled
645        $itk_component(simulate) configure -state normal \
646            -command [itcl::code $this simulate]
647
648        #
649        # If there's a special message, then put it up next to the button.
650        #
651        set mesg [lindex $args 0]
652        if {"" != $mesg} {
653            $itk_component(simstatus) configure -state normal
654            $itk_component(simstatus) delete 1.0 end
655            $itk_component(simstatus) insert end $mesg
656
657            #
658            # If there are any settings, then install them in the
659            # "Simulate" button.  Also, pop them up as a tooltip
660            # for the message.
661            #
662            set settings [lindex $args 1]
663            if {[llength $settings] > 0} {
664                $itk_component(simulate) configure \
665                    -command [eval itcl::code $this simulate $settings]
666
667                set details ""
668                foreach {path val} $settings {
669                    set str [$_tool xml get $path.about.label]
670                    if {"" == $str} {
671                        set str [$_tool xml element -as id $path]
672                    }
673                    append details "$str = $val\n"
674                }
675                set details [string trim $details]
676
677                Rappture::Tooltip::for $itk_component(simstatus) $details
678                $itk_component(simstatus) insert end " "
679                $itk_component(simstatus) insert end "(details...)" popup
680            }
681            $itk_component(simstatus) configure -state disabled
682        }
683    } else {
684        if {"" != $itk_option(-simcontrolbackground)} {
685            set simcbg $itk_option(-simcontrolbackground)
686        } else {
687            set simcbg $itk_option(-background)
688        }
689        $itk_interior.simol configure \
690            -background $itk_option(-simcontroloutline)
691        $itk_interior.simol.simbg configure -background $simcbg
692        $itk_component(simulate) configure -highlightbackground $simcbg
693        $itk_component(simstatus) configure -background $simcbg
694
695        $itk_component(simulate) configure -state disabled
696        $itk_component(abort) configure -state normal
697
698        $itk_component(simstatus) configure -state normal
699        $itk_component(simstatus) delete 1.0 end
700        $itk_component(simstatus) configure -state disabled
701        Rappture::Tooltip::for $itk_component(simstatus) ""
702    }
703}
704
705# ----------------------------------------------------------------------
706# USAGE: _simOutput <message>
707#
708# Invoked automatically whenever output comes in while running the
709# tool.  Extracts any =RAPPTURE-???=> messages from the output and
710# sends the output to the display.  For example, any
711# =RAPPTURE-PROGRESS=> message pops up the progress meter and updates
712# it to show the latest progress message.  This is useful for
713# long-running tools, to let the user know how much longer the
714# simulation will take.
715# ----------------------------------------------------------------------
716itcl::body Rappture::Analyzer::_simOutput {message} {
717    #
718    # Scan through and pick out any =RAPPTURE-PROGRESS=> messages first.
719    #
720    while {[regexp -indices \
721               {=RAPPTURE-PROGRESS=>([0-9]+) +([^\n]*)(\n|$)} $message \
722                match percent mesg]} {
723
724        foreach {i0 i1} $percent break
725        set percent [string range $message $i0 $i1]
726
727        foreach {i0 i1} $mesg break
728        set mesg [string range $message $i0 $i1]
729
730        pack $itk_component(progress) -fill x -padx 10 -pady 10
731        $itk_component(progress) settings -percent $percent -message $mesg
732
733        foreach {i0 i1} $match break
734        set message [string replace $message $i0 $i1]
735    }
736
737    #
738    # Break up the remaining lines according to =RAPPTURE-ERROR=> messages.
739    # Show errors in a special color.
740    #
741    $itk_component(runinfo) configure -state normal
742
743    while {[regexp -indices \
744               {=RAPPTURE-([a-zA-Z]+)=>([^\n]*)(\n|$)} $message \
745                match type mesg]} {
746
747        foreach {i0 i1} $match break
748        set first [string range $message 0 [expr {$i0-1}]]
749        if {[string length $first] > 0} {
750            $itk_component(runinfo) insert end $first
751            $itk_component(runinfo) insert end \n
752        }
753
754        foreach {t0 t1} $type break
755        set type [string range $message $t0 $t1]
756        foreach {m0 m1} $mesg break
757        set mesg [string range $message $m0 $m1]
758        if {[string length $mesg] > 0 && $type != "RUN"} {
759            $itk_component(runinfo) insert end $mesg $type
760            $itk_component(runinfo) insert end \n $type
761        }
762
763        set message [string range $message [expr {$i1+1}] end]
764    }
765
766    if {[string length $message] > 0} {
767        $itk_component(runinfo) insert end $message
768        if {[$itk_component(runinfo) get end-2char] != "\n"} {
769            $itk_component(runinfo) insert end "\n"
770        }
771        $itk_component(runinfo) see end
772    }
773    $itk_component(runinfo) configure -state disabled
774}
775
776# ----------------------------------------------------------------------
777# USAGE: _fixSimControl
778#
779# Used internally to add or remove the simulation control at the
780# top of the analysis area.  This is controlled by the -simcontrol
781# option.
782# ----------------------------------------------------------------------
783itcl::body Rappture::Analyzer::_fixSimControl {} {
784    switch -- $itk_option(-simcontrol) {
785        on {
786            pack $itk_interior.simol -fill x -before $itk_interior.nb
787        }
788        off {
789            pack forget $itk_interior.simol
790        }
791        auto {
792            #
793            # If we have two or more radiodials, then there is a
794            # chance of encountering a combination of parameters
795            # with no data, requiring simulation.
796            #
797            if {[$itk_component(resultset) size -controls] >= 2} {
798                pack $itk_interior.simol -fill x -before $itk_interior.nb
799            } else {
800                pack forget $itk_interior.simol
801            }
802        }
803        default {
804            error "bad value \"$itk_option(-simcontrol)\": should be on, off, auto"
805        }
806    }
807}
808
809# ----------------------------------------------------------------------
810# CONFIGURATION OPTION: -simcontrol
811#
812# Controls whether or not the Simulate button is showing.  In some
813# cases, it is not needed.
814# ----------------------------------------------------------------------
815itcl::configbody Rappture::Analyzer::simcontrol {
816    _fixSimControl
817}
Note: See TracBrowser for help on using the repository browser.