source: trunk/gui/scripts/sequence.tcl @ 435

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

Fixed the <sequence> object so that it can support multiple objects
within each <element>. For example, the zoo/sequence demo now includes
two parameters A and B, and the B parameters are used to generate a
series of <curve> objects within each <element>.

Fixed the <sequence> so it works correctly when an index has units.

File size: 6.6 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: sequence - represents a sequence of output results
3#
4#  This object represents a sequence of other output results.  Each
5#  element in the sequence has an index and a value.  All values in
6#  the sequence must have the same type, but they can all be curves,
7#  images, or other results.
8# ======================================================================
9#  AUTHOR:  Michael McLennan, Purdue University
10#  Copyright (c) 2004-2005  Purdue Research Foundation
11#
12#  See the file "license.terms" for information on usage and
13#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14# ======================================================================
15package require Itcl
16package require BLT
17
18namespace eval Rappture { # forward declaration }
19
20itcl::class Rappture::Sequence {
21    constructor {xmlobj path} { # defined below }
22    destructor { # defined below }
23
24    public method value {pos}
25    public method index {pos}
26    public method size {}
27    public method hints {{keyword ""}}
28
29    private variable _xmlobj ""  ;# ref to lib obj with sequence data
30    private variable _dataobjs   ;# maps index => data object
31    private variable _indices    ;# list of sorted index values
32    private variable _hints      ;# cache of hints stored in XML
33}
34
35# ----------------------------------------------------------------------
36# CONSTRUCTOR
37# ----------------------------------------------------------------------
38itcl::body Rappture::Sequence::constructor {xmlobj path} {
39    if {![Rappture::library isvalid $xmlobj]} {
40        error "bad value \"$xmlobj\": should be LibraryObj"
41    }
42    set _xmlobj [$xmlobj element -as object $path]
43
44    #
45    # Extract data values from the element definitions.
46    #
47    foreach name [$_xmlobj children -type element] {
48        set index [$xmlobj get $path.$name.index]
49        if {"" == $index} {
50            continue
51        }
52
53        set ctype ""
54        set _dataobjs($index) ""
55        foreach cname [$_xmlobj children $name] {
56            set type [$xmlobj element -as type $path.$name.$cname]
57            switch -- $type {
58                index {
59                    # ignore this
60                    continue
61                }
62                curve {
63                    set obj [Rappture::Curve ::#auto $xmlobj $path.$name.$cname]
64                }
65                field {
66                    set obj [Rappture::Field ::#auto $xmlobj $path.$name.$cname]
67                }
68                image {
69                    set obj [Rappture::Image ::#auto $xmlobj $path.$name.$cname]
70                }
71                default {
72                    error "don't know how to handle sequences of $type"
73                }
74            }
75            if {"" == $ctype} {
76                set ctype $type
77            }
78            if {$type == $ctype} {
79                lappend _dataobjs($index) $obj
80            } else {
81                itcl::delete object $obj
82            }
83        }
84    }
85
86    #
87    # Generate a list of sorted index values.
88    #
89    set units [$xmlobj get $path.index.units]
90    if {"" != $units} {
91        # build up a list:  {10m 10} {10cm 0.1} ...
92        set vals ""
93        foreach key [array names _dataobjs] {
94            lappend vals [list $key [Rappture::Units::convert $key \
95                -context $units -to $units -units off]]
96        }
97
98        # sort according to raw values; store both values
99        set _indices [lsort -real -index 1 $vals]
100
101    } else {
102        # are the indices integers, reals, or strings?
103        set how -integer
104        foreach key [array names _dataobjs] {
105            if {[regexp {^[0-9]+[eE][-+]?[0-9]+|([0-9]+)?\.[0-9]+([eE][-+]?[0-9]+)$} $key]} {
106                set how -real
107                break
108            } elseif {![regexp {^[0-9]+$} $key]} {
109                set how -dictionary
110                break
111            }
112        }
113
114        # keep a list of indices sorted in order
115        set _indices ""
116        if {[string equal $how -dictionary]} {
117            set n 0
118            foreach val [lsort $how [array names _dataobjs]] {
119                lappend _indices [list $val $n]
120            }
121        } else {
122            foreach val [lsort $how [array names _dataobjs]] {
123                lappend _indices [list $val $val]
124            }
125        }
126    }
127}
128
129# ----------------------------------------------------------------------
130# DESTRUCTOR
131# ----------------------------------------------------------------------
132itcl::body Rappture::Sequence::destructor {} {
133    foreach key [array names _dataobjs] {
134        eval itcl::delete object $_dataobjs($key)
135    }
136    itcl::delete object $_xmlobj
137}
138
139# ----------------------------------------------------------------------
140# USAGE: value <pos>
141#
142# Returns the value for the element as position <pos> in the
143# list of all elements.  Here, <pos> runs from 0 to size-1.
144# ----------------------------------------------------------------------
145itcl::body Rappture::Sequence::value {pos} {
146    set i [lindex [lindex $_indices $pos] 0]
147    return $_dataobjs($i)
148}
149
150# ----------------------------------------------------------------------
151# USAGE: index <pos>
152#
153# Returns information about the index value for the element at
154# position <pos> in the list of all elements.  The return value is
155# a list of two elements:  {string rawNumberValue}.  Here, <pos>
156# runs from 0 to size-1.
157# ----------------------------------------------------------------------
158itcl::body Rappture::Sequence::index {pos} {
159    return [lindex $_indices $pos]
160}
161
162# ----------------------------------------------------------------------
163# USAGE: size
164#
165# Returns the number of elements in this sequence.
166# ----------------------------------------------------------------------
167itcl::body Rappture::Sequence::size {} {
168    return [llength $_indices]
169}
170
171# ----------------------------------------------------------------------
172# USAGE: hints ?<keyword>?
173#
174# Returns a list of key/value pairs for various hints about showing
175# this image.  If a particular <keyword> is specified, then it returns
176# the hint for that <keyword>, if it exists.
177# ----------------------------------------------------------------------
178itcl::body Rappture::Sequence::hints {{keyword ""}} {
179    if {![info exists _hints]} {
180        foreach {key path} {
181            label        about.label
182            indexlabel   index.label
183            indexdesc    index.description
184        } {
185            set str [$_xmlobj get $path]
186            if {"" != $str} {
187                set _hints($key) $str
188            }
189        }
190    }
191
192    if {$keyword != ""} {
193        if {[info exists _hints($keyword)]} {
194            return $_hints($keyword)
195        }
196        return ""
197    }
198    return [array get _hints]
199}
Note: See TracBrowser for help on using the repository browser.