/* * @(#)FloatingTextField.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.text; import edu.umd.cs.findbugs.annotations.Nullable; import org.jhotdraw.draw.event.FigureListener; import org.jhotdraw.draw.event.FigureAdapter; import org.jhotdraw.draw.event.FigureEvent; import org.jhotdraw.draw.*; import javax.swing.*; import java.awt.*; import java.awt.geom.*; import java.awt.event.*; import static org.jhotdraw.draw.AttributeKeys.*; /** * A <em>floating text field</em> that is used to edit a {@link TextHolderFigure}. * <p> * {@code FloatingTextField} requires a two step initialization: * In a first step the overlay is created and in a * second step it can be positioned. * * <hr> * <b>Design Patterns</b> * * <p><em>Framework</em><br> * The text creation and editing tools and the {@code TextHolderFigure} * interface define together the contracts of a smaller framework inside of the * JHotDraw framework for structured drawing editors.<br> * Contract: {@link TextHolderFigure}, {@link org.jhotdraw.draw.tool.TextCreationTool}, * {@link org.jhotdraw.draw.tool.TextAreaCreationTool}, * {@link org.jhotdraw.draw.tool.TextEditingTool}, * {@link org.jhotdraw.draw.tool.TextAreaEditingTool}, {@link FloatingTextField}, * {@link FloatingTextArea}. * <hr> * * @author Werner Randelshofer * @version $Id: FloatingTextField.java -1 $ */ public class FloatingTextField { @Nullable private TextHolderFigure editedFigure; private JTextField textField; private DrawingView view; private FigureListener figureHandler = new FigureAdapter() { @Override public void attributeChanged(FigureEvent e) { updateWidget(); } }; public FloatingTextField() { textField = new JTextField(20); } public void requestFocus() { textField.requestFocus(); } /** * Creates the overlay for the given Container using a * specific font. */ public void createOverlay(DrawingView view, TextHolderFigure figure) { view.getComponent().add(textField, 0); textField.setText(figure.getText()); textField.setColumns(figure.getTextColumns()); textField.selectAll(); textField.setVisible(true); editedFigure = figure; editedFigure.addFigureListener(figureHandler); this.view = view; updateWidget(); } protected void updateWidget() { Font font = editedFigure.getFont(); font = font.deriveFont(font.getStyle(), (float) (editedFigure.getFontSize() * view.getScaleFactor())); textField.setFont(font); textField.setForeground(editedFigure.getTextColor()); textField.setBackground(editedFigure.getFillColor()); Rectangle2D.Double fDrawBounds = editedFigure.getBounds(); Point2D.Double fDrawLoc = new Point2D.Double(fDrawBounds.getX(), fDrawBounds.getY()); if (editedFigure.get(TRANSFORM) != null) { editedFigure.get(TRANSFORM).transform(fDrawLoc, fDrawLoc); } Point fViewLoc = view.drawingToView(fDrawLoc); Rectangle fViewBounds = view.drawingToView(fDrawBounds); fViewBounds.x = fViewLoc.x; fViewBounds.y = fViewLoc.y; Dimension tfDim = textField.getPreferredSize(); Insets tfInsets = textField.getInsets(); float fontBaseline = textField.getGraphics().getFontMetrics(font).getMaxAscent(); double fBaseline = editedFigure.getBaseline() * view.getScaleFactor(); textField.setBounds( fViewBounds.x - tfInsets.left, fViewBounds.y - tfInsets.top - (int) (fontBaseline - fBaseline), Math.max(fViewBounds.width + tfInsets.left + tfInsets.right, tfDim.width), Math.max(fViewBounds.height + tfInsets.top + tfInsets.bottom, tfDim.height) ); } public Insets getInsets() { return textField.getInsets(); } /** * Adds an action listener */ public void addActionListener(ActionListener listener) { textField.addActionListener(listener); } /** * Remove an action listener */ public void removeActionListener(ActionListener listener) { textField.removeActionListener(listener); } /** * Gets the text contents of the overlay. */ public String getText() { return textField.getText(); } /** * Gets the preferred size of the overlay. */ public Dimension getPreferredSize(int cols) { textField.setColumns(cols); return textField.getPreferredSize(); } /** * Removes the overlay. */ public void endOverlay() { view.getComponent().requestFocus(); if (textField != null) { textField.setVisible(false); view.getComponent().remove(textField); Rectangle bounds = textField.getBounds(); view.getComponent().repaint(bounds.x, bounds.y, bounds.width, bounds.height); } if (editedFigure != null) { editedFigure.removeFigureListener(figureHandler); editedFigure = null; } } }