001/* Appletable Plotter
002
003 @Author: Edward A. Lee and Christopher Hylands
004
005 @Version: $Id$
006
007 @Copyright (c) 1997-2018 The Regents of the University of California.
008 All rights reserved.
009
010 Permission is hereby granted, without written agreement and without
011 license or royalty fees, to use, copy, modify, and distribute this
012 software and its documentation for any purpose, provided that the
013 above copyright notice and the following two paragraphs appear in all
014 copies of this software.
015
016 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
017 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
018 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
019 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
020 SUCH DAMAGE.
021
022 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
023 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
024 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
025 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
026 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
027 ENHANCEMENTS, OR MODIFICATIONS.
028
029 PT_COPYRIGHT_VERSION_2
030 COPYRIGHTENDKEY
031 */
032package ptolemy.plot;
033
034import java.awt.BorderLayout;
035import java.awt.Color;
036import java.io.FileNotFoundException;
037import java.io.IOException;
038import java.io.InputStream;
039import java.net.MalformedURLException;
040import java.net.URL;
041
042import javax.swing.JApplet;
043import javax.swing.SwingUtilities;
044
045///////////////////////////////////////////////////////////////////
046//// PlotApplet
047
048/**
049 An Applet that can plot data from a URL.
050 The URL should be specified using the dataurl applet parameter.
051 The formatting commands are included in the file with the
052 the data.
053 If no URL is given, then a sample plot is generated.
054
055 @author Edward A. Lee, Christopher Hylands, Contributor: Roger Robins
056 @version $Id$
057 @since Ptolemy II 0.2
058 @Pt.ProposedRating Yellow (cxh)
059 @Pt.AcceptedRating Yellow (cxh)
060 @see PlotBox
061 @see Plot
062 */
063@SuppressWarnings("serial")
064public class PlotApplet extends JApplet {
065    //     /** Construct a Plot applet */
066    //     public PlotApplet() {
067    // FIXME: having the mutex causes applets to hang.
068    // The mutex was introduced to Work around problem in Java
069    // 1.3.1_08 where if we create 6 instances of a Plot applet then
070    // navigate forward then back - IE and Navigator hang.
071    // However, since we are now operating inside the Swing Event
072    // thread, I think this code is unnecessary.
073    //         if (_mutex == null) {
074    //             _mutex = new Object();
075    //         }
076    //     }
077
078    /** Cleanup after execution of the model.  This method is called
079     *  by the browser or appletviewer to inform this applet that
080     *  it should clean up.
081     */
082    @Override
083    public void destroy() {
084        try {
085            // See http://download.oracle.com/javase/tutorial/uiswing/components/applet.html
086            SwingUtilities.invokeAndWait(new Runnable() {
087                @Override
088                public void run() {
089                    _plot.destroy();
090                    // Needed to get rid of the Mouse, MouseMotion and Key listeners
091                    //getRootPane().getContentPane().removeAll();
092                    getContentPane().remove(_plot);
093                    _plot = null;
094                }
095            });
096        } catch (Throwable throwable) {
097            System.err.println("init() didn't successfully complete");
098            throwable.printStackTrace();
099        }
100        super.destroy();
101    }
102
103    /** Return a string describing this applet.
104     *  @return A string describing the applet.
105     */
106    @Override
107    public String getAppletInfo() {
108        return "PlotApplet " + PlotBox.PTPLOT_RELEASE + ": A data plotter.\n"
109                + "By: Edward A. Lee and\n " + "Christopher Hylands\n"
110                + "($Id$)";
111    }
112
113    /** Return information about parameters.
114     *  @return A array of arrays giving parameter names, the type,
115     *   and the default value or description.
116     */
117    @Override
118    public String[][] getParameterInfo() {
119        String[][] pinfo = {
120                { "background", "hexcolor value", "background color" },
121                { "foreground", "hexcolor value", "foreground color" },
122                { "dataurl", "url", "the URL of the data to plot" },
123                { "height", "integer", "100" },
124                { "width", "integer", "100" }, };
125        return pinfo;
126    }
127
128    /** Initialize the applet.  Read the applet parameters.
129
130     *  Subclasses that extend this method and call Swing UI methods
131     *  should do so in the Swing Event thread by calling
132     *  SwingUtilities.invokeAndWait().
133     *  Note that some Plot methods will automatically run in the
134     *  Swing Event thread, some will not.
135     *  For details about SwingUtilities.invokeAndWait(), see
136     *  <a href="http://download.oracle.com/javase/tutorial/uiswing/components/applet.html#thread">The Sun Applet Tutorial</a>
137     */
138    @Override
139    public void init() {
140        super.init();
141
142        // FIXME: having the mutex causes applets to hang.
143        //synchronized (_mutex) {
144        Runnable doActions = new Runnable() {
145            @Override
146            public void run() {
147                if (_plot == null) {
148                    _plot = newPlot();
149                }
150
151                getContentPane().add(plot(), BorderLayout.NORTH);
152
153                // Process the width and height applet parameters
154                int width;
155
156                // Process the width and height applet parameters
157                int height;
158                String widthspec = getParameter("width");
159
160                if (widthspec != null) {
161                    width = Integer.parseInt(widthspec);
162                } else {
163                    width = 400;
164                }
165
166                String heightspec = getParameter("height");
167
168                if (heightspec != null) {
169                    height = Integer.parseInt(heightspec);
170                } else {
171                    height = 400;
172                }
173
174                _setPlotSize(width, height);
175                plot().setButtons(true);
176
177                // Process the background parameter.
178                Color background = Color.white;
179                String colorspec = getParameter("background");
180
181                if (colorspec != null) {
182                    background = PlotBox.getColorByName(colorspec);
183                }
184
185                setBackground(background);
186                plot().setBackground(background);
187                getContentPane().setBackground(background);
188
189                // Process the foreground parameter.
190                Color foreground = Color.black;
191                colorspec = getParameter("foreground");
192
193                if (colorspec != null) {
194                    foreground = PlotBox.getColorByName(colorspec);
195                }
196
197                setForeground(foreground);
198                plot().setForeground(foreground);
199                plot().setVisible(true);
200
201                // Process the dataurl parameter.
202                String dataurlspec = getParameter("dataurl");
203
204                if (dataurlspec != null) {
205                    try {
206                        showStatus("Reading data");
207
208                        URL dataurl = new URL(getDocumentBase(), dataurlspec);
209                        InputStream in = dataurl.openStream();
210                        _read(in);
211                        showStatus("Done");
212                    } catch (MalformedURLException e) {
213                        System.err.println(e.toString());
214                    } catch (FileNotFoundException e) {
215                        System.err.println("PlotApplet: file not found: " + e);
216                    } catch (IOException e) {
217                        System.err.println(
218                                "PlotApplet: error reading input file: " + e);
219                    }
220                }
221            }
222        };
223
224        try {
225            // NOTE: Using invokeAndWait() here risks causing
226            // deadlock.  However, the Sun Tutorial recommends calling
227            // invokeAndWait so that the work finishes before returning.
228            // if we call invokeLater() then demo/PlotFourierSeries.java
229            // has problems.
230            SwingUtilities.invokeAndWait(doActions);
231        } catch (Throwable throwable) {
232            // Ignore InterruptedException.
233            // Other exceptions should not occur.
234        }
235
236        //}
237    }
238
239    /** Create a new Plot object for the applet.  Derived classes can
240     *  redefine this method to return a different type of plot object.
241     *  @return A new instance of PlotBox.
242     */
243    public PlotBox newPlot() {
244        return new Plot();
245    }
246
247    /** Return the plot object to operate on.
248     *  @return The plot object associated with this applet.
249     */
250    public PlotBox plot() {
251        return _plot;
252    }
253
254    /** Set the plot object to operate on.
255     *  @param plot The plot object to associate with this applet.
256     */
257    public void setPlot(PlotBox plot) {
258        // FIXME: this method is necessary for PxgraphApplet to work
259        // properly.  We could modify newPlot() to set _plot, but
260        // that would change the newPlot() contract, so we add another method.
261        _plot = plot;
262    }
263
264    ///////////////////////////////////////////////////////////////////
265    ////                         protected methods                 ////
266
267    /** Read the specified stream.  Derived classes may override this
268     *  to support other file formats.
269     *  @param in The input stream.
270     *  @exception IOException If the stream cannot be read.
271     */
272    protected void _read(InputStream in) throws IOException {
273        plot().read(in);
274    }
275
276    /** Given the size of the applet, set the size of the plot.
277     *  Derived classes may override this to allow room for other
278     *  widgets below the plot.
279     *  @param appletWidth The width of the applet.
280     *  @param appletHeight The height of the applet.
281     */
282    protected void _setPlotSize(int appletWidth, int appletHeight) {
283        plot().setSize(appletWidth, appletHeight);
284    }
285
286    ///////////////////////////////////////////////////////////////////
287    ////                         private variables                 ////
288    // Work around problem in Java 1.3.1_08 where if we create
289    // 6 instances of a Plot applet then navigate forward then
290    // back - IE and Navigator hang. (Roger Robins)
291    // FIXME: having the mutex causes applets to hang.
292    //private static Object _mutex = null;
293    // The Plot component we are running.
294    private transient PlotBox _plot;
295}