source: trunk/gui/scripts/page.tcl @ 2943

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

experimental drawing entry enabled

File size: 9.8 KB
Line 
1# ----------------------------------------------------------------------
2#  COMPONENT: page - single page of widgets
3#
4#  This widget is a smart frame.  It takes the XML description for
5#  a Rappture <input> or an <input><phase> and decides how to lay
6#  out the widgets for the controls within it.  It uses various
7#  heuristics to achieve a decent layout under a variety of
8#  circumstances.
9# ======================================================================
10#  AUTHOR:  Michael McLennan, Purdue University
11#  Copyright (c) 2004-2005  Purdue Research Foundation
12#
13#  See the file "license.terms" for information on usage and
14#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15# ======================================================================
16package require Itk
17
18itcl::class Rappture::Page {
19    inherit itk::Widget
20
21    constructor {owner path args} { # defined below }
22
23    protected method _buildGroup {frame xmlobj path}
24    protected method _link {xmlobj path widget path2}
25
26    private variable _owner ""       ;# thing managing this page
27}
28                                                                               
29itk::usual Page {
30}
31
32# ----------------------------------------------------------------------
33# CONSTRUCTOR
34# ----------------------------------------------------------------------
35itcl::body Rappture::Page::constructor {owner path args} {
36    if {[catch {$owner isa Rappture::ControlOwner} valid] || !$valid} {
37        error "object \"$owner\" is not a Rappture::ControlOwner"
38    }
39    set _owner $owner
40    set xmlobj [$owner xml object]
41
42    set type [$xmlobj element -as type $path]
43    if {$type != "input" && $type != "phase"} {
44        error "bad path \"$path\" in $xmlobj: should be <input> or <input><phase>"
45    }
46
47    eval itk_initialize $args
48
49    # build all of the controls for this page
50    _buildGroup $itk_interior $xmlobj $path
51}
52
53# ----------------------------------------------------------------------
54# USAGE: _buildGroup <frame> <xmlobj> <path>
55#
56# Used internally when this page is being constructed to build the
57# controls within the group at the specified <path> in the <xmlobj>.
58# The controls are added to the given <frame>.
59# ----------------------------------------------------------------------
60itcl::body Rappture::Page::_buildGroup {frame xmlobj path} {
61    frame $frame.results
62    pack $frame.results -side right -fill y
63
64    set deveditor ""
65
66    #
67    # Scan through all remaining input elements.  If there is an
68    # ambient group, then add its children to the device editor,
69    # if there is one.
70    #
71    set num 0
72    set clist [$xmlobj children $path]
73    while {[llength $clist] > 0} {
74        set cname [lindex $clist 0]
75        set clist [lrange $clist 1 end]
76
77        set type [$xmlobj element -as type $path.$cname]
78        if {$type == "about"} {
79            continue
80        }
81        if {$type == "loader"} {
82            #
83            # Add <loader>'s at the top of the page.
84            #
85            if {![winfo exists $frame.loaders]} {
86                frame $frame.loaders
87                pack $frame.loaders -side top -fill x
88
89                frame $frame.loaders.sep -height 2 \
90                    -borderwidth 1 -relief sunken
91                pack $frame.loaders.sep -side bottom -fill x -pady 4
92            }
93            set w "$frame.loaders.l[incr num]"
94            Rappture::Controls $w $_owner
95            pack $w -fill x
96            $w insert end $path.$cname
97        } elseif {$type == "structure"} {
98            #
99            # Add <structure>'s as the central element of the page.
100            #
101            set w "$frame.device[incr num]"
102            Rappture::DeviceEditor ::$w $_owner@$path.$cname.current
103            pack $w -expand yes -fill both
104            $_owner widgetfor $path.$cname $w
105            bind $w <<Value>> [list $_owner changed $path.$cname]
106
107            if {"" == $deveditor} {
108                set deveditor $w
109            }
110
111            # if there's a default value, load it now
112            if {"" != [$xmlobj element -as type $path.$cname.current]} {
113                set elem $path.$cname.current
114            } else {
115                set elem $path.$cname.default
116            }
117            if {"" != [$xmlobj element -as type $elem]} {
118                set val [$xmlobj get $elem]
119                if {[string length $val] > 0} {
120                    $w value $val
121                    $xmlobj put $path.$cname.current $val
122                } else {
123                    set obj [$xmlobj element -as object $elem]
124                    $w value $obj
125                    $xmlobj put $path.$cname.current $obj
126                }
127            }
128
129            # if there's a link, then set up a callback to load from it
130            set link [$xmlobj get $path.$cname.link]
131            if {"" != $link} {
132                $_owner notify add $this $link \
133                    [itcl::code $this _link $xmlobj $link $w $path.$cname]
134            }
135        } elseif {$type == "drawing"} {
136            #
137            # Add <drawing>'s as the central element of the page.
138            #
139            set w "$frame.drawing[incr num]"
140            Rappture::DrawingEntry ::$w $_owner $path.$cname
141            pack $w -expand yes -fill both
142            $_owner widgetfor $path.$cname $w
143            bind $w <<Value>> [list $_owner changed $path.$cname]
144
145            # if there's a default value, load it now
146            if {"" != [$xmlobj element -as type $path.$cname.current]} {
147                set elem $path.$cname.current
148            } else {
149                set elem $path.$cname.default
150            }
151            if {"" != [$xmlobj element -as type $elem]} {
152                set val [$xmlobj get $elem]
153                if {[string length $val] > 0} {
154                    $w value $val
155                    $xmlobj put $path.$cname.current $val
156                } else {
157                    set obj [$xmlobj element -as object $elem]
158                    $w value $obj
159                    $xmlobj put $path.$cname.current $obj
160                }
161            }
162        } elseif {$type == "tool"} {
163            set service [Rappture::Service ::#auto $_owner $path.$cname]
164            #
165            # Scan through all extra inputs associated with this subtool
166            # and create corresponding inputs in the top-level tool.
167            # Then, add the input names to the list being processed here,
168            # so that we'll create the controls during subsequent passes
169            # through the loop.
170            #
171            set extra ""
172            foreach obj [$service input] {
173                set cname [$obj element]
174                $xmlobj copy $path.$cname from $obj ""
175                lappend extra $cname
176            }
177
178            #
179            # If there's a control for this service, then add it
180            # to the end of the extra controls added above.
181            #
182            foreach obj [$service control] {
183                set cname [$obj element]
184                $xmlobj copy $path.$cname from $obj ""
185                $xmlobj put $path.$cname.service $service
186                lappend extra $cname
187            }
188            if {[llength $extra] > 0} {
189                set clist [eval linsert [list $clist] 0 $extra]
190            }
191
192            #
193            # Scan through all outputs associated with this subtool
194            # and create any corresponding feedback widgets.
195            #
196            foreach obj [$service output] {
197                set cname [$obj element]
198                $xmlobj copy $cname from $obj ""
199
200                # pick a good size based on output type
201                set w $frame.results.result[incr num]
202                set type [$obj element -as type]
203                switch -- $type {
204                    number - integer - boolean - choice {
205                        Rappture::ResultViewer $w -width 0 -height 0
206                        pack $w -fill x -padx 4 -pady 4
207                    }
208                    default {
209                        Rappture::ResultViewer $w -width 4i -height 4i
210                        pack $w -expand yes -fill both -padx 4 -pady 4
211                    }
212                }
213                $service output for $obj $w
214            }
215        } elseif {$type == "current"} {
216            # Don't do anything.
217        } else {
218            # create a control panel, if necessary
219            if {![winfo exists $frame.cntls]} {
220                Rappture::Controls $frame.cntls $_owner
221                pack $frame.cntls -expand yes -fill both -pady 4
222            }
223
224            # if this is a group, then build that group
225            if {[$xmlobj element -as type $path.$cname] == "group"} {
226                if {[$xmlobj element -as id $path.$cname] == "ambient"
227                       && $deveditor != ""} {
228                    set w [$deveditor component top]
229                } else {
230                    if {[catch {$frame.cntls insert end $path.$cname} c]} {
231                        global errorInfo
232                        error $c "$c\n$errorInfo\n    (while building control for $path.$cname)"
233                    } else {
234                        set gentry [$frame.cntls control $c]
235                        set w [$gentry component inner]
236                    }
237                }
238                _buildGroup $w $xmlobj $path.$cname
239            } else {
240                if {[catch {$frame.cntls insert end $path.$cname} c]} {
241                    global errorInfo
242                    error $c "$c\n$errorInfo\n    (while building control for $path.$cname)"
243                }
244            }
245        }
246    }
247}
248
249itcl::body Rappture::Page::_link {xmlobj path w path2} {
250    if {"" != [$xmlobj element -as type $path.current]} {
251        set val [$xmlobj get $path.current]
252        if {[string length $val] > 0} {
253            $w value $val
254            $xmlobj put $path.current $val
255        } else {
256            set obj [$xmlobj element -as object $path.current]
257            $w value $obj
258            $xmlobj put $path.current $obj
259        }
260    }
261    $_owner changed $path2
262}
Note: See TracBrowser for help on using the repository browser.