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

Last change on this file since 23 was 23, checked in by mmc, 19 years ago

Fixed the output processing to recognize messages
tagged with the prefix =RAPPTURE-???=> as Rappture
directives. The following directives are now recognized:

=RAPPTURE-PROGRESS=>percent message
=RAPPTURE-ERROR=>message
=RAPPTURE-RUN=>runfile

Also, added the Rappture::exec command to make it easy
to exec a tool within a wrapper script and handle stdout
and stderr messages properly.

File size: 28.7 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: analyzer - output area for Rappture
3#
4#  This widget acts as the output side of a Rappture application.
5#  When the input has changed, it displays a Simulate button that
6#  launches the simulation.  When a simulation is running, this
7#  area shows status.  When it is finished, the results appear
8#  in place of the button, according to the specs in the <analyze>
9#  XML data.
10# ======================================================================
11#  AUTHOR:  Michael McLennan, Purdue University
12#  Copyright (c) 2004-2005
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                set result $msg
314            }
315        } else {
316            set status 1
317            set result "Can't find result file in output:\n\n$result"
318        }
319    }
320
321    # back to normal
322    if {$itk_option(-holdwindow) != ""} {
323        blt::busy release $itk_option(-holdwindow)
324    }
325    $itk_component(abort) configure -state disabled
326
327    if {$status != 0} {
328        $itk_component(runinfo) configure -state normal
329        $itk_component(runinfo) delete 1.0 end
330        $itk_component(runinfo) insert end "Problem launching job:\n\n"
331        $itk_component(runinfo) insert end $result
332        $itk_component(runinfo) configure -state disabled
333    } else {
334        $itk_component(notebook) current analyze
335    }
336}
337
338# ----------------------------------------------------------------------
339# USAGE: reset
340#
341# Used to reset the analyzer whenever the input to a simulation has
342# changed.  Sets the mode back to "simulate", so the user has to
343# simulate again to see the output.  If the <start> option is set
344# to "auto", the simulation is invoked immediately.
345# ----------------------------------------------------------------------
346itcl::body Rappture::Analyzer::reset {} {
347    # check to see if simulation is really needed
348    $_tool sync
349    if {![$itk_component(resultset) contains [$_tool xml object]]} {
350        # if control mode is "auto", then simulate right away
351        if {[string match auto* $_control]} {
352            # auto control -- don't need button
353            pack forget $itk_interior.simol
354
355            after cancel [itcl::code $this simulate]
356            after idle [itcl::code $this simulate]
357        } else {
358            _simState on "new input parameters"
359        }
360    } else {
361        _simState off
362    }
363}
364
365# ----------------------------------------------------------------------
366# USAGE: load <file>
367#
368# Loads the data from the given <file> into the appropriate results
369# sets.  If necessary, new results sets are created to store the data.
370# ----------------------------------------------------------------------
371itcl::body Rappture::Analyzer::load {file} {
372    # try to load new results from the given file
373    set xmlobj [Rappture::library $file]
374    lappend _runs $xmlobj
375
376    # go through the analysis and find all result sets
377    set haveresults 0
378    foreach item [_reorder [$xmlobj children output]] {
379        switch -glob -- $item {
380            log* {
381                _autoLabel $xmlobj output.$item "Output Log" counters
382            }
383            curve* - field* {
384                _autoLabel $xmlobj output.$item "Plot" counters
385            }
386            structure* {
387                _autoLabel $xmlobj output.$item "Structure" counters
388            }
389            table* {
390                _autoLabel $xmlobj output.$item "Energy Levels" counters
391            }
392        }
393        set label [$xmlobj get output.$item.about.group]
394        if {"" == $label} {
395            set label [$xmlobj get output.$item.about.label]
396        }
397
398        set hidden [$xmlobj get output.$item.hide]
399        set hidden [expr {"" != $hidden && $hidden}]
400
401        if {"" != $label && !$hidden} {
402            set haveresults 1
403        }
404    }
405
406    # if there are any valid results, add them to the resultset
407    if {$haveresults} {
408        set size [$itk_component(resultset) size]
409        set index [$itk_component(resultset) add $xmlobj]
410
411        # add each result to a result viewer
412        foreach item [_reorder [$xmlobj children output]] {
413            set label [$xmlobj get output.$item.about.group]
414            if {"" == $label} {
415                set label [$xmlobj get output.$item.about.label]
416            }
417
418            set hidden [$xmlobj get output.$item.hide]
419            set hidden [expr {"" != $hidden && $hidden}]
420
421            if {"" != $label && !$hidden} {
422                if {![info exists _label2page($label)]} {
423                    set name "page[incr _pages]"
424                    set page [$itk_component(resultpages) insert end $name]
425                    set _label2page($label) $page
426                    Rappture::ResultViewer $page.rviewer
427                    pack $page.rviewer -expand yes -fill both -pady 4
428
429                    $itk_component(resultselector) choices insert end \
430                        $name $label
431                }
432
433                # add/replace the latest result into this viewer
434                set page $_label2page($label)
435
436                if {![info exists reset($page)]} {
437                    $page.rviewer clear $index
438                    set reset($page) 1
439                }
440                $page.rviewer add $index $xmlobj output.$item
441            }
442        }
443    }
444
445    # if there is only one result page, take down the selector
446    set w [$itk_component(notebook) page analyze]
447    if {[$itk_component(resultselector) choices size] <= 1} {
448        pack forget $w.top
449    } else {
450        pack $w.top -before $itk_component(results) -side top -fill x
451    }
452
453    # show the first page by default
454    set first [$itk_component(resultselector) choices get -label 0]
455    if {$first != ""} {
456        set page [$itk_component(resultselector) choices get -value 0]
457        $itk_component(resultpages) current $page
458        $itk_component(resultselector) value $first
459    }
460}
461
462# ----------------------------------------------------------------------
463# USAGE: clear
464#
465# Discards all results previously loaded into the analyzer.
466# ----------------------------------------------------------------------
467itcl::body Rappture::Analyzer::clear {} {
468    foreach obj $_runs {
469        itcl::delete object $obj
470    }
471    set _runs ""
472
473    $itk_component(resultset) clear
474    $itk_component(results) fraction end 0.1
475
476    foreach label [array names _label2page] {
477        set page $_label2page($label)
478        $page.rviewer clear
479    }
480    $itk_component(resultselector) value ""
481    $itk_component(resultselector) choices delete 0 end
482    catch {unset _label2page}
483    set _plotlist ""
484
485    #
486    # HACK ALERT!!
487    # The following statement should be in place, but it causes
488    # vtk to dump core.  Leave it out until we can fix the core dump.
489    # In the mean time, we leak memory...
490    #
491    #$itk_component(resultpages) delete -all
492    #set _pages 0
493
494    _simState on
495    _fixSimControl
496    reset
497}
498
499# ----------------------------------------------------------------------
500# USAGE: _plot ?<index> <options> <index> <options>...?
501#
502# Used internally to update the plot shown in the current result
503# viewer whenever the resultset settings have changed.  Causes the
504# desired results to show up on screen.
505# ----------------------------------------------------------------------
506itcl::body Rappture::Analyzer::_plot {args} {
507    set _plotlist $args
508
509    set page [$itk_component(resultselector) value]
510    set page [$itk_component(resultselector) translate $page]
511    set f [$itk_component(resultpages) page $page]
512    $f.rviewer plot clear
513    foreach {index opts} $_plotlist {
514        $f.rviewer plot add $index $opts
515    }
516}
517
518# ----------------------------------------------------------------------
519# USAGE: _reorder <compList>
520#
521# Used internally to change the order of a series of output components
522# found in the <output> section.  Moves the <log> elements to the end
523# and returns the updated list.
524# ----------------------------------------------------------------------
525itcl::body Rappture::Analyzer::_reorder {comps} {
526    set i 0
527    set max [llength $comps]
528    while {$i < $max} {
529        set c [lindex $comps $i]
530        if {[string match log* $c]} {
531            set comps [lreplace $comps $i $i]
532            lappend comps $c
533            incr max -1
534        } else {
535            incr i
536        }
537    }
538    return $comps
539}
540
541# ----------------------------------------------------------------------
542# USAGE: _autoLabel <xmlobj> <path> <title> <cntVar>
543#
544# Used internally to check for an about.label property at the <path>
545# in <xmlobj>.  If this object doesn't have a label, then one is
546# supplied using the given <title>.  The <cntVar> is an array of
547# counters in the calling scopes for titles that have been used
548# in the past.  This is used to create titles like "Plot #2" the
549# second time it is encountered.
550#
551# The <xmlobj> is updated so that the label is inserted directly in
552# the tree.
553# ----------------------------------------------------------------------
554itcl::body Rappture::Analyzer::_autoLabel {xmlobj path title cntVar} {
555    upvar $cntVar counters
556
557    set group [$xmlobj get $path.about.group]
558    set label [$xmlobj get $path.about.label]
559    if {"" == $label} {
560        # no label -- make one up using the title specified
561        if {![info exists counters($group-$title)]} {
562            set counters($group-$title) 1
563            set label $title
564        } else {
565            set label "$title (#[incr counters($group-$title)])"
566        }
567        $xmlobj put $path.about.label $label
568    } else {
569        # handle the case of two identical labels in <output>
570        if {![info exists counters($group-$label)]} {
571            set counters($group-$label) 1
572        } else {
573            set label "$label (#[incr counters($group-$label)])"
574            $xmlobj put $path.about.label $label
575        }
576    }
577    return $label
578}
579
580# ----------------------------------------------------------------------
581# USAGE: _fixResult
582#
583# Used internally to change the result page being displayed whenever
584# the user selects a page from the results combobox.
585# ----------------------------------------------------------------------
586itcl::body Rappture::Analyzer::_fixResult {} {
587    set page [$itk_component(resultselector) value]
588    set page [$itk_component(resultselector) translate $page]
589    if {$page != ""} {
590        $itk_component(resultpages) current $page
591
592        set f [$itk_component(resultpages) page $page]
593        $f.rviewer plot clear
594        eval $f.rviewer plot add $_plotlist
595    }
596}
597
598# ----------------------------------------------------------------------
599# USAGE: _fixSize
600#
601# Used internally to change the size of the result set area whenever
602# a new control appears.  Adjusts the size available for the result
603# set up to some maximum.
604# ----------------------------------------------------------------------
605itcl::body Rappture::Analyzer::_fixSize {} {
606    set f [$itk_component(results) fraction end]
607    if {$f < 0.4} {
608        $itk_component(results) fraction end [expr {$f+0.15}]
609    }
610    _fixSimControl
611}
612
613# ----------------------------------------------------------------------
614# USAGE: _simState <boolean> ?<message>? ?<settings>?
615#
616# Used internally to change the "Simulation" button on or off.
617# If the <boolean> is on, then any <message> and <settings> are
618# displayed as well.  The <message> is a note to the user about
619# what will be simulated, and the <settings> are a list of
620# tool parameter settings of the form {path1 val1 path2 val2 ...}.
621# When these are in place, the next Simulate operation will use
622# these settings.  This helps fill in missing data values.
623# ----------------------------------------------------------------------
624itcl::body Rappture::Analyzer::_simState {state args} {
625    if {$state} {
626        $itk_interior.simol configure \
627            -background $itk_option(-simcontrolactiveoutline)
628        $itk_interior.simol.simbg configure \
629            -background $itk_option(-simcontrolactivebackground)
630        $itk_component(simulate) configure \
631            -highlightbackground $itk_option(-simcontrolactivebackground)
632        $itk_component(simstatus) configure \
633            -background $itk_option(-simcontrolactivebackground)
634
635        $itk_component(abort) configure -state disabled
636        $itk_component(simulate) configure -state normal \
637            -command [itcl::code $this simulate]
638
639        #
640        # If there's a special message, then put it up next to the button.
641        #
642        set mesg [lindex $args 0]
643        if {"" != $mesg} {
644            $itk_component(simstatus) configure -state normal
645            $itk_component(simstatus) delete 1.0 end
646            $itk_component(simstatus) insert end $mesg
647
648            #
649            # If there are any settings, then install them in the
650            # "Simulate" button.  Also, pop them up as a tooltip
651            # for the message.
652            #
653            set settings [lindex $args 1]
654            if {[llength $settings] > 0} {
655                $itk_component(simulate) configure \
656                    -command [eval itcl::code $this simulate $settings]
657
658                set details ""
659                foreach {path val} $settings {
660                    set str [$_tool xml get $path.about.label]
661                    if {"" == $str} {
662                        set str [$_tool xml element -as id $path]
663                    }
664                    append details "$str = $val\n"
665                }
666                set details [string trim $details]
667
668                Rappture::Tooltip::for $itk_component(simstatus) $details
669                $itk_component(simstatus) insert end " "
670                $itk_component(simstatus) insert end "(details...)" popup
671            }
672            $itk_component(simstatus) configure -state disabled
673        }
674    } else {
675        if {"" != $itk_option(-simcontrolbackground)} {
676            set simcbg $itk_option(-simcontrolbackground)
677        } else {
678            set simcbg $itk_option(-background)
679        }
680        $itk_interior.simol configure \
681            -background $itk_option(-simcontroloutline)
682        $itk_interior.simol.simbg configure -background $simcbg
683        $itk_component(simulate) configure -highlightbackground $simcbg
684        $itk_component(simstatus) configure -background $simcbg
685
686        $itk_component(simulate) configure -state disabled
687        $itk_component(abort) configure -state normal
688
689        $itk_component(simstatus) configure -state normal
690        $itk_component(simstatus) delete 1.0 end
691        $itk_component(simstatus) configure -state disabled
692        Rappture::Tooltip::for $itk_component(simstatus) ""
693    }
694}
695
696# ----------------------------------------------------------------------
697# USAGE: _simOutput <message>
698#
699# Invoked automatically whenever output comes in while running the
700# tool.  Extracts any =RAPPTURE-???=> messages from the output and
701# sends the output to the display.  For example, any
702# =RAPPTURE-PROGRESS=> message pops up the progress meter and updates
703# it to show the latest progress message.  This is useful for
704# long-running tools, to let the user know how much longer the
705# simulation will take.
706# ----------------------------------------------------------------------
707itcl::body Rappture::Analyzer::_simOutput {message} {
708    #
709    # Scan through and pick out any =RAPPTURE-PROGRESS=> messages first.
710    #
711    while {[regexp -indices \
712               {=RAPPTURE-PROGRESS=>([0-9]+) +([^\n]*)(\n|$)} $message \
713                match percent mesg]} {
714
715        foreach {i0 i1} $percent break
716        set percent [string range $message $i0 $i1]
717
718        foreach {i0 i1} $mesg break
719        set mesg [string range $message $i0 $i1]
720
721        pack $itk_component(progress) -fill x -padx 10 -pady 10
722        $itk_component(progress) settings -percent $percent -message $mesg
723
724        foreach {i0 i1} $match break
725        set message [string replace $message $i0 $i1]
726    }
727
728    #
729    # Break up the remaining lines according to =RAPPTURE-ERROR=> messages.
730    # Show errors in a special color.
731    #
732    $itk_component(runinfo) configure -state normal
733
734    while {[regexp -indices \
735               {=RAPPTURE-([a-zA-Z]+)=>([^\n]*)(\n|$)} $message \
736                match type mesg]} {
737
738        foreach {i0 i1} $match break
739        set first [string range $message 0 [expr {$i0-1}]]
740        if {[string length $first] > 0} {
741            $itk_component(runinfo) insert end $first
742            $itk_component(runinfo) insert end \n
743        }
744
745        foreach {t0 t1} $type break
746        set type [string range $message $t0 $t1]
747        foreach {m0 m1} $mesg break
748        set mesg [string range $message $m0 $m1]
749        if {[string length $mesg] > 0 && $type != "RUN"} {
750            $itk_component(runinfo) insert end $mesg $type
751            $itk_component(runinfo) insert end \n $type
752        }
753
754        set message [string range $message [expr {$i1+1}] end]
755    }
756
757    if {[string length $message] > 0} {
758        $itk_component(runinfo) insert end $message
759        if {[$itk_component(runinfo) get end-2char] != "\n"} {
760            $itk_component(runinfo) insert end "\n"
761        }
762        $itk_component(runinfo) see end
763    }
764    $itk_component(runinfo) configure -state disabled
765}
766
767# ----------------------------------------------------------------------
768# USAGE: _fixSimControl
769#
770# Used internally to add or remove the simulation control at the
771# top of the analysis area.  This is controlled by the -simcontrol
772# option.
773# ----------------------------------------------------------------------
774itcl::body Rappture::Analyzer::_fixSimControl {} {
775    switch -- $itk_option(-simcontrol) {
776        on {
777            pack $itk_interior.simol -fill x -before $itk_interior.nb
778        }
779        off {
780            pack forget $itk_interior.simol
781        }
782        auto {
783            #
784            # If we have two or more radiodials, then there is a
785            # chance of encountering a combination of parameters
786            # with no data, requiring simulation.
787            #
788            if {[$itk_component(resultset) size -controls] >= 2} {
789                pack $itk_interior.simol -fill x -before $itk_interior.nb
790            } else {
791                pack forget $itk_interior.simol
792            }
793        }
794        default {
795            error "bad value \"$itk_option(-simcontrol)\": should be on, off, auto"
796        }
797    }
798}
799
800# ----------------------------------------------------------------------
801# CONFIGURATION OPTION: -simcontrol
802#
803# Controls whether or not the Simulate button is showing.  In some
804# cases, it is not needed.
805# ----------------------------------------------------------------------
806itcl::configbody Rappture::Analyzer::simcontrol {
807    _fixSimControl
808}
Note: See TracBrowser for help on using the repository browser.