001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.util;
003
004import java.awt.Color;
005import java.awt.Graphics;
006import java.awt.Rectangle;
007import java.lang.reflect.Method;
008
009import javax.swing.JComponent;
010import javax.swing.JMenuItem;
011import javax.swing.MenuSelectionManager;
012import javax.swing.UIManager;
013import javax.swing.plaf.ComponentUI;
014import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;
015import javax.swing.plaf.basic.BasicMenuItemUI;
016
017import org.openstreetmap.josm.tools.Logging;
018import org.openstreetmap.josm.tools.ReflectionUtils;
019
020/**
021 * A CheckBoxMenuItem UI delegate that doesn't close the menu when selected.
022 * @author Darryl Burke https://stackoverflow.com/a/3759675/2257172
023 * @since 15288
024 */
025public class StayOpenCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI {
026
027    @Override
028    protected void doClick(MenuSelectionManager msm) {
029        menuItem.doClick(0);
030    }
031
032    @Override
033    protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
034        ComponentUI ui = UIManager.getUI(menuItem);
035        if (ui instanceof BasicMenuItemUI) {
036            try {
037                Method paintBackground = BasicMenuItemUI.class.getDeclaredMethod(
038                        "paintBackground", Graphics.class, JMenuItem.class, Color.class);
039                ReflectionUtils.setObjectsAccessible(paintBackground);
040                paintBackground.invoke(ui, g, menuItem, bgColor);
041            } catch (ReflectiveOperationException | SecurityException | IllegalArgumentException e) {
042                Logging.error(e);
043                super.paintBackground(g, menuItem, bgColor);
044            }
045        } else {
046            super.paintBackground(g, menuItem, bgColor);
047        }
048    }
049
050    @Override
051    protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) {
052        ComponentUI ui = UIManager.getUI(menuItem);
053        if (ui instanceof BasicMenuItemUI) {
054            try {
055                Method paintText = BasicMenuItemUI.class.getDeclaredMethod(
056                        "paintText", Graphics.class, JMenuItem.class, Rectangle.class, String.class);
057                ReflectionUtils.setObjectsAccessible(paintText);
058                paintText.invoke(ui, g, menuItem, textRect, text);
059            } catch (ReflectiveOperationException | SecurityException | IllegalArgumentException e) {
060                Logging.error(e);
061                super.paintText(g, menuItem, textRect, text);
062            }
063        } else {
064            super.paintText(g, menuItem, textRect, text);
065        }
066    }
067
068    /**
069     * Creates a new {@code StayOpenCheckBoxMenuItemUI}.
070     * @param c not used
071     * @return newly created {@code StayOpenCheckBoxMenuItemUI}
072     */
073    public static ComponentUI createUI(JComponent c) {
074        return new StayOpenCheckBoxMenuItemUI();
075    }
076}