Package research.figure

Source Code of research.figure.TextAreaFigure$JInerTextArea

package research.figure;

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

import javax.swing.*;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.event.InputEvent;
import java.util.Vector;
import java.util.Hashtable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.AttributedString;
import java.text.AttributedCharacterIterator;

import research.util.ColorMap;

/**
* author: zhangwei
* Date: 2003-6-8
* Time: 14:55:30
*/
public class TextAreaFigure extends AbstractFigure
        implements FigureChangeListener, TextAreaHolder {

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

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

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

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

    private transient JInerTextArea textAgent = null;

    private class JInerTextArea extends JTextArea {

        public int getRowHeight() {
            return super.getRowHeight();
        }

        public int getColumnWidth() {
            return super.getColumnWidth();
        }
    }

    protected JInerTextArea getTextAgent() {
        if (textAgent == null) {

            Integer colums = (Integer) this.getAttribute("columns");

            //temp-test
            if (colums == null) {
                colums = new Integer(9);
                System.out.println("warning info: the 'columns' attribute of " + this + " is null");
            }
            //

            textAgent = new JInerTextArea();
            textAgent.setColumns(colums.intValue());
            textAgent.setEditable(false);
            textAgent.setEnabled(false);
            textAgent.setDisabledTextColor(textAgent.getForeground());
            textAgent.setCaretColor(textAgent.getBackground());
            textAgent.setBorder(BorderFactory.createEmptyBorder());
            textAgent.setOpaque(false);
            textAgent.setLineWrap(true);
            textAgent.setWrapStyleWord(true);
        }

        return textAgent;
    }


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

    public TextAreaFigure() {

        setAttribute("font", new Font("Dialog", Font.PLAIN, 14));
        setAttribute("anchor", new Point(0, 0));
        setAttribute("size", new Dimension(0, 0));
        setAttribute("fillColor", ColorMap.color("None"));
        setAttribute("textColor", Color.black);
        setAttribute("frameColor", ColorMap.color("None"));
        setAttribute("insets", new Insets(1, 4, 0, 4));
        setAttribute("columns", new Integer(9));

        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);
    }

    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) {

        Rectangle rect = new Rectangle(newOrigin);
        rect.add(newCorner);

        Point anchor = (Point) this.getAttribute("anchor");
        Dimension size = (Dimension) this.getAttribute("size");

        anchor.x = rect.x;
        anchor.y = rect.y;

        size.width = rect.width;
        size.height = rect.height;
    }

    public Rectangle getDisplayBox() {
        Dimension extent = textExtent();
        Insets insets = (Insets) this.getAttribute("insets");
        Point anchor = (Point) this.getAttribute("anchor");
        Dimension size = (Dimension) this.getAttribute("size");

        //temp-test
        if (size == null) {
            size = new Dimension(0, 0);
            System.out.println("warning info: the 'size' attribute of " + this + " is null");
        }
        //

        return new Rectangle(anchor.x, anchor.y,
                Math.max(extent.width, size.width) + insets.left + insets.right,
                Math.max(extent.height, size.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");
        Dimension size = (Dimension) this.getAttribute("size");
        rect.setBounds(anchor.x, anchor.y,
                Math.max(extent.width, size.width) + insets.left + insets.right,
                Math.max(extent.height, size.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);
            markDirty();
            changed();
        }
    }

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

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

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

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

    public void drawText(Graphics g) {

        Graphics2D g2 = (Graphics2D) g;

        if ((g2.getTransform().getScaleX() == 1) && (g2.getTransform().getScaleY() == 1)) {

            //old
            /**
             Rectangle rect = g.getClipBounds();
             Rectangle textBox = textDisplayBox();
             getTextAgent().setFont((Font) getAttribute("font"));
             getTextAgent().setText(getText());
             getTextAgent().setBounds(textBox);
             g.setClip(textBox);
             getTextAgent().getUI().getRootView(getTextAgent()).paint(g, textBox);
             g.setClip(rect);
             getTextAgent().getRows();
             **/

            //test
            Rectangle rect = g.getClipBounds();
            Rectangle textBox = textDisplayBox();
            getTextAgent().setBounds(textBox);
            getTextAgent().setForeground(g.getColor());
            getTextAgent().setDisabledTextColor(g.getColor());
            g.setClip(textBox);
            getTextAgent().getUI().getRootView(getTextAgent()).paint(g, textBox);
            g.setClip(rect);

        } else {
             /**
             Rectangle rect = g.getClipBounds();
             Rectangle textBox = textDisplayBox();
             getTextAgent().setBounds(textBox);
             g.setClip(textBox);
             getTextAgent().getUI().getRootView(getTextAgent()).paint(g, textBox);
             g.setClip(rect);
             **/

            Rectangle textBox = textDisplayBox();

            AffineTransform oldAT = g2.getTransform();
            g2.setTransform(AffineTransform.getTranslateInstance(0, 0));

            FontRenderContext frc = g2.getFontRenderContext();

            Point2D pen = textBox.getLocation();

            int rowsHeight = getTextAgent().getRowHeight();
            int lineCount = getTextAgent().getLineCount();

            String text = getText();
            if (text.length() == 0)
                text = " ";

            getTextAgent().setText(text);

            for (int i = 0; i < lineCount; i++) {
                String currentString = null;

                try {
                    //��õ�i�а������ַ�
                    currentString = text.substring(getTextAgent().getLineStartOffset(i), getTextAgent().getLineEndOffset(i));
                } catch (Exception e) {
                    ;
                }

                TextLayout layout = null;

                if (currentString.length() > 0) {

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

                    Hashtable map = new Hashtable();
                    map.put(TextAttribute.FONT, (Font) getAttribute("font"));
                    AttributedString as = new AttributedString(currentString, map);
                    AttributedCharacterIterator aci = as.getIterator();

                    LineBreakMeasurer measurer = new LineBreakMeasurer(aci, frc);
                    float wrappingWidth = textBox.width;

                    while (measurer.getPosition() < currentString.length()) {
                        layout = measurer.nextLayout(wrappingWidth);

                        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);

                        pen.setLocation(pen.getX(), pen.getY() + rowsHeight);
                    }

                } else {
                    pen.setLocation(pen.getX(), pen.getY() + rowsHeight);
                }

            }

            g2.setTransform(oldAT);
        }

    }

    private Dimension textExtent() {
        if (!fSizeIsDirty) {
            return new Dimension(fWidth, fHeight);
        }
        /**
         Font font = (Font) this.getAttribute("font");
         FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
         fWidth = metrics.stringWidth(getText());
         fHeight = metrics.getHeight()*5;
         fSizeIsDirty = false;
         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;
    }

    private void markDirty() {
        fSizeIsDirty = true;
    }

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

    public void setColumns(int cols) {
        int oldCols = getTextAgent().getColumns();
        int oldRows = getTextAgent().getRows();

        if (oldCols == cols)
            return;

        willChange();

        setAttribute("columns", new Integer(cols));

        if (cols > oldCols) {
            getTextAgent().setColumns(cols);
            getTextAgent().invalidate();
        } else {
            textAgent = new JInerTextArea();
            textAgent.setColumns(cols);
            textAgent.setRows(oldRows);
            textAgent.setEditable(false);
            textAgent.setEnabled(false);
            textAgent.setDisabledTextColor(textAgent.getForeground());
            textAgent.setCaretColor(textAgent.getBackground());
            textAgent.setBorder(BorderFactory.createEmptyBorder());
            textAgent.setOpaque(false);
            textAgent.setLineWrap(true);
            textAgent.setWrapStyleWord(true);

            textAgent.setText(getText());
            textAgent.invalidate();
        }

        markDirty();
        changed();

    }

    public Dimension getPreferredSize() {
        return getTextAgent().getPreferredSize();
    }

    public int getColumnsWidth() {
        return getTextAgent().getColumnWidth();
    }

    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 AreaWithHandle(this));

        //handles.addElement(new AreaFontSizeHandle(this, RelativeLocator.southWest()));

        return handles;
    }

    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;
            }
        }
    }

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

    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();
    }

    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 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();
            }
        }
    }

    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;
    }
}

class AreaWithHandle extends LocatorHandle {

    protected transient int columnWidth;
    protected transient int columns;

    protected transient int width;

    public AreaWithHandle(TextAreaFigure owner) {
        super(owner, RelativeLocator.east());
    }

    public void invokeStart(int x, int y, DrawingView view) {
        TextAreaFigure owner = (TextAreaFigure) this.owner();
        columnWidth = owner.getColumnsWidth();
        columns = owner.getColumns();
        width = owner.getPreferredSize().width;

        owner.willChange();
        owner.changed();
    }

    public void invokeStep(InputEvent inputEvent, int x, int y, int anchorX, int anchorY, DrawingView view) {
        TextAreaFigure owner = (TextAreaFigure) this.owner();

        int deltaX = x - anchorX;
        int deltaColumns = deltaX / columnWidth;

        int newColumns = columns + deltaColumns;

        if (newColumns <= 0) newColumns = 1;

        if (newColumns < 9) return;

        owner.willChange();

        Dimension before = owner.getPreferredSize();
        int oldColumns = owner.getColumns();
        owner.setColumns(newColumns);

        Dimension after = owner.getPreferredSize();

        if (before.width == after.width) {
            owner.setColumns(oldColumns);
        }

        owner.setAttribute("size", after);

        owner.changed();
    }

    public void invokeEnd(int x, int y, int anchorX, int anchorY, DrawingView view) {
        columnWidth = 0;
        columns = 0;
        width = 0;

        TextAreaFigure owner = (TextAreaFigure) this.owner();
        owner.willChange();
        owner.changed();
    }

}
TOP

Related Classes of research.figure.TextAreaFigure$JInerTextArea

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.