Package javax.swing.text

Source Code of javax.swing.text.PlainView

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
/**
* @author Alexey A. Ivanov
* @version $Revision$
*/
package javax.swing.text;

import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentEvent.ElementChange;
import javax.swing.event.DocumentEvent.EventType;

import org.apache.harmony.awt.text.TextKit;
import org.apache.harmony.awt.text.TextUtils;

import org.apache.harmony.x.swing.internal.nls.Messages;

public class PlainView extends View implements TabExpander {
    protected FontMetrics metrics;
    final TextPaintParams paintParams = new TextPaintParams(this);
    private Element widestLine;
    private int widestLineWidth;

    /**
     * It is assumed that <code>element</code> is default root of document
     * this view represents (PlainDocument).
     */
    public PlainView(final Element element) {
        super(element);
    }

    public float getPreferredSpan(final int axis) {
        conditionalUpdateMetrics();

        switch (axis) {
        case X_AXIS:
            return getLineWidth(widestLine);

        case Y_AXIS:
            return metrics.getHeight() * getElement().getElementCount();

        default:
            throw new IllegalArgumentException(Messages.getString("swing.00", axis)); //$NON-NLS-1$
        }
    }

    public void insertUpdate(final DocumentEvent event, final Shape shape,
                             final ViewFactory factory) {
        updateDamage(event, shape, factory);
    }

    public void removeUpdate(final DocumentEvent event, final Shape shape,
                             final ViewFactory factory) {
        updateDamage(event, shape, factory);
    }

    public void changedUpdate(final DocumentEvent event, final Shape shape,
                              final ViewFactory factory) {
        updateDamage(event, shape, factory);
    }

    /**
     * Returns the rectangle where the caret will be painted. This rectangle
     * is positioned between characters (at position <code>pos</code>).
     * Its width is 1, and height is the height of the line (of the font used).
     * <p>For more information about position see
     * http://java.sun.com/products/jfc/tsc/articles/text/element_buffer/
     * in the heading <strong>The Position Interface</strong>.)
     */
    public Shape modelToView(final int pos, final Shape shape,
                             final Position.Bias bias)
        throws BadLocationException {

        if (pos < 0 || pos > getDocument().getLength() + 1) {
            throw new BadLocationException(Messages.getString("swing.98"), pos); //$NON-NLS-1$
        }

        final int lineNo = getElement().getElementIndex(pos);
        final Element line = getElement().getElement(lineNo);

        getDocument().getText(line.getStartOffset(),
                              pos - line.getStartOffset(), getLineBuffer());
        final Rectangle bounds = shape.getBounds();
        return new Rectangle(
                TextUtils.getTabbedTextWidth(getLineBuffer(), metrics,
                                             bounds.x, this, pos) + bounds.x,
                bounds.y + metrics.getHeight() * lineNo,
                1, metrics.getHeight());
    }

    public int viewToModel(final float x, final float y,
                           final Shape shape,
                           final Position.Bias[] biasReturn) {
        biasReturn[0] = Position.Bias.Forward;

        final Rectangle bounds = shape.getBounds();

        if (y >= getPreferredSpan(Y_AXIS) + bounds.y) {
            return getDocument().getLength();
        }
        if (y < bounds.y) {
            return 0;
        }

        final int lineNo = (int)(y - bounds.y) / metrics.getHeight();

        final Element line  = getElement().getElement(lineNo);
        final int     start = line.getStartOffset();
        final int     end   = line.getEndOffset() - 1;
        try {
            getDocument().getText(start, end - start, getLineBuffer());
        } catch (final BadLocationException e) { }

        return start + TextUtils.getTabbedTextOffset(getLineBuffer(), metrics,
                                                     bounds.x,
                                                     (int)Math.max(x, bounds.x),
                                                     this, start);
    }

    public float nextTabStop(final float x, final int tabOffset) {
        conditionalUpdateMetrics();
        return paintParams.nextTabStop(x);
    }

    public void paint(final Graphics g, final Shape shape) {
        final Rectangle bounds = shape.getBounds();
        int y = bounds.y + metrics.getAscent();

        paintParams.updateFields();

        final Rectangle clipBounds = g.getClipBounds();
        final int height = metrics.getHeight();

        final TextKit textKit = getTextKit();
        for (int i = 0; i < getElement().getElementCount(); i++, y += height) {
            if (!lineToRect(shape, i).intersects(clipBounds)) {
                continue;
            }

            if (textKit != null) {
                Element line = getElement().getElement(i);
                textKit.paintLayeredHighlights(g, line.getStartOffset(),
                                               line.getEndOffset() - 1,
                                               shape, this);
            }
            drawLine(i, g, bounds.x, y);
        }
    }

    public void setSize(final float width, final float height) {
        conditionalUpdateMetrics();
    }

    protected void drawLine(final int lineNo, final Graphics g,
                            final int x, final int y) {
        final Element line = getElement().getElement(lineNo);
        drawLine(paintParams,
                 line.getStartOffset(), line.getEndOffset() - 1,
                 g, x, y);
    }

    protected int drawSelectedText(final Graphics g,
                                   final int x, final int y,
                                   final int start, final int end)
        throws BadLocationException {

        return drawText(g, paintParams.selColor, paintParams,
                        x, y, start, end);
    }

    protected int drawUnselectedText(final Graphics g,
                                     final int x, final int y,
                                     final int start, final int end)
        throws BadLocationException {

        return drawText(g, paintParams.color, paintParams,
                        x, y, start, end);
    }

    protected final Segment getLineBuffer() {
        return paintParams.buffer;
    }

    protected int getTabSize() {
        return paintParams.getTabSize();
    }

    protected Rectangle lineToRect(final Shape shape, final int lineNo) {
        conditionalUpdateMetrics();

        int height = metrics.getHeight();
        Rectangle bounds = shape.getBounds();
        return new Rectangle(bounds.x, bounds.y + height * lineNo,
                             bounds.width, height);
    }

    protected void damageLineRange(final int startLine,
                                   final int endLine,
                                   final Shape shape,
                                   final Component component) {
        Rectangle lineRect;
        for (int i = startLine; i <= endLine; i++) {
            lineRect = lineToRect(shape, i);
            component.repaint(lineRect.x, lineRect.y,
                              lineRect.width, lineRect.height);
        }
    }

    protected void updateDamage(final DocumentEvent event, final Shape shape,
                                final ViewFactory factory) {
        if (shape == null) {
            return;
        }

        if (metrics == null) {
            updateMetrics();
            preferenceChanged(null, true, true);
            return;
        }

        final ElementChange change = event.getChange(getElement());

        if (event.getType() == EventType.INSERT) {
            updateDamageOnInsert(event, change, shape);
        } else {
            updateDamageOnRemove(event, change, shape);
        }
    }

    protected void updateMetrics() {
        paintParams.updateMetrics();
        metrics = paintParams.metrics;

        updateWidestLine();
    }

    final void conditionalUpdateMetrics() {
        if (paintParams.areMetricsValid()) {
            updateMetrics();
        }
    }

    private void updateWidestLine() {
        widestLine = getElement().getElement(0);
        widestLineWidth = getLineWidth(widestLine);

        updateWidestLine(1, getElement().getElementCount() - 1);
    }

    private void updateWidestLine(final int start, final int end) {
        for (int i = start; i <= end; i++) {
            int w = getLineWidth(i);
            if (w > widestLineWidth) {
                widestLineWidth = w;
                widestLine = getElement().getElement(i);
            }
        }
    }

    private int getLineWidth(final Element line) {
        try {
            getDocument().getText(line.getStartOffset(),
                                  line.getEndOffset()
                                  - line.getStartOffset() - 1,
                                  getLineBuffer());
        } catch (final BadLocationException e) { }

        return TextUtils.getTabbedTextWidth(getLineBuffer(), metrics, 0,
                                            this, line.getStartOffset());
    }

    private int getLineWidth(final int lineNo) {
        return getLineWidth(getElement().getElement(lineNo));
    }

    private void updateDamageOnInsert(final DocumentEvent event,
                                      final ElementChange change,
                                      final Shape shape) {
        boolean linesAdded = change != null;
        int start = linesAdded
                    ? change.getIndex()
                    : getElement().getElementIndex(event.getOffset());
        int length = linesAdded ? change.getChildrenAdded().length - 1 : 0;
        int width = widestLineWidth;
        if (widestLine.getEndOffset() < event.getOffset()
            || widestLine.getStartOffset() > event.getOffset()
                                             + event.getLength()) {
            // The previous longest line was not affected
            updateWidestLine(start, start + length);
        } else {
            updateWidestLine();
        }
        preferenceChanged(null, widestLineWidth != width, linesAdded);
        damageLineRange(start,
                        linesAdded ? getElement().getElementCount() - 1 : start,
                        shape, getComponent());
    }

    private void updateDamageOnRemove(final DocumentEvent event,
                                      final ElementChange change,
                                      final Shape shape) {
        int width = widestLineWidth;
        if (change != null) {
            updateWidestLine();
            preferenceChanged(null, widestLineWidth != width, true);
            getComponent().repaint();
        } else {
            int lineNo = getElement().getElementIndex(event.getOffset());
            Element line = getElement().getElement(lineNo);
            if (widestLine == line) {
                updateWidestLine();
                preferenceChanged(null, widestLineWidth != width, false);
            }
            damageLineRange(lineNo, lineNo, shape, getComponent());
        }
    }

}
TOP

Related Classes of javax.swing.text.PlainView

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.