/** * Copyright 2011 multibit.org * * Licensed under the MIT license (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://opensource.org/licenses/mit-license.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.multibit.viewsystem.swing.view; import org.multibit.viewsystem.swing.view.panels.AbstractTradePanel; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.StringTokenizer; import javax.imageio.ImageIO; import javax.swing.AbstractButton; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.TransferHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ImageSelection extends TransferHandler implements Transferable { private static final long serialVersionUID = 756395092284264645L; private static final Logger log = LoggerFactory.getLogger(ImageSelection.class); private DataFlavor urlFlavor; private DataFlavor uriListAsStringFlavor; private DataFlavor uriListAsReaderFlavor; private DataFlavor flavors[]; private Image image; private AbstractTradePanel abstractTradePanel; private boolean canImport; public ImageSelection(AbstractTradePanel abstractTradePanel, boolean canImport) { this.abstractTradePanel = abstractTradePanel; this.canImport = canImport; try { urlFlavor = new DataFlavor("application/x-java-url; class=java.net.URL"); uriListAsStringFlavor = new DataFlavor("text/uri-list; class=java.lang.String"); uriListAsReaderFlavor = new DataFlavor("text/uri-list;class=java.io.Reader"); flavors = new DataFlavor[] { DataFlavor.imageFlavor, DataFlavor.javaFileListFlavor, urlFlavor, uriListAsStringFlavor, uriListAsReaderFlavor }; } catch (ClassNotFoundException e) { e.printStackTrace(); } } @Override public int getSourceActions(JComponent c) { return TransferHandler.COPY; } @Override public boolean canImport(JComponent comp, DataFlavor flavor[]) { if (!canImport) { return false; } if (!(comp instanceof JLabel) && !(comp instanceof AbstractButton)) { return false; } for (int i = 0, n = flavor.length; i < n; i++) { for (int j = 0, m = flavors.length; j < m; j++) { if (flavor[i].equals(flavors[j])) { return true; } } } return false; } @Override public Transferable createTransferable(JComponent comp) { // Clear. image = null; if (comp instanceof JLabel) { JLabel label = (JLabel) comp; Icon icon = label.getIcon(); if (icon instanceof ImageIcon) { image = ((ImageIcon) icon).getImage(); return this; } } return null; } @Override public boolean importData(JComponent comp, Transferable transferable) { if (comp instanceof JLabel) { //log.debug("importData - 1"); JLabel label = (JLabel) comp; image = getDropData(transferable, label); //log.debug("importData - 2 - image = {}", image); return abstractTradePanel.processDroppedImage(image); } return false; } // Transferable. @Override public Object getTransferData(DataFlavor flavor) { if (isDataFlavorSupported(flavor)) { if (DataFlavor.imageFlavor.equals(flavor) && image != null && image.getHeight(null) > 0) { return image; } if (DataFlavor.javaFileListFlavor.equals(flavor)) { java.util.List<File> list = new java.util.LinkedList<File>(); File qrCodeFile = writeImageToFile(); if (qrCodeFile != null) { list.add(qrCodeFile); } return list; } if (uriListAsStringFlavor.equals(flavor)) { log.debug("uriListAsStringFlavor is supported"); File qrCodeFile = writeImageToFile(); if (qrCodeFile != null) { return "file://" + qrCodeFile.getAbsolutePath() + "\r\n"; } } } return null; } private File writeImageToFile() { // Write the image to the output stream. File qrCodeFile = null; try { // Default name just in case. String filename = ""; boolean areAdding = false; if (abstractTradePanel != null) { if (abstractTradePanel.getLabel() != null && !"".equals(abstractTradePanel.getLabel())) { filename = abstractTradePanel.getLabel(); areAdding = true; } if (abstractTradePanel.getAmount() != null && !"".equals(abstractTradePanel.getAmount())) { if (areAdding) { filename = filename + " - "; } filename = filename + abstractTradePanel.getAmount(); areAdding = true; } if (abstractTradePanel.getAddress() != null && !"".equals(abstractTradePanel.getAddress())) { if (areAdding) { filename = filename + " - "; } filename = filename + abstractTradePanel.getAddress(); areAdding = true; } } // Default if everything is missing. if ("".equals(filename)) { filename = "qrcode" + System.currentTimeMillis() + ".png"; } // Get the temporary directory location. File testFile = File.createTempFile("test", "txt"); testFile.deleteOnExit(); qrCodeFile = new File(testFile.getParent() + File.separator + filename + ".png"); qrCodeFile.deleteOnExit(); ImageIO.write(toBufferedImage(image, -1, -1), "png", qrCodeFile); } catch (IOException e1) { e1.printStackTrace(); } return qrCodeFile; } @Override public DataFlavor[] getTransferDataFlavors() { return flavors; } @Override public boolean isDataFlavorSupported(DataFlavor flavor) { for (int j = 0, m = flavors.length; j < m; j++) { if (flavor.equals(flavors[j])) { if (DataFlavor.imageFlavor.equals(flavor)) { if ( image != null && image.getHeight(null) > 0) { return true; } else { return false; } } else { return true; } } } return false; } @SuppressWarnings("rawtypes") private Image getDropData(Transferable transferable, JComponent label) { try { // Try to get an image. if (transferable.isDataFlavorSupported(DataFlavor.imageFlavor)) { log.debug("image flavor is supported"); Image img = (Image) transferable.getTransferData(DataFlavor.imageFlavor); if (img != null && img.getWidth(null) != -1) { return img; } } if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { log.debug("javaFileList is supported"); java.util.List list = (java.util.List) transferable.getTransferData(DataFlavor.javaFileListFlavor); for (Object aList : list) { File f = (File) aList; ImageIcon icon = new ImageIcon(f.getAbsolutePath()); if (icon.getImage() != null) { return icon.getImage(); } } } if (transferable.isDataFlavorSupported(uriListAsStringFlavor)) { log.debug("uriListAsStringFlavor is supported"); String uris = (String) transferable.getTransferData(uriListAsStringFlavor); // url-lists are defined by rfc 2483 as crlf-delimited // TODO iterate over list for all of them StringTokenizer tokenizer = new StringTokenizer(uris, "\r\n"); if (tokenizer.hasMoreTokens()) { String uri = tokenizer.nextToken(); // ignore comments if (!uri.startsWith("#") && !uri.isEmpty()) { log.debug("uri = '{}'", uri); java.awt.Image image = getURLImage(new URL(uri)); if (image != null) { return image; } ImageIcon uriIcon = new ImageIcon(uri); if (uriIcon.getImage() != null) { return uriIcon.getImage(); } } } } if (transferable.isDataFlavorSupported(uriListAsReaderFlavor)) { log.debug("uriListAsReaderFlavor is supported"); BufferedReader read = new BufferedReader(uriListAsReaderFlavor.getReaderForText(transferable)); // Remove 'file://' from file name. String fileName = read.readLine().substring(7).replace("%20", " "); // Remove 'localhost' from OS X file names. if (fileName.substring(0, 9).equals("localhost")) { fileName = fileName.substring(9); } read.close(); java.awt.Image image = getFileImage(new File(fileName)); if (image != null) { return image; } } if (transferable.isDataFlavorSupported(urlFlavor)) { log.debug("urlFlavor is supported"); URL url = (URL) transferable.getTransferData(urlFlavor); log.debug("url = '{}'", url); java.awt.Image image = getURLImage(url); if (image != null) { return image; } ImageIcon urlIcon = new ImageIcon(url); if (urlIcon.getImage() != null) { return urlIcon.getImage(); } } } catch (IOException ioe) { ioe.printStackTrace(); } catch (UnsupportedFlavorException e) { e.printStackTrace(); } return null; } private Image getURLImage(URL url) { Image imageToReturn = null; try { imageToReturn = ImageIO.read(url); } catch (IOException e) { e.printStackTrace(); } return imageToReturn; } private Image getFileImage(File file) { Image imageToReturn = null; try { imageToReturn = ImageIO.read(file); } catch (IOException e) { e.printStackTrace(); } return imageToReturn; } private BufferedImage toBufferedImage(Image image, int width, int height) { //log.debug("toBufferedImage - 1"); if (image == null) { return null; } if (width == -1) { width = image.getWidth(null); } if (height == -1) { height = image.getHeight(null); } // Draw original image to thumbnail image object and // scale it to the new size on-the-fly. //log.debug("toBufferedImage - 2.2, image = {}, width = {}, height = {}", new Object[] {image,width,height}); BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //log.debug("toBufferedImage - 2.3, bufferedImage = {}", bufferedImage); Graphics2D g2 = bufferedImage.createGraphics(); //log.debug("toBufferedImage - 3"); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.drawImage(image, 0, 0, width, height, null); //log.debug("toBufferedImage - 4"); g2.dispose(); return bufferedImage; } }