Changeset 13 for trunk/gui


Ignore:
Timestamp:
Jun 8, 2005 5:37:19 PM (16 years ago)
Author:
mmc
Message:

Many improvements, including a new energy level viewer
for Huckel-IV. Added support for a new <boolean> type.
Fixed the cloud/field stuff so that when a cloud is 1D,
it reverts to BLT vectors so it will plot correctly.
Fixed the install script to work better on Windows.

Location:
trunk/gui
Files:
4 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/gui/apps/driver

    r12 r13  
    2525package require Rappture
    2626
    27 option add *MainWin.mode desktop startupFile
     27option add *MainWin.mode web startupFile
    2828option add *MainWin.borderWidth 0 startupFile
    29 option add *MainWin.anchor center startupFile
     29option add *MainWin.anchor nw startupFile
    3030
    3131# "web site" look
     
    4343option add *Gauge.textBackground white
    4444option add *TemperatureGauge.textBackground white
     45option add *Switch.textBackground white
    4546
    4647#
  • trunk/gui/scripts/analyzer.tcl

    r12 r13  
    374374            }
    375375        }
    376         set label [$xmlobj get output.$item.about.label]
     376        set label [$xmlobj get output.$item.about.group]
     377        if {"" == $label} {
     378            set label [$xmlobj get output.$item.about.label]
     379        }
    377380
    378381        if {"" != $label} {
     
    384387    if {$haveresults} {
    385388        set size [$itk_component(resultset) size]
    386         set op [$itk_component(resultset) add $xmlobj]
     389        set index [$itk_component(resultset) add $xmlobj]
    387390
    388391        # add each result to a result viewer
    389392        foreach item [_reorder [$xmlobj children output]] {
    390             set label [$xmlobj get output.$item.about.label]
     393            set label [$xmlobj get output.$item.about.group]
     394            if {"" == $label} {
     395                set label [$xmlobj get output.$item.about.label]
     396            }
    391397
    392398            if {"" != $label} {
     
    400406                    $itk_component(resultselector) choices insert end \
    401407                        $name $label
    402 
    403                     #
    404                     # NOTE:
    405                     #
    406                     # If this result is showing up late in the game, then
    407                     # we must fill the resultviewer with a series of blank
    408                     # entries, so the latest result will align with (have
    409                     # the same index as) results in all other viewers.
    410                     #
    411                     for {set i 0} {$i < $size} {incr i} {
    412                         $page.rviewer add $xmlobj ""
    413                     }
    414408                }
    415409
    416410                # add/replace the latest result into this viewer
    417411                set page $_label2page($label)
    418                 eval $page.rviewer $op [list $xmlobj output.$item]
     412
     413                if {![info exists reset($page)]} {
     414                    $page.rviewer clear $index
     415                    set reset($page) 1
     416                }
     417                $page.rviewer add $index $xmlobj output.$item
    419418            }
    420419        }
     
    432431    set first [$itk_component(resultselector) choices get -label 0]
    433432    if {$first != ""} {
    434         $itk_component(resultpages) current page1
     433        set page [$itk_component(resultselector) choices get -value 0]
     434        $itk_component(resultpages) current $page
    435435        $itk_component(resultselector) value $first
    436436    }
     
    448448    set _runs ""
    449449
     450    $itk_component(resultset) clear
     451    $itk_component(results) fraction end 0.1
     452
    450453    foreach label [array names _label2page] {
    451454        set page $_label2page($label)
    452455        $page.rviewer clear
    453456    }
    454 
    455     $itk_component(resultset) clear
    456     $itk_component(results) fraction end 0.1
     457    $itk_component(resultselector) value ""
     458    $itk_component(resultselector) choices delete 0 end
     459    catch {unset _label2page}
     460    set _plotlist ""
     461
     462    #
     463    # HACK ALERT!!
     464    # The following statement should be in place, but it causes
     465    # vtk to dump core.  Leave it out until we can fix the core dump.
     466    # In the mean time, we leak memory...
     467    #
     468    #$itk_component(resultpages) delete -all
     469    #set _pages 0
    457470
    458471    _simState on
     
    481494
    482495# ----------------------------------------------------------------------
    483 # USAGE: _reorder
     496# USAGE: _reorder <compList>
    484497#
    485498# Used internally to change the order of a series of output components
     
    519532    upvar $cntVar counters
    520533
     534    set group [$xmlobj get $path.about.group]
    521535    set label [$xmlobj get $path.about.label]
    522536    if {"" == $label} {
    523537        # no label -- make one up using the title specified
    524         if {![info exists counters($title)]} {
    525             set counters($title) 1
     538        if {![info exists counters($group-$title)]} {
     539            set counters($group-$title) 1
    526540            set label $title
    527541        } else {
    528             set label "$title #[incr counters($title)]"
     542            set label "$title (#[incr counters($group-$title)])"
    529543        }
    530544        $xmlobj put $path.about.label $label
    531545    } else {
    532546        # handle the case of two identical labels in <output>
    533         if {![info exists counters($label)]} {
    534             set counters($label) 1
     547        if {![info exists counters($group-$label)]} {
     548            set counters($group-$label) 1
    535549        } else {
    536             set label "$label #[incr counters($label)]"
     550            set label "$label (#[incr counters($group-$label)])"
    537551            $xmlobj put $path.about.label $label
    538552        }
     
    550564    set page [$itk_component(resultselector) value]
    551565    set page [$itk_component(resultselector) translate $page]
    552     $itk_component(resultpages) current $page
    553 
    554     set f [$itk_component(resultpages) page $page]
    555     $f.rviewer plot clear
    556     eval $f.rviewer plot add $_plotlist
     566    if {$page != ""} {
     567        $itk_component(resultpages) current $page
     568
     569        set f [$itk_component(resultpages) page $page]
     570        $f.rviewer plot clear
     571        eval $f.rviewer plot add $_plotlist
     572    }
    557573}
    558574
  • trunk/gui/scripts/contourresult.tcl

    r11 r13  
    5757
    5858    public method add {dataobj {settings ""}}
     59    public method get {}
    5960    public method delete {args}
    6061    public method scale {args}
     
    108109            -command [itcl::code $this _zoom reset]
    109110    } {
     111        usual
    110112        ignore -borderwidth
    111113        rename -highlightbackground -controlbackground controlBackground Background
     
    120122            -command [itcl::code $this _zoom in]
    121123    } {
     124        usual
    122125        ignore -borderwidth
    123126        rename -highlightbackground -controlbackground controlBackground Background
     
    132135            -command [itcl::code $this _zoom out]
    133136    } {
     137        usual
    134138        ignore -borderwidth
    135139        rename -highlightbackground -controlbackground controlBackground Background
     
    201205# Clients use this to add a data object to the plot.  The optional
    202206# <settings> are used to configure the plot.  Allowed settings are
    203 # -color, -width, and -raise.
     207# -color, -brightness, -width, -linestyle, and -raise.
    204208# ----------------------------------------------------------------------
    205209itcl::body Rappture::ContourResult::add {dataobj {settings ""}} {
     
    207211        -color black
    208212        -width 1
     213        -linestyle solid
     214        -brightness 0
    209215        -raise 0
    210216    }
     
    226232        after idle [itcl::code $this _rebuild]
    227233    }
     234}
     235
     236# ----------------------------------------------------------------------
     237# USAGE: get
     238#
     239# Clients use this to query the list of objects being plotted, in
     240# order from bottom to top of this result.
     241# ----------------------------------------------------------------------
     242itcl::body Rappture::ContourResult::get {} {
     243    # put the dataobj list in order according to -raise options
     244    set dlist $_dlist
     245    foreach obj $dlist {
     246        if {[info exists _obj2raise($obj)] && $_obj2raise($obj)} {
     247            set i [lsearch -exact $dlist $obj]
     248            if {$i >= 0} {
     249                set dlist [lreplace $dlist $i $i]
     250                lappend dlist $obj
     251            }
     252        }
     253    }
     254    return $dlist
    228255}
    229256
     
    318345    }
    319346
    320     # put the dataobj list in order according to -raise options
    321     set dlist $_dlist
    322     foreach obj $dlist {
    323         if {[info exists _obj2raise($obj)] && $_obj2raise($obj)} {
    324             set i [lsearch -exact $dlist $obj]
    325             if {$i >= 0} {
    326                 set dlist [lreplace $dlist $i $i]
    327                 lappend dlist $obj
    328             }
    329         }
    330     }
    331 
    332347    # scan through all data objects and build the contours
    333348    set _counter 0
    334     foreach dataobj $dlist {
     349    foreach dataobj [get] {
    335350        foreach comp [$dataobj components] {
    336351            set pd $this-polydata$_counter
     
    501516        }
    502517        drag {
    503             set w [winfo width $itk_component(plot)]
    504             set h [winfo height $itk_component(plot)]
    505             set dx [expr {double($x-$_click(x))/$w}]
    506             set dy [expr {double($y-$_click(y))/$h}]
    507             foreach actor $_actors($this-ren) {
    508                 foreach {ax ay az} [$actor GetPosition] break
    509                 $actor SetPosition [expr {$ax+$dx}] [expr {$ay-$dy}] 0
     518            if {[array size _click] == 0} {
     519                _move click $x $y
     520            } else {
     521                set w [winfo width $itk_component(plot)]
     522                set h [winfo height $itk_component(plot)]
     523                set dx [expr {double($x-$_click(x))/$w}]
     524                set dy [expr {double($y-$_click(y))/$h}]
     525                foreach actor $_actors($this-ren) {
     526                    foreach {ax ay az} [$actor GetPosition] break
     527                    $actor SetPosition [expr {$ax+$dx}] [expr {$ay-$dy}] 0
     528                }
     529                $this-renWin Render
     530
     531                set _click(x) $x
     532                set _click(y) $y
    510533            }
    511             $this-renWin Render
    512 
    513             set _click(x) $x
    514             set _click(y) $y
    515534        }
    516535        release {
    517536            _move drag $x $y
    518537            blt::busy configure $itk_component(area) -cursor left_ptr
     538            catch {unset _click}
    519539        }
    520540        default {
  • trunk/gui/scripts/controls.tcl

    r11 r13  
    2121    itk_option define -padding padding Padding 0
    2222
    23     constructor {tool args} { # defined below }
     23    constructor {owner args} { # defined below }
    2424
    2525    public method insert {pos xmlobj path}
     
    3232    protected method _formatLabel {str}
    3333
    34     private variable _tool ""        ;# controls belong to this tool
     34    private variable _owner ""       ;# controls belong to this owner
    3535    private variable _counter 0      ;# counter for control names
    3636    private variable _dispatcher ""  ;# dispatcher for !events
     
    4545# CONSTRUCTOR
    4646# ----------------------------------------------------------------------
    47 itcl::body Rappture::Controls::constructor {tool args} {
     47itcl::body Rappture::Controls::constructor {owner args} {
    4848    Rappture::dispatcher _dispatcher
    4949    $_dispatcher register !layout
    5050    $_dispatcher dispatch $this !layout "[itcl::code $this _layout]; list"
    5151
    52     set _tool $tool
     52    set _owner $owner
    5353
    5454    eval itk_initialize $args
     
    9191        }
    9292        loader {
    93             Rappture::Loader $w $xmlobj $path -tool $_tool
     93            Rappture::Loader $w $xmlobj $path -tool [$_owner tool]
    9494            bind $w <<Value>> [itcl::code $this _controlChanged $path]
    9595        }
     
    9898            bind $w <<Value>> [itcl::code $this _controlChanged $path]
    9999        }
     100        boolean {
     101            Rappture::BooleanEntry $w $xmlobj $path
     102            bind $w <<Value>> [itcl::code $this _controlChanged $path]
     103        }
    100104        string {
    101105            Rappture::TextEntry $w $xmlobj $path
     
    106110        }
    107111    }
    108     $_tool widgetfor $path $w
     112    $_owner widgetfor $path $w
    109113
    110114    # make a label for this control
     
    289293# ----------------------------------------------------------------------
    290294itcl::body Rappture::Controls::_controlChanged {path} {
    291     if {"" != $_tool} {
    292         $_tool changed $path
     295    if {"" != $_owner} {
     296        $_owner changed $path
    293297    }
    294298}
  • trunk/gui/scripts/curve.tcl

    r11 r13  
    148148itcl::body Rappture::Curve::hints {{keyword ""}} {
    149149    foreach {key path} {
    150         label   label
    151         color   color
    152         color   style
     150        group   about.group
     151        label   about.label
     152        color   about.color
     153        style   about.style
    153154        xlabel  xaxis.label
    154155        xunits  xaxis.units
     
    173174    }
    174175
     176    if {[info exists hints(group)] && [info exists hints(label)]} {
     177        # pop-up help for each curve
     178        set hints(tooltip) $hints(label)
     179    }
     180
    175181    if {$keyword != ""} {
    176182        if {[info exists hints($keyword)]} {
  • trunk/gui/scripts/deviceEditor.tcl

    r11 r13  
    1919    inherit itk::Widget
    2020
    21     constructor {tool args} { # defined below }
     21    constructor {owner args} { # defined below }
    2222
    2323    public method value {args}
     24
     25    # used for syncing embedded widgets
     26    public method widgetfor {path {widget ""}}
     27    public method changed {path}
     28    public method sync {}
     29    public method tool {}
    2430
    2531    protected method _redraw {}
    2632    protected method _type {xmlobj}
    2733
    28     private variable _tool ""        ;# tool containing this editor
     34    private variable _owner ""       ;# owner containing this editor
    2935    private variable _xmlobj ""      ;# XML <structure> object
     36    private variable _path2widget    ;# maps path => widget in this editor
    3037}
    3138                                                                               
     
    3643# CONSTRUCTOR
    3744# ----------------------------------------------------------------------
    38 itcl::body Rappture::DeviceEditor::constructor {tool args} {
    39     set _tool $tool
     45itcl::body Rappture::DeviceEditor::constructor {owner args} {
     46    set _owner $owner
    4047
    4148    itk_option add hull.width hull.height
     
    9299        event generate $itk_component(hull) <<Value>>
    93100
    94     } elseif {[llength $args] != 0} {
     101    } elseif {[llength $args] == 0} {
     102        sync  ;# querying -- must sync controls with the value
     103    } else {
    95104        error "wrong # args: should be \"value ?-check? ?newval?\""
    96105    }
    97106    return $_xmlobj
     107}
     108
     109# ----------------------------------------------------------------------
     110# USAGE: widgetfor <path> ?<widget>?
     111#
     112# Used by embedded widgets such as a Controls panel to register the
     113# various controls associated with this page.  That way, this editor
     114# knows what widgets to look at when syncing itself to the underlying
     115# XML data.
     116# ----------------------------------------------------------------------
     117itcl::body Rappture::DeviceEditor::widgetfor {path {widget ""}} {
     118    # if this is a query operation, then look for the path
     119    if {"" == $widget} {
     120        if {[info exists _path2widget($path)]} {
     121            return $_path2widget($path)
     122        }
     123        return ""
     124    }
     125
     126    # otherwise, associate the path with the given widget
     127    if {[info exists _path2widget($path)]} {
     128        error "$path already associated with widget $_path2widget($path)"
     129    }
     130    set _path2widget($path) $widget
     131}
     132
     133# ----------------------------------------------------------------------
     134# USAGE: changed <path>
     135#
     136# Invoked automatically by the various widgets associated with this
     137# editor whenever their value changes.  If this tool has a -analyzer,
     138# then it is notified that input has changed, so it can reset itself
     139# for a new analysis.
     140# ----------------------------------------------------------------------
     141itcl::body Rappture::DeviceEditor::changed {path} {
     142    if {"" != $_owner} {
     143        $_owner changed $path
     144    }
     145}
     146
     147# ----------------------------------------------------------------------
     148# USAGE: sync
     149#
     150# Used by descendents such as a Controls panel to register the
     151# various controls associated with this page.  That way, this Tool
     152# knows what widgets to look at when syncing itself to the underlying
     153# XML data.
     154# ----------------------------------------------------------------------
     155itcl::body Rappture::DeviceEditor::sync {} {
     156    foreach path [array names _path2widget] {
     157        $_xmlobj put $path.current [$_path2widget($path) value]
     158    }
     159}
     160
     161# ----------------------------------------------------------------------
     162# USAGE: tool
     163#
     164# Clients use this to figure out which tool is associated with
     165# this object.  Returns the tool containing this editor.
     166# ----------------------------------------------------------------------
     167itcl::body Rappture::Tool::tool {} {
     168    return [$_owner tool]
    98169}
    99170
     
    111182            if {[catch {$itk_component(editors) page molecule} p]} {
    112183                set p [$itk_component(editors) insert end molecule]
    113                 Rappture::MoleculeViewer $p.mol $_tool
     184                Rappture::MoleculeViewer $p.mol $this
    114185                pack $p.mol -expand yes -fill both
    115186            }
     
    120191            if {[catch {$itk_component(editors) page device1D} p]} {
    121192                set p [$itk_component(editors) insert end device1D]
    122                 Rappture::DeviceViewer1D $p.dev $_tool
     193                Rappture::DeviceViewer1D $p.dev $this
    123194                pack $p.dev -expand yes -fill both
    124195            }
  • trunk/gui/scripts/energyLevels.tcl

    r11 r13  
    1717option add *EnergyLevels.width 4i widgetDefault
    1818option add *EnergyLevels.height 4i widgetDefault
    19 option add *EnergyLevels.levelColor blue widgetDefault
    20 option add *EnergyLevels.levelTextForeground blue widgetDefault
    21 option add *EnergyLevels.levelTextBackground #d9d9d9 widgetDefault
     19option add *EnergyLevels.padding 4 widgetDefault
     20option add *EnergyLevels.controlBackground gray widgetDefault
     21option add *EnergyLevels.shadeColor gray widgetDefault
     22option add *EnergyLevels.levelColor black widgetDefault
     23option add *EnergyLevels.levelTextForeground black widgetDefault
     24option add *EnergyLevels.levelTextBackground white widgetDefault
    2225
    2326option add *EnergyLevels.font \
    2427    -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
    2528
    26 option add *EnergyLevels.detailFont \
    27     -*-helvetica-medium-r-normal-*-*-100-* widgetDefault
     29blt::bitmap define EnergyLevels-reset {
     30#define reset_width 12
     31#define reset_height 12
     32static unsigned char reset_bits[] = {
     33   0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02,
     34   0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00};
     35}
     36
     37blt::bitmap define EnergyLevels-zoomin {
     38#define zoomin_width 12
     39#define zoomin_height 12
     40static unsigned char zoomin_bits[] = {
     41   0x7c, 0x00, 0x82, 0x00, 0x11, 0x01, 0x11, 0x01, 0x7d, 0x01, 0x11, 0x01,
     42   0x11, 0x01, 0x82, 0x03, 0xfc, 0x07, 0x80, 0x0f, 0x00, 0x0f, 0x00, 0x06};
     43}
     44
     45blt::bitmap define EnergyLevels-zoomout {
     46#define zoomout_width 12
     47#define zoomout_height 12
     48static unsigned char zoomout_bits[] = {
     49   0x7c, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x7d, 0x01, 0x01, 0x01,
     50   0x01, 0x01, 0x82, 0x03, 0xfc, 0x07, 0x80, 0x0f, 0x00, 0x0f, 0x00, 0x06};
     51}
     52
     53blt::bitmap define EnergyLevels-rdiag {
     54#define rdiag_width 8
     55#define rdiag_height 8
     56static unsigned char rdiag_bits[] = {
     57   0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99, 0xcc};
     58}
     59
    2860
    2961itcl::class Rappture::EnergyLevels {
    3062    inherit itk::Widget
    3163
    32     itk_option define -layout layout Layout ""
    33     itk_option define -output output Output ""
     64    itk_option define -padding padding Padding 0
     65    itk_option define -shadecolor shadeColor ShadeColor ""
    3466    itk_option define -levelcolor levelColor LevelColor ""
    3567    itk_option define -leveltextforeground levelTextForeground Foreground ""
     
    3769
    3870    constructor {args} { # defined below }
    39     destructor { # defined below }
    40 
    41     protected method _render {}
    42     protected method _adjust {what val}
    43     protected method _getColumn {name}
    44     protected method _getUnits {name}
    45     protected method _getMidPt {elist pos}
     71
     72    public proc columns {table}
     73
     74    public method add {table {settings ""}}
     75    public method delete {args}
     76    public method scale {args}
     77
     78    protected method _redraw {{what all}}
     79    protected method _zoom {option args}
     80    protected method _view {midE delE}
     81    protected method _hilite {option args}
     82    protected method _getLayout {}
     83
     84    private variable _dispatcher "" ;# dispatcher for !events
     85
     86    private variable _dlist ""     ;# list of data objects
     87    private variable _dobj2color   ;# maps data obj => color option
     88    private variable _dobj2raise   ;# maps data obj => raise option
     89    private variable _dobj2cols    ;# maps data obj => column names
     90    private variable _emin ""      ;# autoscale min for energy
     91    private variable _emax ""      ;# autoscale max for energy
     92    private variable _eviewmin ""  ;# min for "zoom" view
     93    private variable _eviewmax ""  ;# max for "zoom" view
     94    private variable _edefmin ""   ;# min for default "zoom" view
     95    private variable _edefmax ""   ;# max for default "zoom" view
     96    private variable _ehomo ""     ;# energy of HOMO level in topmost dataset
     97    private variable _elumo ""     ;# energy of LUMO level in topmost dataset
     98    private variable _hilite ""    ;# item currently highlighted
    4699}
    47100
    48101itk::usual EnergyLevels {
     102    keep -background -foreground -cursor -font
    49103}
    50104
     
    53107# ----------------------------------------------------------------------
    54108itcl::body Rappture::EnergyLevels::constructor {args} {
     109    Rappture::dispatcher _dispatcher
     110    $_dispatcher register !redraw
     111    $_dispatcher dispatch $this !redraw "[itcl::code $this _redraw all]; list"
     112    $_dispatcher register !zoom
     113    $_dispatcher dispatch $this !zoom "[itcl::code $this _redraw zoom]; list"
     114
    55115    itk_option add hull.width hull.height
    56116    pack propagate $itk_component(hull) no
    57117
     118    itk_component add controls {
     119        frame $itk_interior.cntls
     120    } {
     121        usual
     122        rename -background -controlbackground controlBackground Background
     123    }
     124    pack $itk_component(controls) -side right -fill y
     125
     126    itk_component add reset {
     127        button $itk_component(controls).reset \
     128            -borderwidth 1 -padx 1 -pady 1 \
     129            -bitmap EnergyLevels-reset \
     130            -command [itcl::code $this _zoom reset]
     131    } {
     132        usual
     133        ignore -borderwidth
     134        rename -highlightbackground -controlbackground controlBackground Background }
     135    pack $itk_component(reset) -padx 4 -pady 4
     136    Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level"
     137
     138    itk_component add zoomin {
     139        button $itk_component(controls).zin \
     140            -borderwidth 1 -padx 1 -pady 1 \
     141            -bitmap EnergyLevels-zoomin \
     142            -command [itcl::code $this _zoom in]
     143    } {
     144        usual
     145        ignore -borderwidth
     146        rename -highlightbackground -controlbackground controlBackground Background
     147    }
     148    pack $itk_component(zoomin) -padx 4 -pady 4
     149    Rappture::Tooltip::for $itk_component(zoomin) "Zoom in"
     150
     151    itk_component add zoomout {
     152        button $itk_component(controls).zout \
     153            -borderwidth 1 -padx 1 -pady 1 \
     154            -bitmap EnergyLevels-zoomout \
     155            -command [itcl::code $this _zoom out]
     156    } {
     157        usual
     158        ignore -borderwidth
     159        rename -highlightbackground -controlbackground controlBackground Background
     160    }
     161    pack $itk_component(zoomout) -padx 4 -pady 4
     162    Rappture::Tooltip::for $itk_component(zoomout) "Zoom out"
     163
    58164    #
    59165    # Add label for the title.
     
    64170    pack $itk_component(title) -side top
    65171
    66 
    67     itk_component add cntls {
    68         frame $itk_interior.cntls
    69     }
    70     pack $itk_component(cntls) -side right -fill y
    71     grid rowconfigure $itk_component(cntls) 0 -weight 1
    72     grid rowconfigure $itk_component(cntls) 1 -minsize 10
    73     grid rowconfigure $itk_component(cntls) 2 -weight 1
    74 
    75     #
    76     # Add MORE/FEWER levels control for TOP of graph
    77     #
    78     itk_component add upperE {
    79         frame $itk_component(cntls).upperE
    80     }
    81 
    82     itk_component add upperEmore {
    83         label $itk_component(upperE).morel -text "More"
     172    #
     173    # Add graph showing levels
     174    #
     175    itk_component add graph {
     176        canvas $itk_interior.graph -highlightthickness 0
    84177    } {
    85178        usual
    86         rename -font -detailfont detailFont Font
    87     }
    88     pack $itk_component(upperEmore) -side top
    89 
    90     itk_component add upperEfewer {
    91         label $itk_component(upperE).fewerl -text "Fewer"
    92     } {
    93         usual
    94         rename -font -detailfont detailFont Font
    95     }
    96     pack $itk_component(upperEfewer) -side bottom
    97 
    98     itk_component add upperEcntl {
    99         scale $itk_component(upperE).cntl -orient vertical -showvalue 0 \
    100             -command [itcl::code $this _adjust upper]
    101     }
    102     pack $itk_component(upperEcntl) -side top -fill y
    103 
    104     #
    105     # Add MORE/FEWER levels control for BOTTOM of graph
    106     #
    107     itk_component add lowerE {
    108         frame $itk_component(cntls).lowerE
    109     }
    110 
    111     itk_component add lowerEmore {
    112         label $itk_component(lowerE).morel -text "More"
    113     } {
    114         usual
    115         rename -font -detailfont detailFont Font
    116     }
    117     pack $itk_component(lowerEmore) -side bottom
    118 
    119     itk_component add lowerEfewer {
    120         label $itk_component(lowerE).fewerl -text "Fewer"
    121     } {
    122         usual
    123         rename -font -detailfont detailFont Font
    124     }
    125     pack $itk_component(lowerEfewer) -side top
    126 
    127     itk_component add lowerEcntl {
    128         scale $itk_component(lowerE).cntl -orient vertical -showvalue 0 \
    129             -command [itcl::code $this _adjust lower]
    130     }
    131     pack $itk_component(lowerEcntl) -side top -fill y
    132 
    133     #
    134     # Add graph showing levels
    135     #
    136     itk_component add graph {
    137         blt::graph $itk_interior.graph \
    138             -highlightthickness 0 -plotpadx 0 -plotpady 0 \
    139             -width 3i -height 3i
    140     } {
    141         keep -background -foreground -cursor -font
     179        ignore -highlightthickness
    142180    }
    143181    pack $itk_component(graph) -expand yes -fill both
    144     $itk_component(graph) legend configure -hide yes
     182
     183    bind $itk_component(graph) <Configure> \
     184        [list $_dispatcher event -idle !redraw]
     185
     186    bind $itk_component(graph) <ButtonPress-1> \
     187        [itcl::code $this _zoom at %x %y]
     188    bind $itk_component(graph) <B1-Motion> \
     189        [itcl::code $this _zoom at %x %y]
     190
     191    bind $itk_component(graph) <Motion> \
     192        [itcl::code $this _hilite brush %x %y]
     193    bind $itk_component(graph) <Leave> \
     194        [itcl::code $this _hilite hide]
     195
     196    bind $itk_component(graph) <KeyPress-Up> \
     197        [itcl::code $this _zoom nudge 1]
     198    bind $itk_component(graph) <KeyPress-Right> \
     199        [itcl::code $this _zoom nudge 1]
     200    bind $itk_component(graph) <KeyPress-plus> \
     201        [itcl::code $this _zoom nudge 1]
     202
     203    bind $itk_component(graph) <KeyPress-Down> \
     204        [itcl::code $this _zoom nudge -1]
     205    bind $itk_component(graph) <KeyPress-Left> \
     206        [itcl::code $this _zoom nudge -1]
     207    bind $itk_component(graph) <KeyPress-minus> \
     208        [itcl::code $this _zoom nudge -1]
    145209
    146210    eval itk_initialize $args
     
    148212
    149213# ----------------------------------------------------------------------
    150 # DESTRUCTOR
    151 # ----------------------------------------------------------------------
    152 itcl::body Rappture::EnergyLevels::destructor {} {
    153 }
    154 
    155 # ----------------------------------------------------------------------
    156 # USAGE: _render
     214# USAGE: columns <table>
     215#
     216# Clients use this to scan a <table> XML object and see if it contains
     217# columns for energy levels.  If so, it returns a list of two column
     218# names: {labels energies}.
     219# ----------------------------------------------------------------------
     220itcl::body Rappture::EnergyLevels::columns {dataobj} {
     221    set names [$dataobj columns -component]
     222    set epos [lsearch -exact $names column(levels)]
     223    if {$epos >= 0} {
     224        set units [$dataobj columns -units $epos]
     225        if {![string match energy* [Rappture::Units::description $units]]} {
     226            set epos -1
     227        }
     228    }
     229
     230    # can't find column named "levels"? then look for column with energies
     231    if {$epos < 0} {
     232        set index 0
     233        foreach units [$dataobj columns -units] {
     234            if {[string match energy* [Rappture::Units::description $units]]} {
     235                if {$epos >= 0} {
     236                    # more than one energy column -- bail out
     237                    set epos -1
     238                    break
     239                }
     240                set epos $index
     241            }
     242            incr index
     243        }
     244    }
     245
     246    # look for a column with labels
     247    set lpos -1
     248    set index 0
     249    foreach units [$dataobj columns -units] {
     250        if {"" == $units} {
     251            set vals [$dataobj values -column $index]
     252            if {[regexp {(^|[[:space:]])HOMO([[:space:]]|$)} $vals]} {
     253                if {$lpos >= 0} {
     254                    # more than one labels column -- bail out
     255                    set lpos -1
     256                    break
     257                }
     258                set lpos $index
     259            }
     260        }
     261        incr index
     262    }
     263
     264    if {$epos >= 0 || $lpos >= 0} {
     265        return [list [lindex $names $lpos] [lindex $names $epos]]
     266    }
     267    return ""
     268}
     269
     270# ----------------------------------------------------------------------
     271# USAGE: add <dataobj> ?<settings>?
     272#
     273# Clients use this to add a data object to the plot.  The optional
     274# <settings> are used to configure the plot.  Allowed settings are
     275# -color, -brightness, -width, -linestyle and -raise.
     276# ----------------------------------------------------------------------
     277itcl::body Rappture::EnergyLevels::add {dataobj {settings ""}} {
     278    #
     279    # Make sure this table contains energy levels.
     280    #
     281    set cols [Rappture::EnergyLevels::columns $dataobj]
     282    if {"" == $cols} {
     283        error "table \"$dataobj\" does not contain energy levels"
     284    }
     285
     286    #
     287    # Scan through the settings and resolve all values.
     288    #
     289    array set params {
     290        -color black
     291        -brightness 0
     292        -width 1
     293        -raise 0
     294        -linestyle solid
     295    }
     296    foreach {opt val} $settings {
     297        if {![info exists params($opt)]} {
     298            error "bad setting \"$opt\": should be [join [lsort [array names params]] {, }]"
     299        }
     300        set params($opt) $val
     301    }
     302
     303    # convert -linestyle to BLT -dashes
     304    switch -- $params(-linestyle) {
     305        dashed { set params(-linestyle) {4 4} }
     306        dotted { set params(-linestyle) {2 4} }
     307        default { set params(-linestyle) {} }
     308    }
     309
     310    # if -brightness is set, then update the color
     311    if {$params(-brightness) != 0} {
     312        set params(-color) [Rappture::color::brightness \
     313            $params(-color) $params(-brightness)]
     314    }
     315
     316    set pos [lsearch -exact $dataobj $_dlist]
     317    if {$pos < 0} {
     318        lappend _dlist $dataobj
     319        set _dobj2color($dataobj) $params(-color)
     320        set _dobj2raise($dataobj) $params(-raise)
     321
     322        foreach {lcol ecol} $cols break
     323        set _dobj2cols($dataobj-label) $lcol
     324        set _dobj2cols($dataobj-energy) $ecol
     325
     326        $_dispatcher event -idle !redraw
     327    }
     328}
     329
     330# ----------------------------------------------------------------------
     331# USAGE: delete ?<dataobj1> <dataobj2> ...?
     332#
     333# Clients use this to delete a dataobj from the plot.  If no dataobjs
     334# are specified, then all dataobjs are deleted.
     335# ----------------------------------------------------------------------
     336itcl::body Rappture::EnergyLevels::delete {args} {
     337    if {[llength $args] == 0} {
     338        set args $_dlist
     339        set _eviewmin ""
     340        set _eviewmax ""
     341    }
     342
     343    # delete all specified data objs
     344    set changed 0
     345    foreach dataobj $args {
     346        set pos [lsearch -exact $_dlist $dataobj]
     347        if {$pos >= 0} {
     348            set _dlist [lreplace $_dlist $pos $pos]
     349            catch {unset _dobj2color($dataobj)}
     350            catch {unset _dobj2raise($dataobj)}
     351            catch {unset _dobj2cols($dataobj-label)}
     352            catch {unset _dobj2cols($dataobj-energy)}
     353            set changed 1
     354        }
     355    }
     356
     357    # if anything changed, then rebuild the plot
     358    if {$changed} {
     359        $_dispatcher event -idle !redraw
     360    }
     361}
     362
     363# ----------------------------------------------------------------------
     364# USAGE: scale ?<dataobj1> <dataobj2> ...?
     365#
     366# Sets the default limits for the overall plot according to the
     367# limits of the data for all of the given <dataobj> objects.  This
     368# accounts for all dataobjs--even those not showing on the screen.
     369# Because of this, the limits are appropriate for all data as
     370# the user scans through data in the ResultSet viewer.
     371# ----------------------------------------------------------------------
     372itcl::body Rappture::EnergyLevels::scale {args} {
     373    set _emin ""
     374    set _emax ""
     375    foreach obj $args {
     376        if {![info exists _dobj2cols($obj-energy)]} {
     377            # don't recognize this object? then ignore it
     378            continue
     379        }
     380        foreach {min max} [$obj limits $_dobj2cols($obj-energy)] break
     381
     382        if {"" != $min && "" != $max} {
     383            if {"" == $_emin} {
     384                set _emin $min
     385                set _emax $max
     386            } else {
     387                if {$min < $_emin} { set _emin $min }
     388                if {$max > $_emax} { set _emax $max }
     389            }
     390        }
     391    }
     392}
     393
     394# ----------------------------------------------------------------------
     395# USAGE: _redraw
    157396#
    158397# Used internally to load a list of energy levels from a <table> within
    159 # the -output XML object.  The -layout object indicates how information
    160 # should be extracted from the table.  The <layout> should have an
    161 # <energies> tag and perhaps a <labels> tag, which indicates the table
    162 # and the column within the table containing the energies.
    163 # ----------------------------------------------------------------------
    164 itcl::body Rappture::EnergyLevels::_render {} {
    165     #
    166     # Clear any information shown in the graph.
    167     #
    168     set graph $itk_component(graph)
    169     eval $graph element delete [$graph element names]
    170     eval $graph marker delete [$graph marker names]
    171 
    172     #
    173     # Plug in the title from the layout
    174     #
    175     set title ""
    176     if {$itk_option(-layout) != ""} {
    177         set title [$itk_option(-layout) get label]
    178     }
    179     if {"" != $title} {
    180         pack $itk_component(title) -side top -before $graph
    181         $itk_component(title) configure -text $title
     398# the data objects.
     399# ----------------------------------------------------------------------
     400itcl::body Rappture::EnergyLevels::_redraw {{what all}} {
     401    # scale data now, if we haven't already
     402    if {"" == $_emin || "" == $_emax} {
     403        eval scale $_dlist
     404    }
     405
     406    # put the dataobj list in order according to -raise options
     407    set dlist $_dlist
     408    foreach obj $dlist {
     409        if {[info exists _dobj2raise($obj)] && $_dobj2raise($obj)} {
     410            set i [lsearch -exact $dlist $obj]
     411            if {$i >= 0} {
     412                set dlist [lreplace $dlist $i $i]
     413                lappend dlist $obj
     414            }
     415        }
     416    }
     417    set topdobj [lindex $dlist end]
     418
     419    _getLayout
     420
     421    #
     422    # Redraw the overall layout
     423    #
     424    if {$what == "all"} {
     425        $c delete all
     426        if {[llength $dlist] == 0} {
     427            return
     428        }
     429
     430        #
     431        # Scan through all data objects and plot them in order from
     432        # the bottom up.
     433        #
     434        set e2y [expr {($y1-$y0)/($_emax-$_emin)}]
     435
     436        set title ""
     437        set dataobj ""
     438        foreach dataobj $dlist {
     439            if {"" == $title} {
     440                set title [$dataobj hints label]
     441            }
     442
     443            set ecol $_dobj2cols($dataobj-energy)
     444            set color $_dobj2color($dataobj)
     445            if {"" == $color} {
     446                set color $itk_option(-levelcolor)
     447            }
     448            set color [Rappture::color::brightness $color 0.7]
     449
     450            foreach eval [$dataobj values -column $ecol] {
     451                set y [expr {($eval-$_emin)*$e2y + $y0}]
     452                $c create line $xx0 $y $xx1 $y -fill $color -width 1
     453            }
     454        }
     455
     456        #
     457        # Scan through the data and look for HOMO/LUMO levels.
     458        # Set the default view to the energy just above and
     459        # just below the HOMO/LUMO levels.
     460        #
     461        set _edefmin [expr {0.4*($_emax-$_emin) + $_emin}]
     462        set _edefmax [expr {0.6*($_emax-$_emin) + $_emin}]
     463
     464        set nlumo -1
     465        set nhomo -1
     466
     467        set dataobj [lindex $dlist end]
     468        if {"" != $dataobj} {
     469            set lcol $_dobj2cols($dataobj-label)
     470            set ecol $_dobj2cols($dataobj-energy)
     471            set units [$dataobj columns -units $ecol]
     472
     473            set n 0
     474            foreach eval [$dataobj values -column $ecol] \
     475                    lval [$dataobj values -column $lcol] {
     476
     477                if {$lval == "HOMO"} {
     478                    set nhomo $n
     479                    set nlumo [expr {$n+1}]
     480                } elseif {$lval == "LUMO"} {
     481                    set nlumo $n
     482                }
     483                incr n
     484            }
     485
     486            if {$nhomo >= 0 && $nlumo >= 0} {
     487                set elist [$dataobj values -column $ecol]
     488                set _ehomo [lindex $elist $nhomo]
     489                set _elumo [lindex $elist $nlumo]
     490                set gap [expr {$_elumo - $_ehomo}]
     491                set _edefmin [expr {$_ehomo - 0.3*$gap}]
     492                set _edefmax [expr {$_elumo + 0.3*$gap}]
     493
     494                set y [expr {($_ehomo-$_emin)*$e2y + $y0}]
     495                set id [$c create rectangle $xx0 $y $xx1 $y0 \
     496                    -stipple EnergyLevels-rdiag \
     497                    -outline "" -fill $itk_option(-shadecolor)]
     498                $c lower $id
     499            }
     500        }
     501        if {"" == $_eviewmin || "" == $_eviewmax} {
     502            set _eviewmin $_edefmin
     503            set _eviewmax $_edefmax
     504        }
     505
     506        if {"" != $title} {
     507            pack $itk_component(title) -side top -before $c
     508            $itk_component(title) configure -text $title
     509        } else {
     510            pack forget $itk_component(title)
     511        }
     512
     513        # draw the lines for the "zoom" view (fixed up below)
     514        set color $itk_option(-foreground)
     515        $c create line $x0 $y0 $x1 $y0 -fill $color -tags zmin
     516        $c create line $x0 $y0 $x1 $y0 -fill $color -tags zmax
     517
     518        $c create line $x1 $y0 $x2 $y0 -fill $color -tags zoomup
     519        $c create line $x1 $y0 $x2 $y1 -fill $color -tags zoomdn
     520
     521        $c create line $x2 $y0 $x3 $y0 -fill $color
     522        $c create line $x2 $y1 $x3 $y1 -fill $color
     523    }
     524
     525    #
     526    # Redraw the "zoom" area on the right side
     527    #
     528    if {$what == "zoom" || $what == "all"} {
     529        set e2y [expr {($y1-$y0)/($_emax-$_emin)}]
     530
     531        set y [expr {($_eviewmin-$_emin)*$e2y + $y0}]
     532        $c coords zmin $x0 $y $x1 $y
     533        $c coords zoomup $x1 $y $x2 $y0
     534
     535        set y [expr {($_eviewmax-$_emin)*$e2y + $y0}]
     536        $c coords zmax $x0 $y $x1 $y
     537        $c coords zoomdn $x1 $y $x2 $y1
     538
     539        # redraw all levels in the current view
     540        $c delete zlevels zlabels
     541
     542        set e2y [expr {($y1-$y0)/($_eviewmax-$_eviewmin)}]
     543        foreach dataobj $dlist {
     544            set ecol $_dobj2cols($dataobj-energy)
     545            set color $_dobj2color($dataobj)
     546            if {"" == $color} {
     547                set color $itk_option(-levelcolor)
     548            }
     549
     550            set n 0
     551            foreach eval [$dataobj values -column $ecol] {
     552                if {$eval >= $_eviewmin && $eval <= $_eviewmax} {
     553                    set y [expr {($eval-$_eviewmin)*$e2y + $y0}]
     554                    set id [$c create line $xx2 $y $xx3 $y \
     555                        -fill $color -width 1 \
     556                        -tags [list zlevels $dataobj-$n]]
     557                }
     558                incr n
     559            }
     560        }
     561
     562        if {"" != $_ehomo && "" != $_elumo} {
     563            set ecol $_dobj2cols($topdobj-energy)
     564            set units [$topdobj columns -units $ecol]
     565
     566            set yy0 [expr {($_ehomo-$_eviewmin)*$e2y + $y0}]
     567            set yy1 [expr {($_elumo-$_eviewmin)*$e2y + $y0}]
     568            $c create line [expr {$x3-10}] $yy0 [expr {$x3-10}] $yy1 \
     569                -arrow both -fill $itk_option(-foreground) \
     570                -tags zlabels
     571            $c create text [expr {$x3-15}] [expr {0.5*($yy0+$yy1)}] \
     572                -anchor e -text "Eg = [expr {$_elumo-$_ehomo}] $units" \
     573                -tags zlabels
     574
     575            # label the HOMO level
     576            set tid [$c create text [expr {0.5*($x2+$x3)}] $yy0 -anchor c \
     577                -text "HOMO = $_ehomo $units" \
     578                -fill $itk_option(-leveltextforeground) \
     579                -tags zlabels]
     580
     581            foreach {xb0 yb0 xb1 yb1} [$c bbox $tid] break
     582            set tid2 [$c create rectangle \
     583                [expr {$xb0-1}] [expr {$yb0-1}] \
     584                [expr {$xb1+1}] [expr {$yb1+1}] \
     585                -outline $itk_option(-leveltextforeground) \
     586                -fill $itk_option(-leveltextbackground) \
     587                -tags zlabels]
     588            $c lower $tid2 $tid
     589
     590            # label the LUMO level
     591            set tid [$c create text [expr {0.5*($x2+$x3)}] $yy1 -anchor c \
     592                -text "LUMO = $_elumo $units" \
     593                -fill $itk_option(-leveltextforeground) \
     594                -tags zlabels]
     595
     596            foreach {xb0 yb0 xb1 yb1} [$c bbox $tid] break
     597            set tid2 [$c create rectangle \
     598                [expr {$xb0-1}] [expr {$yb0-1}] \
     599                [expr {$xb1+1}] [expr {$yb1+1}] \
     600                -outline $itk_option(-leveltextforeground) \
     601                -fill $itk_option(-leveltextbackground) \
     602                -tags zlabels]
     603            $c lower $tid2 $tid
     604
     605            set id [$c create rectangle $xx2 $yy0 $xx3 $y0 \
     606                -stipple EnergyLevels-rdiag \
     607                -outline "" -fill $itk_option(-shadecolor) \
     608                -tags zlabels]
     609            $c lower $id
     610        }
     611    }
     612}
     613
     614# ----------------------------------------------------------------------
     615# USAGE: _zoom in
     616# USAGE: _zoom out
     617# USAGE: _zoom reset
     618# USAGE: _zoom at <x> <y>
     619# USAGE: _zoom nudge <dir>
     620#
     621# Called automatically when the user clicks on one of the zoom
     622# controls for this widget.  Changes the zoom for the current view.
     623# ----------------------------------------------------------------------
     624itcl::body Rappture::EnergyLevels::_zoom {option args} {
     625    switch -- $option {
     626        in {
     627            set midE [expr {0.5*($_eviewmax + $_eviewmin)}]
     628            set delE [expr {0.8*($_eviewmax - $_eviewmin)}]
     629            _view $midE $delE
     630        }
     631        out {
     632            set midE [expr {0.5*($_eviewmax + $_eviewmin)}]
     633            set delE [expr {1.25*($_eviewmax - $_eviewmin)}]
     634            _view $midE $delE
     635        }
     636        reset {
     637            set _eviewmin $_edefmin
     638            set _eviewmax $_edefmax
     639            $_dispatcher event -idle !zoom
     640        }
     641        at {
     642            if {[llength $args] != 2} {
     643                error "wrong # args: should be \"_zoom at x y\""
     644            }
     645            set x [lindex $args 0]
     646            set y [lindex $args 1]
     647
     648            _getLayout
     649            set y2e [expr {($_emax-$_emin)/($y1-$y0)}]
     650
     651            if {$x > $x1} {
     652                return
     653            }
     654            set midE [expr {($y-$y0)*$y2e + $_emin}]
     655            set delE [expr {$_eviewmax - $_eviewmin}]
     656            _view $midE $delE
     657        }
     658        nudge {
     659            if {[llength $args] != 1} {
     660                error "wrong # args: should be \"_zoom nudge dir\""
     661            }
     662            set dir [lindex $args 0]
     663
     664            set midE [expr {0.5*($_eviewmax + $_eviewmin)}]
     665            set delE [expr {$_eviewmax - $_eviewmin}]
     666            set midE [expr {$midE + $dir*0.25*$delE}]
     667            _view $midE $delE
     668        }
     669    }
     670    focus $itk_component(graph)
     671}
     672
     673# ----------------------------------------------------------------------
     674# USAGE: _view <midE> <delE>
     675#
     676# Called automatically when the user clicks/drags on the left side
     677# of the widget where energy levels are displayed.  Sets the zoom
     678# view so that it's centered on the <y> coordinate.
     679# ----------------------------------------------------------------------
     680itcl::body Rappture::EnergyLevels::_view {midE delE} {
     681    if {$delE > $_emax-$_emin} {
     682        set delE [expr {$_emax - $_emin}]
     683    }
     684    if {$midE - 0.5*$delE < $_emin} {
     685        set _eviewmin $_emin
     686        set _eviewmax [expr {$_eviewmin+$delE}]
     687    } elseif {$midE + 0.5*$delE > $_emax} {
     688        set _eviewmax $_emax
     689        set _eviewmin [expr {$_eviewmax-$delE}]
    182690    } else {
    183         pack forget $itk_component(title)
    184     }
    185 
    186     #
    187     # Look through the layout and figure out what to extract
    188     # from the table.
    189     #
    190     set elist [_getColumn energies]
    191     if {[llength $elist] == 0} {
    192         return
    193     }
    194     set units [_getUnits energies]
    195 
    196     set llist [_getColumn names]
    197     if {[llength $llist] == 0} {
    198         # no labels? then invent some
    199         set i 0
    200         foreach name $elist {
    201             lappend llist "E$i"
    202             incr i
    203         }
    204     }
    205 
    206     #
    207     # Update the graph to show the current set of levels.
    208     #
    209     set n 0
    210     set nlumo -1
    211     set emax ""
    212     set emin ""
    213     set ehomo ""
    214     set elumo ""
    215     foreach eval $elist lval $llist {
    216         if {$lval == "HOMO"} {
    217             set ehomo $eval
    218             set lval "HOMO = $eval $units"
    219             set nlumo [expr {$n+1}]
    220         } elseif {$lval == "LUMO" || $n == $nlumo} {
    221             set elumo $eval
    222             set lval "LUMO = $eval $units"
    223         } else {
    224             set lval ""
    225         }
    226 
    227         set elem "elem[incr n]"
    228         $graph element create $elem \
    229             -xdata {0 1} -ydata [list $eval $eval] \
    230             -color $itk_option(-levelcolor) -symbol "" -linewidth 1
    231 
    232         if {$lval != ""} {
    233             $graph marker create text -coords [list 0.5 $eval] \
    234                 -text $lval -anchor c \
    235                 -foreground $itk_option(-leveltextforeground) \
    236                 -background $itk_option(-leveltextbackground)
    237         }
    238 
    239         if {$emax == ""} {
    240             set emax $eval
    241             set emin $eval
    242         } else {
    243             if {$eval > $emax} {set emax $eval}
    244             if {$eval < $emin} {set emin $eval}
    245         }
    246     }
    247     $graph xaxis configure -min 0 -max 1 -showticks off -linewidth 0
    248     if {$units != ""} {
    249         $graph yaxis configure -title "Energy ($units)"
    250     } else {
    251         $graph yaxis configure -title "Energy"
    252     }
    253 
    254     # bump the limits so they are big enough to show labels
    255     set fnt $itk_option(-font)
    256     set h [expr {0.5*([font metrics $fnt -linespace] + 5)}]
    257     set emin [expr {$emin-($emax-$emin)*$h/150.0}]
    258     set emax [expr {$emax+($emax-$emin)*$h/150.0}]
    259     $graph yaxis configure -min $emin -max $emax
    260 
    261     #
    262     # If we found HOMO/LUMO levels, then add the band gap at
    263     # that point.  Also, fix the controls for energy range.
    264     #
    265     if {$ehomo != "" && $elumo != ""} {
    266         set id [$graph marker create line \
    267             -coords [list 0.2 $elumo 0.2 $ehomo]]
    268         $graph marker after $id
    269 
    270         set egap [expr {$elumo-$ehomo}]
    271         set emid [expr {0.5*($ehomo+$elumo)}]
    272         $graph marker create text \
    273             -coords [list 0.21 $emid] -background "" \
    274             -text "Eg = [format %.2g $egap] $units" -anchor w
    275 
    276         # fix the limits for the lower scale
    277         set elim [_getMidPt $elist [expr {$nlumo-1}]]
    278         if {"" != $elim} {
    279             $itk_component(lowerEcntl) configure -from $elim -to $emin \
    280                 -resolution [expr {0.02*($elim-$emin)}]
    281             grid $itk_component(lowerE) -row 2 -column 0 -sticky ns
    282 
    283             set e0 [_getMidPt $elist [expr {$nlumo-3}]]
    284             if {"" != $e0} {
    285                 $itk_component(lowerEcntl) set $e0
     691        set _eviewmin [expr {$midE - 0.5*$delE}]
     692        set _eviewmax [expr {$midE + 0.5*$delE}]
     693    }
     694    $_dispatcher event -idle !zoom
     695}
     696
     697# ----------------------------------------------------------------------
     698# USAGE: _hilite brush <x> <y>
     699# USAGE: _hilite show <dataobj> <level>
     700# USAGE: _hilite hide
     701#
     702# Used internally to highlight energy levels in the zoom view and
     703# show their associated energy.  The "brush" operation is called
     704# as the mouse moves in the zoom view, to see if the <x>,<y>
     705# coordinate is touching a level.  The show/hide operations are
     706# then used to show/hide level info.
     707# ----------------------------------------------------------------------
     708itcl::body Rappture::EnergyLevels::_hilite {option args} {
     709    switch -- $option {
     710        brush {
     711            if {[llength $args] != 2} {
     712                error "wrong # args: should be \"_hilite brush x y\""
     713            }
     714            set x [lindex $args 0]
     715            set y [lindex $args 1]
     716
     717            _getLayout
     718            if {$x < $x2 || $x > $x3} {
     719                return   ;# pointer must be in "zoom" area
     720            }
     721
     722            set c $itk_component(graph)
     723            set id [$c find withtag current]
     724
     725            # touching a line? then find the level and show its info
     726            if {"" != $id} {
     727                set e2y [expr {($y1-$y0)/($_eviewmax-$_eviewmin)}]
     728
     729                # put the dataobj list in order according to -raise options
     730                set dlist $_dlist
     731                foreach obj $dlist {
     732                    if {[info exists _dobj2raise($obj)] && $_dobj2raise($obj)} {
     733                        set i [lsearch -exact $dlist $obj]
     734                        if {$i >= 0} {
     735                            set dlist [lreplace $dlist $i $i]
     736                            lappend dlist $obj
     737                        }
     738                    }
     739                }
     740
     741                set found 0
     742                foreach dataobj $dlist {
     743                    set ecol $_dobj2cols($dataobj-energy)
     744                    set n 0
     745                    foreach eval [$dataobj values -column $ecol] {
     746                        set ylevel [expr {($eval-$_eviewmin)*$e2y + $y0}]
     747                        if {$y >= $ylevel-3 && $y <= $ylevel+3} {
     748                            set found 1
     749                            break
     750                        }
     751                        incr n
     752                    }
     753                    if {$found} break
     754                }
     755                if {$found} {
     756                    _hilite show $dataobj $n
     757                } else {
     758                    _hilite hide
     759                }
    286760            } else {
    287                 $itk_component(lowerEcntl) set $elim
    288             }
    289         } else {
    290             grid forget $itk_component(lowerE)
    291         }
    292 
    293         # fix the limits for the upper scale
    294         set elim [_getMidPt $elist [expr {$nlumo+1}]]
    295         if {"" != $elim} {
    296             $itk_component(upperEcntl) configure -from $emax -to $elim \
    297                 -resolution [expr {0.02*($emax-$elim)}]
    298             grid $itk_component(upperE) -row 0 -column 0 -sticky ns
    299 
    300             set e0 [_getMidPt $elist [expr {$nlumo+3}]]
    301             if {"" != $e0} {
    302                 $itk_component(upperEcntl) set $e0
    303             } else {
    304                 $itk_component(upperEcntl) set $elim
    305             }
    306         } else {
    307             grid forget $itk_component(upperE)
    308         }
    309     } else {
    310         grid forget $itk_component(upperE)
    311         grid forget $itk_component(lowerE)
    312     }
    313 }
    314 
    315 # ----------------------------------------------------------------------
    316 # USAGE: _adjust <what> <val>
     761                _hilite hide
     762            }
     763        }
     764        show {
     765            if {[llength $args] != 2} {
     766                error "wrong # args: should be \"_hilite show dataobj level\""
     767            }
     768            set dataobj [lindex $args 0]
     769            set level [lindex $args 1]
     770
     771            if {$_hilite == "$dataobj $level"} {
     772                return
     773            }
     774            _hilite hide
     775
     776            set lcol $_dobj2cols($dataobj-label)
     777            set lval [lindex [$dataobj values -column $lcol] $level]
     778            set ecol $_dobj2cols($dataobj-energy)
     779            set eval [lindex [$dataobj values -column $ecol] $level]
     780            set units [$dataobj columns -units $ecol]
     781
     782            if {$eval == $_ehomo || $eval == $_elumo} {
     783                # don't pop up info for the HOMO/LUMO levels
     784                return
     785            }
     786
     787            _getLayout
     788            set e2y [expr {($y1-$y0)/($_eviewmax-$_eviewmin)}]
     789            set y [expr {($eval-$_eviewmin)*$e2y + $y0}]
     790
     791            set tid [$c create text [expr {0.5*($x2+$x3)}] $y -anchor c \
     792                -text "$lval = $eval $units" \
     793                -fill $itk_option(-leveltextforeground) \
     794                -tags hilite]
     795
     796            foreach {x0 y0 x1 y1} [$c bbox $tid] break
     797            set tid2 [$c create rectangle \
     798                [expr {$x0-1}] [expr {$y0-1}] \
     799                [expr {$x1+1}] [expr {$y1+1}] \
     800                -outline $itk_option(-leveltextforeground) \
     801                -fill $itk_option(-leveltextbackground) \
     802                -tags hilite]
     803            $c lower $tid2 $tid
     804
     805            $c itemconfigure $dataobj-$level -width 2
     806            set _hilite "$dataobj $level"
     807        }
     808        hide {
     809            if {"" != $_hilite} {
     810                $itk_component(graph) delete hilite
     811                $itk_component(graph) itemconfigure zlevels -width 1
     812                set _hilite ""
     813            }
     814        }
     815        default {
     816            error "bad option \"$option\": should be brush, show, hide"
     817        }
     818    }
     819}
     820
     821# ----------------------------------------------------------------------
     822# USAGE: _getLayout
    317823#
    318 # Used internally to adjust the upper/lower limits of the graph
    319 # as the user drags the slider from "More" to "Fewer".  Sets
    320 # the specified limit to the given value.
    321 # ----------------------------------------------------------------------
    322 itcl::body Rappture::EnergyLevels::_adjust {what val} {
    323     switch -- $what {
    324         upper {
    325             $itk_component(graph) yaxis configure -max $val
    326         }
    327         lower {
    328             $itk_component(graph) yaxis configure -min $val
    329         }
    330         default {
    331             error "bad limit \"$what\": should be upper or lower"
    332         }
    333     }
    334 }
    335 
    336 # ----------------------------------------------------------------------
    337 # USAGE: _getColumn <name>
    338 #
    339 # Used internally to load a list of energy levels from a <table> within
    340 # the -output XML object.  The -layout object indicates how information
    341 # should be extracted from the table.  The <layout> should have an
    342 # <energies> tag and perhaps a <labels> tag, which indicates the table
    343 # and the column within the table containing the energies.
    344 # ----------------------------------------------------------------------
    345 itcl::body Rappture::EnergyLevels::_getColumn {name} {
    346 puts "_getColumn $name"
    347     if {$itk_option(-output) == ""} {
    348         return
    349     }
    350 
    351     #
    352     # Figure out which column in which table contains the data.
    353     # Then, find that table and extract the column.  Figure out
    354     # the position of the column from the list of all column names.
    355     #
    356     if {$itk_option(-layout) != ""} {
    357         set table [$itk_option(-layout) get $name.table]
    358         set col [$itk_option(-layout) get $name.column]
    359 
    360         set clist ""
    361         foreach c [$itk_option(-output) children -type column $table] {
    362             lappend clist [$itk_option(-output) get $table.$c.label]
    363         }
    364         set ipos [lsearch $clist $col]
    365         if {$ipos < 0} {
    366             return  ;# can't find data -- bail out!
    367         }
    368         set units [$itk_option(-output) get $table.column$ipos.units]
    369         set path "$table.data"
    370     } else {
    371         set clist ""
    372         foreach c [$itk_option(-output) children -type column] {
    373             lappend clist [$itk_option(-output) get $c.units]
    374         }
    375         if {$name == "energies"} {
    376             set units "eV"
    377         } else {
    378             set units ""
    379         }
    380         set ipos [lsearch -exact $clist $units]
    381         if {$ipos < 0} {
    382             return  ;# can't find data -- bail out!
    383         }
    384         set path "data"
    385     }
    386 
    387     set rlist ""
    388     foreach line [split [$itk_option(-output) get $path] "\n"] {
    389         if {"" != [string trim $line]} {
    390             set val [lindex $line $ipos]
    391 
    392             if {$units != ""} {
    393                 set val [Rappture::Units::convert $val \
    394                     -context $units -to $units -units off]
    395             }
    396             lappend rlist $val
    397         }
    398     }
    399     return $rlist
    400 }
    401 
    402 # ----------------------------------------------------------------------
    403 # USAGE: _getUnits <name>
    404 #
    405 # Used internally to extract the units from a <table> within the
    406 # -output XML object.  The -layout object indicates how information
    407 # should be extracted from the table.  The <layout> should have an
    408 # <energies> tag and perhaps a <labels> tag, which indicates the table
    409 # and the column within the table containing the units.
    410 # ----------------------------------------------------------------------
    411 itcl::body Rappture::EnergyLevels::_getUnits {name} {
    412     if {$itk_option(-output) == ""} {
    413         return
    414     }
    415 
    416     #
    417     # Figure out which column in which table contains the data.
    418     # Then, find that table and extract the column.  Figure out
    419     # the position of the column from the list of all column names.
    420     #
    421     if {$itk_option(-layout) != ""} {
    422         set table [$itk_option(-layout) get $name.table]
    423         set col [$itk_option(-layout) get $name.column]
    424 
    425         set clist ""
    426         foreach c [$itk_option(-output) children -type column $table] {
    427             lappend clist [$itk_option(-output) get $table.$c.label]
    428         }
    429         set ipos [lsearch $clist $col]
    430         if {$ipos < 0} {
    431             return  ;# can't find data -- bail out!
    432         }
    433         set units [$itk_option(-output) get $table.column$ipos.units]
    434     } else {
    435         if {$name == "energies"} {
    436             set units "eV"
    437         } else {
    438             set units ""
    439         }
    440     }
    441     return $units
    442 }
    443 
    444 # ----------------------------------------------------------------------
    445 # USAGE: _getMidPt <elist> <pos>
    446 #
    447 # Used internally to compute the midpoint between two energy levels
    448 # at <pos> and <pos-1> in the <elist>.  Returns a number representing
    449 # the mid-point (average value) or "" if the levels involved do
    450 # no exist in <elist>.
    451 # ----------------------------------------------------------------------
    452 itcl::body Rappture::EnergyLevels::_getMidPt {elist pos} {
    453     if {$pos < [llength $elist] && $pos > 1} {
    454         set e1 [lindex $elist $pos]
    455         set e0 [lindex $elist [expr {$pos-1}]]
    456         return [expr {0.5*($e0+$e1)}]
    457     }
    458     return ""
    459 }
    460 
    461 # ----------------------------------------------------------------------
    462 # OPTION: -layout
    463 # ----------------------------------------------------------------------
    464 itcl::configbody Rappture::EnergyLevels::layout {
    465     if {$itk_option(-layout) != ""
    466           && ![Rappture::library isvalid $itk_option(-layout)]} {
    467         error "bad value \"$itk_option(-layout)\": should be Rappture::library object"
    468     }
    469     after idle [itcl::code $this _render]
    470 }
    471 
    472 # ----------------------------------------------------------------------
    473 # OPTION: -output
    474 # ----------------------------------------------------------------------
    475 itcl::configbody Rappture::EnergyLevels::output {
    476     if {$itk_option(-output) != ""
    477           && ![Rappture::library isvalid $itk_option(-output)]} {
    478         error "bad value \"$itk_option(-output)\": should be Rappture::library object"
    479     }
    480     after cancel [itcl::code $this _render]
    481     after idle [itcl::code $this _render]
     824# Used internally to compute a series of variables used when redrawing
     825# the widget.  Creates the variables with the proper values in the
     826# calling context.
     827# ----------------------------------------------------------------------
     828itcl::body Rappture::EnergyLevels::_getLayout {} {
     829    upvar c c
     830    set c $itk_component(graph)
     831
     832    upvar w w
     833    set w [winfo width $c]
     834
     835    upvar h h
     836    set h [winfo height $c]
     837
     838    #
     839    # Measure the size of a typical label and use that to size
     840    # the left/right portions.  If the label is too big, leave
     841    # at least a little room for the labels.
     842    #
     843    set size [font measure $itk_option(-font) "HOMO = X.XXXXXXe-XX eV"]
     844    set size [expr {$size + 6*$itk_option(-padding)}]
     845
     846    if {$size > $w-20} {
     847        set size [expr {$w-20}]
     848    } elseif {$size < 0.66*$w} {
     849        set size [expr {0.66*$w}]
     850    }
     851    set xm [expr {$w - $size}]
     852
     853    upvar x0 x0
     854    set x0 $itk_option(-padding)
     855
     856    upvar x1 x1
     857    set x1 [expr {$xm - $itk_option(-padding)}]
     858
     859    upvar x2 x2
     860    set x2 [expr {$xm + $itk_option(-padding)}]
     861
     862    upvar x3 x3
     863    set x3 [expr {$w - $itk_option(-padding)}]
     864
     865
     866    upvar xx0 xx0
     867    set xx0 [expr {$x0 + $itk_option(-padding)}]
     868
     869    upvar xx1 xx1
     870    set xx1 [expr {$x1 - $itk_option(-padding)}]
     871
     872    upvar xx2 xx2
     873    set xx2 [expr {$x2 + $itk_option(-padding)}]
     874
     875    upvar xx3 xx3
     876    set xx3 [expr {$x3 - $itk_option(-padding)}]
     877
     878
     879    upvar y0 y0
     880    set y0 [expr {$h - $itk_option(-padding)}]
     881
     882    upvar y1 y1
     883    set y1 $itk_option(-padding)
    482884}
    483885
     
    486888# ----------------------------------------------------------------------
    487889itcl::configbody Rappture::EnergyLevels::levelcolor {
    488     after cancel [itcl::code $this _render]
    489     after idle [itcl::code $this _render]
     890    $_dispatcher event -idle !redraw
    490891}
    491892
     
    494895# ----------------------------------------------------------------------
    495896itcl::configbody Rappture::EnergyLevels::leveltextforeground {
    496     after cancel [itcl::code $this _render]
    497     after idle [itcl::code $this _render]
     897    $_dispatcher event -idle !redraw
    498898}
    499899
     
    502902# ----------------------------------------------------------------------
    503903itcl::configbody Rappture::EnergyLevels::leveltextbackground {
    504     after cancel [itcl::code $this _render]
    505     after idle [itcl::code $this _render]
    506 }
     904    $_dispatcher event -idle !redraw
     905}
  • trunk/gui/scripts/field.tcl

    r11 r13  
    257257# ----------------------------------------------------------------------
    258258itcl::body Rappture::Field::hints {{keyword ""}} {
    259     foreach key {label scale color units} {
    260         set str [$_field get $key]
     259    foreach {key path} {
     260        group   about.group
     261        label   about.label
     262        color   about.color
     263        style   about.style
     264        scale   about.scale
     265        units   units
     266    } {
     267        set str [$_field get $path]
    261268        if {"" != $str} {
    262269            set hints($key) $str
    263270        }
     271    }
     272
     273    if {[info exists hints(group)] && [info exists hints(label)]} {
     274        # pop-up help for each curve
     275        set hints(tooltip) $hints(label)
    264276    }
    265277
     
    357369
    358370            if {$xv != "" && $yv != ""} {
     371                # sort x-coords in increasing order
     372                $xv sort $yv
     373
    359374                set _comp2dims($cname) "1D"
    360375                set _comp2xy($cname) [list $xv $yv]
     
    370385            if {[$_xmlobj element $path] != ""} {
    371386                set cobj [Rappture::Cloud::fetch $_xmlobj $path]
    372                 set values [$_field get $cname.values]
    373                 set farray [vtkFloatArray ::vals$_counter]
    374 
    375                 foreach v $values {
    376                     if {"" != $_units} {
    377                         set v [Rappture::Units::convert $v \
    378                             -context $_units -to $_units -units off]
     387                if {[$cobj dimensions] > 1} {
     388                    #
     389                    # 2D/3D data
     390                    # Store cloud/field as components
     391                    #
     392                    set values [$_field get $cname.values]
     393                    set farray [vtkFloatArray ::vals$_counter]
     394
     395                    foreach v $values {
     396                        if {"" != $_units} {
     397                            set v [Rappture::Units::convert $v \
     398                                -context $_units -to $_units -units off]
     399                        }
     400                        $farray InsertNextValue $v
    379401                    }
    380                     $farray InsertNextValue $v
     402
     403                    set _comp2dims($cname) "[$cobj dimensions]D"
     404                    set _comp2vtk($cname) [list $cobj $farray]
     405                    incr _counter
     406                } else {
     407                    #
     408                    # OOPS!  This is 1D data
     409                    # Forget the cloud/field -- store BLT vectors
     410                    #
     411                    set xv [blt::vector create x$_counter]
     412                    set yv [blt::vector create y$_counter]
     413
     414                    set vtkpts [$cobj points]
     415                    set max [$vtkpts GetNumberOfPoints]
     416                    for {set i 0} {$i < $max} {incr i} {
     417                        set xval [lindex [$vtkpts GetPoint $i] 0]
     418                        $xv append $xval
     419                    }
     420                    Rappture::Cloud::release $cobj
     421
     422                    set values [$_field get $cname.values]
     423                    foreach yval $values {
     424                        if {"" != $_units} {
     425                            set yval [Rappture::Units::convert $yval \
     426                                -context $_units -to $_units -units off]
     427                        }
     428                        $yv append $yval
     429                    }
     430
     431                    # sort x-coords in increasing order
     432                    $xv sort $yv
     433
     434                    set _comp2dims($cname) "1D"
     435                    set _comp2xy($cname) [list $xv $yv]
     436                    incr _counter
    381437                }
    382 
    383                 set _comp2dims($cname) "[$cobj dimensions]D"
    384                 set _comp2vtk($cname) [list $cobj $farray]
    385                 incr _counter
    386438            } else {
    387439                puts "WARNING: can't find mesh $path for field component"
  • trunk/gui/scripts/loader.tcl

    r11 r13  
    6767    set defval [$xmlobj get $path.default]
    6868
     69    set flist ""
     70    foreach comp [$xmlobj children -type example $path] {
     71        lappend flist [$xmlobj get $path.$comp]
     72    }
     73
     74    # if there are no examples, then look for *.xml
     75    if {[llength $flist] == 0} {
     76        set flist *.xml
     77    }
     78
     79    if {$itk_option(-tool) != ""} {
     80        set fdir [$itk_option(-tool) installdir]
     81    } else {
     82        set fdir "."
     83    }
     84
    6985    set _counter 1
    70     foreach comp [$xmlobj children -type example $path] {
    71         if {$itk_option(-tool) != ""} {
    72             set fdir [$itk_option(-tool) installdir]
    73         } else {
    74             set fdir "."
    75         }
    76         set ftail [$xmlobj get $path.$comp]
    77         if {"" != $ftail} {
    78             set fname [file join $fdir examples $ftail]
     86    foreach ftail $flist {
     87        set fpath [file join $fdir examples $ftail]
     88        foreach fname [glob -nocomplain $fpath] {
    7989            if {[file exists $fname]} {
    8090                if {[catch {set obj [Rappture::library $fname]} result]} {
     
    8898                    $itk_component(combo) choices insert end $obj $label
    8999
    90                     if {[string equal $defval $ftail]} {
     100                    if {[string equal $defval [file tail $fname]]} {
    91101                        $xmlobj put $path.default $label
    92102                    }
  • trunk/gui/scripts/mainwin.tcl

    r11 r13  
    138138        }
    139139
    140         set titleh 0
    141         set fnt [option get $itk_component(hull) titleFont Font]
    142         if {$itk_option(-title) != "" && $fnt != ""} {
    143             set titleh [expr {[font metrics $fnt -linespace]+2}]
    144         }
    145         if {$h+$titleh > $sh} {
    146             set $h [expr {$sh-$titleh}]
    147             set clip 1
    148         }
    149 
    150140        switch -- $itk_option(-anchor) {
    151141            n {
    152142                set x [expr {$sw/2}]
    153                 set y $titleh
    154                 set tx [expr {$x-$w/2}]
    155                 set ty $titleh
     143                set y 0
    156144            }
    157145            s {
    158146                set x [expr {$sw/2}]
    159147                set y $sh
    160                 set tx [expr {$x-$w/2}]
    161                 set ty [expr {$sh-$h}]
    162148            }
    163149            center {
    164150                set x [expr {$sw/2}]
    165151                set y [expr {$sh/2}]
    166                 set tx [expr {$x-$w/2}]
    167                 set ty [expr {$y-$h/2}]
    168152            }
    169153            w {
    170154                set x 0
    171155                set y [expr {$sh/2}]
    172                 set tx 0
    173                 set ty [expr {$y-$h/2}]
    174156            }
    175157            e {
    176158                set x $sw
    177159                set y [expr {$sh/2}]
    178                 set tx [expr {$sw-$w}]
    179                 set ty [expr {$y-$h/2}]
    180160            }
    181161            nw {
    182162                set x 0
    183                 set y $titleh
    184                 set tx 0
    185                 set ty $titleh
     163                set y 0
    186164            }
    187165            ne {
    188166                set x $sw
    189                 set y $titleh
    190                 set tx [expr {$sw-$w}]
    191                 set ty $titleh
     167                set y 0
    192168            }
    193169            sw {
    194170                set x 0
    195171                set y $sh
    196                 set tx 0
    197                 set ty [expr {$sh-$h}]
    198172            }
    199173            se {
    200174                set x $sw
    201175                set y $sh
    202                 set tx [expr {$sw-$w}]
    203                 set ty [expr {$sh-$h}]
    204176            }
    205177        }
     
    214186            -anchor $itk_option(-anchor) -window $itk_component(app) \
    215187            -width $w -height $h
    216 
    217         if {$itk_option(-title) != "" && $fnt != ""} {
    218             $itk_component(area) create text $tx [expr {$ty-2}] \
    219                 -anchor sw -text $itk_option(-title) -font $fnt
    220         }
    221188    }
    222189}
  • trunk/gui/scripts/resultset.tcl

    r11 r13  
    1414option add *ResultSet.width 4i widgetDefault
    1515option add *ResultSet.height 4i widgetDefault
    16 option add *ResultSet.colors {blue #000066} widgetDefault
     16option add *ResultSet.colors {blue magenta} widgetDefault
    1717option add *ResultSet.toggleBackground gray widgetDefault
    1818option add *ResultSet.toggleForeground white widgetDefault
     
    130130# Adds a new result to this result set.  Scans through all existing
    131131# results to look for a difference compared to previous results.
    132 # Returns an instruction to the caller, indicating how the various
     132# Returns the index of this new result to the caller.  The various
    133133# data objects for this result set should be added to their result
    134 # viewers.
     134# viewers at the same index.
    135135# ----------------------------------------------------------------------
    136136itcl::body Rappture::ResultSet::add {xmlobj} {
     
    149149        $itk_component(status) configure -text "1 result"
    150150        $itk_component(clear) configure -state normal
    151         return "add"
     151        return 0
    152152    }
    153153
     
    173173
    174174    # build a tuple for this new object
    175     set op "add"
    176175    set cols ""
    177176    set tuple ""
     
    198197
    199198        # overwrite the first matching entry
    200         set i [lindex $ilist 0]
    201         $_results put $i $tuple
     199        set index [lindex $ilist 0]
     200        $_results put $index $tuple
    202201        set _recent $xmlobj
    203         set op "replace $i"
    204 
    205202    } else {
     203        set index [$_results size]
    206204        $_results insert end $tuple
    207205        set _recent $xmlobj
     
    215213    $itk_component(clear) configure -state normal
    216214
    217     return $op
     215    return $index
    218216}
    219217
     
    232230    }
    233231    catch {unset _col2widget}
     232    set _plotall ""
    234233    set _counter 0
    235234
  • trunk/gui/scripts/resultviewer.tcl

    r11 r13  
    2626    destructor { # defined below }
    2727
    28     public method add {xmlobj path}
    29     public method replace {index xmlobj path}
    30     public method clear {}
     28    public method add {index xmlobj path}
     29    public method clear {{index ""}}
    3130
    3231    public method plot {option args}
     
    3938    private variable _mode ""        ;# current plotting mode (xy, etc.)
    4039    private variable _mode2widget    ;# maps plotting mode => widget
    41     private variable _dataobjs ""    ;# list of all data objects in this widget
    42     private variable _plotlist ""    ;# list of indices plotted in _dataobjs
     40    private variable _dataslots ""   ;# list of all data objects in this widget
     41    private variable _plotlist ""    ;# list of indices plotted in _dataslots
    4342}
    4443                                                                               
     
    6766# ----------------------------------------------------------------------
    6867itcl::body Rappture::ResultViewer::destructor {} {
    69     foreach obj $_dataobjs {
    70         itcl::delete object $obj
    71     }
    72 }
    73 
    74 # ----------------------------------------------------------------------
    75 # USAGE: add <xmlobj> <path>
    76 #
    77 # Adds a new result to this result viewer.  Scans through all existing
    78 # results to look for a difference compared to previous results.
    79 # ----------------------------------------------------------------------
    80 itcl::body Rappture::ResultViewer::add {xmlobj path} {
     68    foreach slot $_dataslots {
     69        foreach obj $slot {
     70            itcl::delete object $obj
     71        }
     72    }
     73}
     74
     75# ----------------------------------------------------------------------
     76# USAGE: add <index> <xmlobj> <path>
     77#
     78# Adds a new result to this result viewer at the specified <index>.
     79# Data is taken from the <xmlobj> object at the <path>.
     80# ----------------------------------------------------------------------
     81itcl::body Rappture::ResultViewer::add {index xmlobj path} {
    8182    if {$path != ""} {
    8283        set dobj [_xml2data $xmlobj $path]
     
    8485        set dobj ""
    8586    }
    86     lappend _dataobjs $dobj
     87
     88    #
     89    # If the index doesn't exist, then fill in empty slots and
     90    # make it exist.
     91    #
     92    for {set i [llength $_dataslots]} {$i <= $index} {incr i} {
     93        lappend _dataslots ""
     94    }
     95    set slot [lindex $_dataslots $index]
     96    lappend slot $dobj
     97    set _dataslots [lreplace $_dataslots $index $index $slot]
    8798
    8899    $_dispatcher event -idle !scale
     
    90101
    91102# ----------------------------------------------------------------------
    92 # USAGE: replace <index> <xmlobj> <path>
    93 #
    94 # Stores a new result to this result viewer, overwriting the previous
    95 # result at position <index>.
    96 # ----------------------------------------------------------------------
    97 itcl::body Rappture::ResultViewer::replace {index xmlobj path} {
    98     set dobj [lindex $_dataobjs $index]
    99     if {"" != $dobj} {
    100         itcl::delete object $dobj
    101     }
    102 
    103     set dobj [_xml2data $xmlobj $path]
    104     set _dataobjs [lreplace $_dataobjs $index $index $dobj]
    105 
    106     $_dispatcher event -idle !scale
    107 }
    108 
    109 # ----------------------------------------------------------------------
    110 # USAGE: clear
    111 #
    112 # Clears all results in this result viewer.
    113 # ----------------------------------------------------------------------
    114 itcl::body Rappture::ResultViewer::clear {} {
    115     plot clear
    116 
    117     foreach obj $_dataobjs {
    118         itcl::delete object $obj
    119     }
    120     set _dataobjs ""
     103# USAGE: clear ?<index>?
     104#
     105# Clears one or all results in this result viewer.
     106# ----------------------------------------------------------------------
     107itcl::body Rappture::ResultViewer::clear {{index ""}} {
     108    if {"" != $index} {
     109        # clear one result
     110        if {$index >= 0 && $index < [llength $_dataslots]} {
     111            set slot [lindex $_dataslots $index]
     112            foreach dobj $slot {
     113                itcl::delete object $dobj
     114            }
     115            set _dataslots [lreplace $_dataslots $index $index ""]
     116        }
     117    } else {
     118        # clear all results
     119        plot clear
     120        foreach slot $_dataslots {
     121            foreach dobj $slot {
     122                itcl::delete object $dobj
     123            }
     124        }
     125        set _dataslots ""
     126    }
    121127}
    122128
     
    136142        add {
    137143            foreach {index opts} $args {
    138                 set dobj [lindex $_dataobjs $index]
    139                 if {"" != $dobj} {
    140                     _plotAdd $dobj $opts
     144                set slot [lindex $_dataslots $index]
     145                foreach dobj $slot {
     146                    # start with default settings from data object
     147                    if {[catch {$dobj hints style} settings]} {
     148                        set settings ""
     149                    }
     150                    # add override settings passed in here
     151                    eval lappend settings $opts
     152
     153                    _plotAdd $dobj $settings
    141154                }
    142155            }
     
    186199                    set mode "contour"
    187200                    if {![info exists _mode2widget($mode)]} {
    188                         set w $itk_interior.xy
     201                        set w $itk_interior.contour
    189202                        Rappture::ContourResult $w
    190203                        set _mode2widget($mode) $w
     
    193206                default {
    194207                    error "can't handle [$dataobj components -dimensions] field"
     208                }
     209            }
     210        }
     211        ::Rappture::Table {
     212            set cols [Rappture::EnergyLevels::columns $dataobj]
     213            if {"" != $cols} {
     214                set mode "energies"
     215                if {![info exists _mode2widget($mode)]} {
     216                    set w $itk_interior.energies
     217                    Rappture::EnergyLevels $w
     218                    set _mode2widget($mode) $w
    195219                }
    196220            }
     
    206230                    }
    207231                }
    208                 table {
    209                     # table for now -- should have a Table object!
    210                     set mode "energies"
    211                     if {![info exists _mode2widget($mode)]} {
    212                         set w $itk_interior.energies
    213                         Rappture::EnergyLevels $w
    214                         set _mode2widget($mode) $w
    215                     }
    216                 }
    217232            }
    218233        }
     
    223238
    224239    if {$mode != $_mode && $_mode != ""} {
    225         return  ;# mixing data that doesn't mix -- ignore it!
     240        set nactive [llength [$_mode2widget($_mode) get]]
     241        if {$nactive > 0} {
     242            return  ;# mixing data that doesn't mix -- ignore it!
     243        }
    226244    }
    227245
     
    250268itcl::body Rappture::ResultViewer::_fixScale {args} {
    251269    if {"" != $_mode} {
    252         eval $_mode2widget($_mode) scale $_dataobjs
     270        set dlist ""
     271        foreach slot $_dataslots {
     272            foreach dobj $slot {
     273                lappend dlist $dobj
     274            }
     275        }
     276        eval $_mode2widget($_mode) scale $dlist
    253277    }
    254278}
     
    270294        }
    271295        table {
    272             return [$xmlobj element -as object $path]
     296            return [Rappture::Table ::#auto $xmlobj $path]
    273297        }
    274298        log {
  • trunk/gui/scripts/table.tcl

    r11 r13  
    22#  COMPONENT: table - extracts data from an XML description of a table
    33#
    4 #  This object represents one table in an XML description of a device.
     4#  This object represents one table in an XML description of a table.
    55#  It simplifies the process of extracting data representing columns
    66#  in the table.
     
    1111# ======================================================================
    1212package require Itcl
    13 package require BLT
    1413
    1514namespace eval Rappture { # forward declaration }
    1615
    1716itcl::class Rappture::Table {
    18     constructor {libobj path} { # defined below }
     17    constructor {xmlobj path} { # defined below }
    1918    destructor { # defined below }
    2019
    2120    public method rows {}
    22     public method columns {{pattern *}}
    23     public method vectors {{what -overall}}
     21    public method columns {args}
     22    public method values {args}
     23    public method limits {col}
    2424    public method hints {{key ""}}
    2525
    26     protected method _build {}
    27 
    28     private variable _units ""   ;# system of units for this table
    29     private variable _limits     ;# maps slab name => {z0 z1} limits
    30     private variable _zmax 0     ;# length of the device
    31 
     26    private variable _xmlobj ""  ;# ref to lib obj with curve data
    3227    private variable _table ""   ;# lib obj representing this table
    33     private variable _tree ""    ;# BLT tree used to contain table data
    34 
    35     private common _counter 0    ;# counter for unique vector names
     28    private variable _tuples ""  ;# list of tuples with table data
    3629}
    3730
     
    3932# CONSTRUCTOR
    4033# ----------------------------------------------------------------------
    41 itcl::body Rappture::Table::constructor {libobj path} {
    42     if {![Rappture::library isvalid $libobj]} {
    43         error "bad value \"$libobj\": should be LibraryObj"
    44     }
    45     set _table [$libobj element -as object $path]
    46     set _units [$_table get units]
    47 
    48     # determine the overall size of the device
    49     set z0 [set z1 0]
    50     foreach elem [$_device children recipe] {
    51         switch -glob -- $elem {
    52             slab* - molecule* {
    53                 if {![regexp {[0-9]$} $elem]} {
    54                     set elem "${elem}0"
    55                 }
    56                 set tval [$_device get recipe.$elem.thickness]
    57                 set tval [Rappture::Units::convert $tval \
    58                     -context um -to um -units off]
    59                 set z1 [expr {$z0+$tval}]
    60                 set _limits($elem) [list $z0 $z1]
    61 
    62                 set z0 $z1
    63             }
    64         }
    65     }
    66     set _zmax $z1
    67 
    68     # build up vectors for various components of the table
    69     _build
     34itcl::body Rappture::Table::constructor {xmlobj path} {
     35    if {![Rappture::library isvalid $xmlobj]} {
     36        error "bad value \"$xmlobj\": should be Rappture::library"
     37    }
     38    set _table [$xmlobj element -as object $path]
     39
     40    #
     41    # Load data from the table and store in the tuples.
     42    #
     43    set _tuples [Rappture::Tuples ::#auto]
     44    foreach cname [$_table children -type column] {
     45        set label [$_table get $cname.label]
     46        $_tuples column insert end -name $cname -label $label
     47    }
     48
     49    set cols [llength [$_tuples column names]]
     50    set nline 1
     51    foreach line [split [$_table get data] \n] {
     52        if {[llength $line] == 0} {
     53            continue
     54        }
     55        if {[llength $line] != $cols} {
     56            error "bad data at line $nline: expected $cols columns but got \"[string trim $line]\""
     57        }
     58        $_tuples insert end $line
     59        incr nline
     60    }
    7061}
    7162
     
    7465# ----------------------------------------------------------------------
    7566itcl::body Rappture::Table::destructor {} {
     67    itcl::delete object $_tuples
    7668    itcl::delete object $_table
    77     # don't destroy the _device! we don't own it!
    78 
    79     foreach name [array names _comp2vecs] {
    80         eval blt::vector destroy $_comp2vecs($name)
    81     }
    82 }
    83 
    84 # ----------------------------------------------------------------------
    85 # USAGE: components ?<pattern>?
    86 #
    87 # Returns a list of names for the various components of this table.
    88 # If the optional glob-style <pattern> is specified, then it returns
    89 # only the component names matching the pattern.
    90 # ----------------------------------------------------------------------
    91 itcl::body Rappture::Table::components {{pattern *}} {
     69    # don't destroy the _xmlobj! we don't own it!
     70}
     71
     72# ----------------------------------------------------------------------
     73# USAGE: rows
     74#
     75# Returns the number of rows of information in this table.
     76# ----------------------------------------------------------------------
     77itcl::body Rappture::Table::rows {} {
     78    return [$_tuples size]
     79}
     80
     81# ----------------------------------------------------------------------
     82# USAGE: columns ?-component|-label|-units? ?<pos>?
     83#
     84# Returns information about the columns associated with this table.
     85# ----------------------------------------------------------------------
     86itcl::body Rappture::Table::columns {args} {
     87    Rappture::getopts args params {
     88        flag switch -component
     89        flag switch -label default
     90        flag switch -units
     91    }
     92    if {[llength $args] == 0} {
     93        set cols [llength [$_tuples column names]]
     94        set plist ""
     95        for {set i 0} {$i < $cols} {incr i} {
     96            lappend plist $i
     97        }
     98    } elseif {[llength $args] == 1} {
     99        set p [lindex $args 0]
     100        if {[string is integer $p]} {
     101            lappend plist $p
     102        } else {
     103            set pos [lsearch -exact [$_tuples column names] $p]
     104            if {$pos < 0} {
     105                error "bad column \"$p\": should be column name or integer index"
     106            }
     107            lappend plist $pos
     108        }
     109    } else {
     110        error "wrong # args: should be \"columns ?-component|-label|-units? ?pos?\""
     111    }
     112
    92113    set rlist ""
    93     foreach name [array names _comp2vecs] {
    94         if {[string match $pattern $name]} {
    95             lappend rlist $name
     114    switch -- $params(switch) {
     115        -component {
     116            set names [$_tuples column names]
     117            foreach p $plist {
     118                lappend rlist [lindex $names $p]
     119            }
     120        }
     121        -label {
     122            set names [$_tuples column names]
     123            foreach p $plist {
     124                set name [lindex $names $p]
     125                catch {unset opts}
     126                array set opts [$_tuples column info $name]
     127                lappend rlist $opts(-label)
     128            }
     129        }
     130        -units {
     131            set names [$_tuples column names]
     132            foreach p $plist {
     133                set comp [lindex $names $p]
     134                lappend rlist [$_table get $comp.units]
     135            }
    96136        }
    97137    }
     
    100140
    101141# ----------------------------------------------------------------------
    102 # USAGE: vectors ?<name>?
    103 #
    104 # Returns a list {xvec yvec} for the specified table component <name>.
    105 # If the name is not specified, then it returns the vectors for the
    106 # overall table (sum of all components).
    107 # ----------------------------------------------------------------------
    108 itcl::body Rappture::Table::vectors {{what -overall}} {
    109     if {[info exists _comp2vecs($what)]} {
    110         return $_comp2vecs($what)
    111     }
    112     error "bad option \"$what\": should be [join [lsort [array names _comp2vecs]] {, }]"
     142# USAGE: values ?-row <index>? ?-column <index>?
     143#
     144# Returns a single value or a list of values for data in this table.
     145# If a particular -row and -column is specified, then it returns
     146# a single value for that row/column.  If either the -row or the
     147# -column is specified, then it returns a list of values in that
     148# row or column.  With no args, it returns all values in the table.
     149# ----------------------------------------------------------------------
     150itcl::body Rappture::Table::values {args} {
     151    Rappture::getopts args params {
     152        value -row ""
     153        value -column ""
     154    }
     155    if {[llength $args] > 0} {
     156        error "wrong # args: should be \"values ?-row r? ?-column c?\""
     157    }
     158    if {"" == $params(-row) && "" == $params(-column)} {
     159        return [$_tuples get]
     160    } elseif {"" == $params(-column)} {
     161        return [lindex [$_tuples get $params(-row)] 0]
     162    }
     163
     164    if {[string is integer $params(-column)]} {
     165        set col [lindex [$_tuples column names] $params(-column)]
     166    } else {
     167        set col $params(-column)
     168        if {"" == [$_tuples column names $col]} {
     169            error "bad column name \"$col\": should be [join [$_tuples column names] {, }]"
     170        }
     171    }
     172
     173    if {"" == $params(-row)} {
     174        # return entire column
     175        return [$_tuples get -format $col]
     176    }
     177    # return a particular cell
     178    return [$_tuples get -format $col $params(-row)]
     179}
     180
     181# ----------------------------------------------------------------------
     182# USAGE: limits <column>
     183#
     184# Returns the {min max} limits of the numerical values in the
     185# specified <column>, which can be either an integer index to
     186# a column or a column name.
     187# ----------------------------------------------------------------------
     188itcl::body Rappture::Table::limits {column} {
     189    set min ""
     190    set max ""
     191    foreach v [values -column $column] {
     192        if {"" == $min} {
     193            set min $v
     194            set max $v
     195        } else {
     196            if {$v < $min} { set min $v }
     197            if {$v > $max} { set max $v }
     198        }
     199    }
     200    return [list $min $max]
    113201}
    114202
     
    121209# ----------------------------------------------------------------------
    122210itcl::body Rappture::Table::hints {{keyword ""}} {
    123     foreach key {label scale color units restrict} {
    124         set str [$_table get $key]
     211    foreach {key path} {
     212        label   about.label
     213        color   about.color
     214        style   about.style
     215    } {
     216        set str [$_table get $path]
    125217        if {"" != $str} {
    126218            set hints($key) $str
     
    136228    return [array get hints]
    137229}
    138 
    139 # ----------------------------------------------------------------------
    140 # USAGE: _build
    141 #
    142 # Used internally to build up the vector representation for the
    143 # table when the object is first constructed, or whenever the table
    144 # data changes.  Discards any existing vectors and builds everything
    145 # from scratch.
    146 # ----------------------------------------------------------------------
    147 itcl::body Rappture::Table::_build {} {
    148     # discard any existing data
    149     foreach name [array names _comp2vecs] {
    150         eval blt::vector destroy $_comp2vecs($name)
    151     }
    152     catch {unset _comp2vecs}
    153 
    154     #
    155     # Scan through the components of the table and create
    156     # vectors for each part.
    157     #
    158     foreach cname [$_table children -type component] {
    159         set xv ""
    160         set yv ""
    161 
    162         set val [$_table get $cname.constant]
    163         if {$val != ""} {
    164             set domain [$_table get $cname.domain]
    165             if {$domain == "" || ![info exists _limits($domain)]} {
    166                 set z0 0
    167                 set z1 $_zmax
    168             } else {
    169                 foreach {z0 z1} $_limits($domain) { break }
    170             }
    171             set xv [blt::vector create x$_counter]
    172             $xv append $z0 $z1
    173 
    174             if {$_units != ""} {
    175                 set val [Rappture::Units::convert $val \
    176                     -context $_units -to $_units -units off]
    177             }
    178             set yv [blt::vector create y$_counter]
    179             $yv append $val $val
    180 
    181             set zm [expr {0.5*($z0+$z1)}]
    182         } else {
    183             set xydata [$_table get $cname.xy]
    184             if {"" != $xydata} {
    185                 set xv [blt::vector create x$_counter]
    186                 set yv [blt::vector create y$_counter]
    187 
    188                 foreach line [split $xydata \n] {
    189                     if {[scan $line {%g %g} xval yval] == 2} {
    190                         $xv append $xval
    191                         $yv append $yval
    192                     }
    193                 }
    194             }
    195         }
    196 
    197         if {$xv != "" && $yv != ""} {
    198             set _comp2vecs($cname) [list $xv $yv]
    199             incr _counter
    200         }
    201     }
    202 }
  • trunk/gui/scripts/textresult.tcl

    r11 r13  
    2323
    2424    public method add {dataobj {settings ""}}
     25    public method get {}
    2526    public method delete {args}
    2627    public method scale {args}
     28
     29    set _dataobj ""  ;# data object currently being displayed
    2730}
    2831                                                                               
     
    5861# Clients use this to add a data object to the plot.  If the optional
    5962# <settings> are specified, then the are applied to the data.  Allowed
    60 # settings are -color and -width/-raise (ignored).
     63# settings are -color and -brightness, -width, -linestyle and -raise.
     64# (Many of these are ignored.)
    6165# ----------------------------------------------------------------------
    6266itcl::body Rappture::TextResult::add {dataobj {settings ""}} {
    6367    array set params {
    6468        -color ""
     69        -brightness ""
    6570        -width ""
     71        -linestyle ""
    6672        -raise ""
    6773    }
     
    9298
    9399    $itk_component(text) configure -state disabled
     100    set _dataobj $dataobj
     101}
     102
     103# ----------------------------------------------------------------------
     104# USAGE: get
     105#
     106# Clients use this to query the list of objects being plotted, in
     107# order from bottom to top of this result.
     108# ----------------------------------------------------------------------
     109itcl::body Rappture::TextResult::get {} {
     110    return $_dataobj
    94111}
    95112
     
    104121    $itk_component(text) delete 1.0 end
    105122    $itk_component(text) configure -state disabled
     123    set _dataobj ""
    106124}
    107125
  • trunk/gui/scripts/tool.tcl

    r11 r13  
    2424
    2525    public method load {xmlobj}
    26     public method changed {path}
    2726    public method run {args}
    2827    public method abort {}
    2928
    3029    public method widgetfor {path {widget ""}}
     30    public method changed {path}
    3131    public method sync {}
     32    public method tool {}
    3233
    3334    private variable _xmlobj ""      ;# XML overall <run> object
     
    155156# USAGE: widgetfor <path> ?<widget>?
    156157#
    157 # Used by descendents such as a Controls panel to register the
     158# Used by embedded widgets such as a Controls panel to register the
    158159# various controls associated with this page.  That way, this Tool
    159160# knows what widgets to look at when syncing itself to the underlying
     
    227228    }
    228229}
     230
     231# ----------------------------------------------------------------------
     232# USAGE: tool
     233#
     234# Clients use this to figure out which tool is associated with
     235# this object.  Since this is a tool, it returns itself.
     236# ----------------------------------------------------------------------
     237itcl::body Rappture::Tool::tool {} {
     238    return $this
     239}
  • trunk/gui/scripts/xyresult.tcl

    r12 r13  
    1616option add *XyResult.height 4i widgetDefault
    1717option add *XyResult.gridColor #d9d9d9 widgetDefault
     18option add *XyResult.hiliteColor black widgetDefault
     19option add *XyResult.controlBackground gray widgetDefault
    1820option add *XyResult.font \
    1921    -*-helvetica-medium-r-normal-*-*-120-* widgetDefault
    2022
     23blt::bitmap define ContourResult-reset {
     24#define reset_width 12
     25#define reset_height 12
     26static unsigned char reset_bits[] = {
     27   0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02,
     28   0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00};
     29}
     30
    2131itcl::class Rappture::XyResult {
    2232    inherit itk::Widget
    2333
    2434    itk_option define -gridcolor gridColor GridColor ""
     35    itk_option define -hilitecolor hiliteColor HiliteColor ""
    2536
    2637    constructor {args} { # defined below }
     
    2839
    2940    public method add {curve {settings ""}}
     41    public method get {}
    3042    public method delete {args}
    3143    public method scale {args}
     
    3345    protected method _rebuild {}
    3446    protected method _fixLimits {}
     47    protected method _zoom {option args}
     48    protected method _hilite {state x y}
    3549
    3650    private variable _clist ""     ;# list of curve objects
    3751    private variable _curve2color  ;# maps curve => plotting color
    3852    private variable _curve2width  ;# maps curve => line width
     53    private variable _curve2dashes ;# maps curve => BLT -dashes list
    3954    private variable _curve2raise  ;# maps curve => raise flag 0/1
    40     private variable _curve2elems  ;# maps curve => elements on graph
     55    private variable _elem2curve   ;# maps graph element => curve
    4156    private variable _xmin ""      ;# autoscale min for x-axis
    4257    private variable _xmax ""      ;# autoscale max for x-axis
    4358    private variable _ymin ""      ;# autoscale min for y-axis
    4459    private variable _ymax ""      ;# autoscale max for y-axis
     60    private variable _hilite ""    ;# info from last _hilite operation
    4561}
    4662                                                                               
     
    5571    option add hull.width hull.height
    5672    pack propagate $itk_component(hull) no
     73
     74    itk_component add controls {
     75        frame $itk_interior.cntls
     76    } {
     77        usual
     78        rename -background -controlbackground controlBackground Background
     79    }
     80    pack $itk_component(controls) -side right -fill y
     81
     82    itk_component add reset {
     83        button $itk_component(controls).reset \
     84            -borderwidth 1 -padx 1 -pady 1 \
     85            -bitmap ContourResult-reset \
     86            -command [itcl::code $this _zoom reset]
     87    } {
     88        usual
     89        ignore -borderwidth
     90        rename -highlightbackground -controlbackground controlBackground Background
     91    }
     92    pack $itk_component(reset) -padx 4 -pady 4
     93    Rappture::Tooltip::for $itk_component(reset) "Reset the view to the default zoom level"
     94
    5795
    5896    itk_component add plot {
     
    65103    pack $itk_component(plot) -expand yes -fill both
    66104
     105    # special pen for highlighting active traces
     106    $itk_component(plot) element bind all <Enter> \
     107        [itcl::code $this _hilite on %x %y]
     108    $itk_component(plot) element bind all <Leave> \
     109        [itcl::code $this _hilite off %x %y]
     110
    67111    Blt_ZoomStack $itk_component(plot)
    68112    $itk_component(plot) legend configure -hide yes
     
    81125#
    82126# Clients use this to add a curve to the plot.  The optional <settings>
    83 # are used to configure the plot.  Allowed settings are -color, -width,
    84 # and -raise.
     127# are used to configure the plot.  Allowed settings are -color,
     128# -brightness, -width, -linestyle and -raise.
    85129# ----------------------------------------------------------------------
    86130itcl::body Rappture::XyResult::add {curve {settings ""}} {
    87131    array set params {
    88132        -color black
     133        -brightness 0
    89134        -width 1
    90135        -raise 0
     136        -linestyle solid
    91137    }
    92138    foreach {opt val} $settings {
     
    95141        }
    96142        set params($opt) $val
     143    }
     144
     145    # convert -linestyle to BLT -dashes
     146    switch -- $params(-linestyle) {
     147        dashed { set params(-linestyle) {4 4} }
     148        dotted { set params(-linestyle) {2 4} }
     149        default { set params(-linestyle) {} }
     150    }
     151
     152    # if -brightness is set, then update the color
     153    if {$params(-brightness) != 0} {
     154        set params(-color) [Rappture::color::brightness \
     155            $params(-color) $params(-brightness)]
    97156    }
    98157
     
    102161        set _curve2color($curve) $params(-color)
    103162        set _curve2width($curve) $params(-width)
     163        set _curve2dashes($curve) $params(-linestyle)
    104164        set _curve2raise($curve) $params(-raise)
    105165
     
    107167        after idle [itcl::code $this _rebuild]
    108168    }
     169}
     170
     171# ----------------------------------------------------------------------
     172# USAGE: get
     173#
     174# Clients use this to query the list of objects being plotted, in
     175# order from bottom to top of this result.
     176# ----------------------------------------------------------------------
     177itcl::body Rappture::XyResult::get {} {
     178    # put the dataobj list in order according to -raise options
     179    set clist $_clist
     180    foreach obj $clist {
     181        if {[info exists _curve2raise($obj)] && $_curve2raise($obj)} {
     182            set i [lsearch -exact $clist $obj]
     183            if {$i >= 0} {
     184                set clist [lreplace $clist $i $i]
     185                lappend clist $obj
     186            }
     187        }
     188    }
     189    return $clist
    109190}
    110191
     
    128209            catch {unset _curve2color($curve)}
    129210            catch {unset _curve2width($curve)}
     211            catch {unset _curve2dashes($curve)}
    130212            catch {unset _curve2raise($curve)}
    131             catch {unset _curve2elems($curve)}
     213            foreach elem [array names _elem2curve] {
     214                if {$_elem2curve($elem) == $curve} {
     215                    unset _elem2curve($elem)
     216                }
     217            }
    132218            set changed 1
    133219        }
     
    191277
    192278    # extract axis information from the first curve
    193     set xydata [lindex $_clist 0]
     279    set clist [get]
     280    set xydata [lindex $clist 0]
    194281    if {$xydata != ""} {
    195282        set legend [$xydata hints legend]
     
    216303    # plot all of the curves
    217304    set count 0
    218     foreach xydata $_clist {
    219         set _curve2elems($xydata) ""
    220 
     305    foreach xydata $clist {
    221306        foreach comp [$xydata components] {
    222307            set xv [$xydata mesh $comp]
     
    238323            }
    239324
     325            if {[info exists _curve2dashes($xydata)]} {
     326                set dashes $_curve2dashes($xydata)
     327            } else {
     328                set dashes ""
     329            }
     330
     331            if {[$xv length] <= 1} {
     332                set sym square
     333            } else {
     334                set sym ""
     335            }
     336
    240337            set elem "elem[incr count]"
    241             lappend _curve2elems($xydata) $elem
     338            set _elem2curve($elem) $xydata
    242339
    243340            set label [$xydata hints label]
    244341            $g element create $elem -x $xv -y $yv \
    245                 -symbol "" -linewidth $lwidth -label $label -color $color
    246 
    247             set style [$xydata hints style]
    248             if {$style != ""} {
    249                 eval $g element configure $elem $style
    250             }
    251         }
    252     }
    253 
    254     # raise those tagged to be on top
    255     set dlist [$g element show]
    256     foreach xydata $_clist {
    257         if {[info exists _curve2raise($xydata)] && $_curve2raise($xydata)} {
    258             foreach elem $_curve2elems($xydata) {
    259                 set i [lsearch -exact $dlist $elem]
    260                 if {$i >= 0} {
    261                     # move element to end of display list
    262                     set dlist [lreplace $dlist $i $i]
    263                     lappend dlist $elem
    264                 }
    265             }
    266         }
    267     }
    268     $g element show $dlist
     342                -symbol $sym -pixels 6 -linewidth $lwidth -label $label \
     343                -color $color -dashes $dashes
     344        }
     345    }
    269346
    270347    _fixLimits
     
    287364    # limits.
    288365    #
    289     $g axis configure x -min $_xmin -max $_xmax
     366    if {$_xmin != $_xmax} {
     367        $g axis configure x -min $_xmin -max $_xmax
     368    } else {
     369        $g axis configure x -min "" -max ""
     370    }
    290371
    291372    if {"" != $_ymin && "" != $_ymax} {
     
    312393            }
    313394        }
    314         $g axis configure y -min $min -max $max
     395        if {$min != $max} {
     396            $g axis configure y -min $min -max $max
     397        } else {
     398            $g axis configure y -min "" -max ""
     399        }
    315400    } else {
    316401        $g axis configure y -min "" -max ""
     402    }
     403}
     404
     405# ----------------------------------------------------------------------
     406# USAGE: _zoom reset
     407#
     408# Called automatically when the user clicks on one of the zoom
     409# controls for this widget.  Changes the zoom for the current view.
     410# ----------------------------------------------------------------------
     411itcl::body Rappture::XyResult::_zoom {option args} {
     412    switch -- $option {
     413        reset {
     414            _fixLimits
     415        }
     416    }
     417}
     418
     419# ----------------------------------------------------------------------
     420# USAGE: _hilite <state> <x> <y>
     421#
     422# Called automatically when the user brushes one of the elements
     423# on the plot.  Causes the element to highlight and a tooltip to
     424# pop up with element info.
     425# ----------------------------------------------------------------------
     426itcl::body Rappture::XyResult::_hilite {state x y} {
     427    set elem [$itk_component(plot) element get current]
     428    if {$state} {
     429        #
     430        # Highlight ON:
     431        # - fatten line
     432        # - change color
     433        # - pop up tooltip about data
     434        #
     435        set t [$itk_component(plot) element cget $elem -linewidth]
     436        $itk_component(plot) element configure $elem -linewidth [expr {$t+2}]
     437
     438        set _hilite [$itk_component(plot) element cget $elem -color]
     439        $itk_component(plot) element configure $elem \
     440            -color $itk_option(-hilitecolor)
     441
     442        set tip ""
     443        if {[info exists _elem2curve($elem)]} {
     444            set curve $_elem2curve($elem)
     445            set tip [$curve hints tooltip]
     446        }
     447        if {"" != $tip} {
     448            set x [expr {$x+4}]  ;# move the tooltip over a bit
     449            set y [expr {$y+4}]
     450            Rappture::Tooltip::text $itk_component(plot) $tip
     451            Rappture::Tooltip::tooltip show $itk_component(plot) +$x,$y
     452        }
     453    } else {
     454        #
     455        # Highlight OFF:
     456        # - put line width back to normal
     457        # - put color back to normal
     458        # - take down tooltip
     459        #
     460        set t [$itk_component(plot) element cget $elem -linewidth]
     461        $itk_component(plot) element configure $elem -linewidth [expr {$t-2}]
     462
     463        if {"" != $_hilite} {
     464            $itk_component(plot) element configure $elem -color $_hilite
     465        }
     466        Rappture::Tooltip::tooltip cancel
    317467    }
    318468}
Note: See TracChangeset for help on using the changeset viewer.