001/* A standalone plot application.
002
003 Copyright (c) 1998-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026 */
027package ptolemy.plot;
028
029import java.awt.event.WindowAdapter;
030import java.awt.event.WindowEvent;
031import java.io.File;
032import java.io.FileInputStream;
033import java.io.FileNotFoundException;
034import java.io.IOException;
035import java.io.InputStream;
036import java.net.MalformedURLException;
037import java.net.URL;
038
039import javax.swing.JOptionPane;
040import javax.swing.SwingUtilities;
041
042import ptolemy.util.StringUtilities;
043
044///////////////////////////////////////////////////////////////////
045//// PlotApplication
046
047/**
048 PlotApplication is a versatile two-dimensional data plotter application.
049 <p>It can read files compatible with the Ptolemy plot
050 file format (currently only ASCII).  For a description of the file
051 format, see the Plot and PlotBox classes.
052 Command-line options include:</p>
053
054 <dl>
055
056 <dt><code>-help</code></dt>
057 <dd>Print the usage, including all command-line options
058 that exist for backward compatibility and then exit.
059 The help menu choice will display the same information.</dd>
060
061 <dt><code>-test</code></dt>
062 <dd>Display the plot, then exit after 2 seconds.</dd>
063
064 <dt><code>-version</code></dt>
065 <dd>Print the program version and then exit.
066 While ptplot is running,
067 the version menu choice will display the same information.</dd>
068
069 <dt><code>-</code></dt>
070 <dd>Read the plot data from standard in.</dd>
071
072 </dl>
073
074 <p>
075 For compatibility with historical applications, this application has
076 a limited ability to read pxgraph files.  The command line arguments
077 must be used, and the options that are understood are exactly those
078 of the pxgraph application, plus some more to allow for cross-platform
079 reading.  It is not possible to read pxgraph files
080 using the "Open" menu command (because of the cross-platform problems).
081 The additional command-line arguments are:</p>
082
083 <dl>
084
085 <dt><code>-bigendian</code></dt>
086 <dd>Data files are in big-endian, or network binary format.
087 If you are on a little-endian machine, such as a machine
088 with an Intel x86 chip, and you would like to read a binary
089 format file created on a big-endian machine, such as a Sun SPARC,
090 use the <code>-bigendian</code> flag.</dd>
091
092 <dt><code>-littleendian</code></dt>
093 <dd>Data files are in little-endian, or x86 binary format.
094 If you are on a big-endian machine, such as a Sun Sparc,
095 and you would like to read a binary
096 format file created on a little-endian machine, such as Intel x86
097 machine, then use the <code>-littleendian</code> flag.</dd>
098 </dl>
099
100 <p>
101 To compile and run this application, do the following:</p>
102 <pre>
103 javac -classpath ../.. PlotApplication.java
104 java -classpath ../.. ptolemy.plot.PlotApplication
105 </pre>
106 <p>
107 This assumes a particular directory structure.  If this is not what you
108 have, then alter the above accordingly.</p>
109
110 @see Plot
111 @see PlotBox
112 @author Christopher Brooks and Edward A. Lee
113 @version $Id$
114 @since Ptolemy II 0.2
115 @Pt.ProposedRating Yellow (cxh)
116 @Pt.AcceptedRating Yellow (cxh)
117 */
118@SuppressWarnings("serial")
119public class PlotApplication extends PlotFrame {
120    /** Construct a plot with no command-line arguments.
121     *  It initially displays a sample plot.
122     *  @exception Exception Not thrown in this base class.
123     */
124    public PlotApplication() throws Exception {
125        this(new String[0]);
126    }
127
128    /** Construct a plot with the specified command-line arguments.
129     *  @param args The command-line arguments.
130     *  @exception Exception If command line arguments have problems.
131     */
132    public PlotApplication(String[] args) throws Exception {
133        this(new Plot(), args);
134    }
135
136    /** Construct a plot with the specified command-line arguments
137     *  and instance of plot.  If there are no command-line arguments,
138     *  then display a sample plot.
139     *  @param plot The instance of Plot to use.
140     *  @param args The command-line arguments.
141     *  @exception Exception If command line arguments have problems.
142     */
143    public PlotApplication(PlotBox plot, String[] args) throws Exception {
144        // invoke the base class constructor and pass in the argument a Plot
145        // object. This makes sure that the plot field is an instance of
146        // Plot class.
147        super("PlotApplication", plot);
148
149        // Handle window closing by exiting the application.
150        addWindowListener(new WindowClosingAdapter());
151
152        _parseArgs(args);
153
154        if (args == null || args.length == 0) {
155            samplePlot();
156        }
157
158        setVisible(true);
159
160        if (_printPDF) {
161            _printPDF();
162        }
163    }
164
165    /** Display the given plot.  Unlike the two argument constructor,
166     *  this does not take command-line arguments, and does not fill
167     *  the plot with a sample plot.
168     *  @param plot The instance of Plot to display.
169     */
170    public PlotApplication(PlotBox plot) {
171        // Invoke the base class constructor and pass in the argument a Plot
172        // object. This makes sure that the plot field is an instance of
173        // Plot class.
174        super("PlotApplication", plot);
175
176        // Handle window closing by exiting the application.
177        addWindowListener(new WindowClosingAdapter());
178
179        setVisible(true);
180    }
181
182    ///////////////////////////////////////////////////////////////////
183    ////                         public methods                    ////
184
185    /** Create a new plot window and map it to the screen.
186     *        @param args The command line arguments.  See the class comment
187     *  for details.
188     */
189    public static void main(final String[] args) {
190        try {
191            // Run this in the Swing Event Thread.
192            Runnable doActions = new Runnable() {
193                @Override
194                public void run() {
195                    try {
196                        new PlotApplication(new Plot(), args);
197                    } catch (Exception ex) {
198                        System.err.println(ex.toString());
199                        ex.printStackTrace();
200                    }
201                }
202            };
203
204            SwingUtilities.invokeAndWait(doActions);
205        } catch (Throwable throwable) {
206            throwable.printStackTrace();
207        }
208
209        // If the -test arg was set, then exit after 2 seconds.
210        if (_test) {
211            try {
212                Thread.sleep(2000);
213            } catch (InterruptedException e) {
214            }
215
216            StringUtilities.exit(0);
217        }
218    }
219
220    ///////////////////////////////////////////////////////////////////
221    ////                         protected methods                 ////
222    @Override
223    protected void _about() {
224        JOptionPane.showMessageDialog(this,
225                "PlotApplication class\n" + "By: Edward A. Lee "
226                        + "and Christopher Brooks\n" + "Version "
227                        + PlotBox.PTPLOT_RELEASE + ", Build: $Id$\n\n"
228                        + "For more information, see\n"
229                        + "http://ptolemy.eecs.berkeley.edu/java/ptplot\n\n"
230                        + "Copyright (c) 1997-2014, "
231                        + "The Regents of the University of California.",
232                "About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
233    }
234
235    /** Exit the application.
236     */
237    @Override
238    protected void _close() {
239        StringUtilities.exit(0);
240    }
241
242    /** Display more detailed information than given by _about().
243     */
244    @Override
245    protected void _help() {
246        JOptionPane.showMessageDialog(this,
247                "PlotApplication is a standalone plot " + " application.\n"
248                        + "  File formats understood: Ptplot ASCII.\n"
249                        + "  Left mouse button: Zooming.\n\n" + _usage(),
250                "About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
251    }
252
253    /** Parse the command-line
254     *  arguments and make calls to the Plot class accordingly.
255     *        @param args The command line arguments.  See the class comment
256     *  for details.
257     *  @return The number of arguments read.
258     *  @exception CmdLineArgException If a command line argument cannot
259     *  be parsed.
260     *  @exception FileNotFoundException If an input file cannot be found.
261     *  @exception IOException If there is a problem reading an input.
262     */
263    protected int _parseArgs(String[] args)
264            throws CmdLineArgException, FileNotFoundException, IOException {
265        int i = 0;
266        int argumentsRead;
267        String arg;
268        String title = "Ptolemy plot";
269
270        int width = 500; // Default width of the graph
271        int height = 300; // Default height of the graph
272
273        while (args != null && i < args.length) {
274            arg = args[i++];
275
276            if (arg.equals("-height")) {
277                if (i > args.length - 1) {
278                    throw new CmdLineArgException(_usage());
279                }
280
281                height = Integer.parseInt(args[i++]);
282                continue;
283            } else if (arg.equals("-help")) {
284                System.out.println(_usage());
285                StringUtilities.exit(0);
286                continue;
287            } else if (arg.equals("-printPDF")) {
288                _printPDF = true;
289                continue;
290            } else if (arg.equals("-test")) {
291                _test = true;
292                continue;
293            } else if (arg.equals("-version")) {
294                System.out.println(
295                        "Version " + PlotBox.PTPLOT_RELEASE + ", Build $Id$");
296                StringUtilities.exit(0);
297                continue;
298            } else if (arg.equals("-width")) {
299                if (i > args.length - 1) {
300                    throw new CmdLineArgException(
301                            "-width requires an integer argument");
302                }
303
304                width = Integer.parseInt(args[i++]);
305                continue;
306            } else if (arg.equals("")) {
307                // Ignore blank argument.
308            } else if (arg.equals("-")) {
309                // read from standard input
310                URL base = new URL("file", null, "standard input");
311                _read(base, System.in);
312            } else if (!arg.startsWith("-")) {
313                // Have a filename.  First attempt to open it as a URL.
314                InputStream instream;
315                URL base;
316
317                try {
318                    // First argument is null because we are only
319                    // processing absolute URLs this way.  Relative
320                    // URLs are opened as ordinary files.
321                    URL inurl = new URL(null, arg);
322                    base = inurl;
323                    instream = inurl.openStream();
324                } catch (MalformedURLException ex) {
325                    File file = new File(arg);
326                    instream = new FileInputStream(file);
327                    _file = new File(file.getAbsolutePath());
328                    title = _file.getName();
329                    _directory = _file.getParentFile();
330                    base = new URL("file", null, _directory.getAbsolutePath());
331                }
332
333                _read(base, instream);
334            } else {
335                // Unrecognized option.
336                throw new CmdLineArgException("Unrecognized option: " + arg);
337            }
338        }
339
340        setSize(width, height);
341        setTitle(title);
342
343        argumentsRead = i;
344
345        return argumentsRead;
346    }
347
348    /** Return a string summarizing the command-line arguments.
349     *  @return A usage string.
350     */
351    protected String _usage() {
352        // We use a table here to keep things neat.
353        // If we have:
354        //  {"-bd",  "<color>", "Border",  "White", "(Unsupported)"},
355        // -bd       - The argument
356        // <color>   - The description of the value of the argument
357        // Border    - The Xgraph file directive (not supported at this time).
358        // White     - The default (not supported at this time)
359        // "(Unsupported)" - The string that is printed to indicate if
360        //                   a option is unsupported.
361        String[][] commandOptions = { { "-height", "<pixels>" },
362                { "-width", "<pixels>" }, };
363
364        String[] commandFlags = { "-help", "-printPDF", "-test", "-version",
365                "-", };
366        StringBuffer result = new StringBuffer(
367                "Usage: ptplot [ options ] [file ...]\n\n"
368                        + "Options that take values:\n");
369
370        int i;
371
372        for (i = 0; i < commandOptions.length; i++) {
373            result.append(" " + commandOptions[i][0] + " "
374                    + commandOptions[i][1] + "\n");
375        }
376
377        result.append("\nBoolean flags:\n");
378
379        for (i = 0; i < commandFlags.length; i++) {
380            result.append(" " + commandFlags[i]);
381        }
382
383        return result.toString();
384    }
385
386    ///////////////////////////////////////////////////////////////////
387    ////                         protected variables               ////
388
389    /** If true, then print to PDF. */
390    protected static boolean _printPDF = false;
391
392    /** If true, then auto exit after a few seconds. */
393    protected static boolean _test = false;
394
395    private static class WindowClosingAdapter extends WindowAdapter {
396        @Override
397        public void windowClosing(WindowEvent e) {
398            // Strangely, calling _close() here sends javac into
399            // an infinite loop (in jdk 1.1.4).
400            //              _close();
401            StringUtilities.exit(0);
402        }
403    }
404}