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

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