2647 lines · 96.6 KB · Java
RawDownload
/* * Copyright (c) 1997, 2010, 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.util.*;import java.awt.*;import java.awt.event.*;import java.awt.datatransfer.*;import java.awt.im.InputContext;import java.beans.*;import java.io.*;import javax.swing.*;import javax.swing.plaf.*;import javax.swing.text.*;import javax.swing.event.*;import javax.swing.border.Border;import javax.swing.plaf.UIResource;import javax.swing.plaf.synth.SynthUI;import sun.swing.DefaultLookup;import sun.awt.AppContext;import javax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag; /** * <p> * Basis of a text components look-and-feel.  This provides the * basic editor view and controller services that may be useful * when creating a look-and-feel for an extension of * <code>JTextComponent</code>. * <p> * Most state is held in the associated <code>JTextComponent</code> * as bound properties, and the UI installs default values for the * various properties.  This default will install something for * all of the properties.  Typically, a LAF implementation will * do more however.  At a minimum, a LAF would generally install * key bindings. * <p> * This class also provides some concurrency support if the * <code>Document</code> associated with the JTextComponent is a subclass of * <code>AbstractDocument</code>.  Access to the View (or View hierarchy) is * serialized between any thread mutating the model and the Swing * event thread (which is expected to render, do model/view coordinate * translation, etc).  <em>Any access to the root view should first * acquire a read-lock on the AbstractDocument and release that lock * in a finally block.</em> * <p> * An important method to define is the {@link #getPropertyPrefix} method * which is used as the basis of the keys used to fetch defaults * from the UIManager.  The string should reflect the type of * TextUI (eg. TextField, TextArea, etc) without the particular * LAF part of the name (eg Metal, Motif, etc). * <p> * To build a view of the model, one of the following strategies * can be employed. * <ol> * <li> * One strategy is to simply redefine the * ViewFactory interface in the UI.  By default, this UI itself acts * as the factory for View implementations.  This is useful * for simple factories.  To do this reimplement the * {@link #create} method. * <li> * A common strategy for creating more complex types of documents * is to have the EditorKit implementation return a factory.  Since * the EditorKit ties all of the pieces necessary to maintain a type * of document, the factory is typically an important part of that * and should be produced by the EditorKit implementation. * </ol> * <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 * @author Shannon Hickey (drag and drop) */public abstract class BasicTextUI extends TextUI implements ViewFactory {     /**     * Creates a new UI.     */    public BasicTextUI() {        painted = false;    }     /**     * Creates the object to use for a caret.  By default an     * instance of BasicCaret is created.  This method     * can be redefined to provide something else that implements     * the InputPosition interface or a subclass of JCaret.     *     * @return the caret object     */    protected Caret createCaret() {        return new BasicCaret();    }     /**     * Creates the object to use for adding highlights.  By default     * an instance of BasicHighlighter is created.  This method     * can be redefined to provide something else that implements     * the Highlighter interface or a subclass of DefaultHighlighter.     *     * @return the highlighter     */    protected Highlighter createHighlighter() {        return new BasicHighlighter();    }     /**     * Fetches the name of the keymap that will be installed/used     * by default for this UI. This is implemented to create a     * name based upon the classname.  The name is the the name     * of the class with the package prefix removed.     *     * @return the name     */    protected String getKeymapName() {        String nm = getClass().getName();        int index = nm.lastIndexOf('.');        if (index >= 0) {            nm = nm.substring(index+1, nm.length());        }        return nm;    }     /**     * Creates the keymap to use for the text component, and installs     * any necessary bindings into it.  By default, the keymap is     * shared between all instances of this type of TextUI. The     * keymap has the name defined by the getKeymapName method.  If the     * keymap is not found, then DEFAULT_KEYMAP from JTextComponent is used.     * <p>     * The set of bindings used to create the keymap is fetched     * from the UIManager using a key formed by combining the     * {@link #getPropertyPrefix} method     * and the string <code>.keyBindings</code>.  The type is expected     * to be <code>JTextComponent.KeyBinding[]</code>.     *     * @return the keymap     * @see #getKeymapName     * @see javax.swing.text.JTextComponent     */    protected Keymap createKeymap() {        String nm = getKeymapName();        Keymap map = JTextComponent.getKeymap(nm);        if (map == null) {            Keymap parent = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);            map = JTextComponent.addKeymap(nm, parent);            String prefix = getPropertyPrefix();            Object o = DefaultLookup.get(editor, this,                prefix + ".keyBindings");            if ((o != null) && (o instanceof JTextComponent.KeyBinding[])) {                JTextComponent.KeyBinding[] bindings = (JTextComponent.KeyBinding[]) o;                JTextComponent.loadKeymap(map, bindings, getComponent().getActions());            }        }        return map;    }     /**     * 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 do nothing (i.e. the response to     * properties in JTextComponent itself are handled prior     * to calling this method).     *     * This implementation updates the background of the text     * component if the editable and/or enabled state changes.     *     * @param evt the property change event     */    protected void propertyChange(PropertyChangeEvent evt) {        if (evt.getPropertyName().equals("editable") ||                evt.getPropertyName().equals("enabled")) {             updateBackground((JTextComponent)evt.getSource());        }    }     /**     * Updates the background of the text component based on whether the     * text component is editable and/or enabled.     *     * @param c the JTextComponent that needs its background color updated     */    private void updateBackground(JTextComponent c) {        // This is a temporary workaround.        // This code does not correctly deal with Synth (Synth doesn't use        // properties like this), nor does it deal with the situation where        // the developer grabs the color from a JLabel and sets it as        // the background for a JTextArea in all look and feels. The problem        // scenario results if the Color obtained for the Label and TextArea        // is ==, which is the case for the windows look and feel.        // Until an appropriate solution is found, the code is being        // reverted to what it was before the original fix.        if (this instanceof SynthUI || (c instanceof JTextArea)) {            return;        }        Color background = c.getBackground();        if (background instanceof UIResource) {            String prefix = getPropertyPrefix();             Color disabledBG =                DefaultLookup.getColor(c, this, prefix + ".disabledBackground", null);            Color inactiveBG =                DefaultLookup.getColor(c, this, prefix + ".inactiveBackground", null);            Color bg =                DefaultLookup.getColor(c, this, prefix + ".background", null);             /* In an ideal situation, the following check would not be necessary             * and we would replace the color any time the previous color was a             * UIResouce. However, it turns out that there is existing code that             * uses the following inadvisable pattern to turn a text area into             * what appears to be a multi-line label:             *             * JLabel label = new JLabel();             * JTextArea area = new JTextArea();             * area.setBackground(label.getBackground());             * area.setEditable(false);             *             * JLabel's default background is a UIResource. As such, just             * checking for UIResource would have us always changing the             * background away from what the developer wanted.             *             * Therefore, for JTextArea/JEditorPane, we'll additionally check             * that the color we're about to replace matches one that was             * installed by us from the UIDefaults.             */            if ((c instanceof JTextArea || c instanceof JEditorPane)                    && background != disabledBG                    && background != inactiveBG                    && background != bg) {                 return;            }             Color newColor = null;            if (!c.isEnabled()) {                newColor = disabledBG;            }            if (newColor == null && !c.isEditable()) {                newColor = inactiveBG;            }            if (newColor == null) {                newColor = bg;            }            if (newColor != null && newColor != background) {                c.setBackground(newColor);            }        }    }     /**     * Gets 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     */    protected abstract String getPropertyPrefix();     /**     * Initializes component properties, such as font, foreground,     * background, caret color, selection color, selected text color,     * disabled text color, and border color.  The font, foreground, and     * background properties are only set if their current value is either null     * or a UIResource, other properties are set if the current     * value is null.     *     * @see #uninstallDefaults     * @see #installUI     */    protected void installDefaults()    {        String prefix = getPropertyPrefix();        Font f = editor.getFont();        if ((f == null) || (f instanceof UIResource)) {            editor.setFont(UIManager.getFont(prefix + ".font"));        }         Color bg = editor.getBackground();        if ((bg == null) || (bg instanceof UIResource)) {            editor.setBackground(UIManager.getColor(prefix + ".background"));        }         Color fg = editor.getForeground();        if ((fg == null) || (fg instanceof UIResource)) {            editor.setForeground(UIManager.getColor(prefix + ".foreground"));        }         Color color = editor.getCaretColor();        if ((color == null) || (color instanceof UIResource)) {            editor.setCaretColor(UIManager.getColor(prefix + ".caretForeground"));        }         Color s = editor.getSelectionColor();        if ((s == null) || (s instanceof UIResource)) {            editor.setSelectionColor(UIManager.getColor(prefix + ".selectionBackground"));        }         Color sfg = editor.getSelectedTextColor();        if ((sfg == null) || (sfg instanceof UIResource)) {            editor.setSelectedTextColor(UIManager.getColor(prefix + ".selectionForeground"));        }         Color dfg = editor.getDisabledTextColor();        if ((dfg == null) || (dfg instanceof UIResource)) {            editor.setDisabledTextColor(UIManager.getColor(prefix + ".inactiveForeground"));        }         Border b = editor.getBorder();        if ((b == null) || (b instanceof UIResource)) {            editor.setBorder(UIManager.getBorder(prefix + ".border"));        }         Insets margin = editor.getMargin();        if (margin == null || margin instanceof UIResource) {            editor.setMargin(UIManager.getInsets(prefix + ".margin"));        }         updateCursor();    }     private void installDefaults2() {        editor.addMouseListener(dragListener);        editor.addMouseMotionListener(dragListener);         String prefix = getPropertyPrefix();         Caret caret = editor.getCaret();        if (caret == null || caret instanceof UIResource) {            caret = createCaret();            editor.setCaret(caret);             int rate = DefaultLookup.getInt(getComponent(), this, prefix + ".caretBlinkRate", 500);            caret.setBlinkRate(rate);        }         Highlighter highlighter = editor.getHighlighter();        if (highlighter == null || highlighter instanceof UIResource) {            editor.setHighlighter(createHighlighter());        }         TransferHandler th = editor.getTransferHandler();        if (th == null || th instanceof UIResource) {            editor.setTransferHandler(getTransferHandler());        }    }     /**     * Sets the component properties that have not been explicitly overridden     * to {@code null}.  A property is considered overridden if its current     * value is not a {@code UIResource}.     *     * @see #installDefaults     * @see #uninstallUI     */    protected void uninstallDefaults()    {        editor.removeMouseListener(dragListener);        editor.removeMouseMotionListener(dragListener);         if (editor.getCaretColor() instanceof UIResource) {            editor.setCaretColor(null);        }         if (editor.getSelectionColor() instanceof UIResource) {            editor.setSelectionColor(null);        }         if (editor.getDisabledTextColor() instanceof UIResource) {            editor.setDisabledTextColor(null);        }         if (editor.getSelectedTextColor() instanceof UIResource) {            editor.setSelectedTextColor(null);        }         if (editor.getBorder() instanceof UIResource) {            editor.setBorder(null);        }         if (editor.getMargin() instanceof UIResource) {            editor.setMargin(null);        }         if (editor.getCaret() instanceof UIResource) {            editor.setCaret(null);        }         if (editor.getHighlighter() instanceof UIResource) {            editor.setHighlighter(null);        }         if (editor.getTransferHandler() instanceof UIResource) {            editor.setTransferHandler(null);        }         if (editor.getCursor() instanceof UIResource) {            editor.setCursor(null);        }    }     /**     * Installs listeners for the UI.     */    protected void installListeners() {    }     /**     * Uninstalls listeners for the UI.     */    protected void uninstallListeners() {    }     protected void installKeyboardActions() {        // backward compatibility support... keymaps for the UI        // are now installed in the more friendly input map.        editor.setKeymap(createKeymap());         InputMap km = getInputMap();        if (km != null) {            SwingUtilities.replaceUIInputMap(editor, JComponent.WHEN_FOCUSED,                                             km);        }         ActionMap map = getActionMap();        if (map != null) {            SwingUtilities.replaceUIActionMap(editor, map);        }         updateFocusAcceleratorBinding(false);    }     /**     * Get the InputMap to use for the UI.     */    InputMap getInputMap() {        InputMap map = new InputMapUIResource();         InputMap shared =            (InputMap)DefaultLookup.get(editor, this,            getPropertyPrefix() + ".focusInputMap");        if (shared != null) {            map.setParent(shared);        }        return map;    }     /**     * Invoked when the focus accelerator changes, this will update the     * key bindings as necessary.     */    void updateFocusAcceleratorBinding(boolean changed) {        char accelerator = editor.getFocusAccelerator();         if (changed || accelerator != '\0') {            InputMap km = SwingUtilities.getUIInputMap                        (editor, JComponent.WHEN_IN_FOCUSED_WINDOW);             if (km == null && accelerator != '\0') {                km = new ComponentInputMapUIResource(editor);                SwingUtilities.replaceUIInputMap(editor, JComponent.                                                 WHEN_IN_FOCUSED_WINDOW, km);                ActionMap am = getActionMap();                SwingUtilities.replaceUIActionMap(editor, am);            }            if (km != null) {                km.clear();                if (accelerator != '\0') {                    km.put(KeyStroke.getKeyStroke(accelerator,

Lines 1–500 of 2647.