1871 lines · 69.6 KB · Java
RawDownload
/* * Copyright (c) 2002, 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 sun.swing; import java.security.*;import java.lang.reflect.*;import java.awt.*;import static java.awt.RenderingHints.*;import java.awt.event.*;import java.awt.font.*;import java.awt.geom.*;import java.awt.print.PrinterGraphics;import java.text.Bidi;import java.text.AttributedCharacterIterator;import java.text.AttributedString; import javax.swing.*;import javax.swing.plaf.*;import javax.swing.text.Highlighter;import javax.swing.text.JTextComponent;import javax.swing.text.DefaultHighlighter;import javax.swing.text.DefaultCaret;import javax.swing.table.TableCellRenderer;import javax.swing.table.TableColumnModel; import sun.swing.PrintColorUIResource;import sun.swing.ImageIconUIResource;import sun.print.ProxyPrintGraphics;import sun.awt.*;import sun.security.action.GetPropertyAction;import sun.security.util.SecurityConstants;import java.io.*;import java.util.*;import sun.font.FontDesignMetrics;import sun.font.FontUtilities;import sun.java2d.SunGraphicsEnvironment; import java.util.concurrent.Callable;import java.util.concurrent.Future;import java.util.concurrent.FutureTask; /** * A collection of utility methods for Swing. * <p> * <b>WARNING:</b> While this class is public, it should not be treated as * public API and its API may change in incompatable ways between dot dot * releases and even patch releases. You should not rely on this class even * existing. * */public class SwingUtilities2 {    /**     * The <code>AppContext</code> key for our one <code>LAFState</code>     * instance.     */    public static final Object LAF_STATE_KEY =            new StringBuffer("LookAndFeel State");     // Maintain a cache of CACHE_SIZE fonts and the left side bearing     // of the characters falling into the range MIN_CHAR_INDEX to     // MAX_CHAR_INDEX. The values in fontCache are created as needed.     private static LSBCacheEntry[] fontCache;     // Windows defines 6 font desktop properties, we will therefore only     // cache the metrics for 6 fonts.     private static final int CACHE_SIZE = 6;     // nextIndex in fontCache to insert a font into.     private static int nextIndex;     // LSBCacheEntry used to search in fontCache to see if we already     // have an entry for a particular font     private static LSBCacheEntry searchKey;      // getLeftSideBearing will consult all characters that fall in the     // range MIN_CHAR_INDEX to MAX_CHAR_INDEX.     private static final int MIN_CHAR_INDEX = (int)'W';     private static final int MAX_CHAR_INDEX = (int)'W' + 1;     public static final FontRenderContext DEFAULT_FRC =        new FontRenderContext(null, false, false);     /**     * A JComponent client property is used to determine text aa settings.     * To avoid having this property persist between look and feels changes     * the value of the property is set to null in JComponent.setUI     */    public static final Object AA_TEXT_PROPERTY_KEY =                          new StringBuffer("AATextInfoPropertyKey");     /**     * Attribute key for the content elements.  If it is set on an element, the     * element is considered to be a line break.     */    public static final String IMPLIED_CR = "CR";     /**     * Used to tell a text component, being used as an editor for table     * or tree, how many clicks it took to start editing.     */    private static final StringBuilder SKIP_CLICK_COUNT =        new StringBuilder("skipClickCount");     /* Presently this class assumes default fractional metrics.     * This may need to change to emulate future platform L&Fs.     */    public static class AATextInfo {         private static AATextInfo getAATextInfoFromMap(Map hints) {             Object aaHint   = hints.get(KEY_TEXT_ANTIALIASING);            Object contHint = hints.get(KEY_TEXT_LCD_CONTRAST);             if (aaHint == null ||                aaHint == VALUE_TEXT_ANTIALIAS_OFF ||                aaHint == VALUE_TEXT_ANTIALIAS_DEFAULT) {                return null;            } else {                return new AATextInfo(aaHint, (Integer)contHint);            }        }         public static AATextInfo getAATextInfo(boolean lafCondition) {            SunToolkit.setAAFontSettingsCondition(lafCondition);            Toolkit tk = Toolkit.getDefaultToolkit();            Object map = tk.getDesktopProperty(SunToolkit.DESKTOPFONTHINTS);            if (map instanceof Map) {                return getAATextInfoFromMap((Map)map);            } else {                return null;            }        }         Object aaHint;        Integer lcdContrastHint;        FontRenderContext frc;         /* These are rarely constructed objects, and only when a complete         * UI is being updated, so the cost of the tests here is minimal         * and saves tests elsewhere.         * We test that the values are ones we support/expect.         */        public AATextInfo(Object aaHint, Integer lcdContrastHint) {            if (aaHint == null) {                throw new InternalError("null not allowed here");            }            if (aaHint == VALUE_TEXT_ANTIALIAS_OFF ||                aaHint == VALUE_TEXT_ANTIALIAS_DEFAULT) {                throw new InternalError("AA must be on");            }            this.aaHint = aaHint;            this.lcdContrastHint = lcdContrastHint;            this.frc = new FontRenderContext(null, aaHint,                                             VALUE_FRACTIONALMETRICS_DEFAULT);        }    }     /**     * Key used in client properties used to indicate that the     * <code>ComponentUI</code> of the JComponent instance should be returned.     */    public static final Object COMPONENT_UI_PROPERTY_KEY =                            new StringBuffer("ComponentUIPropertyKey");     /** Client Property key for the text maximal offsets for BasicMenuItemUI */    public static final StringUIClientPropertyKey BASICMENUITEMUI_MAX_TEXT_OFFSET =        new StringUIClientPropertyKey ("maxTextOffset");     // security stuff    private static Field inputEvent_CanAccessSystemClipboard_Field = null;    private static final String UntrustedClipboardAccess =        "UNTRUSTED_CLIPBOARD_ACCESS_KEY";     //all access to  charsBuffer is to be synchronized on charsBufferLock    private static final int CHAR_BUFFER_SIZE = 100;    private static final Object charsBufferLock = new Object();    private static char[] charsBuffer = new char[CHAR_BUFFER_SIZE];     static {        fontCache = new LSBCacheEntry[CACHE_SIZE];    }     /**     * Fill the character buffer cache.  Return the buffer length.     */    private static int syncCharsBuffer(String s) {        int length = s.length();        if ((charsBuffer == null) || (charsBuffer.length < length)) {            charsBuffer = s.toCharArray();        } else {            s.getChars(0, length, charsBuffer, 0);        }        return length;    }     /**     * checks whether TextLayout is required to handle characters.     *     * @param text characters to be tested     * @param start start     * @param limit limit     * @return <tt>true</tt>  if TextLayout is required     *         <tt>false</tt> if TextLayout is not required     */    public static final boolean isComplexLayout(char[] text, int start, int limit) {        return FontUtilities.isComplexText(text, start, limit);    }     //    // WARNING WARNING WARNING WARNING WARNING WARNING    // Many of the following methods are invoked from older API.    // As this older API was not passed a Component, a null Component may    // now be passsed in.  For example, SwingUtilities.computeStringWidth    // is implemented to call SwingUtilities2.stringWidth, the    // SwingUtilities variant does not take a JComponent, as such    // SwingUtilities2.stringWidth can be passed a null Component.    // In other words, if you add new functionality to these methods you    // need to gracefully handle null.    //     /**     * Returns whether or not text should be drawn antialiased.     *     * @param c JComponent to test.     * @return Whether or not text should be drawn antialiased for the     *         specified component.     */    public static AATextInfo drawTextAntialiased(JComponent c) {        if (c != null) {            /* a non-null property implies some form of AA requested */            return (AATextInfo)c.getClientProperty(AA_TEXT_PROPERTY_KEY);        }        // No component, assume aa is off        return null;    }     /**     * Returns the left side bearing of the first character of string. The     * left side bearing is calculated from the passed in     * FontMetrics.  If the passed in String is less than one     * character {@code 0} is returned.     *     * @param c JComponent that will display the string     * @param fm FontMetrics used to measure the String width     * @param string String to get the left side bearing for.     * @throws NullPointerException if {@code string} is {@code null}     *     * @return the left side bearing of the first character of string     * or {@code 0} if the string is empty     */    public static int getLeftSideBearing(JComponent c, FontMetrics fm,                                         String string) {        if ((string == null) || (string.length() == 0)) {            return 0;        }        return getLeftSideBearing(c, fm, string.charAt(0));    }     /**     * Returns the left side bearing of the first character of string. The     * left side bearing is calculated from the passed in FontMetrics.     *     * @param c JComponent that will display the string     * @param fm FontMetrics used to measure the String width     * @param firstChar Character to get the left side bearing for.     */    public static int getLeftSideBearing(JComponent c, FontMetrics fm,                                         char firstChar) {        int charIndex = (int) firstChar;        if (charIndex < MAX_CHAR_INDEX && charIndex >= MIN_CHAR_INDEX) {            byte[] lsbs = null;             FontRenderContext frc = getFontRenderContext(c, fm);            Font font = fm.getFont();            synchronized (SwingUtilities2.class) {                LSBCacheEntry entry = null;                if (searchKey == null) {                    searchKey = new LSBCacheEntry(frc, font);                } else {                    searchKey.reset(frc, font);                }                // See if we already have an entry for this pair                for (LSBCacheEntry cacheEntry : fontCache) {                    if (searchKey.equals(cacheEntry)) {                        entry = cacheEntry;                        break;                    }                }                if (entry == null) {                    // No entry for this pair, add it.                    entry = searchKey;                    fontCache[nextIndex] = searchKey;                    searchKey = null;                    nextIndex = (nextIndex + 1) % CACHE_SIZE;                }                return entry.getLeftSideBearing(firstChar);            }        }        return 0;    }     /**     * Returns the FontMetrics for the current Font of the passed     * in Graphics.  This method is used when a Graphics     * is available, typically when painting.  If a Graphics is not     * available the JComponent method of the same name should be used.     * <p>     * Callers should pass in a non-null JComponent, the exception     * to this is if a JComponent is not readily available at the time of     * painting.     * <p>     * This does not necessarily return the FontMetrics from the     * Graphics.     *     * @param c JComponent requesting FontMetrics, may be null     * @param g Graphics Graphics     */    public static FontMetrics getFontMetrics(JComponent c, Graphics g) {        return getFontMetrics(c, g, g.getFont());    }      /**     * Returns the FontMetrics for the specified Font.     * This method is used when a Graphics is available, typically when     * painting.  If a Graphics is not available the JComponent method of     * the same name should be used.     * <p>     * Callers should pass in a non-null JComonent, the exception     * to this is if a JComponent is not readily available at the time of     * painting.     * <p>     * This does not necessarily return the FontMetrics from the     * Graphics.     *     * @param c JComponent requesting FontMetrics, may be null     * @param c Graphics Graphics     * @param font Font to get FontMetrics for     */    public static FontMetrics getFontMetrics(JComponent c, Graphics g,                                             Font font) {        if (c != null) {            // Note: We assume that we're using the FontMetrics            // from the widget to layout out text, otherwise we can get            // mismatches when printing.            return c.getFontMetrics(font);        }        return Toolkit.getDefaultToolkit().getFontMetrics(font);    }      /**     * Returns the width of the passed in String.     * If the passed String is <code>null</code>, returns zero.     *     * @param c JComponent that will display the string, may be null     * @param fm FontMetrics used to measure the String width     * @param string String to get the width of     */    public static int stringWidth(JComponent c, FontMetrics fm, String string){        if (string == null || string.equals("")) {            return 0;        }        boolean needsTextLayout = ((c != null) &&                (c.getClientProperty(TextAttribute.NUMERIC_SHAPING) != null));        if (needsTextLayout) {            synchronized(charsBufferLock) {                int length = syncCharsBuffer(string);                needsTextLayout = isComplexLayout(charsBuffer, 0, length);            }        }        if (needsTextLayout) {            TextLayout layout = createTextLayout(c, string,                                    fm.getFont(), fm.getFontRenderContext());            return (int) layout.getAdvance();        } else {            return fm.stringWidth(string);        }    }      /**     * Clips the passed in String to the space provided.     *     * @param c JComponent that will display the string, may be null     * @param fm FontMetrics used to measure the String width     * @param string String to display     * @param availTextWidth Amount of space that the string can be drawn in     * @return Clipped string that can fit in the provided space.     */    public static String clipStringIfNecessary(JComponent c, FontMetrics fm,                                               String string,                                               int availTextWidth) {        if ((string == null) || (string.equals("")))  {            return "";        }        int textWidth = SwingUtilities2.stringWidth(c, fm, string);        if (textWidth > availTextWidth) {            return SwingUtilities2.clipString(c, fm, string, availTextWidth);        }        return string;    }      /**     * Clips the passed in String to the space provided.  NOTE: this assumes     * the string does not fit in the available space.     *     * @param c JComponent that will display the string, may be null     * @param fm FontMetrics used to measure the String width     * @param string String to display     * @param availTextWidth Amount of space that the string can be drawn in     * @return Clipped string that can fit in the provided space.     */    public static String clipString(JComponent c, FontMetrics fm,                                    String string, int availTextWidth) {        // c may be null here.        String clipString = "...";        availTextWidth -= SwingUtilities2.stringWidth(c, fm, clipString);        if (availTextWidth <= 0) {            //can not fit any characters            return clipString;        }         boolean needsTextLayout;        synchronized (charsBufferLock) {            int stringLength = syncCharsBuffer(string);            needsTextLayout =                isComplexLayout(charsBuffer, 0, stringLength);            if (!needsTextLayout) {                int width = 0;                for (int nChars = 0; nChars < stringLength; nChars++) {                    width += fm.charWidth(charsBuffer[nChars]);                    if (width > availTextWidth) {                        string = string.substring(0, nChars);                        break;                    }                }            }        }        if (needsTextLayout) {            FontRenderContext frc = getFontRenderContext(c, fm);            AttributedString aString = new AttributedString(string);            if (c != null) {                aString.addAttribute(TextAttribute.NUMERIC_SHAPING,                        c.getClientProperty(TextAttribute.NUMERIC_SHAPING));            }            LineBreakMeasurer measurer =                new LineBreakMeasurer(aString.getIterator(), frc);            int nChars = measurer.nextOffset(availTextWidth);            string = string.substring(0, nChars);         }        return string + clipString;    }      /**     * Draws the string at the specified location.     *     * @param c JComponent that will display the string, may be null     * @param g Graphics to draw the text to     * @param text String to display     * @param x X coordinate to draw the text at     * @param y Y coordinate to draw the text at     */    public static void drawString(JComponent c, Graphics g, String text,                                  int x, int y) {        // c may be null         // All non-editable widgets that draw strings call into this        // methods.  By non-editable that means widgets like JLabel, JButton        // but NOT JTextComponents.        if ( text == null || text.length() <= 0 ) { //no need to paint empty strings            return;        }        if (isPrinting(g)) {            Graphics2D g2d = getGraphics2D(g);            if (g2d != null) {                /* The printed text must scale linearly with the UI.

Lines 1–500 of 1871.