Changeset 3760


Ignore:
Timestamp:
Jul 8, 2013, 12:57:40 PM (11 years ago)
Author:
gah
Message:

rewrite of xyresult to handle limits through graph instead of computing

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/examples/zoo/sequence/sequence2.tcl

    r3177 r3760  
    3131set xmax 1
    3232set npts 30
    33 set elem output.sequence(outs).about.label "Sequence of Plots"
    34 set elem output.sequence(outs).index.label "Parameter A"
     33$driver put output.sequence(outs).about.label "Sequence of Plots"
     34$driver put output.sequence(outs).index.label "Parameter A"
    3535foreach A $avals {
    3636    set elem output.sequence(outs).element($A)
  • trunk/gui/scripts/xylegend.tcl

    r3330 r3760  
    7272    destructor {}
    7373
    74     public method reset {}
     74    public method reset { list }
    7575
    7676    private method Add { elem label {flags ""}}
     
    239239
    240240# ----------------------------------------------------------------------
    241 # USAGE: reset <curve> ?<settings>?
     241# USAGE: reset
    242242#
    243243# Clients use this to add a curve to the plot.  The optional <settings>
     
    245245# -brightness, -width, -linestyle and -raise.
    246246# ----------------------------------------------------------------------
    247 itcl::body Rappture::XyLegend::reset {} {
     247itcl::body Rappture::XyLegend::reset { list } {
    248248    foreach node [$_tree children root] {
    249249        $_tree delete $node
    250250    }
    251     foreach elem [$_graph element show] {
     251    foreach elem $list {
    252252        if {[catch {$_graph element cget $elem -label} label] == 0} {
    253253            if {$label eq ""} {
  • trunk/gui/scripts/xyresult.tcl

    r3749 r3760  
    7171    itk_option define -autocolors autoColors AutoColors ""
    7272
     73    private variable _viewable "";          # Display list for widget.
    7374    constructor {args} {
    7475        # defined below
     
    8889    protected method Rebuild {}
    8990    protected method ResetLimits {}
     91    protected method ResetLegend {}
    9092    protected method Zoom {option args}
    9193    protected method Hilite {state x y}
     
    106108    private variable _dataobj2type   ;# maps dataobj => type of graph element
    107109    private variable _dataobj2barwidth ;# maps dataobj => type of graph element
    108     private variable _elem2dataobj   ;# maps graph element => dataobj
     110    private variable _elem2comp   ;# maps graph element => dataobj
     111    private variable _comp2elem   ;# maps graph element => dataobj
    109112    private variable _label2axis   ;# maps axis label => axis ID
    110113    private variable _limits       ;# axis limits:  x-min, x-max, etc.
     
    117120    private variable _nextElement 0
    118121
     122    private method BuildElements { dlist }
     123    private method BuildMarkers { dataobj elem }
    119124    private method FormatAxis { axis w value }
    120125    private method GetFormattedValue { axis g value }
     
    204209    }
    205210    pack $itk_component(legend) -expand yes -fill both
    206     after idle [subst {
    207         update idletasks
    208         $itk_component(legend) reset
    209     }]
     211    after idle [itcl::code $this ResetLegend]
    210212
    211213    # quick-and-dirty zoom functionality, for now...
     
    230232# ----------------------------------------------------------------------
    231233itcl::body Rappture::XyResult::add {dataobj {settings ""}} {
     234    #puts stderr "XyResult::add dataobj=$dataobj settings=$settings"
    232235    array set params {
    233236        -color auto
     
    293296    }
    294297
    295     set pos [lsearch -exact $dataobj $_dlist]
    296     if {$pos < 0} {
    297         lappend _dlist $dataobj
    298         set _dataobj2color($dataobj) $params(-color)
    299         set _dataobj2width($dataobj) $params(-width)
    300         set _dataobj2dashes($dataobj) $params(-linestyle)
    301         set _dataobj2raise($dataobj) $params(-raise)
    302         set _dataobj2desc($dataobj) $params(-description)
    303         set _dataobj2type($dataobj) $params(-type)
    304         set _dataobj2barwidth($dataobj) $params(-barwidth)
    305         $_dispatcher event -idle !rebuild
    306     }
     298    set dataobj2raise($dataobj) $params(-raise)
     299
     300    set g $itk_component(plot)
     301    set color $params(-color)
     302    set lwidth $params(-width)
     303    set dashes $params(-linestyle)
     304    set raise $params(-raise)
     305    set desc $params(-description)
     306    set type $params(-type)
     307    set barwidth $params(-barwidth)
     308    foreach {mapx mapy} [GetAxes $dataobj] break
     309    foreach comp [$dataobj components] {
     310        set tag $dataobj-$comp
     311        if { [info exists _comp2elem($tag)] } {
     312            set elem $_comp2elem($tag)
     313            switch -- $type {
     314                "line" - "scatter" {
     315                    $g element configure $elem \
     316                        -linewidth $lwidth \
     317                        -dashes $dashes -hide no
     318                } "bar" {
     319                    $g bar configure $elem \
     320                        -barwidth $barwidth \
     321                        -hide no
     322                }
     323            }
     324        } else {
     325            set elem "$type[incr _nextElement]"
     326            set label [$dataobj hints label]
     327            set _elem2comp($elem) $tag
     328            set _comp2elem($tag) $elem
     329            lappend label2elem($label) $elem
     330            set xv [$dataobj mesh $comp]
     331            set yv [$dataobj values $comp]
     332            switch -- $type {
     333                "line" {
     334                    if {([$xv length] <= 1) || ($lwidth == 0)} {
     335                        set sym square
     336                        set pixels 2
     337                    } else {
     338                        set sym ""
     339                        set pixels 6
     340                    }
     341                    $g element create $elem -x $xv -y $yv \
     342                        -symbol $sym -pixels $pixels -linewidth $lwidth \
     343                        -label $label \
     344                        -color $color -dashes $dashes \
     345                        -mapx $mapx -mapy $mapy -hide no
     346                }
     347                "scatter" {
     348                    $g element create $elem -x $xv -y $yv \
     349                        -symbol square -pixels 2 -linewidth $lwidth \
     350                        -label $label \
     351                        -color $color -dashes $dashes \
     352                        -mapx $mapx -mapy $mapy -hide no
     353                }
     354                "bar" {
     355                    $g bar create $elem -x $xv -y $yv \
     356                        -barwidth $barwidth \
     357                        -label $label \
     358                        -color $color \
     359                        -mapx $mapx -mapy $mapy
     360                }
     361            }
     362        }
     363        if { [lsearch $_viewable $elem] < 0 } {
     364            lappend _viewable $elem
     365        }
     366    }
     367    if { [$dataobj info class] == "Rappture::Curve" } {
     368        BuildMarkers $dataobj $elem
     369    }
     370    $_dispatcher event -idle !rebuild
    307371}
    308372
     
    335399# ----------------------------------------------------------------------
    336400itcl::body Rappture::XyResult::delete {args} {
    337     if {[llength $args] == 0} {
    338         set args $_dlist
    339     }
    340 
    341     # delete all specified dataobjs
    342     set changed 0
     401    #puts stderr "XyResult::delete args=$args"
     402    set g $itk_component(plot)
     403
     404    # First try to create list of elements from the dataobjs specified
     405    set elemlist {}
    343406    foreach dataobj $args {
    344         set pos [lsearch -exact $_dlist $dataobj]
    345         if {$pos >= 0} {
    346             set _dlist [lreplace $_dlist $pos $pos]
    347             array unset _dataobj2color    $dataobj
    348             array unset _dataobj2width    $dataobj
    349             array unset _dataobj2dashes   $dataobj
    350             array unset _dataobj2raise    $dataobj
    351             array unset _dataobj2type     $dataobj
    352             array unset _dataobj2barwidth $dataobj
    353             foreach elem [array names _elem2dataobj] {
    354                 if {$_elem2dataobj($elem) == $dataobj} {
    355                     array unset _elem2dataobj $elem
    356                 }
    357             }
    358             set changed 1
    359         }
    360     }
    361 
    362     # If anything changed, then rebuild the plot
    363     if {$changed} {
    364         $_dispatcher event -idle !rebuild
    365     }
    366 
    367     # Nothing left? then start over with auto colors
    368     if {[llength $_dlist] == 0} {
    369         set _autoColorI 0
     407        foreach cname [$dataobj components] {
     408            set tag $dataobj-$cname
     409            if { [info exists _comp2elem($tag)] } {
     410                lappend elemlist $_comp2elem($tag)
     411            }
     412        }
     413    }
     414    # If no dataobjs were specified then hide all elements.
     415    if { [llength $elemlist] == 0 } {
     416        set elemlist [$g element names]
     417    }
     418    # Hide all elements specified by their dataobjs
     419    foreach elem $elemlist {
     420        $g element configure $elem -hide yes
     421        set i [lsearch $_viewable $elem]
     422        if { $i >= 0 } {
     423            set _viewable [lreplace $_viewable $i $i]
     424        }
    370425    }
    371426}
     
    381436# ----------------------------------------------------------------------
    382437itcl::body Rappture::XyResult::scale {args} {
    383     set g $itk_component(plot)
    384 
    385 
    386     set allx [$itk_component(plot) x2axis use]
    387     lappend allx x  ;# fix main x-axis too
    388 
    389     set ally [$itk_component(plot) y2axis use]
    390     lappend ally y  ;# fix main y-axis too
    391     catch {unset _limits}
    392    
    393     eval $g element delete [$g element names]
    394     foreach dataobj $args {
    395         set label [$dataobj hints label]
    396         foreach {mapx mapy} [GetAxes $dataobj] break
    397         foreach comp [$dataobj components] {
    398             set xv [$dataobj mesh $comp]
    399             set yv [$dataobj values $comp]
    400 
    401             if {[info exists _dataobj2type($dataobj)]} {
    402                 set type $_dataobj2type($dataobj)
    403             } else {
    404                 set type "line"
    405             }
    406             if {[info exists _dataobj2barwidth($dataobj)]} {
    407                 set barwidth $_dataobj2barwidth($dataobj)
    408             } else {
    409                 set barwidth 1.0
    410             }
    411             if {[info exists _dataobj2width($dataobj)]} {
    412                 set lwidth $_dataobj2width($dataobj)
    413             } else {
    414                 set lwidth 2
    415             }
    416             if {([$xv length] <= 1) || ($lwidth == 0)} {
    417                 set sym square
    418                 set pixels 2
    419             } else {
    420                 set sym ""
    421                 set pixels 6
    422             }
    423             set elem "elem[incr _nextElement]"
    424             set _elem2dataobj($elem) $dataobj
    425             switch -- $type {
    426                 "line" - "scatter" {
    427                     $g element create $elem -x $xv -y $yv \
    428                         -symbol $sym -pixels $pixels -linewidth $lwidth \
    429                         -mapx $mapx -mapy $mapy
    430                 } "bar" {
    431                     $g bar create $elem -x $xv -y $yv \
    432                         -barwidth $barwidth \
    433                         -mapx $mapx -mapy $mapy
    434                 }
    435             }
    436         }
    437     }
    438     foreach axis {x y} {
    439         if { [info exists _limits({$axis}log)] } {
    440             set type "log"
    441             $g axis configure -logscale 1
    442         } else {
    443             set type "lin"
    444         }
    445         foreach {min max} [$g axis limits $axis] break
    446         set _limits(${axis}-min) $min
    447         set _limits(${axis}-max) $max
    448         set min [$dataobj hints ${axis}min]
    449         set max [$dataobj hints ${axis}max]
    450         if {"" != $min } {
    451             set _limits(${axis}-min) $min
    452         }
    453         if {"" != $max } {
    454             set _limits(${axis}-max) $max
    455         }
    456     }
    457     eval $g element delete [$g element names]
    458     if 0 {
    459     foreach dataobj $args {
    460         # Find the axes for this dataobj (e.g., {x y2})
    461         foreach {map(x) map(y)} [GetAxes $dataobj] break
    462         foreach axis {x y} {
    463             if {[$dataobj hints ${axis}scale] == "log"} {
    464                 set _limits(${axis}log) 1
    465             }
    466             # Get defaults for both linear and log scales
    467             foreach type {lin log} {
    468                 # store results -- ex: _limits(x2log-min)
    469                 set id $map($axis)$type
    470                 set min [$dataobj hints ${axis}min]
    471                 set max [$dataobj hints ${axis}max]
    472                 if {"" != $min && "" != $max} {
    473                     if {![info exists _limits($id-min)]} {
    474                         set _limits($id-min) $min
    475                         set _limits($id-max) $max
    476                     } else {
    477                         if {$min < $_limits($id-min)} {
    478                             set _limits($id-min) $min
    479                         }
    480                         if {$max > $_limits($id-max)} {
    481                             set _limits($id-max) $max
    482                         }
    483                     }
    484                 }
    485             }
    486         }
    487     }
    488     }
    489     ResetLimits
     438    #puts stderr "XyResult::scale args=$args"
     439    set _dlist $args
     440    BuildElements $args
    490441}
    491442
     
    661612
    662613# ----------------------------------------------------------------------
    663 # USAGE: BuildElementsAndMarkers
    664 #
    665 #       This does what "Rebuild" used to.  It (re)creates all the 
    666 #       the elements and markers for the graph based on the data objects
    667 #       given.  The axes are also set if min and max have been set for
    668 #       any data object. 
     614# USAGE: Rebuild
     615#
     616#       Called automatically whenever something changes that affects the
    669617# data in the widget.  Clears any existing data and rebuilds the
    670618# widget to display new data.
    671619# ----------------------------------------------------------------------
    672 itcl::body Rappture::XyResult::BuildElementsAndMarkers { dlist } {
     620itcl::body Rappture::XyResult::Rebuild {} {
     621    ResetLegend
     622    # Fix raise/lower elements
     623}
     624
     625# ----------------------------------------------------------------------
     626# USAGE: ResetLimits
     627#
     628# Used internally to apply automatic limits to the axes for the
     629# current plot.
     630# ----------------------------------------------------------------------
     631itcl::body Rappture::XyResult::ResetLimits {} {
    673632    set g $itk_component(plot)
    674633
    675     # First clear out the widget and hide the axes.
    676     eval $g element delete [$g element names]
    677     eval $g marker delete [$g marker names]
    678     foreach label [array names _label2axis] {
    679         set axis $_label2axis($label)
    680         switch -- $axis {
    681             "x" - "x2" - "y" - "y2" {
    682                 # Do nothing
    683                 $g axis configure $axis -hide yes
    684             }
    685             default {
    686                 $g axis delete $axis
    687             }
    688     }
    689     array unset _label2axis
    690     array unset _limits
    691 
    692     # Scan through all objects and create a list of all axes.
    693     # The first x-axis gets mapped to "x".  The second, to "x2".
    694     # Beyond that, we must create new axes "x3", "x4", etc.
    695     # We do the same for y.
    696 
    697     set anum(x) 0
    698     set anum(y) 0
    699     foreach dataobj $dlist {
    700         foreach axis {x y} {
    701             set label [$dataobj hints ${axis}label]
    702             if { $label == "" } {
     634    foreach axis [$g axis names] {
     635        $g axis configure $axis -min "" -max ""
     636    }
     637}
     638
     639# ----------------------------------------------------------------------
     640# USAGE: ResetLegend
     641#
     642# Used internally to apply automatic limits to the axes for the
     643# current plot.
     644# ----------------------------------------------------------------------
     645itcl::body Rappture::XyResult::ResetLegend {} {
     646    update idletasks
     647
     648    set g $itk_component(plot)
     649    # Fix duplicate labels by appending the simulation number
     650    # Collect the labels from all the viewable elements.
     651    foreach elem $_viewable {
     652        foreach {dataobj cname} [split $_elem2comp($elem) -] break
     653        set label [$dataobj hints label]
     654        lappend label2elem($label) $elem
     655    }
     656    # Then relabel elements with the same label, using the simulation number.
     657    foreach label [array names label2elem] {
     658        foreach elem $label2elem($label) {
     659            if { [llength $label2elem($label)] == 1 } {
     660                $g element configure $elem -label $label
    703661                continue
    704662            }
    705             # Collect the limits (if set for the axis)
    706             set min [$dataobj hints ${axis}min]
    707             set max [$dataobj hints ${axis}max]
    708             if { $min != "" && (![info exists _limits(${label}-min)] ||
    709                                 $_limits(${label}-min) > $min) } {
    710                 set _limits(${label}-min} $min
    711             }
    712             if { $max != "" && (![info exists _limits(${label}-max)] ||
    713                                 $_limits(${label}-max) < $max) } {
    714                 set _limits(${label}-max} $max
    715             }
    716             if  {[$dataobj hints ${axis}scale] == "log"} {
    717                 set _limits(${axis}log) 1
    718             }
    719             if {![info exists _label2axis($label)]} {
    720                 switch [incr anum($axis)] {
    721                     1 { set axisName $axis }
    722                     2 { set axisName ${axis}2 }
    723                     default {
    724                         set axis $axis$anum($axis)
    725                         catch {$g axis create $axisName}
    726                     }
    727                 }
    728                 $g axis configure $axisName -title $label -hide no \
    729                     -checklimits no
    730                 set _label2axis($label) $axisName
    731                
    732                 # if this axis has a description, add it as a tooltip
    733                 set desc [string trim [$dataobj hints ${axis}desc]]
    734                 Rappture::Tooltip::text $g-$axisName $desc
    735             }
    736         }
    737     }
    738 
    739     # Next set the axes based on what we've found.
    740     foreach label [array names _label2axis] {
    741         if { [info exist _limits(${label}log)] } {
    742             set logscale 1
    743         } else {
    744             set logscale 0
    745         }
    746         set amin ""
    747         if { [info exists _limits(${label}-min)] } {
    748             set amin $_limits(${label}-min)
    749         }
    750         set amax ""
    751         if { [info exists _limits(${label}-max)] } {
    752             set amax $_limits(${label}-max)
    753         }
    754         set axis $_label2axis($label)
    755         $g axis configure $axis \
    756             -hide no -checklimits no \
    757             -command [itcl::code $this GetFormattedValue $axis] \
    758             -min $amin -max $amax -logscale $logscale
    759         $g axis bind $axis <Enter> \
    760             [itcl::code $this Axis hilite $axis on]
    761         $g axis bind $axis <Leave> \
    762             [itcl::code $this Axis hilite $axis off]
    763         $g axis bind $axis <ButtonPress-1> \
    764             [itcl::code $this Axis click $axis %x %y]
    765         $g axis bind $axis <B1-Motion> \
    766             [itcl::code $this Axis drag $axis %x %y]
    767         $g axis bind $axis <ButtonRelease-1> \
    768             [itcl::code $this Axis release $axis %x %y]
    769         $g axis bind $axis <KeyPress> \
    770             [list ::Rappture::Tooltip::tooltip cancel]
    771     }
    772 
    773     # Generate all the data elements and markers, but mark them as hidden.
    774     # The Rebuild method will un-hide them.
    775     set count 0
    776     foreach dataobj $dlist {
    777         set label [$dataobj hints label]
    778         foreach {mapx mapy} [GetAxes $dataobj] break
    779         foreach comp [$dataobj components] {
    780             set xv [$dataobj mesh $comp]
    781             set yv [$dataobj values $comp]
    782 
    783             if {[info exists _dataobj2color($dataobj)]} {
    784                 set color $_dataobj2color($dataobj)
    785             } else {
    786                 set color black
    787             }
    788             if {[info exists _dataobj2type($dataobj)]} {
    789                 set type $_dataobj2type($dataobj)
    790             } else {
    791                 set type "line"
    792             }
    793             if {[info exists _dataobj2barwidth($dataobj)]} {
    794                 set barwidth $_dataobj2barwidth($dataobj)
    795             } else {
    796                 set barwidth 1.0
    797             }
    798             if {[info exists _dataobj2width($dataobj)]} {
    799                 set lwidth $_dataobj2width($dataobj)
    800             } else {
    801                 set lwidth 2
    802             }
    803             if {[info exists _dataobj2dashes($dataobj)]} {
    804                 set dashes $_dataobj2dashes($dataobj)
    805             } else {
    806                 set dashes ""
    807             }
    808             if {([$xv length] <= 1) || ($lwidth == 0)} {
    809                 set sym square
    810                 set pixels 2
    811             } else {
    812                 set sym ""
    813                 set pixels 6
    814             }
    815 
    816             set elem "elem[incr _nextElement]"
    817             set _elem2dataobj($elem) $dataobj
    818             lappend label2elem($label) $elem
    819             switch -- $type {
    820                 "line" - "scatter" {
    821                     $g element create $elem -x $xv -y $yv \
    822                         -symbol $sym -pixels $pixels -linewidth $lwidth \
    823                         -label $label \
    824                         -color $color -dashes $dashes \
    825                         -mapx $mapx -mapy $mapy -hide yes
    826                 } "bar" {
    827                     $g bar create $elem -x $xv -y $yv \
    828                         -barwidth $barwidth \
    829                         -label $label \
    830                         -color $color \
    831                         -mapx $mapx -mapy $mapy -hide yes
    832                 }
    833             }
    834             if { [$dataobj info class] == "Rappture::Curve" } {
    835                 BuildMarkers $dataobj $elem
    836             }
    837         }
    838     }
    839     # Fix duplicate labels by appending the simulation number
    840     foreach label [array names label2elem] {
    841         if { [llength $label2elem($label)] == 1 } {
    842             continue
    843         }
    844         foreach elem $label2elem($label) {
    845             set dataobj $_elem2dataobj($elem)
     663            foreach {dataobj cname} [split $_elem2comp($elem) -] break
    846664            regexp {^::curve(?:Value)?([0-9]+)$} $dataobj match suffix
    847665            incr suffix
     
    850668        }
    851669    }       
    852     $itk_component(legend) reset
    853 }
    854 
    855 # ----------------------------------------------------------------------
    856 # USAGE: Rebuild
    857 #
    858 #       Called automatically whenever something changes that affects the
    859 # data in the widget.  Clears any existing data and rebuilds the
    860 # widget to display new data.
    861 # ----------------------------------------------------------------------
    862 itcl::body Rappture::XyResult::Rebuild {} {
    863     set g $itk_component(plot)
    864 
    865     # First clear out the widget
    866     eval $g element delete [$g element names]
    867     eval $g marker delete [$g marker names]
    868 
    869     foreach axis [$g axis names] {
    870         if { [info exist _limits(${axis}log)] } {
    871             set type "log"
    872             set logscale 1
    873         } else {
    874             set type "lin"
    875             set logscale 0
    876         }
    877         set amin ""
    878         if { [info exists _limits(${axis}-min)] } {
    879             set amin $_limits(${axis}-min)
    880         }
    881         set amax ""
    882         if { [info exists _limits(${axis}-max)] } {
    883             set amax $_limits(${axis}-max)
    884         }
    885         $g axis configure $axis \
    886             -hide yes -checklimits no \
    887             -command [itcl::code $this GetFormattedValue $axis] \
    888             -min $amin -max $amax -logscale $logscale
    889     }
    890     # Presumably you want at least an X-axis and Y-axis displayed.
    891     $g xaxis configure -hide no
    892     $g yaxis configure -hide no
    893     array unset _label2axis
    894 
    895     #
    896     # Scan through all objects and create a list of all axes.
    897     # The first x-axis gets mapped to "x".  The second, to "x2".
    898     # Beyond that, we must create new axes "x3", "x4", etc.
    899     # We do the same for y.
    900     #
    901     set anum(x) 0
    902     set anum(y) 0
    903     foreach dataobj [get] {
    904         foreach ax {x y} {
    905             set label [$dataobj hints ${ax}label]
    906             if {"" != $label} {
    907                 if {![info exists _label2axis($ax-$label)]} {
    908                     switch [incr anum($ax)] {
    909                         1 { set axis $ax }
    910                         2 { set axis ${ax}2 }
    911                         default {
    912                             set axis $ax$anum($ax)
    913                             catch {$g axis create $axis}
    914                         }
    915                     }
    916                     $g axis configure $axis -title $label -hide no \
    917                         -checklimits no
    918                     set _label2axis($ax-$label) $axis
    919 
    920                     # if this axis has a description, add it as a tooltip
    921                     set desc [string trim [$dataobj hints ${ax}desc]]
    922                     Rappture::Tooltip::text $g-$axis $desc
    923                 }
    924             }
    925         }
    926     }
    927 
    928     #
    929     # All of the extra axes get mapped to the x2/y2 (top/right)
    930     # position.
    931     #
    932     set all ""
    933     foreach ax {x y} {
    934         lappend all $ax
    935 
    936         set extra ""
    937         for {set i 2} {$i <= $anum($ax)} {incr i} {
    938             lappend extra ${ax}$i
    939         }
    940         eval lappend all $extra
    941         $g ${ax}2axis use $extra
    942         if {$ax == "y"} {
    943             $g configure -rightmargin [expr {($extra == "") ? 10 : 0}]
    944         }
    945     }
    946 
    947     foreach axis $all {
    948         $g axis bind $axis <Enter> \
    949             [itcl::code $this Axis hilite $axis on]
    950         $g axis bind $axis <Leave> \
    951             [itcl::code $this Axis hilite $axis off]
    952         $g axis bind $axis <ButtonPress-1> \
    953             [itcl::code $this Axis click $axis %x %y]
    954         $g axis bind $axis <B1-Motion> \
    955             [itcl::code $this Axis drag $axis %x %y]
    956         $g axis bind $axis <ButtonRelease-1> \
    957             [itcl::code $this Axis release $axis %x %y]
    958         $g axis bind $axis <KeyPress> \
    959             [list ::Rappture::Tooltip::tooltip cancel]
    960     }
    961 
    962     #
    963     # Plot all of the dataobjs.
    964     #
    965     set count 0
    966     foreach dataobj $_dlist {
    967         set label [$dataobj hints label]
    968         foreach {mapx mapy} [GetAxes $dataobj] break
    969         foreach comp [$dataobj components] {
    970             set xv [$dataobj mesh $comp]
    971             set yv [$dataobj values $comp]
    972 
    973             if {[info exists _dataobj2color($dataobj)]} {
    974                 set color $_dataobj2color($dataobj)
    975             } else {
    976                 set color black
    977             }
    978             if {[info exists _dataobj2type($dataobj)]} {
    979                 set type $_dataobj2type($dataobj)
    980             } else {
    981                 set type "line"
    982             }
    983             if {[info exists _dataobj2barwidth($dataobj)]} {
    984                 set barwidth $_dataobj2barwidth($dataobj)
    985             } else {
    986                 set barwidth 1.0
    987             }
    988             if {[info exists _dataobj2width($dataobj)]} {
    989                 set lwidth $_dataobj2width($dataobj)
    990             } else {
    991                 set lwidth 2
    992             }
    993             if {[info exists _dataobj2dashes($dataobj)]} {
    994                 set dashes $_dataobj2dashes($dataobj)
    995             } else {
    996                 set dashes ""
    997             }
    998             if {([$xv length] <= 1) || ($lwidth == 0)} {
    999                 set sym square
    1000                 set pixels 2
    1001             } else {
    1002                 set sym ""
    1003                 set pixels 6
    1004             }
    1005 
    1006             set elem "elem[incr _nextElement]"
    1007             set _elem2dataobj($elem) $dataobj
    1008             lappend label2elem($label) $elem
    1009             switch -- $type {
    1010                 "line" - "scatter" {
    1011                     $g element create $elem -x $xv -y $yv \
    1012                         -symbol $sym -pixels $pixels -linewidth $lwidth \
    1013                         -label $label \
    1014                         -color $color -dashes $dashes \
    1015                         -mapx $mapx -mapy $mapy
    1016                 } "bar" {
    1017                     $g bar create $elem -x $xv -y $yv \
    1018                         -barwidth $barwidth \
    1019                         -label $label \
    1020                         -color $color \
    1021                         -mapx $mapx -mapy $mapy
    1022                 }
    1023             }
    1024         }
    1025     }
    1026 
    1027     # Fix duplicate labels by appending the simulation number
    1028     foreach label [array names label2elem] {
    1029         if { [llength $label2elem($label)] == 1 } {
    1030             continue
    1031         }
    1032         foreach elem $label2elem($label) {
    1033             set dataobj $_elem2dataobj($elem)
    1034             regexp {^::curve(?:Value)?([0-9]+)$} $dataobj match suffix
    1035             incr suffix
    1036             set elabel [format "%s \#%d" $label $suffix]
    1037             $g element configure $elem -label $elabel
    1038         }
    1039     }       
    1040 
    1041     foreach dataobj $_dlist {
    1042         set xmin -Inf
    1043         set ymin -Inf
    1044         set xmax Inf
    1045         set ymax Inf
    1046         #
    1047         # Create text/line markers for each *axis.marker specified.
    1048         #
    1049         if { [$dataobj info class] == "Rappture::Curve" } {
    1050             foreach m [$dataobj xmarkers] {
    1051                 foreach {at label style} $m break
    1052                 set id [$g marker create line \
    1053                             -coords [list $at $ymin $at $ymax]]
    1054                 $g marker bind $id <Enter> \
    1055                     [itcl::code $this EnterMarker $g x-$label $at $ymin $at]
    1056                 $g marker bind $id <Leave> \
    1057                     [itcl::code $this LeaveMarker $g x-$label]
    1058                 set options [GetLineMarkerOptions $style]
    1059                 if { $options != "" } {
    1060                     eval $g marker configure $id $options
    1061                 }
    1062                 if { $label != "" } {
    1063                     set id [$g marker create text -anchor nw \
    1064                                 -text $label -coords [list $at $ymax]]
    1065                     set options [GetTextMarkerOptions $style]
    1066                     if { $options != "" } {
    1067                         eval $g marker configure $id $options
    1068                     }
    1069                 }
    1070             }
    1071             foreach m [$dataobj ymarkers] {
    1072                 foreach {at label style} $m break
    1073                 set id [$g marker create line \
    1074                             -coords [list $xmin $at $xmax $at]]
    1075                 $g marker bind $id <Enter> \
    1076                     [itcl::code $this EnterMarker $g y-$label $at $xmin $at]
    1077                 $g marker bind $id <Leave> \
    1078                     [itcl::code $this LeaveMarker $g y-$label]
    1079                 set options [GetLineMarkerOptions $style]
    1080                 if { $options != "" } {
    1081                     eval $g marker configure $id $options
    1082                 }
    1083                 if { $label != "" } {
    1084                     set id [$g marker create text -anchor se \
    1085                                 -text $label -coords [list $xmax $at]]
    1086                     set options [GetTextMarkerOptions $style]
    1087                     if { $options != "" } {
    1088                         eval $g marker configure $id $options
    1089                     }
    1090                 }
    1091             }
    1092         }
    1093     }
    1094     $itk_component(legend) reset
    1095 }
    1096 
    1097 # ----------------------------------------------------------------------
    1098 # USAGE: ResetLimits
    1099 #
    1100 # Used internally to apply automatic limits to the axes for the
    1101 # current plot.
    1102 # ----------------------------------------------------------------------
    1103 itcl::body Rappture::XyResult::ResetLimits {} {
    1104     set g $itk_component(plot)
    1105 
    1106     foreach axis [$g axis names] {
    1107         $g axis configure $axis -min "" -max ""
    1108     }
    1109 }
     670    $itk_component(legend) reset $_viewable
     671}
     672
    1110673
    1111674# ----------------------------------------------------------------------
     
    1150713            set mapx [$g element cget $elem -mapx]
    1151714            set mapy [$g element cget $elem -mapy]
    1152             if {[info exists _elem2dataobj($elem)]} {
    1153                 foreach {mapx mapy} [GetAxes $_elem2dataobj($elem)] break
     715            if {[info exists _elem2comp($elem)]} {
     716                foreach {dataobj cname} [split $_elem2comp($elem) -] break
     717                foreach {mapx mapy} [GetAxes $dataobj] break
    1154718            }
    1155719
     
    1163727                set y [$g axis transform $mapy $info(y)]
    1164728               
    1165                 if {[info exists _elem2dataobj($elem)]} {
    1166                     set dataobj $_elem2dataobj($elem)
     729                if {[info exists _elem2comp($elem)]} {
     730                    foreach {dataobj cname} [split $_elem2comp($elem) -] break
    1167731                    set yunits [$dataobj hints yunits]
    1168732                    set xunits [$dataobj hints xunits]
     
    1187751            set mapx [$g element cget $elem -mapx]
    1188752            set mapy [$g element cget $elem -mapy]
    1189             if {[info exists _elem2dataobj($elem)]} {
    1190                 foreach {mapx mapy} [GetAxes $_elem2dataobj($elem)] break
     753            if {[info exists _elem2comp($elem)]} {
     754                foreach {dataobj cname} [split $_elem2comp($elem) -] break
     755                foreach {mapx mapy} [GetAxes $dataobj] break
    1191756            }
    1192757
     
    1195760            set y [$g axis transform $mapy $info(y)]
    1196761               
    1197             if {[info exists _elem2dataobj($elem)]} {
    1198                 set dataobj $_elem2dataobj($elem)
     762            if {[info exists _elem2comp($elem)]} {
     763                foreach {dataobj cname} [split $_elem2comp($elem) -] break
    1199764                set yunits [$dataobj hints yunits]
    1200765                set xunits [$dataobj hints xunits]
     
    1232797        set mapx [$g element cget $elem -mapx]
    1233798        set mapy [$g element cget $elem -mapy]
    1234         if {[info exists _elem2dataobj($elem)]} {
    1235             foreach {mapx mapy} [GetAxes $_elem2dataobj($elem)] break
     799        if {[info exists _elem2comp($elem)]} {
     800            foreach {dataobj cname} [split $_elem2comp($elem) -] break
     801            foreach {mapx mapy} [GetAxes $dataobj] break
    1236802        }
    1237803        set allx [$g x2axis use]
     
    19431509    return [format $fmt $value]
    19441510}
     1511
     1512
     1513#
     1514# BuildElements --
     1515#
     1516#       This procedure loads each data objects specified into the
     1517#       graph.  The data object may already be loaded (from the "add"
     1518#       method which gets called first).   The graph elements that
     1519#       are created, are hidden.  This allows the graph to account
     1520#       for all datasets, even those not currently being displayed.
     1521#       
     1522itcl::body Rappture::XyResult::BuildElements { dlist } {
     1523    set g $itk_component(plot)
     1524   
     1525    foreach label [array names _label2axis] {
     1526        set axis $_label2axis($label)
     1527        switch -- $axis {
     1528            "x" - "x2" - "y" - "y2" {
     1529                $g axis configure $axis -hide yes
     1530            }
     1531            default {
     1532                $g axis delete $axis
     1533            }
     1534        }
     1535    }
     1536    array unset _label2axis
     1537    array unset _limits
     1538
     1539    # Scan through all objects and create a list of all axes.
     1540    # The first x-axis gets mapped to "x".  The second, to "x2".
     1541    # Beyond that, we must create new axes "x3", "x4", etc.
     1542    # We do the same for y.
     1543   
     1544    set anum(x) 0
     1545    set anum(y) 0
     1546    foreach dataobj $dlist {
     1547        foreach axis {x y} {
     1548            set label [$dataobj hints ${axis}label]
     1549            if { $label == "" } {
     1550                continue
     1551            }
     1552            # Collect the limits (if set for the axis)
     1553            set min [$dataobj hints ${axis}min]
     1554            set max [$dataobj hints ${axis}max]
     1555            set tag ${label}-min
     1556            if { $min != "" && ( ![info exists _limits($tag)] ||
     1557                                   $_limits($tag) > $min ) } {
     1558                set _limits(tag) $min
     1559            }
     1560            set tag ${label}-max
     1561            if { $max != "" && (![info exists _limits($tag)] ||
     1562                                  $_limits($tag) < $max) } {
     1563                set _limits($tag) $max
     1564            }
     1565            if  { [$dataobj hints ${axis}scale] == "log" } {
     1566                set _limits(${axis}log) 1
     1567            }
     1568            if { ![info exists _label2axis($label)] } {
     1569                switch [incr anum($axis)] {
     1570                    1 { set axisName $axis }
     1571                    2 { set axisName ${axis}2 }
     1572                    default {
     1573                        set axis $axis$anum($axis)
     1574                        catch {$g axis create $axisName}
     1575                    }
     1576                }
     1577                $g axis configure $axisName -title $label -hide no \
     1578                    -checklimits no
     1579                set _label2axis($label) $axisName
     1580               
     1581                # If this axis has a description, add it as a tooltip
     1582                set desc [string trim [$dataobj hints ${axis}desc]]
     1583                Rappture::Tooltip::text $g-$axisName $desc
     1584            }
     1585        }
     1586    }
     1587    # Next set the axes based on what we've found.
     1588    foreach label [array names _label2axis] {
     1589        set logscale [info exists _limits(${label}log)]
     1590        set amin ""
     1591        if { [info exists _limits(${label}-min)] } {
     1592            set amin $_limits(${label}-min)
     1593        }
     1594        set amax ""
     1595        if { [info exists _limits(${label}-max)] } {
     1596            set amax $_limits(${label}-max)
     1597        }
     1598        set axis $_label2axis($label)
     1599        $g axis configure $axis \
     1600            -hide no -checklimits no \
     1601            -command [itcl::code $this GetFormattedValue $axis] \
     1602            -min $amin -max $amax -logscale $logscale
     1603        $g axis bind $axis <Enter> \
     1604            [itcl::code $this Axis hilite $axis on]
     1605        $g axis bind $axis <Leave> \
     1606            [itcl::code $this Axis hilite $axis off]
     1607        $g axis bind $axis <ButtonPress-1> \
     1608            [itcl::code $this Axis click $axis %x %y]
     1609        $g axis bind $axis <B1-Motion> \
     1610            [itcl::code $this Axis drag $axis %x %y]
     1611        $g axis bind $axis <ButtonRelease-1> \
     1612            [itcl::code $this Axis release $axis %x %y]
     1613        $g axis bind $axis <KeyPress> \
     1614            [list ::Rappture::Tooltip::tooltip cancel]
     1615    }
     1616   
     1617    # Create data elements and markers, but mark them as hidden.
     1618    # The "add" method will un-hide them.
     1619    set count 0
     1620    foreach dataobj $dlist {
     1621        set label [$dataobj hints label]
     1622        array set params [$dataobj hints style]
     1623        # Default
     1624        if {[info exists params(-color)]} {
     1625            set color params(-color)
     1626        } else {
     1627            set color black
     1628        }
     1629        if {[info exists parmas(-type)]} {
     1630            set type $params(-type)
     1631        } else {
     1632            set type "line"
     1633        }
     1634        if {[info exists parmas(-barwidth)]} {
     1635            set barwidth $params(-barwidth)
     1636        } else {
     1637            set barwidth 1.0
     1638        }
     1639        if {[info exists params(-width)]} {
     1640            set lwidth $params(-width)
     1641        } else {
     1642            set lwidth 2
     1643        }
     1644        if {[info exists params(-linestyle)]} {
     1645            set dashes $parmas(-linestyle)
     1646        } else {
     1647            set dashes ""
     1648        }
     1649        foreach {mapx mapy} [GetAxes $dataobj] break
     1650        foreach comp [$dataobj components] {
     1651            set tag $dataobj-$comp
     1652            if { [info exists _comp2elem($tag)] } {
     1653                set found($_comp2elem($tag)) 1
     1654                lappend label2elem($label) $_comp2elem($tag)
     1655                # Element already created for data object/component.
     1656                continue
     1657            }
     1658            set xv [$dataobj mesh $comp]
     1659            set yv [$dataobj values $comp]
     1660           
     1661            if {([$xv length] <= 1) || ($lwidth == 0)} {
     1662                set sym square
     1663                set pixels 2
     1664            } else {
     1665                set sym ""
     1666                set pixels 6
     1667            }
     1668            set elem "elem[incr _nextElement]"
     1669            set _elem2comp($elem) $tag
     1670            set _comp2elem($tag) $elem
     1671            set found($_comp2elem($tag)) 1
     1672            lappend label2elem($label) $elem
     1673            switch -- $type {
     1674                "line" - "scatter" {
     1675                    $g element create $elem \
     1676                        -x $xv -y $yv \
     1677                        -symbol $sym \
     1678                        -pixels $pixels \
     1679                        -linewidth $lwidth \
     1680                        -label $label \
     1681                        -color $color \
     1682                        -dashes $dashes \
     1683                        -mapx $mapx \
     1684                        -mapy $mapy \
     1685                        -hide yes
     1686                } "bar" {
     1687                    $g bar create $elem \
     1688                        -x $xv -y $yv \
     1689                        -barwidth $barwidth \
     1690                        -label $label \
     1691                        -color $color \
     1692                        -mapx $mapx \
     1693                        -mapy $mapy \
     1694                        -hide yes
     1695                }
     1696            }
     1697            if { [$dataobj info class] == "Rappture::Curve" } {
     1698                BuildMarkers $dataobj $elem
     1699            }
     1700        }
     1701    }
     1702    foreach elem [$g element names] {
     1703        if { ![info exists found($elem)] } {
     1704            $g element delete $elem
     1705        }
     1706    }
     1707    ResetLegend
     1708}
Note: See TracChangeset for help on using the changeset viewer.