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

Last change on this file since 210 was 210, checked in by mmc, 18 years ago

Last few fixes for file upload/download. Changed the "Download..."
button to an icon, and added a "Download..." option on the drop-down
list for the Results area. Fixed the "Upload..." to pop up a message,
in case the web form doesn't appear.

Fixed the "grab" function, so it won't fail with a Tk error box.
If it can't get the grab, it tries a few more times and then gives
up. Also, fixed <Esc><Esc><Esc> desperation binding to release
any busy windows.

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