Back to index

wims  3.65+svn20090927
PlotFrame.java
Go to the documentation of this file.
00001 /* Top-level window containing a plotter.
00002 
00003  Copyright (c) 1998-2005 The Regents of the University of California.
00004  All rights reserved.
00005  Permission is hereby granted, without written agreement and without
00006  license or royalty fees, to use, copy, modify, and distribute this
00007  software and its documentation for any purpose, provided that the above
00008  copyright notice and the following two paragraphs appear in all copies
00009  of this software.
00010 
00011  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
00012  FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
00013  ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
00014  THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
00015  SUCH DAMAGE.
00016 
00017  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00018  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
00020  PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
00021  CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
00022  ENHANCEMENTS, OR MODIFICATIONS.
00023 
00024  PT_COPYRIGHT_VERSION_2
00025  COPYRIGHTENDKEY
00026  */
00027 package ptolemy.plot;
00028 
00029 import java.awt.BorderLayout;
00030 import java.awt.Color;
00031 import java.awt.Dimension;
00032 import java.awt.Event;
00033 import java.awt.Toolkit;
00034 import java.awt.event.ActionEvent;
00035 import java.awt.event.ActionListener;
00036 import java.awt.event.KeyEvent;
00037 import java.awt.print.PrinterJob;
00038 import java.io.File;
00039 import java.io.FileInputStream;
00040 import java.io.FileNotFoundException;
00041 import java.io.FileOutputStream;
00042 import java.io.IOException;
00043 import java.io.InputStream;
00044 import java.net.URL;
00045 
00046 import javax.print.attribute.HashPrintRequestAttributeSet;
00047 import javax.print.attribute.PrintRequestAttributeSet;
00048 import javax.swing.JFileChooser;
00049 import javax.swing.JFrame;
00050 import javax.swing.JMenu;
00051 import javax.swing.JMenuBar;
00052 import javax.swing.JMenuItem;
00053 import javax.swing.JOptionPane;
00054 import javax.swing.KeyStroke;
00055 import javax.swing.UIManager;
00056 import javax.swing.filechooser.FileFilter;
00057 
00058 import ptolemy.util.StringUtilities;
00059 
00060 // TO DO:
00061 //   - Add a mechanism for combining two plots into one
00064 
00098 public class PlotFrame extends JFrame {
00103     public PlotFrame() {
00104         this("Ptolemy Plot Frame");
00105     }
00106 
00112     public PlotFrame(String title) {
00113         this(title, null);
00114     }
00115 
00123     public PlotFrame(String title, PlotBox plotArg) {
00124         super(title);
00125 
00126         // The Java look & feel is pretty lame, so we use the native
00127         // look and feel of the platform we are running on.
00128         try {
00129             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
00130         } catch (Exception e) {
00131             // Ignore exceptions, which only result in the wrong look and feel.
00132         }
00133 
00134         if (plotArg == null) {
00135             plot = new Plot();
00136         } else {
00137             plot = plotArg;
00138         }
00139 
00140         // Background color is a light grey.
00141         plot.setBackground(new Color(0xe5e5e5));
00142 
00143         _fileMenu.setMnemonic(KeyEvent.VK_F);
00144         _editMenu.setMnemonic(KeyEvent.VK_E);
00145         _specialMenu.setMnemonic(KeyEvent.VK_S);
00146 
00147         // File menu
00148         JMenuItem[] fileMenuItems = { new JMenuItem("Open", KeyEvent.VK_O),
00149                 new JMenuItem("Save", KeyEvent.VK_S),
00150                 new JMenuItem("SaveAs", KeyEvent.VK_A),
00151                 new JMenuItem("Export", KeyEvent.VK_E),
00152                 new JMenuItem("Print", KeyEvent.VK_P),
00153                 new JMenuItem("Close", KeyEvent.VK_C), };
00154 
00155         // Open button = ctrl-o.
00156         fileMenuItems[0].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
00157                 Event.CTRL_MASK));
00158 
00159         // Save button = ctrl-s.
00160         fileMenuItems[1].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
00161                 Event.CTRL_MASK));
00162 
00163         // Print button = ctrl-p.
00164         fileMenuItems[4].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,
00165                 Event.CTRL_MASK));
00166 
00167         // Close button = ctrl-w.
00168         fileMenuItems[5].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W,
00169                 Event.CTRL_MASK));
00170 
00171         FileMenuListener fml = new FileMenuListener();
00172 
00173         // Set the action command and listener for each menu item.
00174         for (int i = 0; i < fileMenuItems.length; i++) {
00175             fileMenuItems[i].setActionCommand(fileMenuItems[i].getText());
00176             fileMenuItems[i].addActionListener(fml);
00177             _fileMenu.add(fileMenuItems[i]);
00178         }
00179 
00180         _menubar.add(_fileMenu);
00181 
00182         // Edit menu
00183         JMenuItem format = new JMenuItem("Format", KeyEvent.VK_F);
00184         FormatListener formatListener = new FormatListener();
00185         format.addActionListener(formatListener);
00186         _editMenu.add(format);
00187         _menubar.add(_editMenu);
00188 
00189         // Special menu
00190         JMenuItem[] specialMenuItems = { new JMenuItem("About", KeyEvent.VK_A),
00191                 new JMenuItem("Help", KeyEvent.VK_H),
00192                 new JMenuItem("Clear", KeyEvent.VK_C),
00193                 new JMenuItem("Fill", KeyEvent.VK_F),
00194                 new JMenuItem("Reset axes", KeyEvent.VK_R),
00195                 new JMenuItem("Sample plot", KeyEvent.VK_S), };
00196         SpecialMenuListener sml = new SpecialMenuListener();
00197 
00198         // Set the action command and listener for each menu item.
00199         for (int i = 0; i < specialMenuItems.length; i++) {
00200             specialMenuItems[i].setActionCommand(specialMenuItems[i].getText());
00201             specialMenuItems[i].addActionListener(sml);
00202             _specialMenu.add(specialMenuItems[i]);
00203         }
00204 
00205         _menubar.add(_specialMenu);
00206 
00207         setJMenuBar(_menubar);
00208 
00209         getContentPane().add(plot, BorderLayout.CENTER);
00210 
00211         // FIXME: This should not be hardwired in here.
00212         setSize(500, 300);
00213 
00214         // Center.
00215         Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
00216         Dimension frameSize = getSize();
00217         int x = (screenSize.width - frameSize.width) / 2;
00218         int y = (screenSize.height - frameSize.height) / 2;
00219         setLocation(x, y);
00220     }
00221 
00224 
00227     public void samplePlot() {
00228         _file = null;
00229         _directory = null;
00230         plot.samplePlot();
00231     }
00232 
00238     public void setVisible(boolean visible) {
00239         super.setVisible(visible);
00240         _editMenu.setBackground(_menubar.getBackground());
00241         _fileMenu.setBackground(_menubar.getBackground());
00242         _specialMenu.setBackground(_menubar.getBackground());
00243     }
00244 
00247 
00250     // FIXME: uncomment final when we upgrade to jdk1.2
00251     public/*final*/PlotBox plot;
00252 
00255 
00257     protected JMenuBar _menubar = new JMenuBar();
00258 
00260     protected JMenu _editMenu = new JMenu("Edit");
00261 
00263     protected JMenu _fileMenu = new JMenu("File");
00264 
00266     protected JMenu _specialMenu = new JMenu("Special");
00267 
00269     protected File _directory = null;
00270 
00272     protected File _file = null;
00273 
00276     protected void _about() {
00277         JOptionPane
00278                 .showMessageDialog(
00279                         this,
00280                         "PlotFrame class\n"
00281                                 + "By: Edward A. Lee "
00282                                 + "and Christopher Brooks\n"
00283                                 + "Version "
00284                                 + PlotBox.PTPLOT_RELEASE
00285                                 + ", Build: $Id: PlotFrame.java,v 1.84 2007/12/16 07:29:48 cxh Exp $\n\n"
00286                                 + "For more information, see\n"
00287                                 + "http://ptolemy.eecs.berkeley.edu/java/ptplot\n\n"
00288                                 + "Copyright (c) 1997-2005, "
00289                                 + "The Regents of the University of California.",
00290                         "About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
00291     }
00292 
00295     protected void _close() {
00296         dispose();
00297     }
00298 
00301     protected void _editFormat() {
00302         PlotFormatter fmt = new PlotFormatter(plot);
00303         fmt.openModal();
00304     }
00305 
00309     protected void _export() {
00310         JFileChooser fileDialog = new JFileChooser();
00311         fileDialog.addChoosableFileFilter(new EPSFileFilter());
00312         fileDialog.setDialogTitle("Export EPS to...");
00313 
00314         if (_directory != null) {
00315             fileDialog.setCurrentDirectory(_directory);
00316         } else {
00317             // The default on Windows is to open at user.home, which is
00318             // typically an absurd directory inside the O/S installation.
00319             // So we use the current directory instead.
00320             String cwd = StringUtilities.getProperty("user.dir");
00321 
00322             if (cwd != null) {
00323                 fileDialog.setCurrentDirectory(new File(cwd));
00324             }
00325         }
00326 
00327         fileDialog.setSelectedFile(new File(fileDialog.getCurrentDirectory(),
00328                 "plot.eps"));
00329 
00330         int returnVal = fileDialog.showDialog(this, "Export");
00331 
00332         if (returnVal == JFileChooser.APPROVE_OPTION) {
00333             File file = fileDialog.getSelectedFile();
00334 
00335             try {
00336                 FileOutputStream fout = null;
00337 
00338                 try {
00339                     fout = new FileOutputStream(file);
00340                     plot.export(fout);
00341                 } finally {
00342                     try {
00343                         fout.close();
00344                     } catch (Throwable throwable) {
00345                         System.out.println("Ignoring failure to close stream "
00346                                 + "on " + file);
00347                         throwable.printStackTrace();
00348                     }
00349                 }
00350             } catch (IOException ex) {
00351                 JOptionPane.showMessageDialog(this, "Error exporting plot: "
00352                         + ex, "Ptolemy II Error", JOptionPane.WARNING_MESSAGE);
00353             }
00354         }
00355     }
00356 
00359     protected void _help() {
00360         JOptionPane.showMessageDialog(this,
00361                 "PlotFrame is a plot in a top-level window.\n"
00362                         + "  File formats understood: Ptplot ASCII.\n"
00363                         + "  Left mouse button: Zooming.",
00364                 "About Ptolemy Plot", JOptionPane.INFORMATION_MESSAGE);
00365     }
00366 
00369     protected void _open() {
00370         JFileChooser fileDialog = new JFileChooser();
00371         fileDialog.setDialogTitle("Select a plot file");
00372 
00373         // Filter file names.
00374         fileDialog.addChoosableFileFilter(new PLTOrXMLFileFilter());
00375 
00376         if (_directory != null) {
00377             fileDialog.setCurrentDirectory(_directory);
00378         } else {
00379             // The default on Windows is to open at user.home, which is
00380             // typically an absurd directory inside the O/S installation.
00381             // So we use the current directory instead.
00382             String cwd = StringUtilities.getProperty("user.dir");
00383 
00384             if (cwd != null) {
00385                 fileDialog.setCurrentDirectory(new File(cwd));
00386             }
00387         }
00388 
00389         int returnVal = fileDialog.showOpenDialog(this);
00390 
00391         if (returnVal == JFileChooser.APPROVE_OPTION) {
00392             _file = fileDialog.getSelectedFile();
00393             setTitle(_file.getName());
00394             _directory = fileDialog.getCurrentDirectory();
00395 
00396             try {
00397                 plot.clear(true);
00398                 _read(new URL("file", null, _directory.getAbsolutePath()),
00399                         new FileInputStream(_file));
00400                 plot.repaint();
00401             } catch (FileNotFoundException ex) {
00402                 JOptionPane.showMessageDialog(this, "File not found:\n"
00403                         + ex.toString(), "Ptolemy Plot Error",
00404                         JOptionPane.WARNING_MESSAGE);
00405             } catch (IOException ex) {
00406                 JOptionPane.showMessageDialog(this, "Error reading input:\n"
00407                         + ex.toString(), "Ptolemy Plot Error",
00408                         JOptionPane.WARNING_MESSAGE);
00409             }
00410         }
00411     }
00412 
00415     protected void _print() {
00416         _printCrossPlatform();
00417 
00418         //_printNative();
00419     }
00420 
00426     protected void _printCrossPlatform() {
00427         // Build a set of attributes
00428         PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
00429         PrinterJob job = PrinterJob.getPrinterJob();
00430         job.setPrintable(plot);
00431 
00432         if (job.printDialog(aset)) {
00433             try {
00434                 job.print(aset);
00435             } catch (Exception ex) {
00436                 JOptionPane.showMessageDialog(this, "Printing failed:\n"
00437                         + ex.toString(), "Print Error",
00438                         JOptionPane.WARNING_MESSAGE);
00439             }
00440         }
00441     }
00442 
00447     protected void _printNative() {
00448         PrinterJob job = PrinterJob.getPrinterJob();
00449 
00450         //PageFormat pageFormat = job.defaultPage();
00451         //job.setPrintable(plot, pageFormat);
00452         job.setPrintable(plot);
00453 
00454         if (job.printDialog()) {
00455             try {
00456                 // job.print() eventually
00457                 // calls PlotBox.print(Graphics, PageFormat)
00458                 job.print();
00459             } catch (Exception ex) {
00460                 JOptionPane.showMessageDialog(this, "Printing failed:\n"
00461                         + ex.toString(), "Print Error",
00462                         JOptionPane.WARNING_MESSAGE);
00463             }
00464         }
00465     }
00466 
00474     protected void _read(URL base, InputStream in) throws IOException {
00475         plot.read(in);
00476     }
00477 
00481     protected void _save() {
00482         if (_file != null) {
00483             try {
00484                 FileOutputStream fout = new FileOutputStream(_file);
00485                 plot.write(fout);
00486             } catch (IOException ex) {
00487                 JOptionPane.showMessageDialog(this, "Error writing file:\n"
00488                         + ex.toString(), "Ptolemy Plot Error",
00489                         JOptionPane.WARNING_MESSAGE);
00490             }
00491         } else {
00492             _saveAs();
00493         }
00494     }
00495 
00498     protected void _saveAs() {
00499         JFileChooser fileDialog = new JFileChooser();
00500         fileDialog.addChoosableFileFilter(new PLTOrXMLFileFilter());
00501         fileDialog.setDialogTitle("Save plot as...");
00502 
00503         if (_directory != null) {
00504             fileDialog.setCurrentDirectory(_directory);
00505         } else {
00506             // The default on Windows is to open at user.home, which is
00507             // typically an absurd directory inside the O/S installation.
00508             // So we use the current directory instead.
00509             String cwd = StringUtilities.getProperty("user.dir");
00510 
00511             if (cwd != null) {
00512                 fileDialog.setCurrentDirectory(new File(cwd));
00513             }
00514         }
00515 
00516         fileDialog.setSelectedFile(new File(fileDialog.getCurrentDirectory(),
00517                 "plot.xml"));
00518 
00519         int returnVal = fileDialog.showSaveDialog(this);
00520 
00521         if (returnVal == JFileChooser.APPROVE_OPTION) {
00522             _file = fileDialog.getSelectedFile();
00523             setTitle(_file.getName());
00524             _directory = fileDialog.getCurrentDirectory();
00525             _save();
00526         }
00527     }
00528 
00531     class FileMenuListener implements ActionListener {
00532         public void actionPerformed(ActionEvent e) {
00533             JMenuItem target = (JMenuItem) e.getSource();
00534             String actionCommand = target.getActionCommand();
00535 
00536             try {
00537                 if (actionCommand.equals("Open")) {
00538                     _open();
00539                 } else if (actionCommand.equals("Save")) {
00540                     _save();
00541                 } else if (actionCommand.equals("SaveAs")) {
00542                     _saveAs();
00543                 } else if (actionCommand.equals("Export")) {
00544                     _export();
00545                 } else if (actionCommand.equals("Print")) {
00546                     _print();
00547                 } else if (actionCommand.equals("Close")) {
00548                     _close();
00549                 }
00550             } catch (Exception exception) {
00551                 // If we do not catch exceptions here, then they
00552                 // disappear to stdout, which is bad if we launched
00553                 // where there is no stdout visible.
00554                 JOptionPane.showMessageDialog(null, "File Menu Exception:\n"
00555                         + exception.toString(), "Ptolemy Plot Error",
00556                         JOptionPane.WARNING_MESSAGE);
00557             }
00558 
00559             // NOTE: The following should not be needed, but there jdk1.3beta
00560             // appears to have a bug in swing where repainting doesn't
00561             // properly occur.
00562             repaint();
00563         }
00564     }
00565 
00566     class FormatListener implements ActionListener {
00567         public void actionPerformed(ActionEvent e) {
00568             try {
00569                 _editFormat();
00570             } catch (Exception exception) {
00571                 // If we do not catch exceptions here, then they
00572                 // disappear to stdout, which is bad if we launched
00573                 // where there is no stdout visible.
00574                 JOptionPane.showMessageDialog(null, "Format Exception:\n"
00575                         + exception.toString(), "Ptolemy Plot Error",
00576                         JOptionPane.WARNING_MESSAGE);
00577             }
00578 
00579             // NOTE: The following should not be needed, but there jdk1.3beta
00580             // appears to have a bug in swing where repainting doesn't
00581             // properly occur.
00582             repaint();
00583         }
00584     }
00585 
00586     class SpecialMenuListener implements ActionListener {
00587         public void actionPerformed(ActionEvent e) {
00588             JMenuItem target = (JMenuItem) e.getSource();
00589             String actionCommand = target.getActionCommand();
00590 
00591             try {
00592                 if (actionCommand.equals("About")) {
00593                     _about();
00594                 } else if (actionCommand.equals("Help")) {
00595                     _help();
00596                 } else if (actionCommand.equals("Fill")) {
00597                     plot.fillPlot();
00598                 } else if (actionCommand.equals("Reset axes")) {
00599                     plot.resetAxes();
00600                 } else if (actionCommand.equals("Clear")) {
00601                     plot.clear(false);
00602                     plot.repaint();
00603                 } else if (actionCommand.equals("Sample plot")) {
00604                     plot.clear(true);
00605                     samplePlot();
00606                 }
00607             } catch (Exception exception) {
00608                 // If we do not catch exceptions here, then they
00609                 // disappear to stdout, which is bad if we launched
00610                 // where there is no stdout visible.
00611                 JOptionPane.showMessageDialog(null, "Special Menu Exception:\n"
00612                         + exception.toString(), "Ptolemy Plot Error",
00613                         JOptionPane.WARNING_MESSAGE);
00614             }
00615 
00616             // NOTE: The following should not be needed, but there jdk1.3beta
00617             // appears to have a bug in swing where repainting doesn't
00618             // properly occur.
00619             repaint();
00620         }
00621     }
00622 
00625 
00627     static class EPSFileFilter extends FileFilter {
00632         public boolean accept(File fileOrDirectory) {
00633             if (fileOrDirectory.isDirectory()) {
00634                 return true;
00635             }
00636 
00637             String fileOrDirectoryName = fileOrDirectory.getName();
00638             int dotIndex = fileOrDirectoryName.lastIndexOf('.');
00639 
00640             if (dotIndex == -1) {
00641                 return false;
00642             }
00643 
00644             String extension = fileOrDirectoryName.substring(dotIndex);
00645 
00646             if (extension != null) {
00647                 if (extension.equalsIgnoreCase(".eps")) {
00648                     return true;
00649                 } else {
00650                     return false;
00651                 }
00652             }
00653 
00654             return false;
00655         }
00656 
00658         public String getDescription() {
00659             return "Encapsulated PostScript (.eps) files";
00660         }
00661     }
00662 
00664     static class PLTOrXMLFileFilter extends FileFilter {
00669         public boolean accept(File fileOrDirectory) {
00670             if (fileOrDirectory.isDirectory()) {
00671                 return true;
00672             }
00673 
00674             String fileOrDirectoryName = fileOrDirectory.getName();
00675             int dotIndex = fileOrDirectoryName.lastIndexOf('.');
00676 
00677             if (dotIndex == -1) {
00678                 return false;
00679             }
00680 
00681             String extension = fileOrDirectoryName.substring(dotIndex);
00682 
00683             if (extension != null) {
00684                 if (extension.equalsIgnoreCase(".plt")
00685                         || extension.equalsIgnoreCase(".xml")) {
00686                     return true;
00687                 } else {
00688                     return false;
00689                 }
00690             }
00691 
00692             return false;
00693         }
00694 
00696         public String getDescription() {
00697             return ".plt and .xml files";
00698         }
00699     }
00700 }