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

Last change on this file since 1444 was 1442, checked in by gah, 15 years ago

new flowvisviewer and pushbutton widgets

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