0N/A/*
3261N/A * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.swing;
0N/A
0N/Aimport java.security.*;
0N/Aimport java.lang.reflect.*;
0N/Aimport java.awt.*;
0N/Aimport static java.awt.RenderingHints.*;
0N/Aimport java.awt.event.*;
0N/Aimport java.awt.font.*;
0N/Aimport java.awt.geom.*;
0N/Aimport java.awt.print.PrinterGraphics;
0N/Aimport java.text.Bidi;
0N/Aimport java.text.AttributedCharacterIterator;
0N/Aimport java.text.AttributedString;
0N/A
0N/Aimport javax.swing.*;
0N/Aimport javax.swing.plaf.*;
0N/Aimport javax.swing.text.Highlighter;
0N/Aimport javax.swing.text.JTextComponent;
0N/Aimport javax.swing.text.DefaultHighlighter;
0N/Aimport javax.swing.text.DefaultCaret;
0N/Aimport javax.swing.table.TableCellRenderer;
2381N/Aimport javax.swing.table.TableColumnModel;
2381N/A
0N/Aimport sun.swing.PrintColorUIResource;
0N/Aimport sun.swing.ImageIconUIResource;
0N/Aimport sun.print.ProxyPrintGraphics;
0N/Aimport sun.awt.*;
0N/Aimport sun.security.action.GetPropertyAction;
0N/Aimport sun.security.util.SecurityConstants;
0N/Aimport java.io.*;
0N/Aimport java.util.*;
0N/Aimport sun.font.FontDesignMetrics;
1686N/Aimport sun.font.FontUtilities;
760N/Aimport sun.java2d.SunGraphicsEnvironment;
0N/A
0N/Aimport java.util.concurrent.Callable;
0N/Aimport java.util.concurrent.Future;
0N/Aimport java.util.concurrent.FutureTask;
0N/A
0N/A/**
0N/A * A collection of utility methods for Swing.
0N/A * <p>
0N/A * <b>WARNING:</b> While this class is public, it should not be treated as
0N/A * public API and its API may change in incompatable ways between dot dot
0N/A * releases and even patch releases. You should not rely on this class even
0N/A * existing.
0N/A *
0N/A */
0N/Apublic class SwingUtilities2 {
0N/A /**
0N/A * The <code>AppContext</code> key for our one <code>LAFState</code>
0N/A * instance.
0N/A */
0N/A public static final Object LAF_STATE_KEY =
0N/A new StringBuffer("LookAndFeel State");
0N/A
1637N/A // Maintain a cache of CACHE_SIZE fonts and the left side bearing
1637N/A // of the characters falling into the range MIN_CHAR_INDEX to
1637N/A // MAX_CHAR_INDEX. The values in fontCache are created as needed.
1637N/A private static LSBCacheEntry[] fontCache;
1637N/A // Windows defines 6 font desktop properties, we will therefore only
1637N/A // cache the metrics for 6 fonts.
1637N/A private static final int CACHE_SIZE = 6;
1637N/A // nextIndex in fontCache to insert a font into.
1637N/A private static int nextIndex;
1637N/A // LSBCacheEntry used to search in fontCache to see if we already
1637N/A // have an entry for a particular font
1637N/A private static LSBCacheEntry searchKey;
1637N/A
1637N/A // getLeftSideBearing will consult all characters that fall in the
1637N/A // range MIN_CHAR_INDEX to MAX_CHAR_INDEX.
1637N/A private static final int MIN_CHAR_INDEX = (int)'W';
1637N/A private static final int MAX_CHAR_INDEX = (int)'W' + 1;
0N/A
0N/A public static final FontRenderContext DEFAULT_FRC =
0N/A new FontRenderContext(null, false, false);
0N/A
0N/A /**
0N/A * A JComponent client property is used to determine text aa settings.
0N/A * To avoid having this property persist between look and feels changes
0N/A * the value of the property is set to null in JComponent.setUI
0N/A */
0N/A public static final Object AA_TEXT_PROPERTY_KEY =
0N/A new StringBuffer("AATextInfoPropertyKey");
0N/A
0N/A /**
2450N/A * Attribute key for the content elements. If it is set on an element, the
2450N/A * element is considered to be a line break.
2450N/A */
2450N/A public static final String IMPLIED_CR = "CR";
2450N/A
2450N/A /**
0N/A * Used to tell a text component, being used as an editor for table
0N/A * or tree, how many clicks it took to start editing.
0N/A */
0N/A private static final StringBuilder SKIP_CLICK_COUNT =
0N/A new StringBuilder("skipClickCount");
0N/A
0N/A /* Presently this class assumes default fractional metrics.
0N/A * This may need to change to emulate future platform L&Fs.
0N/A */
0N/A public static class AATextInfo {
0N/A
0N/A private static AATextInfo getAATextInfoFromMap(Map hints) {
0N/A
0N/A Object aaHint = hints.get(KEY_TEXT_ANTIALIASING);
0N/A Object contHint = hints.get(KEY_TEXT_LCD_CONTRAST);
0N/A
0N/A if (aaHint == null ||
0N/A aaHint == VALUE_TEXT_ANTIALIAS_OFF ||
0N/A aaHint == VALUE_TEXT_ANTIALIAS_DEFAULT) {
0N/A return null;
0N/A } else {
0N/A return new AATextInfo(aaHint, (Integer)contHint);
0N/A }
0N/A }
0N/A
0N/A public static AATextInfo getAATextInfo(boolean lafCondition) {
0N/A SunToolkit.setAAFontSettingsCondition(lafCondition);
0N/A Toolkit tk = Toolkit.getDefaultToolkit();
0N/A Object map = tk.getDesktopProperty(SunToolkit.DESKTOPFONTHINTS);
0N/A if (map instanceof Map) {
0N/A return getAATextInfoFromMap((Map)map);
0N/A } else {
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A Object aaHint;
0N/A Integer lcdContrastHint;
0N/A FontRenderContext frc;
0N/A
0N/A /* These are rarely constructed objects, and only when a complete
0N/A * UI is being updated, so the cost of the tests here is minimal
0N/A * and saves tests elsewhere.
0N/A * We test that the values are ones we support/expect.
0N/A */
0N/A public AATextInfo(Object aaHint, Integer lcdContrastHint) {
0N/A if (aaHint == null) {
0N/A throw new InternalError("null not allowed here");
0N/A }
0N/A if (aaHint == VALUE_TEXT_ANTIALIAS_OFF ||
0N/A aaHint == VALUE_TEXT_ANTIALIAS_DEFAULT) {
0N/A throw new InternalError("AA must be on");
0N/A }
0N/A this.aaHint = aaHint;
0N/A this.lcdContrastHint = lcdContrastHint;
0N/A this.frc = new FontRenderContext(null, aaHint,
0N/A VALUE_FRACTIONALMETRICS_DEFAULT);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Key used in client properties used to indicate that the
0N/A * <code>ComponentUI</code> of the JComponent instance should be returned.
0N/A */
0N/A public static final Object COMPONENT_UI_PROPERTY_KEY =
0N/A new StringBuffer("ComponentUIPropertyKey");
0N/A
0N/A /** Client Property key for the text maximal offsets for BasicMenuItemUI */
0N/A public static final StringUIClientPropertyKey BASICMENUITEMUI_MAX_TEXT_OFFSET =
0N/A new StringUIClientPropertyKey ("maxTextOffset");
0N/A
0N/A // security stuff
0N/A private static Field inputEvent_CanAccessSystemClipboard_Field = null;
0N/A private static final String UntrustedClipboardAccess =
0N/A "UNTRUSTED_CLIPBOARD_ACCESS_KEY";
0N/A
0N/A //all access to charsBuffer is to be synchronized on charsBufferLock
0N/A private static final int CHAR_BUFFER_SIZE = 100;
0N/A private static final Object charsBufferLock = new Object();
0N/A private static char[] charsBuffer = new char[CHAR_BUFFER_SIZE];
0N/A
1637N/A static {
1637N/A fontCache = new LSBCacheEntry[CACHE_SIZE];
1637N/A }
1637N/A
0N/A /**
1734N/A * Fill the character buffer cache. Return the buffer length.
1734N/A */
1734N/A private static int syncCharsBuffer(String s) {
1734N/A int length = s.length();
1734N/A if ((charsBuffer == null) || (charsBuffer.length < length)) {
1734N/A charsBuffer = s.toCharArray();
1734N/A } else {
1734N/A s.getChars(0, length, charsBuffer, 0);
1734N/A }
1734N/A return length;
1734N/A }
1734N/A
1734N/A /**
0N/A * checks whether TextLayout is required to handle characters.
0N/A *
0N/A * @param text characters to be tested
0N/A * @param start start
0N/A * @param limit limit
0N/A * @return <tt>true</tt> if TextLayout is required
0N/A * <tt>false</tt> if TextLayout is not required
0N/A */
0N/A public static final boolean isComplexLayout(char[] text, int start, int limit) {
1686N/A return FontUtilities.isComplexText(text, start, limit);
0N/A }
0N/A
0N/A //
0N/A // WARNING WARNING WARNING WARNING WARNING WARNING
0N/A // Many of the following methods are invoked from older API.
0N/A // As this older API was not passed a Component, a null Component may
0N/A // now be passsed in. For example, SwingUtilities.computeStringWidth
0N/A // is implemented to call SwingUtilities2.stringWidth, the
0N/A // SwingUtilities variant does not take a JComponent, as such
0N/A // SwingUtilities2.stringWidth can be passed a null Component.
0N/A // In other words, if you add new functionality to these methods you
0N/A // need to gracefully handle null.
0N/A //
0N/A
0N/A /**
0N/A * Returns whether or not text should be drawn antialiased.
0N/A *
0N/A * @param c JComponent to test.
0N/A * @return Whether or not text should be drawn antialiased for the
0N/A * specified component.
0N/A */
0N/A public static AATextInfo drawTextAntialiased(JComponent c) {
0N/A if (c != null) {
0N/A /* a non-null property implies some form of AA requested */
0N/A return (AATextInfo)c.getClientProperty(AA_TEXT_PROPERTY_KEY);
0N/A }
0N/A // No component, assume aa is off
0N/A return null;
0N/A }
0N/A
0N/A /**
0N/A * Returns the left side bearing of the first character of string. The
1637N/A * left side bearing is calculated from the passed in
1637N/A * FontMetrics. If the passed in String is less than one
1738N/A * character {@code 0} is returned.
0N/A *
0N/A * @param c JComponent that will display the string
0N/A * @param fm FontMetrics used to measure the String width
0N/A * @param string String to get the left side bearing for.
1738N/A * @throws NullPointerException if {@code string} is {@code null}
1738N/A *
1738N/A * @return the left side bearing of the first character of string
1738N/A * or {@code 0} if the string is empty
0N/A */
0N/A public static int getLeftSideBearing(JComponent c, FontMetrics fm,
0N/A String string) {
3973N/A if ((string == null) || (string.length() == 0)) {
3973N/A return 0;
1738N/A }
3973N/A return getLeftSideBearing(c, fm, string.charAt(0));
0N/A }
0N/A
0N/A /**
1637N/A * Returns the left side bearing of the first character of string. The
0N/A * left side bearing is calculated from the passed in FontMetrics.
0N/A *
0N/A * @param c JComponent that will display the string
0N/A * @param fm FontMetrics used to measure the String width
0N/A * @param firstChar Character to get the left side bearing for.
0N/A */
0N/A public static int getLeftSideBearing(JComponent c, FontMetrics fm,
0N/A char firstChar) {
1637N/A int charIndex = (int) firstChar;
1637N/A if (charIndex < MAX_CHAR_INDEX && charIndex >= MIN_CHAR_INDEX) {
1637N/A byte[] lsbs = null;
0N/A
1637N/A FontRenderContext frc = getFontRenderContext(c, fm);
1637N/A Font font = fm.getFont();
1637N/A synchronized (SwingUtilities2.class) {
1637N/A LSBCacheEntry entry = null;
1637N/A if (searchKey == null) {
1637N/A searchKey = new LSBCacheEntry(frc, font);
1637N/A } else {
1637N/A searchKey.reset(frc, font);
0N/A }
1637N/A // See if we already have an entry for this pair
1637N/A for (LSBCacheEntry cacheEntry : fontCache) {
0N/A if (searchKey.equals(cacheEntry)) {
0N/A entry = cacheEntry;
0N/A break;
0N/A }
0N/A }
1637N/A if (entry == null) {
1637N/A // No entry for this pair, add it.
1637N/A entry = searchKey;
1637N/A fontCache[nextIndex] = searchKey;
1637N/A searchKey = null;
1637N/A nextIndex = (nextIndex + 1) % CACHE_SIZE;
1637N/A }
1637N/A return entry.getLeftSideBearing(firstChar);
0N/A }
0N/A }
1637N/A return 0;
0N/A }
0N/A
0N/A /**
0N/A * Returns the FontMetrics for the current Font of the passed
0N/A * in Graphics. This method is used when a Graphics
0N/A * is available, typically when painting. If a Graphics is not
0N/A * available the JComponent method of the same name should be used.
0N/A * <p>
0N/A * Callers should pass in a non-null JComponent, the exception
0N/A * to this is if a JComponent is not readily available at the time of
0N/A * painting.
0N/A * <p>
0N/A * This does not necessarily return the FontMetrics from the
0N/A * Graphics.
0N/A *
0N/A * @param c JComponent requesting FontMetrics, may be null
0N/A * @param g Graphics Graphics
0N/A */
0N/A public static FontMetrics getFontMetrics(JComponent c, Graphics g) {
0N/A return getFontMetrics(c, g, g.getFont());
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Returns the FontMetrics for the specified Font.
0N/A * This method is used when a Graphics is available, typically when
0N/A * painting. If a Graphics is not available the JComponent method of
0N/A * the same name should be used.
0N/A * <p>
0N/A * Callers should pass in a non-null JComonent, the exception
0N/A * to this is if a JComponent is not readily available at the time of
0N/A * painting.
0N/A * <p>
0N/A * This does not necessarily return the FontMetrics from the
0N/A * Graphics.
0N/A *
0N/A * @param c JComponent requesting FontMetrics, may be null
0N/A * @param c Graphics Graphics
0N/A * @param font Font to get FontMetrics for
0N/A */
0N/A public static FontMetrics getFontMetrics(JComponent c, Graphics g,
0N/A Font font) {
0N/A if (c != null) {
0N/A // Note: We assume that we're using the FontMetrics
0N/A // from the widget to layout out text, otherwise we can get
0N/A // mismatches when printing.
0N/A return c.getFontMetrics(font);
0N/A }
0N/A return Toolkit.getDefaultToolkit().getFontMetrics(font);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Returns the width of the passed in String.
0N/A * If the passed String is <code>null</code>, returns zero.
0N/A *
0N/A * @param c JComponent that will display the string, may be null
0N/A * @param fm FontMetrics used to measure the String width
0N/A * @param string String to get the width of
0N/A */
0N/A public static int stringWidth(JComponent c, FontMetrics fm, String string){
0N/A if (string == null || string.equals("")) {
0N/A return 0;
0N/A }
1734N/A boolean needsTextLayout = ((c != null) &&
1734N/A (c.getClientProperty(TextAttribute.NUMERIC_SHAPING) != null));
1734N/A if (needsTextLayout) {
1734N/A synchronized(charsBufferLock) {
1734N/A int length = syncCharsBuffer(string);
1734N/A needsTextLayout = isComplexLayout(charsBuffer, 0, length);
1734N/A }
1734N/A }
1734N/A if (needsTextLayout) {
1734N/A TextLayout layout = createTextLayout(c, string,
1734N/A fm.getFont(), fm.getFontRenderContext());
1734N/A return (int) layout.getAdvance();
1734N/A } else {
1734N/A return fm.stringWidth(string);
1734N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Clips the passed in String to the space provided.
0N/A *
0N/A * @param c JComponent that will display the string, may be null
0N/A * @param fm FontMetrics used to measure the String width
0N/A * @param string String to display
0N/A * @param availTextWidth Amount of space that the string can be drawn in
0N/A * @return Clipped string that can fit in the provided space.
0N/A */
0N/A public static String clipStringIfNecessary(JComponent c, FontMetrics fm,
0N/A String string,
0N/A int availTextWidth) {
0N/A if ((string == null) || (string.equals(""))) {
0N/A return "";
0N/A }
0N/A int textWidth = SwingUtilities2.stringWidth(c, fm, string);
0N/A if (textWidth > availTextWidth) {
0N/A return SwingUtilities2.clipString(c, fm, string, availTextWidth);
0N/A }
0N/A return string;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Clips the passed in String to the space provided. NOTE: this assumes
0N/A * the string does not fit in the available space.
0N/A *
0N/A * @param c JComponent that will display the string, may be null
0N/A * @param fm FontMetrics used to measure the String width
0N/A * @param string String to display
0N/A * @param availTextWidth Amount of space that the string can be drawn in
0N/A * @return Clipped string that can fit in the provided space.
0N/A */
0N/A public static String clipString(JComponent c, FontMetrics fm,
0N/A String string, int availTextWidth) {
0N/A // c may be null here.
0N/A String clipString = "...";
0N/A availTextWidth -= SwingUtilities2.stringWidth(c, fm, clipString);
2524N/A if (availTextWidth <= 0) {
2524N/A //can not fit any characters
2524N/A return clipString;
2524N/A }
2524N/A
625N/A boolean needsTextLayout;
0N/A synchronized (charsBufferLock) {
1734N/A int stringLength = syncCharsBuffer(string);
0N/A needsTextLayout =
0N/A isComplexLayout(charsBuffer, 0, stringLength);
0N/A if (!needsTextLayout) {
0N/A int width = 0;
0N/A for (int nChars = 0; nChars < stringLength; nChars++) {
0N/A width += fm.charWidth(charsBuffer[nChars]);
0N/A if (width > availTextWidth) {
0N/A string = string.substring(0, nChars);
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A if (needsTextLayout) {
0N/A FontRenderContext frc = getFontRenderContext(c, fm);
0N/A AttributedString aString = new AttributedString(string);
1734N/A if (c != null) {
1734N/A aString.addAttribute(TextAttribute.NUMERIC_SHAPING,
1734N/A c.getClientProperty(TextAttribute.NUMERIC_SHAPING));
1734N/A }
0N/A LineBreakMeasurer measurer =
0N/A new LineBreakMeasurer(aString.getIterator(), frc);
0N/A int nChars = measurer.nextOffset(availTextWidth);
0N/A string = string.substring(0, nChars);
0N/A
0N/A }
0N/A return string + clipString;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Draws the string at the specified location.
0N/A *
0N/A * @param c JComponent that will display the string, may be null
0N/A * @param g Graphics to draw the text to
0N/A * @param text String to display
0N/A * @param x X coordinate to draw the text at
0N/A * @param y Y coordinate to draw the text at
0N/A */
0N/A public static void drawString(JComponent c, Graphics g, String text,
0N/A int x, int y) {
0N/A // c may be null
0N/A
0N/A // All non-editable widgets that draw strings call into this
0N/A // methods. By non-editable that means widgets like JLabel, JButton
0N/A // but NOT JTextComponents.
0N/A if ( text == null || text.length() <= 0 ) { //no need to paint empty strings
0N/A return;
0N/A }
0N/A if (isPrinting(g)) {
0N/A Graphics2D g2d = getGraphics2D(g);
0N/A if (g2d != null) {
0N/A /* The printed text must scale linearly with the UI.
0N/A * Calculate the width on screen, obtain a TextLayout with
0N/A * advances for the printer graphics FRC, and then justify
0N/A * it to fit in the screen width. This distributes the spacing
0N/A * more evenly than directly laying out to the screen advances.
0N/A */
0N/A float screenWidth = (float)
0N/A g2d.getFont().getStringBounds(text, DEFAULT_FRC).getWidth();
1734N/A TextLayout layout = createTextLayout(c, text, g2d.getFont(),
0N/A g2d.getFontRenderContext());
0N/A
0N/A layout = layout.getJustifiedLayout(screenWidth);
0N/A /* Use alternate print color if specified */
0N/A Color col = g2d.getColor();
0N/A if (col instanceof PrintColorUIResource) {
0N/A g2d.setColor(((PrintColorUIResource)col).getPrintColor());
0N/A }
0N/A
0N/A layout.draw(g2d, x, y);
0N/A
0N/A g2d.setColor(col);
0N/A
0N/A return;
0N/A }
0N/A }
0N/A
0N/A // If we get here we're not printing
0N/A AATextInfo info = drawTextAntialiased(c);
0N/A if (info != null && (g instanceof Graphics2D)) {
0N/A Graphics2D g2 = (Graphics2D)g;
0N/A
0N/A Object oldContrast = null;
0N/A Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING);
0N/A if (info.aaHint != oldAAValue) {
0N/A g2.setRenderingHint(KEY_TEXT_ANTIALIASING, info.aaHint);
0N/A } else {
0N/A oldAAValue = null;
0N/A }
0N/A if (info.lcdContrastHint != null) {
0N/A oldContrast = g2.getRenderingHint(KEY_TEXT_LCD_CONTRAST);
0N/A if (info.lcdContrastHint.equals(oldContrast)) {
0N/A oldContrast = null;
0N/A } else {
0N/A g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST,
0N/A info.lcdContrastHint);
0N/A }
0N/A }
0N/A
1734N/A boolean needsTextLayout = ((c != null) &&
1734N/A (c.getClientProperty(TextAttribute.NUMERIC_SHAPING) != null));
1734N/A if (needsTextLayout) {
1734N/A synchronized(charsBufferLock) {
1734N/A int length = syncCharsBuffer(text);
1734N/A needsTextLayout = isComplexLayout(charsBuffer, 0, length);
1734N/A }
1734N/A }
1734N/A if (needsTextLayout) {
1734N/A TextLayout layout = createTextLayout(c, text, g2.getFont(),
1734N/A g2.getFontRenderContext());
1734N/A layout.draw(g2, x, y);
1734N/A } else {
1734N/A g.drawString(text, x, y);
1734N/A }
0N/A
0N/A if (oldAAValue != null) {
0N/A g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue);
0N/A }
0N/A if (oldContrast != null) {
0N/A g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, oldContrast);
0N/A }
0N/A }
0N/A else {
0N/A g.drawString(text, x, y);
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Draws the string at the specified location underlining the specified
0N/A * character.
0N/A *
0N/A * @param c JComponent that will display the string, may be null
0N/A * @param g Graphics to draw the text to
0N/A * @param text String to display
0N/A * @param underlinedIndex Index of a character in the string to underline
0N/A * @param x X coordinate to draw the text at
0N/A * @param y Y coordinate to draw the text at
0N/A */
0N/A public static void drawStringUnderlineCharAt(JComponent c,Graphics g,
0N/A String text, int underlinedIndex, int x,int y) {
0N/A if (text == null || text.length() <= 0) {
0N/A return;
0N/A }
0N/A SwingUtilities2.drawString(c, g, text, x, y);
0N/A int textLength = text.length();
0N/A if (underlinedIndex >= 0 && underlinedIndex < textLength ) {
0N/A int underlineRectY = y;
0N/A int underlineRectHeight = 1;
0N/A int underlineRectX = 0;
0N/A int underlineRectWidth = 0;
0N/A boolean isPrinting = isPrinting(g);
0N/A boolean needsTextLayout = isPrinting;
0N/A if (!needsTextLayout) {
0N/A synchronized (charsBufferLock) {
1734N/A syncCharsBuffer(text);
0N/A needsTextLayout =
0N/A isComplexLayout(charsBuffer, 0, textLength);
0N/A }
0N/A }
0N/A if (!needsTextLayout) {
0N/A FontMetrics fm = g.getFontMetrics();
0N/A underlineRectX = x +
0N/A SwingUtilities2.stringWidth(c,fm,
0N/A text.substring(0,underlinedIndex));
0N/A underlineRectWidth = fm.charWidth(text.
0N/A charAt(underlinedIndex));
0N/A } else {
0N/A Graphics2D g2d = getGraphics2D(g);
0N/A if (g2d != null) {
0N/A TextLayout layout =
1734N/A createTextLayout(c, text, g2d.getFont(),
0N/A g2d.getFontRenderContext());
0N/A if (isPrinting) {
0N/A float screenWidth = (float)g2d.getFont().
0N/A getStringBounds(text, DEFAULT_FRC).getWidth();
0N/A layout = layout.getJustifiedLayout(screenWidth);
0N/A }
0N/A TextHitInfo leading =
0N/A TextHitInfo.leading(underlinedIndex);
0N/A TextHitInfo trailing =
0N/A TextHitInfo.trailing(underlinedIndex);
0N/A Shape shape =
0N/A layout.getVisualHighlightShape(leading, trailing);
0N/A Rectangle rect = shape.getBounds();
0N/A underlineRectX = x + rect.x;
0N/A underlineRectWidth = rect.width;
0N/A }
0N/A }
0N/A g.fillRect(underlineRectX, underlineRectY + 1,
0N/A underlineRectWidth, underlineRectHeight);
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * A variation of locationToIndex() which only returns an index if the
0N/A * Point is within the actual bounds of a list item (not just in the cell)
0N/A * and if the JList has the "List.isFileList" client property set.
0N/A * Otherwise, this method returns -1.
0N/A * This is used to make WindowsL&F JFileChooser act like native dialogs.
0N/A */
0N/A public static int loc2IndexFileList(JList list, Point point) {
0N/A int index = list.locationToIndex(point);
0N/A if (index != -1) {
0N/A Object bySize = list.getClientProperty("List.isFileList");
0N/A if (bySize instanceof Boolean && ((Boolean)bySize).booleanValue() &&
0N/A !pointIsInActualBounds(list, index, point)) {
0N/A index = -1;
0N/A }
0N/A }
0N/A return index;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Returns true if the given point is within the actual bounds of the
0N/A * JList item at index (not just inside the cell).
0N/A */
0N/A private static boolean pointIsInActualBounds(JList list, int index,
0N/A Point point) {
0N/A ListCellRenderer renderer = list.getCellRenderer();
0N/A ListModel dataModel = list.getModel();
0N/A Object value = dataModel.getElementAt(index);
0N/A Component item = renderer.getListCellRendererComponent(list,
0N/A value, index, false, false);
0N/A Dimension itemSize = item.getPreferredSize();
0N/A Rectangle cellBounds = list.getCellBounds(index, index);
0N/A if (!item.getComponentOrientation().isLeftToRight()) {
0N/A cellBounds.x += (cellBounds.width - itemSize.width);
0N/A }
0N/A cellBounds.width = itemSize.width;
0N/A
0N/A return cellBounds.contains(point);
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Returns true if the given point is outside the preferredSize of the
0N/A * item at the given row of the table. (Column must be 0).
0N/A * Does not check the "Table.isFileList" property. That should be checked
0N/A * before calling this method.
0N/A * This is used to make WindowsL&F JFileChooser act like native dialogs.
0N/A */
0N/A public static boolean pointOutsidePrefSize(JTable table, int row, int column, Point p) {
0N/A if (table.convertColumnIndexToModel(column) != 0 || row == -1) {
0N/A return true;
0N/A }
0N/A TableCellRenderer tcr = table.getCellRenderer(row, column);
0N/A Object value = table.getValueAt(row, column);
0N/A Component cell = tcr.getTableCellRendererComponent(table, value, false,
0N/A false, row, column);
0N/A Dimension itemSize = cell.getPreferredSize();
0N/A Rectangle cellBounds = table.getCellRect(row, column, false);
0N/A cellBounds.width = itemSize.width;
0N/A cellBounds.height = itemSize.height;
0N/A
0N/A // See if coords are inside
0N/A // ASSUME: mouse x,y will never be < cell's x,y
0N/A assert (p.x >= cellBounds.x && p.y >= cellBounds.y);
625N/A return p.x > cellBounds.x + cellBounds.width ||
625N/A p.y > cellBounds.y + cellBounds.height;
0N/A }
0N/A
0N/A /**
0N/A * Set the lead and anchor without affecting selection.
0N/A */
0N/A public static void setLeadAnchorWithoutSelection(ListSelectionModel model,
0N/A int lead, int anchor) {
0N/A if (anchor == -1) {
0N/A anchor = lead;
0N/A }
0N/A if (lead == -1) {
0N/A model.setAnchorSelectionIndex(-1);
0N/A model.setLeadSelectionIndex(-1);
0N/A } else {
0N/A if (model.isSelectedIndex(lead)) {
0N/A model.addSelectionInterval(lead, lead);
0N/A } else {
0N/A model.removeSelectionInterval(lead, lead);
0N/A }
0N/A model.setAnchorSelectionIndex(anchor);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Ignore mouse events if the component is null, not enabled, the event
0N/A * is not associated with the left mouse button, or the event has been
0N/A * consumed.
0N/A */
0N/A public static boolean shouldIgnore(MouseEvent me, JComponent c) {
0N/A return c == null || !c.isEnabled()
0N/A || !SwingUtilities.isLeftMouseButton(me)
0N/A || me.isConsumed();
0N/A }
0N/A
0N/A /**
0N/A * Request focus on the given component if it doesn't already have it
0N/A * and <code>isRequestFocusEnabled()</code> returns true.
0N/A */
0N/A public static void adjustFocus(JComponent c) {
0N/A if (!c.hasFocus() && c.isRequestFocusEnabled()) {
0N/A c.requestFocus();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * The following draw functions have the same semantic as the
0N/A * Graphics methods with the same names.
0N/A *
0N/A * this is used for printing
0N/A */
0N/A public static int drawChars(JComponent c, Graphics g,
0N/A char[] data,
0N/A int offset,
0N/A int length,
0N/A int x,
0N/A int y) {
0N/A if ( length <= 0 ) { //no need to paint empty strings
0N/A return x;
0N/A }
0N/A int nextX = x + getFontMetrics(c, g).charsWidth(data, offset, length);
0N/A if (isPrinting(g)) {
0N/A Graphics2D g2d = getGraphics2D(g);
0N/A if (g2d != null) {
0N/A FontRenderContext deviceFontRenderContext = g2d.
0N/A getFontRenderContext();
0N/A FontRenderContext frc = getFontRenderContext(c);
0N/A if (frc != null &&
0N/A !isFontRenderContextPrintCompatible
0N/A (deviceFontRenderContext, frc)) {
0N/A TextLayout layout =
1734N/A createTextLayout(c, new String(data, offset, length),
0N/A g2d.getFont(),
0N/A deviceFontRenderContext);
0N/A float screenWidth = (float)g2d.getFont().
0N/A getStringBounds(data, offset, offset + length, frc).
0N/A getWidth();
0N/A layout = layout.getJustifiedLayout(screenWidth);
0N/A
0N/A /* Use alternate print color if specified */
0N/A Color col = g2d.getColor();
0N/A if (col instanceof PrintColorUIResource) {
0N/A g2d.setColor(((PrintColorUIResource)col).getPrintColor());
0N/A }
0N/A
0N/A layout.draw(g2d,x,y);
0N/A
0N/A g2d.setColor(col);
0N/A
0N/A return nextX;
0N/A }
0N/A }
0N/A }
0N/A // Assume we're not printing if we get here, or that we are invoked
0N/A // via Swing text printing which is laid out for the printer.
0N/A AATextInfo info = drawTextAntialiased(c);
0N/A if (info != null && (g instanceof Graphics2D)) {
0N/A Graphics2D g2 = (Graphics2D)g;
0N/A
0N/A Object oldContrast = null;
0N/A Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING);
0N/A if (info.aaHint != null && info.aaHint != oldAAValue) {
0N/A g2.setRenderingHint(KEY_TEXT_ANTIALIASING, info.aaHint);
0N/A } else {
0N/A oldAAValue = null;
0N/A }
0N/A if (info.lcdContrastHint != null) {
0N/A oldContrast = g2.getRenderingHint(KEY_TEXT_LCD_CONTRAST);
0N/A if (info.lcdContrastHint.equals(oldContrast)) {
0N/A oldContrast = null;
0N/A } else {
0N/A g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST,
0N/A info.lcdContrastHint);
0N/A }
0N/A }
0N/A
0N/A g.drawChars(data, offset, length, x, y);
0N/A
0N/A if (oldAAValue != null) {
0N/A g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue);
0N/A }
0N/A if (oldContrast != null) {
0N/A g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, oldContrast);
0N/A }
0N/A }
0N/A else {
0N/A g.drawChars(data, offset, length, x, y);
0N/A }
0N/A return nextX;
0N/A }
0N/A
0N/A /*
0N/A * see documentation for drawChars
0N/A * returns the advance
0N/A */
0N/A public static float drawString(JComponent c, Graphics g,
0N/A AttributedCharacterIterator iterator,
0N/A int x,
0N/A int y) {
0N/A
0N/A float retVal;
0N/A boolean isPrinting = isPrinting(g);
0N/A Color col = g.getColor();
0N/A
0N/A if (isPrinting) {
0N/A /* Use alternate print color if specified */
0N/A if (col instanceof PrintColorUIResource) {
0N/A g.setColor(((PrintColorUIResource)col).getPrintColor());
0N/A }
0N/A }
0N/A
0N/A Graphics2D g2d = getGraphics2D(g);
0N/A if (g2d == null) {
0N/A g.drawString(iterator,x,y); //for the cases where advance
0N/A //matters it should not happen
0N/A retVal = x;
0N/A
0N/A } else {
0N/A FontRenderContext frc;
0N/A if (isPrinting) {
0N/A frc = getFontRenderContext(c);
0N/A if (frc.isAntiAliased() || frc.usesFractionalMetrics()) {
0N/A frc = new FontRenderContext(frc.getTransform(), false, false);
0N/A }
0N/A } else if ((frc = getFRCProperty(c)) != null) {
0N/A /* frc = frc; ! */
0N/A } else {
0N/A frc = g2d.getFontRenderContext();
0N/A }
0N/A TextLayout layout = new TextLayout(iterator, frc);
0N/A if (isPrinting) {
0N/A FontRenderContext deviceFRC = g2d.getFontRenderContext();
0N/A if (!isFontRenderContextPrintCompatible(frc, deviceFRC)) {
0N/A float screenWidth = layout.getAdvance();
0N/A layout = new TextLayout(iterator, deviceFRC);
0N/A layout = layout.getJustifiedLayout(screenWidth);
0N/A }
0N/A }
0N/A layout.draw(g2d, x, y);
0N/A retVal = layout.getAdvance();
0N/A }
0N/A
0N/A if (isPrinting) {
0N/A g.setColor(col);
0N/A }
0N/A
0N/A return retVal;
0N/A }
0N/A
1734N/A private static TextLayout createTextLayout(JComponent c, String s,
1734N/A Font f, FontRenderContext frc) {
1734N/A Object shaper = (c == null ?
1734N/A null : c.getClientProperty(TextAttribute.NUMERIC_SHAPING));
1734N/A if (shaper == null) {
1734N/A return new TextLayout(s, f, frc);
1734N/A } else {
1734N/A Map<TextAttribute, Object> a = new HashMap<TextAttribute, Object>();
1734N/A a.put(TextAttribute.FONT, f);
1734N/A a.put(TextAttribute.NUMERIC_SHAPING, shaper);
1734N/A return new TextLayout(s, a, frc);
1734N/A }
1734N/A }
1734N/A
0N/A /*
0N/A * Checks if two given FontRenderContexts are compatible for printing.
0N/A * We can't just use equals as we want to exclude from the comparison :
0N/A * + whether AA is set as irrelevant for printing and shouldn't affect
0N/A * printed metrics anyway
0N/A * + any translation component in the transform of either FRC, as it
0N/A * does not affect metrics.
0N/A * Compatible means no special handling needed for text painting
0N/A */
0N/A private static boolean
0N/A isFontRenderContextPrintCompatible(FontRenderContext frc1,
0N/A FontRenderContext frc2) {
0N/A
0N/A if (frc1 == frc2) {
0N/A return true;
0N/A }
0N/A
0N/A if (frc1 == null || frc2 == null) { // not supposed to happen
0N/A return false;
0N/A }
0N/A
0N/A if (frc1.getFractionalMetricsHint() !=
0N/A frc2.getFractionalMetricsHint()) {
0N/A return false;
0N/A }
0N/A
0N/A /* If both are identity, return true */
0N/A if (!frc1.isTransformed() && !frc2.isTransformed()) {
0N/A return true;
0N/A }
0N/A
0N/A /* That's the end of the cheap tests, need to get and compare
0N/A * the transform matrices. We don't care about the translation
0N/A * components, so return true if they are otherwise identical.
0N/A */
0N/A double[] mat1 = new double[4];
0N/A double[] mat2 = new double[4];
0N/A frc1.getTransform().getMatrix(mat1);
0N/A frc2.getTransform().getMatrix(mat2);
0N/A return
0N/A mat1[0] == mat2[0] &&
0N/A mat1[1] == mat2[1] &&
0N/A mat1[2] == mat2[2] &&
0N/A mat1[3] == mat2[3];
0N/A }
0N/A
0N/A /*
0N/A * Tries it best to get Graphics2D out of the given Graphics
0N/A * returns null if can not derive it.
0N/A */
0N/A public static Graphics2D getGraphics2D(Graphics g) {
0N/A if (g instanceof Graphics2D) {
0N/A return (Graphics2D) g;
0N/A } else if (g instanceof ProxyPrintGraphics) {
0N/A return (Graphics2D)(((ProxyPrintGraphics)g).getGraphics());
0N/A } else {
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Returns FontRenderContext associated with Component.
0N/A * FontRenderContext from Component.getFontMetrics is associated
0N/A * with the component.
0N/A *
0N/A * Uses Component.getFontMetrics to get the FontRenderContext from.
0N/A * see JComponent.getFontMetrics and TextLayoutStrategy.java
0N/A */
0N/A public static FontRenderContext getFontRenderContext(Component c) {
0N/A assert c != null;
0N/A if (c == null) {
0N/A return DEFAULT_FRC;
0N/A } else {
0N/A return c.getFontMetrics(c.getFont()).getFontRenderContext();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * A convenience method to get FontRenderContext.
0N/A * Returns the FontRenderContext for the passed in FontMetrics or
0N/A * for the passed in Component if FontMetrics is null
0N/A */
0N/A private static FontRenderContext getFontRenderContext(Component c, FontMetrics fm) {
0N/A assert fm != null || c!= null;
0N/A return (fm != null) ? fm.getFontRenderContext()
0N/A : getFontRenderContext(c);
0N/A }
0N/A
0N/A /*
0N/A * This method is to be used only for JComponent.getFontMetrics.
0N/A * In all other places to get FontMetrics we need to use
0N/A * JComponent.getFontMetrics.
0N/A *
0N/A */
0N/A public static FontMetrics getFontMetrics(JComponent c, Font font) {
0N/A FontRenderContext frc = getFRCProperty(c);
0N/A if (frc == null) {
0N/A frc = DEFAULT_FRC;
0N/A }
0N/A return FontDesignMetrics.getMetrics(font, frc);
0N/A }
0N/A
0N/A
0N/A /* Get any FontRenderContext associated with a JComponent
0N/A * - may return null
0N/A */
0N/A private static FontRenderContext getFRCProperty(JComponent c) {
0N/A if (c != null) {
0N/A AATextInfo info =
0N/A (AATextInfo)c.getClientProperty(AA_TEXT_PROPERTY_KEY);
0N/A if (info != null) {
0N/A return info.frc;
0N/A }
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A /*
0N/A * returns true if the Graphics is print Graphics
0N/A * false otherwise
0N/A */
0N/A static boolean isPrinting(Graphics g) {
0N/A return (g instanceof PrinterGraphics || g instanceof PrintGraphics);
0N/A }
0N/A
0N/A /**
0N/A * Determines whether the SelectedTextColor should be used for painting text
0N/A * foreground for the specified highlight.
0N/A *
0N/A * Returns true only if the highlight painter for the specified highlight
0N/A * is the swing painter (whether inner class of javax.swing.text.DefaultHighlighter
0N/A * or com.sun.java.swing.plaf.windows.WindowsTextUI) and its background color
0N/A * is null or equals to the selection color of the text component.
0N/A *
0N/A * This is a hack for fixing both bugs 4761990 and 5003294
0N/A */
0N/A public static boolean useSelectedTextColor(Highlighter.Highlight h, JTextComponent c) {
0N/A Highlighter.HighlightPainter painter = h.getPainter();
0N/A String painterClass = painter.getClass().getName();
0N/A if (painterClass.indexOf("javax.swing.text.DefaultHighlighter") != 0 &&
0N/A painterClass.indexOf("com.sun.java.swing.plaf.windows.WindowsTextUI") != 0) {
0N/A return false;
0N/A }
0N/A try {
0N/A DefaultHighlighter.DefaultHighlightPainter defPainter =
0N/A (DefaultHighlighter.DefaultHighlightPainter) painter;
0N/A if (defPainter.getColor() != null &&
0N/A !defPainter.getColor().equals(c.getSelectionColor())) {
0N/A return false;
0N/A }
0N/A } catch (ClassCastException e) {
0N/A return false;
0N/A }
0N/A return true;
0N/A }
0N/A
0N/A /**
1637N/A * LSBCacheEntry is used to cache the left side bearing (lsb) for
1637N/A * a particular <code>Font</code> and <code>FontRenderContext</code>.
1637N/A * This only caches characters that fall in the range
1637N/A * <code>MIN_CHAR_INDEX</code> to <code>MAX_CHAR_INDEX</code>.
0N/A */
1637N/A private static class LSBCacheEntry {
1637N/A // Used to indicate a particular entry in lsb has not been set.
1637N/A private static final byte UNSET = Byte.MAX_VALUE;
1637N/A // Used in creating a GlyphVector to get the lsb
1637N/A private static final char[] oneChar = new char[1];
1637N/A
1637N/A private byte[] lsbCache;
0N/A private Font font;
0N/A private FontRenderContext frc;
1637N/A
1637N/A
1637N/A public LSBCacheEntry(FontRenderContext frc, Font font) {
1637N/A lsbCache = new byte[MAX_CHAR_INDEX - MIN_CHAR_INDEX];
1637N/A reset(frc, font);
0N/A
1637N/A }
1637N/A
1637N/A public void reset(FontRenderContext frc, Font font) {
1637N/A this.font = font;
1637N/A this.frc = frc;
1637N/A for (int counter = lsbCache.length - 1; counter >= 0; counter--) {
1637N/A lsbCache[counter] = UNSET;
1637N/A }
0N/A }
0N/A
0N/A public int getLeftSideBearing(char aChar) {
1637N/A int index = aChar - MIN_CHAR_INDEX;
1637N/A assert (index >= 0 && index < (MAX_CHAR_INDEX - MIN_CHAR_INDEX));
1637N/A byte lsb = lsbCache[index];
1637N/A if (lsb == UNSET) {
1637N/A oneChar[0] = aChar;
1637N/A GlyphVector gv = font.createGlyphVector(frc, oneChar);
1637N/A lsb = (byte) gv.getGlyphPixelBounds(0, frc, 0f, 0f).x;
1637N/A if (lsb < 0) {
1637N/A /* HRGB/HBGR LCD glyph images will always have a pixel
1637N/A * on the left used in colour fringe reduction.
1637N/A * Text rendering positions this correctly but here
1637N/A * we are using the glyph image to adjust that position
1637N/A * so must account for it.
1637N/A */
1637N/A Object aaHint = frc.getAntiAliasingHint();
1637N/A if (aaHint == VALUE_TEXT_ANTIALIAS_LCD_HRGB ||
1637N/A aaHint == VALUE_TEXT_ANTIALIAS_LCD_HBGR) {
1637N/A lsb++;
1637N/A }
1637N/A }
1637N/A lsbCache[index] = lsb;
0N/A }
1637N/A return lsb;
0N/A
0N/A
0N/A }
0N/A
0N/A public boolean equals(Object entry) {
0N/A if (entry == this) {
0N/A return true;
0N/A }
1637N/A if (!(entry instanceof LSBCacheEntry)) {
0N/A return false;
0N/A }
1637N/A LSBCacheEntry oEntry = (LSBCacheEntry) entry;
0N/A return (font.equals(oEntry.font) &&
0N/A frc.equals(oEntry.frc));
0N/A }
0N/A
0N/A public int hashCode() {
0N/A int result = 17;
0N/A if (font != null) {
0N/A result = 37 * result + font.hashCode();
0N/A }
0N/A if (frc != null) {
0N/A result = 37 * result + frc.hashCode();
0N/A }
0N/A return result;
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * here goes the fix for 4856343 [Problem with applet interaction
0N/A * with system selection clipboard]
0N/A *
0N/A * NOTE. In case isTrustedContext() no checking
0N/A * are to be performed
0N/A */
0N/A
0N/A /**
1637N/A * checks the security permissions for accessing system clipboard
1637N/A *
1637N/A * for untrusted context (see isTrustedContext) checks the
1637N/A * permissions for the current event being handled
1637N/A *
1637N/A */
1637N/A public static boolean canAccessSystemClipboard() {
1637N/A boolean canAccess = false;
1637N/A if (!GraphicsEnvironment.isHeadless()) {
1637N/A SecurityManager sm = System.getSecurityManager();
1637N/A if (sm == null) {
1637N/A canAccess = true;
1637N/A } else {
1637N/A try {
1637N/A sm.checkSystemClipboardAccess();
1637N/A canAccess = true;
1637N/A } catch (SecurityException e) {
1637N/A }
1637N/A if (canAccess && ! isTrustedContext()) {
1637N/A canAccess = canCurrentEventAccessSystemClipboard(true);
1637N/A }
1637N/A }
1637N/A }
1637N/A return canAccess;
1637N/A }
0N/A /**
1637N/A * Returns true if EventQueue.getCurrentEvent() has the permissions to
0N/A * access the system clipboard
0N/A */
0N/A public static boolean canCurrentEventAccessSystemClipboard() {
0N/A return isTrustedContext()
0N/A || canCurrentEventAccessSystemClipboard(false);
0N/A }
0N/A
0N/A /**
0N/A * Returns true if the given event has permissions to access the
0N/A * system clipboard
0N/A *
0N/A * @param e AWTEvent to check
0N/A */
0N/A public static boolean canEventAccessSystemClipboard(AWTEvent e) {
0N/A return isTrustedContext()
0N/A || canEventAccessSystemClipboard(e, false);
0N/A }
0N/A
0N/A /**
0N/A * returns canAccessSystemClipboard field from InputEvent
0N/A *
0N/A * @param ie InputEvent to get the field from
0N/A */
0N/A private static synchronized boolean inputEvent_canAccessSystemClipboard(InputEvent ie) {
0N/A if (inputEvent_CanAccessSystemClipboard_Field == null) {
0N/A inputEvent_CanAccessSystemClipboard_Field =
625N/A AccessController.doPrivileged(
625N/A new java.security.PrivilegedAction<Field>() {
625N/A public Field run() {
0N/A try {
625N/A Field field = InputEvent.class.
0N/A getDeclaredField("canAccessSystemClipboard");
0N/A field.setAccessible(true);
0N/A return field;
0N/A } catch (SecurityException e) {
0N/A } catch (NoSuchFieldException e) {
0N/A }
0N/A return null;
0N/A }
0N/A });
0N/A }
0N/A if (inputEvent_CanAccessSystemClipboard_Field == null) {
0N/A return false;
0N/A }
0N/A boolean ret = false;
0N/A try {
0N/A ret = inputEvent_CanAccessSystemClipboard_Field.
0N/A getBoolean(ie);
0N/A } catch(IllegalAccessException e) {
0N/A }
0N/A return ret;
0N/A }
0N/A
0N/A /**
0N/A * Returns true if the given event is corrent gesture for
0N/A * accessing clipboard
0N/A *
0N/A * @param ie InputEvent to check
0N/A */
0N/A
0N/A private static boolean isAccessClipboardGesture(InputEvent ie) {
0N/A boolean allowedGesture = false;
0N/A if (ie instanceof KeyEvent) { //we can validate only keyboard gestures
0N/A KeyEvent ke = (KeyEvent)ie;
0N/A int keyCode = ke.getKeyCode();
0N/A int keyModifiers = ke.getModifiers();
0N/A switch(keyCode) {
0N/A case KeyEvent.VK_C:
0N/A case KeyEvent.VK_V:
0N/A case KeyEvent.VK_X:
0N/A allowedGesture = (keyModifiers == InputEvent.CTRL_MASK);
0N/A break;
0N/A case KeyEvent.VK_INSERT:
0N/A allowedGesture = (keyModifiers == InputEvent.CTRL_MASK ||
0N/A keyModifiers == InputEvent.SHIFT_MASK);
0N/A break;
0N/A case KeyEvent.VK_COPY:
0N/A case KeyEvent.VK_PASTE:
0N/A case KeyEvent.VK_CUT:
0N/A allowedGesture = true;
0N/A break;
0N/A case KeyEvent.VK_DELETE:
0N/A allowedGesture = ( keyModifiers == InputEvent.SHIFT_MASK);
0N/A break;
0N/A }
0N/A }
0N/A return allowedGesture;
0N/A }
0N/A
0N/A /**
0N/A * Returns true if e has the permissions to
0N/A * access the system clipboard and if it is allowed gesture (if
0N/A * checkGesture is true)
0N/A *
0N/A * @param e AWTEvent to check
0N/A * @param checkGesture boolean
0N/A */
0N/A private static boolean canEventAccessSystemClipboard(AWTEvent e,
0N/A boolean checkGesture) {
0N/A if (EventQueue.isDispatchThread()) {
0N/A /*
0N/A * Checking event permissions makes sense only for event
0N/A * dispathing thread
0N/A */
0N/A if (e instanceof InputEvent
0N/A && (! checkGesture || isAccessClipboardGesture((InputEvent)e))) {
0N/A return inputEvent_canAccessSystemClipboard((InputEvent)e);
0N/A } else {
0N/A return false;
0N/A }
0N/A } else {
0N/A return true;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns true if EventQueue.getCurrentEvent() has the permissions to
0N/A * access the system clipboard and if it is allowed gesture (if
0N/A * checkGesture true)
0N/A *
0N/A * @param checkGesture boolean
0N/A */
0N/A private static boolean canCurrentEventAccessSystemClipboard(boolean
0N/A checkGesture) {
0N/A AWTEvent event = EventQueue.getCurrentEvent();
0N/A return canEventAccessSystemClipboard(event, checkGesture);
0N/A }
0N/A
0N/A /**
0N/A * see RFE 5012841 [Per AppContect security permissions] for the
0N/A * details
0N/A *
0N/A */
0N/A private static boolean isTrustedContext() {
0N/A return (System.getSecurityManager() == null)
0N/A || (AppContext.getAppContext().
0N/A get(UntrustedClipboardAccess) == null);
0N/A }
0N/A
0N/A public static String displayPropertiesToCSS(Font font, Color fg) {
0N/A StringBuffer rule = new StringBuffer("body {");
0N/A if (font != null) {
0N/A rule.append(" font-family: ");
0N/A rule.append(font.getFamily());
0N/A rule.append(" ; ");
0N/A rule.append(" font-size: ");
0N/A rule.append(font.getSize());
0N/A rule.append("pt ;");
0N/A if (font.isBold()) {
0N/A rule.append(" font-weight: 700 ; ");
0N/A }
0N/A if (font.isItalic()) {
0N/A rule.append(" font-style: italic ; ");
0N/A }
0N/A }
0N/A if (fg != null) {
0N/A rule.append(" color: #");
0N/A if (fg.getRed() < 16) {
0N/A rule.append('0');
0N/A }
0N/A rule.append(Integer.toHexString(fg.getRed()));
0N/A if (fg.getGreen() < 16) {
0N/A rule.append('0');
0N/A }
0N/A rule.append(Integer.toHexString(fg.getGreen()));
0N/A if (fg.getBlue() < 16) {
0N/A rule.append('0');
0N/A }
0N/A rule.append(Integer.toHexString(fg.getBlue()));
0N/A rule.append(" ; ");
0N/A }
0N/A rule.append(" }");
0N/A return rule.toString();
0N/A }
0N/A
0N/A /**
0N/A * Utility method that creates a <code>UIDefaults.LazyValue</code> that
0N/A * creates an <code>ImageIcon</code> <code>UIResource</code> for the
0N/A * specified image file name. The image is loaded using
0N/A * <code>getResourceAsStream</code>, starting with a call to that method
0N/A * on the base class parameter. If it cannot be found, searching will
0N/A * continue through the base class' inheritance hierarchy, up to and
0N/A * including <code>rootClass</code>.
0N/A *
0N/A * @param baseClass the first class to use in searching for the resource
0N/A * @param rootClass an ancestor of <code>baseClass</code> to finish the
0N/A * search at
0N/A * @param imageFile the name of the file to be found
0N/A * @return a lazy value that creates the <code>ImageIcon</code>
0N/A * <code>UIResource</code> for the image,
0N/A * or null if it cannot be found
0N/A */
0N/A public static Object makeIcon(final Class<?> baseClass,
0N/A final Class<?> rootClass,
0N/A final String imageFile) {
0N/A
0N/A return new UIDefaults.LazyValue() {
0N/A public Object createValue(UIDefaults table) {
0N/A /* Copy resource into a byte array. This is
0N/A * necessary because several browsers consider
0N/A * Class.getResource a security risk because it
0N/A * can be used to load additional classes.
0N/A * Class.getResourceAsStream just returns raw
0N/A * bytes, which we can convert to an image.
0N/A */
625N/A byte[] buffer =
0N/A java.security.AccessController.doPrivileged(
625N/A new java.security.PrivilegedAction<byte[]>() {
625N/A public byte[] run() {
0N/A try {
0N/A InputStream resource = null;
0N/A Class<?> srchClass = baseClass;
0N/A
0N/A while (srchClass != null) {
0N/A resource = srchClass.getResourceAsStream(imageFile);
0N/A
0N/A if (resource != null || srchClass == rootClass) {
0N/A break;
0N/A }
0N/A
0N/A srchClass = srchClass.getSuperclass();
0N/A }
0N/A
0N/A if (resource == null) {
0N/A return null;
0N/A }
0N/A
0N/A BufferedInputStream in =
0N/A new BufferedInputStream(resource);
0N/A ByteArrayOutputStream out =
0N/A new ByteArrayOutputStream(1024);
0N/A byte[] buffer = new byte[1024];
0N/A int n;
0N/A while ((n = in.read(buffer)) > 0) {
0N/A out.write(buffer, 0, n);
0N/A }
0N/A in.close();
0N/A out.flush();
0N/A return out.toByteArray();
0N/A } catch (IOException ioe) {
0N/A System.err.println(ioe.toString());
0N/A }
0N/A return null;
0N/A }
0N/A });
0N/A
0N/A if (buffer == null) {
0N/A return null;
0N/A }
0N/A if (buffer.length == 0) {
0N/A System.err.println("warning: " + imageFile +
0N/A " is zero-length");
0N/A return null;
0N/A }
0N/A
0N/A return new ImageIconUIResource(buffer);
0N/A }
0N/A };
0N/A }
0N/A
0N/A /* Used to help decide if AA text rendering should be used, so
0N/A * this local display test should be additionally qualified
0N/A * against whether we have XRender support on both ends of the wire,
0N/A * as with that support remote performance may be good enough to turn
0N/A * on by default. An additional complication there is XRender does not
0N/A * appear capable of performing gamma correction needed for LCD text.
0N/A */
0N/A public static boolean isLocalDisplay() {
760N/A boolean isLocal;
760N/A GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
760N/A if (ge instanceof SunGraphicsEnvironment) {
760N/A isLocal = ((SunGraphicsEnvironment) ge).isDisplayLocal();
760N/A } else {
760N/A isLocal = true;
0N/A }
760N/A return isLocal;
0N/A }
0N/A
0N/A /**
0N/A * Returns an integer from the defaults table. If <code>key</code> does
0N/A * not map to a valid <code>Integer</code>, or can not be convered from
0N/A * a <code>String</code> to an integer, the value 0 is returned.
0N/A *
0N/A * @param key an <code>Object</code> specifying the int.
0N/A * @return the int
0N/A */
0N/A public static int getUIDefaultsInt(Object key) {
0N/A return getUIDefaultsInt(key, 0);
0N/A }
0N/A
0N/A /**
0N/A * Returns an integer from the defaults table that is appropriate
0N/A * for the given locale. If <code>key</code> does not map to a valid
0N/A * <code>Integer</code>, or can not be convered from a <code>String</code>
0N/A * to an integer, the value 0 is returned.
0N/A *
0N/A * @param key an <code>Object</code> specifying the int. Returned value
0N/A * is 0 if <code>key</code> is not available,
0N/A * @param l the <code>Locale</code> for which the int is desired
0N/A * @return the int
0N/A */
0N/A public static int getUIDefaultsInt(Object key, Locale l) {
0N/A return getUIDefaultsInt(key, l, 0);
0N/A }
0N/A
0N/A /**
0N/A * Returns an integer from the defaults table. If <code>key</code> does
0N/A * not map to a valid <code>Integer</code>, or can not be convered from
0N/A * a <code>String</code> to an integer, <code>default</code> is
0N/A * returned.
0N/A *
0N/A * @param key an <code>Object</code> specifying the int. Returned value
0N/A * is 0 if <code>key</code> is not available,
0N/A * @param defaultValue Returned value if <code>key</code> is not available,
0N/A * or is not an Integer
0N/A * @return the int
0N/A */
0N/A public static int getUIDefaultsInt(Object key, int defaultValue) {
0N/A return getUIDefaultsInt(key, null, defaultValue);
0N/A }
0N/A
0N/A /**
0N/A * Returns an integer from the defaults table that is appropriate
0N/A * for the given locale. If <code>key</code> does not map to a valid
0N/A * <code>Integer</code>, or can not be convered from a <code>String</code>
0N/A * to an integer, <code>default</code> is returned.
0N/A *
0N/A * @param key an <code>Object</code> specifying the int. Returned value
0N/A * is 0 if <code>key</code> is not available,
0N/A * @param l the <code>Locale</code> for which the int is desired
0N/A * @param defaultValue Returned value if <code>key</code> is not available,
0N/A * or is not an Integer
0N/A * @return the int
0N/A */
0N/A public static int getUIDefaultsInt(Object key, Locale l, int defaultValue) {
0N/A Object value = UIManager.get(key, l);
0N/A
0N/A if (value instanceof Integer) {
0N/A return ((Integer)value).intValue();
0N/A }
0N/A if (value instanceof String) {
0N/A try {
0N/A return Integer.parseInt((String)value);
0N/A } catch (NumberFormatException nfe) {}
0N/A }
0N/A return defaultValue;
0N/A }
0N/A
0N/A // At this point we need this method here. But we assume that there
0N/A // will be a common method for this purpose in the future releases.
0N/A public static Component compositeRequestFocus(Component component) {
0N/A if (component instanceof Container) {
0N/A Container container = (Container)component;
0N/A if (container.isFocusCycleRoot()) {
0N/A FocusTraversalPolicy policy = container.getFocusTraversalPolicy();
0N/A Component comp = policy.getDefaultComponent(container);
0N/A if (comp!=null) {
0N/A comp.requestFocus();
0N/A return comp;
0N/A }
0N/A }
0N/A Container rootAncestor = container.getFocusCycleRootAncestor();
0N/A if (rootAncestor!=null) {
0N/A FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy();
0N/A Component comp = policy.getComponentAfter(rootAncestor, container);
0N/A
0N/A if (comp!=null && SwingUtilities.isDescendingFrom(comp, container)) {
0N/A comp.requestFocus();
0N/A return comp;
0N/A }
0N/A }
0N/A }
0N/A if (component.isFocusable()) {
0N/A component.requestFocus();
0N/A return component;
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A /**
0N/A * Change focus to the visible component in {@code JTabbedPane}.
0N/A * This is not a general-purpose method and is here only to permit
0N/A * sharing code.
0N/A */
0N/A public static boolean tabbedPaneChangeFocusTo(Component comp) {
0N/A if (comp != null) {
0N/A if (comp.isFocusTraversable()) {
0N/A SwingUtilities2.compositeRequestFocus(comp);
0N/A return true;
0N/A } else if (comp instanceof JComponent
0N/A && ((JComponent)comp).requestDefaultFocus()) {
0N/A
0N/A return true;
0N/A }
0N/A }
0N/A
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Submits a value-returning task for execution on the EDT and
0N/A * returns a Future representing the pending results of the task.
0N/A *
0N/A * @param task the task to submit
0N/A * @return a Future representing pending completion of the task
0N/A * @throws NullPointerException if the task is null
0N/A */
0N/A public static <V> Future<V> submit(Callable<V> task) {
0N/A if (task == null) {
0N/A throw new NullPointerException();
0N/A }
0N/A FutureTask<V> future = new FutureTask<V>(task);
0N/A execute(future);
0N/A return future;
0N/A }
0N/A
0N/A /**
0N/A * Submits a Runnable task for execution on the EDT and returns a
0N/A * Future representing that task.
0N/A *
0N/A * @param task the task to submit
0N/A * @param result the result to return upon successful completion
0N/A * @return a Future representing pending completion of the task,
0N/A * and whose <tt>get()</tt> method will return the given
0N/A * result value upon completion
0N/A * @throws NullPointerException if the task is null
0N/A */
0N/A public static <V> Future<V> submit(Runnable task, V result) {
0N/A if (task == null) {
0N/A throw new NullPointerException();
0N/A }
0N/A FutureTask<V> future = new FutureTask<V>(task, result);
0N/A execute(future);
0N/A return future;
0N/A }
0N/A
0N/A /**
0N/A * Sends a Runnable to the EDT for the execution.
0N/A */
0N/A private static void execute(Runnable command) {
0N/A SwingUtilities.invokeLater(command);
0N/A }
0N/A
0N/A /**
0N/A * Sets the {@code SKIP_CLICK_COUNT} client property on the component
0N/A * if it is an instance of {@code JTextComponent} with a
0N/A * {@code DefaultCaret}. This property, used for text components acting
0N/A * as editors in a table or tree, tells {@code DefaultCaret} how many
0N/A * clicks to skip before starting selection.
0N/A */
0N/A public static void setSkipClickCount(Component comp, int count) {
0N/A if (comp instanceof JTextComponent
0N/A && ((JTextComponent) comp).getCaret() instanceof DefaultCaret) {
0N/A
0N/A ((JTextComponent) comp).putClientProperty(SKIP_CLICK_COUNT, count);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Return the MouseEvent's click count, possibly reduced by the value of
0N/A * the component's {@code SKIP_CLICK_COUNT} client property. Clears
0N/A * the {@code SKIP_CLICK_COUNT} property if the mouse event's click count
0N/A * is 1. In order for clearing of the property to work correctly, there
0N/A * must be a mousePressed implementation on the caller with this
0N/A * call as the first line.
0N/A */
0N/A public static int getAdjustedClickCount(JTextComponent comp, MouseEvent e) {
0N/A int cc = e.getClickCount();
0N/A
0N/A if (cc == 1) {
0N/A comp.putClientProperty(SKIP_CLICK_COUNT, null);
0N/A } else {
0N/A Integer sub = (Integer) comp.getClientProperty(SKIP_CLICK_COUNT);
0N/A if (sub != null) {
0N/A return cc - sub;
0N/A }
0N/A }
0N/A
0N/A return cc;
0N/A }
0N/A
0N/A /**
0N/A * Used by the {@code liesIn} method to return which section
0N/A * the point lies in.
0N/A *
0N/A * @see #liesIn
0N/A */
0N/A public enum Section {
0N/A
0N/A /** The leading section */
0N/A LEADING,
0N/A
0N/A /** The middle section */
0N/A MIDDLE,
0N/A
0N/A /** The trailing section */
0N/A TRAILING
0N/A }
0N/A
0N/A /**
0N/A * This method divides a rectangle into two or three sections along
0N/A * the specified axis and determines which section the given point
0N/A * lies in on that axis; used by drag and drop when calculating drop
0N/A * locations.
0N/A * <p>
0N/A * For two sections, the rectangle is divided equally and the method
0N/A * returns whether the point lies in {@code Section.LEADING} or
0N/A * {@code Section.TRAILING}. For horizontal divisions, the calculation
0N/A * respects component orientation.
0N/A * <p>
0N/A * For three sections, if the rectangle is greater than or equal to
0N/A * 30 pixels in length along the axis, the calculation gives 10 pixels
0N/A * to each of the leading and trailing sections and the remainder to the
0N/A * middle. For smaller sizes, the rectangle is divided equally into three
0N/A * sections.
0N/A * <p>
0N/A * Note: This method assumes that the point is within the bounds of
0N/A * the given rectangle on the specified axis. However, in cases where
0N/A * it isn't, the results still have meaning: {@code Section.MIDDLE}
0N/A * remains the same, {@code Section.LEADING} indicates that the point
0N/A * is in or somewhere before the leading section, and
0N/A * {@code Section.TRAILING} indicates that the point is in or somewhere
0N/A * after the trailing section.
0N/A *
0N/A * @param rect the rectangle
0N/A * @param p the point the check
0N/A * @param horizontal {@code true} to use the horizontal axis,
0N/A * or {@code false} for the vertical axis
0N/A * @param ltr {@code true} for left to right orientation,
0N/A * or {@code false} for right to left orientation;
0N/A * only used for horizontal calculations
0N/A * @param three {@code true} for three sections,
0N/A * or {@code false} for two
0N/A *
0N/A * @return the {@code Section} where the point lies
0N/A *
0N/A * @throws NullPointerException if {@code rect} or {@code p} are
0N/A * {@code null}
0N/A */
0N/A private static Section liesIn(Rectangle rect, Point p, boolean horizontal,
0N/A boolean ltr, boolean three) {
0N/A
0N/A /* beginning of the rectangle on the axis */
0N/A int p0;
0N/A
0N/A /* point on the axis we're interested in */
0N/A int pComp;
0N/A
0N/A /* length of the rectangle on the axis */
0N/A int length;
0N/A
0N/A /* value of ltr if horizontal, else true */
0N/A boolean forward;
0N/A
0N/A if (horizontal) {
0N/A p0 = rect.x;
0N/A pComp = p.x;
0N/A length = rect.width;
0N/A forward = ltr;
0N/A } else {
0N/A p0 = rect.y;
0N/A pComp = p.y;
0N/A length = rect.height;
0N/A forward = true;
0N/A }
0N/A
0N/A if (three) {
0N/A int boundary = (length >= 30) ? 10 : length / 3;
0N/A
0N/A if (pComp < p0 + boundary) {
0N/A return forward ? Section.LEADING : Section.TRAILING;
0N/A } else if (pComp >= p0 + length - boundary) {
0N/A return forward ? Section.TRAILING : Section.LEADING;
0N/A }
0N/A
0N/A return Section.MIDDLE;
0N/A } else {
0N/A int middle = p0 + length / 2;
0N/A if (forward) {
0N/A return pComp >= middle ? Section.TRAILING : Section.LEADING;
0N/A } else {
0N/A return pComp < middle ? Section.TRAILING : Section.LEADING;
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * This method divides a rectangle into two or three sections along
0N/A * the horizontal axis and determines which section the given point
0N/A * lies in; used by drag and drop when calculating drop locations.
0N/A * <p>
0N/A * See the documentation for {@link #liesIn} for more information
0N/A * on how the section is calculated.
0N/A *
0N/A * @param rect the rectangle
0N/A * @param p the point the check
0N/A * @param ltr {@code true} for left to right orientation,
0N/A * or {@code false} for right to left orientation
0N/A * @param three {@code true} for three sections,
0N/A * or {@code false} for two
0N/A *
0N/A * @return the {@code Section} where the point lies
0N/A *
0N/A * @throws NullPointerException if {@code rect} or {@code p} are
0N/A * {@code null}
0N/A */
0N/A public static Section liesInHorizontal(Rectangle rect, Point p,
0N/A boolean ltr, boolean three) {
0N/A return liesIn(rect, p, true, ltr, three);
0N/A }
0N/A
0N/A /**
0N/A * This method divides a rectangle into two or three sections along
0N/A * the vertical axis and determines which section the given point
0N/A * lies in; used by drag and drop when calculating drop locations.
0N/A * <p>
0N/A * See the documentation for {@link #liesIn} for more information
0N/A * on how the section is calculated.
0N/A *
0N/A * @param rect the rectangle
0N/A * @param p the point the check
0N/A * @param three {@code true} for three sections,
0N/A * or {@code false} for two
0N/A *
0N/A * @return the {@code Section} where the point lies
0N/A *
0N/A * @throws NullPointerException if {@code rect} or {@code p} are
0N/A * {@code null}
0N/A */
0N/A public static Section liesInVertical(Rectangle rect, Point p,
0N/A boolean three) {
0N/A return liesIn(rect, p, false, false, three);
0N/A }
2381N/A
2381N/A /**
2381N/A * Maps the index of the column in the view at
2381N/A * {@code viewColumnIndex} to the index of the column
2381N/A * in the table model. Returns the index of the corresponding
2381N/A * column in the model. If {@code viewColumnIndex}
2381N/A * is less than zero, returns {@code viewColumnIndex}.
2381N/A *
2381N/A * @param cm the table model
2381N/A * @param viewColumnIndex the index of the column in the view
2381N/A * @return the index of the corresponding column in the model
2381N/A *
2381N/A * @see JTable#convertColumnIndexToModel(int)
2381N/A * @see javax.swing.plaf.basic.BasicTableHeaderUI
2381N/A */
2381N/A public static int convertColumnIndexToModel(TableColumnModel cm,
2381N/A int viewColumnIndex) {
2381N/A if (viewColumnIndex < 0) {
2381N/A return viewColumnIndex;
2381N/A }
2381N/A return cm.getColumn(viewColumnIndex).getModelIndex();
2381N/A }
2381N/A
2381N/A /**
2381N/A * Maps the index of the column in the {@code cm} at
2381N/A * {@code modelColumnIndex} to the index of the column
2381N/A * in the view. Returns the index of the
2381N/A * corresponding column in the view; returns {@code -1} if this column
2381N/A * is not being displayed. If {@code modelColumnIndex} is less than zero,
2381N/A * returns {@code modelColumnIndex}.
2381N/A *
2381N/A * @param cm the table model
2381N/A * @param modelColumnIndex the index of the column in the model
2381N/A * @return the index of the corresponding column in the view
2381N/A *
2381N/A * @see JTable#convertColumnIndexToView(int)
2381N/A * @see javax.swing.plaf.basic.BasicTableHeaderUI
2381N/A */
2381N/A public static int convertColumnIndexToView(TableColumnModel cm,
2381N/A int modelColumnIndex) {
2381N/A if (modelColumnIndex < 0) {
2381N/A return modelColumnIndex;
2381N/A }
2381N/A for (int column = 0; column < cm.getColumnCount(); column++) {
2381N/A if (cm.getColumn(column).getModelIndex() == modelColumnIndex) {
2381N/A return column;
2381N/A }
2381N/A }
2381N/A return -1;
2381N/A }
5653N/A
5653N/A public static int getSystemMnemonicKeyMask() {
5653N/A Toolkit toolkit = Toolkit.getDefaultToolkit();
5653N/A if (toolkit instanceof SunToolkit) {
5653N/A return ((SunToolkit) toolkit).getFocusAcceleratorKeyMask();
5653N/A }
5653N/A return InputEvent.ALT_MASK;
5653N/A }
0N/A}