/* * The University of Wales, Cardiff Triana Project Software License (Based * on the Apache Software License Version 1.1) * * Copyright (c) 2007 University of Wales, Cardiff. All rights reserved. * * Redistribution and use of the software in source and binary forms, with * or without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, * must include the following acknowledgment: "This product includes * software developed by the University of Wales, Cardiff for the Triana * Project (http://www.trianacode.org)." Alternately, this * acknowledgment may appear in the software itself, if and wherever * such third-party acknowledgments normally appear. * * 4. The names "Triana" and "University of Wales, Cardiff" must not be * used to endorse or promote products derived from this software * without prior written permission. For written permission, please * contact triana@trianacode.org. * * 5. Products derived from this software may not be called "Triana," nor * may Triana appear in their name, without prior written permission of * the University of Wales, Cardiff. * * 6. This software may not be sold, used or incorporated into any product * for sale to third parties. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL UNIVERSITY OF WALES, CARDIFF OR ITS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * ------------------------------------------------------------------------ * * This software consists of voluntary contributions made by many * individuals on behalf of the Triana Project. For more information on the * Triana Project, please see. http://www.trianacode.org. * * This license is based on the BSD license as adopted by the Apache * Foundation and is governed by the laws of England and Wales. * */ package org.trianacode.gui.action.files; import org.trianacode.gui.action.ActionDisplayOptions; import org.trianacode.gui.desktop.DesktopView; import org.trianacode.gui.hci.GUIEnv; import org.trianacode.gui.main.TaskGraphPanel; import org.trianacode.gui.panels.IntegerField; import org.trianacode.gui.panels.LabelledTextFieldPanel; import org.trianacode.gui.panels.OptionPane; import org.trianacode.gui.panels.TFileChooser; import org.trianacode.gui.util.TaskGraphPanelUtils; import org.trianacode.taskgraph.TaskGraph; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.FileImageOutputStream; import javax.swing.*; import javax.swing.border.EmptyBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Iterator; /** * Action to handle workflow/taskgraph Exporting. * * @author Matthew Shields * @version $Revision: 4048 $ */ public class ImageAction extends AbstractAction implements ActionDisplayOptions { private static int margin = 20; public ImageAction() { putValue(SHORT_DESCRIPTION, "Create Image"); putValue(ACTION_COMMAND_KEY, "Create Image"); putValue(SMALL_ICON, GUIEnv.getIcon("pic.png")); putValue(NAME, "Create Image"); } /** * Invoked when an action occurs. */ public void actionPerformed(ActionEvent event) { TaskGraphPanel taskgraphpanel = null; Component comp = null; DesktopView view = GUIEnv.getSelectedDesktopView(); if (view != null) { taskgraphpanel = view.getTaskgraphPanel(); if (taskgraphpanel != null) { TaskGraph tg = taskgraphpanel.getTaskGraph(); if (tg == null || tg.getTasks(false).length == 0) { JOptionPane.showMessageDialog(GUIEnv.getApplicationFrame(), "No Task Graph to Create an Image From", "Create Image", JOptionPane.ERROR_MESSAGE, GUIEnv.getTrianaIcon()); return; } comp = taskgraphpanel.getContainer(); } else { JOptionPane.showMessageDialog(GUIEnv.getApplicationFrame(), "Error: No Panel", "Create Image", JOptionPane.ERROR_MESSAGE, GUIEnv.getTrianaIcon()); return; } } else { JOptionPane.showMessageDialog(GUIEnv.getApplicationFrame(), "Error: No View", "Create Image", JOptionPane.ERROR_MESSAGE, GUIEnv.getTrianaIcon()); return; } if (comp != null && comp.isVisible()) { Dimension size = comp.getSize(); BufferedImage image = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB); Rectangle2D rect = TaskGraphPanelUtils.getBoundingBox(taskgraphpanel); ImagePanel p = new ImagePanel(comp, rect, image); } else { JOptionPane.showMessageDialog(GUIEnv.getApplicationFrame(), "Error: No Visible Panel", "Create Image", JOptionPane.ERROR_MESSAGE, GUIEnv.getTrianaIcon()); } } public static void save(File output, double scale, String type) { TaskGraphPanel taskgraphpanel = null; Component comp = null; DesktopView view = GUIEnv.getSelectedDesktopView(); if (view != null) { taskgraphpanel = view.getTaskgraphPanel(); if (taskgraphpanel != null) { TaskGraph tg = taskgraphpanel.getTaskGraph(); if (tg == null || tg.getTasks(false).length == 0) { System.out.println("No taskgraph found."); return; } comp = taskgraphpanel.getContainer(); } else { System.out.println("No taskgraph panel found."); return; } } else { System.out.println("no taskgraph view found."); return; } if (comp != null && comp.isVisible()) { Dimension size = comp.getSize(); BufferedImage image = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB); Rectangle2D rect = TaskGraphPanelUtils.getBoundingBox(taskgraphpanel); save(output, comp, scale, rect, image, type, false); } else { System.out.println("no Component found."); } } private static void save(File f, Component comp, double scale, Rectangle2D rect, BufferedImage image, String type, boolean display) { if (scale == 0.0) { scale = 0.1; } String nm = f.getName(); if (nm.indexOf(".") > -1) { nm = nm.substring(0, nm.indexOf(".") + 1) + type; } else { nm += ("." + type); } File out = new File(f.getParentFile(), nm); if (out.exists()) { int choice = JOptionPane.OK_OPTION; if (display) { choice = JOptionPane.showConfirmDialog(GUIEnv.getApplicationFrame(), "Over write existing file '" + nm + "'?", "Over Write", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, GUIEnv.getTrianaIcon()); } if (choice == JOptionPane.CANCEL_OPTION) { return; } else { String path = out.getAbsolutePath(); out.delete(); out = new File(path); } } comp.paint(image.getGraphics()); AffineTransform tx = new AffineTransform(); tx.scale(scale, scale); tx.translate(-(rect.getX() - (margin)), -(rect.getY() - (margin))); AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); BufferedImage dest = new BufferedImage((int) ((rect.getWidth()) * scale) + (margin * 2), (int) ((rect.getHeight()) * scale) + (margin * 2), BufferedImage.TYPE_INT_RGB); Graphics g = dest.getGraphics(); Color c = g.getColor(); g.setColor(comp.getBackground()); g.fillRect(0, 0, dest.getWidth(), dest.getHeight()); g.setColor(c); image = op.filter(image, dest); Iterator iter = ImageIO.getImageWritersByFormatName(type); if (iter == null || !iter.hasNext()) { if (display) { OptionPane.showError("No Image writers availabale for " + type, "Error", GUIEnv.getApplicationFrame()); } else { System.out.println("ImageAction.save: No Image writers could be found for:" + type); } } ImageWriter writer = (ImageWriter) iter.next(); ImageWriteParam iwp = writer.getDefaultWriteParam(); if (writer.canWriteRasters()) { iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); iwp.setCompressionQuality(1); } try { FileImageOutputStream fout = new FileImageOutputStream(out); writer.setOutput(fout); IIOImage im = new IIOImage(image, null, null); writer.write(null, im, iwp); writer.dispose(); fout.flush(); fout.close(); } catch (IOException e) { if (display) { OptionPane.showError(e.getMessage(), "Error", GUIEnv.getApplicationFrame()); } else { e.printStackTrace(); } } } private class ImagePanel extends JDialog implements ChangeListener, ActionListener { private JRadioButton jpg = new JRadioButton("JPG (Better for scaled images)"); private JRadioButton png = new JRadioButton("PNG (Better for unscaled images)"); private JTextField widthField = new IntegerField(); private JTextField heightField = new IntegerField(); private JButton saveBut = new JButton("Save As"); private Rectangle2D rect; private BufferedImage image; private int width; private int height; private double scale = 1.0; private Component comp; public ImagePanel(Component comp, Rectangle2D rect, BufferedImage image) { super(GUIEnv.getApplicationFrame(), "Create Image", true); setResizable(false); jpg.setSelected(false); png.setSelected(true); this.comp = comp; this.rect = rect; this.image = image; this.width = (int) rect.getWidth(); this.height = (int) rect.getHeight(); widthField.setText(width + ""); heightField.setText(height + ""); widthField.setEnabled(false); heightField.setEnabled(false); init(); } /** * This method is called when the task is set for this panel. It is overridden to create the panel layout. */ public void init() { JPanel main = new JPanel(); main.setLayout(new BorderLayout()); main.setBorder(new EmptyBorder(3, 3, 3, 3)); JPanel radiopanel = new JPanel(new GridLayout(2, 1)); radiopanel.setBorder(new EmptyBorder(3, 3, 3, 3)); radiopanel.add(jpg); radiopanel.add(png); ButtonGroup group = new ButtonGroup(); group.add(jpg); group.add(png); JPanel dims = new LabelledTextFieldPanel(new String[]{"Width", "Height"}, new JTextField[]{widthField, heightField}); JSlider scale = new JSlider(JSlider.HORIZONTAL, 0, 100, 100); scale.setMajorTickSpacing(10); scale.setMinorTickSpacing(1); scale.setPaintTicks(true); scale.setPaintLabels(true); scale.addChangeListener(this); JPanel scalePanel = new JPanel(); scalePanel.setLayout(new BoxLayout(scalePanel, BoxLayout.Y_AXIS)); scalePanel.add(new JLabel("Scaling Percentage")); scalePanel.add(scale); JPanel sliderPane = new JPanel(new BorderLayout()); sliderPane.add(scalePanel, BorderLayout.NORTH); sliderPane.add(dims, BorderLayout.CENTER); JPanel butPane = new JPanel(); butPane.setLayout(new BoxLayout(butPane, BoxLayout.X_AXIS)); JButton cancel = new JButton("Cancel"); cancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { setVisible(false); dispose(); } }); butPane.add(cancel); saveBut.addActionListener(this); butPane.add(Box.createHorizontalGlue()); butPane.add(saveBut); sliderPane.setBorder(new EmptyBorder(3, 3, 3, 3)); sliderPane.add(butPane, BorderLayout.SOUTH); main.add(radiopanel, BorderLayout.CENTER); main.add(sliderPane, BorderLayout.SOUTH); getContentPane().add(main); pack(); setLocationRelativeTo(GUIEnv.getApplicationFrame()); setVisible(true); } public void stateChanged(ChangeEvent e) { JSlider source = (JSlider) e.getSource(); if (!source.getValueIsAdjusting()) { int i = source.getValue(); this.scale = (double) i / 100; widthField.setText(((int) (width * scale)) + ""); heightField.setText(((int) (height * scale)) + ""); } } private String getFileType() { if (this.jpg.isSelected()) { return "jpg"; } return "png"; } private double getScale() { return scale; } @Override public void actionPerformed(ActionEvent actionEvent) { TFileChooser chooser = new TFileChooser(System.getProperty("user.dir")); chooser.setDialogTitle("Save"); chooser.setMultiSelectionEnabled(false); int result = chooser.showSaveDialog(GUIEnv.getApplicationFrame()); if (result == TFileChooser.APPROVE_OPTION) { final File f = chooser.getSelectedFile(); if (f != null) { Thread thread = new Thread() { public void run() { save(f, comp, getScale(), rect, image, getFileType(), true); setVisible(false); dispose(); } }; thread.setName("ImageActionThread"); thread.setPriority(Thread.NORM_PRIORITY); thread.start(); } } } } }