394 lines · 13.4 KB · Java
RawDownload
/* * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package javax.swing.plaf.basic; import java.beans.*;import java.awt.*;import java.awt.event.KeyEvent;import java.awt.event.InputEvent;import javax.swing.*;import javax.swing.event.DocumentEvent;import javax.swing.text.*;import javax.swing.plaf.*; /** * Provides the look and feel for a plain text editor.  In this * implementation the default UI is extended to act as a simple * view factory. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing.  As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @author  Timothy Prinzing */public class BasicTextAreaUI extends BasicTextUI {     /**     * Creates a UI for a JTextArea.     *     * @param ta a text area     * @return the UI     */    public static ComponentUI createUI(JComponent ta) {        return new BasicTextAreaUI();    }     /**     * Constructs a new BasicTextAreaUI object.     */    public BasicTextAreaUI() {        super();    }     /**     * Fetches the name used as a key to look up properties through the     * UIManager.  This is used as a prefix to all the standard     * text properties.     *     * @return the name ("TextArea")     */    protected String getPropertyPrefix() {        return "TextArea";    }     protected void installDefaults() {        super.installDefaults();        //the fix for 4785160 is undone    }     /**     * This method gets called when a bound property is changed     * on the associated JTextComponent.  This is a hook     * which UI implementations may change to reflect how the     * UI displays bound properties of JTextComponent subclasses.     * This is implemented to rebuild the View when the     * <em>WrapLine</em> or the <em>WrapStyleWord</em> property changes.     *     * @param evt the property change event     */    protected void propertyChange(PropertyChangeEvent evt) {        super.propertyChange(evt);        if (evt.getPropertyName().equals("lineWrap") ||            evt.getPropertyName().equals("wrapStyleWord") ||                evt.getPropertyName().equals("tabSize")) {            // rebuild the view            modelChanged();        } else if ("editable".equals(evt.getPropertyName())) {            updateFocusTraversalKeys();        }    }      /**     * The method is overridden to take into account caret width.     *     * @param c the editor component     * @return the preferred size     * @throws IllegalArgumentException if invalid value is passed     *     * @since 1.5     */    public Dimension getPreferredSize(JComponent c) {        return super.getPreferredSize(c);        //the fix for 4785160 is undone    }     /**     * The method is overridden to take into account caret width.     *     * @param c the editor component     * @return the minimum size     * @throws IllegalArgumentException if invalid value is passed     *     * @since 1.5     */    public Dimension getMinimumSize(JComponent c) {        return super.getMinimumSize(c);        //the fix for 4785160 is undone    }     /**     * Creates the view for an element.  Returns a WrappedPlainView or     * PlainView.     *     * @param elem the element     * @return the view     */    public View create(Element elem) {        Document doc = elem.getDocument();        Object i18nFlag = doc.getProperty("i18n"/*AbstractDocument.I18NProperty*/);        if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) {            // build a view that support bidi            return createI18N(elem);        } else {            JTextComponent c = getComponent();            if (c instanceof JTextArea) {                JTextArea area = (JTextArea) c;                View v;                if (area.getLineWrap()) {                    v = new WrappedPlainView(elem, area.getWrapStyleWord());                } else {                    v = new PlainView(elem);                }                return v;            }        }        return null;    }     View createI18N(Element elem) {        String kind = elem.getName();        if (kind != null) {            if (kind.equals(AbstractDocument.ContentElementName)) {                return new PlainParagraph(elem);            } else if (kind.equals(AbstractDocument.ParagraphElementName)) {                return new BoxView(elem, View.Y_AXIS);            }        }        return null;    }     /**     * Returns the baseline.     *     * @throws NullPointerException {@inheritDoc}     * @throws IllegalArgumentException {@inheritDoc}     * @see javax.swing.JComponent#getBaseline(int, int)     * @since 1.6     */    public int getBaseline(JComponent c, int width, int height) {        super.getBaseline(c, width, height);        Object i18nFlag = ((JTextComponent)c).getDocument().                                              getProperty("i18n");        Insets insets = c.getInsets();        if (Boolean.TRUE.equals(i18nFlag)) {            View rootView = getRootView((JTextComponent)c);            if (rootView.getViewCount() > 0) {                height = height - insets.top - insets.bottom;                int baseline = insets.top;                int fieldBaseline = BasicHTML.getBaseline(                        rootView.getView(0), width - insets.left -                        insets.right, height);                if (fieldBaseline < 0) {                    return -1;                }                return baseline + fieldBaseline;            }            return -1;        }        FontMetrics fm = c.getFontMetrics(c.getFont());        return insets.top + fm.getAscent();    }     /**     * Returns an enum indicating how the baseline of the component     * changes as the size changes.     *     * @throws NullPointerException {@inheritDoc}     * @see javax.swing.JComponent#getBaseline(int, int)     * @since 1.6     */    public Component.BaselineResizeBehavior getBaselineResizeBehavior(            JComponent c) {        super.getBaselineResizeBehavior(c);        return Component.BaselineResizeBehavior.CONSTANT_ASCENT;    }      /**     * Paragraph for representing plain-text lines that support     * bidirectional text.     */    static class PlainParagraph extends ParagraphView {         PlainParagraph(Element elem) {            super(elem);            layoutPool = new LogicalView(elem);            layoutPool.setParent(this);        }         public void setParent(View parent) {            super.setParent(parent);            if (parent != null) {                setPropertiesFromAttributes();            }        }         protected void setPropertiesFromAttributes() {            Component c = getContainer();            if ((c != null) && (! c.getComponentOrientation().isLeftToRight())) {                setJustification(StyleConstants.ALIGN_RIGHT);            } else {                setJustification(StyleConstants.ALIGN_LEFT);            }        }         /**         * Fetch the constraining span to flow against for         * the given child index.         */        public int getFlowSpan(int index) {            Component c = getContainer();            if (c instanceof JTextArea) {                JTextArea area = (JTextArea) c;                if (! area.getLineWrap()) {                    // no limit if unwrapped                    return Integer.MAX_VALUE;                }            }            return super.getFlowSpan(index);        }         protected SizeRequirements calculateMinorAxisRequirements(int axis,                                                                  SizeRequirements r) {            SizeRequirements req = super.calculateMinorAxisRequirements(axis, r);            Component c = getContainer();            if (c instanceof JTextArea) {                JTextArea area = (JTextArea) c;                if (! area.getLineWrap()) {                    // min is pref if unwrapped                    req.minimum = req.preferred;                } else {                    req.minimum = 0;                    req.preferred = getWidth();                    if (req.preferred == Integer.MAX_VALUE) {                        // We have been initially set to MAX_VALUE, but we                        // don't want this as our preferred.                        req.preferred = 100;                    }                }            }            return req;        }         /**         * Sets the size of the view.  If the size has changed, layout         * is redone.  The size is the full size of the view including         * the inset areas.         *         * @param width the width >= 0         * @param height the height >= 0         */        public void setSize(float width, float height) {            if ((int) width != getWidth()) {                preferenceChanged(null, true, true);            }            super.setSize(width, height);        }         /**         * This class can be used to represent a logical view for         * a flow.  It keeps the children updated to reflect the state         * of the model, gives the logical child views access to the         * view hierarchy, and calculates a preferred span.  It doesn't         * do any rendering, layout, or model/view translation.         */        static class LogicalView extends CompositeView {             LogicalView(Element elem) {                super(elem);            }             protected int getViewIndexAtPosition(int pos) {                Element elem = getElement();                if (elem.getElementCount() > 0) {                    return elem.getElementIndex(pos);                }                return 0;            }             protected boolean updateChildren(DocumentEvent.ElementChange ec,                                             DocumentEvent e, ViewFactory f) {                return false;            }             protected void loadChildren(ViewFactory f) {                Element elem = getElement();                if (elem.getElementCount() > 0) {                    super.loadChildren(f);                } else {                    View v = new GlyphView(elem);                    append(v);                }            }             public float getPreferredSpan(int axis) {                if( getViewCount() != 1 )                    throw new Error("One child view is assumed.");                 View v = getView(0);                return v.getPreferredSpan(axis);            }             /**             * Forward the DocumentEvent to the given child view.  This             * is implemented to reparent the child to the logical view             * (the children may have been parented by a row in the flow             * if they fit without breaking) and then execute the superclass             * behavior.             *             * @param v the child view to forward the event to.             * @param e the change information from the associated document             * @param a the current allocation of the view             * @param f the factory to use to rebuild if the view has children             * @see #forwardUpdate             * @since 1.3             */            protected void forwardUpdateToView(View v, DocumentEvent e,                                               Shape a, ViewFactory f) {                v.setParent(this);                super.forwardUpdateToView(v, e, a, f);            }             // The following methods don't do anything useful, they            // simply keep the class from being abstract.             public void paint(Graphics g, Shape allocation) {            }             protected boolean isBefore(int x, int y, Rectangle alloc) {                return false;            }             protected boolean isAfter(int x, int y, Rectangle alloc) {                return false;            }             protected View getViewAtPoint(int x, int y, Rectangle alloc) {                return null;            }             protected void childAllocation(int index, Rectangle a) {            }        }    } }