001/* Display a java.awt.Image
002
003 @Copyright (c) 1998-2015 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.image;
029
030import java.awt.Color;
031import java.awt.Container;
032
033import ptolemy.actor.gui.Placeable;
034import ptolemy.actor.injection.ActorModuleInitializer;
035import ptolemy.actor.injection.PtolemyInjector;
036import ptolemy.actor.lib.Sink;
037import ptolemy.data.Token;
038import ptolemy.data.type.BaseType;
039import ptolemy.kernel.CompositeEntity;
040import ptolemy.kernel.util.IllegalActionException;
041import ptolemy.kernel.util.InternalErrorException;
042import ptolemy.kernel.util.NameDuplicationException;
043import ptolemy.kernel.util.Workspace;
044
045///////////////////////////////////////////////////////////////////
046//// ImageDisplay
047
048/**
049 Display an image on the screen using the ptolemy.media.Picture
050 class.  For a sequence of images that are all the same size, this class
051 will continually update the picture with new data.   If the size of the
052 input image changes, then a new Picture object is created.  This class
053 will only accept an ImageToken on its input.
054
055 Note that this class does not work well when executed within Eclipse. In Eclipse, the
056 Swing event thread blocks "waiting for: OGLRenderQueue$QueueFluher", and spends most of its
057 time blocked rather than rendering. Hence, we do not get smooth updates of images.
058
059 @author James Yeh, Edward A. Lee
060 @version $Id$
061 @since Ptolemy II 3.0
062 @Pt.ProposedRating Red
063 @Pt.AcceptedRating Red
064 */
065public class ImageDisplay extends Sink implements Placeable {
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 ImageDisplay(CompositeEntity container, String name)
075            throws IllegalActionException, NameDuplicationException {
076        super(container, name);
077
078        // FIXME: This is required to be an ImageToken, but
079        // we don't see to have that class.
080        input.setTypeEquals(BaseType.GENERAL);
081        _getImplementation().initWindowAndSizeProperties();
082    }
083
084    ///////////////////////////////////////////////////////////////////
085    ////                         public methods                    ////
086
087    /** Free up memory when closing. */
088    public void cleanUp() {
089        _getImplementation().setFrame(null);
090        _getImplementation().cleanUp();
091    }
092
093    /** Clone the actor into the specified workspace. This calls the
094     *  base class and then removes association with graphical objects
095     *  belonging to the original class.
096     *  @param workspace The workspace for the new object.
097     *  @return A new actor.
098     *  @exception CloneNotSupportedException If a derived class contains
099     *   an attribute that cannot be cloned.
100     */
101    @Override
102    public Object clone(Workspace workspace) throws CloneNotSupportedException {
103        ImageDisplay newObject = (ImageDisplay) super.clone(workspace);
104
105        newObject._implementation = null;
106        try {
107            // See _getImplementation():
108            if (PtolemyInjector.getInjector() == null) {
109                System.err.println("Warning: main() did not call "
110                        + "ActorModuleInitializer.initializeInjector(), "
111                        + "so ImageDisplayInterface.clone() is calling it for you.");
112                ActorModuleInitializer.initializeInjector();
113            }
114            newObject._implementation = PtolemyInjector.getInjector()
115                    .getInstance(ImageDisplayInterface.class);
116            newObject._implementation.init(newObject);
117            newObject._implementation.initWindowAndSizeProperties();
118
119        } catch (Exception e) {
120            // This should not occur.
121            throw new CloneNotSupportedException("Clone failed: " + e);
122        }
123
124        return newObject;
125    }
126
127    /** Get the background.
128     *  @return The background color.
129     *  @see #setBackground(Color)
130     */
131    public Color getBackground() {
132        return _getImplementation().getBackground();
133    }
134
135    /** Initialize this actor.
136     *  If place has not been called, then create a frame to display the
137     *  image in.
138     *  @exception IllegalActionException If a contained method throws it.
139     */
140    @Override
141    public void initialize() throws IllegalActionException {
142        super.initialize();
143        _getImplementation().initializeEffigy();
144    }
145
146    /** Set the container that this actor should image display data in.  If place
147     * is not called, then the actor will create its own frame for display.
148     */
149    @Override
150    public void place(Container container) {
151        _getImplementation().placeContainer(container);
152    }
153
154    /** Consume a token from the <i>input</i> port
155     *  and display the token as an image.  If a token is not available,
156     *  do nothing.
157     *  @exception IllegalActionException If there is no director, or
158     *   if the base class throws it.
159     */
160    @Override
161    public boolean postfire() throws IllegalActionException {
162        if (input.hasToken(0)) {
163            final Token in = input.get(0);
164            _getImplementation().display(in);
165        }
166
167        return super.postfire();
168    }
169
170    /** Set the background.
171     *  @param background The background color.
172     *  @see #getBackground()
173     */
174    public void setBackground(Color background) {
175        _getImplementation().setBackground(background);
176    }
177
178    ///////////////////////////////////////////////////////////////////
179    ////                         private methods                   ////
180
181    /** Get the right instance of the implementation depending upon the
182     *  of the dependency specified through dependency injection.
183     *  If the instance has not been created, then it is created.
184     *  If the instance already exists then return the same.
185     *
186     *        <p>This code is used as part of the dependency injection needed for the
187     *  HandSimDroid project, see $PTII/ptserver.  This code uses dependency
188     *  inject to determine what implementation to use at runtime.
189     *  This method eventually reads ptolemy/actor/ActorModule.properties.
190     *  {@link ptolemy.actor.injection.ActorModuleInitializer#initializeInjector()}
191     *  should be called before this method is called.  If it is not
192     *  called, then a message is printed and initializeInjector() is called.</p>
193     *
194     *  @return the instance of the implementation.
195     */
196    protected ImageDisplayInterface _getImplementation() {
197        if (_implementation == null) {
198            if (PtolemyInjector.getInjector() == null) {
199                System.err.println("Warning: main() did not call "
200                        + "ActorModuleInitializer.initializeInjector(), "
201                        + "so ImageDisplay is calling it for you.");
202                ActorModuleInitializer.initializeInjector();
203            }
204            _implementation = PtolemyInjector.getInjector()
205                    .getInstance(ImageDisplayInterface.class);
206            try {
207                _implementation.init(this);
208            } catch (NameDuplicationException e) {
209                throw new InternalErrorException(this, e,
210                        "Failed to initialize implementation");
211            } catch (IllegalActionException e) {
212                throw new InternalErrorException(this, e,
213                        "Failed to initialize implementation");
214            }
215        }
216        return _implementation;
217    }
218
219    ///////////////////////////////////////////////////////////////////
220    ////                         private variables                 ////
221
222    // Implementation of the ImageDisplayInterface
223    private ImageDisplayInterface _implementation;
224
225}