source: trunk/gui/scripts/transferfunctioneditor.tcl @ 4094

Last change on this file since 4094 was 4088, checked in by gah, 10 years ago

fix editor to handle current component, add binding to delete key to remove markers

File size: 11.2 KB
Line 
1# -*- mode: tcl; indent-tabs-mode: nil -*-
2
3# ----------------------------------------------------------------------
4#  COMPONENT: transferfunctioneditor - Rudimentary editor for 3D volume
5#                                      transfer functions
6#
7#  This class is used to modify transfer functions used in volume rendering
8#  on 3D scalar/vector datasets.
9#
10# ======================================================================
11#  AUTHOR:  Michael McLennan, Purdue University
12#  Copyright (c) 2004-2012  HUBzero Foundation, LLC
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
18package require BLT
19package require Img
20
21itcl::class Rappture::TransferFunctionEditor {
22    private variable _nextId 0;         # Used to create unique marker names
23    private variable _values;           # Relative values for each marker.
24    private variable _limits;           # Over limits of transfer function.
25    private variable _labels;           # Label id for each marker.
26    private variable _ticks;            # Tick id for each marker.
27    private variable _canvas    ""
28    private variable _name "";          # Name of transfer function.
29    private variable _activeMotion   0
30    private variable _activePress    0
31    private variable _id2name
32    private common   _normalIcon [Rappture::icon nvlegendmark]
33    private common   _activeIcon [Rappture::icon nvlegendmark2]
34    public variable command ""
35
36    private method SetAbsoluteValue { name x }
37    private method GetAbsoluteValue { name }
38    private method ContinueDrag { name x y }
39    private method EnterTick { name }
40    private method GetOverlappingMarkers { x y }
41    private method GetScreenPosition { name }
42    private method LeaveTick { name }
43    private method SetRelativeValue  { name x }
44    private method GetRelativeValue  { name }
45    private method RemoveDuplicateMarkers {name x y}
46    private method SetScreenPosition { name }
47    private method SetVisibility { name bool }
48    private method StartDrag { name x y }
49    private method StopDrag { name x y }
50    private method Activate { name }
51    private method Deactivate { name }
52    private method UpdateViewer {}
53
54    constructor {c name args} {}
55    destructor {}
56    public method limits { min max }
57    public method names {}
58    public method name {}
59    public method values {}
60    public method absoluteValues {}
61    public method removeMarkers { list }
62    public method addMarkers { values }
63    public method newMarker { x y state }
64    public method deleteMarker { x y }
65    public method hideMarkers { {list {}} }
66    public method showMarkers { {limits {}} }
67}
68
69itcl::body Rappture::TransferFunctionEditor::constructor {c name args} {
70    set _canvas $c
71    set _name $name
72    set _limits [list 0.0 1.0]
73    eval configure $args
74}
75
76itcl::body Rappture::TransferFunctionEditor::limits { min max } {
77    set _limits [list $min $max]
78}
79
80itcl::body Rappture::TransferFunctionEditor::names {} {
81    return [lsort [array names _values]]
82}
83
84itcl::body Rappture::TransferFunctionEditor::values {} {
85    set list {}
86    foreach name [array names _ticks] {
87        lappend list [GetRelativeValue $name]
88    }
89    return [lsort -real $list]
90}
91
92itcl::body Rappture::TransferFunctionEditor::absoluteValues {} {
93    set list {}
94    foreach name [array names _values] {
95        lappend list [GetAbsoluteValue $name]
96    }
97    return $list
98}
99
100itcl::body Rappture::TransferFunctionEditor::deleteMarker { x y } {
101    foreach marker [GetOverlappingMarkers $x $y] {
102        $_canvas delete $_ticks($marker)
103        $_canvas delete $_labels($marker)
104        array unset _ticks $marker
105        array unset _labels $marker
106        array unset _values $marker
107        bell
108        UpdateViewer
109    }
110}
111
112itcl::body Rappture::TransferFunctionEditor::newMarker { x y state } {
113    foreach id [$_canvas find overlapping \
114                    [expr $x-5] [expr $y-5] [expr $x+5] [expr $y+5]] {
115        if { [info exists _id2name($id)] } {
116            puts stderr "Too close to existing marker"
117            return;                     # Too close to existing marker
118        }
119    }
120    set name "tick[incr _nextId]"
121    set w [winfo width $_canvas]
122    set h [winfo height $_canvas]
123
124    set _ticks($name) [$_canvas create image 0 $h \
125                           -image $_normalIcon -anchor s \
126                           -tags "tick $_name $this" -state $state]
127    set _labels($name) [$_canvas create text 0 $h \
128                            -anchor n -fill white -font "Helvetica 8" \
129                            -tags "$this $_name" -state $state]
130    set _id2name($_ticks($name)) $name
131    $_canvas bind $_ticks($name) <Enter> [itcl::code $this EnterTick $name]
132    $_canvas bind $_ticks($name) <Leave> [itcl::code $this LeaveTick $name]
133    $_canvas bind $_ticks($name) <ButtonPress-1> \
134        [itcl::code $this StartDrag $name %x %y]
135    $_canvas bind $_ticks($name) <B1-Motion> \
136        [itcl::code $this ContinueDrag $name %x %y]
137    $_canvas bind $_ticks($name) <ButtonRelease-1> \
138        [itcl::code $this StopDrag $name %x %y]
139
140    SetRelativeValue $name [expr {double($x-10)/($w-20)}]
141    if { $state == "normal" } {
142        UpdateViewer
143    }
144    return $name
145}
146
147itcl::body Rappture::TransferFunctionEditor::destructor {} {
148    $_canvas delete $_name
149}
150
151itcl::body Rappture::TransferFunctionEditor::name {} {
152    return $_name
153}
154
155itcl::body Rappture::TransferFunctionEditor::Activate { name } {
156    if  { $_activePress || $_activeMotion } {
157        $_canvas itemconfigure $_labels($name) -state normal
158        $_canvas itemconfigure $_ticks($name) -image $_activeIcon
159        $_canvas itemconfigure title -state hidden
160    }
161}
162
163itcl::body Rappture::TransferFunctionEditor::Deactivate { name } {
164    if  { $_activePress || $_activeMotion } {
165        #puts stderr "do nothing for Deactivate"
166    } else {
167        $_canvas itemconfigure $_labels($name) -state hidden
168        $_canvas itemconfigure $_ticks($name) -image $_normalIcon
169        $_canvas itemconfigure title -state normal
170    }
171}
172
173itcl::body Rappture::TransferFunctionEditor::SetVisibility { name bool } {
174    if { $bool } {
175        $_canvas itemconfigure $_ticks($name) -state normal
176        $_canvas raise $_ticks($name)
177    } else {
178        $_canvas itemconfigure $_ticks($name) -state hidden
179    }
180}
181
182itcl::body Rappture::TransferFunctionEditor::GetScreenPosition { name } {
183    set x [GetRelativeValue $name]
184    if { $x < 0.0 } {
185        set x 0.0
186    } elseif { $x > 1.0 } {
187        set x 1.0
188    }
189    set low 10
190    set w [winfo width $_canvas]
191    set high [expr {$w  - 10}]
192    set x [expr {round($x*($high - $low) + $low)}]
193    return $x
194}
195
196itcl::body Rappture::TransferFunctionEditor::SetScreenPosition { name } {
197    set value $_values($name)
198    set x [GetScreenPosition $name]
199    set absval [GetAbsoluteValue $name]
200    set y 31
201    $_canvas itemconfigure $_labels($name) -text [format %.2g $absval]
202    $_canvas coords $_ticks($name) $x [expr {$y+3}]
203    $_canvas coords $_labels($name) $x [expr {$y+5}]
204}
205
206itcl::body Rappture::TransferFunctionEditor::GetAbsoluteValue { name } {
207    foreach {min max} $_limits break
208    return [expr {($_values($name) * ($max - $min)) + $min}]
209}
210
211itcl::body Rappture::TransferFunctionEditor::SetAbsoluteValue { name value } {
212    foreach {min max} $_limits break
213    set absval $value
214    set relval [expr {($absval - $min) / ($max - $min)}]
215    set _values($name) $relval
216    set y 31
217    $_canvas itemconfigure $_label -text [format %.2g $absval]
218    set x [GetScreenPosition $name]
219    $_canvas coords $_ticks($name) $x [expr {$y+3}]
220    $_canvas coords $_labels($name) $x [expr {$y+5}]
221    return $absval
222}
223
224itcl::body Rappture::TransferFunctionEditor::GetRelativeValue  { name } {
225    return $_values($name)
226}
227
228itcl::body Rappture::TransferFunctionEditor::SetRelativeValue  { name value } {
229    set _values($name) $value
230    set x [GetScreenPosition $name]
231    set y 31
232    set absval [GetAbsoluteValue $name]
233    $_canvas itemconfigure $_labels($name) -text [format %.2g $absval]
234    $_canvas coords $_ticks($name) $x [expr {$y+3}]
235    $_canvas coords $_labels($name) $x [expr {$y+5}]
236}
237
238itcl::body Rappture::TransferFunctionEditor::EnterTick { name } {
239    set _activeMotion 1
240    Activate $name
241    $_canvas raise $_ticks($name)
242}
243
244itcl::body Rappture::TransferFunctionEditor::LeaveTick { name } {
245    set _activeMotion 0
246    Deactivate $name
247}
248
249itcl::body Rappture::TransferFunctionEditor::StartDrag { name x y } {
250    $_canvas raise $_ticks($name)
251    set _activePress 1
252    Activate $name
253    $_canvas itemconfigure limits -state hidden
254    $_canvas itemconfigure title -state hidden
255}
256
257itcl::body Rappture::TransferFunctionEditor::StopDrag { name x y } {
258    ContinueDrag $name $x $y
259    RemoveDuplicateMarkers $name $x $y
260    set _activePress 0
261    Deactivate $name
262    $_canvas itemconfigure limits -state normal
263    $_canvas itemconfigure title -state normal
264}
265
266itcl::body Rappture::TransferFunctionEditor::ContinueDrag { name x y } {
267    set w [winfo width $_canvas]
268    SetRelativeValue $name [expr {double($x-10)/($w-20)}]
269    UpdateViewer
270    $_canvas raise $_ticks($name)
271    set _activePress 1
272    Activate $name
273    $_canvas itemconfigure limits -state hidden
274    $_canvas itemconfigure title -state hidden
275}
276
277itcl::body Rappture::TransferFunctionEditor::GetOverlappingMarkers { x y } {
278    set list {}
279    foreach id [$_canvas find overlapping $x $y $x $y] {
280        if { [info exists _id2name($id)] } {
281            lappend list $_id2name($id)
282        }
283    }
284    return $list
285}
286
287itcl::body Rappture::TransferFunctionEditor::hideMarkers { {list {}} } {
288    if { $list == "" } {
289        set list [array names _values]
290    }
291    foreach name $list {
292        SetVisibility $name 0
293    }
294}
295
296itcl::body Rappture::TransferFunctionEditor::showMarkers { {limits {}} } {
297    if { $limits != "" } {
298        set _limits $limits
299        foreach name [array names _values] {
300            SetScreenPosition $name
301        }
302    }
303    foreach name [array names _values] {
304        SetVisibility $name 1
305    }
306}
307
308itcl::body Rappture::TransferFunctionEditor::RemoveDuplicateMarkers {name x y} {
309    foreach marker [GetOverlappingMarkers $x $y] {
310        if { $marker != $name } {
311            Activate $marker
312            set markerx [GetScreenPosition $marker]
313            if { ($x < ($markerx-3)) || ($x > ($markerx+3)) } {
314                continue
315            }
316            $_canvas delete $_ticks($marker)
317            $_canvas delete $_labels($marker)
318            array unset _ticks $marker
319            array unset _labels $marker
320            array unset _values $marker
321            bell
322        }
323    }
324}
325
326itcl::body Rappture::TransferFunctionEditor::addMarkers { values } {
327    foreach value $values {
328        set name [newMarker 0 0 hidden]
329        SetRelativeValue $name $value
330    }
331}
332
333itcl::body Rappture::TransferFunctionEditor::removeMarkers { names } {
334    if { $names == "" } {
335        set names [array names _values]
336    }
337    foreach name $names {
338        $_canvas delete $_ticks($name)
339        $_canvas delete $_labels($name)
340        array unset _ticks $name
341        array unset _labels $name
342        array unset _values $name
343    }
344    UpdateViewer
345}
346
347itcl::body Rappture::TransferFunctionEditor::UpdateViewer {} {
348    # Tell the nanovis/flowvis client to update its transfer functions
349    # now that a marker position has changed.
350    if { $command != "" } {
351        eval uplevel \#0 $command
352    }
353}
Note: See TracBrowser for help on using the repository browser.