001/* Plot functions of time in oscilloscope style.
002
003 @Copyright (c) 1998-2014 The Regents of the University of California.
004 All rights reserved.
005
006 Permission is hereby granted, without written agreement and without
007 license or royalty fees, to use, copy, modify, and distribute this
008 software and its documentation for any purpose, provided that the
009 above copyright notice and the following two paragraphs appear in all
010 copies of this software.
011
012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
016 SUCH DAMAGE.
017
018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023 ENHANCEMENTS, OR MODIFICATIONS.
024
025 PT_COPYRIGHT_VERSION 2
026 COPYRIGHTENDKEY
027 */
028package ptolemy.actor.lib.gui;
029
030import ptolemy.data.DoubleToken;
031import ptolemy.data.expr.Parameter;
032import ptolemy.data.type.BaseType;
033import ptolemy.kernel.CompositeEntity;
034import ptolemy.kernel.util.Attribute;
035import ptolemy.kernel.util.IllegalActionException;
036import ptolemy.kernel.util.NameDuplicationException;
037import ptolemy.plot.Plot;
038
039///////////////////////////////////////////////////////////////////
040//// TimedScope
041
042/**
043 <p>A signal plotter that plots in an oscilloscope style, meaning that the
044 horizontal axis is wrapped and that there is finite persistence.  This
045 plotter contains an instance of the Plot class from the Ptolemy plot
046 package as a public member.  Data at the input, which can consist of
047 any number of channels, are plotted on this instance.  Each channel is
048 plotted as a separate data set.  The input is of type DoubleToken.
049
050 </p><p>The horizontal axis represents time.  The <i>width</i> parameter is
051 a double that gives the width of the plot. The horizontal axis will be
052 labeled from 0.0 to <i>width</i>.  It defaults to 10.0.
053
054 </p><p>If the <i>persistence</i> parameter is positive, then it specifies
055 the amount of time into the past that points are shown.  It also
056 defaults to 10.0, so any point older than 10.0 time units is erased and
057 forgotten.</p>
058
059 @author  Edward A. Lee
060 @version $Id$
061 @since Ptolemy II 1.0
062 @Pt.ProposedRating Yellow (eal)
063 @Pt.AcceptedRating Yellow (neuendor)
064 */
065public class TimedScope extends TimedPlotter {
066    /** Construct an actor with the given container and name.
067     *  @param container The container.
068     *  @param name The name of this actor.
069     *  @exception IllegalActionException If the actor cannot be contained
070     *   by the proposed container.
071     *  @exception NameDuplicationException If the container already has an
072     *   actor with this name.
073     */
074    public TimedScope(CompositeEntity container, String name)
075            throws IllegalActionException, NameDuplicationException {
076        super(container, name);
077
078        // set the parameters
079        width = new Parameter(this, "width", new DoubleToken(10.0));
080        width.setTypeEquals(BaseType.DOUBLE);
081        persistence = new Parameter(this, "persistence", new DoubleToken(10.0));
082        persistence.setTypeEquals(BaseType.DOUBLE);
083    }
084
085    ///////////////////////////////////////////////////////////////////
086    ////                     ports and parameters                  ////
087
088    /** The width of the X axis (a double). */
089    public Parameter width;
090
091    /** The amount of data displayed at any one time (a double).
092     *  This has units of the X axis.
093     */
094    public Parameter persistence;
095
096    ///////////////////////////////////////////////////////////////////
097    ////                         public methods                    ////
098
099    /** Notify this that an attribute has changed.  If either parameter
100     *  is changed, then this actor updates the configuration of the
101     *  visible plot.
102     *  @param attribute The attribute that changed.
103     *  @exception IllegalActionException If the expression of the
104     *  attribute cannot be parsed or cannot be evaluated.
105     */
106    @Override
107    public void attributeChanged(Attribute attribute)
108            throws IllegalActionException {
109        if (attribute == width && plot != null) {
110            double widthValue = ((DoubleToken) width.getToken()).doubleValue();
111            plot.setXRange(0.0, widthValue);
112        } else if (attribute == persistence && plot != null) {
113            double persValue = ((DoubleToken) persistence.getToken())
114                    .doubleValue();
115
116            // NOTE: We assume the superclass ensures this cast is safe.
117            ((Plot) plot).setXPersistence(persValue);
118        } else {
119            super.attributeChanged(attribute);
120        }
121    }
122
123    /** Initialize this actor.  This method configures the plotter
124     *  using the current parameter values.
125     *  @exception IllegalActionException If the parent class throws it.
126     */
127    @Override
128    public void initialize() throws IllegalActionException {
129        super.initialize();
130
131        double widthValue = ((DoubleToken) width.getToken()).doubleValue();
132        plot.setXRange(0.0, widthValue);
133
134        // NOTE: We assume the superclass ensures this cast is safe.
135        ((Plot) plot).setWrap(true);
136
137        double persValue = ((DoubleToken) persistence.getToken()).doubleValue();
138        ((Plot) plot).setXPersistence(persValue);
139        plot.repaint();
140
141        // Override the default so that there are not gaps in the lines.
142        if (((Plot) plot).getMarksStyle().equals("none")) {
143            ((Plot) plot).setMarksStyle("pixels");
144        }
145    }
146
147    /** Call the base class postfire() method, then yield this
148     *  thread so that the event thread gets a chance.  This is necessary,
149     *  because otherwise the swing thread may be starved and accumulate a
150     *  large number of points waiting to be plotted.
151     *  @exception IllegalActionException If there is no director,
152     *   or if the base class throws it.
153     *  @return True if it is OK to continue.
154     */
155    @Override
156    public boolean postfire() throws IllegalActionException {
157        boolean result = super.postfire();
158        Thread.yield();
159        return result;
160    }
161}