001/* Plot frame that is capable of reading PlotML files.
002
003 @Author: Edward A. Lee
004
005 @Version: $Id$
006
007 @Copyright (c) 1997-2016 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.plotml;
033
034import java.io.BufferedInputStream;
035import java.io.IOException;
036import java.io.InputStream;
037import java.net.URL;
038
039import javax.swing.JOptionPane;
040
041import com.microstar.xml.XmlException;
042
043import ptolemy.plot.Plot;
044import ptolemy.plot.PlotBox;
045import ptolemy.plot.PlotFrame;
046
047///////////////////////////////////////////////////////////////////
048//// PlotMLFrame
049
050/**
051 PlotMLFrame is a versatile two-dimensional data plotter that runs as
052 part of an application, but in its own window. It can read files
053 in the PlotML format and, for backward compatibility, the old Ptolemy
054 plot file format.
055 An application can also interact directly with the contained Plot
056 object, which is visible as a public member, by invoking its methods.
057 <p>
058 An application that uses this class should set up the handling of
059 window-closing events.  Presumably, the application will exit when
060 all windows have been closed. This is done with code something like:
061 <pre>
062 plotFrameInstance.addWindowListener(new WindowAdapter() {
063 public void windowClosing(WindowEvent e) {
064 // Handle the event
065 }
066 });
067 </pre>
068 <p>
069 PlotMLFrame contains an instance of PlotBox. PlotBox is the base class for
070 classes with drawing capability, e.g. Plot, LogicAnalyzer. If not
071 specified in the constructor, the default is to contain a Plot object. This
072 field is set once in the constructor and immutable afterwards.
073
074 @see Plot
075 @see PlotBox
076 @author Christopher Hylands and Edward A. Lee
077 @version $Id$
078 @since Ptolemy II 0.4
079 @Pt.ProposedRating red (eal)
080 @Pt.AcceptedRating red (cxh)
081 */
082@SuppressWarnings("serial")
083public class PlotMLFrame extends PlotFrame {
084    /** Construct a plot with no command-line arguments.
085     *  It initially displays a sample plot.
086     */
087    public PlotMLFrame() {
088        this("Ptolemy Plot Frame");
089    }
090
091    /** Construct a plot frame with the specified title and by default
092     *  contains an instance of Plot.
093     *  @param title The title of the Plot frame.
094     */
095    public PlotMLFrame(String title) {
096        this(title, null);
097    }
098
099    /** Construct a plot frame with the specified title and the specified
100     *  instance of PlotBox.
101     *  @param title The title of the Plot frame.
102     *  @param plotArg The specified PlotBox.
103     */
104    public PlotMLFrame(String title, PlotBox plotArg) {
105        super(title, plotArg);
106    }
107
108    ///////////////////////////////////////////////////////////////////
109    ////                         protected methods                 ////
110
111    /** Display basic information about the application.
112     */
113    @Override
114    protected void _about() {
115        JOptionPane.showMessageDialog(this,
116                "Ptolemy plot frame\n" + "By: Edward A. Lee\n"
117                        + "and Christopher Hylands\n" + "Version "
118                        + PlotBox.PTPLOT_RELEASE + ", Build: $Id$"
119                        + "For more information, see\n"
120                        + "http://ptolemy.eecs.berkeley.edu/java/ptplot\n",
121                "About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
122    }
123
124    /** Read the specified stream.  This method checks to see whether
125     *  the data is PlotML data, and if so, creates a parser to read it.
126     *  If not, it defers to the parent class to read it.  The current
127     *  working directory (or the directory of the last opened or saved
128     *  file) is the base for relative references.
129     *  @param base The base for relative file references, or null if
130     *   there are not relative file references.
131     *  @param in The input stream.
132     *  @exception IOException If the stream cannot be read.
133     */
134    @Override
135    protected void _read(URL base, InputStream in) throws IOException {
136        // Create a buffered input stream so that mark and reset
137        // are supported.
138        BufferedInputStream bin = new BufferedInputStream(in);
139
140        // Peek at the file...
141        bin.mark(9);
142
143        // Read 8 bytes in case 16-bit encoding is being used.
144        byte[] peek = new byte[8];
145        int bytesRead = bin.read(peek);
146        if (bytesRead != peek.length) {
147            throw new IOException("Read only " + bytesRead + "bytes, expecting "
148                    + peek.length);
149        }
150        bin.reset();
151
152        if (new String(peek).startsWith("<?xm")) {
153            // file is an XML file.
154            PlotBoxMLParser parser;
155
156            if (plot instanceof Plot) {
157                parser = new PlotMLParser((Plot) plot);
158            } else {
159                parser = new PlotBoxMLParser(plot);
160            }
161
162            try {
163                parser.parse(base, bin);
164            } catch (Exception ex) {
165                String msg;
166
167                if (ex instanceof XmlException) {
168                    XmlException xmlex = (XmlException) ex;
169                    msg = "PlotMLFrame: failed to parse PlotML data:\n"
170                            + "line: " + xmlex.getLine() + ", column: "
171                            + xmlex.getColumn() + "\nIn entity: "
172                            + xmlex.getSystemId() + "\n";
173                } else {
174                    msg = "PlotMLFrame: failed to parse PlotML data:\n";
175                }
176
177                System.err.println(msg + ex.toString());
178                ex.printStackTrace();
179            }
180        } else {
181            super._read(base, bin);
182        }
183    }
184}