/******************************************************************************* * Copyright (c) 2006-2012 * Software Technology Group, Dresden University of Technology * DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026 * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Technology Group - TU Dresden, Germany; * DevBoost GmbH - Berlin, Germany * - initial API and implementation ******************************************************************************/ /* * @(#)TextAreaCreationTool.java 2.3.1 2009-09-29 * * Copyright (c) 1996-2009 by the original authors of JHotDraw * and all its contributors. * All rights reserved. * * The copyright of this software is owned by the authors and * contributors of the JHotDraw project ("the copyright holders"). * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * the copyright holders. For details see accompanying license terms. */ package org.jhotdraw.draw; import java.awt.*; import java.awt.geom.*; import java.awt.event.*; import java.util.*; import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.UndoableEdit; import org.jhotdraw.geom.*; import org.jhotdraw.util.ResourceBundleUtil; /** * A tool to create new or edit existing figures that implement the TextHolderFigure * interface, such as TextAreaFigure. The figure to be created is specified by a * prototype. * <p> * To create a figure using the TextAreaCreationTool, the user does the following mouse * gestures on a DrawingView: * <ol> * <li>Press the mouse button over the DrawingView. This defines the * start point of the Figure bounds.</li> * <li>Drag the mouse while keeping the mouse button pressed, and then release * the mouse button. This defines the end point of the Figure bounds.</li> * </ol> * When the user has performed these mouse gesture, the TextAreaCreationTool overlays * a text area over the drawing where the user can enter the text for the Figure. * <p> * To edit an existing text figure using the TextAreaCreationTool, the user does the * following mouse gesture on a DrawingView: * </p> * <ol> * <li>Press the mouse button over a Figure on the DrawingView.</li> * </ol> * <p> * The TextAreaCreationTool then uses Figure.findFigureInside to find a Figure that * implements the TextHolderFigure interface and that is editable. Then it overlays * a text area over the drawing where the user can enter the text for the Figure. * </p> * <p> * XXX - Maybe this class should be split up into a CreateTextAreaTool and * a EditTextAreaTool. * </p> * * @author Werner Randelshofer * @version 2.3.1 2009-03-29 Editing of a TextArea which is behind another figure * did not work. Partially implemented undoable edit handling. * <br>2.3 2008-05-17 Honor toolDoneAfterCreation property. * <br>2.2 2007-11-25 Added variable isForCreationOnly. * <br>2.1 2007-08-22 Added support for property 'toolDoneAfterCreation'. * <br>2.0 2006-01-14 Changed to support double precison coordinates. * <br>1.0 2003-12-01 Derived from JHotDraw 5.4b1. * @see TextHolderFigure * @see FloatingTextArea */ public class TextAreaCreationTool extends CreationTool implements ActionListener { private FloatingTextArea textArea; private TextHolderFigure typingTarget; /** * Rubberband color of the tool. When this is null, the tool does not * draw a rubberband. */ private Color rubberbandColor = null; /** Creates a new instance. */ public TextAreaCreationTool(TextHolderFigure prototype) { super(prototype); } public TextAreaCreationTool(TextHolderFigure prototype, Map<AttributeKey,Object> attributes) { super(prototype, attributes); } /** * Sets the rubberband color for the tool. Setting this to null, disables * the rubberband. * * @param c Rubberband color or null. */ public void setRubberbandColor(Color c) { rubberbandColor = c; } @Override public void deactivate(DrawingEditor editor) { endEdit(); super.deactivate(editor); } /** * Creates a new figure at the mouse location. * If editing is in progress, this finishes editing. */ @Override public void mousePressed(MouseEvent e) { TextHolderFigure textHolder = null; // Note: The search sequence used here, must be // consistent with the search sequence used by the // HandleTracker, SelectAreaTracker, DelegationSelectionTool, SelectionTool. // If possible, continue to work with the current selection DrawingView v = getView(); Point2D.Double p = v.viewToDrawing(e.getPoint()); Figure pressedFigure = null; if (true /*isSelectBehindEnabled()*/) { for (Figure f : v.getSelectedFigures()) { if (f.contains(p)) { pressedFigure = f; break; } } } // If the point is not contained in the current selection, // search for a figure in the drawing. if (pressedFigure == null) { pressedFigure = getDrawing().findFigureInside(p); } // if (pressedFigure instanceof TextHolderFigure) { textHolder = (TextHolderFigure) pressedFigure; textHolder = null; } if (textHolder != null) { createdFigure = null; beginEdit(textHolder); return; } if (typingTarget != null) { endEdit(); if (isToolDoneAfterCreation()) { fireToolDone(); } } else { super.mousePressed(e); } } /** * This method allows subclasses to do perform additonal user interactions * after the new figure has been created. * The implementation of this class just invokes fireToolDone. */ @Override protected void creationFinished(Figure createdFigure) { getView().clearSelection(); getView().addToSelection(createdFigure); beginEdit((TextHolderFigure) createdFigure); } /* public void mouseDragged(java.awt.event.MouseEvent e) { } */ @Override public void draw(Graphics2D g) { if (createdFigure != null && rubberbandColor != null) { g.setColor(rubberbandColor); g.draw(getView().drawingToView(createdFigure.getBounds())); } } protected void beginEdit(TextHolderFigure textHolder) { if (textArea == null) { textArea = new FloatingTextArea(); //textArea.addActionListener(this); } if (textHolder != typingTarget && typingTarget != null) { endEdit(); } textArea.createOverlay(getView(), textHolder); textArea.setBounds(getFieldBounds(textHolder), textHolder.getText()); textArea.requestFocus(); typingTarget = textHolder; } private Rectangle2D.Double getFieldBounds(TextHolderFigure figure) { Rectangle2D.Double r = figure.getDrawingArea(); Insets2D.Double insets = figure.getInsets(); insets.subtractTo(r); // FIXME - Find a way to determine the parameters for grow. //r.grow(1,2); //r.width += 16; r.x -= 1; r.y -= 2; r.width += 18; r.height += 4; return r; } protected void endEdit() { if (typingTarget != null) { typingTarget.willChange(); final TextHolderFigure editedFigure = typingTarget; final String oldText = typingTarget.getText(); final String newText = textArea.getText(); if (newText.length() > 0) { typingTarget.setText(newText); } else { if (createdFigure != null) { getDrawing().remove((Figure) getAddedFigure()); // XXX - Fire undoable edit here!! } else { typingTarget.setText(""); } } UndoableEdit edit = new AbstractUndoableEdit() { @Override public String getPresentationName() { ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"); return labels.getString("attribute.text.text"); } @Override public void undo() { super.undo(); editedFigure.willChange(); editedFigure.setText(oldText); editedFigure.changed(); } @Override public void redo() { super.redo(); editedFigure.willChange(); editedFigure.setText(newText); editedFigure.changed(); } }; getDrawing().fireUndoableEditHappened(edit); typingTarget.changed(); typingTarget = null; textArea.endOverlay(); } // view().checkDamage(); } public void actionPerformed(ActionEvent event) { endEdit(); if (isToolDoneAfterCreation()) { fireToolDone(); } } }