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

Last change on this file since 23 was 23, checked in by mmc, 17 years ago

Fixed the output processing to recognize messages
tagged with the prefix =RAPPTURE-???=> as Rappture
directives. The following directives are now recognized:

=RAPPTURE-PROGRESS=>percent message
=RAPPTURE-ERROR=>message
=RAPPTURE-RUN=>runfile

Also, added the Rappture::exec command to make it easy
to exec a tool within a wrapper script and handle stdout
and stderr messages properly.

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