source: trunk/gui/scripts/resultviewer.tcl @ 13

Last change on this file since 13 was 13, checked in by mmc, 16 years ago

Many improvements, including a new energy level viewer
for Huckel-IV. Added support for a new <boolean> type.
Fixed the cloud/field stuff so that when a cloud is 1D,
it reverts to BLT vectors so it will plot correctly.
Fixed the install script to work better on Windows.

File size: 10.3 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: ResultViewer - plots a collection of related results
3#
4#  This widget plots a collection of results that all represent
5#  the same quantity, but for various ranges of input values.  It
6#  is normally used as part of an Analyzer, to plot the various
7#  results selected by a ResultSet.
8# ======================================================================
9#  AUTHOR:  Michael McLennan, Purdue University
10#  Copyright (c) 2004-2005
11#  Purdue Research Foundation, West Lafayette, IN
12# ======================================================================
13package require Itk
14
15option add *ResultViewer.width 4i widgetDefault
16option add *ResultViewer.height 4i widgetDefault
17
18itcl::class Rappture::ResultViewer {
19    inherit itk::Widget
20
21    itk_option define -colors colors Colors ""
22    itk_option define -clearcommand clearCommand ClearCommand ""
23    itk_option define -simulatecommand simulateCommand SimulateCommand ""
24
25    constructor {args} { # defined below }
26    destructor { # defined below }
27
28    public method add {index xmlobj path}
29    public method clear {{index ""}}
30
31    public method plot {option args}
32
33    protected method _plotAdd {xmlobj {settings ""}}
34    protected method _fixScale {args}
35    protected proc _xml2data {xmlobj path}
36
37    private variable _dispatcher ""  ;# dispatchers for !events
38    private variable _mode ""        ;# current plotting mode (xy, etc.)
39    private variable _mode2widget    ;# maps plotting mode => widget
40    private variable _dataslots ""   ;# list of all data objects in this widget
41    private variable _plotlist ""    ;# list of indices plotted in _dataslots
42}
43                                                                               
44itk::usual ResultViewer {
45    keep -background -foreground -cursor -font
46}
47
48# ----------------------------------------------------------------------
49# CONSTRUCTOR
50# ----------------------------------------------------------------------
51itcl::body Rappture::ResultViewer::constructor {args} {
52    option add hull.width hull.height
53    pack propagate $itk_component(hull) no
54
55    # create a dispatcher for events
56    Rappture::dispatcher _dispatcher
57    $_dispatcher register !scale
58    $_dispatcher dispatch $this !scale \
59        [itcl::code $this _fixScale]
60
61    eval itk_initialize $args
62}
63
64# ----------------------------------------------------------------------
65# DESTRUCTOR
66# ----------------------------------------------------------------------
67itcl::body Rappture::ResultViewer::destructor {} {
68    foreach slot $_dataslots {
69        foreach obj $slot {
70            itcl::delete object $obj
71        }
72    }
73}
74
75# ----------------------------------------------------------------------
76# USAGE: add <index> <xmlobj> <path>
77#
78# Adds a new result to this result viewer at the specified <index>.
79# Data is taken from the <xmlobj> object at the <path>.
80# ----------------------------------------------------------------------
81itcl::body Rappture::ResultViewer::add {index xmlobj path} {
82    if {$path != ""} {
83        set dobj [_xml2data $xmlobj $path]
84    } else {
85        set dobj ""
86    }
87
88    #
89    # If the index doesn't exist, then fill in empty slots and
90    # make it exist.
91    #
92    for {set i [llength $_dataslots]} {$i <= $index} {incr i} {
93        lappend _dataslots ""
94    }
95    set slot [lindex $_dataslots $index]
96    lappend slot $dobj
97    set _dataslots [lreplace $_dataslots $index $index $slot]
98
99    $_dispatcher event -idle !scale
100}
101
102# ----------------------------------------------------------------------
103# USAGE: clear ?<index>?
104#
105# Clears one or all results in this result viewer.
106# ----------------------------------------------------------------------
107itcl::body Rappture::ResultViewer::clear {{index ""}} {
108    if {"" != $index} {
109        # clear one result
110        if {$index >= 0 && $index < [llength $_dataslots]} {
111            set slot [lindex $_dataslots $index]
112            foreach dobj $slot {
113                itcl::delete object $dobj
114            }
115            set _dataslots [lreplace $_dataslots $index $index ""]
116        }
117    } else {
118        # clear all results
119        plot clear
120        foreach slot $_dataslots {
121            foreach dobj $slot {
122                itcl::delete object $dobj
123            }
124        }
125        set _dataslots ""
126    }
127}
128
129# ----------------------------------------------------------------------
130# USAGE: plot add ?<index> <settings> <index> <settings> ...?
131# USAGE: plot clear
132#
133# Used to manipulate the contents of this viewer.  The "plot clear"
134# command clears the current viewer.  Data is still stored in the
135# widget, but the results are not shown on screen.  The "plot add"
136# command adds the data at the specified <index> to the plot.  If
137# the optional <settings> are specified, then they are applied
138# to the plot; otherwise, default settings are used.
139# ----------------------------------------------------------------------
140itcl::body Rappture::ResultViewer::plot {option args} {
141    switch -- $option {
142        add {
143            foreach {index opts} $args {
144                set slot [lindex $_dataslots $index]
145                foreach dobj $slot {
146                    # start with default settings from data object
147                    if {[catch {$dobj hints style} settings]} {
148                        set settings ""
149                    }
150                    # add override settings passed in here
151                    eval lappend settings $opts
152
153                    _plotAdd $dobj $settings
154                }
155            }
156        }
157        clear {
158            # clear the contents of the current mode
159            if {"" != $_mode} {
160                $_mode2widget($_mode) delete
161            }
162            set _plotlist ""
163        }
164        default {
165            error "bad option \"$option\": should be add or clear"
166        }
167    }
168}
169
170# ----------------------------------------------------------------------
171# USAGE: _plotAdd <dataobj> <settings>
172#
173# Used internally to add a <dataobj> representing some data to
174# the plot at the top of this widget.  The data is added to the
175# current plot.  Use the "clear" function to clear before adding
176# new data.
177# ----------------------------------------------------------------------
178itcl::body Rappture::ResultViewer::_plotAdd {dataobj {settings ""}} {
179    switch -- [$dataobj info class] {
180        ::Rappture::Curve {
181            set mode "xy"
182            if {![info exists _mode2widget($mode)]} {
183                set w $itk_interior.xy
184                Rappture::XyResult $w
185                set _mode2widget($mode) $w
186            }
187        }
188        ::Rappture::Field {
189            switch -- [$dataobj components -dimensions] {
190                1D {
191                    set mode "xy"
192                    if {![info exists _mode2widget($mode)]} {
193                        set w $itk_interior.xy
194                        Rappture::XyResult $w
195                        set _mode2widget($mode) $w
196                    }
197                }
198                2D {
199                    set mode "contour"
200                    if {![info exists _mode2widget($mode)]} {
201                        set w $itk_interior.contour
202                        Rappture::ContourResult $w
203                        set _mode2widget($mode) $w
204                    }
205                }
206                default {
207                    error "can't handle [$dataobj components -dimensions] field"
208                }
209            }
210        }
211        ::Rappture::Table {
212            set cols [Rappture::EnergyLevels::columns $dataobj]
213            if {"" != $cols} {
214                set mode "energies"
215                if {![info exists _mode2widget($mode)]} {
216                    set w $itk_interior.energies
217                    Rappture::EnergyLevels $w
218                    set _mode2widget($mode) $w
219                }
220            }
221        }
222        ::Rappture::LibraryObj {
223            switch -- [$dataobj element -as type] {
224                log {
225                    set mode "log"
226                    if {![info exists _mode2widget($mode)]} {
227                        set w $itk_interior.log
228                        Rappture::TextResult $w
229                        set _mode2widget($mode) $w
230                    }
231                }
232            }
233        }
234        default {
235            error "don't know how to plot <$type> data"
236        }
237    }
238
239    if {$mode != $_mode && $_mode != ""} {
240        set nactive [llength [$_mode2widget($_mode) get]]
241        if {$nactive > 0} {
242            return  ;# mixing data that doesn't mix -- ignore it!
243        }
244    }
245
246    # are we plotting in a new mode? then change widgets
247    if {$_mode2widget($mode) != [pack slaves $itk_interior]} {
248        # remove any current window
249        foreach w [pack slaves $itk_interior] {
250            pack forget $w
251        }
252        pack $_mode2widget($mode) -expand yes -fill both
253
254        set _mode $mode
255        $_dispatcher event -idle !scale
256    }
257    $_mode2widget($mode) add $dataobj $settings
258}
259
260# ----------------------------------------------------------------------
261# USAGE: _fixScale ?<eventArgs>...?
262#
263# Invoked automatically whenever a new dataset is added to fix the
264# overall scales of the viewer.  This makes the visualizer consistent
265# across all <dataobj> in this widget, so that it can plot all
266# available data.
267# ----------------------------------------------------------------------
268itcl::body Rappture::ResultViewer::_fixScale {args} {
269    if {"" != $_mode} {
270        set dlist ""
271        foreach slot $_dataslots {
272            foreach dobj $slot {
273                lappend dlist $dobj
274            }
275        }
276        eval $_mode2widget($_mode) scale $dlist
277    }
278}
279
280# ----------------------------------------------------------------------
281# USAGE: _xml2data <xmlobj> <path>
282#
283# Used internally to create a data object for the data at the
284# specified <path> in the <xmlobj>.
285# ----------------------------------------------------------------------
286itcl::body Rappture::ResultViewer::_xml2data {xmlobj path} {
287    set type [$xmlobj element -as type $path]
288    switch -- $type {
289        curve {
290            return [Rappture::Curve ::#auto $xmlobj $path]
291        }
292        field {
293            return [Rappture::Field ::#auto $xmlobj $path]
294        }
295        table {
296            return [Rappture::Table ::#auto $xmlobj $path]
297        }
298        log {
299            return [$xmlobj element -as object $path]
300        }
301        time - status {
302            return ""
303        }
304    }
305    error "don't know how to plot <$type> data"
306}
Note: See TracBrowser for help on using the repository browser.