From 6c570d7eafc343169e5e1a9a22f0f5c8ac6e6aca Mon Sep 17 00:00:00 2001 From: bkuker Date: Sun, 12 Jan 2014 12:23:56 -0500 Subject: [PATCH] Add a Save, refactored Copy. --- .../gui/figure3d/photo/PhotoFrame.java | 98 ++++++++++++++++++- .../gui/figure3d/photo/PhotoPanel.java | 79 +++++---------- 2 files changed, 123 insertions(+), 54 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java index c9eec5b44..8d2b583e8 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoFrame.java @@ -3,11 +3,17 @@ package net.sf.openrocket.gui.figure3d.photo; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.Window; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JDialog; @@ -17,6 +23,7 @@ import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; +import javax.swing.filechooser.FileFilter; import net.sf.openrocket.database.Databases; import net.sf.openrocket.document.OpenRocketDocument; @@ -26,6 +33,7 @@ import net.sf.openrocket.gui.main.SwingExceptionHandler; import net.sf.openrocket.gui.util.FileHelper; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.Icons; +import net.sf.openrocket.gui.util.SimpleFileFilter; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.logging.LoggingSystemSetup; @@ -114,6 +122,7 @@ public class PhotoFrame extends JFrame { if (option == JFileChooser.APPROVE_OPTION) { File file = chooser.getSelectedFile(); log.debug("Opening File " + file.getAbsolutePath()); + ((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory()); GeneralRocketLoader grl = new GeneralRocketLoader(file); try { OpenRocketDocument doc = grl.load(); @@ -125,6 +134,60 @@ public class PhotoFrame extends JFrame { } }); menu.add(item); + + + item = new JMenuItem("Save Image...", KeyEvent.VK_S); //TODO Trans + item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, SHORTCUT_KEY)); + // // Open a rocket design + item.getAccessibleContext().setAccessibleDescription("Save Image"); //TODO Trans + item.setIcon(Icons.FILE_OPEN); + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + log.info(Markers.USER_MARKER, "Save... selected"); + photoPanel.addImageCallback(new PhotoPanel.ImageCallback() { + @Override + public void performAction(final BufferedImage image) { + log.info("Got image {} to save...", image); + + final FileFilter png = new SimpleFileFilter("PNG Image", ".png"); //TODO Trans + + final JFileChooser chooser = new JFileChooser(); + + chooser.addChoosableFileFilter(png); + chooser.setFileFilter(png); + chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + + chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory()); + final int option = chooser.showSaveDialog(PhotoFrame.this); + + if (option != JFileChooser.APPROVE_OPTION) { + log.info(Markers.USER_MARKER, "User decided not to save, option=" + option); + return; + } + + final File file = FileHelper.forceExtension(chooser.getSelectedFile(), "png"); + if (file == null) { + log.info(Markers.USER_MARKER, "User did not select a file"); + return; + } + + ((SwingPreferences) Application.getPreferences()).setDefaultDirectory(chooser.getCurrentDirectory()); + log.info(Markers.USER_MARKER, "User chose to save image as {}", file); + + if ( FileHelper.confirmWrite(file, PhotoFrame.this) ){ + try { + ImageIO.write(image, "png", file); + } catch (IOException e) { + throw new Error(e); + } + } + } + }); + } + }); + menu.add(item); + } // // Edit @@ -137,7 +200,40 @@ public class PhotoFrame extends JFrame { Action action = new AbstractAction("Copy") { @Override public void actionPerformed(ActionEvent e) { - photoPanel.doCopy(); + photoPanel.addImageCallback(new PhotoPanel.ImageCallback() { + @Override + public void performAction(final BufferedImage image) { + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new Transferable() { + @Override + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + if (flavor.equals(DataFlavor.imageFlavor) && image != null) { + return image; + } else { + throw new UnsupportedFlavorException(flavor); + } + } + + @Override + public DataFlavor[] getTransferDataFlavors() { + DataFlavor[] flavors = new DataFlavor[1]; + flavors[0] = DataFlavor.imageFlavor; + return flavors; + } + + @Override + public boolean isDataFlavorSupported(DataFlavor flavor) { + DataFlavor[] flavors = getTransferDataFlavors(); + for (int i = 0; i < flavors.length; i++) { + if (flavor.equals(flavors[i])) { + return true; + } + } + + return false; + } + }, null); + } + }); } }; item = new JMenuItem(action); diff --git a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoPanel.java b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoPanel.java index cb0319591..9dd949f6b 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoPanel.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoPanel.java @@ -3,17 +3,14 @@ package net.sf.openrocket.gui.figure3d.photo; import java.awt.BorderLayout; import java.awt.Component; import java.awt.SplashScreen; -import java.awt.Toolkit; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; -import java.io.IOException; import java.util.Collection; import java.util.EventObject; import java.util.HashSet; import java.util.Iterator; +import java.util.List; +import java.util.Vector; import javax.media.opengl.DebugGL2; import javax.media.opengl.GL; @@ -71,9 +68,18 @@ public class PhotoPanel extends JPanel implements GLEventListener { private Component canvas; private TextureCache textureCache = new TextureCache(); private double ratio; - private boolean doCopy = false; private boolean needUpdate = false; + private List imageCallbacks = new java.util.Vector(); + + interface ImageCallback { + public void performAction(BufferedImage i); + } + + void addImageCallback(ImageCallback a) { + imageCallbacks.add(a); + } + private RocketRenderer rr; private PhotoSettings p; @@ -109,11 +115,6 @@ public class PhotoPanel extends JPanel implements GLEventListener { }); } - void doCopy() { - doCopy = true; - repaint(); - } - PhotoSettings getSettings() { return p; } @@ -203,8 +204,8 @@ public class PhotoPanel extends JPanel implements GLEventListener { final double y1 = (2 * lastY - height) / height; final double x2 = (width - 2 * e.getX()) / width; final double y2 = (2 * e.getY() - height) / height; - - p.setViewAltAz(p.getViewAlt() - (y1-y2), p.getViewAz() + (x1-x2)); + + p.setViewAltAz(p.getViewAlt() - (y1 - y2), p.getViewAz() + (x1 - x2)); lastX = e.getX(); lastY = e.getY(); @@ -249,11 +250,19 @@ public class PhotoPanel extends JPanel implements GLEventListener { gl.glAccum(GL2.GL_RETURN, 1.0f); } - if (doCopy) { - copy(drawable); - doCopy = false; + if (!imageCallbacks.isEmpty()) { + BufferedImage i = (new AWTGLReadBufferUtil(GLProfile.get(GLProfile.GL2), false)).readPixelsToBufferedImage( + drawable.getGL(), 0, 0, drawable.getWidth(), drawable.getHeight(), true); + final Vector cbs = new Vector(imageCallbacks); + imageCallbacks.clear(); + for (ImageCallback ia : cbs) { + try { + ia.performAction(i); + } catch (Throwable t) { + log.error("Image Callback {} threw", i, t); + } + } } - } private static void convertColor(Color color, float[] out) { @@ -472,40 +481,4 @@ public class PhotoPanel extends JPanel implements GLEventListener { gl.glTranslated(-b.xMin - b.xSize / 2.0, 0, 0); } - private void copy(final GLAutoDrawable drawable) { - - final BufferedImage image = (new AWTGLReadBufferUtil(GLProfile.get(GLProfile.GL2), false)) - .readPixelsToBufferedImage(drawable.getGL(), 0, 0, drawable.getWidth(), drawable.getHeight(), true); - - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new Transferable() { - @Override - public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { - if (flavor.equals(DataFlavor.imageFlavor) && image != null) { - return image; - } else { - throw new UnsupportedFlavorException(flavor); - } - } - - @Override - public DataFlavor[] getTransferDataFlavors() { - DataFlavor[] flavors = new DataFlavor[1]; - flavors[0] = DataFlavor.imageFlavor; - return flavors; - } - - @Override - public boolean isDataFlavorSupported(DataFlavor flavor) { - DataFlavor[] flavors = getTransferDataFlavors(); - for (int i = 0; i < flavors.length; i++) { - if (flavor.equals(flavors[i])) { - return true; - } - } - - return false; - } - }, null); - } - }