[5029] | 1 | # -*- mode: tcl; indent-tabs-mode: nil -*- |
---|
[1] | 2 | #!/bin/sh |
---|
| 3 | # ---------------------------------------------------------------------- |
---|
| 4 | # USER INTERFACE DRIVER |
---|
| 5 | # |
---|
| 6 | # This driver program loads a tool description from a tool.xml file, |
---|
[11] | 7 | # and produces a user interface automatically to drive an application. |
---|
| 8 | # The user can set up input, click and button to launch a tool, and |
---|
| 9 | # browse through output. |
---|
[1] | 10 | # |
---|
| 11 | # RUN AS FOLLOWS: |
---|
[2080] | 12 | # wish main.tcl ?-tool <toolfile>? |
---|
[1] | 13 | # |
---|
[11] | 14 | # If the <toolfile> is not specified, it defaults to "tool.xml" in |
---|
| 15 | # the current working directory. |
---|
[1] | 16 | # |
---|
| 17 | # ====================================================================== |
---|
| 18 | # AUTHOR: Michael McLennan, Purdue University |
---|
[3177] | 19 | # Copyright (c) 2004-2012 HUBzero Foundation, LLC |
---|
[115] | 20 | # |
---|
| 21 | # See the file "license.terms" for information on usage and |
---|
| 22 | # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
[1] | 23 | # ====================================================================== |
---|
[2159] | 24 | |
---|
| 25 | # take the main window down for now, so we can avoid a flash on the screen |
---|
| 26 | wm withdraw . |
---|
| 27 | |
---|
[365] | 28 | package require Itcl |
---|
[2081] | 29 | package require Img |
---|
[1] | 30 | package require Rappture |
---|
[158] | 31 | package require RapptureGUI |
---|
[1] | 32 | |
---|
[22] | 33 | option add *MainWin.mode desktop startupFile |
---|
[1] | 34 | option add *MainWin.borderWidth 0 startupFile |
---|
[44] | 35 | option add *MainWin.anchor fill startupFile |
---|
[1] | 36 | |
---|
| 37 | # "web site" look |
---|
| 38 | option add *MainWin.bgScript { |
---|
| 39 | rectangle 0 0 200 <h> -outline "" -fill #5880BB |
---|
| 40 | rectangle 200 0 300 <h> -outline "" -fill #425F8B |
---|
| 41 | rectangle 300 0 <w> <h> -outline "" -fill #324565 |
---|
| 42 | } startupFile |
---|
| 43 | |
---|
| 44 | # "clean" look |
---|
| 45 | option add *MainWin.bgScript "" startupFile |
---|
| 46 | option add *MainWin.bgColor white startupFile |
---|
[9] | 47 | option add *Tooltip.background white |
---|
[11] | 48 | option add *Editor.background white |
---|
| 49 | option add *Gauge.textBackground white |
---|
| 50 | option add *TemperatureGauge.textBackground white |
---|
[13] | 51 | option add *Switch.textBackground white |
---|
[23] | 52 | option add *Progress.barColor #ffffcc |
---|
[413] | 53 | option add *Balloon.titleBackground #6666cc |
---|
| 54 | option add *Balloon.titleForeground white |
---|
[676] | 55 | option add *Balloon*Label.font -*-helvetica-medium-r-normal-*-12-* |
---|
| 56 | option add *Balloon*Radiobutton.font -*-helvetica-medium-r-normal-*-12-* |
---|
| 57 | option add *Balloon*Checkbutton.font -*-helvetica-medium-r-normal-*-12-* |
---|
[3024] | 58 | option add *ResultSelector.controlbarBackground #6666cc |
---|
| 59 | option add *ResultSelector.controlbarForeground white |
---|
| 60 | option add *ResultSelector.activeControlBackground #ccccff |
---|
| 61 | option add *ResultSelector.activeControlForeground black |
---|
[413] | 62 | option add *Radiodial.length 3i |
---|
[464] | 63 | option add *BugReport*banner*foreground white |
---|
| 64 | option add *BugReport*banner*background #a9a9a9 |
---|
| 65 | option add *BugReport*banner*highlightBackground #a9a9a9 |
---|
[676] | 66 | option add *BugReport*banner*font -*-helvetica-bold-r-normal-*-18-* |
---|
[1275] | 67 | option add *hubcntls*Button.padX 0 widgetDefault |
---|
| 68 | option add *hubcntls*Button.padY 0 widgetDefault |
---|
| 69 | option add *hubcntls*Button.relief flat widgetDefault |
---|
| 70 | option add *hubcntls*Button.overRelief raised widgetDefault |
---|
| 71 | option add *hubcntls*Button.borderWidth 1 widgetDefault |
---|
| 72 | option add *hubcntls*Button.font \ |
---|
| 73 | -*-helvetica-medium-r-normal-*-8-* widgetDefault |
---|
[1] | 74 | |
---|
[17] | 75 | switch $tcl_platform(platform) { |
---|
| 76 | unix - windows { |
---|
| 77 | event add <<PopupMenu>> <ButtonPress-3> |
---|
| 78 | } |
---|
| 79 | macintosh { |
---|
| 80 | event add <<PopupMenu>> <Control-ButtonPress-1> |
---|
| 81 | } |
---|
| 82 | } |
---|
| 83 | |
---|
[464] | 84 | # install a better bug handler |
---|
| 85 | Rappture::bugreport::install |
---|
[52] | 86 | # fix the "grab" command to support a stack of grab windows |
---|
| 87 | Rappture::grab::init |
---|
| 88 | |
---|
[1] | 89 | # |
---|
| 90 | # Process command line args to get the names of files to load... |
---|
| 91 | # |
---|
[11] | 92 | Rappture::getopts argv params { |
---|
| 93 | value -tool tool.xml |
---|
[1399] | 94 | list -load "" |
---|
[5121] | 95 | value -input "" |
---|
[5981] | 96 | value -simset "" |
---|
[1159] | 97 | value -nosim 0 |
---|
[1] | 98 | } |
---|
| 99 | |
---|
[3700] | 100 | proc ReadToolParameters { numTries } { |
---|
[5029] | 101 | incr numTries -1 |
---|
[3700] | 102 | if { $numTries < 0 } { |
---|
[5121] | 103 | return |
---|
[3700] | 104 | } |
---|
| 105 | global env |
---|
| 106 | set paramsFile $env(TOOL_PARAMETERS) |
---|
| 107 | if { ![file readable $paramsFile] } { |
---|
[5121] | 108 | after 500 ReadToolParmeters $numTries |
---|
| 109 | return |
---|
[3700] | 110 | } |
---|
[5029] | 111 | catch { |
---|
[3700] | 112 | set f [open $paramsFile "r"] |
---|
| 113 | set contents [read $f] |
---|
| 114 | close $f |
---|
[5029] | 115 | set pattern {^file\((.*)\):(.*)$} |
---|
[3700] | 116 | foreach line [split $contents "\n"] { |
---|
| 117 | if { [regexp $pattern $line match path rest] } { |
---|
| 118 | set ::Rappture::parameters($path) $rest |
---|
| 119 | } |
---|
| 120 | } |
---|
| 121 | } |
---|
| 122 | } |
---|
| 123 | |
---|
| 124 | if { [info exists env(TOOL_PARAMETERS)] } { |
---|
| 125 | ReadToolParameters 10 |
---|
| 126 | } |
---|
| 127 | |
---|
[1159] | 128 | set loadobjs {} |
---|
| 129 | foreach runfile $params(-load) { |
---|
| 130 | if {![file exists $runfile]} { |
---|
| 131 | puts stderr "can't find run: \"$runfile\"" |
---|
| 132 | exit 1 |
---|
| 133 | } |
---|
| 134 | set status [catch {Rappture::library $runfile} result] |
---|
| 135 | lappend loadobjs $result |
---|
| 136 | } |
---|
| 137 | |
---|
[5121] | 138 | set inputobj {} |
---|
| 139 | if {$params(-input) ne ""} { |
---|
| 140 | if {![file exists $params(-input)]} { |
---|
| 141 | puts stderr "can't find input file: \"$params(-input)\"" |
---|
| 142 | exit 1 |
---|
| 143 | } |
---|
| 144 | if {[catch {Rappture::library $params(-input)} result] == 0} { |
---|
| 145 | set inputobj $result |
---|
| 146 | } |
---|
| 147 | } |
---|
| 148 | |
---|
[1] | 149 | # open the XML file containing the tool parameters |
---|
[11] | 150 | if {![file exists $params(-tool)]} { |
---|
[1159] | 151 | # check to see if the user specified any run.xml files to load. |
---|
| 152 | # if so, we can use that as the tool.xml. if we can find where |
---|
| 153 | # the original application was installed using the xml tag |
---|
| 154 | # tool.version.application.directory(top), the user can |
---|
| 155 | # run new simulations, otherwise they can only revisualize the |
---|
| 156 | # run.xml files they are loading. |
---|
| 157 | set pseudotool "" |
---|
[5121] | 158 | if {[llength $loadobjs] == 0 && $inputobj eq ""} { |
---|
[1159] | 159 | puts stderr "can't find tool \"$params(-tool)\"" |
---|
| 160 | exit 1 |
---|
| 161 | } |
---|
[1206] | 162 | # search the loadfiles for the install location |
---|
| 163 | # we could just use run.xml files as tool.xml, but |
---|
| 164 | # if there are loaders or notes, they will still need |
---|
| 165 | # examples/ and docs/ dirs from the install location |
---|
[5121] | 166 | set check [concat $loadobjs $inputobj] |
---|
| 167 | foreach runobj $check { |
---|
[3656] | 168 | set tdir \ |
---|
| 169 | [string trim [$runobj get tool.version.application.directory(tool)]] |
---|
[1206] | 170 | if {[file isdirectory $tdir] && \ |
---|
| 171 | [file exists $tdir/tool.xml]} { |
---|
| 172 | set pseudotool $tdir/tool.xml |
---|
| 173 | break |
---|
[1159] | 174 | } |
---|
| 175 | } |
---|
| 176 | if {![file exists $pseudotool]} { |
---|
| 177 | # we didn't find a tool.xml file, |
---|
| 178 | # use info from a runfile to build gui |
---|
| 179 | # disable simulation, because no tool.xml |
---|
| 180 | set pseudotool [lindex $params(-load) 0] |
---|
| 181 | array set params [list -nosim true] |
---|
| 182 | } |
---|
| 183 | if {![file exists $pseudotool]} { |
---|
| 184 | puts stderr "can't find tool \"$params(-tool)\"" |
---|
| 185 | exit 1 |
---|
| 186 | } |
---|
| 187 | array set params [list -tool $pseudotool] |
---|
[1] | 188 | } |
---|
[1159] | 189 | |
---|
[11] | 190 | set xmlobj [Rappture::library $params(-tool)] |
---|
| 191 | |
---|
[3152] | 192 | set installdir [file normalize [file dirname $params(-tool)]] |
---|
| 193 | $xmlobj put tool.version.application.directory(tool) $installdir |
---|
[11] | 194 | set tool [Rappture::Tool ::#auto $xmlobj $installdir] |
---|
[1] | 195 | |
---|
| 196 | # ---------------------------------------------------------------------- |
---|
[728] | 197 | # CHECK JOB FAILURE REPORTING |
---|
| 198 | # |
---|
| 199 | # If this tool might fail when it launches jobs (i.e., Rappture |
---|
| 200 | # can't check some inputs, such as strings), then disable the |
---|
| 201 | # automatic ticket submission for job failures |
---|
| 202 | # ---------------------------------------------------------------------- |
---|
[3513] | 203 | set val [string trim [$tool xml get tool.reportJobFailures]] |
---|
[1547] | 204 | if { "" != $val} { |
---|
[728] | 205 | if {[catch {Rappture::bugreport::shouldReport jobfailures $val} result]} { |
---|
| 206 | puts stderr "WARNING for reportJobFailures: $result" |
---|
| 207 | } |
---|
| 208 | } |
---|
| 209 | |
---|
| 210 | # ---------------------------------------------------------------------- |
---|
[413] | 211 | # LOAD RESOURCE SETTINGS |
---|
| 212 | # |
---|
| 213 | # Try to load the $SESSIONDIR/resources file, which contains |
---|
| 214 | # middleware settings, such as the application name and the |
---|
| 215 | # filexfer settings. |
---|
| 216 | # ---------------------------------------------------------------------- |
---|
| 217 | Rappture::resources::load |
---|
| 218 | |
---|
| 219 | # ---------------------------------------------------------------------- |
---|
[3186] | 220 | # START LOGGING |
---|
| 221 | # |
---|
| 222 | # If the $RAPPTURE_LOG directory is set to a directory used for |
---|
| 223 | # logging, then open a log file and start logging. |
---|
| 224 | # ---------------------------------------------------------------------- |
---|
| 225 | Rappture::Logger::init |
---|
| 226 | |
---|
| 227 | # ---------------------------------------------------------------------- |
---|
[50] | 228 | # INITIALIZE THE DESKTOP CONNECTION |
---|
| 229 | # |
---|
| 230 | # If there's a SESSION ID, then this must be running within the |
---|
| 231 | # nanoHUB. Try to initialize the server handling the desktop |
---|
| 232 | # connection. |
---|
| 233 | # ---------------------------------------------------------------------- |
---|
| 234 | Rappture::filexfer::init |
---|
| 235 | |
---|
| 236 | # ---------------------------------------------------------------------- |
---|
[1] | 237 | # MAIN WINDOW |
---|
| 238 | # ---------------------------------------------------------------------- |
---|
| 239 | Rappture::MainWin .main -borderwidth 0 |
---|
[3647] | 240 | .main configure -title [string trim [$tool xml get tool.title]] |
---|
[11] | 241 | wm withdraw .main |
---|
[3187] | 242 | wm protocol .main WM_DELETE_WINDOW {Rappture::Logger::cleanup; exit} |
---|
[1] | 243 | |
---|
[56] | 244 | # if the FULLSCREEN variable is set, then nanoHUB wants us to go full screen |
---|
| 245 | if {[info exists env(FULLSCREEN)]} { |
---|
| 246 | .main configure -mode web |
---|
| 247 | } |
---|
| 248 | |
---|
[11] | 249 | # |
---|
| 250 | # The main window has a pager that acts as a notebook for the |
---|
| 251 | # various parts. This notebook as at least two pages--an input |
---|
| 252 | # page and an output (analysis) page. If there are <phase>'s |
---|
| 253 | # for input, then there are more pages in the notebook. |
---|
| 254 | # |
---|
[1] | 255 | set win [.main component app] |
---|
[52] | 256 | Rappture::Postern $win.postern |
---|
| 257 | pack $win.postern -side bottom -fill x |
---|
| 258 | |
---|
[11] | 259 | Rappture::Pager $win.pager |
---|
| 260 | pack $win.pager -expand yes -fill both |
---|
[1] | 261 | |
---|
[1275] | 262 | # |
---|
[6103] | 263 | # Add a place for menu button in the breadcrumbs area of this pager. |
---|
[1275] | 264 | # |
---|
[3656] | 265 | set app [string trim [$tool xml get tool.id]] |
---|
[1275] | 266 | set url [Rappture::Tool::resources -huburl] |
---|
[6103] | 267 | set crumbs [$win.pager component breadcrumbarea] |
---|
| 268 | frame $crumbs.hubcntls |
---|
| 269 | pack $crumbs.hubcntls -side right -padx 4 |
---|
[1275] | 270 | |
---|
[6103] | 271 | set m $crumbs.hubcntls.help.menu |
---|
| 272 | menubutton $crumbs.hubcntls.help \ |
---|
| 273 | -image [Rappture::icon hamburger_menu] \ |
---|
| 274 | -highlightthickness 0 \ |
---|
| 275 | -menu $m |
---|
| 276 | pack $crumbs.hubcntls.help -side top -anchor w |
---|
[5981] | 277 | |
---|
[1275] | 278 | # |
---|
| 279 | # Load up the components in the various phases of input. |
---|
| 280 | # |
---|
[11] | 281 | set phases [$tool xml children -type phase input] |
---|
| 282 | if {[llength $phases] > 0} { |
---|
| 283 | set plist "" |
---|
| 284 | foreach name $phases { |
---|
| 285 | lappend plist input.$name |
---|
[1] | 286 | } |
---|
[11] | 287 | set phases $plist |
---|
| 288 | } else { |
---|
| 289 | set phases input |
---|
| 290 | } |
---|
[1] | 291 | |
---|
[11] | 292 | foreach comp $phases { |
---|
[3513] | 293 | set title [string trim [$tool xml get $comp.about.label]] |
---|
[11] | 294 | if {$title == ""} { |
---|
| 295 | set title "Input #auto" |
---|
[1] | 296 | } |
---|
[11] | 297 | $win.pager insert end -name $comp -title $title |
---|
[1] | 298 | |
---|
[11] | 299 | # |
---|
| 300 | # Build the page of input controls for this phase. |
---|
| 301 | # |
---|
| 302 | set f [$win.pager page $comp] |
---|
| 303 | Rappture::Page $f.cntls $tool $comp |
---|
| 304 | pack $f.cntls -expand yes -fill both |
---|
[1] | 305 | } |
---|
| 306 | |
---|
[1268] | 307 | # let components (loaders) in the newly created pages settle |
---|
| 308 | update |
---|
| 309 | |
---|
[1] | 310 | # ---------------------------------------------------------------------- |
---|
| 311 | # OUTPUT AREA |
---|
| 312 | # ---------------------------------------------------------------------- |
---|
[1267] | 313 | |
---|
| 314 | # adjust the title of the page here. |
---|
| 315 | # to adjust the button text, look in analyzer.tcl |
---|
[3653] | 316 | set simtxt [string trim [$xmlobj get tool.action.label]] |
---|
[1143] | 317 | if {"" == $simtxt} { |
---|
| 318 | set simtxt "Simulate" |
---|
| 319 | } |
---|
| 320 | $win.pager insert end -name analyzer -title $simtxt |
---|
[11] | 321 | set f [$win.pager page analyzer] |
---|
[942] | 322 | $win.pager page analyzer -command [subst { |
---|
[1206] | 323 | if { !$params(-nosim) } { |
---|
| 324 | $win.pager busy yes |
---|
| 325 | update |
---|
| 326 | $f.analyze simulate -ifneeded |
---|
| 327 | $win.pager busy no |
---|
| 328 | } |
---|
[942] | 329 | }] |
---|
[1] | 330 | |
---|
[1159] | 331 | Rappture::Analyzer $f.analyze $tool -simcontrol auto -notebookpage about |
---|
[11] | 332 | pack $f.analyze -expand yes -fill both |
---|
| 333 | |
---|
[22] | 334 | $tool notify add analyzer * [list $f.analyze reset] |
---|
[6103] | 335 | $f.analyze buildMenu $m $url $app |
---|
[11] | 336 | |
---|
[6103] | 337 | |
---|
[1] | 338 | # ---------------------------------------------------------------------- |
---|
[11] | 339 | # Finalize the arrangement |
---|
[1] | 340 | # ---------------------------------------------------------------------- |
---|
[2977] | 341 | if {[llength [$win.pager page]] > 2} { |
---|
| 342 | # We have phases, so we shouldn't allow the "Simulate" button. |
---|
| 343 | # If it pops up, there are two ways to push simulate and duplicate |
---|
| 344 | # links for "About" and "Questions?". |
---|
| 345 | $f.analyze configure -simcontrol off |
---|
| 346 | } elseif {[llength [$win.pager page]] == 2} { |
---|
[3653] | 347 | set style [string trim [$xmlobj get tool.layout]] |
---|
[5468] | 348 | set screenw [winfo screenwidth .] |
---|
[9] | 349 | |
---|
[11] | 350 | update idletasks |
---|
| 351 | set w0 [winfo reqwidth [$win.pager page @0]] |
---|
| 352 | set w1 [winfo reqwidth [$win.pager page @1]] |
---|
[9] | 353 | |
---|
[1547] | 354 | if { $style != "wizard" } { |
---|
[2744] | 355 | # If only two windows and they're small enough, put them up |
---|
| 356 | # side-by-side |
---|
| 357 | if {$w0+$w1 < $screenw } { |
---|
| 358 | $win.pager configure -arrangement side-by-side |
---|
| 359 | $f.analyze configure -holdwindow [$win.pager page @0] |
---|
| 360 | } |
---|
[9] | 361 | } |
---|
[3513] | 362 | set type [string trim [$tool xml get tool.control]] |
---|
[1639] | 363 | if {$type == ""} { |
---|
[3513] | 364 | set type [string trim [$tool xml get tool.control.type]] |
---|
[1639] | 365 | } |
---|
[1657] | 366 | set arrangement [$win.pager cget -arrangement] |
---|
[1571] | 367 | if { $type == "" } { |
---|
[5029] | 368 | if { $arrangement != "side-by-side" } { |
---|
[1639] | 369 | set type auto |
---|
[1571] | 370 | } |
---|
| 371 | } |
---|
[5029] | 372 | if { $arrangement != "side-by-side" && |
---|
[2977] | 373 | ($type == "manual" || $type == "manual-resim" || |
---|
[5121] | 374 | $type == "auto" || $style == "wizard") } { |
---|
[2744] | 375 | # in "auto" mode, we don't need a simulate button |
---|
| 376 | $f.analyze configure -simcontrol off |
---|
[1547] | 377 | } else { |
---|
[2744] | 378 | # not in "auto" mode but side-by-side, we always need the button |
---|
| 379 | $f.analyze configure -simcontrol on |
---|
[1547] | 380 | } |
---|
[1] | 381 | } |
---|
[1159] | 382 | |
---|
| 383 | # load previous xml runfiles |
---|
[6310] | 384 | update |
---|
[5121] | 385 | if {[llength $params(-load)] > 0} { |
---|
[1159] | 386 | foreach runobj $loadobjs { |
---|
| 387 | $f.analyze load $runobj |
---|
| 388 | } |
---|
[5121] | 389 | # load the inputs for the very last run |
---|
| 390 | $tool load $runobj |
---|
| 391 | |
---|
[1206] | 392 | # don't need simulate button if we cannot simulate |
---|
[1159] | 393 | if {$params(-nosim)} { |
---|
| 394 | $f.analyze configure -simcontrol off |
---|
| 395 | } |
---|
[1206] | 396 | $f.analyze configure -notebookpage analyze |
---|
[6310] | 397 | $win.pager configure -nosim 1 |
---|
[1206] | 398 | $win.pager current analyzer |
---|
[6310] | 399 | $win.pager configure -nosim 0 |
---|
[5981] | 400 | } elseif {$params(-simset) ne ""} { |
---|
| 401 | $f.analyze reload $params(-simset) |
---|
[5121] | 402 | } elseif {$params(-input) ne ""} { |
---|
| 403 | $tool load $inputobj |
---|
[1159] | 404 | } |
---|
[5833] | 405 | |
---|
[5121] | 406 | # let components (loaders) settle after the newly loaded runs |
---|
| 407 | update |
---|
| 408 | |
---|
| 409 | foreach path [array names ::Rappture::parameters] { |
---|
[6231] | 410 | if { $path == "simset" } { |
---|
| 411 | continue; # Don't consider file(simset) |
---|
| 412 | } |
---|
[5121] | 413 | set fname $::Rappture::parameters($path) |
---|
[6231] | 414 | if { ![file exists $fname] } { |
---|
| 415 | puts stderr "WARNING: tool parameters file \"$fname\" doesn't exist" |
---|
| 416 | continue; # Can't find parameters file |
---|
| 417 | } |
---|
| 418 | if { ![file readable $fname] } { |
---|
| 419 | puts stderr "WARNING: can't read tool parameters file \"$fname\"" |
---|
| 420 | continue; # Can't read parameters file |
---|
[5121] | 421 | } |
---|
[6231] | 422 | set f [open $fname r] |
---|
| 423 | set contents [read $f] |
---|
| 424 | close $f |
---|
| 425 | |
---|
| 426 | set w [$tool widgetfor $path] |
---|
| 427 | if { $w == "" } { |
---|
| 428 | puts stderr "WARNING: can't find control for tool parameter: $path" |
---|
| 429 | continue; # Can't find rappture control for path |
---|
| 430 | } |
---|
| 431 | if {[catch {$w value [string trim $info]} result]} { |
---|
| 432 | puts stderr "WARNING: bad tool parameter value for \"$path\"" |
---|
| 433 | puts stderr " $result" |
---|
| 434 | } |
---|
[5121] | 435 | } |
---|
| 436 | |
---|
[11] | 437 | wm deiconify .main |
---|