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

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

Added popup options for the "download" button. Right now this works
only for <curve> objects. You can select between CSV and PDF output.
Will add other formats later.

Fixed a few "after cancel" errors that were happening when you switch
between inputs in the structure demo.

Fixed the colors and fonts for the new bug report window.

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