source: trunk/gui/scripts/deviceLayout1D.tcl @ 11

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

Major reorganization of the entire package. The config.xml file
is now irrelevant. All the action is in the tool.xml file. The
main program now organizes all input into 1) side-by-side pages,
2) input/result (wizard-style) pages, or 3) a series of wizard-
style pages. The <input> can have <phase> parts representing
the various pages.

Added a new ContourResult? widget based on Swaroop's vtk plotting
code.

Also, added easymesh and showmesh to the "tools" directory.
We need these for Eric Polizzi's code.

File size: 18.5 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: deviceLayout1D - visualizer for 1D device geometries
3#
4#  This widget is a simple visualizer for the layout of 1D devices.
5#  It takes the Rappture XML representation for a 1D device and draws
6#  the series of slabs representing the various material layers in the
7#  device.  It can be configured to allow simple selection and editing
8#  of material layers.
9# ======================================================================
10#  AUTHOR:  Michael McLennan, Purdue University
11#  Copyright (c) 2004-2005
12#  Purdue Research Foundation, West Lafayette, IN
13# ======================================================================
14package require Itk
15package require BLT
16
17option add *DeviceLayout1D.width 4i widgetDefault
18option add *DeviceLayout1D.deviceSize 0.25i widgetDefault
19option add *DeviceLayout1D.deviceOutline black widgetDefault
20option add *DeviceLayout1D.annotate all widgetDefault
21option add *DeviceLayout1D.font \
22    -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
23
24itcl::class Rappture::DeviceLayout1D {
25    inherit itk::Widget
26
27    itk_option define -font font Font ""
28    itk_option define -device device Device ""
29    itk_option define -devicesize deviceSize DeviceSize 0
30    itk_option define -deviceoutline deviceOutline DeviceOutline ""
31    itk_option define -leftmargin leftMargin LeftMargin 0
32    itk_option define -rightmargin rightMargin RightMargin 0
33
34    constructor {args} { # defined below }
35    public method limits {}
36    public method extents {what}
37    public method controls {option args}
38
39    protected method _layout {}
40    protected method _redraw {}
41    protected method _drawLayer {index x0 x1}
42    protected method _drawIcon {index x0 x1 imh}
43    protected method _drawAnnotation {index x0 x1}
44    protected method _mater2color {mater}
45
46    private variable _dispatcher "" ;# dispatcher for !events
47    private variable _sizes         ;# maps size name => pixels
48
49    private variable _device ""     ;# LibraryObj for device representation
50    private variable _slabs ""      ;# list of node names for slabs in device
51    private variable _z0 ""         ;# list parallel to _slabs with z0
52                                    ;#   coord for lhs of each slab
53    private variable _z1 ""         ;# list parallel to _slabs with z1
54                                    ;#   coord for rhs of each slab
55    private variable _maters ""     ;# list parallel to _slabs with material
56                                    ;#   for each slab
57    private variable _colors ""     ;# list parallel to _slabs with color
58                                    ;#   for each slab
59
60    private variable _controls      ;# maps control path => status on/off
61
62    private variable _icons         ;# maps icon data => image handle
63}
64                                                                               
65itk::usual DeviceLayout1D {
66    keep -background -cursor
67    keep -device -deviceoutline -devicesize
68    keep -selectbackground -selectforeground -selectborderwidth
69    keep -width
70}
71
72# ----------------------------------------------------------------------
73# CONSTRUCTOR
74# ----------------------------------------------------------------------
75itcl::body Rappture::DeviceLayout1D::constructor {args} {
76    Rappture::dispatcher _dispatcher
77    $_dispatcher register !layout
78    $_dispatcher dispatch $this !layout "[itcl::code $this _layout]; list"
79    $_dispatcher register !redraw
80    $_dispatcher dispatch $this !redraw "[itcl::code $this _redraw]; list"
81
82    itk_option add hull.width
83    pack propagate $itk_component(hull) no
84
85    itk_component add area {
86        canvas $itk_interior.area -borderwidth 0 -highlightthickness 0
87    } {
88        usual
89        ignore -borderwidth -relief
90        ignore -highlightthickness -highlightbackground -highlightcolor
91    }
92    pack $itk_component(area) -fill both
93    bind $itk_component(area) <Configure> \
94        [list $_dispatcher event -idle !redraw]
95
96    eval itk_initialize $args
97}
98
99# ----------------------------------------------------------------------
100# USAGE: limits
101#
102# Clients use this to query the limits of the x-axis for the
103# current device.  Returns the min/max limits indicating the
104# physical size of the device.
105# ----------------------------------------------------------------------
106itcl::body Rappture::DeviceLayout1D::limits {} {
107    if {[$_dispatcher ispending !layout]} {
108        $_dispatcher cancel !layout
109        _layout
110    }
111    set zmin [lindex $_z0 0]
112    set zmax [lindex $_z1 end]
113    return [list $zmin $zmax]
114}
115
116# ----------------------------------------------------------------------
117# USAGE: extents <what>
118#
119# Clients use this to query the size of various things within this
120# widget--similar to the "extents" method of the BLT graph.  Returns
121# the size of some item in pixels.
122# ----------------------------------------------------------------------
123itcl::body Rappture::DeviceLayout1D::extents {what} {
124    switch -- $what {
125        bar3D { return $_sizes(bar45) }
126        default {
127            error "bad option \"$what\": should be bar3D"
128        }
129    }
130}
131
132# ----------------------------------------------------------------------
133# USAGE: controls add <path>
134#
135# Clients use this to add hints about the controls that should be
136# added to the layout area.  Common paths are components.slab#.material
137# and components.slab#.thickness.
138# ----------------------------------------------------------------------
139itcl::body Rappture::DeviceLayout1D::controls {option args} {
140    switch -- $option {
141        add {
142            if {[llength $args] != 1} {
143                error "wrong # args: should be \"controls add path\""
144            }
145            set path [lindex $args 0]
146            set _controls($path) 1
147            $_dispatcher event -idle !layout
148        }
149        remove {
150            error "not yet implemented"
151        }
152    }
153}
154
155# ----------------------------------------------------------------------
156# USAGE: _layout
157#
158# Called automatically whenever something changes that affects the
159# layout of the widget.  Recalculates the layout and computes a good
160# overall value for the minimum height of the widget.  This may cause
161# the widget to change size, which in turn would trigger another
162# _redraw.
163# ----------------------------------------------------------------------
164itcl::body Rappture::DeviceLayout1D::_layout {} {
165    # first, recompute the overall height of this widget
166    set h [expr {$_sizes(bar)+$_sizes(bar45)+2}]
167
168    set fnt $itk_option(-font)
169    # see if any of the slabs has a material
170    foreach m $_maters {
171        if {"" != $m} {
172            set extra [expr {1.5*[font metrics $fnt -linespace]}]
173            set h [expr {$h+$extra}]
174            break
175        }
176    }
177
178    # see if any of the slabs has a label
179    if {$_device != ""} {
180        foreach nn [$_device children components] {
181            if {"" != [$_device get components.$nn.about.label]} {
182                set extra [expr {1.2*[font metrics $fnt -linespace]}]
183                set h [expr {$h+$extra}]
184                break
185            }
186        }
187    }
188
189    set oldh [component hull cget -height]
190    if {$h != $oldh} {
191        component hull configure -height $h
192        $_dispatcher event -idle !redraw
193    }
194
195    # next, scan through the device and compute layer positions
196    set slabs ""
197    set z0 ""
198    set z1 ""
199    set maters ""
200    set colors ""
201
202    if {$_device != ""} {
203        # get the default system of units
204        set units [set defunits [$_device get units]]
205        if {$units == "arbitrary"} {
206            set defunits "m"
207            set units "um"
208        }
209
210        foreach nn [$_device children components] {
211            switch -glob -- $nn {
212                box* {
213                    # get x-coord for each corner
214                    set c0 [lindex [$_device get components.$nn.corner0] 0]
215                    set c0 [Rappture::Units::convert $c0 \
216                        -context $defunits -to $units -units off]
217
218                    set c1 [lindex [$_device get components.$nn.corner1] 0]
219                    set c1 [Rappture::Units::convert $c1 \
220                        -context $defunits -to $units -units off]
221
222                    lappend slabs components.$nn
223                    lappend z0 $c0
224                    lappend z1 $c1
225
226                    set m [$_device get components.$nn.material]
227                    lappend maters $m
228
229                    if {"" != $m} {
230                        set c [_mater2color $m]
231                    } else {
232                        set c [$_device get components.$nn.about.color]
233                    }
234                    if {"" == $c} { set c gray }
235                    lappend colors $c
236                }
237                default {
238                    # element not recognized -- skip it
239                }
240            }
241        }
242    }
243
244    # something change? then store new layout and redraw
245    if {![string equal $z0 $_z0]
246          || ![string equal $z1 $_z1]
247          || ![string equal $maters $_maters]
248          || ![string equal $colors $_colors]} {
249        set _slabs $slabs
250        set _z0 $z0
251        set _z1 $z1
252        set _maters $maters
253        set _colors $colors
254
255        $_dispatcher event -idle !redraw
256    }
257}
258
259# ----------------------------------------------------------------------
260# USAGE: _redraw
261#
262# Called automatically whenever the device geometry changes, or when
263# the canvas changes size, to redraw all elements within it.
264# ----------------------------------------------------------------------
265itcl::body Rappture::DeviceLayout1D::_redraw {} {
266    set c $itk_component(area)
267
268    # clean up images and delete all other items
269    $c delete all
270
271    set w [expr {[winfo width $c]-1 - $_sizes(lm) - $_sizes(rm)}]
272
273    set x0 $_sizes(lm)
274    set x1 [expr {$x0 + $w}]
275
276    set zmax [lindex $_z1 end]
277    set xx0 $x0
278    set xx1 $x1
279
280    for {set i 0} {$i < [llength $_slabs]} {incr i} {
281        set name [lindex $_slabs $i]
282        set z0 [lindex $_z0 $i]
283        set z1 [lindex $_z1 $i]
284        set xx0 [expr {double($z0)/$zmax * ($x1-$x0) + $x0}]
285        set xx1 [expr {double($z1)/$zmax * ($x1-$x0) + $x0}]
286
287        set icon [$_device get $name.about.icon]
288        if {"" != $icon} {
289            if {[info exists _icons($icon)]} {
290                set imh $_icons($icon)
291            } else {
292                set imh [image create photo -data $icon]
293                set _icons($icon) $imh
294            }
295            _drawIcon $i $xx0 $xx1 $imh
296        } else {
297            _drawLayer $i $xx0 $xx1
298        }
299        _drawAnnotation $i $xx0 $xx1
300    }
301}
302
303# ----------------------------------------------------------------------
304# USAGE: _drawLayer <index> <x0> <x1>
305#
306# Used internally within _redraw to draw one material layer at the
307# <index> within the slab list into the active area.  The layer is
308# drawn between coordinates <x0> and <x1> on the canvas.
309# ----------------------------------------------------------------------
310itcl::body Rappture::DeviceLayout1D::_drawLayer {index x0 x1} {
311    set c $itk_component(area)
312    set h [expr {[winfo height $c]-1}]
313
314    set y0 $h
315    set y0p [expr {$y0-$_sizes(bar45)}]
316    set y1p [expr {$y0-$_sizes(bar)}]
317    set y1 [expr {$y1p-$_sizes(bar45)}]
318
319    set x0p [expr {$x0+$_sizes(bar45)}]
320    set x1p [expr {$x1+$_sizes(bar45)}]
321
322    set lcolor $itk_option(-deviceoutline)
323
324    if {$index < [llength $_slabs]} {
325        set fcolor [lindex $_colors $index]
326
327        #
328        # Draw one segment of the bar in the canvas:
329        #
330        #      ___________________  ____ y1
331        #     /                  /| ____ y0p
332        #    /__________________/ / ____ y1p
333        #    |__________________|/: ____ y0
334        #    : :                : :
335        #   x0 x0p             x1 x1p
336        #
337        $c create polygon \
338            $x0 $y0  $x1 $y0  $x1p $y0p  $x1p $y1  $x0p $y1  $x0 $y1p  $x0 $y0 \
339            -outline $lcolor -fill $fcolor
340        $c create line $x0 $y1p  $x1 $y1p -fill $lcolor
341
342        #
343        # Draw the outline around the end cap
344        #
345        $c create line $x1 $y0  $x1 $y1p  $x1p $y1 -fill $lcolor
346    }
347}
348
349# ----------------------------------------------------------------------
350# USAGE: _drawIcon <index> <x0> <x1> <imh>
351#
352# Used internally within _redraw to draw a material layer that is
353# represented by an icon.  The layer sits at <index> within the slab
354# list into the active area.  The layer is drawn between coordinates
355# <x0> and <x1> on the canvas.
356# ----------------------------------------------------------------------
357itcl::body Rappture::DeviceLayout1D::_drawIcon {index x0 x1 imh} {
358    set c $itk_component(area)
359    set h [expr {[winfo height $c]-1}]
360
361    set y0 $h
362    set y0p [expr {$y0-$_sizes(bar45)}]
363    set y1p [expr {$y0-$_sizes(bar)}]
364    set y1 [expr {$y1p-$_sizes(bar45)}]
365    set x0p [expr {$x0+$_sizes(bar45)}]
366    set x1p [expr {$x1+$_sizes(bar45)}]
367
368    set xx0 [expr {0.5*($x0+$x0p)}]
369    set xx1 [expr {0.5*($x1+$x1p)}]
370    set y [expr {0.5*($y0+$y0p) + 0.5*($y1-$y0p)}]
371
372    ##set lcolor $itk_option(-deviceoutline)
373    ##$c create line $xx0 $y $xx1 $y -width 3
374
375    $c create image [expr {0.5*($xx0+$xx1)}] $y -anchor c -image $imh
376}
377
378# ----------------------------------------------------------------------
379# USAGE: _drawAnnotation <index> <x0> <x1>
380#
381# Used internally within _redraw to draw one material layer at the
382# <index> within the slab list into the active area.  The layer is
383# drawn between coordinates <x0> and <x1> on the canvas.
384# ----------------------------------------------------------------------
385itcl::body Rappture::DeviceLayout1D::_drawAnnotation {index x0 x1} {
386    set c $itk_component(area)
387    set h [expr {[winfo height $c]-1}]
388
389    set y0 $h
390    set y1 [expr {$y0-$_sizes(bar)-$_sizes(bar45)}]
391
392    set x0p [expr {$x0+$_sizes(bar45)}]
393    set x1p [expr {$x1+$_sizes(bar45)}]
394    set xmid [expr {0.5*($x0p+$x1p)}]
395
396    set fnt $itk_option(-font)
397    set lh [font metrics $fnt -linespace]
398    set ymid [expr {$y1-2-0.5*$lh}]
399    set y [expr {$y1-4}]
400
401    #
402    # If there's a .material control for this slab, draw it here.
403    #
404    set elem [lindex $_slabs $index]
405    set mater [lindex $_maters $index]
406    if {"" != $mater} {
407        set x $x1p
408        $c create rectangle [expr {$x-10}] [expr {$y-14}] \
409            [expr {$x-0}] [expr {$y-4}] \
410            -outline black -fill [_mater2color $mater]
411        set x [expr {$x-12}]
412        $c create text $x [expr {$y-7}] -anchor e \
413            -text $mater
414        set y [expr {$y-1.5*$lh}]
415    }
416
417    #
418    # If there's a <label> for this layer, then draw it.
419    #
420    if {"" != $_device} {
421        set label [$_device get $elem.about.label]
422        if {"" != $label} {
423            $c create text [expr {0.5*($x0p+$x1p)}] $y -anchor s \
424                -text $label
425        }
426    }
427}
428
429# ----------------------------------------------------------------------
430# USAGE: _mater2color <material>
431#
432# Used internally to convert a <material> name to the color that
433# should be used to represent it in the viewer.
434# ----------------------------------------------------------------------
435itcl::body Rappture::DeviceLayout1D::_mater2color {mater} {
436    set lib [Rappture::library standard]
437    set color [$lib get materials.($mater).color]
438    if {$color != ""} {
439        return $color
440    }
441    return gray
442}
443
444# ----------------------------------------------------------------------
445# CONFIGURATION OPTION: -font
446#
447# Controls the font used to all text on the layout, including
448# annotations.
449# ----------------------------------------------------------------------
450itcl::configbody Rappture::DeviceLayout1D::font {
451    $_dispatcher event -idle !layout
452}
453
454# ----------------------------------------------------------------------
455# CONFIGURATION OPTION: -device
456#
457# Set to the Rappture::Library object representing the device being
458# displayed in the viewer.  If set to "", the viewer is cleared to
459# display nothing.
460# ----------------------------------------------------------------------
461itcl::configbody Rappture::DeviceLayout1D::device {
462    if {$itk_option(-device) != ""} {
463        if {![Rappture::library isvalid $itk_option(-device)]} {
464            error "bad value \"$itk_option(-device)\": should be Rappture::Library"
465        }
466    }
467    set _device $itk_option(-device)
468    $_dispatcher event -idle !redraw
469}
470
471# ----------------------------------------------------------------------
472# CONFIGURATION OPTION: -devicesize
473#
474# Sets the height of the bar representing the device area.
475# ----------------------------------------------------------------------
476itcl::configbody Rappture::DeviceLayout1D::devicesize {
477    if {[catch {
478          winfo pixels $itk_component(hull) $itk_option(-devicesize)
479      } pixels]} {
480        error "bad screen distance \"$itk_option(-devicesize)\""
481    }
482    set _sizes(bar) $pixels
483    set _sizes(bar45) [expr {0.5*sqrt(2)*$pixels}]
484
485    set pixels [winfo pixels $itk_component(hull) $itk_option(-rightmargin)]
486    set _sizes(rm) [expr {($pixels > 0) ? $pixels : $_sizes(bar45)}]
487
488    $_dispatcher event -idle !layout
489}
490
491# ----------------------------------------------------------------------
492# CONFIGURATION OPTION: -deviceoutline
493#
494# Sets the outline color around the various slabs in the device.
495# ----------------------------------------------------------------------
496itcl::configbody Rappture::DeviceLayout1D::deviceoutline {
497    $_dispatcher event -idle !redraw
498}
499
500# ----------------------------------------------------------------------
501# CONFIGURATION OPTION: -leftmargin
502#
503# Sets the width of the left margin, a blank area along the left
504# side.  Setting the margin allows the device layout to line up
505# with a graph of internal fields.
506# ----------------------------------------------------------------------
507itcl::configbody Rappture::DeviceLayout1D::leftmargin {
508    if {[catch {
509          winfo pixels $itk_component(hull) $itk_option(-leftmargin)
510      } pixels]} {
511        error "bad screen distance \"$itk_option(-leftmargin)\""
512    }
513    set _sizes(lm) $pixels
514    $_dispatcher event -idle !layout
515    $_dispatcher event -idle !redraw
516}
517
518# ----------------------------------------------------------------------
519# CONFIGURATION OPTION: -rightmargin
520#
521# Sets the width of the right margin, a blank area along the right
522# side.  Setting the margin allows the device layout to line up
523# with a graph of internal fields.
524# ----------------------------------------------------------------------
525itcl::configbody Rappture::DeviceLayout1D::rightmargin {
526    if {[catch {
527          winfo pixels $itk_component(hull) $itk_option(-rightmargin)
528      } pixels]} {
529        error "bad screen distance \"$itk_option(-rightmargin)\""
530    }
531    set _sizes(rm) [expr {($pixels > 0) ? $pixels : $_sizes(bar45)}]
532    $_dispatcher event -idle !layout
533    $_dispatcher event -idle !redraw
534}
Note: See TracBrowser for help on using the repository browser.