source: trunk/gui/scripts/spectrum.tcl @ 551

Last change on this file since 551 was 115, checked in by mmc, 19 years ago

Updated all copyright notices.

File size: 8.1 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: spectrum - maps a range of real values onto a color
3#
4#  This data object represents the mapping of a range of real values
5#  onto a range of colors.  It is used in conjunction with other
6#  widgets, such as the Rappture::Gauge.
7#
8#  EXAMPLE:
9#    Rappture::Spectrum #auto {
10#       0.0   red
11#       1.0   green
12#      10.0   #d9d9d9
13#    }
14# ======================================================================
15#  AUTHOR:  Michael McLennan, Purdue University
16#  Copyright (c) 2004-2005  Purdue Research Foundation
17#
18#  See the file "license.terms" for information on usage and
19#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
20# ======================================================================
21package require Itk
22
23itcl::class Rappture::Spectrum {
24    inherit Rappture::Dispatcher
25
26    public variable units ""  ;# default units for all real values
27
28    constructor {{sdata ""} args} { # defined below }
29
30    public method insert {args}
31    public method delete {first {last ""}}
32    public method get {args}
33
34    private variable _axis ""       ;# list of real values along axis
35    private variable _rvals ""      ;# list of red components along axis
36    private variable _gvals ""      ;# list of green components along axis
37    private variable _bvals ""      ;# list of blue components along axis
38}
39                                                                               
40# ----------------------------------------------------------------------
41# CONSTRUCTOR
42# ----------------------------------------------------------------------
43itcl::body Rappture::Spectrum::constructor {{sdata ""} args} {
44    register !change  ;# used to signal changes in spectrum
45
46    if {[llength $sdata] > 0} {
47        regsub -all {\n} $sdata { } sdata
48        eval insert $sdata
49    }
50    eval configure $args
51}
52
53# ----------------------------------------------------------------------
54# USAGE: insert ?<value1> <color1> <value2> <color2> ...?
55#
56# Clients use this to insert one or more values into the spectrum.
57# Each value has an associated color.  These values are used in the
58# "get" method to map any incoming value to its interpolated color
59# in the spectrum.
60# ----------------------------------------------------------------------
61itcl::body Rappture::Spectrum::insert {args} {
62    set changed 0
63    foreach {value color} $args {
64        if {"" != $units} {
65            set value [Rappture::Units::convert $value \
66                -context $units -to $units -units off]
67        }
68        foreach {r g b} [winfo rgb . $color] { break }
69
70        set i 0
71        foreach v $_axis {
72            if {$value == $v} {
73                set _rvals [lreplace $_rvals $i $i $r]
74                set _gvals [lreplace $_gvals $i $i $g]
75                set _bvals [lreplace $_bvals $i $i $b]
76                set changed 1
77                break
78            } elseif {$value < $v} {
79                set _axis  [linsert $_axis $i $value]
80                set _rvals [linsert $_rvals $i $r]
81                set _gvals [linsert $_gvals $i $g]
82                set _bvals [linsert $_bvals $i $b]
83                set changed 1
84                break
85            }
86            incr i
87        }
88
89        if {$i >= [llength $_axis]} {
90            lappend _axis $value
91            lappend _rvals $r
92            lappend _gvals $g
93            lappend _bvals $b
94            set changed 1
95        }
96    }
97
98    # let any clients know if something has changed
99    if {$changed} {
100        event !change
101    }
102}
103
104# ----------------------------------------------------------------------
105# USAGE: delete <first> ?<last>?
106#
107# Clients use this to delete one or more entries from the spectrum.
108# The <first> and <last> represent the integer index of the desired
109# element.  If only <first> is specified, then that one element is
110# deleted.  If <last> is specified, then all elements in the range
111# <first> to <last> are deleted.
112# ----------------------------------------------------------------------
113itcl::body Rappture::Spectrum::delete {first {last ""}} {
114    if {$last == ""} {
115        set last $first
116    }
117    if {![regexp {^[0-9]+|end$} $first]} {
118        error "bad index \"$first\": should be integer or \"end\""
119    }
120    if {![regexp {^[0-9]+|end$} $last]} {
121        error "bad index \"$last\": should be integer or \"end\""
122    }
123
124    if {[llength [lrange $_axis $first $last]] > 0} {
125        set _axis [lreplace $_axis $first $last]
126        set _rvals [lreplace $_rvals $first $last]
127        set _gvals [lreplace $_gvals $first $last]
128        set _bvals [lreplace $_bvals $first $last]
129        event !change
130    }
131}
132
133# ----------------------------------------------------------------------
134# USAGE: get ?-color|-fraction? ?<value>?
135#
136# Clients use this to get information about the spectrum.  With no args,
137# it returns a list of elements in the form accepted by the "insert"
138# method.  Otherwise, it returns the interpolated value for the given
139# <value>.  By default, it returns the interpolated color, but the
140# -fraction flag can be specified to query the fractional position
141# along the spectrum.
142# ----------------------------------------------------------------------
143itcl::body Rappture::Spectrum::get {args} {
144    if {[llength $args] == 0} {
145        set rlist ""
146        foreach v $_axis r $_rvals g $_gvals b $_bvals {
147            lappend rlist "$v$units" [format {#%.4x%.4x%.4x} $r $g $b]
148        }
149        return $rlist
150    }
151
152    set what "-color"
153    while {[llength $args] > 0} {
154        set first [lindex $args 0]
155        if {[regexp {^-[a-zA-Z]} $first]} {
156            set what $first
157            set args [lrange $args 1 end]
158        } else {
159            break
160        }
161    }
162    if {[llength $args] != 1} {
163        error "wrong # args: should be \"get ?-color|-fraction? ?value?\""
164    }
165
166    set value [lindex $args 0]
167    if {$units != ""} {
168        set value [Rappture::Units::convert $value \
169            -context $units -to $units -units off]
170    }
171
172    switch -- $what {
173        -color {
174            set i 0
175            set ilast ""
176            while {$i <= [llength $_axis]} {
177                set v [lindex $_axis $i]
178
179                if {$v == ""} {
180                    set r [lindex $_rvals $ilast]
181                    set g [lindex $_gvals $ilast]
182                    set b [lindex $_bvals $ilast]
183                    return [format {#%.4x%.4x%.4x} $r $g $b]
184                } elseif {$value < $v} {
185                    if {$ilast == ""} {
186                        set r [lindex $_rvals $i]
187                        set g [lindex $_gvals $i]
188                        set b [lindex $_bvals $i]
189                    } else {
190                        set vlast [lindex $_axis $ilast]
191                        set frac [expr {($value-$vlast)/double($v-$vlast)}]
192
193                        set rlast [lindex $_rvals $ilast]
194                        set r [lindex $_rvals $i]
195                        set r [expr {round($frac*($r-$rlast) + $rlast)}]
196
197                        set glast [lindex $_gvals $ilast]
198                        set g [lindex $_gvals $i]
199                        set g [expr {round($frac*($g-$glast) + $glast)}]
200
201                        set blast [lindex $_bvals $ilast]
202                        set b [lindex $_bvals $i]
203                        set b [expr {round($frac*($b-$blast) + $blast)}]
204                    }
205                    return [format {#%.4x%.4x%.4x} $r $g $b]
206                }
207                set ilast $i
208                incr i
209            }
210        }
211        -fraction {
212            set v0 [lindex $_axis 0]
213            set vend [lindex $_axis end]
214            return [expr {($value-$v0)/double($vend-$v0)}]
215        }
216        default {
217            error "bad flag \"$what\": should be -color or -fraction"
218        }
219    }
220}
221
222# ----------------------------------------------------------------------
223# CONFIGURATION OPTIONS: -units
224# ----------------------------------------------------------------------
225itcl::configbody Rappture::Spectrum::units {
226    if {"" != $units && [Rappture::Units::System::for $units] == ""} {
227        error "bad value \"$units\": should be system of units"
228    }
229    event !change
230}
Note: See TracBrowser for help on using the repository browser.