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

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