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

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

disabling the simstatus label after we adjust the text

File size: 39.0 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: analyzer - output area for Rappture
3#
4#  This widget acts as the output side of a Rappture application.
5#  When the input has changed, it displays a Simulate button that
6#  launches the simulation.  When a simulation is running, this
7#  area shows status.  When it is finished, the results appear
8#  in place of the button, according to the specs in the <analyze>
9#  XML data.
10# ======================================================================
11#  AUTHOR:  Michael McLennan, Purdue University
12#  Copyright (c) 2004-2005  Purdue Research Foundation
13#
14#  See the file "license.terms" for information on usage and
15#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16# ======================================================================
17package require Itk
18
19option add *Analyzer.width 3.5i widgetDefault
20option add *Analyzer.height 4i widgetDefault
21option add *Analyzer.simControl "auto" widgetDefault
22option add *Analyzer.simControlBackground "" widgetDefault
23option add *Analyzer.simControlOutline gray widgetDefault
24option add *Analyzer.simControlActiveBackground #ffffcc widgetDefault
25option add *Analyzer.simControlActiveOutline black widgetDefault
26option add *Analyzer.notebookpage "about" widgetDefault
27
28option add *Analyzer.font \
29    -*-helvetica-medium-r-normal-*-12-* widgetDefault
30option add *Analyzer.codeFont \
31    -*-courier-medium-r-normal-*-12-* widgetDefault
32option add *Analyzer.textFont \
33    -*-helvetica-medium-r-normal-*-12-* widgetDefault
34option add *Analyzer.boldTextFont \
35    -*-helvetica-bold-r-normal-*-12-* widgetDefault
36
37itcl::class Rappture::Analyzer {
38    inherit itk::Widget
39
40    itk_option define -codefont codeFont Font ""
41    itk_option define -textfont textFont Font ""
42    itk_option define -boldtextfont boldTextFont Font ""
43    itk_option define -simcontrol simControl SimControl ""
44    itk_option define -simcontroloutline simControlOutline Background ""
45    itk_option define -simcontrolbackground simControlBackground Background ""
46    itk_option define -simcontrolactiveoutline simControlActiveOutline Background ""
47    itk_option define -simcontrolactivebackground simControlActiveBackground Background ""
48    itk_option define -holdwindow holdWindow HoldWindow ""
49    itk_option define -notebookpage notebookPage NotebookPage ""
50
51    constructor {tool args} { # defined below }
52    destructor { # defined below }
53
54    public method simulate {args}
55    public method reset {{when -eventually}}
56    public method load {xmlobj}
57    public method clear {}
58    public method download {option args}
59
60    protected method _plot {args}
61    protected method _reorder {comps}
62    protected method _autoLabel {xmlobj path title cntVar}
63    protected method _fixResult {}
64    protected method _fixSize {}
65    protected method _fixSimControl {}
66    protected method _fixNotebook {}
67    protected method _simState {state args}
68    protected method _simOutput {message}
69    protected method _resultTooltip {}
70
71    private variable _tool ""          ;# belongs to this tool
72    private variable _control "manual" ;# start mode
73    private variable _runs ""          ;# list of XML objects with results
74    private variable _pages 0          ;# number of pages for result sets
75    private variable _label2page       ;# maps output label => result set
76    private variable _label2desc       ;# maps output label => description
77    private variable _lastlabel ""     ;# label of last example loaded
78    private variable _plotlist ""      ;# items currently being plotted
79
80    private common job                 ;# array var used for blt::bgexec jobs
81}
82
83itk::usual Analyzer {
84    keep -background -cursor foreground -font
85}
86
87# ----------------------------------------------------------------------
88# CONSTRUCTOR
89# ----------------------------------------------------------------------
90itcl::body Rappture::Analyzer::constructor {tool args} {
91    set _tool $tool
92
93    itk_option add hull.width hull.height
94    pack propagate $itk_component(hull) no
95
96    frame $itk_interior.simol -borderwidth 1 -relief flat
97    pack $itk_interior.simol -fill x
98
99    frame $itk_interior.simol.simbg -borderwidth 0
100    pack $itk_interior.simol.simbg -expand yes -fill both
101
102    set simtxt [$tool xml get tool.action.label]
103    if {"" == $simtxt} {
104        set simtxt "Simulate"
105    }
106    itk_component add simulate {
107        button $itk_interior.simol.simbg.simulate -text $simtxt \
108            -command [itcl::code $this simulate]
109    }
110    pack $itk_component(simulate) -side left -padx 4 -pady 4
111
112    itk_component add simstatus {
113        text $itk_interior.simol.simbg.simstatus -borderwidth 0 \
114            -highlightthickness 0 -height 1 -width 1 -wrap none \
115            -state disabled
116    } {
117        usual
118        ignore -highlightthickness
119        rename -font -textfont textFont Font
120    }
121    pack $itk_component(simstatus) -side left -expand yes -fill x
122
123    $itk_component(simstatus) tag configure popup \
124        -underline 1 -foreground blue
125
126    $itk_component(simstatus) tag bind popup \
127        <Enter> {%W configure -cursor center_ptr}
128    $itk_component(simstatus) tag bind popup \
129        <Leave> {%W configure -cursor ""}
130    $itk_component(simstatus) tag bind popup \
131        <ButtonPress> {after idle {Rappture::Tooltip::tooltip show %W}}
132
133
134    itk_component add notebook {
135        Rappture::Notebook $itk_interior.nb
136    }
137    pack $itk_interior.nb -expand yes -fill both
138
139    # ------------------------------------------------------------------
140    # ABOUT PAGE
141    # ------------------------------------------------------------------
142    set w [$itk_component(notebook) insert end about]
143
144    Rappture::Scroller $w.info -xscrollmode off -yscrollmode auto
145    pack $w.info -expand yes -fill both -padx 4 -pady 20
146    itk_component add toolinfo {
147        text $w.info.text -width 1 -height 1 -wrap word \
148            -borderwidth 0 -highlightthickness 0
149    } {
150        usual
151        ignore -borderwidth -relief
152        rename -font -textfont textFont Font
153    }
154    $w.info contents $w.info.text
155
156    # ------------------------------------------------------------------
157    # SIMULATION PAGE
158    # ------------------------------------------------------------------
159    set w [$itk_component(notebook) insert end simulate]
160    frame $w.cntls
161    pack $w.cntls -side bottom -fill x -pady 12
162    frame $w.cntls.sep -background black -height 1
163    pack $w.cntls.sep -side top -fill x
164
165    itk_component add abort {
166        button $w.cntls.abort -text "Abort" \
167            -command [itcl::code $_tool abort]
168    }
169    pack $itk_component(abort) -side left -expand yes -padx 4 -pady 4
170
171    Rappture::Scroller $w.info -xscrollmode auto -yscrollmode auto
172    pack $w.info -expand yes -fill both -padx 4 -pady 4
173    itk_component add runinfo {
174        text $w.info.text -width 1 -height 1 -wrap none \
175            -borderwidth 0 -highlightthickness 0 \
176            -state disabled
177    } {
178        usual
179        ignore -borderwidth -relief
180        rename -font -codefont codeFont Font
181    }
182    $w.info contents $w.info.text
183
184    itk_component add progress {
185        Rappture::Progress $w.progress
186    }
187
188    # ------------------------------------------------------------------
189    # ANALYZE PAGE
190    # ------------------------------------------------------------------
191    set w [$itk_component(notebook) insert end analyze]
192
193    frame $w.top
194    pack $w.top -side top -fill x -pady 8
195    label $w.top.l -text "Result:" -font $itk_option(-font)
196    pack $w.top.l -side left
197
198    itk_component add resultselector {
199        Rappture::Combobox $w.top.sel -width 10 -editable no
200    } {
201        usual
202        rename -font -textfont textFont Font
203    }
204    pack $itk_component(resultselector) -side left -expand yes -fill x
205    bind $itk_component(resultselector) <<Value>> [itcl::code $this _fixResult]
206    bind $itk_component(resultselector) <Enter> \
207        [itcl::code $this download coming]
208
209    Rappture::Tooltip::for $itk_component(resultselector) \
210        "@[itcl::code $this _resultTooltip]"
211
212    $itk_component(resultselector) choices insert end \
213        --- "---"
214
215    itk_component add download {
216        button $w.top.dl -image [Rappture::icon download] -anchor e \
217            -borderwidth 1 -relief flat -overrelief raised \
218            -command [itcl::code $this download start $w.top.dl]
219    }
220    pack $itk_component(download) -side right -padx {4 0}
221    bind $itk_component(download) <Enter> \
222        [itcl::code $this download coming]
223
224    $itk_component(resultselector) choices insert end \
225        @download [Rappture::filexfer::label download]
226
227    if {[Rappture::filexfer::enabled]} {
228        Rappture::Tooltip::for $itk_component(download) "Downloads the current result to a new web browser window on your desktop.  From there, you can easily print or save results.
229
230NOTE:  Your web browser must allow pop-ups from this site.  If your output does not appear, look for a 'pop-up blocked' message and enable pop-ups."
231    } else {
232        Rappture::Tooltip::for $itk_component(download) "Saves the current result to a file on your desktop."
233    }
234
235    itk_component add results {
236        Rappture::Panes $w.pane -sashwidth 1 -sashrelief solid -sashpadding {4 0}
237    }
238    pack $itk_component(results) -expand yes -fill both
239    set f [$itk_component(results) pane 0]
240
241    itk_component add resultpages {
242        Rappture::Notebook $f.nb
243    }
244    pack $itk_component(resultpages) -expand yes -fill both
245
246    set f [$itk_component(results) insert end -fraction 0.1]
247    itk_component add resultset {
248        Rappture::ResultSet $f.rset \
249            -clearcommand [itcl::code $this clear] \
250            -settingscommand [itcl::code $this _plot] \
251            -promptcommand [itcl::code $this _simState]
252    }
253    pack $itk_component(resultset) -expand yes -fill both
254    bind $itk_component(resultset) <<Control>> [itcl::code $this _fixSize]
255    bind $itk_component(results) <Configure> [itcl::code $this _fixSize]
256
257    eval itk_initialize $args
258
259    $itk_component(runinfo) tag configure ERROR -foreground red
260    $itk_component(runinfo) tag configure text -font $itk_option(-textfont)
261
262    #
263    # Load up tool info on the first page.
264    #
265    $itk_component(toolinfo) tag configure title \
266        -font $itk_option(-boldtextfont)
267
268    set mesg [$tool xml get tool.title]
269    if {"" != $mesg} {
270        $itk_component(toolinfo) insert end $mesg title
271        $itk_component(toolinfo) insert end "\n\n"
272    }
273
274    set mesg [$tool xml get tool.about]
275    if {"" != $mesg} {
276        $itk_component(toolinfo) insert end $mesg
277    }
278    $itk_component(toolinfo) configure -state disabled
279    $itk_component(notebook) current about
280
281    # tool can run on "manual" (default) or "auto"
282    set cntl [$tool xml get tool.control]
283    if {"" == $cntl} {
284        set cntl [$tool xml get tool.control.type]
285    }
286    if {"" != $cntl} {
287        set _control $cntl
288    }
289
290    # reset everything to a clean state
291    reset
292}
293
294# ----------------------------------------------------------------------
295# DESTRUCTOR
296# ----------------------------------------------------------------------
297itcl::body Rappture::Analyzer::destructor {} {
298    foreach obj $_runs {
299        itcl::delete object $obj
300    }
301    after cancel [itcl::code $this simulate]
302}
303
304# ----------------------------------------------------------------------
305# USAGE: simulate ?-ifneeded?
306# USAGE: simulate ?<path1> <value1> <path2> <value2> ...?
307#
308# Kicks off the simulator by executing the tool.command associated
309# with the tool.  If any arguments are specified, they are used to
310# set parameters for the simulation.  While the simulation is running,
311# it shows status.  When the simulation is finished, it switches
312# automatically to "analyze" mode and shows the results.
313# ----------------------------------------------------------------------
314itcl::body Rappture::Analyzer::simulate {args} {
315    if {$args == "-ifneeded"} {
316        # check to see if simulation is really needed
317        $_tool sync
318        if {[$itk_component(resultset) contains [$_tool xml object]]
319              && ![string equal $_control "manual-resim"]} {
320            # not needed -- show results and return
321            $itk_component(notebook) current analyze
322            return
323        }
324        set args ""
325    }
326
327    # simulation is needed -- go to simulation page
328    $itk_component(notebook) current simulate
329
330    # no progress messages yet
331    pack forget $itk_component(progress)
332    lappend args -output [itcl::code $this _simOutput]
333
334    _simState off
335    $itk_component(runinfo) configure -state normal
336    $itk_component(runinfo) delete 1.0 end
337    $itk_component(runinfo) insert end "Running simulation...\n\n" text
338    $itk_component(runinfo) configure -state disabled
339
340    # if the hold window is set, then put up a busy cursor
341    if {$itk_option(-holdwindow) != ""} {
342        blt::busy hold $itk_option(-holdwindow)
343        raise $itk_component(hull)
344        update
345    }
346
347    # execute the job
348    foreach {status result} [eval $_tool run $args] break
349
350    # if job was aborted, then allow simulation again
351    if {$result == "ABORT"} {
352        _simState on "Aborted"
353    }
354
355    # load results from run.xml into analyzer
356    if {$status == 0 && $result != "ABORT"} {
357        set status [catch {load $result} result]
358    }
359
360    # back to normal
361    if {$itk_option(-holdwindow) != ""} {
362        blt::busy release $itk_option(-holdwindow)
363    }
364    $itk_component(abort) configure -state disabled
365
366    if {$status != 0} {
367        $itk_component(runinfo) configure -state normal
368        $itk_component(runinfo) delete 1.0 end
369        $itk_component(runinfo) insert end "Problem launching job:\n\n" text
370        _simOutput $result
371        $itk_component(runinfo) configure -state disabled
372        $itk_component(runinfo) see 1.0
373
374        # Try to create a support ticket for this error.
375        # It may be a real problem.
376        if {[Rappture::bugreport::shouldReport for jobs]} {
377            Rappture::bugreport::register "Problem launching job:\n\n$result\n== RAPPTURE INPUT ==\n[$_tool xml xml]"
378        }
379    } else {
380        $itk_component(notebook) current analyze
381    }
382
383    # do this last -- after _simOutput above
384    pack forget $itk_component(progress)
385}
386
387# ----------------------------------------------------------------------
388# USAGE: reset ?-eventually|-now?
389#
390# Used to reset the analyzer whenever the input to a simulation has
391# changed.  Sets the mode back to "simulate", so the user has to
392# simulate again to see the output.  If the <start> option is set
393# to "auto", the simulation is invoked immediately.
394# ----------------------------------------------------------------------
395itcl::body Rappture::Analyzer::reset {{when -eventually}} {
396    if {$when == "-eventually"} {
397        after cancel [list catch [itcl::code $this reset -now]]
398        after idle [list catch [itcl::code $this reset -now]]
399        return
400    }
401
402    # check to see if simulation is really needed
403    $_tool sync
404    if {![$itk_component(resultset) contains [$_tool xml object]]
405          || [string equal $_control "manual-resim"]} {
406        # if control mode is "auto", then simulate right away
407        if {[string match auto* $_control]} {
408            # auto control -- don't need button
409            pack forget $itk_interior.simol
410
411            after cancel [itcl::code $this simulate]
412            after idle [itcl::code $this simulate]
413        } else {
414            _simState on "new input parameters"
415        }
416    } else {
417        _simState off
418    }
419}
420
421# ----------------------------------------------------------------------
422# USAGE: load <xmlobj>
423#
424# Loads the data from the given <xmlobj> into the appropriate results
425# sets.  If necessary, new results sets are created to store the data.
426# ----------------------------------------------------------------------
427itcl::body Rappture::Analyzer::load {xmlobj} {
428    # only show the last result? then clear first
429    if {[$_tool xml get tool.analyzer] == "last"} {
430        clear
431    }
432
433    lappend _runs $xmlobj
434
435    # go through the analysis and find all result sets
436    set haveresults 0
437    foreach item [_reorder [$xmlobj children output]] {
438        switch -glob -- $item {
439            log* {
440                _autoLabel $xmlobj output.$item "Output Log" counters
441            }
442            string* {
443                _autoLabel $xmlobj output.$item "String" counters
444            }
445            histogram* - curve* - field* {
446                _autoLabel $xmlobj output.$item "Plot" counters
447            }
448            structure* {
449                _autoLabel $xmlobj output.$item "Structure" counters
450            }
451            table* {
452                _autoLabel $xmlobj output.$item "Energy Levels" counters
453            }
454            sequence* {
455                _autoLabel $xmlobj output.$item "Sequence" counters
456            }
457        }
458        set label [$xmlobj get output.$item.about.group]
459        if {"" == $label} {
460            set label [$xmlobj get output.$item.about.label]
461        }
462
463        set hidden [$xmlobj get output.$item.hide]
464        set hidden [expr {"" != $hidden && $hidden}]
465
466        if {"" != $label && !$hidden} {
467            set haveresults 1
468        }
469    }
470
471    # if there are any valid results, add them to the resultset
472    if {$haveresults} {
473        set index [$itk_component(resultset) add $xmlobj]
474
475        # add each result to a result viewer
476        foreach item [_reorder [$xmlobj children output]] {
477            set label [$xmlobj get output.$item.about.group]
478            if {"" == $label} {
479                set label [$xmlobj get output.$item.about.label]
480            }
481
482            set hidden [$xmlobj get output.$item.hide]
483            set hidden [expr {"" != $hidden && $hidden}]
484
485            if {"" != $label && !$hidden} {
486                if {![info exists _label2page($label)]} {
487                    set name "page[incr _pages]"
488                    set page [$itk_component(resultpages) insert end $name]
489                    set _label2page($label) $page
490                    set _label2desc($label) \
491                        [$xmlobj get output.$item.about.description]
492                    Rappture::ResultViewer $page.rviewer
493                    pack $page.rviewer -expand yes -fill both -pady 4
494
495                    set end [$itk_component(resultselector) \
496                        choices index -value ---]
497                    if {$end < 0} {
498                        set end "end"
499                    }
500                    $itk_component(resultselector) choices insert $end \
501                        $name $label
502                }
503
504                # add/replace the latest result into this viewer
505                set page $_label2page($label)
506
507                if {![info exists reset($page)]} {
508                    $page.rviewer clear $index
509                    set reset($page) 1
510                }
511                $page.rviewer add $index $xmlobj output.$item
512            }
513        }
514    }
515
516    # show the first page by default
517    set max [$itk_component(resultselector) choices size]
518    for {set i 0} {$i < $max} {incr i} {
519        set first [$itk_component(resultselector) choices get -label $i]
520        if {$first != ""} {
521            set page [$itk_component(resultselector) choices get -value $i]
522            set char [string index $page 0]
523            if {$char != "@" && $char != "-"} {
524                $itk_component(resultpages) current $page
525                $itk_component(resultselector) value $first
526                set _lastlabel $first
527                break
528            }
529        }
530    }
531}
532
533# ----------------------------------------------------------------------
534# USAGE: clear
535#
536# Discards all results previously loaded into the analyzer.
537# ----------------------------------------------------------------------
538itcl::body Rappture::Analyzer::clear {} {
539    foreach obj $_runs {
540        itcl::delete object $obj
541    }
542    set _runs ""
543
544    $itk_component(resultset) clear
545
546    # reset the size of the controls area
547    set ht [winfo height $itk_component(results)]
548    set cntlht [$itk_component(resultset) size -controlarea]
549    set frac [expr {double($cntlht)/$ht}]
550    $itk_component(results) fraction end $frac
551
552    foreach label [array names _label2page] {
553        set page $_label2page($label)
554        $page.rviewer clear
555    }
556    $itk_component(resultselector) value ""
557    $itk_component(resultselector) choices delete 0 end
558    catch {unset _label2page}
559    catch {unset _label2desc}
560    set _plotlist ""
561
562    $itk_component(resultselector) choices insert end --- "---"
563    $itk_component(resultselector) choices insert end \
564        @download [Rappture::filexfer::label download]
565    set _lastlabel ""
566
567    #
568    # HACK ALERT!!
569    # The following statement should be in place, but it causes
570    # vtk to dump core.  Leave it out until we can fix the core dump.
571    # In the mean time, we leak memory...
572    #
573    #$itk_component(resultpages) delete -all
574    #set _pages 0
575
576    _simState on
577    _fixSimControl
578    reset
579}
580
581# ----------------------------------------------------------------------
582# USAGE: download coming
583# USAGE: download controls <downloadCommand>
584# USAGE: download start ?widget?
585# USAGE: download now ?widget?
586#
587# Spools the current result so the user can download it.
588# ----------------------------------------------------------------------
589itcl::body Rappture::Analyzer::download {option args} {
590    set title [$itk_component(resultselector) value]
591    set page [$itk_component(resultselector) translate $title]
592
593    switch -- $option {
594        coming {
595            #
596            # Warn result that a download is coming, in case
597            # it needs to take a screen snap.
598            #
599            if {![regexp {^(|@download|---)$} $page]} {
600                set f [$itk_component(resultpages) page $page]
601                $f.rviewer download coming
602            }
603        }
604        controls {
605            # no controls for this download yet
606            return ""
607        }
608        start {
609            set widget $itk_component(download)
610            if {[llength $args] > 0} {
611                set widget [lindex $args 0]
612                if {[catch {winfo class $widget}]} {
613                    set widget $itk_component(download)
614                }
615            }
616            #
617            # See if this download has any controls.  If so, then
618            # post them now and let the user continue the download
619            # after selecting a file format.
620            #
621            if {$page != ""} {
622                set ext ""
623                set f [$itk_component(resultpages) page $page]
624                set popup [$f.rviewer download controls \
625                    [itcl::code $this download now $widget]]
626
627                if {"" != $popup} {
628                    $popup activate $widget below
629                } else {
630                    download now $widget
631                }
632            } else {
633                # this shouldn't happen
634                set file error.html
635                set data "<h1>Not Found</h1>There is no result selected."
636            }
637        }
638        now {
639            set widget $itk_component(download)
640            if {[llength $args] > 0} {
641                set widget [lindex $args 0]
642                if {[catch {winfo class $widget}]} {
643                    set widget $itk_component(download)
644                }
645            }
646            #
647            # Perform the actual download.
648            #
649            if {$page != ""} {
650                set ext ""
651                set f [$itk_component(resultpages) page $page]
652                foreach {ext data} [$f.rviewer download now] break
653                if {"" == $ext} {
654                    if {"" != $widget} {
655                        Rappture::Tooltip::cue $widget \
656                            "Can't download this result."
657                    }
658                    return
659                }
660                regsub -all {[\ -\/\:-\@\{-\~]} $title {} title
661                set file "$title$ext"
662            } else {
663                # this shouldn't happen
664                set file error.html
665                set data "<h1>Not Found</h1>There is no result selected."
666            }
667
668            set mesg [Rappture::filexfer::download $data $file]
669            if {[string length $mesg] > 0} {
670                Rappture::Tooltip::cue $widget $mesg
671            }
672        }
673        default {
674            error "bad option \"$option\": should be coming, controls, now, start"
675        }
676    }
677}
678
679# ----------------------------------------------------------------------
680# USAGE: _plot ?<index> <options> <index> <options>...?
681#
682# Used internally to update the plot shown in the current result
683# viewer whenever the resultset settings have changed.  Causes the
684# desired results to show up on screen.
685# ----------------------------------------------------------------------
686itcl::body Rappture::Analyzer::_plot {args} {
687    set _plotlist $args
688
689    set page [$itk_component(resultselector) value]
690    set page [$itk_component(resultselector) translate $page]
691    if {"" != $page} {
692        set f [$itk_component(resultpages) page $page]
693        $f.rviewer plot clear
694        foreach {index opts} $_plotlist {
695            $f.rviewer plot add $index $opts
696        }
697    }
698}
699
700# ----------------------------------------------------------------------
701# USAGE: _reorder <compList>
702#
703# Used internally to change the order of a series of output components
704# found in the <output> section.  Moves the <log> elements to the end
705# and returns the updated list.
706# ----------------------------------------------------------------------
707itcl::body Rappture::Analyzer::_reorder {comps} {
708    set i 0
709    set max [llength $comps]
710    while {$i < $max} {
711        set c [lindex $comps $i]
712        if {[string match log* $c]} {
713            set comps [lreplace $comps $i $i]
714            lappend comps $c
715            incr max -1
716        } else {
717            incr i
718        }
719    }
720    return $comps
721}
722
723# ----------------------------------------------------------------------
724# USAGE: _autoLabel <xmlobj> <path> <title> <cntVar>
725#
726# Used internally to check for an about.label property at the <path>
727# in <xmlobj>.  If this object doesn't have a label, then one is
728# supplied using the given <title>.  The <cntVar> is an array of
729# counters in the calling scopes for titles that have been used
730# in the past.  This is used to create titles like "Plot #2" the
731# second time it is encountered.
732#
733# The <xmlobj> is updated so that the label is inserted directly in
734# the tree.
735# ----------------------------------------------------------------------
736itcl::body Rappture::Analyzer::_autoLabel {xmlobj path title cntVar} {
737    upvar $cntVar counters
738
739    set group [$xmlobj get $path.about.group]
740    set label [$xmlobj get $path.about.label]
741    if {"" == $label} {
742        # no label -- make one up using the title specified
743        if {![info exists counters($group-$title)]} {
744            set counters($group-$title) 1
745            set label $title
746        } else {
747            set label "$title (#[incr counters($group-$title)])"
748        }
749        $xmlobj put $path.about.label $label
750    } else {
751        # handle the case of two identical labels in <output>
752        if {![info exists counters($group-$label)]} {
753            set counters($group-$label) 1
754        } else {
755            set label "$label (#[incr counters($group-$label)])"
756            $xmlobj put $path.about.label $label
757        }
758    }
759    return $label
760}
761
762# ----------------------------------------------------------------------
763# USAGE: _fixResult
764#
765# Used internally to change the result page being displayed whenever
766# the user selects a page from the results combobox.
767# ----------------------------------------------------------------------
768itcl::body Rappture::Analyzer::_fixResult {} {
769    set name [$itk_component(resultselector) value]
770    set page ""
771    if {"" != $name} {
772        set page [$itk_component(resultselector) translate $name]
773    }
774    if {$page == "@download"} {
775        # put the combobox back to its last value
776        $itk_component(resultselector) component entry configure -state normal
777        $itk_component(resultselector) component entry delete 0 end
778        $itk_component(resultselector) component entry insert end $_lastlabel
779        $itk_component(resultselector) component entry configure -state disabled
780        # perform the actual download
781        download start $itk_component(resultselector)
782    } elseif {$page == "---"} {
783        # put the combobox back to its last value
784        $itk_component(resultselector) component entry configure -state normal
785        $itk_component(resultselector) component entry delete 0 end
786        $itk_component(resultselector) component entry insert end $_lastlabel
787        $itk_component(resultselector) component entry configure -state disabled
788    } elseif {$page != ""} {
789        set _lastlabel $name
790        set win [winfo toplevel $itk_component(hull)]
791        blt::busy hold $win; update idletasks
792        $itk_component(resultpages) current $page
793
794        set f [$itk_component(resultpages) page $page]
795        $f.rviewer plot clear
796        eval $f.rviewer plot add $_plotlist
797        blt::busy release [winfo toplevel $itk_component(hull)]
798    }
799}
800
801# ----------------------------------------------------------------------
802# USAGE: _fixSize
803#
804# Used internally to change the size of the result set area whenever
805# a new control appears.  Adjusts the size available for the result
806# set up to some maximum.
807# ----------------------------------------------------------------------
808itcl::body Rappture::Analyzer::_fixSize {} {
809    set ht [winfo height $itk_component(results)]
810    if {$ht <= 1} { set ht [winfo reqheight $itk_component(results)] }
811    set cntlht [$itk_component(resultset) size -controlarea]
812    set frac [expr {double($cntlht)/$ht}]
813
814    if {$frac < 0.4} {
815        $itk_component(results) fraction end $frac
816    }
817    _fixSimControl
818}
819
820# ----------------------------------------------------------------------
821# USAGE: _simState <boolean> ?<message>? ?<settings>?
822#
823# Used internally to change the "Simulation" button on or off.
824# If the <boolean> is on, then any <message> and <settings> are
825# displayed as well.  If the <boolean> is off, then only display
826# the message. The <message> is a note to the user about
827# what will be simulated, and the <settings> are a list of
828# tool parameter settings of the form {path1 val1 path2 val2 ...}.
829# When these are in place, the next Simulate operation will use
830# these settings.  This helps fill in missing data values.
831# ----------------------------------------------------------------------
832itcl::body Rappture::Analyzer::_simState {state args} {
833    if {$state} {
834        $itk_interior.simol configure \
835            -background $itk_option(-simcontrolactiveoutline)
836        $itk_interior.simol.simbg configure \
837            -background $itk_option(-simcontrolactivebackground)
838        $itk_component(simulate) configure \
839            -highlightbackground $itk_option(-simcontrolactivebackground)
840        $itk_component(simstatus) configure \
841            -background $itk_option(-simcontrolactivebackground)
842
843        $itk_component(abort) configure -state disabled
844        $itk_component(simulate) configure -state normal \
845            -command [itcl::code $this simulate]
846
847        #
848        # If there's a special message, then put it up next to the button.
849        #
850        set mesg [lindex $args 0]
851        if {"" != $mesg} {
852            $itk_component(simstatus) configure -state normal
853            $itk_component(simstatus) delete 1.0 end
854            $itk_component(simstatus) insert end $mesg
855
856            #
857            # If there are any settings, then install them in the
858            # "Simulate" button.  Also, pop them up as a tooltip
859            # for the message.
860            #
861            set settings [lindex $args 1]
862            if {[llength $settings] > 0} {
863                $itk_component(simulate) configure \
864                    -command [eval itcl::code $this simulate $settings]
865
866                set details ""
867                foreach {path val} $settings {
868                    set str [$_tool xml get $path.about.label]
869                    if {"" == $str} {
870                        set str [$_tool xml element -as id $path]
871                    }
872                    append details "$str = $val\n"
873                }
874                set details [string trim $details]
875
876                Rappture::Tooltip::for $itk_component(simstatus) $details
877                $itk_component(simstatus) insert end " "
878                $itk_component(simstatus) insert end "(details...)" popup
879            }
880            $itk_component(simstatus) configure -state disabled
881        }
882    } else {
883        if {"" != $itk_option(-simcontrolbackground)} {
884            set simcbg $itk_option(-simcontrolbackground)
885        } else {
886            set simcbg $itk_option(-background)
887        }
888        $itk_interior.simol configure \
889            -background $itk_option(-simcontroloutline)
890        $itk_interior.simol.simbg configure -background $simcbg
891        $itk_component(simulate) configure -highlightbackground $simcbg
892        $itk_component(simstatus) configure -background $simcbg
893
894        $itk_component(simulate) configure -state disabled
895        $itk_component(abort) configure -state normal
896
897        $itk_component(simstatus) configure -state normal
898        $itk_component(simstatus) delete 1.0 end
899        set mesg [lindex $args 0]
900        if {"" != $mesg} {
901            $itk_component(simstatus) insert end $mesg
902        }
903        $itk_component(simstatus) configure -state disabled
904    }
905}
906
907# ----------------------------------------------------------------------
908# USAGE: _simOutput <message>
909#
910# Invoked automatically whenever output comes in while running the
911# tool.  Extracts any =RAPPTURE-???=> messages from the output and
912# sends the output to the display.  For example, any
913# =RAPPTURE-PROGRESS=> message pops up the progress meter and updates
914# it to show the latest progress message.  This is useful for
915# long-running tools, to let the user know how much longer the
916# simulation will take.
917# ----------------------------------------------------------------------
918itcl::body Rappture::Analyzer::_simOutput {message} {
919    #
920    # Scan through and pick out any =RAPPTURE-PROGRESS=> messages first.
921    #
922    while {[regexp -indices \
923               {=RAPPTURE-PROGRESS=> *([-+]?[0-9]+) +([^\n]*)(\n|$)} $message \
924                match percent mesg]} {
925
926        foreach {i0 i1} $percent break
927        set percent [string range $message $i0 $i1]
928
929        foreach {i0 i1} $mesg break
930        set mesg [string range $message $i0 $i1]
931
932        pack $itk_component(progress) -fill x -padx 10 -pady 10
933        $itk_component(progress) settings -percent $percent -message $mesg
934
935        foreach {i0 i1} $match break
936        set message [string replace $message $i0 $i1]
937    }
938
939    #
940    # Break up the remaining lines according to =RAPPTURE-ERROR=> messages.
941    # Show errors in a special color.
942    #
943    $itk_component(runinfo) configure -state normal
944
945    while {[regexp -indices \
946               {=RAPPTURE-([a-zA-Z]+)=>([^\n]*)(\n|$)} $message \
947                match type mesg]} {
948
949        foreach {i0 i1} $match break
950        set first [string range $message 0 [expr {$i0-1}]]
951        if {[string length $first] > 0} {
952            $itk_component(runinfo) insert end $first
953            $itk_component(runinfo) insert end \n
954        }
955
956        foreach {t0 t1} $type break
957        set type [string range $message $t0 $t1]
958        foreach {m0 m1} $mesg break
959        set mesg [string range $message $m0 $m1]
960        if {[string length $mesg] > 0 && $type != "RUN"} {
961            $itk_component(runinfo) insert end $mesg $type
962            $itk_component(runinfo) insert end \n $type
963        }
964
965        set message [string range $message [expr {$i1+1}] end]
966    }
967
968    if {[string length $message] > 0} {
969        $itk_component(runinfo) insert end $message
970        if {[$itk_component(runinfo) get end-2char] != "\n"} {
971            $itk_component(runinfo) insert end "\n"
972        }
973        $itk_component(runinfo) see end
974    }
975    $itk_component(runinfo) configure -state disabled
976}
977
978# ----------------------------------------------------------------------
979# USAGE: _resultTooltip
980#
981# Used internally to build the tooltip string displayed for the
982# result selector.  If the current page has an associated description,
983# then it is displayed beneath the result.
984#
985# Returns the string for the tooltip.
986# ----------------------------------------------------------------------
987itcl::body Rappture::Analyzer::_resultTooltip {} {
988    set tip ""
989    set name [$itk_component(resultselector) value]
990    if {[info exists _label2desc($name)] &&
991         [string length $_label2desc($name)] > 0} {
992        append tip "$_label2desc($name)\n\n"
993    }
994    if {[array size _label2page] > 1} {
995        append tip "Use this control to display other output results."
996    }
997    return $tip
998}
999
1000# ----------------------------------------------------------------------
1001# USAGE: _fixSimControl
1002#
1003# Used internally to add or remove the simulation control at the
1004# top of the analysis area.  This is controlled by the -simcontrol
1005# option.
1006# ----------------------------------------------------------------------
1007itcl::body Rappture::Analyzer::_fixSimControl {} {
1008    switch -- $itk_option(-simcontrol) {
1009        on {
1010            pack $itk_interior.simol -fill x -before $itk_interior.nb
1011        }
1012        off {
1013            pack forget $itk_interior.simol
1014        }
1015        auto {
1016            #
1017            # If we have two or more radiodials, then there is a
1018            # chance of encountering a combination of parameters
1019            # with no data, requiring simulation.
1020            #
1021            if {[$itk_component(resultset) size -controls] >= 2} {
1022                pack $itk_interior.simol -fill x -before $itk_interior.nb
1023            } else {
1024                pack forget $itk_interior.simol
1025            }
1026        }
1027        default {
1028            error "bad value \"$itk_option(-simcontrol)\": should be on, off, auto"
1029        }
1030    }
1031}
1032
1033# ----------------------------------------------------------------------
1034# USAGE: _fixNotebook
1035#
1036# Used internally to switch the active notebook page
1037# ----------------------------------------------------------------------
1038itcl::body Rappture::Analyzer::_fixNotebook {} {
1039    switch -- $itk_option(-notebookpage) {
1040        about {
1041            $itk_component(notebook) current about
1042        }
1043        simulate {
1044            $itk_component(notebook) current simulate
1045        }
1046        analyze {
1047            $itk_component(notebook) current analyze
1048        }
1049        default {
1050            error "bad value \"$itk_option(-notebookpage)\": should be about, simulate, analyze"
1051        }
1052    }
1053}
1054
1055# ----------------------------------------------------------------------
1056# CONFIGURATION OPTION: -simcontrol
1057#
1058# Controls whether or not the Simulate button is showing.  In some
1059# cases, it is not needed.
1060# ----------------------------------------------------------------------
1061itcl::configbody Rappture::Analyzer::simcontrol {
1062    _fixSimControl
1063}
1064
1065# ----------------------------------------------------------------------
1066# CONFIGURATION OPTION: -notebookpage
1067#
1068# Controls which page of the analyzer notebook is shown. It is
1069# particularly needed when using rerun, when you don't want to
1070# "simulate -ifneeded" because an actual simulation might be
1071# kicked off due to differences between tool.xml and run.xml
1072# ----------------------------------------------------------------------
1073itcl::configbody Rappture::Analyzer::notebookpage {
1074    _fixNotebook
1075}
Note: See TracBrowser for help on using the repository browser.