4632N/A/*
4632N/A * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
4632N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4632N/A *
4632N/A * This code is free software; you can redistribute it and/or modify it
4632N/A * under the terms of the GNU General Public License version 2 only, as
4632N/A * published by the Free Software Foundation. Oracle designates this
4632N/A * particular file as subject to the "Classpath" exception as provided
4632N/A * by Oracle in the LICENSE file that accompanied this code.
4632N/A *
4632N/A * This code is distributed in the hope that it will be useful, but WITHOUT
4632N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4632N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4632N/A * version 2 for more details (a copy is included in the LICENSE file that
4632N/A * accompanied this code).
4632N/A *
4632N/A * You should have received a copy of the GNU General Public License version
4632N/A * 2 along with this work; if not, write to the Free Software Foundation,
4632N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4632N/A *
4632N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4632N/A * or visit www.oracle.com if you need additional information or have any
4632N/A * questions.
4632N/A */
4632N/A
4632N/Apackage com.apple.laf;
4632N/A
4632N/Aimport java.awt.*;
4632N/Aimport java.awt.image.BufferedImage;
4632N/A
4632N/Aimport javax.swing.*;
4632N/Aimport javax.swing.border.Border;
4891N/Aimport javax.swing.plaf.UIResource;
4632N/Aimport javax.swing.plaf.basic.BasicHTML;
4632N/Aimport javax.swing.text.View;
4632N/A
4632N/Aimport apple.laf.*;
4632N/Aimport apple.laf.JRSUIConstants.*;
4632N/Aimport apple.laf.JRSUIState.ValueState;
4632N/A
4632N/Aimport com.apple.laf.AquaUtilControlSize.*;
4632N/Aimport com.apple.laf.AquaUtils.RecyclableSingleton;
4632N/A
4632N/Apublic abstract class AquaButtonLabeledUI extends AquaButtonToggleUI implements Sizeable {
4632N/A protected static RecyclableSizingIcon regularIcon = new RecyclableSizingIcon(18);
4632N/A protected static RecyclableSizingIcon smallIcon = new RecyclableSizingIcon(16);
4632N/A protected static RecyclableSizingIcon miniIcon = new RecyclableSizingIcon(14);
4632N/A
4632N/A protected static class RecyclableSizingIcon extends RecyclableSingleton<Icon> {
4632N/A final int iconSize;
4632N/A public RecyclableSizingIcon(final int iconSize) { this.iconSize = iconSize; }
4632N/A
4632N/A protected Icon getInstance() {
4632N/A return new ImageIcon(new BufferedImage(iconSize, iconSize, BufferedImage.TYPE_INT_ARGB_PRE));
4632N/A }
4632N/A }
4632N/A
4632N/A protected AquaButtonBorder widgetBorder;
4632N/A
4632N/A public AquaButtonLabeledUI() {
4632N/A widgetBorder = getPainter();
4632N/A }
4632N/A
4632N/A public void applySizeFor(final JComponent c, final Size newSize) {
4632N/A super.applySizeFor(c, newSize);
4632N/A widgetBorder = (AquaButtonBorder)widgetBorder.deriveBorderForSize(newSize);
4632N/A }
4632N/A
4632N/A public Icon getDefaultIcon(final JComponent c) {
4632N/A final Size componentSize = AquaUtilControlSize.getUserSizeFrom(c);
4632N/A if (componentSize == Size.REGULAR) return regularIcon.get();
4632N/A if (componentSize == Size.SMALL) return smallIcon.get();
4632N/A if (componentSize == Size.MINI) return miniIcon.get();
4632N/A return regularIcon.get();
4632N/A }
4632N/A
4632N/A protected void setThemeBorder(final AbstractButton b) {
4632N/A super.setThemeBorder(b);
4632N/A
4891N/A Border border = b.getBorder();
4891N/A if (border == null || border instanceof UIResource) {
4891N/A // Set the correct border
4891N/A b.setBorder(AquaButtonBorder.getBevelButtonBorder());
4891N/A }
4632N/A }
4632N/A
4632N/A protected abstract AquaButtonBorder getPainter();
4632N/A
4632N/A public synchronized void paint(final Graphics g, final JComponent c) {
4632N/A final AbstractButton b = (AbstractButton)c;
4632N/A final ButtonModel model = b.getModel();
4632N/A
4632N/A final Font f = c.getFont();
4632N/A g.setFont(f);
4632N/A final FontMetrics fm = g.getFontMetrics();
4632N/A
4632N/A Dimension size = b.getSize();
4632N/A
4632N/A final Insets i = c.getInsets();
4632N/A
4632N/A Rectangle viewRect = new Rectangle(b.getWidth(), b.getHeight());
4632N/A Rectangle iconRect = new Rectangle();
4632N/A Rectangle textRect = new Rectangle();
4632N/A
4632N/A Icon altIcon = b.getIcon();
4632N/A
4632N/A final boolean isCellEditor = c.getParent() instanceof CellRendererPane;
4632N/A
4632N/A // This was erroneously removed to fix [3155996] but really we wanted the controls to just be
4632N/A // opaque. So we put this back in to fix [3179839] (radio buttons not being translucent)
4632N/A if (b.isOpaque() || isCellEditor) {
4632N/A g.setColor(b.getBackground());
4632N/A g.fillRect(0, 0, size.width, size.height);
4632N/A }
4632N/A
4632N/A // only do this if borders are on!
4632N/A if (((AbstractButton)c).isBorderPainted() && !isCellEditor) {
4632N/A final Border border = c.getBorder();
4632N/A if (border instanceof AquaButtonBorder) {
4632N/A ((AquaButtonBorder)border).paintButton(c, g, viewRect.x, viewRect.y, viewRect.width, viewRect.height);
4632N/A }
4632N/A }
4632N/A
4632N/A viewRect.x = i.left;
4632N/A viewRect.y = i.top;
4632N/A viewRect.width = b.getWidth() - (i.right + viewRect.x);
4632N/A viewRect.height = b.getHeight() - (i.bottom + viewRect.y);
4632N/A
4632N/A // normal size ??
4632N/A // at some point we substitute the small icon instead of the normal icon
4632N/A // we should base this on height. Use normal unless we are under a certain size
4632N/A // see our button code!
4632N/A
4632N/A final String text = SwingUtilities.layoutCompoundLabel(c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(b), b.getVerticalAlignment(), b.getHorizontalAlignment(), b.getVerticalTextPosition(), b.getHorizontalTextPosition(), viewRect, iconRect, textRect, b.getText() == null ? 0 : b.getIconTextGap());
4632N/A
4632N/A // fill background
4632N/A
4632N/A // draw the native radio button stuff here.
4632N/A if (altIcon == null) {
4632N/A widgetBorder.paintButton(c, g, iconRect.x, iconRect.y, iconRect.width, iconRect.height);
4632N/A } else {
4632N/A // Paint the button
4632N/A if (!model.isEnabled()) {
4632N/A if (model.isSelected()) {
4632N/A altIcon = b.getDisabledSelectedIcon();
4632N/A } else {
4632N/A altIcon = b.getDisabledIcon();
4632N/A }
4632N/A } else if (model.isPressed() && model.isArmed()) {
4632N/A altIcon = b.getPressedIcon();
4632N/A if (altIcon == null) {
4632N/A // Use selected icon
4632N/A altIcon = b.getSelectedIcon();
4632N/A }
4632N/A } else if (model.isSelected()) {
4632N/A if (b.isRolloverEnabled() && model.isRollover()) {
4632N/A altIcon = b.getRolloverSelectedIcon();
4632N/A if (altIcon == null) {
4632N/A altIcon = b.getSelectedIcon();
4632N/A }
4632N/A } else {
4632N/A altIcon = b.getSelectedIcon();
4632N/A }
4632N/A } else if (b.isRolloverEnabled() && model.isRollover()) {
4632N/A altIcon = b.getRolloverIcon();
4632N/A }
4632N/A
4632N/A if (altIcon == null) {
4632N/A altIcon = b.getIcon();
4632N/A }
4632N/A
4632N/A altIcon.paintIcon(c, g, iconRect.x, iconRect.y);
4632N/A }
4632N/A
4632N/A // Draw the Text
4632N/A if (text != null) {
4632N/A final View v = (View)c.getClientProperty(BasicHTML.propertyKey);
4632N/A if (v != null) {
4632N/A v.paint(g, textRect);
4632N/A } else {
4632N/A paintText(g, b, textRect, text);
4632N/A }
4632N/A }
4632N/A }
4632N/A
4632N/A /**
4632N/A * The preferred size of the button
4632N/A */
4632N/A public Dimension getPreferredSize(final JComponent c) {
4632N/A if (c.getComponentCount() > 0) { return null; }
4632N/A
4632N/A final AbstractButton b = (AbstractButton)c;
4632N/A
4632N/A final String text = b.getText();
4632N/A
4632N/A Icon buttonIcon = b.getIcon();
4632N/A if (buttonIcon == null) {
4632N/A buttonIcon = getDefaultIcon(b);
4632N/A }
4632N/A
4632N/A final Font font = b.getFont();
4632N/A final FontMetrics fm = b.getFontMetrics(font);
4632N/A
4632N/A Rectangle prefViewRect = new Rectangle(Short.MAX_VALUE, Short.MAX_VALUE);
4632N/A Rectangle prefIconRect = new Rectangle();
4632N/A Rectangle prefTextRect = new Rectangle();
4632N/A
4632N/A SwingUtilities.layoutCompoundLabel(c, fm, text, buttonIcon, b.getVerticalAlignment(), b.getHorizontalAlignment(), b.getVerticalTextPosition(), b.getHorizontalTextPosition(), prefViewRect, prefIconRect, prefTextRect, text == null ? 0 : b.getIconTextGap());
4632N/A
4632N/A // find the union of the icon and text rects (from Rectangle.java)
4632N/A final int x1 = Math.min(prefIconRect.x, prefTextRect.x);
4632N/A final int x2 = Math.max(prefIconRect.x + prefIconRect.width, prefTextRect.x + prefTextRect.width);
4632N/A final int y1 = Math.min(prefIconRect.y, prefTextRect.y);
4632N/A final int y2 = Math.max(prefIconRect.y + prefIconRect.height, prefTextRect.y + prefTextRect.height);
4632N/A int width = x2 - x1;
4632N/A int height = y2 - y1;
4632N/A
4632N/A Insets prefInsets = b.getInsets();
4632N/A width += prefInsets.left + prefInsets.right;
4632N/A height += prefInsets.top + prefInsets.bottom;
4632N/A return new Dimension(width, height);
4632N/A }
4632N/A
4632N/A public static abstract class LabeledButtonBorder extends AquaButtonBorder {
4632N/A public LabeledButtonBorder(final SizeDescriptor sizeDescriptor) {
4632N/A super(sizeDescriptor);
4632N/A }
4632N/A
4632N/A public LabeledButtonBorder(final LabeledButtonBorder other) {
4632N/A super(other);
4632N/A }
4632N/A
4632N/A @Override
4632N/A protected AquaPainter<? extends JRSUIState> createPainter() {
4632N/A final AquaPainter<ValueState> painter = AquaPainter.create(JRSUIStateFactory.getLabeledButton());
4632N/A painter.state.set(AlignmentVertical.CENTER);
4632N/A painter.state.set(AlignmentHorizontal.CENTER);
4632N/A return painter;
4632N/A }
4632N/A
4632N/A protected void doButtonPaint(final AbstractButton b, final ButtonModel model, final Graphics g, final int x, final int y, final int width, final int height) {
4632N/A painter.state.set(AquaUtilControlSize.getUserSizeFrom(b));
4632N/A ((ValueState)painter.state).setValue(model.isSelected() ? isIndeterminate(b) ? 2 : 1 : 0); // 2=mixed, 1=on, 0=off
4632N/A super.doButtonPaint(b, model, g, x, y, width, height);
4632N/A }
4632N/A
4632N/A protected State getButtonState(final AbstractButton b, final ButtonModel model) {
4632N/A final State state = super.getButtonState(b, model);
4632N/A
4632N/A if (state == State.INACTIVE) return State.INACTIVE;
4632N/A if (state == State.DISABLED) return State.DISABLED;
4632N/A if (model.isArmed() && model.isPressed()) return State.PRESSED;
4632N/A if (model.isSelected()) return State.ACTIVE;
4632N/A
4632N/A return state;
4632N/A }
4632N/A
4632N/A static boolean isIndeterminate(final AbstractButton b) {
4632N/A return "indeterminate".equals(b.getClientProperty("JButton.selectedState"));
4632N/A }
4632N/A }
4632N/A}