I fixed the method SwingUtilities.layoutCompoundLabel() so that it
passes the Intel and Mauve testsuite completely (except for some mauve
tests that also fail on the JDK). Also, I have taken care to make it as
efficient as possible, because that method is used in layouting and
painting of a couple of component UIs.
Unfortunately, these UIs have been coded to match the wrong behaviour
that we had in this method before. I needed to adjust all the UIs that
use this method. While doing so, I changed these UIs to use cached
Rectangles (that is in part the point of this method).
I also added the feature of trimming oversize strings, so that a 'very
very very long String' will be trimmed to 'very very ve...' when it
doesn't fit on the component.
Note that the JTabbedPane is broken now as it uses the
SwingUtilities.layoutCompoundLabel() in the wrong way too. I didn't fix
it up because I know that Robert is working on it and I want to talk to
him first.
2006-08-17 Roman Kennke <[EMAIL PROTECTED]>
* javax/swing/SwingUtilities.java
(clipString): New helper method for trimming strings.
(layoutCompoundLabelImpl): Fixed algorithm to conform
testsuites. Trim text if it's too long. Avoid creating
new Rectangles. Optimized for performance.
(layoutCompoundLabel): Use switch rather then if-else-chain.
* javax/swing/plaf/basic/BasicButtonUI.java
(viewR): New field.
(iconR): New field.
(textR): New field.
(paint): Reset and use cached rectangles. Only call paintIcon()
if icon is not null. Don't call paintButtonPressed() when
button is selected, only when it is both armed and pressed.
* javax/swing/plaf/basic/BasicGraphicsUtils.java
(getPreferredButtonSize): Reused cached rectangles rather
then creating new ones. Don't create new Rectangle via
Rectangle.union().
* javax/swing/plaf/basic/BasicLabelUI.java
(getPreferredSize): Correctly reset cached rectangles. Especially
the view rect must have a big size to give it room for layouting.
Short cut layout when text == null.
(paint): Correctly reset cached rectangles.
* javax/swing/plaf/basic/BasicMenuItemUI.java
(resetRectangles): New helper method.
(getPreferredMenuItemSize): Correctly reset the cached rectangles.
(paintMenuItem): Correctly reset the cached rectangles.
* javax/swing/plaf/basic/BasicRadioButtonUI.java
(getPreferredSize): Use cached Rectangle objects and initialize
them correctly.
(paint): Use cached Rectangle objects and initialize
them correctly.
/Roman
Index: javax/swing/SwingUtilities.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/SwingUtilities.java,v
retrieving revision 1.56
diff -u -1 -2 -r1.56 SwingUtilities.java
--- javax/swing/SwingUtilities.java 4 Aug 2006 11:09:11 -0000 1.56
+++ javax/swing/SwingUtilities.java 17 Aug 2006 14:44:56 -0000
@@ -31,25 +31,24 @@
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package javax.swing;
import java.applet.Applet;
import java.awt.Component;
-import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
@@ -712,56 +711,53 @@
int verticalAlignment,
int horizontalAlignment,
int verticalTextPosition,
int horizontalTextPosition,
Rectangle viewR,
Rectangle iconR,
Rectangle textR,
int textIconGap)
{
// Fix up the orientation-based horizontal positions.
- if (horizontalTextPosition == LEADING)
- {
- if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT)
- horizontalTextPosition = RIGHT;
- else
- horizontalTextPosition = LEFT;
- }
- else if (horizontalTextPosition == TRAILING)
+ boolean ltr = true;
+ if (c != null && ! c.getComponentOrientation().isLeftToRight())
+ ltr = false;
+
+ switch (horizontalTextPosition)
{
- if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT)
- horizontalTextPosition = LEFT;
- else
- horizontalTextPosition = RIGHT;
+ case LEADING:
+ horizontalTextPosition = ltr ? LEFT : RIGHT;
+ break;
+ case TRAILING:
+ horizontalTextPosition = ltr ? RIGHT : LEFT;
+ break;
+ default:
+ // Nothing to do in the other cases.
}
// Fix up the orientation-based alignments.
-
- if (horizontalAlignment == LEADING)
- {
- if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT)
- horizontalAlignment = RIGHT;
- else
- horizontalAlignment = LEFT;
- }
- else if (horizontalAlignment == TRAILING)
+ switch (horizontalAlignment)
{
- if (c.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT)
- horizontalAlignment = LEFT;
- else
- horizontalAlignment = RIGHT;
+ case LEADING:
+ horizontalAlignment = ltr ? LEFT : RIGHT;
+ break;
+ case TRAILING:
+ horizontalAlignment = ltr ? RIGHT : LEFT;
+ break;
+ default:
+ // Nothing to do in the other cases.
}
-
+
return layoutCompoundLabelImpl(c, fm, text, icon,
verticalAlignment,
horizontalAlignment,
verticalTextPosition,
horizontalTextPosition,
viewR, iconR, textR, textIconGap);
}
/**
* <p>Layout a "compound label" consisting of a text string and an icon
* which is to be placed near the rendered text. Once the text and icon
* are laid out, the text rectangle and icon rectangle parameters are
@@ -912,131 +908,177 @@
if (icon == null)
{
textIconGap = 0;
iconR.width = 0;
iconR.height = 0;
}
else
{
iconR.width = icon.getIconWidth();
iconR.height = icon.getIconHeight();
}
+
if (text == null || text.equals(""))
{
textIconGap = 0;
textR.width = 0;
textR.height = 0;
+ text = "";
}
else
{
+ int availableWidth = viewR.width;
+ if (horizontalTextPosition != CENTER)
+ availableWidth -= iconR.width + textIconGap;
View html = c == null ? null
: (View) c.getClientProperty(BasicHTML.propertyKey);
if (html != null)
{
textR.width = (int) html.getPreferredSpan(View.X_AXIS);
+ textR.width = Math.min(availableWidth, textR.width);
textR.height = (int) html.getPreferredSpan(View.Y_AXIS);
}
else
{
int fromIndex = 0;
textR.width = fm.stringWidth(text);
- textR.height = fm.getHeight();
- while (text.indexOf('\n', fromIndex) != -1)
+ textR.height = fm.getHeight();
+ if (textR.width > availableWidth)
{
- textR.height += fm.getHeight();
- fromIndex = text.indexOf('\n', fromIndex) + 1;
+ text = clipString(c, fm, text, availableWidth);
+ textR.width = fm.stringWidth(text);
}
}
}
- // Work out the position of text and icon, assuming the top-left coord
+ // Work out the position of text, assuming the top-left coord
// starts at (0,0). We will fix that up momentarily, after these
// "position" decisions are made and we look at alignment.
- switch (horizontalTextPosition)
+ switch (verticalTextPosition)
{
- case LEFT:
- textR.x = 0;
- iconR.x = textR.width + textIconGap;
+ case TOP:
+ textR.y = horizontalTextPosition == CENTER ?
+ - textR.height - textIconGap : 0;
break;
- case RIGHT:
- iconR.x = 0;
- textR.x = iconR.width + textIconGap;
+ case BOTTOM:
+ textR.y = horizontalTextPosition == CENTER ?
+ iconR.height + textIconGap : iconR.height - textR.height;
break;
case CENTER:
- int centerLine = Math.max(textR.width, iconR.width) / 2;
- textR.x = centerLine - textR.width/2;
- iconR.x = centerLine - iconR.width/2;
+ textR.y = iconR.height / 2 - textR.height / 2;
break;
}
- switch (verticalTextPosition)
+ switch (horizontalTextPosition)
{
- case TOP:
- textR.y = 0;
- iconR.y = (horizontalTextPosition == CENTER
- ? textR.height + textIconGap : 0);
+ case LEFT:
+ textR.x = -(textR.width + textIconGap);
break;
- case BOTTOM:
- iconR.y = 0;
- textR.y = (horizontalTextPosition == CENTER
- ? iconR.height + textIconGap
- : Math.max(iconR.height - textR.height, 0));
+ case RIGHT:
+ textR.x = iconR.width + textIconGap;
break;
case CENTER:
- int centerLine = Math.max(textR.height, iconR.height) / 2;
- textR.y = centerLine - textR.height/2;
- iconR.y = centerLine - iconR.height/2;
+ textR.x = iconR.width / 2 - textR.width / 2;
break;
}
+
// The two rectangles are laid out correctly now, but only assuming
// that their upper left corner is at (0,0). If we have any alignment other
// than TOP and LEFT, we need to adjust them.
- Rectangle u = textR.union(iconR);
- int horizontalAdjustment = viewR.x;
- int verticalAdjustment = viewR.y;
+ // These coordinates specify the rectangle that contains both the
+ // icon and text. Move it so that it fullfills the alignment properties.
+ int lx = Math.min(iconR.x, textR.x);
+ int lw = Math.max(iconR.x + iconR.width, textR.x + textR.width) - lx;
+ int ly = Math.min(iconR.y, textR.y);
+ int lh = Math.max(iconR.y + iconR.height, textR.y + textR.height) - ly;
+ int horizontalAdjustment = 0;
+ int verticalAdjustment = 0;
switch (verticalAlignment)
{
case TOP:
+ verticalAdjustment = viewR.y - ly;
break;
case BOTTOM:
- verticalAdjustment += (viewR.height - u.height);
+ verticalAdjustment = viewR.y + viewR.height - ly - lh;
break;
case CENTER:
- verticalAdjustment += ((viewR.height/2) - (u.height/2));
+ verticalAdjustment = viewR.y + viewR.height / 2 - ly - lh / 2;
break;
}
switch (horizontalAlignment)
{
case LEFT:
+ horizontalAdjustment = viewR.x - lx;
break;
case RIGHT:
- horizontalAdjustment += (viewR.width - u.width);
+ horizontalAdjustment = viewR.x + viewR.width - lx - lw;
break;
case CENTER:
- horizontalAdjustment += ((viewR.width/2) - (u.width/2));
+ horizontalAdjustment = (viewR.x + (viewR.width / 2)) - (lx + (lw / 2));
break;
}
-
iconR.x += horizontalAdjustment;
iconR.y += verticalAdjustment;
textR.x += horizontalAdjustment;
textR.y += verticalAdjustment;
return text;
}
+ /**
+ * The method clips the specified string so that it fits into the
+ * available width. It is only called when the text really doesn't fit,
+ * so we don't need to check that again.
+ *
+ * @param c the component
+ * @param fm the font metrics
+ * @param text the text
+ * @param availableWidth the available width
+ *
+ * @return the clipped string
+ */
+ private static String clipString(JComponent c, FontMetrics fm, String text,
+ int availableWidth)
+ {
+ String dots = "...";
+ int dotsWidth = fm.stringWidth(dots);
+ char[] string = text.toCharArray();
+ int endIndex = string.length;
+ while (fm.charsWidth(string, 0, endIndex) + dotsWidth > availableWidth
+ && endIndex > 0)
+ endIndex--;
+ String clipped;
+ if (string.length >= endIndex + 3)
+ {
+ string[endIndex] = '.';
+ string[endIndex + 1] = '.';
+ string[endIndex + 2] = '.';
+ clipped = new String(string, 0, endIndex + 3);
+ }
+ else
+ {
+ char[] clippedChars = new char[string.length + 3];
+ System.arraycopy(string, 0, clippedChars, 0, string.length);
+ clippedChars[endIndex] = '.';
+ clippedChars[endIndex + 1] = '.';
+ clippedChars[endIndex + 2] = '.';
+ clipped = new String(clippedChars, 0, endIndex + 3);
+ }
+ return clipped;
+ }
+
/**
* Calls [EMAIL PROTECTED] java.awt.EventQueue#invokeLater} with the
* specified [EMAIL PROTECTED] Runnable}.
*/
public static void invokeLater(Runnable doRun)
{
java.awt.EventQueue.invokeLater(doRun);
}
/**
* Calls [EMAIL PROTECTED] java.awt.EventQueue#invokeAndWait} with the
* specified [EMAIL PROTECTED] Runnable}.
Index: javax/swing/plaf/basic/BasicButtonUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicButtonUI.java,v
retrieving revision 1.40
diff -u -1 -2 -r1.40 BasicButtonUI.java
--- javax/swing/plaf/basic/BasicButtonUI.java 4 Aug 2006 11:09:11 -0000 1.40
+++ javax/swing/plaf/basic/BasicButtonUI.java 17 Aug 2006 14:44:56 -0000
@@ -33,46 +33,65 @@
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package javax.swing.plaf.basic;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
+import java.awt.Insets;
import java.awt.Rectangle;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.ButtonUI;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.text.View;
/**
* A UI delegate for the [EMAIL PROTECTED] JButton} component.
*/
public class BasicButtonUI extends ButtonUI
{
/**
+ * Cached rectangle for layouting the label. Used in paint() and
+ * BasicGraphicsUtils.getPreferredButtonSize().
+ */
+ static Rectangle viewR = new Rectangle();
+
+ /**
+ * Cached rectangle for layouting the label. Used in paint() and
+ * BasicGraphicsUtils.getPreferredButtonSize().
+ */
+ static Rectangle iconR = new Rectangle();
+
+ /**
+ * Cached rectangle for layouting the label. Used in paint() and
+ * BasicGraphicsUtils.getPreferredButtonSize().
+ */
+ static Rectangle textR = new Rectangle();
+
+ /**
* A constant used to pad out elements in the button's layout and
* preferred size calculations.
*/
protected int defaultTextIconGap = 4;
/**
* A constant added to the defaultTextIconGap to adjust the text
* within this particular button.
*/
protected int defaultTextShiftOffset;
private int textShiftOffset;
@@ -369,62 +388,68 @@
/**
* Paint the component, which is an [EMAIL PROTECTED] AbstractButton}, according to
* its current state.
*
* @param g The graphics context to paint with
* @param c The component to paint the state of
*/
public void paint(Graphics g, JComponent c)
{
AbstractButton b = (AbstractButton) c;
- Rectangle tr = new Rectangle();
- Rectangle ir = new Rectangle();
- Rectangle vr = new Rectangle();
+ Insets i = c.getInsets();
+ viewR.x = i.left;
+ viewR.y = i.top;
+ viewR.width = c.getWidth() - i.left - i.right;
+ viewR.height = c.getHeight() - i.top - i.bottom;
+ textR.x = 0;
+ textR.y = 0;
+ textR.width = 0;
+ textR.height = 0;
+ iconR.x = 0;
+ iconR.y = 0;
+ iconR.width = 0;
+ iconR.height = 0;
Font f = c.getFont();
-
g.setFont(f);
+ Icon icon = b.getIcon();
+ String text = b.getText();
+ text = SwingUtilities.layoutCompoundLabel(c, g.getFontMetrics(f),
+ text, icon,
+ b.getVerticalAlignment(),
+ b.getHorizontalAlignment(),
+ b.getVerticalTextPosition(),
+ b.getHorizontalTextPosition(),
+ viewR, iconR, textR,
+ text == null ? 0
+ : b.getIconTextGap());
- if (b.isBorderPainted())
- SwingUtilities.calculateInnerArea(b, vr);
- else
- vr = SwingUtilities.getLocalBounds(b);
- String text = SwingUtilities.layoutCompoundLabel(c, g.getFontMetrics(f),
- b.getText(),
- currentIcon(b),
- b.getVerticalAlignment(),
- b.getHorizontalAlignment(),
- b.getVerticalTextPosition(),
- b.getHorizontalTextPosition(),
- vr, ir, tr,
- b.getIconTextGap()
- + defaultTextShiftOffset);
-
- if ((b.getModel().isArmed() && b.getModel().isPressed())
- || b.isSelected())
+ ButtonModel model = b.getModel();
+ if (model.isArmed() && model.isPressed())
paintButtonPressed(g, b);
-
- paintIcon(g, c, ir);
+
+ if (icon != null)
+ paintIcon(g, c, iconR);
if (text != null)
{
View html = (View) b.getClientProperty(BasicHTML.propertyKey);
if (html != null)
- html.paint(g, tr);
+ html.paint(g, textR);
else
- paintText(g, b, tr, text);
+ paintText(g, b, textR, text);
}
if (b.isFocusOwner() && b.isFocusPainted())
- paintFocus(g, b, vr, tr, ir);
+ paintFocus(g, b, viewR, textR, iconR);
}
/**
* Paint any focus decoration this [EMAIL PROTECTED] JComponent} might have. The
* component, which in this case will be an [EMAIL PROTECTED] AbstractButton},
* should only have focus decoration painted if it has the focus, and its
* "focusPainted" property is <code>true</code>.
*
* @param g Graphics context to paint with
* @param b Button to paint the focus of
* @param vr Visible rectangle, the area in which to paint
* @param tr Text rectangle, contained in visible rectangle
Index: javax/swing/plaf/basic/BasicGraphicsUtils.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java,v
retrieving revision 1.18
diff -u -1 -2 -r1.18 BasicGraphicsUtils.java
--- javax/swing/plaf/basic/BasicGraphicsUtils.java 21 Jun 2006 13:13:40 -0000 1.18
+++ javax/swing/plaf/basic/BasicGraphicsUtils.java 17 Aug 2006 14:44:56 -0000
@@ -739,78 +739,83 @@
g.drawLine(i, y, i, y);
g.drawLine(i, bottom, i, bottom);
}
/* Draw the left and right edge of the dotted rectangle. */
for (int i = y; i <= bottom; i += 2)
{
g.drawLine(x, i, x, i);
g.drawLine(right, i, right, i);
}
}
-
/**
* Determines the preferred width and height of an AbstractButton,
* given the gap between the button’s text and icon.
*
* @param b the button whose preferred size is determined.
*
* @param textIconGap the gap between the button’s text and
* icon.
*
* @return a <code>Dimension</code> object whose <code>width</code>
* and <code>height</code> fields indicate the preferred
* extent in pixels.
*
* @see javax.swing.SwingUtilities#layoutCompoundLabel(JComponent,
* FontMetrics, String, Icon, int, int, int, int, Rectangle, Rectangle,
* Rectangle, int)
*/
public static Dimension getPreferredButtonSize(AbstractButton b,
int textIconGap)
{
- Rectangle contentRect;
- Rectangle viewRect;
- Rectangle iconRect = new Rectangle();
- Rectangle textRect = new Rectangle();
- Insets insets = b.getInsets();
-
- viewRect = new Rectangle();
+ // These cached rectangles are use here and in BasicButtonUI.paint(),
+ // so these two methods must never be executed concurrently. Maybe
+ // we must use other Rectangle instances here. OTOH, Swing is
+ // designed to be not thread safe, and every layout and paint operation
+ // should be performed from the EventDispatchThread, so it _should_ be
+ // OK to do this optimization.
+ Rectangle viewRect = BasicButtonUI.viewR;
+ viewRect.x = 0;
+ viewRect.y = 0;
+ viewRect.width = Short.MAX_VALUE;
+ viewRect.height = Short.MAX_VALUE;
+ Rectangle iconRect = BasicButtonUI.iconR;
+ iconRect.x = 0;
+ iconRect.y = 0;
+ iconRect.width = 0;
+ iconRect.height = 0;
+ Rectangle textRect = BasicButtonUI.textR;
+ textRect.x = 0;
+ textRect.y = 0;
+ textRect.width = 0;
+ textRect.height = 0;
- /* java.awt.Toolkit.getFontMetrics is deprecated. However, it
- * seems not obvious how to get to the correct FontMetrics object
- * otherwise. The real problem probably is that the method
- * javax.swing.SwingUtilities.layoutCompundLabel should take a
- * LineMetrics, not a FontMetrics argument. But fixing this that
- * would change the public API.
- */
SwingUtilities.layoutCompoundLabel(
b, // for the component orientation
- b.getToolkit().getFontMetrics(b.getFont()), // see comment above
+ b.getFontMetrics(b.getFont()), // see comment above
b.getText(),
b.getIcon(),
b.getVerticalAlignment(),
b.getHorizontalAlignment(),
b.getVerticalTextPosition(),
b.getHorizontalTextPosition(),
viewRect, iconRect, textRect,
textIconGap);
/* +------------------------+ +------------------------+
* | | | |
* | ICON | | CONTENTCONTENTCONTENT |
* | TEXTTEXTTEXT | --> | CONTENTCONTENTCONTENT |
* | TEXTTEXTTEXT | | CONTENTCONTENTCONTENT |
* +------------------------+ +------------------------+
*/
- contentRect = textRect.union(iconRect);
-
- return new Dimension(insets.left
- + contentRect.width
- + insets.right + b.getHorizontalAlignment(),
- insets.top
- + contentRect.height
- + insets.bottom);
+ Rectangle contentRect =
+ SwingUtilities.computeUnion(textRect.x, textRect.y, textRect.width,
+ textRect.height, iconRect);
+
+ Insets insets = b.getInsets();
+ return new Dimension(insets.left + contentRect.width + insets.right,
+ insets.top + contentRect.height + insets.bottom);
}
}
Index: javax/swing/plaf/basic/BasicLabelUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicLabelUI.java,v
retrieving revision 1.24
diff -u -1 -2 -r1.24 BasicLabelUI.java
--- javax/swing/plaf/basic/BasicLabelUI.java 22 Jun 2006 14:25:48 -0000 1.24
+++ javax/swing/plaf/basic/BasicLabelUI.java 17 Aug 2006 14:44:56 -0000
@@ -110,31 +110,55 @@
* Returns the preferred size of this component as calculated by the
* [EMAIL PROTECTED] #layoutCL(JLabel, FontMetrics, String, Icon, Rectangle, Rectangle,
* Rectangle)} method.
*
* @param c This [EMAIL PROTECTED] JComponent} to get a preferred size for.
*
* @return The preferred size.
*/
public Dimension getPreferredSize(JComponent c)
{
JLabel lab = (JLabel) c;
Insets insets = lab.getInsets();
- FontMetrics fm = lab.getFontMetrics(lab.getFont());
- layoutCL(lab, fm, lab.getText(), lab.getIcon(), vr, ir, tr);
- Rectangle cr = SwingUtilities.computeUnion(tr.x, tr.y, tr.width, tr.height,
- ir);
- return new Dimension(insets.left + cr.width + insets.right, insets.top
- + cr.height + insets.bottom);
-
+ int insetsX = insets.left + insets.right;
+ int insetsY = insets.top + insets.bottom;
+ Icon icon = lab.getIcon();
+ String text = lab.getText();
+ Dimension ret;
+ if (icon == null && text == null)
+ ret = new Dimension(insetsX, insetsY);
+ else if (icon != null && text == null)
+ ret = new Dimension(icon.getIconWidth() + insetsX,
+ icon.getIconHeight() + insetsY);
+ else
+ {
+ FontMetrics fm = lab.getFontMetrics(lab.getFont());
+ ir.x = 0;
+ ir.y = 0;
+ ir.width = 0;
+ ir.height = 0;
+ tr.x = 0;
+ tr.y = 0;
+ tr.width = 0;
+ tr.height = 0;
+ vr.x = 0;
+ vr.y = 0;
+ vr.width = Short.MAX_VALUE;
+ vr.height = Short.MAX_VALUE;
+ layoutCL(lab, fm, text, icon, vr, ir, tr);
+ Rectangle cr = SwingUtilities.computeUnion(tr.x, tr.y, tr.width,
+ tr.height, ir);
+ ret = new Dimension(cr.width + insetsX, cr.height + insetsY);
+ }
+ return ret;
}
/**
* This method returns the minimum size of the [EMAIL PROTECTED] JComponent} given. If
* this method returns null, then it is up to the Layout Manager to give
* this component a minimum size.
*
* @param c The [EMAIL PROTECTED] JComponent} to get a minimum size for.
*
* @return The minimum size.
*/
public Dimension getMinimumSize(JComponent c)
@@ -157,31 +181,38 @@
}
/**
* The method that paints the label according to its current state.
*
* @param g The [EMAIL PROTECTED] Graphics} object to paint with.
* @param c The [EMAIL PROTECTED] JComponent} to paint.
*/
public void paint(Graphics g, JComponent c)
{
JLabel b = (JLabel) c;
FontMetrics fm = g.getFontMetrics();
- vr = SwingUtilities.calculateInnerArea(c, vr);
-
- if (vr.width < 0)
- vr.width = 0;
- if (vr.height < 0)
- vr.height = 0;
+ Insets i = c.getInsets();
+ vr.x = i.left;
+ vr.y = i.right;
+ vr.width = c.getWidth() - i.left + i.right;
+ vr.height = c.getHeight() - i.top + i.bottom;
+ ir.x = 0;
+ ir.y = 0;
+ ir.width = 0;
+ ir.height = 0;
+ tr.x = 0;
+ tr.y = 0;
+ tr.width = 0;
+ tr.height = 0;
Icon icon = (b.isEnabled()) ? b.getIcon() : b.getDisabledIcon();
String text = layoutCL(b, fm, b.getText(), icon, vr, ir, tr);
if (icon != null)
icon.paintIcon(b, g, ir.x, ir.y);
Object htmlRenderer = b.getClientProperty(BasicHTML.propertyKey);
if (htmlRenderer == null)
{
if (text != null && !text.equals(""))
{
Index: javax/swing/plaf/basic/BasicMenuItemUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java,v
retrieving revision 1.50
diff -u -1 -2 -r1.50 BasicMenuItemUI.java
--- javax/swing/plaf/basic/BasicMenuItemUI.java 2 Aug 2006 23:05:59 -0000 1.50
+++ javax/swing/plaf/basic/BasicMenuItemUI.java 17 Aug 2006 14:44:56 -0000
@@ -440,24 +440,25 @@
* space between icon and text in the given menuItem
* @return $Dimension$ preferred size for the given menu item
*/
protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon,
Icon arrowIcon,
int defaultTextIconGap)
{
JMenuItem m = (JMenuItem) c;
String accelText = getAcceleratorString(m);
// Layout the menu item. The result gets stored in the rectangle
// fields of this class.
+ resetRectangles(null);
layoutMenuItem(m, accelText);
// The union of the text and icon areas is the label area.
cachedRect.setBounds(textRect);
Rectangle pref = SwingUtilities.computeUnion(iconRect.x, iconRect.y,
iconRect.width,
iconRect.height,
cachedRect);
// Find the widest menu item text and accelerator and store it in
// client properties of the parent, so that we can align the accelerators
// properly. Of course, we only need can do this, if the parent is
@@ -691,24 +692,26 @@
// Fetch fonts.
Font oldFont = g.getFont();
Font font = c.getFont();
g.setFont(font);
FontMetrics accelFm = m.getFontMetrics(acceleratorFont);
// Create accelerator string.
String accelText = getAcceleratorString(m);
// Layout menu item. The result gets stored in the rectangle fields
// of this class.
+ resetRectangles(m);
+
layoutMenuItem(m, accelText);
// Paint the background.
paintBackground(g, m, background);
Color oldColor = g.getColor();
// Paint the check icon.
if (checkIcon != null)
{
checkIcon.paintIcon(m, g, checkIconRect.x, checkIconRect.y);
}
@@ -1262,49 +1265,61 @@
accelText += acceleratorDelimiter;
}
int keycode = accel.getKeyCode();
if (keycode != 0)
accelText += KeyEvent.getKeyText(keycode);
else
accelText += accel.getKeyChar();
}
return accelText;
}
/**
- * A helper method that lays out the menu item. The layout is stored
- * in the fields of this class.
+ * Resets the cached layout rectangles. If <code>i</code> is not null, then
+ * the view rectangle is set to the inner area of the component, otherwise
+ * it is set to (0, 0, Short.MAX_VALUE, Short.MAX_VALUE), this is needed
+ * for layouting.
*
- * @param m the menu item to layout
- * @param accelText the accelerator text
+ * @param i the component for which to initialize the rectangles
*/
- private void layoutMenuItem(JMenuItem m, String accelText)
+ private void resetRectangles(JMenuItem i)
{
- int width = m.getWidth();
- int height = m.getHeight();
-
// Reset rectangles.
iconRect.setBounds(0, 0, 0, 0);
textRect.setBounds(0, 0, 0, 0);
accelRect.setBounds(0, 0, 0, 0);
checkIconRect.setBounds(0, 0, 0, 0);
arrowIconRect.setBounds(0, 0, 0, 0);
- viewRect.setBounds(0, 0, width, height);
+ if (i == null)
+ viewRect.setBounds(0, 0, Short.MAX_VALUE, Short.MAX_VALUE);
+ else
+ {
+ Insets insets = i.getInsets();
+ viewRect.setBounds(insets.left, insets.top,
+ i.getWidth() - insets.left - insets.right,
+ i.getHeight() - insets.top - insets.bottom);
+ }
+ }
- // Substract insets to the view rect.
- Insets insets = m.getInsets();
- viewRect.x += insets.left;
- viewRect.y += insets.top;
- viewRect.width -= insets.left + insets.right;
- viewRect.height -= insets.top + insets.bottom;
+ /**
+ * A helper method that lays out the menu item. The layout is stored
+ * in the fields of this class.
+ *
+ * @param m the menu item to layout
+ * @param accelText the accelerator text
+ */
+ private void layoutMenuItem(JMenuItem m, String accelText)
+ {
+ int width = m.getWidth();
+ int height = m.getHeight();
// Fetch the fonts.
Font font = m.getFont();
FontMetrics fm = m.getFontMetrics(font);
FontMetrics accelFm = m.getFontMetrics(acceleratorFont);
String text = m.getText();
SwingUtilities.layoutCompoundLabel(m, fm, text, m.getIcon(),
m.getVerticalAlignment(),
m.getHorizontalAlignment(),
m.getVerticalTextPosition(),
m.getHorizontalTextPosition(),
Index: javax/swing/plaf/basic/BasicRadioButtonUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java,v
retrieving revision 1.19
diff -u -1 -2 -r1.19 BasicRadioButtonUI.java
--- javax/swing/plaf/basic/BasicRadioButtonUI.java 16 Jun 2006 12:36:21 -0000 1.19
+++ javax/swing/plaf/basic/BasicRadioButtonUI.java 17 Aug 2006 14:44:56 -0000
@@ -120,101 +120,118 @@
}
/**
* Paints the RadioButton.
*
* @param g the Graphics context to paint with
* @param c the button to paint
*/
public void paint(Graphics g, JComponent c)
{
AbstractButton b = (AbstractButton) c;
- Rectangle tr = new Rectangle();
- Rectangle ir = new Rectangle();
- Rectangle vr = new Rectangle();
+ Insets i = b.getInsets();
+ Rectangle tr = textR;
+ textR.x = 0;
+ textR.y = 0;
+ textR.width = 0;
+ textR.height = 0;
+ Rectangle ir = iconR;
+ iconR.x = 0;
+ iconR.y = 0;
+ iconR.width = 0;
+ iconR.height = 0;
+ Rectangle vr = viewR;
+ viewR.x = i.left;
+ viewR.y = i.right;
+ viewR.width = b.getWidth() - i.left - i.right;
+ viewR.height = b.getHeight() - i.top - i.bottom;
Font f = c.getFont();
g.setFont(f);
ButtonModel m = b.getModel();
// FIXME: Do a filtering on any customized icon if the following property
// is set.
boolean enabled = b.isEnabled();
Icon currentIcon = b.getIcon();
if (currentIcon == null)
{
currentIcon = getDefaultIcon();
}
- SwingUtilities.calculateInnerArea(b, vr);
String text = SwingUtilities.layoutCompoundLabel(c, g.getFontMetrics(f),
b.getText(), currentIcon,
b.getVerticalAlignment(), b.getHorizontalAlignment(),
b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
vr, ir, tr, b.getIconTextGap() + defaultTextShiftOffset);
-
+
currentIcon.paintIcon(c, g, ir.x, ir.y);
if (text != null)
paintText(g, b, tr, text);
if (b.hasFocus() && b.isFocusPainted() && m.isEnabled())
paintFocus(g, tr, c.getSize());
}
public Dimension getPreferredSize(JComponent c)
{
// This is basically the same code as in
// BasicGraphicsUtils.getPreferredButtonSize() but takes the default icon
// property into account. JRadioButton and subclasses always have an icon:
// the check box. If the user explicitly changes it with setIcon() that
// one will be used for layout calculations and painting instead.
// The other icon properties are ignored.
AbstractButton b = (AbstractButton) c;
- Rectangle contentRect;
- Rectangle viewRect;
- Rectangle iconRect = new Rectangle();
- Rectangle textRect = new Rectangle();
Insets insets = b.getInsets();
-
+
+ String text = b.getText();
Icon i = b.getIcon();
if (i == null)
i = getDefaultIcon();
- viewRect = new Rectangle();
+ textR.x = 0;
+ textR.y = 0;
+ textR.width = 0;
+ textR.height = 0;
+ iconR.x = 0;
+ iconR.y = 0;
+ iconR.width = 0;
+ iconR.height = 0;
+ viewR.x = 0;
+ viewR.y = 0;
+ viewR.width = Short.MAX_VALUE;
+ viewR.height = Short.MAX_VALUE;
SwingUtilities.layoutCompoundLabel(
b, // for the component orientation
b.getFontMetrics(b.getFont()),
b.getText(),
i,
b.getVerticalAlignment(),
b.getHorizontalAlignment(),
b.getVerticalTextPosition(),
b.getHorizontalTextPosition(),
- viewRect, iconRect, textRect,
+ viewR, iconR, textR,
defaultTextIconGap + defaultTextShiftOffset);
- contentRect = textRect.union(iconRect);
-
- return new Dimension(insets.left
- + contentRect.width
- + insets.right + b.getHorizontalAlignment(),
- insets.top
- + contentRect.height
- + insets.bottom);
+ Rectangle r = SwingUtilities.computeUnion(textR.x, textR.y, textR.width,
+ textR.height, iconR);
+
+ return new Dimension(insets.left + r.width + insets.right,
+ insets.top + r.height + insets.bottom);
}
/**
* Paints the focus indicator for JRadioButtons.
*
* @param g the graphics context
* @param tr the rectangle for the text label
* @param size the size of the <code>JRadioButton</code> component.
*/
protected void paintFocus(Graphics g, Rectangle tr, Dimension size)
{
Color focusColor = UIManager.getColor(getPropertyPrefix() + ".focus");