/*
* %W% %E%
*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
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.print.PrinterGraphics;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import javax.swing.*;
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.print.ProxyPrintGraphics;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import java.io.*;
import java.util.*;
import sun.font.FontDesignMetrics;
import sun.font.FontManager;
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.
*
* @version %I% %G%
*/
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 Object(); // 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 Object SKIP_CLICK_COUNT = new Object(); // 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];
}
/**
* 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 FontManager.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 passe