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

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

Fixed the download button so that it doesn't force the
analyzer screen to be too big, and so that it disappears
gracefully when squeezed out.

Fixed the molecule viewer so that it handles the case
where one molecule is empty and another is not, and
they're being compared with the comparison dial. Was
chocking on the empty molecule with no xmin/xmax set.

File size: 31.4 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 10 -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..." -anchor w \
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
205NOTE:  Your web browser must allow pop-ups from this site.  If your output does not appear, look for a 'pop-up blocked' message and enable pop-ups."
206    }
207
208    itk_component add results {
209        Rappture::Panes $w.pane
210    }
211    pack $itk_component(results) -expand yes -fill both
212    set f [$itk_component(results) pane 0]
213
214    itk_component add resultpages {
215        Rappture::Notebook $f.nb
216    }
217    pack $itk_component(resultpages) -expand yes -fill both
218
219    set f [$itk_component(results) insert end -fraction 0.1]
220    itk_component add resultset {
221        Rappture::ResultSet $f.rset \
222            -clearcommand [itcl::code $this clear] \
223            -settingscommand [itcl::code $this _plot] \
224            -promptcommand [itcl::code $this _simState]
225    }
226    pack $itk_component(resultset) -expand yes -fill both
227    bind $itk_component(resultset) <<Control>> [itcl::code $this _fixSize]
228
229    eval itk_initialize $args
230
231    $itk_component(runinfo) tag configure ERROR -foreground red
232    $itk_component(runinfo) tag configure text -font $itk_option(-textfont)
233
234    #
235    # Load up tool info on the first page.
236    #
237    $itk_component(toolinfo) tag configure title \
238        -font $itk_option(-boldtextfont)
239
240    set mesg [$tool xml get tool.title]
241    if {"" != $mesg} {
242        $itk_component(toolinfo) insert end $mesg title
243        $itk_component(toolinfo) insert end "\n\n"
244    }
245
246    set mesg [$tool xml get tool.about]
247    if {"" != $mesg} {
248        $itk_component(toolinfo) insert end $mesg
249    }
250    $itk_component(toolinfo) configure -state disabled
251    $itk_component(notebook) current about
252
253    # tool can run on "manual" (default) or "auto"
254    set cntl [$tool xml get tool.control]
255    if {"" == $cntl} {
256        set cntl [$tool xml get tool.control.type]
257    }
258    if {"" != $cntl} {
259        set _control $cntl
260    }
261
262    # reset everything to a clean state
263    reset
264}
265
266# ----------------------------------------------------------------------
267# DESTRUCTOR
268# ----------------------------------------------------------------------
269itcl::body Rappture::Analyzer::destructor {} {
270    foreach obj $_runs {
271        itcl::delete object $obj
272    }
273    after cancel [itcl::code $this simulate]
274}
275
276# ----------------------------------------------------------------------
277# USAGE: simulate ?-ifneeded?
278# USAGE: simulate ?<path1> <value1> <path2> <value2> ...?
279#
280# Kicks off the simulator by executing the tool.command associated
281# with the tool.  If any arguments are specified, they are used to
282# set parameters for the simulation.  While the simulation is running,
283# it shows status.  When the simulation is finished, it switches
284# automatically to "analyze" mode and shows the results.
285# ----------------------------------------------------------------------
286itcl::body Rappture::Analyzer::simulate {args} {
287    if {$args == "-ifneeded"} {
288        # check to see if simulation is really needed
289        $_tool sync
290        if {[$itk_component(resultset) contains [$_tool xml object]]} {
291            # not needed -- show results and return
292            $itk_component(notebook) current analyze
293            return
294        }
295        set args ""
296    }
297
298    # simulation is needed -- go to simulation page
299    $itk_component(notebook) current simulate
300
301    # no progress messages yet
302    pack forget $itk_component(progress)
303    lappend args -output [itcl::code $this _simOutput]
304
305    _simState off
306    $itk_component(runinfo) configure -state normal
307    $itk_component(runinfo) delete 1.0 end
308    $itk_component(runinfo) insert end "Running simulation...\n\n" text
309    $itk_component(runinfo) configure -state disabled
310
311    # if the hold window is set, then put up a busy cursor
312    if {$itk_option(-holdwindow) != ""} {
313        blt::busy hold $itk_option(-holdwindow)
314        raise $itk_component(hull)
315        update
316    }
317
318    # execute the job
319    foreach {status result} [eval $_tool run $args] break
320
321    # if job was aborted, then allow simulation again
322    if {$result == "ABORT"} {
323        _simState on "Aborted"
324    }
325
326    # read back the results from run.xml
327    if {$status == 0 && $result != "ABORT"} {
328        if {[regexp {=RAPPTURE-RUN=>([^\n]+)} $result match file]} {
329            set status [catch {load $file} msg]
330            if {$status != 0} {
331                global errorInfo
332                set result "$msg\n$errorInfo"
333            }
334        } else {
335            set status 1
336            set result "Can't find result file in output:\n\n$result"
337        }
338    }
339
340    # back to normal
341    if {$itk_option(-holdwindow) != ""} {
342        blt::busy release $itk_option(-holdwindow)
343    }
344    $itk_component(abort) configure -state disabled
345
346    if {$status != 0} {
347        $itk_component(runinfo) configure -state normal
348        $itk_component(runinfo) delete 1.0 end
349        $itk_component(runinfo) insert end "Problem launching job:\n\n" text
350        _simOutput $result
351        $itk_component(runinfo) configure -state disabled
352        $itk_component(runinfo) see 1.0
353    } else {
354        $itk_component(notebook) current analyze
355    }
356
357    # do this last -- after _simOutput above
358    pack forget $itk_component(progress)
359}
360
361# ----------------------------------------------------------------------
362# USAGE: reset
363#
364# Used to reset the analyzer whenever the input to a simulation has
365# changed.  Sets the mode back to "simulate", so the user has to
366# simulate again to see the output.  If the <start> option is set
367# to "auto", the simulation is invoked immediately.
368# ----------------------------------------------------------------------
369itcl::body Rappture::Analyzer::reset {} {
370    # check to see if simulation is really needed
371    $_tool sync
372    if {![$itk_component(resultset) contains [$_tool xml object]]} {
373        # if control mode is "auto", then simulate right away
374        if {[string match auto* $_control]} {
375            # auto control -- don't need button
376            pack forget $itk_interior.simol
377
378            after cancel [itcl::code $this simulate]
379            after idle [itcl::code $this simulate]
380        } else {
381            _simState on "new input parameters"
382        }
383    } else {
384        _simState off
385    }
386}
387
388# ----------------------------------------------------------------------
389# USAGE: load <file>
390#
391# Loads the data from the given <file> into the appropriate results
392# sets.  If necessary, new results sets are created to store the data.
393# ----------------------------------------------------------------------
394itcl::body Rappture::Analyzer::load {file} {
395    # only show the last result? then clear first
396    if {[$_tool xml get tool.analyzer] == "last"} {
397        clear
398    }
399
400    # try to load new results from the given file
401    set xmlobj [Rappture::library $file]
402    lappend _runs $xmlobj
403
404    # go through the analysis and find all result sets
405    set haveresults 0
406    foreach item [_reorder [$xmlobj children output]] {
407        switch -glob -- $item {
408            log* {
409                _autoLabel $xmlobj output.$item "Output Log" counters
410            }
411            string* {
412                _autoLabel $xmlobj output.$item "String" counters
413            }
414            curve* - field* {
415                _autoLabel $xmlobj output.$item "Plot" counters
416            }
417            structure* {
418                _autoLabel $xmlobj output.$item "Structure" counters
419            }
420            table* {
421                _autoLabel $xmlobj output.$item "Energy Levels" counters
422            }
423        }
424        set label [$xmlobj get output.$item.about.group]
425        if {"" == $label} {
426            set label [$xmlobj get output.$item.about.label]
427        }
428
429        set hidden [$xmlobj get output.$item.hide]
430        set hidden [expr {"" != $hidden && $hidden}]
431
432        if {"" != $label && !$hidden} {
433            set haveresults 1
434        }
435    }
436
437    # if there are any valid results, add them to the resultset
438    if {$haveresults} {
439        set size [$itk_component(resultset) size]
440        set index [$itk_component(resultset) add $xmlobj]
441
442        # add each result to a result viewer
443        foreach item [_reorder [$xmlobj children output]] {
444            set label [$xmlobj get output.$item.about.group]
445            if {"" == $label} {
446                set label [$xmlobj get output.$item.about.label]
447            }
448
449            set hidden [$xmlobj get output.$item.hide]
450            set hidden [expr {"" != $hidden && $hidden}]
451
452            if {"" != $label && !$hidden} {
453                if {![info exists _label2page($label)]} {
454                    set name "page[incr _pages]"
455                    set page [$itk_component(resultpages) insert end $name]
456                    set _label2page($label) $page
457                    Rappture::ResultViewer $page.rviewer
458                    pack $page.rviewer -expand yes -fill both -pady 4
459
460                    $itk_component(resultselector) choices insert end \
461                        $name $label
462                }
463
464                # add/replace the latest result into this viewer
465                set page $_label2page($label)
466
467                if {![info exists reset($page)]} {
468                    $page.rviewer clear $index
469                    set reset($page) 1
470                }
471                $page.rviewer add $index $xmlobj output.$item
472            }
473        }
474    }
475
476    # show the first page by default
477    set first [$itk_component(resultselector) choices get -label 0]
478    if {$first != ""} {
479        set page [$itk_component(resultselector) choices get -value 0]
480        $itk_component(resultpages) current $page
481        $itk_component(resultselector) value $first
482    }
483}
484
485# ----------------------------------------------------------------------
486# USAGE: clear
487#
488# Discards all results previously loaded into the analyzer.
489# ----------------------------------------------------------------------
490itcl::body Rappture::Analyzer::clear {} {
491    foreach obj $_runs {
492        itcl::delete object $obj
493    }
494    set _runs ""
495
496    $itk_component(resultset) clear
497    $itk_component(results) fraction end 0.1
498
499    foreach label [array names _label2page] {
500        set page $_label2page($label)
501        $page.rviewer clear
502    }
503    $itk_component(resultselector) value ""
504    $itk_component(resultselector) choices delete 0 end
505    catch {unset _label2page}
506    set _plotlist ""
507
508    #
509    # HACK ALERT!!
510    # The following statement should be in place, but it causes
511    # vtk to dump core.  Leave it out until we can fix the core dump.
512    # In the mean time, we leak memory...
513    #
514    #$itk_component(resultpages) delete -all
515    #set _pages 0
516
517    _simState on
518    _fixSimControl
519    reset
520}
521
522# ----------------------------------------------------------------------
523# USAGE: download
524#
525# Spools the current result so the user can download it.
526# ----------------------------------------------------------------------
527itcl::body Rappture::Analyzer::download {} {
528    if {[Rappture::filexfer::enabled]} {
529        set title [$itk_component(resultselector) value]
530        set page [$itk_component(resultselector) translate $title]
531        if {$page != ""} {
532            set ext ""
533            set f [$itk_component(resultpages) page $page]
534            foreach {ext data} [$f.rviewer download] break
535            if {"" == $ext} {
536                Rappture::Tooltip::cue $itk_component(download) \
537                    "Can't download this result."
538                return
539            }
540            regsub -all {[\ -\/\:-\@\{-\~]} $title {} title
541            set file "$title$ext"
542        } else {
543            # this shouldn't happen
544            set file error.html
545            set data "<h1>Not Found</h1>There is no result selected."
546        }
547
548        if {[catch {Rappture::filexfer::spool $data $file} result]} {
549            if {"no clients" == $result} {
550                Rappture::Tooltip::cue $itk_component(download) \
551                    "Can't download this result.  Looks like you might be having trouble with the version of Java installed for your browser."
552            } else {
553                error $result "    (while spooling result \"$title\")"
554            }
555        }
556    }
557}
558
559# ----------------------------------------------------------------------
560# USAGE: _plot ?<index> <options> <index> <options>...?
561#
562# Used internally to update the plot shown in the current result
563# viewer whenever the resultset settings have changed.  Causes the
564# desired results to show up on screen.
565# ----------------------------------------------------------------------
566itcl::body Rappture::Analyzer::_plot {args} {
567    set _plotlist $args
568
569    set page [$itk_component(resultselector) value]
570    set page [$itk_component(resultselector) translate $page]
571    if {"" != $page} {
572        set f [$itk_component(resultpages) page $page]
573        $f.rviewer plot clear
574        foreach {index opts} $_plotlist {
575            $f.rviewer plot add $index $opts
576        }
577    }
578}
579
580# ----------------------------------------------------------------------
581# USAGE: _reorder <compList>
582#
583# Used internally to change the order of a series of output components
584# found in the <output> section.  Moves the <log> elements to the end
585# and returns the updated list.
586# ----------------------------------------------------------------------
587itcl::body Rappture::Analyzer::_reorder {comps} {
588    set i 0
589    set max [llength $comps]
590    while {$i < $max} {
591        set c [lindex $comps $i]
592        if {[string match log* $c]} {
593            set comps [lreplace $comps $i $i]
594            lappend comps $c
595            incr max -1
596        } else {
597            incr i
598        }
599    }
600    return $comps
601}
602
603# ----------------------------------------------------------------------
604# USAGE: _autoLabel <xmlobj> <path> <title> <cntVar>
605#
606# Used internally to check for an about.label property at the <path>
607# in <xmlobj>.  If this object doesn't have a label, then one is
608# supplied using the given <title>.  The <cntVar> is an array of
609# counters in the calling scopes for titles that have been used
610# in the past.  This is used to create titles like "Plot #2" the
611# second time it is encountered.
612#
613# The <xmlobj> is updated so that the label is inserted directly in
614# the tree.
615# ----------------------------------------------------------------------
616itcl::body Rappture::Analyzer::_autoLabel {xmlobj path title cntVar} {
617    upvar $cntVar counters
618
619    set group [$xmlobj get $path.about.group]
620    set label [$xmlobj get $path.about.label]
621    if {"" == $label} {
622        # no label -- make one up using the title specified
623        if {![info exists counters($group-$title)]} {
624            set counters($group-$title) 1
625            set label $title
626        } else {
627            set label "$title (#[incr counters($group-$title)])"
628        }
629        $xmlobj put $path.about.label $label
630    } else {
631        # handle the case of two identical labels in <output>
632        if {![info exists counters($group-$label)]} {
633            set counters($group-$label) 1
634        } else {
635            set label "$label (#[incr counters($group-$label)])"
636            $xmlobj put $path.about.label $label
637        }
638    }
639    return $label
640}
641
642# ----------------------------------------------------------------------
643# USAGE: _fixResult
644#
645# Used internally to change the result page being displayed whenever
646# the user selects a page from the results combobox.
647# ----------------------------------------------------------------------
648itcl::body Rappture::Analyzer::_fixResult {} {
649    set page [$itk_component(resultselector) value]
650    set page [$itk_component(resultselector) translate $page]
651    if {$page != ""} {
652        blt::busy hold [winfo toplevel $itk_component(hull)]; update idletasks
653        $itk_component(resultpages) current $page
654
655        set f [$itk_component(resultpages) page $page]
656        $f.rviewer plot clear
657        eval $f.rviewer plot add $_plotlist
658        blt::busy release [winfo toplevel $itk_component(hull)]
659    }
660}
661
662# ----------------------------------------------------------------------
663# USAGE: _fixSize
664#
665# Used internally to change the size of the result set area whenever
666# a new control appears.  Adjusts the size available for the result
667# set up to some maximum.
668# ----------------------------------------------------------------------
669itcl::body Rappture::Analyzer::_fixSize {} {
670    set f [$itk_component(results) fraction end]
671    if {$f < 0.4} {
672        $itk_component(results) fraction end [expr {$f+0.15}]
673    }
674    _fixSimControl
675}
676
677# ----------------------------------------------------------------------
678# USAGE: _simState <boolean> ?<message>? ?<settings>?
679#
680# Used internally to change the "Simulation" button on or off.
681# If the <boolean> is on, then any <message> and <settings> are
682# displayed as well.  The <message> is a note to the user about
683# what will be simulated, and the <settings> are a list of
684# tool parameter settings of the form {path1 val1 path2 val2 ...}.
685# When these are in place, the next Simulate operation will use
686# these settings.  This helps fill in missing data values.
687# ----------------------------------------------------------------------
688itcl::body Rappture::Analyzer::_simState {state args} {
689    if {$state} {
690        $itk_interior.simol configure \
691            -background $itk_option(-simcontrolactiveoutline)
692        $itk_interior.simol.simbg configure \
693            -background $itk_option(-simcontrolactivebackground)
694        $itk_component(simulate) configure \
695            -highlightbackground $itk_option(-simcontrolactivebackground)
696        $itk_component(simstatus) configure \
697            -background $itk_option(-simcontrolactivebackground)
698
699        $itk_component(abort) configure -state disabled
700        $itk_component(simulate) configure -state normal \
701            -command [itcl::code $this simulate]
702
703        #
704        # If there's a special message, then put it up next to the button.
705        #
706        set mesg [lindex $args 0]
707        if {"" != $mesg} {
708            $itk_component(simstatus) configure -state normal
709            $itk_component(simstatus) delete 1.0 end
710            $itk_component(simstatus) insert end $mesg
711
712            #
713            # If there are any settings, then install them in the
714            # "Simulate" button.  Also, pop them up as a tooltip
715            # for the message.
716            #
717            set settings [lindex $args 1]
718            if {[llength $settings] > 0} {
719                $itk_component(simulate) configure \
720                    -command [eval itcl::code $this simulate $settings]
721
722                set details ""
723                foreach {path val} $settings {
724                    set str [$_tool xml get $path.about.label]
725                    if {"" == $str} {
726                        set str [$_tool xml element -as id $path]
727                    }
728                    append details "$str = $val\n"
729                }
730                set details [string trim $details]
731
732                Rappture::Tooltip::for $itk_component(simstatus) $details
733                $itk_component(simstatus) insert end " "
734                $itk_component(simstatus) insert end "(details...)" popup
735            }
736            $itk_component(simstatus) configure -state disabled
737        }
738    } else {
739        if {"" != $itk_option(-simcontrolbackground)} {
740            set simcbg $itk_option(-simcontrolbackground)
741        } else {
742            set simcbg $itk_option(-background)
743        }
744        $itk_interior.simol configure \
745            -background $itk_option(-simcontroloutline)
746        $itk_interior.simol.simbg configure -background $simcbg
747        $itk_component(simulate) configure -highlightbackground $simcbg
748        $itk_component(simstatus) configure -background $simcbg
749
750        $itk_component(simulate) configure -state disabled
751        $itk_component(abort) configure -state normal
752
753        $itk_component(simstatus) configure -state normal
754        $itk_component(simstatus) delete 1.0 end
755        $itk_component(simstatus) configure -state disabled
756        Rappture::Tooltip::for $itk_component(simstatus) ""
757    }
758}
759
760# ----------------------------------------------------------------------
761# USAGE: _simOutput <message>
762#
763# Invoked automatically whenever output comes in while running the
764# tool.  Extracts any =RAPPTURE-???=> messages from the output and
765# sends the output to the display.  For example, any
766# =RAPPTURE-PROGRESS=> message pops up the progress meter and updates
767# it to show the latest progress message.  This is useful for
768# long-running tools, to let the user know how much longer the
769# simulation will take.
770# ----------------------------------------------------------------------
771itcl::body Rappture::Analyzer::_simOutput {message} {
772    #
773    # Scan through and pick out any =RAPPTURE-PROGRESS=> messages first.
774    #
775    while {[regexp -indices \
776               {=RAPPTURE-PROGRESS=>([0-9]+) +([^\n]*)(\n|$)} $message \
777                match percent mesg]} {
778
779        foreach {i0 i1} $percent break
780        set percent [string range $message $i0 $i1]
781
782        foreach {i0 i1} $mesg break
783        set mesg [string range $message $i0 $i1]
784
785        pack $itk_component(progress) -fill x -padx 10 -pady 10
786        $itk_component(progress) settings -percent $percent -message $mesg
787
788        foreach {i0 i1} $match break
789        set message [string replace $message $i0 $i1]
790    }
791
792    #
793    # Break up the remaining lines according to =RAPPTURE-ERROR=> messages.
794    # Show errors in a special color.
795    #
796    $itk_component(runinfo) configure -state normal
797
798    while {[regexp -indices \
799               {=RAPPTURE-([a-zA-Z]+)=>([^\n]*)(\n|$)} $message \
800                match type mesg]} {
801
802        foreach {i0 i1} $match break
803        set first [string range $message 0 [expr {$i0-1}]]
804        if {[string length $first] > 0} {
805            $itk_component(runinfo) insert end $first
806            $itk_component(runinfo) insert end \n
807        }
808
809        foreach {t0 t1} $type break
810        set type [string range $message $t0 $t1]
811        foreach {m0 m1} $mesg break
812        set mesg [string range $message $m0 $m1]
813        if {[string length $mesg] > 0 && $type != "RUN"} {
814            $itk_component(runinfo) insert end $mesg $type
815            $itk_component(runinfo) insert end \n $type
816        }
817
818        set message [string range $message [expr {$i1+1}] end]
819    }
820
821    if {[string length $message] > 0} {
822        $itk_component(runinfo) insert end $message
823        if {[$itk_component(runinfo) get end-2char] != "\n"} {
824            $itk_component(runinfo) insert end "\n"
825        }
826        $itk_component(runinfo) see end
827    }
828    $itk_component(runinfo) configure -state disabled
829}
830
831# ----------------------------------------------------------------------
832# USAGE: _fixSimControl
833#
834# Used internally to add or remove the simulation control at the
835# top of the analysis area.  This is controlled by the -simcontrol
836# option.
837# ----------------------------------------------------------------------
838itcl::body Rappture::Analyzer::_fixSimControl {} {
839    switch -- $itk_option(-simcontrol) {
840        on {
841            pack $itk_interior.simol -fill x -before $itk_interior.nb
842        }
843        off {
844            pack forget $itk_interior.simol
845        }
846        auto {
847            #
848            # If we have two or more radiodials, then there is a
849            # chance of encountering a combination of parameters
850            # with no data, requiring simulation.
851            #
852            if {[$itk_component(resultset) size -controls] >= 2} {
853                pack $itk_interior.simol -fill x -before $itk_interior.nb
854            } else {
855                pack forget $itk_interior.simol
856            }
857        }
858        default {
859            error "bad value \"$itk_option(-simcontrol)\": should be on, off, auto"
860        }
861    }
862}
863
864# ----------------------------------------------------------------------
865# CONFIGURATION OPTION: -simcontrol
866#
867# Controls whether or not the Simulate button is showing.  In some
868# cases, it is not needed.
869# ----------------------------------------------------------------------
870itcl::configbody Rappture::Analyzer::simcontrol {
871    _fixSimControl
872}
Note: See TracBrowser for help on using the repository browser.