8348760: RadioButton is not shown if JRadioButtonMenuItem is rendered with ImageIcon in WindowsLookAndFeel

Reviewed-by: prr, aivanov
Backport-of: e29346dbd6328dcadc347a70d8c06ce141efef02
This commit is contained in:
Prasanta Sadhukhan 2025-08-12 17:15:36 +00:00
parent 73c28c2e3d
commit 6c48f4ed70
8 changed files with 549 additions and 106 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,10 +26,13 @@
package com.sun.java.swing;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.Window;
import java.awt.geom.AffineTransform;
@ -37,11 +40,16 @@ import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.RepaintManager;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.swing.MenuItemLayoutHelper;
import sun.swing.SwingUtilities2;
import static sun.java2d.pipe.Region.clipRound;
@ -64,6 +72,10 @@ public class SwingUtilities3 {
private static final Object DELEGATE_REPAINT_MANAGER_KEY =
new StringBuilder("DelegateRepaintManagerKey");
private static Color disabledForeground;
private static Color acceleratorSelectionForeground;
private static Color acceleratorForeground;
/**
* Registers delegate RepaintManager for {@code JComponent}.
*/
@ -143,6 +155,128 @@ public class SwingUtilities3 {
return delegate;
}
public static void applyInsets(Rectangle rect, Insets insets) {
if (insets != null) {
rect.x += insets.left;
rect.y += insets.top;
rect.width -= (insets.right + rect.x);
rect.height -= (insets.bottom + rect.y);
}
}
public static void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr,
Color holdc, Color foreground) {
if (lh.getCheckIcon() != null) {
ButtonModel model = lh.getMenuItem().getModel();
if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
&& model.isSelected())) {
g.setColor(foreground);
} else {
g.setColor(holdc);
}
if (lh.useCheckAndArrow()) {
lh.getCheckIcon().paintIcon(lh.getMenuItem(), g,
lr.getCheckRect().x, lr.getCheckRect().y);
}
g.setColor(holdc);
}
}
public static void paintIcon(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr, Color holdc) {
if (lh.getIcon() != null) {
Icon icon;
ButtonModel model = lh.getMenuItem().getModel();
if (!model.isEnabled()) {
icon = lh.getMenuItem().getDisabledIcon();
} else if (model.isPressed() && model.isArmed()) {
icon = lh.getMenuItem().getPressedIcon();
if (icon == null) {
// Use default icon
icon = lh.getMenuItem().getIcon();
}
} else {
icon = lh.getMenuItem().getIcon();
}
if (icon != null) {
icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x,
lr.getIconRect().y);
g.setColor(holdc);
}
}
}
public static void paintAccText(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
if (!lh.getAccText().isEmpty()) {
ButtonModel model = lh.getMenuItem().getModel();
g.setFont(lh.getAccFontMetrics().getFont());
if (!model.isEnabled()) {
// paint the accText disabled
if (disabledForeground != null) {
g.setColor(disabledForeground);
SwingUtilities2.drawString(lh.getMenuItem(), g,
lh.getAccText(), lr.getAccRect().x,
lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
} else {
g.setColor(lh.getMenuItem().getBackground().brighter());
SwingUtilities2.drawString(lh.getMenuItem(), g,
lh.getAccText(), lr.getAccRect().x,
lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
g.setColor(lh.getMenuItem().getBackground().darker());
SwingUtilities2.drawString(lh.getMenuItem(), g,
lh.getAccText(), lr.getAccRect().x - 1,
lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1);
}
} else {
// paint the accText normally
if (model.isArmed()
|| (lh.getMenuItem() instanceof JMenu
&& model.isSelected())) {
g.setColor(acceleratorSelectionForeground);
} else {
g.setColor(acceleratorForeground);
}
SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(),
lr.getAccRect().x, lr.getAccRect().y +
lh.getAccFontMetrics().getAscent());
}
}
}
public static void setDisabledForeground(Color disabledFg) {
disabledForeground = disabledFg;
}
public static void setAcceleratorSelectionForeground(Color acceleratorSelectionFg) {
acceleratorSelectionForeground = acceleratorSelectionFg;
}
public static void setAcceleratorForeground(Color acceleratorFg) {
acceleratorForeground = acceleratorFg;
}
public static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr,
Color foreground) {
if (lh.getArrowIcon() != null) {
ButtonModel model = lh.getMenuItem().getModel();
if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
&& model.isSelected())) {
g.setColor(foreground);
}
if (lh.useCheckAndArrow()) {
lh.getArrowIcon().paintIcon(lh.getMenuItem(), g,
lr.getArrowRect().x, lr.getArrowRect().y);
}
}
}
/**
* A task which paints an <i>unscaled</i> border after {@code Graphics}
* transforms are removed. It's used with the

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,17 +25,52 @@
package javax.swing.plaf.basic;
import java.awt.*;
import java.awt.event.*;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.InputMap;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.KeyStroke;
import javax.swing.LookAndFeel;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.MenuDragMouseEvent;
import javax.swing.event.MenuDragMouseListener;
import javax.swing.event.MenuKeyListener;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ComponentInputMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.MenuItemUI;
import javax.swing.plaf.UIResource;
import javax.swing.text.View;
import sun.swing.*;
import com.sun.java.swing.SwingUtilities3;
import sun.swing.MenuItemCheckIconFactory;
import sun.swing.MenuItemLayoutHelper;
import sun.swing.SwingUtilities2;
import sun.swing.UIAction;
/**
* BasicMenuItem implementation
@ -670,84 +705,22 @@ public class BasicMenuItemUI extends MenuItemUI
private void paintIcon(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr, Color holdc) {
if (lh.getIcon() != null) {
Icon icon;
ButtonModel model = lh.getMenuItem().getModel();
if (!model.isEnabled()) {
icon = lh.getMenuItem().getDisabledIcon();
} else if (model.isPressed() && model.isArmed()) {
icon = lh.getMenuItem().getPressedIcon();
if (icon == null) {
// Use default icon
icon = lh.getMenuItem().getIcon();
}
} else {
icon = lh.getMenuItem().getIcon();
}
if (icon != null) {
icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x,
lr.getIconRect().y);
g.setColor(holdc);
}
}
SwingUtilities3.paintIcon(g, lh, lr, holdc);
}
private void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr,
Color holdc, Color foreground) {
if (lh.getCheckIcon() != null) {
ButtonModel model = lh.getMenuItem().getModel();
if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
&& model.isSelected())) {
g.setColor(foreground);
} else {
g.setColor(holdc);
}
if (lh.useCheckAndArrow()) {
lh.getCheckIcon().paintIcon(lh.getMenuItem(), g,
lr.getCheckRect().x, lr.getCheckRect().y);
}
g.setColor(holdc);
}
SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground);
}
private void paintAccText(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
if (!lh.getAccText().isEmpty()) {
ButtonModel model = lh.getMenuItem().getModel();
g.setFont(lh.getAccFontMetrics().getFont());
if (!model.isEnabled()) {
// *** paint the accText disabled
if (disabledForeground != null) {
g.setColor(disabledForeground);
SwingUtilities2.drawString(lh.getMenuItem(), g,
lh.getAccText(), lr.getAccRect().x,
lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
} else {
g.setColor(lh.getMenuItem().getBackground().brighter());
SwingUtilities2.drawString(lh.getMenuItem(), g,
lh.getAccText(), lr.getAccRect().x,
lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
g.setColor(lh.getMenuItem().getBackground().darker());
SwingUtilities2.drawString(lh.getMenuItem(), g,
lh.getAccText(), lr.getAccRect().x - 1,
lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1);
}
} else {
// *** paint the accText normally
if (model.isArmed()
|| (lh.getMenuItem() instanceof JMenu
&& model.isSelected())) {
g.setColor(acceleratorSelectionForeground);
} else {
g.setColor(acceleratorForeground);
}
SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(),
lr.getAccRect().x, lr.getAccRect().y +
lh.getAccFontMetrics().getAscent());
}
}
SwingUtilities3.setDisabledForeground(disabledForeground);
SwingUtilities3.setAcceleratorSelectionForeground(
acceleratorSelectionForeground);
SwingUtilities3.setAcceleratorForeground(acceleratorForeground);
SwingUtilities3.paintAccText(g, lh, lr);
}
private void paintText(Graphics g, MenuItemLayoutHelper lh,
@ -766,26 +739,11 @@ public class BasicMenuItemUI extends MenuItemUI
private void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr,
Color foreground) {
if (lh.getArrowIcon() != null) {
ButtonModel model = lh.getMenuItem().getModel();
if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
&& model.isSelected())) {
g.setColor(foreground);
}
if (lh.useCheckAndArrow()) {
lh.getArrowIcon().paintIcon(lh.getMenuItem(), g,
lr.getArrowRect().x, lr.getArrowRect().y);
}
}
SwingUtilities3.paintArrowIcon(g, lh, lr, foreground);
}
private void applyInsets(Rectangle rect, Insets insets) {
if(insets != null) {
rect.x += insets.left;
rect.y += insets.top;
rect.width -= (insets.right + rect.x);
rect.height -= (insets.bottom + rect.y);
}
SwingUtilities3.applyInsets(rect, insets);
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@ import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.plaf.ComponentUI;
@ -73,6 +74,24 @@ public final class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI {
}
super.paintBackground(g, menuItem, bgColor);
}
/**
* Paint MenuItem.
*/
protected void paintMenuItem(Graphics g, JComponent c,
Icon checkIcon, Icon arrowIcon,
Color background, Color foreground,
int defaultTextIconGap) {
if (WindowsMenuItemUI.isVistaPainting()) {
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
arrowIcon, background, foreground, defaultTextIconGap,
menuItem, getPropertyPrefix());
return;
}
super.paintMenuItem(g, c, checkIcon, arrowIcon, background,
foreground, defaultTextIconGap);
}
/**
* Method which renders the text of the current menu item.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -880,6 +880,7 @@ public final class WindowsIconFactory implements Serializable
}
assert menuItem == null || c == menuItem;
Icon icon = getIcon();
if (type == JCheckBoxMenuItem.class
|| type == JRadioButtonMenuItem.class) {
AbstractButton b = (AbstractButton) c;
@ -903,19 +904,18 @@ public final class WindowsIconFactory implements Serializable
}
XPStyle xp = XPStyle.getXP();
if (xp != null) {
Skin skin;
skin = xp.getSkin(c, backgroundPart);
skin.paintSkin(g, x, y,
getIconWidth(), getIconHeight(), backgroundState);
if (icon == null) {
skin = xp.getSkin(c, part);
Skin skin = xp.getSkin(c, part);
if (icon == null || icon.getIconHeight() <= 16) {
skin.paintSkin(g, x + OFFSET, y + OFFSET, state);
} else {
skin.paintSkin(g, x + OFFSET, y + icon.getIconHeight() / 2, state);
}
}
}
}
if (icon != null) {
icon.paintIcon(c, g, x + OFFSET, y + OFFSET);
icon.paintIcon(c, g, x + VistaMenuItemCheckIconFactory.getIconWidth(),
y + OFFSET);
}
}
private static WindowsMenuItemUIAccessor getAccessor(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,13 +26,20 @@
package com.sun.java.swing.plaf.windows;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Enumeration;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.DefaultButtonModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
@ -41,6 +48,7 @@ import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicMenuItemUI;
import com.sun.java.swing.SwingUtilities3;
import com.sun.java.swing.plaf.windows.TMSchema.Part;
import com.sun.java.swing.plaf.windows.TMSchema.State;
import com.sun.java.swing.plaf.windows.XPStyle.Skin;
@ -59,6 +67,9 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
* The instance of {@code PropertyChangeListener}.
*/
private PropertyChangeListener changeListener;
private static Color disabledForeground;
private static Color acceleratorSelectionForeground;
private static Color acceleratorForeground;
final WindowsMenuItemUIAccessor accessor =
new WindowsMenuItemUIAccessor() {
@ -123,6 +134,27 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
menuItem.addPropertyChangeListener(changeListener);
}
protected void installDefaults() {
super.installDefaults();
String prefix = getPropertyPrefix();
if (acceleratorSelectionForeground == null ||
acceleratorSelectionForeground instanceof UIResource) {
acceleratorSelectionForeground =
UIManager.getColor(prefix + ".acceleratorSelectionForeground");
}
if (acceleratorForeground == null ||
acceleratorForeground instanceof UIResource) {
acceleratorForeground =
UIManager.getColor(prefix + ".acceleratorForeground");
}
if (disabledForeground == null ||
disabledForeground instanceof UIResource) {
disabledForeground =
UIManager.getColor(prefix + ".disabledForeground");
}
}
/**
* {@inheritDoc}
*/
@ -135,6 +167,114 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
changeListener = null;
}
private static void applyInsets(Rectangle rect, Insets insets) {
SwingUtilities3.applyInsets(rect, insets);
}
private static void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr,
Color holdc, Color foreground) {
SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground);
}
private static void paintIcon(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr, Color holdc) {
SwingUtilities3.paintIcon(g, lh, lr, holdc);
}
private static void paintAccText(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
SwingUtilities3.setDisabledForeground(disabledForeground);
SwingUtilities3.setAcceleratorSelectionForeground(
acceleratorSelectionForeground);
SwingUtilities3.setAcceleratorForeground(acceleratorForeground);
SwingUtilities3.paintAccText(g, lh, lr);
}
private static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr,
Color foreground) {
SwingUtilities3.paintArrowIcon(g, lh, lr, foreground);
}
protected void paintMenuItem(Graphics g, JComponent c,
Icon checkIcon, Icon arrowIcon,
Color background, Color foreground,
int defaultTextIconGap) {
if (WindowsMenuItemUI.isVistaPainting()) {
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
arrowIcon, background, foreground,
defaultTextIconGap, menuItem,
getPropertyPrefix());
return;
}
super.paintMenuItem(g, c, checkIcon, arrowIcon, background,
foreground, defaultTextIconGap);
}
static void paintMenuItem(WindowsMenuItemUIAccessor accessor, Graphics g,
JComponent c, Icon checkIcon, Icon arrowIcon,
Color background, Color foreground,
int defaultTextIconGap, JMenuItem menuItem, String prefix) {
// Save original graphics font and color
Font holdf = g.getFont();
Color holdc = g.getColor();
JMenuItem mi = (JMenuItem) c;
g.setFont(mi.getFont());
Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
applyInsets(viewRect, mi.getInsets());
String acceleratorDelimiter =
UIManager.getString("MenuItem.acceleratorDelimiter");
if (acceleratorDelimiter == null) { acceleratorDelimiter = "+"; }
Font acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont");
if (acceleratorFont == null) {
acceleratorFont = UIManager.getFont("MenuItem.font");
}
MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon,
arrowIcon, viewRect, defaultTextIconGap, acceleratorDelimiter,
mi.getComponentOrientation().isLeftToRight(), mi.getFont(),
acceleratorFont, MenuItemLayoutHelper.useCheckAndArrow(menuItem),
prefix);
MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
paintBackground(accessor, g, mi, background);
paintCheckIcon(g, lh, lr, holdc, foreground);
paintIcon(g, lh, lr, holdc);
if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) {
Rectangle rect = lr.getTextRect();
rect.x += lh.getAfterCheckIconGap();
lr.setTextRect(rect);
}
if (!lh.getText().isEmpty()) {
if (lh.getHtmlView() != null) {
// Text is HTML
lh.getHtmlView().paint(g, lr.getTextRect());
} else {
// Text isn't HTML
paintText(accessor, g, lh.getMenuItem(),
lr.getTextRect(), lh.getText());
}
}
if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) {
Rectangle rect = lr.getAccRect();
rect.x += lh.getAfterCheckIconGap();
lr.setAccRect(rect);
}
paintAccText(g, lh, lr);
paintArrowIcon(g, lh, lr, foreground);
// Restore original graphics font and color
g.setColor(holdc);
g.setFont(holdf);
}
/**
* Method which renders the text of the current menu item.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -130,6 +130,25 @@ public final class WindowsMenuUI extends BasicMenuUI {
hotTrackingOn = (obj instanceof Boolean) ? (Boolean)obj : true;
}
/**
* Paint MenuItem.
*/
protected void paintMenuItem(Graphics g, JComponent c,
Icon checkIcon, Icon arrowIcon,
Color background, Color foreground,
int defaultTextIconGap) {
if (WindowsMenuItemUI.isVistaPainting()) {
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, arrowIcon,
background, foreground,
defaultTextIconGap, menuItem,
getPropertyPrefix());
return;
}
super.paintMenuItem(g, c, checkIcon, arrowIcon, background,
foreground, defaultTextIconGap);
}
/**
* Draws the background of the menu.
* @since 1.4

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@ import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.plaf.ComponentUI;
@ -74,6 +75,23 @@ public final class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItem
super.paintBackground(g, menuItem, bgColor);
}
/**
* Paint MenuItem.
*/
protected void paintMenuItem(Graphics g, JComponent c,
Icon checkIcon, Icon arrowIcon,
Color background, Color foreground,
int defaultTextIconGap) {
if (WindowsMenuItemUI.isVistaPainting()) {
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
arrowIcon, background, foreground, defaultTextIconGap,
menuItem, getPropertyPrefix());
return;
}
super.paintMenuItem(g, c, checkIcon, arrowIcon, background,
foreground, defaultTextIconGap);
}
/**
* Method which renders the text of the current menu item.
*

View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8348760
* @summary Verify if RadioButtonMenuItem bullet and
* JCheckboxMenuItem checkmark is shown if
* JRadioButtonMenuItem and JCheckboxMenuItem
* is rendered with ImageIcon in WindowsLookAndFeel
* @requires (os.family == "windows")
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual TestRadioAndCheckMenuItemWithIcon
*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
public class TestRadioAndCheckMenuItemWithIcon {
private static final String INSTRUCTIONS = """
A top level Menu will be shown.
Clicking on the Menu will show a
JRadioButtonMenuItem group with 3 radiobutton menuitems
and a JCheckBoxMenuItem group with 3 checkbox menuitems.
First radiobutton menuitem is selected with imageicon of a red square.
Second radiobutton menuitem is unselected with imageicon.
Third radiobutton menuItem is unselected without imageicon.
First checkbox menuitem is selected with imageicon.
Second checkbox menuitem is unselected with imageicon.
Third checkbox menuItem is unselected without imageicon.
Verify that for first JRadioButtonMenuItem with imageicon,
a bullet is shown alongside the imageicon and
for first JCheckBoxMenuItem with imageicon
a checkmark is shown alongside the imageicon.
If bullet and checkmark is shown, test passes else fails.""";
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
PassFailJFrame.builder()
.title("JRadioButtonMenuItem Instructions")
.instructions(INSTRUCTIONS)
.columns(60)
.testUI(TestRadioAndCheckMenuItemWithIcon::doTest)
.build()
.awaitAndCheck();
}
public static JFrame doTest() {
BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
g.setColor(Color.red);
g.fillRect(0, 0, img.getWidth(), img.getHeight());
g.dispose();
BufferedImage img2 = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics g2 = img2.getGraphics();
g2.setColor(Color.red);
g2.fillRect(0, 0, img2.getWidth(), img2.getHeight());
g2.dispose();
JFrame frame = new JFrame("RadioButtonWithImageIcon");
ImageIcon imageIcon1 = new ImageIcon(img);
ImageIcon imageIcon2 = new ImageIcon(img2);
AbstractButton button1;
JRadioButtonMenuItem m1 = new JRadioButtonMenuItem("JRadioButtonMenuItem 1",
imageIcon1);
m1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, ActionEvent.ALT_MASK|ActionEvent.CTRL_MASK|ActionEvent.SHIFT_MASK));
button1 = m1;
button1.setSelected(true);
AbstractButton button2 = new JRadioButtonMenuItem("JRadioButtonMenuItem 2", imageIcon2);
AbstractButton button3 = new JRadioButtonMenuItem("JRadioButtonMenuItem 3");
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(button1);
buttonGroup.add(button2);
buttonGroup.add(button3);
AbstractButton check1 = new JCheckBoxMenuItem("JCheckBoxMenuItem 1",
imageIcon1);
check1.setSelected(true);
AbstractButton check2 = new JCheckBoxMenuItem("JCheckBoxMenuItem 2", imageIcon1);
JCheckBoxMenuItem c3;
AbstractButton check3 = c3 = new JCheckBoxMenuItem("JCheckBoxMenuItem 3");
c3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, ActionEvent.ALT_MASK|ActionEvent.CTRL_MASK|ActionEvent.SHIFT_MASK));
JMenu topLevel = new JMenu("Menu");
topLevel.add(button1);
topLevel.add(button2);
topLevel.add(button3);
topLevel.addSeparator();
topLevel.add(check1);
topLevel.add(check2);
topLevel.add(check3);
AbstractButton menuitem1 = new JMenuItem("MenuItem1");
AbstractButton menuitem2 = new JMenuItem("MenuItem2", imageIcon1);
topLevel.addSeparator();
topLevel.add(menuitem1);
topLevel.add(menuitem2);
JMenuBar menuBar = new JMenuBar();
menuBar.add(topLevel);
frame.setJMenuBar(menuBar);
frame.setSize(300, 300);
return frame;
}
}