/* * @(#)TextInputFormat.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 org.jhotdraw.gui.filechooser.ExtensionFileFilter; import org.jhotdraw.draw.*; import java.awt.datatransfer.*; import java.awt.geom.*; import java.io.*; import java.net.URI; import java.util.*; import javax.swing.*; import org.jhotdraw.geom.Dimension2DDouble; /** * An input format for importing text into a drawing. * <p> * This class uses the prototype design pattern. A TextHolderFigure figure is used * as a prototype for creating a figure that holds the imported text. * <p> * For text that spans multiple lines, TextInputFormat can either add all the * text to the same Figure, or it can create a new Figure for each line. * * <hr> * <b>Design Patterns</b> * * <p><em>Prototype</em><br> * The text input format creates new text 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 TextHolderFigure}; Client: {@link org.jhotdraw.draw.io.TextInputFormat}. * <hr> * * @author Werner Randelshofer * @version $Id$ */ public class TextInputFormat implements InputFormat { /** * The prototype for creating a figure that holds the imported text. */ private TextHolderFigure prototype; /** * Format description used for the file filter. */ private String description; /** * File name extension used for the file filter. */ private String fileExtension; /** * Image IO image format name. */ private String formatName; /** * This should be set to true for ImageHolderFigures that can hold multiple * lines of text. */ private boolean isMultiline; /** Creates a new image output format for text, for a figure that can not. * hold multiple lines of text. */ public TextInputFormat(TextHolderFigure prototype) { this(prototype, "Text", "Text", "txt", false); } /** Creates a new image output 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 file filter. * @param isMultiline Set this to true, if the TextHolderFigure can hold * multiple lines of text. If this is true, multiple lines of text are * added to the same figure. If this is false, a new Figure is created for * each line of text. */ public TextInputFormat(TextHolderFigure prototype, String formatName, String description, String fileExtension, boolean isMultiline) { this.prototype = prototype; this.formatName = formatName; this.description = description; this.fileExtension = fileExtension; this.isMultiline = isMultiline; } @Override public javax.swing.filechooser.FileFilter getFileFilter() { return new ExtensionFileFilter(description, fileExtension); } public String getFileExtension() { return fileExtension; } @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) throws IOException { read(file, drawing, true); } public void read(File file, Drawing drawing, boolean replace) throws IOException { try (InputStream in = new FileInputStream(file)) { read(in, drawing, replace); } } @Override public void read(InputStream in, Drawing drawing, boolean replace) throws IOException { if (replace) { drawing.removeAllChildren(); } drawing.basicAddAll(0, createTextHolderFigures(in)); } public LinkedList<Figure> createTextHolderFigures(InputStream in) throws IOException { LinkedList<Figure> list = new LinkedList<>(); BufferedReader r = new BufferedReader(new InputStreamReader(in, "UTF8")); if (isMultiline) { TextHolderFigure figure = (TextHolderFigure) prototype.clone(); StringBuilder buf = new StringBuilder(); for (String line = null; line != null; line = r.readLine()) { if (buf.length() != 0) { buf.append('\n'); } buf.append(line); } figure.setText(buf.toString()); Dimension2DDouble s = figure.getPreferredSize(); figure.setBounds( new Point2D.Double(0, 0), new Point2D.Double( s.width, s.height)); } else { double y = 0; for (String line = null; line != null; line = r.readLine()) { TextHolderFigure figure = (TextHolderFigure) prototype.clone(); figure.setText(line); Dimension2DDouble s = figure.getPreferredSize(); figure.setBounds( new Point2D.Double(0, y), new Point2D.Double( s.width, s.height)); list.add(figure); y += s.height; } } if (list.size() == 0) { throw new IOException("No text found"); } return list; } @Override public boolean isDataFlavorSupported(DataFlavor flavor) { return flavor.equals(DataFlavor.stringFlavor); } @Override public void read(Transferable t, Drawing drawing, boolean replace) throws UnsupportedFlavorException, IOException { String text = (String) t.getTransferData(DataFlavor.stringFlavor); LinkedList<Figure> list = new LinkedList<>(); if (isMultiline) { TextHolderFigure figure = (TextHolderFigure) prototype.clone(); figure.setText(text); Dimension2DDouble s = figure.getPreferredSize(); figure.willChange(); figure.setBounds( new Point2D.Double(0, 0), new Point2D.Double( s.width, s.height)); figure.changed(); list.add(figure); } else { double y = 0; for (String line : text.split("\n")) { TextHolderFigure figure = (TextHolderFigure) prototype.clone(); figure.setText(line); Dimension2DDouble s = figure.getPreferredSize(); y += s.height; figure.willChange(); figure.setBounds( new Point2D.Double(0, 0 + y), new Point2D.Double( s.width, s.height + y)); figure.changed(); list.add(figure); } } if (replace) { drawing.removeAllChildren(); } drawing.addAll(list); } }