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

Last change on this file since 903 was 903, checked in by mmc, 15 years ago

Final tweaks on the optimization package. The demo now works properly.
Just run "wish simple.tcl" to see it work.

Fixed the Tool class to work better with the optimizer. The "run"
method now returns the result directly as a Rappture::Library object,
and the Analyzer merely loads the object.

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