001/*  This parameter, when inserted into a port, causes the port to display its unconsumed inputs.
002
003 @Copyright (c) 2007-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.vergil.actor.lib;
029
030import java.util.Collection;
031import java.util.List;
032
033import ptolemy.actor.IOPort;
034import ptolemy.actor.Receiver;
035import ptolemy.data.Token;
036import ptolemy.kernel.util.IllegalActionException;
037import ptolemy.kernel.util.Location;
038import ptolemy.kernel.util.NameDuplicationException;
039import ptolemy.kernel.util.NamedObj;
040import ptolemy.kernel.util.Settable;
041import ptolemy.kernel.util.SingletonAttribute;
042import ptolemy.kernel.util.ValueListener;
043import ptolemy.vergil.icon.EditorIcon;
044import ptolemy.vergil.kernel.attributes.RectangleAttribute;
045import ptolemy.vergil.kernel.attributes.TextAttribute;
046
047///////////////////////////////////////////////////////////////////
048//// MonitorReceiverAttribute
049
050/**
051 This parameter, when inserted into a port, causes the port to display data
052 available for the actor to read.
053 It assumes that the port is an input port.
054 Otherwise, it returns an empty string. It is a singleton, and it's
055 name is always _showInfo, regardless of what name argument is specified to the constructor.
056 Note that the display is not automatically updated. Use an instance of RepaintController
057 in your model to cause the display to be updated, or use MonitorReceiverContents.
058
059 @author  Edward A. Lee
060 @version $Id$
061 @since Ptolemy II 8.0
062 @Pt.ProposedRating Yellow (eal)
063 @Pt.AcceptedRating Red (cxh)
064 @see MonitorReceiverContents
065 */
066public class MonitorReceiverAttribute extends SingletonAttribute
067        implements Settable {
068
069    /** Construct an actor with the specified container and name.
070     *  @param container The container.
071     *  @param name The name of this actor.
072     *  @exception IllegalActionException If the entity cannot be contained
073     *   by the proposed container.
074     *  @exception NameDuplicationException If the container already has an
075     *   actor with this name.
076     */
077    public MonitorReceiverAttribute(NamedObj container, String name)
078            throws IllegalActionException, NameDuplicationException {
079        super(container, "_showInfo");
080
081        // The icon.
082        EditorIcon _icon = new EditorIcon(this, "_icon");
083        RectangleAttribute rectangle = new RectangleAttribute(_icon,
084                "rectangle");
085        rectangle.width.setExpression("175.0");
086        rectangle.height.setExpression("20.0");
087        rectangle.fillColor.setExpression("{1.0, 0.7, 0.7, 1.0}");
088
089        Location _location = new Location(rectangle, "_location");
090        _location.setExpression("-5.0, -15.0");
091
092        TextAttribute text = new TextAttribute(_icon, "text");
093        text.text.setExpression("MonitorReceiverAttribute");
094    }
095
096    ///////////////////////////////////////////////////////////////////
097    ////                         public methods                    ////
098
099    /** Add a listener to be notified when the value of this settable
100     *  object changes. An implementation of this method should ignore
101     *  the call if the specified listener is already on the list of
102     *  listeners.  In other words, it should not be possible for the
103     *  same listener to be notified twice of a value update.
104     *  @param listener The listener to add.
105     *  @see #removeValueListener(ValueListener)
106     */
107    @Override
108    public void addValueListener(ValueListener listener) {
109        // FIXME: Ignore for now
110    }
111
112    /** Return the default value of this attribute, if there is
113     *  one, or null if there is none.
114     *  @return The default value of this attribute, or null
115     *   if there is none.
116     */
117    @Override
118    public String getDefaultExpression() {
119        return "Queue monitor";
120    }
121
122    /** Return a name to present to the user.
123     *  @return A name to present to the user.
124     */
125    @Override
126    public String getDisplayName() {
127        return "MonitorReceiverAttribute";
128    }
129
130    /** Get the expression currently used by this variable. The expression
131     *  is either the value set by setExpression(), or a string representation
132     *  of the value set by setToken(), or an empty string if no value
133     *  has been set.
134     *  @return The expression used by this variable.
135     *  @see #setExpression(String)
136     */
137    @Override
138    public String getExpression() {
139        try {
140            NamedObj container = getContainer();
141            if (!(container instanceof IOPort)) {
142                return "Not an IOPort";
143            }
144            Receiver[][] receivers = ((IOPort) container).getReceivers();
145            if (receivers == null || receivers.length == 0) {
146                return "";
147            }
148            StringBuffer result = new StringBuffer();
149            if (((IOPort) container).isMultiport()) {
150                result.append("{");
151            }
152            for (int i = 0; i < receivers.length; i++) {
153                if (i > 0) {
154                    result.append("}, {");
155                }
156                for (int j = 0; j < receivers[i].length; j++) {
157                    // Normally there will only be one j with value 0.
158                    // Just in case, put in a separator.
159                    if (j > 0) {
160                        result.append(" AND ");
161                    }
162                    Receiver receiver = receivers[i][j];
163                    if (receiver != null) {
164                        List<Token> list = receiver.elementList();
165                        if (list != null) {
166                            result.append(list);
167                        } else {
168                            result.append("NULL");
169                        }
170                    } else {
171                        result.append("No Receiver");
172                    }
173                }
174            }
175            if (((IOPort) container).isMultiport()) {
176                result.append("}");
177            }
178            return result.toString();
179        } catch (Exception e) {
180            return "ERROR: " + e;
181        }
182    }
183
184    /** Get the value of the attribute, which is the evaluated expression.
185     *  @return The value.
186     *  @see #getExpression()
187     */
188    @Override
189    public String getValueAsString() {
190        return getExpression();
191    }
192
193    /** Get the visibility of this Settable, as set by setVisibility().
194     *  If setVisibility() has not been called, then implementations of
195     *  this interface should return some default, not null, indicating
196     *  user-level visibility. The returned value is one of the static
197     *  instances of the Visibility inner class.
198     *  @return The visibility of this Settable.
199     *  @see #setVisibility(Settable.Visibility)
200     */
201    @Override
202    public Settable.Visibility getVisibility() {
203        return Settable.NOT_EDITABLE;
204    }
205
206    /** Remove a listener from the list of listeners that are
207     *  notified when the value of this variable changes.  If no such listener
208     *  exists, do nothing.
209     *  @param listener The listener to remove.
210     *  @see #addValueListener(ValueListener)
211     */
212    @Override
213    public void removeValueListener(ValueListener listener) {
214        // FIXME: Ignore for now.
215    }
216
217    /** Set the value of the attribute by giving some expression.
218     *  In some implementations, the listeners and the container will
219     *  be notified immediately.  However, some implementations may
220     *  defer notification until validate() is called.
221     *  @param expression The value of the attribute.
222     *  @exception IllegalActionException If the expression is invalid.
223     *  @see #getExpression()
224     */
225    @Override
226    public void setExpression(String expression) throws IllegalActionException {
227        // Ignore.
228        // Do not throw an exception here, as it prevents undo from working.
229    }
230
231    /** Set the visibility of this Settable.  The argument should be one
232     *  of the static public instances of the inner class Visibility.
233     *  This is enforced by making it impossible to construct instances
234     *  of this inner class outside this interface definition.
235     *  If this method is not called, then implementations of
236     *  this interface should return some default, not null.
237     *  @param visibility The visibility of this Settable.
238     *  @see #getVisibility()
239     */
240    @Override
241    public void setVisibility(Settable.Visibility visibility) {
242        // Ignore.
243    }
244
245    /** Check the validity of the expression set in setExpression().
246     *  Implementations of this method should notify the container
247     *  by calling attributeChanged(), unless the container has already
248     *  been notified in setExpression().  They should also notify any
249     *  registered value listeners if they have not already been notified.
250     *  If any other instances of Settable are validated as a side effect,
251     *  then an implementation should return a Collection containing those
252     *  instances. This can be used by the caller to avoid validating those
253     *  again. The list may contain this instance of Settable.
254     *  @return A collection of settables that are also validated as a
255     *   side effect, or null if there are none.
256     *  @exception IllegalActionException If the expression is not valid, or
257     *   its value is not acceptable to the container or the listeners.
258     */
259    @Override
260    public Collection validate() throws IllegalActionException {
261        // Ignore.
262        return null;
263    }
264}