/*
* @(#)QuaquaNativeButtonBorder.java
*
* Copyright (c) 2011 Werner Randelshofer, Immensee, Switzerland.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
*/
package ch.randelshofer.quaqua;
import java.util.Iterator;
import java.util.HashSet;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.Timer;
import javax.swing.JButton;
import ch.randelshofer.quaqua.border.PressedCueBorder;
import javax.swing.JToolBar;
import java.util.HashMap;
import ch.randelshofer.quaqua.border.CompositeVisualMarginBorder;
import ch.randelshofer.quaqua.border.VisualMarginBorder;
import ch.randelshofer.quaqua.util.Images;
import ch.randelshofer.quaqua.border.ButtonStateBorder;
import ch.randelshofer.quaqua.util.InsetsUtil;
import ch.randelshofer.quaqua.border.BackgroundBorder;
import ch.randelshofer.quaqua.border.FocusedBorder;
import javax.swing.JComponent;
import ch.randelshofer.quaqua.osx.OSXAquaPainter;
import ch.randelshofer.quaqua.util.CachedPainter;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.border.Border;
import static ch.randelshofer.quaqua.osx.OSXAquaPainter.*;
/**
* Native Aqua border for an {@code AbstractButton}.
*
* @author Werner Randelshofer
* @version $Id$
*/
public class QuaquaNativeButtonBorder extends VisualMarginBorder implements Border, PressedCueBorder, BackgroundBorder {
/** Each border type needs to be tweaked in a different way.
* We collect all the tweaks here.
*/
private static class WidgetConfig {
/** The type name used in JButton.buttonType and Quaqua.Button.style. */
String[] type;
/** The native widget id. */
Widget widget;
/** Whether the button needs the trailing separator hack. */
boolean needsTrailingSeparatorHack;
Insets[] margin = new Insets[3];
/** Border insets.
* regular,small,mini
*/
Insets[] borderInsets = new Insets[3];
/** Image insets are used when rendering the native widget onto an image,
* so that native widget's visual bounds are rendered with a fixed
* inset of 3,3,3,3 into the image. The fixed inset allows for cast
* shadows in the image.
*
* only regular,small,mini,
* first regular,small,mini,
* middle regular,small,mini,
* last regular small,mini
*/
Insets[][] imageInsets = new Insets[4][3];
}
private final static HashMap<String, WidgetConfig> wcs;
static {
Object[][] a = {//
// name, hasVisualMargin,widget,border insets, margin insets, image insets
{"push", false, Widget.buttonPush, //
new Insets[]{new Insets(1, 3, 2, 3), new Insets(1, 3, 1, 3), new Insets(1, 2, 1, 2)},//
new Insets[]{new Insets(1, 14, 1, 14), new Insets(1, 5, 1, 5), new Insets(1, 4, 1, 4)},//
new Insets[]{new Insets(2, -3, 0, -3), new Insets(2, -2, 0, -2), new Insets(1, 2, 0, 2)}},
{"square", false, Widget.buttonBevel, //
new Insets[]{new Insets(1, 1, 1, 1), new Insets(1, 1, 1, 1), new Insets(1, 1, 1, 1)},//
new Insets[]{new Insets(2, 8, 2, 8), new Insets(1, 5, 1, 5), new Insets(1, 4, 1, 4)},//
new Insets[]{
new Insets(3, 3, 3, 3), new Insets(3, 3, 3, 3), new Insets(3, 3, 3, 3),//only
new Insets(3, 3, 3, 2), new Insets(3, 3, 3, 2), new Insets(3, 3, 3, 2),// first
new Insets(3, 3, 3, 2), new Insets(3, 3, 3, 2), new Insets(3, 3, 3, 2),// middle
new Insets(3, 3, 3, 3), new Insets(3, 3, 3, 3), new Insets(3, 3, 3, 3)}},// last
{"bevel", false, Widget.buttonBevelRound, //
new Insets[]{new Insets(1, 1, 2, 1), new Insets(1, 1, 2, 1), new Insets(1, 1, 2, 1)},//
new Insets[]{new Insets(3, 13, 4, 13), new Insets(3, 9, 1, 9), new Insets(3, 7, 3, 7)},//
new Insets[]{new Insets(1, 1, 1, 1), new Insets(1, 1, 1, 1), new Insets(1, 1, 1, 1)}},
{"gradient", "placard", false, Widget.buttonBevelInset, //
new Insets[]{new Insets(1, 1, 1, 1), new Insets(1, 1, 1, 1), new Insets(1, 1, 1, 1)},//
new Insets[]{new Insets(2, 8, 2, 8), new Insets(1, 5, 1, 5), new Insets(1, 4, 1, 4)},//
new Insets[]{
new Insets(2, 3, 2, 3), new Insets(2, 3, 2, 3), new Insets(2, 3, 2, 3),// only
new Insets(2, 3, 2, 2), new Insets(2, 3, 2, 2), new Insets(2, 3, 2, 2),// first
new Insets(2, 3, 2, 2), new Insets(2, 3, 2, 2), new Insets(2, 3, 2, 2),// middle
new Insets(2, 3, 2, 3), new Insets(2, 3, 2, 3), new Insets(2, 3, 2, 3)}},// last
{"tableHeader", false, Widget.buttonListHeader, //
new Insets[]{new Insets(2, 4, 2, 4), new Insets(2, 4, 2, 4), new Insets(2, 4, 2, 4)},//
new Insets[]{new Insets(1, 4, 1, 4), new Insets(1, 2, 1, 2), new Insets(1, 2, 1, 2)},//
new Insets[]{new Insets(0, 2, 0, 3), new Insets(0, 2, 0, 3), new Insets(0, 2, 0, 3)}},
{"textured", false, Widget.buttonPushTextured, //
new Insets[]{new Insets(1, 3, 2, 3), new Insets(1, 3, 1, 3), new Insets(1, 2, 1, 2)},//
new Insets[]{new Insets(1, 14, 1, 14), new Insets(1, 5, 1, 5), new Insets(1, 4, 1, 4)},//
new Insets[]{new Insets(3, 3, 2, 3), new Insets(3, 3, 2, 3), new Insets(1, 3, 0, 3)}},
{"roundRect", false, Widget.buttonPushInset, //
new Insets[]{new Insets(1, 5, 1, 5), new Insets(1, 3, 1, 3), new Insets(1, 3, 1, 3)},//
new Insets[]{new Insets(0, 6, 0, 6), new Insets(0, 5, 0, 5), new Insets(0, 4, 0, 4)},//
new Insets[]{new Insets(0, 2, 0, 2), new Insets(0, 2, 0, 2), new Insets(1, 2, 0, 2)}},
{"recessed", false, Widget.buttonPushScope, //
new Insets[]{new Insets(1, 7, 1, 7), new Insets(1, 5, 1, 5), new Insets(1, 5, 1, 5)},//
new Insets[]{new Insets(0, 6, 0, 6), new Insets(0, 5, 0, 5), new Insets(0, 4, 0, 4)},//
new Insets[]{new Insets(0, 2, 0, 2), new Insets(0, 2, 0, 2), new Insets(1, 2, 0, 2)}},
{"colorWell", false, null, //
new Insets[]{new Insets(7, 6, 7, 6), new Insets(7, 6, 7, 6), new Insets(7, 6, 7, 6)},//
new Insets[]{new Insets(1, 10, 1, 10), new Insets(1, 8, 1, 8), new Insets(1, 8, 1, 8)},//
null},
{"help", false, Widget.buttonRoundHelp, //
new Insets[]{new Insets(0, 0, 0, 0), new Insets(0, 0, 0, 0), new Insets(0, 0, 0, 0)},//
new Insets[]{new Insets(1, 4, 1, 4), new Insets(1, 2, 1, 2), new Insets(1, 2, 1, 2)},//
new Insets[]{new Insets(0, 0, 0, 0), new Insets(0, 0, 0, 0), new Insets(0, 0, 0, 0)}},
{"toolBar", false, null, //
new Insets[]{new Insets(3, 3, 3, 3), new Insets(3, 3, 3, 3), new Insets(3, 3, 3, 3)},//
new Insets[]{new Insets(1, 4, 1, 4), new Insets(1, 2, 1, 2), new Insets(1, 2, 1, 2)},//
new Insets[]{new Insets(0, 0, 0, 0), new Insets(0, 0, 0, 0), new Insets(0, 0, 0, 0)}},
{"segmented", "toggle", "toggleEast", "toggleCenter", "toggleWest", true, Widget.buttonSegmented,//
new Insets[]{new Insets(2, 13, 3, 13), new Insets(2, 8, 2, 8), new Insets(2, 7, 2, 7)},//
new Insets[]{new Insets(1, 4, 1, 4), new Insets(1, 2, 1, 2), new Insets(1, 2, 1, 2)},//
new Insets[]{new Insets(0, 1, 0, 1), new Insets(1, 1, 0, 1), new Insets(0, 2, 0, 2),//only regular,small,mini
new Insets(0, 1, 0, 0), new Insets(1, 1, 0, 0), new Insets(0, 2, 0, 0),//first
new Insets(0, 0, 0, 0), new Insets(1, 0, 0, 1), new Insets(0, 0, 0, 0),//middle
new Insets(0, 0, 0, 1), new Insets(1, 1, 0, 1), new Insets(0, 0, 0, 2)}},//last
{"segmentedRoundRect", "segmentedCapsule", "segmentedTextured", true, Widget.buttonSegmentedInset,//
new Insets[]{new Insets(2, 13, 3, 13), new Insets(2, 8, 2, 8), new Insets(2, 7, 2, 7)},//
new Insets[]{new Insets(1, 4, 1, 4), new Insets(1, 2, 1, 2), new Insets(1, 2, 1, 2)},//
new Insets[]{new Insets(0, 1, 0, 1), new Insets(0, 1, 0, 1), new Insets(0, 2, 0, 2),//only regular,small,mini
new Insets(0, 1, 0, 0), new Insets(1, 1, 0, 0), new Insets(0, 2, 0, 0),//first
new Insets(0, 0, 0, 0), new Insets(1, 0, 0, 1), new Insets(0, 0, 0, 0),//middle
new Insets(0, 0, 0, 1), new Insets(1, 1, 0, 1), new Insets(0, 0, 0, 2)}},//last
};
wcs = new HashMap<String, WidgetConfig>();
for (int i = 0; i < a.length; i++) {
int j = 0;
int numNames = 0;
WidgetConfig wp = new WidgetConfig();
while (j < a[i].length) {
while (a[i][j++] instanceof String) {
}
numNames = --j;
//wp.hasVisualMargin = (Boolean) a[i][j++];
wp.needsTrailingSeparatorHack = (Boolean) a[i][j++];
wp.widget = (Widget) a[i][j++];
Insets[] bi = (Insets[]) a[i][j++];
wp.borderInsets[0] = bi[0];
wp.borderInsets[1] = bi[1];
wp.borderInsets[2] = bi[2];
Insets[] mi = (Insets[]) a[i][j++];
wp.margin[0] = mi[0];
wp.margin[1] = mi[1];
wp.margin[2] = mi[2];
Insets[] ii = (Insets[]) a[i][j++];
if (ii != null) {
int k = 0;
wp.imageInsets[0][0] = ii[0];
wp.imageInsets[0][1] = ii[1];
wp.imageInsets[0][2] = ii[2];
wp.imageInsets[1][0] = (ii.length == 3) ? ii[0] : ii[3];
wp.imageInsets[1][1] = (ii.length == 3) ? ii[1] : ii[4];
wp.imageInsets[1][2] = (ii.length == 3) ? ii[2] : ii[5];
wp.imageInsets[2][0] = (ii.length == 3) ? ii[0] : ii[6];
wp.imageInsets[2][1] = (ii.length == 3) ? ii[1] : ii[7];
wp.imageInsets[2][2] = (ii.length == 3) ? ii[2] : ii[8];
wp.imageInsets[3][0] = (ii.length == 3) ? ii[0] : ii[9];
wp.imageInsets[3][1] = (ii.length == 3) ? ii[1] : ii[10];
wp.imageInsets[3][2] = (ii.length == 3) ? ii[2] : ii[11];
}
}
for (j = 0; j < numNames; j++) {
wcs.put((String) a[i][j], wp);
}
}
}
private OSXAquaPainter painter;
private Insets imageInsets;
private Border backgroundBorder;
/** The background border.
* This border delegates the actual painting to different borders, because
* {@link OSXAquaPainter} can not render all borders that we need.
*/
private class BGBorder implements Border, PressedCueBorder, VisualMargin {
private PressedCueBorder nativeBorder;
private PressedCueBorder bevelBorder;
private PressedCueBorder placardBorder;
private PressedCueBorder toolBarBorder;
private PressedCueBorder toolBarTabBorder;
private PressedCueBorder colorWellBorder;
private PressedCueBorder getActualBorder(Component c) {
String s = getStyle(c);
WidgetConfig wp = wcs.get(s);
//return w==null?bevelBorder:nativeBorder;
PressedCueBorder b;
if (wp == null || wp.widget == null) {
if ("colorWell".equals(s)) {
b = getColorWellBorder();
} else if ("toolBar".equals(s)) {
b = getToolBarBorder();
} else if ("toolBarTab".equals(s)) {
b = getToolBarTabBorder();
} else {
b = getBevelBorder();
}
} else {
b = getNativeBorder();
}
return b;
}
private PressedCueBorder getBevelBorder() {
if (bevelBorder == null) {
bevelBorder = new FocusedBorder(
new CompositeVisualMarginBorder(
new ButtonStateBorder(
Images.createImage(QuaquaButtonBorder.class.getResource("images/RoundedBevel.borders.png")), 10, true,
new Insets(10, 9, 10, 8), new Insets(0, 0, 0, 0), true),
3, 2, 2, 2));
}
return bevelBorder;
}
private PressedCueBorder getNativeBorder() {
if (nativeBorder == null) {
this.nativeBorder =
new FocusedBorder(new NativeBGBorder());
}
return nativeBorder;
}
private PressedCueBorder getPlacardBorder() {
if (placardBorder == null) {
// The placarBorder does not have a dynamic visual margin.
placardBorder = new FocusedBorder(
new CompositeVisualMarginBorder(
new QuaquaPlacardButtonBorder(),
1, 0, 1, 0));
}
return placardBorder;
}
private PressedCueBorder getToolBarBorder() {
if (toolBarBorder == null) {
// The placardBorder does not have a dynamic visual margin.
toolBarBorder =
new VisualMarginBorder(0, 4, 0, 4) {
@Override
public boolean hasPressedCue(JComponent c) {
return false;
}
};
}
return toolBarBorder;
}
private PressedCueBorder getColorWellBorder() {
if (colorWellBorder == null) {
colorWellBorder = new FocusedBorder(
new CompositeVisualMarginBorder(
new QuaquaColorWellBorder(),
0, 0, 0, 0));
}
return colorWellBorder;
}
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
getActualBorder(c).paintBorder(c, g, x, y, width, height);
}
public Insets getBorderInsets(Component c) {
return getActualBorder(c).getBorderInsets(c);
}
public boolean isBorderOpaque() {
return false;
}
public Insets getVisualMargin(Component c) {
return ((VisualMargin) getActualBorder(c)).getVisualMargin(c);
}
public boolean hasPressedCue(JComponent c) {
return getActualBorder(c).hasPressedCue(c);
}
private PressedCueBorder getToolBarTabBorder() {
if (toolBarTabBorder==null)
toolBarTabBorder = new QuaquaToolBarTabButtonBorder();
return toolBarTabBorder;
}
}
/** This is the actual native button border. */
private class NativeBGBorder extends CachedPainter implements PressedCueBorder, VisualMargin {
private final static int ARG_ACTIVE = 0;
private final static int ARG_PRESSED = 1;
private final static int ARG_DISABLED = 2;
private final static int ARG_ROLLOVER = 3;
private final static int ARG_SELECTED = 4;
private final static int ARG_FOCUSED = 5;
private final static int ARG_PULSED = 6;
private final static int ARG_SIZE_VARIANT = 7;//2 bits
private final static int ARG_SEGPOS = 9;
private final static int ARG_WIDGET = 12;// 7 bits
private final static int ARG_TRAILING_SEPARATOR = 19;
private final static int ARG_TRAILING_SEPARATOR_HACK = 20;
private final static int ARG_ANIM_FRAME = 21;
public NativeBGBorder() {
super(12);
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
AbstractButton b = null;
JComponent jc = null;
ButtonModel bm = null;
if (c instanceof AbstractButton) {
b = (AbstractButton) c;
jc = b;
bm = b.getModel();
} else if (c instanceof JComponent) {
jc = (JComponent) c;
}
String s = getStyle(c);
WidgetConfig wc = wcs.get(s);
Widget widget = wc.widget;
int args = 0;
OSXAquaPainter.State state;
if (QuaquaUtilities.isOnActiveWindow(c)) {
state = OSXAquaPainter.State.active;
args |= 1 << ARG_ACTIVE;
if (b instanceof JButton && ((JButton) b).isDefaultButton()) {
state = OSXAquaPainter.State.pulsed;
args |= 1 << ARG_PULSED;
long animationTime = System.currentTimeMillis();
args |= animationTime << ARG_ANIM_FRAME;
painter.setValueByKey(Key.animationTime, animationTime / 1000d);
}
} else {
state = OSXAquaPainter.State.inactive;
}
if (bm != null) {
if (bm.isRollover()) {
state = OSXAquaPainter.State.rollover;
args |= 1 << ARG_ROLLOVER;
}
if (bm.isArmed() && bm.isPressed()) {
state = OSXAquaPainter.State.pressed;
args |= 1 << ARG_PRESSED;
}
if (!bm.isEnabled()) {
state = OSXAquaPainter.State.disabled;
args |= 1 << ARG_DISABLED;
}
}
painter.setState(state);
int value = b == null ? 0 : (b.isSelected() ? 1 : 0);
painter.setValueByKey(Key.value, value);
args |= value << ARG_SELECTED;
boolean isFocused = QuaquaUtilities.isFocused(c);
painter.setValueByKey(Key.focused, isFocused ? 1 : 0);
args |= (isFocused) ? 1 << ARG_FOCUSED : 0;
Size size;
switch (QuaquaUtilities.getSizeVariant(c)) {
case REGULAR:
default:
size = Size.regular;
args |= 0 << ARG_SIZE_VARIANT;
break;
case SMALL:
size = Size.small;
args |= 1 << ARG_SIZE_VARIANT;
break;
case LARGE:
size = Size.large;
args |= 2 << ARG_SIZE_VARIANT;
break;
case MINI:
size = Size.mini;
args |= 3 << ARG_SIZE_VARIANT;
break;
}
painter.setSize(size);
SegmentPosition segpos = getSegmentPosition(c);
painter.setSegmentPosition(segpos);
args |= segpos.getId() << ARG_SEGPOS;
switch (segpos) {
case first:
case middle:
painter.setValueByKey(Key.segmentTrailingSeparator, 1);
args |= 1 << ARG_TRAILING_SEPARATOR;
if (wc.needsTrailingSeparatorHack) {
args |= 1 << ARG_TRAILING_SEPARATOR_HACK;
}
break;
default:
painter.setValueByKey(Key.segmentTrailingSeparator, 0);
}
args |= widget.getId() << ARG_WIDGET;
painter.setWidget(widget);
int sizeIndex;
switch (size) {
case regular:
default:
sizeIndex = 0;
break;
case small:
sizeIndex = 1;
break;
case mini:
sizeIndex = 2;
break;
}
int segIndex;
switch (segpos) {
case first:
segIndex = 1;
break;
case middle:
segIndex = 2;
break;
case last:
segIndex = 3;
break;
case only:
default:
segIndex = 0;
break;
}
imageInsets = wc.imageInsets[segIndex][sizeIndex];
paint(c, g, x, y, width, height, args);
}
@Override
protected Image createImage(Component c, int w, int h,
GraphicsConfiguration config) {
return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
}
@Override
protected void paintToImage(Component c, Image img, int w, int h, Object argso) {
Graphics2D ig = (Graphics2D) img.getGraphics();
ig.setColor(new Color(0x0, true));
ig.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
ig.fillRect(0, 0, img.getWidth(null), img.getHeight(null));
ig.dispose();
Insets vm = getVisualMargin(c);
painter.paint((BufferedImage) img,//
imageInsets.left - 3 + vm.left, //
imageInsets.top - 3 + vm.top,//
w - imageInsets.left - imageInsets.right + 6 - vm.left - vm.right, //
h - imageInsets.top - imageInsets.bottom + 6 - vm.top - vm.bottom);
// Workaround for trailing separators: for some reason they are not
// drawn, so we draw them by ourselves.
// FIXME - The color and offsets of the saparator should not be
// hardcoded here.
int args = (Integer) argso;
if ((args & (1 << ARG_TRAILING_SEPARATOR_HACK)) != 0) {
Graphics2D g = ((BufferedImage) img).createGraphics();
g.setColor(new Color(0xeabbbbbb, true));
g.drawLine(w - 1, 6, w - 1, h - 8);
g.dispose();
}
}
@Override
protected void paintToImage(Component c, Graphics g, int w, int h, Object args) {
// round up image size to reduce memory thrashing
BufferedImage img = (BufferedImage) createImage(c, (w / 32 + 1) * 32, (h / 32 + 1) * 32, null);
paintToImage(c, img, w, h, args);
g.drawImage(img, 0, 0, null);
img.flush();
}
/** Returns fake insets since this is just a background border.
* The real insets are returned by {@link QuaquaNativeButtonBorder#getBorderInsets}.
*/
public Insets getBorderInsets(Component c) {
return new Insets(0, 0, 0, 0);
}
public boolean isBorderOpaque() {
return false;
}
public Insets getVisualMargin(Component c) {
Insets i = QuaquaNativeButtonBorder.this.getVisualMargin(c);
return i;
}
public boolean hasPressedCue(JComponent c) {
return true;
}
}
public QuaquaNativeButtonBorder() {
super(new Insets(0, 0, 0, 0));
painter = new OSXAquaPainter();
this.imageInsets = new Insets(0, 0, 0, 0);
}
public Border getBackgroundBorder() {
if (backgroundBorder == null) {
this.backgroundBorder = new BGBorder();
}
return backgroundBorder;
}
@Override
public boolean hasPressedCue(JComponent c) {
Border b = getBackgroundBorder();
if (b instanceof PressedCueBorder) {
return ((PressedCueBorder) b).hasPressedCue(c);
}
return true;
}
private String getStyle(Component c) {
String s = null;
if (c instanceof JComponent) {
JComponent jc = (JComponent) c;
s = (String) jc.getClientProperty("Quaqua.Button.style");
if (s == null) {
s = (String) jc.getClientProperty("JButton.buttonType");
}
}
if (s == null) {
if (c.getParent() instanceof JToolBar) {
String tbs = (String) ((JToolBar) c.getParent()).getClientProperty("Quaqua.ToolBar.style");
if ("gradient".equals(tbs) || "placard".equals(tbs)) {
s = "gradient";
} else {
s = "toolBar";
}
}
}
if (s == null || "push".equals(s)) {
// must call super here, because visualmargin is based on style
Insets vm = super.getVisualMargin(c, new Insets(0, 0, 0, 0));
// push buttons can only have an inner size of 21 pixels or less
if (c.getHeight() - vm.top - vm.bottom > 21
|| QuaquaUtilities.getSizeVariant(c) == QuaquaUtilities.SizeVariant.LARGE) {
s = "bevel";
}
}
// coerce synonyms
if ("placard".equals(s) || "segmentedGradient".equals("")) {
s = "gradient";
}
return (s == null) ? "push" : s;
}
/*
private Widget getWidget(Component c) {
String s = getStyle(c);
WidgetProperty wp = wps.get(s);
return (wp == null) ? null : wp.widget;
}*/
private SegmentPosition getSegmentPosition(Component c) {
String s = null;
if (c instanceof JComponent) {
JComponent jc = (JComponent) c;
s = (String) jc.getClientProperty("Quaqua.Button.style");
if (s != null) {
if ("toggleWest".equals(s)) {
return SegmentPosition.first;
} else if ("toggleCenter".equals(s)) {
return SegmentPosition.middle;
} else if ("toggleEast".equals(s)) {
return SegmentPosition.last;
}
}
s = (String) jc.getClientProperty("JButton.segmentPosition");
if (s != null) {
if ("first".equals(s)) {
return SegmentPosition.first;
} else if ("middle".equals(s)) {
return SegmentPosition.middle;
} else if ("last".equals(s)) {
return SegmentPosition.last;
}
}
}
return SegmentPosition.only;
}
@Override
protected Insets getVisualMargin(Component c, Insets insets) {
String s = getStyle(c);
insets = super.getVisualMargin(c, insets);
if (insets instanceof javax.swing.plaf.UIResource) {
if ("gradient".equals(s) && (c.getParent() instanceof JToolBar)) {
String ts = (String) ((JToolBar) c.getParent()).getClientProperty("Quaqua.ToolBar.style");
if ("placard".equals(ts) || "gradient".equals(ts)) {
InsetsUtil.clear(insets);
}
}
}
WidgetConfig wc = wcs.get(s);
if (insets instanceof javax.swing.plaf.UIResource) {
switch (getSegmentPosition(c)) {
case first:
insets.right = 0;
break;
case middle:
insets.left = insets.right = 0;
break;
case last:
insets.left = 0;
break;
}
}
return insets;
}
@Override
public Insets getBorderInsets(Component c, Insets insets) {
if (c instanceof JComponent) {
Insets i = (Insets) ((JComponent) c).getClientProperty("Quaqua.Border.insets");
if (i != null) {
InsetsUtil.setTo(i, insets);
return insets;
}
}
String s = getStyle(c);
QuaquaUtilities.SizeVariant size = QuaquaUtilities.getSizeVariant(c);
WidgetConfig wc = wcs.get(s);
Insets i = getVisualMargin(c, insets);
int sizeIndex;
switch (size) {
case REGULAR:
default:
sizeIndex = 0;
break;
case SMALL:
sizeIndex = 1;
break;
case MINI:
sizeIndex = 2;
break;
}
if (wc != null) {
Insets borderInsets = wc.borderInsets[sizeIndex];
InsetsUtil.addTo(borderInsets, i);
}
if (c instanceof AbstractButton) {
AbstractButton b = (AbstractButton) c;
Insets margin = b.getMargin();
if (margin == null || (margin instanceof javax.swing.plaf.UIResource)) {
if (b.isBorderPainted()) {
margin = wc==null||wc.margin.length<=sizeIndex?null:wc.margin[sizeIndex];
}
}
if (margin != null) {
InsetsUtil.addTo(margin, i);
}
}
return i;
}
@Override
public boolean isBorderOpaque() {
return false;
}
public static class UIResource extends QuaquaNativeButtonBorder implements javax.swing.plaf.UIResource {
public UIResource() {
super();
}
}
}