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

Last change on this file since 1128 was 1124, checked in by dkearney, 16 years ago

enabling user to switch the text in the "Simulate" Button for cceHUB by using the tool.action.label tag

adding examples/lang directory where we can put example programs for each language showing off usage of bindings. most of the code is already in the wiki, but this will allow the user to easily run the example and see the exact text/steps needed to use a binding function.

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