6797139: JButton title is truncating for some strings irrespective of preferred size
Reviewed-by: peterz
This commit is contained in:
parent
3ef90fd6fd
commit
8db0c57ad0
@ -999,24 +999,20 @@ public class SwingUtilities implements SwingConstants
|
||||
textR.height = (int) v.getPreferredSpan(View.Y_AXIS);
|
||||
} else {
|
||||
textR.width = SwingUtilities2.stringWidth(c, fm, text);
|
||||
|
||||
// Take into account the left and right side bearings.
|
||||
// This gives more space than it is actually needed,
|
||||
// but there are two reasons:
|
||||
// 1. If we set the width to the actual bounds,
|
||||
// all callers would have to account for the bearings
|
||||
// themselves. NOTE: all pref size calculations don't do it.
|
||||
// 2. You can do a drawString at the returned location
|
||||
// and the text won't be clipped.
|
||||
lsb = SwingUtilities2.getLeftSideBearing(c, fm, text);
|
||||
if (lsb < 0) {
|
||||
// If lsb is negative, add it to the width and later
|
||||
// adjust the x location. This gives more space than is
|
||||
// actually needed.
|
||||
// This is done like this for two reasons:
|
||||
// 1. If we set the width to the actual bounds all
|
||||
// callers would have to account for negative lsb
|
||||
// (pref size calculations ONLY look at width of
|
||||
// textR)
|
||||
// 2. You can do a drawString at the returned location
|
||||
// and the text won't be clipped.
|
||||
textR.width -= lsb;
|
||||
}
|
||||
rsb = SwingUtilities2.getRightSideBearing(c, fm, text);
|
||||
if (rsb > 0) {
|
||||
textR.width += rsb;
|
||||
}
|
||||
|
||||
if (textR.width > availTextWidth) {
|
||||
text = SwingUtilities2.clipString(c, fm, text,
|
||||
availTextWidth);
|
||||
|
@ -195,7 +195,7 @@ class SynthMenuItemLayoutHelper extends MenuItemLayoutHelper {
|
||||
getHorizontalAlignment(), getVerticalAlignment(),
|
||||
getHorizontalTextPosition(), getVerticalTextPosition(),
|
||||
getViewRect(), iconRect, textRect, getGap());
|
||||
textRect.width += getLeftTextExtraWidth() + getRightTextExtraWidth();
|
||||
textRect.width += getLeftTextExtraWidth();
|
||||
Rectangle labelRect = iconRect.union(textRect);
|
||||
getLabelSize().setHeight(labelRect.height);
|
||||
getLabelSize().setWidth(labelRect.width);
|
||||
|
@ -84,7 +84,6 @@ public class MenuItemLayoutHelper {
|
||||
private int minTextOffset;
|
||||
|
||||
private int leftTextExtraWidth;
|
||||
private int rightTextExtraWidth;
|
||||
|
||||
private Rectangle viewRect;
|
||||
|
||||
@ -157,7 +156,6 @@ public class MenuItemLayoutHelper {
|
||||
|
||||
private void calcExtraWidths() {
|
||||
leftTextExtraWidth = getLeftExtraWidth(text);
|
||||
rightTextExtraWidth = getRightExtraWidth(text);
|
||||
}
|
||||
|
||||
private int getLeftExtraWidth(String str) {
|
||||
@ -169,15 +167,6 @@ public class MenuItemLayoutHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private int getRightExtraWidth(String str) {
|
||||
int rsb = SwingUtilities2.getRightSideBearing(mi, fm, str);
|
||||
if (rsb > 0) {
|
||||
return rsb;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void setOriginalWidths() {
|
||||
iconSize.origWidth = iconSize.width;
|
||||
textSize.origWidth = textSize.width;
|
||||
@ -313,7 +302,7 @@ public class MenuItemLayoutHelper {
|
||||
verticalAlignment, horizontalAlignment,
|
||||
verticalTextPosition, horizontalTextPosition,
|
||||
viewRect, iconRect, textRect, gap);
|
||||
textRect.width += leftTextExtraWidth + rightTextExtraWidth;
|
||||
textRect.width += leftTextExtraWidth;
|
||||
Rectangle labelRect = iconRect.union(textRect);
|
||||
labelSize.height = labelRect.height;
|
||||
labelSize.width = labelRect.width;
|
||||
@ -1121,10 +1110,6 @@ public class MenuItemLayoutHelper {
|
||||
return leftTextExtraWidth;
|
||||
}
|
||||
|
||||
public int getRightTextExtraWidth() {
|
||||
return rightTextExtraWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false if the component is a JMenu and it is a top
|
||||
* level menu (on the menubar).
|
||||
|
@ -27,7 +27,6 @@ package sun.swing;
|
||||
|
||||
import java.security.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.awt.*;
|
||||
import static java.awt.RenderingHints.*;
|
||||
import java.awt.event.*;
|
||||
@ -78,17 +77,23 @@ public class SwingUtilities2 {
|
||||
public static final Object LAF_STATE_KEY =
|
||||
new StringBuffer("LookAndFeel State");
|
||||
|
||||
// Most of applications use 10 or less fonts simultaneously
|
||||
private static final int STRONG_BEARING_CACHE_SIZE = 10;
|
||||
// Strong cache for the left and right side bearings
|
||||
// for STRONG_BEARING_CACHE_SIZE most recently used fonts.
|
||||
private static BearingCacheEntry[] strongBearingCache =
|
||||
new BearingCacheEntry[STRONG_BEARING_CACHE_SIZE];
|
||||
// Next index to insert an entry into the strong bearing cache
|
||||
private static int strongBearingCacheNextIndex = 0;
|
||||
// Soft cache for the left and right side bearings
|
||||
private static Set<SoftReference<BearingCacheEntry>> softBearingCache =
|
||||
new HashSet<SoftReference<BearingCacheEntry>>();
|
||||
// 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);
|
||||
@ -183,6 +188,10 @@ public class SwingUtilities2 {
|
||||
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.
|
||||
*
|
||||
@ -226,7 +235,9 @@ public class SwingUtilities2 {
|
||||
|
||||
/**
|
||||
* Returns the left side bearing of the first character of string. The
|
||||
* left side bearing is calculated from the passed in FontMetrics.
|
||||
* left side bearing is calculated from the passed in
|
||||
* FontMetrics. If the passed in String is less than one
|
||||
* character, this will throw a StringIndexOutOfBoundsException exception.
|
||||
*
|
||||
* @param c JComponent that will display the string
|
||||
* @param fm FontMetrics used to measure the String width
|
||||
@ -234,14 +245,11 @@ public class SwingUtilities2 {
|
||||
*/
|
||||
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 specified character. The
|
||||
* 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
|
||||
@ -250,105 +258,37 @@ public class SwingUtilities2 {
|
||||
*/
|
||||
public static int getLeftSideBearing(JComponent c, FontMetrics fm,
|
||||
char firstChar) {
|
||||
return getBearing(c, fm, firstChar, true);
|
||||
}
|
||||
int charIndex = (int) firstChar;
|
||||
if (charIndex < MAX_CHAR_INDEX && charIndex >= MIN_CHAR_INDEX) {
|
||||
byte[] lsbs = null;
|
||||
|
||||
/**
|
||||
* Returns the right side bearing of the last character of string. The
|
||||
* right 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 string String to get the right side bearing for.
|
||||
*/
|
||||
public static int getRightSideBearing(JComponent c, FontMetrics fm,
|
||||
String string) {
|
||||
if ((string == null) || (string.length() == 0)) {
|
||||
return 0;
|
||||
}
|
||||
return getRightSideBearing(c, fm, string.charAt(string.length() - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the right side bearing of the specified character. The
|
||||
* right 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 lastChar Character to get the right side bearing for.
|
||||
*/
|
||||
public static int getRightSideBearing(JComponent c, FontMetrics fm,
|
||||
char lastChar) {
|
||||
return getBearing(c, fm, lastChar, false);
|
||||
}
|
||||
|
||||
/* Calculates the left and right side bearing for a character.
|
||||
* Strongly caches bearings for STRONG_BEARING_CACHE_SIZE
|
||||
* most recently used Fonts and softly caches as many as GC allows.
|
||||
*/
|
||||
private static int getBearing(JComponent comp, FontMetrics fm, char c,
|
||||
boolean isLeftBearing) {
|
||||
if (fm == null) {
|
||||
if (comp == null) {
|
||||
return 0;
|
||||
} else {
|
||||
fm = comp.getFontMetrics(comp.getFont());
|
||||
}
|
||||
}
|
||||
synchronized (SwingUtilities2.class) {
|
||||
BearingCacheEntry entry = null;
|
||||
BearingCacheEntry searchKey = new BearingCacheEntry(fm);
|
||||
// See if we already have an entry in the strong cache
|
||||
for (BearingCacheEntry cacheEntry : strongBearingCache) {
|
||||
if (searchKey.equals(cacheEntry)) {
|
||||
entry = cacheEntry;
|
||||
break;
|
||||
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 in the soft cache
|
||||
if (entry == null) {
|
||||
Iterator<SoftReference<BearingCacheEntry>> iter =
|
||||
softBearingCache.iterator();
|
||||
while (iter.hasNext()) {
|
||||
BearingCacheEntry cacheEntry = iter.next().get();
|
||||
if (cacheEntry == null) {
|
||||
// Remove discarded soft reference from the cache
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
// See if we already have an entry for this pair
|
||||
for (LSBCacheEntry cacheEntry : fontCache) {
|
||||
if (searchKey.equals(cacheEntry)) {
|
||||
entry = cacheEntry;
|
||||
putEntryInStrongCache(entry);
|
||||
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);
|
||||
}
|
||||
if (entry == null) {
|
||||
// No entry, add it
|
||||
entry = searchKey;
|
||||
cacheEntry(entry);
|
||||
}
|
||||
return (isLeftBearing)
|
||||
? entry.getLeftSideBearing(c)
|
||||
: entry.getRightSideBearing(c);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized static void cacheEntry(BearingCacheEntry entry) {
|
||||
// Move the oldest entry from the strong cache into the soft cache
|
||||
BearingCacheEntry oldestEntry =
|
||||
strongBearingCache[strongBearingCacheNextIndex];
|
||||
if (oldestEntry != null) {
|
||||
softBearingCache.add(new SoftReference<BearingCacheEntry>(oldestEntry));
|
||||
}
|
||||
// Put entry in the strong cache
|
||||
putEntryInStrongCache(entry);
|
||||
}
|
||||
|
||||
private synchronized static void putEntryInStrongCache(BearingCacheEntry entry) {
|
||||
strongBearingCache[strongBearingCacheNextIndex] = entry;
|
||||
strongBearingCacheNextIndex = (strongBearingCacheNextIndex + 1)
|
||||
% STRONG_BEARING_CACHE_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1063,99 +1003,72 @@ public class SwingUtilities2 {
|
||||
}
|
||||
|
||||
/**
|
||||
* BearingCacheEntry is used to cache left and right character bearings
|
||||
* for a particular <code>Font</code> and <code>FontRenderContext</code>.
|
||||
* LSBCacheEntry is used to cache the left side bearing (lsb) for
|
||||
* a particular <code>Font</code> and <code>FontRenderContext</code>.
|
||||
* This only caches characters that fall in the range
|
||||
* <code>MIN_CHAR_INDEX</code> to <code>MAX_CHAR_INDEX</code>.
|
||||
*/
|
||||
private static class BearingCacheEntry {
|
||||
private FontMetrics fontMetrics;
|
||||
private Font font;
|
||||
private FontRenderContext frc;
|
||||
private Map<Character, Short> cache;
|
||||
// Used for the creation of a GlyphVector
|
||||
private static class LSBCacheEntry {
|
||||
// Used to indicate a particular entry in lsb has not been set.
|
||||
private static final byte UNSET = Byte.MAX_VALUE;
|
||||
// Used in creating a GlyphVector to get the lsb
|
||||
private static final char[] oneChar = new char[1];
|
||||
|
||||
public BearingCacheEntry(FontMetrics fontMetrics) {
|
||||
this.fontMetrics = fontMetrics;
|
||||
this.font = fontMetrics.getFont();
|
||||
this.frc = fontMetrics.getFontRenderContext();
|
||||
this.cache = new HashMap<Character, Short>();
|
||||
assert (font != null && frc != null);
|
||||
private byte[] lsbCache;
|
||||
private Font font;
|
||||
private FontRenderContext frc;
|
||||
|
||||
|
||||
public LSBCacheEntry(FontRenderContext frc, Font font) {
|
||||
lsbCache = new byte[MAX_CHAR_INDEX - MIN_CHAR_INDEX];
|
||||
reset(frc, font);
|
||||
|
||||
}
|
||||
|
||||
public void reset(FontRenderContext frc, Font font) {
|
||||
this.font = font;
|
||||
this.frc = frc;
|
||||
for (int counter = lsbCache.length - 1; counter >= 0; counter--) {
|
||||
lsbCache[counter] = UNSET;
|
||||
}
|
||||
}
|
||||
|
||||
public int getLeftSideBearing(char aChar) {
|
||||
Short bearing = cache.get(aChar);
|
||||
if (bearing == null) {
|
||||
bearing = calcBearing(aChar);
|
||||
cache.put(aChar, bearing);
|
||||
int index = aChar - MIN_CHAR_INDEX;
|
||||
assert (index >= 0 && index < (MAX_CHAR_INDEX - MIN_CHAR_INDEX));
|
||||
byte lsb = lsbCache[index];
|
||||
if (lsb == UNSET) {
|
||||
oneChar[0] = aChar;
|
||||
GlyphVector gv = font.createGlyphVector(frc, oneChar);
|
||||
lsb = (byte) gv.getGlyphPixelBounds(0, frc, 0f, 0f).x;
|
||||
if (lsb < 0) {
|
||||
/* HRGB/HBGR LCD glyph images will always have a pixel
|
||||
* on the left used in colour fringe reduction.
|
||||
* Text rendering positions this correctly but here
|
||||
* we are using the glyph image to adjust that position
|
||||
* so must account for it.
|
||||
*/
|
||||
Object aaHint = frc.getAntiAliasingHint();
|
||||
if (aaHint == VALUE_TEXT_ANTIALIAS_LCD_HRGB ||
|
||||
aaHint == VALUE_TEXT_ANTIALIAS_LCD_HBGR) {
|
||||
lsb++;
|
||||
}
|
||||
}
|
||||
lsbCache[index] = lsb;
|
||||
}
|
||||
return ((0xFF00 & bearing) >>> 8) - 127;
|
||||
}
|
||||
return lsb;
|
||||
|
||||
public int getRightSideBearing(char aChar) {
|
||||
Short bearing = cache.get(aChar);
|
||||
if (bearing == null) {
|
||||
bearing = calcBearing(aChar);
|
||||
cache.put(aChar, bearing);
|
||||
}
|
||||
return (0xFF & bearing) - 127;
|
||||
}
|
||||
|
||||
/* Calculates left and right side bearings for a character.
|
||||
* Makes an assumption that bearing is a value between -127 and +127.
|
||||
* Stores LSB and RSB as single two-byte number (short):
|
||||
* LSB is the high byte, RSB is the low byte.
|
||||
*/
|
||||
private short calcBearing(char aChar) {
|
||||
oneChar[0] = aChar;
|
||||
GlyphVector gv = font.createGlyphVector(frc, oneChar);
|
||||
Rectangle pixelBounds = gv.getGlyphPixelBounds(0, frc, 0f, 0f);
|
||||
|
||||
// Get bearings
|
||||
int lsb = pixelBounds.x;
|
||||
int rsb = pixelBounds.width - fontMetrics.charWidth(aChar);
|
||||
|
||||
/* HRGB/HBGR LCD glyph images will always have a pixel
|
||||
* on the left and a pixel on the right
|
||||
* used in colour fringe reduction.
|
||||
* Text rendering positions this correctly but here
|
||||
* we are using the glyph image to adjust that position
|
||||
* so must account for it.
|
||||
*/
|
||||
if (lsb < 0) {
|
||||
Object aaHint = frc.getAntiAliasingHint();
|
||||
if (aaHint == VALUE_TEXT_ANTIALIAS_LCD_HRGB ||
|
||||
aaHint == VALUE_TEXT_ANTIALIAS_LCD_HBGR) {
|
||||
lsb++;
|
||||
}
|
||||
}
|
||||
if (rsb > 0) {
|
||||
Object aaHint = frc.getAntiAliasingHint();
|
||||
if (aaHint == VALUE_TEXT_ANTIALIAS_LCD_HRGB ||
|
||||
aaHint == VALUE_TEXT_ANTIALIAS_LCD_HBGR) {
|
||||
rsb--;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that LSB and RSB are valid (see 6472972)
|
||||
if (lsb < -127 || lsb > 127) {
|
||||
lsb = 0;
|
||||
}
|
||||
if (rsb < -127 || rsb > 127) {
|
||||
rsb = 0;
|
||||
}
|
||||
|
||||
int bearing = ((lsb + 127) << 8) + (rsb + 127);
|
||||
return (short)bearing;
|
||||
}
|
||||
|
||||
public boolean equals(Object entry) {
|
||||
if (entry == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(entry instanceof BearingCacheEntry)) {
|
||||
if (!(entry instanceof LSBCacheEntry)) {
|
||||
return false;
|
||||
}
|
||||
BearingCacheEntry oEntry = (BearingCacheEntry)entry;
|
||||
LSBCacheEntry oEntry = (LSBCacheEntry) entry;
|
||||
return (font.equals(oEntry.font) &&
|
||||
frc.equals(oEntry.frc));
|
||||
}
|
||||
@ -1172,7 +1085,6 @@ public class SwingUtilities2 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* here goes the fix for 4856343 [Problem with applet interaction
|
||||
* with system selection clipboard]
|
||||
@ -1181,36 +1093,34 @@ public class SwingUtilities2 {
|
||||
* are to be performed
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* checks the security permissions for accessing system clipboard
|
||||
*
|
||||
* for untrusted context (see isTrustedContext) checks the
|
||||
* permissions for the current event being handled
|
||||
*
|
||||
*/
|
||||
public static boolean canAccessSystemClipboard() {
|
||||
boolean canAccess = false;
|
||||
if (!GraphicsEnvironment.isHeadless()) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
canAccess = true;
|
||||
} else {
|
||||
try {
|
||||
sm.checkSystemClipboardAccess();
|
||||
canAccess = true;
|
||||
} catch (SecurityException e) {
|
||||
}
|
||||
if (canAccess && ! isTrustedContext()) {
|
||||
canAccess = canCurrentEventAccessSystemClipboard(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return canAccess;
|
||||
}
|
||||
|
||||
* checks the security permissions for accessing system clipboard
|
||||
*
|
||||
* for untrusted context (see isTrustedContext) checks the
|
||||
* permissions for the current event being handled
|
||||
*
|
||||
*/
|
||||
public static boolean canAccessSystemClipboard() {
|
||||
boolean canAccess = false;
|
||||
if (!GraphicsEnvironment.isHeadless()) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
canAccess = true;
|
||||
} else {
|
||||
try {
|
||||
sm.checkSystemClipboardAccess();
|
||||
canAccess = true;
|
||||
} catch (SecurityException e) {
|
||||
}
|
||||
if (canAccess && ! isTrustedContext()) {
|
||||
canAccess = canCurrentEventAccessSystemClipboard(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return canAccess;
|
||||
}
|
||||
/**
|
||||
* Returns true if EventQueue.getCurrentEvent() has the permissions to
|
||||
* Returns true if EventQueue.getCurrentEvent() has the permissions to
|
||||
* access the system clipboard
|
||||
*/
|
||||
public static boolean canCurrentEventAccessSystemClipboard() {
|
||||
|
62
jdk/test/javax/swing/SwingUtilities/6797139/bug6797139.java
Normal file
62
jdk/test/javax/swing/SwingUtilities/6797139/bug6797139.java
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. 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.
|
||||
*
|
||||
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
*
|
||||
* @bug 6797139
|
||||
* @author Alexander Potochkin
|
||||
* @summary tests that JButton's text is not incorrectly truncated
|
||||
*/
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.basic.BasicButtonUI;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public class bug6797139 {
|
||||
|
||||
private static void createGui() {
|
||||
JButton b = new JButton("Probably");
|
||||
b.setUI(new BasicButtonUI() {
|
||||
protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) {
|
||||
super.paintText(g, b, textRect, text);
|
||||
if (text.endsWith("...")) {
|
||||
throw new RuntimeException("Text is truncated!");
|
||||
}
|
||||
}
|
||||
});
|
||||
b.setSize(b.getPreferredSize());
|
||||
BufferedImage image = new BufferedImage(b.getWidth(), b.getHeight(),
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics g = image.getGraphics();
|
||||
b.paint(g);
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
createGui();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user