/** * MIT License * Copyright (c) 2017 Apollo Zhu (朱智语). *
* Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: *
* The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package io.github.apollozhu.swing;
import javax.swing.*;
import java.awt.*;
import java.beans.ConstructorProperties;
/**
* A subclass of JButton with {@link #setBackground(Color)} working on macOS/OS X.
*
* @author Apollo Zhu
*
* @version 1.0
*/
@SuppressWarnings("serial")
public class AZJButton extends JButton {
/**
* Creates a button with no set text or icon.
*/
public AZJButton() {
super();
}
/**
* Creates a button where properties are taken from the Action
* supplied.
*
* @param a the Action
used to specify the new button
*/
public AZJButton(Action a) {
super(a);
}
/**
* Creates a button with an icon.
*
* @param icon the Icon image to display on the button
*/
public AZJButton(Icon icon) {
super(icon);
}
/**
* Creates a button with text.
*
* @param text the text of the button
*/
@ConstructorProperties({"text"})
public AZJButton(String text) {
super(text);
}
/**
* Creates a button with initial text and an icon.
*
* @param text the text of the button
* @param icon the Icon image to display on the button
*/
public AZJButton(String text, Icon icon) {
super(text, icon);
}
/** Selected menu item color from Apple's Developer Swatch. */
protected static final Color SELECTED_MENU_ITEM_COLOR = new Color(3, 100, 236);
/** Header color from Apple's Developer Swatch. */
protected static final Color HEADER_COLOR = new Color(174, 174, 174);
/** Keyboard focus indicator color from Apple's Developer Swatch. */
protected static final Color KEYBOARD_FOCUS_INDICATOR_COLOR = new Color(76, 149, 255);
/** Selected control color from Apple's Developer Swatch. */
protected static final Color SELECTED_CONTROL_COLOR = new Color(164, 205, 255);
/**
* Check if UIManager is using Apple Aqua Look and Feel.
*
* @return true if current look and feel is aqua.
*/
private boolean isAquaUI() {
try {
return getBorder().getClass().getName().contains("Aqua");
} catch (Exception e) {
return false;
}
}
/**
* Calls the super implementation, unless UIManager is using Apple Aqua Look
* and Feel.
*
* If it is, and if border is required, and has a different background than
* the default one, the button will be drawn differently to match the actual
* look and feel for a button with background color on OS X Yosemite (10.10)
* and other macOSs above.
*
* @param g the Graphics
object to protect
*
* @see #setBackground(Color)
*/
@Override
public void paintComponent(Graphics g) {
if (!isAquaUI()) {
super.paintComponent(g);
return;
}
final Color backgroundColor = getBackground(), foregroundColor = getForeground();
final boolean hasCustomBackground = !backgroundColor.equals(UIManager.getColor("Button.background"));
final boolean isBorderPainted = isBorderPainted();
final boolean isOpaque = isOpaque();
if (isBorderPainted && hasCustomBackground) {
final boolean isPressed = getModel().isPressed();
Insets i = getBorder().getBorderInsets(this);
int r = 8, offset = i.top, x = offset, y = offset, w = getWidth() - 2 * offset,
h = getHeight() - offset - i.bottom;
Graphics2D g2 = (Graphics2D) g;
if (isPressed) {
int midX = getWidth() / 2;
g2.setPaint(new GradientPaint(midX, 0, KEYBOARD_FOCUS_INDICATOR_COLOR, midX, getHeight(), SELECTED_MENU_ITEM_COLOR));
setForeground(Color.white);
} else {
g2.setColor(backgroundColor);
}
g2.fillRoundRect(x, y, w, h, r, r);
g2.setColor(HEADER_COLOR);
g2.drawRoundRect(x, y, w, h, r, r);
if (isPressed || isFocusOwner()) {
g2.setColor(SELECTED_CONTROL_COLOR);
g2.setStroke(new BasicStroke(2));
g2.drawRoundRect(x, y, w, h, r, r);
}
super.setBorderPainted(false);
super.setOpaque(false);
}
super.paintComponent(g);
super.setBorderPainted(isBorderPainted);
super.setOpaque(isOpaque);
super.setForeground(foregroundColor);
}
}