001/* Plot sequences that are potentially infinitely long.
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.IntToken;
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//// SequenceScope
041
042/**
043 <p>A sequence plotter for sequences that are potentially infinitely long.
044 This plotter contains an instance of the Plot
045 class from the Ptolemy plot package as a public member. Data at
046 the input, which can consist of any number of channels, are plotted
047 on this instance.  Each channel is plotted as a separate data set.
048 The horizontal axis represents the count of the iterations, modulo
049 the <i>width</i> parameter, scaled by the <i>xUnit</i> parameter.
050 The <i>width</i> parameter must be an integer that gives the width
051 of the plot in number of samples. It defaults to 10.
052 If the <i>persistence</i> parameter is positive, then it specifies
053 the number of points that are remembered. It also defaults to 10.
054 Any points older than these are erased and forgotten.
055 The horizontal increment between samples is given by the
056 <i>xUnit</i> parameter. Its default value is 1.0. The horizontal value
057 of the first sample is given by the <i>xInit</i> parameter.
058 Its default value is 0.0. The input is of type DoubleToken.
059 </p><p>
060 Note that this actor uses XOR drawing mode, which is fast, but
061 will produce sometimes very annoying artifacts. In particular,
062 when lines or points overlap, they will erase each other (if they
063 are from the same data set) or produce some other color (if
064 they are from distinct data sets).  To avoid these artifacts,
065 use ArrayPlotter.</p>
066
067 @author  Edward A. Lee
068 @version $Id$
069 @since Ptolemy II 1.0
070 @Pt.ProposedRating Yellow (eal)
071 @Pt.AcceptedRating Yellow (neuendor)
072 @see ArrayPlotter
073 */
074public class SequenceScope extends SequencePlotter {
075    /** Construct an actor with the given container and name.
076     *  @param container The container.
077     *  @param name The name of this actor.
078     *  @exception IllegalActionException If the actor cannot be contained
079     *   by the proposed container.
080     *  @exception NameDuplicationException If the container already has an
081     *   actor with this name.
082     */
083    public SequenceScope(CompositeEntity container, String name)
084            throws IllegalActionException, NameDuplicationException {
085        super(container, name);
086
087        // set the parameters
088        width = new Parameter(this, "width", new IntToken(10));
089        width.setTypeEquals(BaseType.INT);
090        persistence = new Parameter(this, "persistence", new IntToken(10));
091        persistence.setTypeEquals(BaseType.INT);
092    }
093
094    ///////////////////////////////////////////////////////////////////
095    ////                     ports and parameters                  ////
096
097    /** The width of the X axis, in number of samples (an integer). */
098    public Parameter width;
099
100    /** The number of samples to be displayed at any one time (an integer). */
101    public Parameter persistence;
102
103    ///////////////////////////////////////////////////////////////////
104    ////                         public methods                    ////
105
106    /** Notify this that an attribute has changed.  If either parameter
107     *  is changed, then this actor updates the configuration of the
108     *  visible plot.
109     *  @param attribute The attribute that changed.
110     *  @exception IllegalActionException If the expression of the
111     *  attribute cannot be parsed or cannot be evaluated.
112     */
113    @Override
114    public void attributeChanged(Attribute attribute)
115            throws IllegalActionException {
116        if ((attribute == width || attribute == xUnit || attribute == xInit)
117                && plot != null) {
118            // Ensure that protected variables are set.
119            super.attributeChanged(attribute);
120
121            int widthValue = ((IntToken) width.getToken()).intValue();
122            plot.setXRange(_xInit, _xUnit * widthValue + _xInit);
123        } else if (attribute == persistence && plot != null) {
124            int persValue = ((IntToken) persistence.getToken()).intValue();
125
126            // NOTE: We assume the superclass ensures this cast is safe.
127            ((Plot) plot).setPointsPersistence(persValue);
128        } else {
129            super.attributeChanged(attribute);
130        }
131    }
132
133    /** Initialize this actor.  This method configures the visible plot
134     *  using the current parameter values.
135     *  @exception IllegalActionException If the parent class throws it.
136     */
137    @Override
138    public void initialize() throws IllegalActionException {
139        super.initialize();
140
141        int widthValue = ((IntToken) width.getToken()).intValue();
142        plot.setXRange(_xInit, _xUnit * widthValue + _xInit);
143        plot.setWrap(true);
144
145        int persValue = ((IntToken) persistence.getToken()).intValue();
146
147        // NOTE: We assume the superclass ensures this cast is safe.
148        ((Plot) plot).setPointsPersistence(persValue);
149
150        // Override the default so that there are not gaps in the lines.
151        // NOTE: We assume the superclass ensures this cast is safe.
152        if (((Plot) plot).getMarksStyle().equals("none")) {
153            ((Plot) plot).setMarksStyle("pixels");
154        }
155
156        plot.repaint();
157    }
158
159    /** Call the base class postfire() method, then yield this
160     *  thread so that the event thread gets a chance.  This is necessary,
161     *  because otherwise the swing thread may be starved and accumulate a
162     *  large number of points waiting to be plotted.
163     *  @exception IllegalActionException If there is no director,
164     *   or if the base class throws it.
165     *  @return True if it is OK to continue.
166     */
167    @Override
168    public boolean postfire() throws IllegalActionException {
169        boolean result = super.postfire();
170        Thread.yield();
171        return result;
172    }
173}