/*
* @(#)ImageInputFormat.java
*
* Copyright (c) 1996-2010 The authors and contributors of JHotDraw.
* You may not use, copy or modify this file, except in compliance with the
* accompanying license terms.
*/
package org.jhotdraw.draw.io;
import java.net.URI;
import org.jhotdraw.gui.filechooser.ExtensionFileFilter;
import org.jhotdraw.draw.*;
import org.jhotdraw.draw.ImageHolderFigure;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.geom.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;
import org.jhotdraw.util.Images;
import static org.jhotdraw.draw.AttributeKeys.*;
/**
* An input format for importing drawings using one of the image formats
* supported by javax.imageio.
* <p>
* This class uses the prototype design pattern. A ImageHolderFigure figure is
* used as a prototype for creating a figure that holds the imported image.
* <p>
* If the drawing is replaced using the loaded image, the size of the
* drawing is set to match the size of the image using the attributes
* {@code AttributeKeys.CANVAS_WIDTH} and {@code AttributeKeys.CANVAS_HEIGHT}.
*
* <hr>
* <b>Design Patterns</b>
*
* <p><em>Prototype</em><br>
* The image input format creates new image holder figures by cloning a prototype figure
* object and assigning an image to it, which was read from data input.
* That's the reason why {@code Figure} extends the {@code Cloneable} interface.
* <br>
* Prototype: {@link org.jhotdraw.draw.ImageHolderFigure}; Client: {@link ImageInputFormat}.
* <hr>
*
* @author Werner Randelshor
* @version $Id$
*/
public class ImageInputFormat implements InputFormat {
/**
* The prototype for creating a figure that holds the imported image.
*/
private ImageHolderFigure prototype;
/**
* Format description used for the file filter.
*/
private String description;
/**
* File name extension used for the file filter.
*/
private String[] fileExtensions;
/**
* Image IO image format name.
*/
private String formatName;
/**
* The mime types which must be matched.
*/
private String[] mimeTypes;
/** Creates a new image input format for all formats supported by
* {@code javax.imageio.ImageIO}. */
public ImageInputFormat(ImageHolderFigure prototype) {
this(prototype, "Image", "Image", ImageIO.getReaderFileSuffixes(), ImageIO.getReaderMIMETypes());
}
/** Creates a new image input format for the specified image format.
*
* @param formatName The format name for the javax.imageio.ImageIO object.
* @param description The format description to be used for the file filter.
* @param fileExtension The file extension to be used for the file filter.
* @param mimeType The mime type used for filtering data flavors from
* Transferable objects.
*/
public ImageInputFormat(ImageHolderFigure prototype, String formatName, String description, String fileExtension,
String mimeType) {
this(prototype, formatName, description, new String[]{fileExtension}, new String[]{mimeType});
}
/** Creates a new image input format for the specified image format.
*
* @param formatName The format name for the javax.imageio.ImageIO object.
* @param description The format description to be used for the file filter.
* @param fileExtensions The file extensions to be used for the file filter.
* @param mimeTypes The mime typse used for filtering data flavors from
* Transferable objects.
*/
public ImageInputFormat(ImageHolderFigure prototype, String formatName, String description, String fileExtensions[], String[] mimeTypes) {
this.prototype = prototype;
this.formatName = formatName;
this.description = description;
this.fileExtensions = fileExtensions.clone();
this.mimeTypes = mimeTypes.clone();
}
@Override
public javax.swing.filechooser.FileFilter getFileFilter() {
return new ExtensionFileFilter(description, fileExtensions);
}
public String[] getFileExtensions() {
return fileExtensions.clone();
}
@Override
public JComponent getInputFormatAccessory() {
return null;
}
@Override
public void read(URI uri, Drawing drawing) throws IOException {
read(new File(uri), drawing);
}
@Override
public void read(URI uri, Drawing drawing, boolean replace) throws IOException {
read(new File(uri), drawing, replace);
}
public void read(File file, Drawing drawing, boolean replace) throws IOException {
ImageHolderFigure figure = (ImageHolderFigure) prototype.clone();
figure.loadImage(file);
figure.setBounds(
new Point2D.Double(0, 0),
new Point2D.Double(
figure.getBufferedImage().getWidth(),
figure.getBufferedImage().getHeight()));
if (replace) {
drawing.removeAllChildren();
drawing.set(CANVAS_WIDTH, figure.getBounds().width);
drawing.set(CANVAS_HEIGHT, figure.getBounds().height);
}
drawing.basicAdd(figure);
}
public void read(File file, Drawing drawing) throws IOException {
read(file, drawing, true);
}
@Override
public void read(InputStream in, Drawing drawing, boolean replace) throws IOException {
ImageHolderFigure figure = createImageHolder(in);
if (replace) {
drawing.removeAllChildren();
drawing.set(CANVAS_WIDTH, figure.getBounds().width);
drawing.set(CANVAS_HEIGHT, figure.getBounds().height);
}
drawing.basicAdd(figure);
}
public ImageHolderFigure createImageHolder(InputStream in) throws IOException {
ImageHolderFigure figure = (ImageHolderFigure) prototype.clone();
figure.loadImage(in);
figure.setBounds(
new Point2D.Double(0, 0),
new Point2D.Double(
figure.getBufferedImage().getWidth(),
figure.getBufferedImage().getHeight()));
return figure;
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
if (DataFlavor.imageFlavor.match(flavor)) {
return true;
}
for (String mimeType : mimeTypes) {
if (flavor.isMimeTypeEqual(mimeType)) {
return true;
}
}
return false;
}
@Override
public void read(Transferable t, Drawing drawing, boolean replace) throws UnsupportedFlavorException, IOException {
DataFlavor importFlavor = null;
SearchLoop:
for (DataFlavor flavor : t.getTransferDataFlavors()) {
if (DataFlavor.imageFlavor.match(flavor)) {
importFlavor = flavor;
break SearchLoop;
}
for (String mimeType : mimeTypes) {
if (flavor.isMimeTypeEqual(mimeType)) {
importFlavor = flavor;
break SearchLoop;
}
}
}
Object data = t.getTransferData(importFlavor);
Image img = null;
if (data instanceof Image) {
img = (Image) data;
} else if (data instanceof InputStream) {
img = ImageIO.read((InputStream) data);
}
if (img == null) {
throw new IOException("Unsupported data format " + importFlavor);
}
ImageHolderFigure figure = (ImageHolderFigure) prototype.clone();
figure.setBufferedImage(Images.toBufferedImage(img));
figure.setBounds(
new Point2D.Double(0, 0),
new Point2D.Double(
figure.getBufferedImage().getWidth(),
figure.getBufferedImage().getHeight()));
LinkedList<Figure> list = new LinkedList<Figure>();
list.add(figure);
if (replace) {
drawing.removeAllChildren();
drawing.set(CANVAS_WIDTH, figure.getBounds().width);
drawing.set(CANVAS_HEIGHT, figure.getBounds().height);
}
drawing.addAll(list);
}
}