Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -26,22 +26,30 @@
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;
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;

Expand All @@ -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}.
*/
Expand Down Expand Up @@ -143,6 +155,128 @@ public static RepaintManager getDelegateRepaintManager(Component
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;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just pointed this out on the main bug but this looks like a copy/paste error.
It should be acceleratorSelectionForeground.

To Alexei's point, why can't we pass these as parameters ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the assignment..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the assignment..

This may be an appropriate quick fix at this moment.

Yet this bug needs fixing in mainline, all the update releases will also be affected as soon as JDK-8348760 is backported.

I've submitted JDK-8365375: Method SU3.setAcceleratorSelectionForeground assigns to acceleratorForeground.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the assignment..

This may be an appropriate quick fix at this moment.

Yet this bug needs fixing in mainline, all the update releases will also be affected as soon as JDK-8348760 is backported.

I expect, and recommend, that the back ports be based on the JDK 25 version.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the assignment..

This may be an appropriate quick fix at this moment.
Yet this bug needs fixing in mainline, all the update releases will also be affected as soon as JDK-8348760 is backported.

I expect, and recommend, that the back ports be based on the JDK 25 version.

The backports are nearly done, so it's impossible to add this small fix at this time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well they'll have to be re-done. That's life.


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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -670,84 +705,22 @@ protected void paintMenuItem(Graphics g, JComponent c,

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,
Expand All @@ -766,26 +739,11 @@ private void paintText(Graphics g, MenuItemLayoutHelper lh,
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);
}

/**
Expand Down
Loading