Package research.figure

Source Code of research.figure.TextFigure

/*
* @(#)TextFigure.java
*
* Project:    JHotdraw - a GUI framework for technical drawings
*        http://www.jhotdraw.org
*        http://jhotdraw.sourceforge.net
* Copyright:  ?by the original author(s) and all contributors
* License:    Lesser GNU Public License (LGPL)
*        http://www.opensource.org/licenses/lgpl-license.html
*/

package research.figure;


import research.*;
import research.connector.BoxConnector;
import research.connector.ChopBoxConnector;
import research.connector.Connector;
import research.store.StorableOutput;
import research.store.StorableInput;

import java.util.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.io.*;

import research.util.ColorMap;

import javax.swing.*;


/**
* A text figure.
*
* @version <$CURRENT_VERSION$>
* @see research.tool.TextTool
*/
public class TextFigure
        extends AbstractFigure
        implements FigureChangeListener, TextHolder {

    protected static final int CENTER = 0;
    protected static final int NORTH = 1;
    protected static final int SOUTH = 2;
    protected static final int WEST = 3;
    protected static final int EAST = 4;

    // cache of the TextFigure's size
    transient private boolean fSizeIsDirty = true;
    transient private int fWidth;
    transient private int fHeight;

    private int minWidth = 0;
    private int leftInset = 0;
    private int rightInset = 0;

    public final static String TEXT = "text";
    private boolean fIsReadOnly;

    private Figure fObservedFigure = null;
    private OffsetLocator fLocator = null;

    private transient JTextField textAgent = null;

    protected JTextField getTextAgent() {
        if (textAgent == null) {
            textAgent = new JTextField();
            textAgent.setEditable(false);
            textAgent.setEnabled(false);
            textAgent.setDisabledTextColor(textAgent.getForeground());
            textAgent.setCaretColor(textAgent.getBackground());
            textAgent.setBorder(BorderFactory.createEmptyBorder());
            textAgent.setOpaque(false);
        }

        return textAgent;
    }

    /*
     * Serialization support.
     */
    private static final long serialVersionUID = 4599820785949456124L;
    private int textFigureSerializedDataVersion = 1;

    public TextFigure() {

        setAttribute("font", new Font("Dialog", Font.PLAIN, 14));
        setAttribute("anchor", new Point(0, 0));
        setAttribute("fillColor", ColorMap.color("None"));
        setAttribute("textColor", Color.black);
        setAttribute("frameColor", ColorMap.color("None"));
        setAttribute("insets", new Insets(1, 6, 1, 6));

        setAttribute("minWidth", 0);
        setAttribute("leftInset", 0);
        setAttribute("rightInset", 0);

        setAttribute(TEXT, "");
        fSizeIsDirty = true;

        initConnectors();
    }

    protected void initConnectors() {
        connector = new Connector[5];
        connector[NORTH] = new BoxConnector(this, BoxConnector.NORTH);
        connector[SOUTH] = new BoxConnector(this, BoxConnector.SOUTH);
        connector[WEST] = new BoxConnector(this, BoxConnector.WEST);
        connector[EAST] = new BoxConnector(this, BoxConnector.EAST);
        connector[CENTER] = new ChopBoxConnector(this);
    }

    @Override
    public void setAttribute(String name, Object value){
        this.willChange();
        super._setAttribute(name, value);
        if(name != null){
            if(name.equals("minWidth")){
                minWidth = (Integer) value;
            } else if(name.equals("leftInset")){
                leftInset = (Integer) value;
            } else if(name.equals("rightInset")){
                rightInset = (Integer) value;
            }
        }
        this.changed();
    }

    @Override
    public void moveBy(int x, int y) {
        willChange();
        basicMoveBy(x, y);
        if (fLocator != null) {
            fLocator.moveBy(x, y);
        }
        changed();
    }

    protected void basicMoveBy(int x, int y) {
        Point anchor = (Point) this.getAttribute("anchor");
        anchor.x += x;
        anchor.y += y;
    }

    public void basicDisplayBox(Point newOrigin, Point newCorner) {
        Point anchor = (Point) this.getAttribute("anchor");
        anchor.x = newOrigin.x;
        anchor.y = newOrigin.y;
    }

    public int getMinWidth() {
        return minWidth;
    }

    public Rectangle getDisplayBox() {
        Dimension extent = textExtent();
        Insets insets = (Insets) this.getAttribute("insets");
        Point anchor = (Point) this.getAttribute("anchor");
        return new Rectangle(anchor.x, anchor.y,
                extent.width + insets.left + insets.right,
                extent.height + insets.top + insets.bottom);
    }

    public Rectangle getDisplayBox(Rectangle rect) {
        if (rect == null)
            rect = new Rectangle();

        Dimension extent = textExtent();
        Insets insets = (Insets) this.getAttribute("insets");
        Point anchor = (Point) this.getAttribute("anchor");
        rect.setBounds(anchor.x, anchor.y,
                extent.width + insets.left + insets.right,
                extent.height + insets.top + insets.bottom);
        return rect;
    }

    public Rectangle textDisplayBox() {
        Dimension extent = textExtent();
        Insets insets = (Insets) this.getAttribute("insets");
        Point anchor = (Point) this.getAttribute("anchor");
        return new Rectangle(anchor.x + insets.left, anchor.y + insets.top, extent.width, extent.height);
    }

    /**
     * Tests whether this figure is read only.
     */
    public boolean readOnly() {
        return fIsReadOnly;
    }

    /**
     * Sets the read only status of the text figure.
     */
    public void setReadOnly(boolean isReadOnly) {
        fIsReadOnly = isReadOnly;
    }

    /**
     * Gets the font.
     */
    public Font getFont() {
        return (Font) this.getAttribute("font");
    }

    /**
     * Sets the font.
     */
    public void setFont(Font newFont) {
        if (newFont == null)
            return;
        willChange();
        setAttribute("font", newFont);
        markDirty();
        changed();
    }

    /**
     * Updates the location whenever the figure changes itself.
     */
    public void changed() {
        super.changed();
        updateLocation();
    }

    /**
     * Gets the text shown by the text figure.
     */
    public String getText() {
        return (String) getAttribute(TEXT);
    }

    /**
     * Sets the text shown by the text figure.
     */
    public void setText(String newText) {
        if (newText == null)
            return;

        if (!getText().equals(newText)) {
            willChange();
            setAttribute(TEXT, newText);

            int realWidth = getDisplayBox().width - leftInset - rightInset;

            if (realWidth <= minWidth) {
                Insets insets = (Insets) this.getAttribute("insets");
                insets.left -= leftInset;
                insets.right -= rightInset;

                setAttribute("leftInset", (minWidth - realWidth) / 2);
                setAttribute("rightInset", minWidth - realWidth - leftInset);

                insets.left += leftInset;
                insets.right += rightInset;
            } else {
                if ((leftInset > 0) || (rightInset > 0)) {
                    Insets insets = (Insets) this.getAttribute("insets");
                    insets.left -= leftInset;
                    insets.right -= rightInset;

                    setAttribute("leftInset", 0);
                    setAttribute("rightInset", 0);
                }
            }

            markDirty();
            changed();
        }
    }

    /**
     * Tests whether the figure accepts typing.
     */
    public boolean acceptsTyping() {
        return !fIsReadOnly;
    }

    @Override
    public void drawBackground(Graphics g) {
        Rectangle r = getDisplayBox();
        g.fillRect(r.x, r.y, r.width, r.height);
    }

    @Override
    public void drawFrame(Graphics g) {
        Rectangle box = getDisplayBox();
        g.drawRect(box.x, box.y, box.width, box.height);
    }

    @Override
    public void drawContent(Graphics g) {
        Color text = getTextColor();
        if (!ColorMap.isTransparent(text)) {
            Color _old = g.getColor();
            g.setColor(text);
            drawText(g);
            g.setColor(_old);
        }
    }

    protected void drawText(Graphics g) {

        Graphics2D g2 = (Graphics2D) g;
        if ((g2.getTransform().getScaleX() == 1) && (g2.getTransform().getScaleY() == 1)) {
            Rectangle rect = g.getClipBounds();
            Rectangle textBox = textDisplayBox();
            getTextAgent().setBounds(textBox);
            getTextAgent().setForeground(g.getColor());
            getTextAgent().setDisabledTextColor(g.getColor());
            getTextAgent().getUI().getRootView(getTextAgent()).paint(g, textBox);
            g.setClip(rect);
        } else {
            //����ַ�������ʾ����
            Rectangle textBox = textDisplayBox();
            //��þɵı任����
            AffineTransform oldAT = g2.getTransform();
            //���ñ任����Ϊ����
            g2.setTransform(AffineTransform.getTranslateInstance(0, 0));

            FontRenderContext frc = g2.getFontRenderContext();

            Point2D pen = textBox.getLocation();

            getTextAgent().setText(getText());

            String currentString = getTextAgent().getText();

            TextLayout layout = null;

            if (currentString.length() > 0) {
                layout = new TextLayout(currentString, (Font) getAttribute("font"), frc);
                pen.setLocation(pen.getX(), pen.getY() + layout.getAscent());

                Shape shape = layout.getOutline(oldAT);
                double deltaScale = textBox.width * oldAT.getScaleX() / shape.getBounds().width;
                if (1 - deltaScale > 0) {
                    AffineTransform adjust = (AffineTransform) oldAT.clone();
                    adjust.scale(deltaScale, 1);
                    shape = layout.getOutline(adjust);
                }
                AffineTransform at = AffineTransform.getTranslateInstance(pen.getX() * oldAT.getScaleX(), pen.getY() * oldAT.getScaleY());
                shape = at.createTransformedShape(shape);
                g2.fill(shape);
            }

            g2.setTransform(oldAT);
        }

    }

    protected Dimension textExtent() {
        if (!fSizeIsDirty) {
            return new Dimension(fWidth, fHeight);
        }

        getTextAgent().setFont((Font) getAttribute("font"));
        getTextAgent().setText(getText());

        Dimension dim = getTextAgent().getPreferredSize();
        fWidth = dim.width;
        fHeight = dim.height;

        return dim;

        /**
         Font font = (Font) this.getAttribute("font");
         FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
         fWidth = metrics.stringWidth(getText());
         fHeight = metrics.getHeight();
         fSizeIsDirty = false;
         return new Dimension(fWidth, fHeight);
         **/
    }

    protected void markDirty() {
        fSizeIsDirty = true;
    }

    /**
     * Gets the number of columns to be overlaid when the figure is edited.
     */
    public int overlayColumns() {
        int length = getText().length();
        int columns = 20;
        if (length != 0) {
            columns = getText().length() + 3;
        }
        return columns;
    }

    public Vector handles() {
        Vector handles = new Vector();
        handles.addElement(new NullHandle(this, RelativeLocator.northWest()));
        handles.addElement(new NullHandle(this, RelativeLocator.northEast()));
        handles.addElement(new NullHandle(this, RelativeLocator.southEast()));
        handles.addElement(new NullHandle(this, RelativeLocator.southWest()));
        //handles.addElement(new FontSizeHandle(this, RelativeLocator.southWest()));
        return handles;
    }

    @Override
    public Connector connectorAt(int x, int y) {
        Rectangle rect = getDisplayBox();
        if (!rect.contains(x, y)) return null;

        int index = findLocation(x, y);
        if (index < 0) return null;

        Connector[] array = getConnectors();
        return array[index];
    }

    private int findLocation(int x, int y) {
        Rectangle rect = getDisplayBox();

        if (x < rect.x + rect.width / 3) {
            if (y < rect.y + rect.height / 3) {
                return -1;
            } else if (y < rect.y + rect.height - rect.height / 3) {
                return WEST;
            } else {
                return -1;
            }
        } else if (x < rect.x + rect.width - rect.width / 3) {
            if (y < rect.y + rect.height / 3) {
                return NORTH;
            } else if (y < rect.y + rect.height - rect.height / 3) {
                return CENTER;
            } else {
                return SOUTH;
            }
        } else {
            if (y < rect.y + rect.height / 3) {
                return -1;
            } else if (y < rect.y + rect.height - rect.height / 3) {
                return EAST;
            } else {
                return -1;
            }
        }
    }

    @Override
    public void write(StorableOutput dw) {
        super.write(dw);
        dw.writeBoolean(fIsReadOnly);
        dw.writeStorable(fObservedFigure);
        dw.writeStorable(fLocator);
    }

    @Override
    public void read(StorableInput dr) throws IOException {
        super.read(dr);
        markDirty();
        fIsReadOnly = dr.readBoolean();

        fObservedFigure = (Figure) dr.readStorable();
        if (fObservedFigure != null) {
            fObservedFigure.addFigureChangeListener(this);
        }
        fLocator = (OffsetLocator) dr.readStorable();

        Object _minWidth = getAttribute("minWidth");
        if (_minWidth != null)
            minWidth = (Integer) _minWidth;
        else
            setAttribute("minWidth", 0);

        Object _leftInset = getAttribute("leftInset");
        if (_leftInset != null)
            leftInset = (Integer) _leftInset;
        else
            setAttribute("leftInset", 0);

        Object _rightInset = getAttribute("rightInset");
        if (_rightInset != null)
            rightInset = (Integer) _rightInset;
        else
            setAttribute("rightInset", 0);
    }


    /**
     * This method is used to implement the clone mtehod of AttributeFigure.
     * @param s
     * @throws ClassNotFoundException
     * @throws IOException
     */
    private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {

        s.defaultReadObject();

        if (fObservedFigure != null) {
            fObservedFigure.addFigureChangeListener(this);
        }
        markDirty();

    }

    public void connect(Figure figure) {
        if (fObservedFigure != null) {
            fObservedFigure.removeFigureChangeListener(this);
        }

        fObservedFigure = figure;
        fLocator = new OffsetLocator(figure.connectedTextLocator(this));
        fObservedFigure.addFigureChangeListener(this);
        updateLocation();
    }

    public boolean isConnected() {
        return (fObservedFigure != null);
    }

    public Figure getConnectedFigure() {
        return fObservedFigure;
    }

    public void figureChanged(FigureChangeEvent e) {
        updateLocation();
    }

    public void figureRemoved(FigureChangeEvent e) {
        if (listener() != null) {
            listener().figureRequestRemove(new FigureChangeEvent(this));
        }
    }

    public void figureRequestRemove(FigureChangeEvent e) {
    }

    public void figureInvalidated(FigureChangeEvent e) {
    }

    public void figureRequestUpdate(FigureChangeEvent e) {
    }

    /**
     * Updates the location relative to the connected figure.
     * The TextFigure is centered around the located point.
     */
    protected void updateLocation() {
        if (fLocator != null) {
            Point p = fLocator.locate(fObservedFigure);
            Point anchor = (Point) this.getAttribute("anchor");

            p.x -= size().width / 2 + anchor.x;
            p.y -= size().height / 2 + anchor.y;
            if (p.x != 0 || p.y != 0) {
                willChange();
                basicMoveBy(p.x, p.y);
                changed();
            }
        }
    }

    @Override
    public void release() {
        super.release();
        disconnect(fObservedFigure);
        fObservedFigure = null;
    }

    /**
     * Disconnects a text holder from a connect figure.
     */
    public void disconnect(Figure disconnectFigure) {
        if (disconnectFigure != null) {
            disconnectFigure.removeFigureChangeListener(this);
        }
        fLocator = null;
    }

}
TOP

Related Classes of research.figure.TextFigure

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.