source: trunk/gui/scripts/drawingentry.tcl @ 2938

Last change on this file since 2938 was 2938, checked in by gah, 12 years ago

experimental drawing entry enabled

File size: 14.1 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: DrawingEntry - widget for entering numeric values
3#
4#  This widget represents a <number> entry on a control panel.
5#  It is used to enter numeric values.
6# ======================================================================
7#  AUTHOR:  Michael McLennan, Purdue University
8#  Copyright (c) 2004-2005  Purdue Research Foundation
9#
10#  See the file "license.terms" for information on usage and
11#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12# ======================================================================
13package require Itk
14
15itcl::class Rappture::DrawingEntry {
16    inherit itk::Widget
17    itk_option define -state state State "normal"
18
19    private variable _owner
20    private variable _path
21    private variable _cname2id
22    private variable _worldX 0
23    private variable _worldY 0
24    private variable _worldWidth 0
25    private variable _worldHeight 0
26
27    constructor {owner path args} { # defined below }
28
29    public method value {args}
30
31    public method label {}
32    public method tooltip {}
33
34    private method ParseDescription {}
35    private method ParseLineDescription { cname }
36    private method ParseGridDescription { cname }
37    private method ParseTextDescription { cname }
38    private method ParseStringDescription { cname }
39    private method ParseNumberDescription { cname }
40    private method GetCanvasHeight { }
41    private method GetCanvasWidth { }
42    private method ScreenX { x }
43    private method ScreenY { y }
44    private method ScreenCoords { coords }
45    private method Highlight { tag }
46    private method Unhighlight { tag }
47}
48
49itk::usual DrawingEntry {
50    keep -cursor -font
51    keep -foreground -background
52    keep -textbackground
53    keep -selectbackground -selectforeground -selectborderwidth
54}
55
56# ----------------------------------------------------------------------
57# CONSTRUCTOR
58# ----------------------------------------------------------------------
59itcl::body Rappture::DrawingEntry::constructor {owner path args} {
60    if {[catch {$owner isa Rappture::ControlOwner} valid] != 0 || !$valid} {
61        error "bad object \"$owner\": should be Rappture::ControlOwner"
62    }
63    set _path $path
64    set _owner $owner
65    #
66    # Display the current drawing.
67    #
68    itk_component add drawing {
69        canvas $itk_interior.canvas -background white -relief sunken -bd 1
70    } {
71        ignore -background
72    }
73    pack $itk_component(drawing) -expand yes -fill both
74    ParseDescription
75    eval itk_initialize $args
76}
77
78# ----------------------------------------------------------------------
79# USAGE: value ?-check? ?<newval>?
80#
81# Clients use this to query/set the value for this widget.  With
82# no args, it returns the current value for the widget.  If the
83# <newval> is specified, it sets the value of the widget and
84# sends a <<Value>> event.  If the -check flag is included, the
85# new value is not actually applied, but just checked for correctness.
86# ----------------------------------------------------------------------
87itcl::body Rappture::DrawingEntry::value {args} {
88puts "value $args"
89    set onlycheck 0
90    set i [lsearch -exact $args -check]
91    if {$i >= 0} {
92        set onlycheck 1
93        set args [lreplace $args $i $i]
94    }
95
96    if {[llength $args] == 1} {
97        if {$onlycheck} {
98            # someday we may add validation...
99            return
100        }
101        set xmlobj [lindex $args 0]
102        $itk_component(drawing) value $xmlobj
103        return $xmlobj
104
105    } elseif {[llength $args] != 0} {
106        error "wrong # args: should be \"value ?-check? ?newval?\""
107    }
108
109    #
110    # Query the value and return.
111    #
112    return [$itk_component(drawing) value]
113}
114
115# ----------------------------------------------------------------------
116# USAGE: label
117#
118# Clients use this to query the label associated with this widget.
119# Reaches into the XML and pulls out the appropriate label string.
120# ----------------------------------------------------------------------
121itcl::body Rappture::DrawingEntry::label {} {
122return ""
123    set label [$_owner xml get $_path.about.label]
124    if {"" == $label} {
125        set label "Drawing"
126    }
127    return $label
128}
129
130# ----------------------------------------------------------------------
131# USAGE: tooltip
132#
133# Clients use this to query the tooltip associated with this widget.
134# Reaches into the XML and pulls out the appropriate description
135# string.  Returns the string that should be used with the
136# Rappture::Tooltip facility.
137# ----------------------------------------------------------------------
138itcl::body Rappture::DrawingEntry::tooltip {} {
139return ""
140    set str [$_owner xml get $_path.about.description]
141    return [string trim $str]
142}
143
144# ----------------------------------------------------------------------
145# CONFIGURATION OPTION: -state
146# ----------------------------------------------------------------------
147itcl::configbody Rappture::DrawingEntry::state {
148    set valid {normal disabled}
149    if {[lsearch -exact $valid $itk_option(-state)] < 0} {
150        error "bad value \"$itk_option(-state)\": should be [join $valid {, }]"
151    }
152}
153
154itcl::body Rappture::DrawingEntry::ParseLineDescription { cname } {
155    array set attr2option {
156        "linewidth"     "-width"
157        "arrow"         "-arrow"
158        "dash"          "-dash"
159        "color"         "-fill"
160    }
161    # Set default options first and then let tool.xml override them.
162    array set options {
163        -arrow          none
164        -width          0
165        -fill           black
166        -dash           ""
167    }
168    # Coords
169    set coords {}
170    set coords [$_owner xml get $_path.components.$cname.coords]
171    set coords [string trim $coords]
172    if { $coords == "" } {
173        set coords "0 0"
174    } else {
175        set coords [ScreenCoords $coords]
176    }
177    puts stderr "ParseLineDescrption description owner=$_owner path=$_path coords=$coords"
178    set list {}
179    foreach attr [$_owner xml children $_path.components.$cname] {
180        if { [info exists attr2option($attr)] } {
181            set option $attr2option($attr)
182            set value [$_owner xml get $_path.components.$cname.$attr]
183            set options($option) $value
184        }
185    }
186    puts stderr "$itk_component(drawing) create line $coords"
187    set id [eval $itk_component(drawing) create line $coords]
188    set _cname2id($cname) $id
189    eval $itk_component(drawing) itemconfigure $id [array get options]
190}
191
192#
193# ParseGridDescription --
194#
195itcl::body Rappture::DrawingEntry::ParseGridDescription { cname } {
196    puts stderr "ParseGridDescrption description owner=$_owner path=$_path"
197    foreach attr [$_owner xml children $_path.components.$cname] {
198        puts stderr attr=$attr
199    }
200    array set attr2option {
201        "linewidth"     "-width"
202        "arrow"         "-arrow"
203        "dash"          "-dash"
204        "color"         "-fill"
205    }
206    # Set default options first and then let tool.xml override them.
207    array set options {
208        -arrow          none
209        -width          0
210        -fill           black
211        -dash           ""
212    }
213    # Coords
214    set xcoords [$_owner xml get $_path.components.$cname.xcoords]
215    set xcoords [string trim $xcoords]
216    set ycoords [$_owner xml get $_path.components.$cname.ycoords]
217    set ycoords [string trim $ycoords]
218    if { $ycoords == "" } {
219        set ycoords "0 1"
220        set ymax 1
221        set ymin 0
222    } else {
223        set list {}
224        set ymax -10000
225        set ymin 10000
226        foreach c $ycoords {
227            set y [ScreenY $c]
228            if { $y > $ymax } {
229                set ymax $y
230            }
231            if { $y < $ymin } {
232                set ymin $y
233            }
234            lappend list $y
235        }
236        set ycoords $list
237    }
238    if { $xcoords == "" } {
239        set xcoords "0 1"
240        set xmax 1
241        set xmin 0
242    } else {
243        set list {}
244        set xmax -10000
245        set xmin 10000
246        foreach c $xcoords {
247            set x [ScreenX $c]
248            if { $x > $xmax } {
249                set xmax $x
250            }
251            if { $x < $xmin } {
252                set xmin $x
253            }
254            lappend list $x
255        }
256        set xcoords $list
257    }
258    puts stderr "ParseLineDescrption description owner=$_owner path=$_path xcoords=$xcoords ycoords=$ycoords"
259    set list {}
260    foreach attr [$_owner xml children $_path.components.$cname] {
261        if { [info exists attr2option($attr)] } {
262            set option $attr2option($attr)
263            set value [$_owner xml get $_path.components.$cname.$attr]
264            set options($option) $value
265        }
266    }
267    foreach y $ycoords {
268        lappend ids \
269            [eval $itk_component(drawing) create line $xmin $y $xmax $y \
270                 [array get options]]
271    }
272    foreach x $xcoords {
273        lappend ids \
274            [eval $itk_component(drawing) create line $x $ymin $x $ymax \
275                 [array get options]]
276    }
277    set _cname2id($cname) $ids
278}
279
280itcl::body Rappture::DrawingEntry::ParseTextDescription { cname } {
281    array set attr2option {
282        "font"          "-font"
283        "default"       "-text"
284        "color"         "-fill"
285        "text"          "-text"
286        "anchor"        "-anchor"
287    }
288    puts stderr "ParseStringDescrption description owner=$_owner path=$_path"
289
290    # Set default options first and then let tool.xml override them.
291    array set options {
292        -font {Arial 12}
293        -text {}
294        -fill black
295        -anchor c
296    }
297    foreach attr [$_owner xml children $_path.components.$cname] {
298        if { [info exists attr2option($attr)] } {
299            set option $attr2option($attr)
300            set value [$_owner xml get $_path.components.$cname.$attr]
301            set options($option) $value
302        }
303    }
304    # Coords
305    set coords {}
306    set coords [$_owner xml get $_path.components.$cname.coords]
307    set coords [string trim $coords]
308    if { $coords == "" } {
309        set coords "0 0"
310    } else {
311        set coords [ScreenCoords $coords]
312    }
313    puts stderr "$itk_component(drawing) create text $coords"
314    set id [eval $itk_component(drawing) create text $coords]
315    set _cname2id($cname) $id
316    puts stderr "$itk_component(drawing) itemconfigure $id [array get options]"
317    eval $itk_component(drawing) itemconfigure $id [array get options]
318}
319
320itcl::body Rappture::DrawingEntry::ParseStringDescription { cname } {
321    array set attr2option {
322        "font"          "-font"
323        "default"       "-text"
324        "color"         "-fill"
325    }
326    puts stderr "ParseStringDescrption description owner=$_owner path=$_path"
327
328    # Set default options first and then let tool.xml override them.
329    array set options {
330        -font {Arial 12}
331        -text {}
332        -fill black
333    }
334    foreach attr [$_owner xml children $_path.components.$cname] {
335        if { [info exists attr2option($attr)] } {
336            set option $attr2option($attr)
337            set value [$_owner xml get $_path.components.$cname.$attr]
338            set options($option) $value
339        }
340    }
341    # Coords
342    set coords {}
343    set coords [$_owner xml get $_path.components.$cname.coords]
344    set coords [string trim $coords]
345    if { $coords == "" } {
346        set coords "0 0"
347    }
348    # Is there a label?
349    set label [$_owner xml get $_path.components.$cname.about.label]
350    set labelWidth 0
351    if { $label != "" } {
352        set labelId [$itk_component(drawing) create text -1000 -1000 \
353                         -text $label -font $options(-font)]
354        set labelWidth [font measure $options(-font) $label]
355    }
356    set id [$itk_component(drawing) create text -1000 -1000  -tag $cname]
357    set entryWidth [font measure $options(-font) $options(-text) ]
358
359    foreach { x y } [ScreenCoords $coords] break
360    set lx $x
361    set ly $y
362    set tx [expr $x + $labelWidth]
363    set ty $y
364
365    eval $itk_component(drawing) coords $id $tx $ty
366    if { $labelWidth > 0 } {
367        puts stderr "LABEL($labelWidth):$itk_component(drawing) coords $labelId $lx $ly"
368        eval $itk_component(drawing) coords $labelId $lx $ly
369    }
370    set _cname2id($cname) $id
371    puts stderr "$itk_component(drawing) itemconfigure $id [array get options]"
372    eval $itk_component(drawing) itemconfigure $id [array get options]
373    set bbox [$itk_component(drawing) bbox $id]
374    puts stderr "cname=$cname bbox=$bbox"
375    set sid [eval $itk_component(drawing) create rectangle $bbox]
376    $itk_component(drawing) itemconfigure $sid -fill "" -outline "" \
377        -tag $cname-bg
378    set sid [eval $itk_component(drawing) create rectangle $bbox]
379    $itk_component(drawing) itemconfigure $sid -fill "" -outline "" \
380        -tag $cname-sensor
381    $itk_component(drawing) bind $cname-sensor <Enter> \
382        [itcl::code $this Highlight $cname]
383    $itk_component(drawing) bind $cname-sensor <Leave> \
384        [itcl::code $this Unhighlight $cname]
385    $itk_component(drawing) lower $cname-bg
386    $itk_component(drawing) raise $cname-sensor
387}
388
389itcl::body Rappture::DrawingEntry::ParseNumberDescription { cname } {
390    puts stderr "ParseNumberDescrption description owner=$_owner path=$_path"
391    foreach attr [$_owner xml children $_path.components.$cname] {
392        puts stderr attr=$attr
393    }
394}
395
396itcl::body Rappture::DrawingEntry::ScreenX { x } {
397    set norm [expr ($x - $_worldX) / double($_worldWidth)]
398    puts stderr "ScreenX x=$x, norm=$norm wx=$_worldX ww=$_worldWidth"
399    set x [expr int($norm * [GetCanvasWidth])]
400    puts stderr "ScreenX after x=$x cw=[GetCanvasWidth]"
401    return $x
402}
403
404itcl::body Rappture::DrawingEntry::ScreenY { y } {
405    set norm [expr ($y - $_worldY) / double($_worldWidth)]
406    set y [expr int($norm * [GetCanvasHeight])]
407    return $y
408}
409
410itcl::body Rappture::DrawingEntry::ScreenCoords { coords } {
411    set list {}
412    foreach {x y} $coords {
413        lappend list [ScreenX $x] [ScreenY $y]
414    }
415    return $list
416}
417
418itcl::body Rappture::DrawingEntry::GetCanvasWidth { } {
419    set w [winfo width $itk_component(drawing)]
420    if { $w < 2 } {
421        set w [winfo reqwidth $itk_component(drawing)]
422    }
423    return $w
424}
425
426itcl::body Rappture::DrawingEntry::GetCanvasHeight { } {
427    set h [winfo height $itk_component(drawing)]
428    if { $h < 2 } {
429        set h [winfo reqheight $itk_component(drawing)]
430    }
431    return $h
432}
433
434itcl::body Rappture::DrawingEntry::ParseDescription {} {
435    puts stderr "ParseDescrption description owner=$_owner path=$_path"
436    set bbox [$_owner xml get $_path.about.bbox]
437    puts stderr bbox=$bbox
438    if { [llength $bbox] != 4 } {
439        set bbox "0 0 [GetCanvasWidth] [GetCanvasHeight]"
440    }
441    foreach { x1 y1 x2 y2 } $bbox break
442    set _worldWidth [expr $x2 - $x1]
443    set _worldHeight [expr $y2 - $y1]
444    set _worldX $x1
445    set _worldY $y1
446    foreach cname [$_owner xml children $_path.components] {
447        switch -glob -- $cname {
448            "line*" {
449                ParseLineDescription $cname
450            }
451            "grid*" {
452                ParseGridDescription $cname
453            }
454            "text*" {
455                ParseTextDescription $cname
456            }
457            "string*" {
458                ParseStringDescription $cname
459            }
460            "number*" {
461                ParseNumberDescription $cname
462            }
463        }
464    }
465}
466
467
468
469itcl::body Rappture::DrawingEntry::Highlight { tag } {
470    $itk_component(drawing) itemconfigure $tag-bg -outline black \
471        -fill lightblue
472}
473
474itcl::body Rappture::DrawingEntry::Unhighlight { tag } {
475    $itk_component(drawing) itemconfigure $tag-bg -outline "" \
476        -fill ""
477}
Note: See TracBrowser for help on using the repository browser.