diff --git a/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonBorder.java b/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonBorder.java index 8a69c09e..b7fecff6 100644 --- a/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonBorder.java +++ b/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonBorder.java @@ -23,6 +23,7 @@ */ package com.github.weisj.darklaf.ui.button; +import com.github.weisj.darklaf.util.AlignmentExt; import com.github.weisj.darklaf.util.DarkUIUtil; import com.github.weisj.darklaf.util.GraphicsContext; @@ -87,6 +88,51 @@ public class DarkButtonBorder implements Border, UIResource { if (labelInsets == null) labelInsets = new Insets(0, 0, 0, 0); } + public static boolean showDropShadow(final JComponent c) { + return showDropShadow(getCornerFlag(c)); + } + + public static boolean showDropShadow(final AlignmentExt a) { + return a == null + || a == AlignmentExt.SOUTH + || a == AlignmentExt.SOUTH_EAST + || a == AlignmentExt.SOUTH_WEST + || a == AlignmentExt.LEFT + || a == AlignmentExt.RIGHT + || a == AlignmentExt.BOTTOM + || a == AlignmentExt.MIDDLE_HORIZONTAL; + } + + protected int getArc(final Component c) { + if (DarkButtonUI.isNoArc(c)) return 0; + boolean square = DarkButtonUI.isSquare(c); + boolean alt = DarkButtonUI.chooseAlternativeArc(c); + return square ? alt ? arc : squareArc : alt ? squareArc : arc; + } + + protected int getFocusArc(final Component c) { + if (DarkButtonUI.isNoArc(c)) return minimumArc; + boolean square = DarkButtonUI.isSquare(c); + boolean alt = DarkButtonUI.chooseAlternativeArc(c); + return square ? alt ? focusArc : squareFocusArc : alt ? squareFocusArc : focusArc; + } + + public static AlignmentExt getCornerFlag(final Component component) { + if (component instanceof JComponent) { + Object align = ((JComponent) component).getClientProperty(DarkButtonUI.KEY_CORNER); + return align instanceof AlignmentExt ? (AlignmentExt) align : null; + } + return null; + } + + protected int getShadowSize() { + return shadowSize; + } + + protected int getBorderSize() { + return borderSize; + } + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { @@ -99,50 +145,56 @@ public class DarkButtonBorder implements Border, UIResource { int arc = getArc(c); int focusArc = getFocusArc(c); GraphicsContext config = new GraphicsContext(g); + AlignmentExt corner = getCornerFlag(c); - if (c.isEnabled()) { - paintShadow(g2, width, height, arc); - } - - int shadowHeight = getShadowSize(); + boolean paintShadow = showDropShadow(corner); + int shadowHeight = paintShadow ? getShadowSize() : 0; int borderSize = getBorderSize(); + Insets insetMask = new Insets(borderSize, borderSize, borderSize, borderSize); + Insets focusIns = new Insets(0, 0, 0, 0); + if (corner != null) { + focusIns = corner.maskInsets(focusIns, -borderSize - focusArc); + insetMask = corner.maskInsets(insetMask, -arc); + } + + int bx = insetMask.left; + int by = insetMask.top; + int bw = width - insetMask.left - insetMask.right; + int bh = height - insetMask.top - insetMask.bottom; + int fx = focusIns.left; + int fy = focusIns.top; + int fw = width - focusIns.left - focusIns.right; + int fh = height - focusIns.top - focusIns.bottom; + + if (c.isEnabled() && paintShadow) { + paintShadow((Graphics2D) g, bx, by, bw, bh, arc); + } - if (c.hasFocus()) { - DarkUIUtil.paintFocusBorder(g2, width, height - shadowHeight, focusArc, borderSize); + if (paintFocus(c)) { + g.translate(fx, fy); + DarkUIUtil.paintFocusBorder(g2, fw, fh - shadowHeight, focusArc, borderSize); + g.translate(-fx, -fy); } g2.setColor(getBorderColor(c)); - DarkUIUtil.paintLineBorder(g2, borderSize, borderSize, width - 2 * borderSize, - height - 2 * borderSize - shadowHeight, arc); + DarkUIUtil.paintLineBorder(g2, bx, by, bw, bh - shadowHeight, arc); config.restore(); } - protected int getArc(final Component c) { - if (DarkButtonUI.isNoArc(c)) return 0; - boolean square = DarkButtonUI.isSquare(c); - boolean alt = DarkButtonUI.chooseAlternativeArc(c); - return square ? alt ? arc : squareArc : alt ? squareArc : arc; - } - - protected int getFocusArc(final Component c) { - if (DarkButtonUI.isNoArc(c)) return minimumArc; - boolean square = DarkButtonUI.isSquare(c); - boolean alt = DarkButtonUI.chooseAlternativeArc(c); - return square ? alt ? focusArc : squareFocusArc : alt ? squareFocusArc : focusArc; + protected boolean paintFocus(final Component c) { + if (c instanceof AbstractButton) { + return ((AbstractButton) c).isFocusPainted() && c.hasFocus(); + } + return c.hasFocus(); } - private void paintShadow(final Graphics2D g2, final int width, final int height, final int arc) { + private void paintShadow(final Graphics2D g2, final int x, final int y, + final int width, final int height, final int arc) { GraphicsContext context = new GraphicsContext(g2); - int borderSize = getBorderSize(); int shadowSize = getShadowSize(); - Area shadowShape = new Area(new RoundRectangle2D.Double(borderSize, borderSize, - width - 2 * borderSize, height - 2 * borderSize, - arc, arc)); - Area innerArea = new Area(new RoundRectangle2D.Double(borderSize, borderSize, - width - 2 * borderSize, - height - 2 * borderSize - shadowSize, - arc, arc)); + Area shadowShape = new Area(new RoundRectangle2D.Double(x, y, width, height, arc, arc)); + Area innerArea = new Area(new RoundRectangle2D.Double(x, y, width, height - shadowSize, arc, arc)); shadowShape.subtract(innerArea); g2.setComposite(DarkUIUtil.SHADOW_COMPOSITE); g2.setColor(shadowColor); @@ -150,16 +202,12 @@ public class DarkButtonBorder implements Border, UIResource { context.restore(); } - protected int getShadowSize() { - return shadowSize; - } - - protected int getBorderSize() { - return borderSize; + public boolean isBorderOpaque() { + return false; } protected Color getBorderColor(final Component c) { - if (c.hasFocus()) { + if (paintFocus(c)) { return focusBorderColor; } else if (c instanceof JButton && ((JButton) c).isDefaultButton() && c.isEnabled()) { return defaultBorderColor; @@ -184,10 +232,19 @@ public class DarkButtonBorder implements Border, UIResource { : thinInsets : square ? squareInsets : insets; - return new InsetsUIResource(pad.top, pad.left, pad.bottom + shadow, pad.right); + return maskInsets(new InsetsUIResource(pad.top, pad.left, pad.bottom, pad.right), c, shadow); } - public boolean isBorderOpaque() { - return false; + protected Insets maskInsets(final Insets ins, final Component c, final int shadow) { + ins.bottom += shadow; + AlignmentExt alignment = getCornerFlag(c); + if (alignment == null) return ins; + Insets insetMask = new Insets(borderSize, borderSize, borderSize + shadow, borderSize); + insetMask = alignment.maskInsetsInverted(insetMask); + ins.top -= insetMask.top; + ins.bottom -= insetMask.bottom; + ins.left -= insetMask.left; + ins.right -= insetMask.right; + return ins; } } diff --git a/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java b/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java index 7a66dd1e..25c12f99 100644 --- a/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java +++ b/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkButtonUI.java @@ -55,6 +55,7 @@ public class DarkButtonUI extends BasicButtonUI implements PropertyChangeListene public static final String KEY_SQUARE = KEY_PREFIX + "square"; public static final String KEY_THIN = KEY_PREFIX + "thin"; public static final String KEY_NO_SHADOW_OVERWRITE = KEY_PREFIX + "noShadowOverwrite"; + public static final String KEY_CORNER = KEY_PREFIX + "cornerFlag"; public static final String VARIANT_ONLY_LABEL = "onlyLabel"; public static final String VARIANT_FULL_SHADOW = "fullShadow"; public static final String VARIANT_SHADOW = "shadow"; @@ -198,6 +199,17 @@ public class DarkButtonUI extends BasicButtonUI implements PropertyChangeListene if (!isShadowVariant(b)) { i = new Insets(i.top, borderSize, i.bottom, borderSize); } + + AlignmentExt corner = DarkButtonBorder.getCornerFlag(c); + Insets insetMask = new Insets(borderSize, borderSize, borderSize, borderSize); + if (corner != null) { + insetMask = corner.maskInsetsInverted(insetMask, 0); + } + i.left -= insetMask.left; + i.right -= insetMask.right; + i.top -= insetMask.top; + i.bottom -= insetMask.bottom; + viewRect.x = i.left; viewRect.y = i.top; viewRect.width = width - (i.right + i.left); @@ -348,33 +360,59 @@ public class DarkButtonUI extends BasicButtonUI implements PropertyChangeListene Insets margin = b.getMargin(); if (margin instanceof UIResource) margin = new Insets(0, 0, 0, 0); if (isShadowVariant(c)) { - if (b.isEnabled() && b.getModel().isRollover()) { - GraphicsUtil.setupAAPainting(g2); - g.setColor(getShadowColor(b)); - if (isFullShadow(c)) { - g.fillRect(margin.left, margin.top, - width - margin.left - margin.right, - height - margin.top - margin.bottom); - } else if (doConvertToShadow(b)) { - int size = Math.min(width - margin.left - margin.right, - height - margin.left - margin.right); - g.fillRoundRect((width - size) / 2, (height - size) / 2, size, size, arc, arc); - } else { - g.fillRoundRect(margin.left, margin.top, - width - margin.left - margin.right, - height - margin.top - margin.bottom, - arc, arc); - } - } + paintShadowBackground(g, c, g2, b, arc, width, height, margin); } else { - g2.setColor(getBackgroundColor(c)); - if (isSquare(c) && !chooseAlternativeArc(c)) { - g2.fillRect(borderSize, borderSize, width - 2 * borderSize, - height - 2 * borderSize - shadowHeight); - } else { - DarkUIUtil.fillRoundRect((Graphics2D) g, borderSize, borderSize, width - 2 * borderSize, - height - 2 * borderSize - shadowHeight, arc); - } + paintDefaultBackground((Graphics2D) g, c, g2, arc, width, height); + } + } + } + + protected void paintDefaultBackground(final Graphics2D g, final JComponent c, final Graphics2D g2, + final int arc, final int width, final int height) { + g2.setColor(getBackgroundColor(c)); + int shadow = DarkButtonBorder.showDropShadow(c) ? shadowHeight : 0; + int effectiveArc = isSquare(c) && !chooseAlternativeArc(c) ? 0 : arc; + Rectangle bgRect = getEffectiveRect(width, height, c, -(effectiveArc + 1)); + if (effectiveArc == 0) { + g2.fillRect(bgRect.x, bgRect.y, bgRect.width, bgRect.height - shadow); + } else { + DarkUIUtil.fillRoundRect(g, bgRect.x, bgRect.y, bgRect.width, bgRect.height - shadow, effectiveArc); + } + } + + protected Rectangle getEffectiveRect(final int width, final int height, final JComponent c, final int adjustment) { + AlignmentExt corner = DarkButtonBorder.getCornerFlag(c); + Insets insetMask = new Insets(borderSize, borderSize, borderSize, borderSize); + if (corner != null) { + insetMask = corner.maskInsets(insetMask, adjustment); + } + + int bx = insetMask.left; + int by = insetMask.top; + int bw = width - insetMask.left - insetMask.right; + int bh = height - insetMask.top - insetMask.bottom; + return new Rectangle(bx, by, bw, bh); + } + + protected void paintShadowBackground(final Graphics g, final JComponent c, final Graphics2D g2, + final AbstractButton b, final int arc, + final int width, final int height, final Insets margin) { + if (b.isEnabled() && b.getModel().isRollover()) { + GraphicsUtil.setupAAPainting(g2); + g.setColor(getShadowColor(b)); + if (isFullShadow(c)) { + g.fillRect(margin.left, margin.top, + width - margin.left - margin.right, + height - margin.top - margin.bottom); + } else if (doConvertToShadow(b)) { + int size = Math.min(width - margin.left - margin.right, + height - margin.left - margin.right); + g.fillRoundRect((width - size) / 2, (height - size) / 2, size, size, arc, arc); + } else { + g.fillRoundRect(margin.left, margin.top, + width - margin.left - margin.right, + height - margin.top - margin.bottom, + arc, arc); } } } diff --git a/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkToggleButtonUI.java b/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkToggleButtonUI.java index 7fef5fb0..1bd80fdd 100644 --- a/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkToggleButtonUI.java +++ b/core/src/main/java/com/github/weisj/darklaf/ui/button/DarkToggleButtonUI.java @@ -116,14 +116,28 @@ public class DarkToggleButtonUI extends DarkButtonUI { } protected Color getBackgroundColor(final JComponent c) { - if (c instanceof JToggleButton && c.isEnabled()) { - if (((JToggleButton) c).isSelected()) { - return background; + AbstractButton b = (AbstractButton) c; + boolean rollOver = (b.isRolloverEnabled() || doConvertToShadow(b)) && (((JButton) c).getModel().isRollover()); + boolean clicked = b.getModel().isArmed(); + if (c.isEnabled()) { + if (clicked) { + return clickBackground; + } else if (rollOver) { + return hoverBackground; } else { - return backgroundInactive; + if (c instanceof JToggleButton && c.isEnabled()) { + if (((JToggleButton) c).isSelected()) { + return background; + } else { + return backgroundInactive; + } + } else { + return super.getBackgroundColor(c); + } } + } else { + return inactiveBackground; } - return super.getBackgroundColor(c); } @Override diff --git a/core/src/main/java/com/github/weisj/darklaf/ui/filechooser/DarkFileChooserUI.java b/core/src/main/java/com/github/weisj/darklaf/ui/filechooser/DarkFileChooserUI.java index 34b4e35c..70427a27 100644 --- a/core/src/main/java/com/github/weisj/darklaf/ui/filechooser/DarkFileChooserUI.java +++ b/core/src/main/java/com/github/weisj/darklaf/ui/filechooser/DarkFileChooserUI.java @@ -26,6 +26,7 @@ package com.github.weisj.darklaf.ui.filechooser; import com.github.weisj.darklaf.components.tooltip.TooltipAwareButton; import com.github.weisj.darklaf.components.tooltip.TooltipAwareToggleButton; import com.github.weisj.darklaf.ui.button.DarkButtonUI; +import com.github.weisj.darklaf.util.AlignmentExt; import sun.swing.FilePane; import javax.accessibility.AccessibleContext; @@ -107,6 +108,7 @@ public class DarkFileChooserUI extends DarkFileChooserUIBridge { upFolderButton.putClientProperty(DarkButtonUI.KEY_SQUARE, true); upFolderButton.putClientProperty(DarkButtonUI.KEY_ALT_ARC, true); upFolderButton.setText(null); + upFolderButton.setFocusPainted(false); upFolderButton.setIcon(upFolderIcon); upFolderButton.setToolTipText(upFolderToolTipText); upFolderButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, @@ -125,6 +127,7 @@ public class DarkFileChooserUI extends DarkFileChooserUIBridge { JButton b = new TooltipAwareButton(homeFolderIcon); b.putClientProperty(DarkButtonUI.KEY_NO_SHADOW_OVERWRITE, true); b.setToolTipText(toolTipText); + b.setFocusPainted(false); b.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, homeFolderAccessibleName); b.setAlignmentX(JComponent.LEFT_ALIGNMENT); @@ -160,10 +163,12 @@ public class DarkFileChooserUI extends DarkFileChooserUIBridge { // List Button listViewButton = new TooltipAwareToggleButton(listViewIcon); + listViewButton.setFocusPainted(false); listViewButton.putClientProperty(DarkButtonUI.KEY_NO_SHADOW_OVERWRITE, true); listViewButton.putClientProperty(DarkButtonUI.KEY_SQUARE, true); listViewButton.putClientProperty(DarkButtonUI.KEY_ALT_ARC, true); listViewButton.putClientProperty(DarkButtonUI.KEY_SQUARE, Boolean.TRUE); + listViewButton.putClientProperty(DarkButtonUI.KEY_CORNER, AlignmentExt.LEFT); listViewButton.setToolTipText(listViewButtonToolTipText); listViewButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, listViewButtonAccessibleName); @@ -177,9 +182,11 @@ public class DarkFileChooserUI extends DarkFileChooserUIBridge { // Details Button detailsViewButton = new TooltipAwareToggleButton(detailsViewIcon); + detailsViewButton.setFocusPainted(false); detailsViewButton.putClientProperty(DarkButtonUI.KEY_NO_SHADOW_OVERWRITE, true); detailsViewButton.putClientProperty(DarkButtonUI.KEY_SQUARE, true); detailsViewButton.putClientProperty(DarkButtonUI.KEY_ALT_ARC, true); + detailsViewButton.putClientProperty(DarkButtonUI.KEY_CORNER, AlignmentExt.RIGHT); detailsViewButton.setToolTipText(detailsViewButtonToolTipText); detailsViewButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, detailsViewButtonAccessibleName); detailsViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); diff --git a/core/src/test/java/ui/button/ButtonDemo.java b/core/src/test/java/ui/button/ButtonDemo.java index fbe58d29..ba241865 100644 --- a/core/src/test/java/ui/button/ButtonDemo.java +++ b/core/src/test/java/ui/button/ButtonDemo.java @@ -25,6 +25,7 @@ package ui.button; import com.github.weisj.darklaf.icons.IconLoader; import com.github.weisj.darklaf.ui.button.DarkButtonUI; +import com.github.weisj.darklaf.util.AlignmentExt; import ui.ComponentDemo; import ui.DemoPanel; import ui.QuickColorChooser; @@ -95,6 +96,21 @@ public class ButtonDemo implements ComponentDemo { setSelectedItem(DarkButtonUI.VARIANT_NONE); addItemListener(e -> button.putClientProperty(DarkButtonUI.KEY_VARIANT, e.getItem())); }}); + controlPanel.add(new JLabel(DarkButtonUI.KEY_CORNER + ":")); + controlPanel.add(new JComboBox() {{ + addItem("None"); + for (AlignmentExt a : AlignmentExt.values()) { + addItem(a.name()); + } + setSelectedItem("None"); + addItemListener(e -> { + if ("None".equals(e.getItem())) { + button.putClientProperty(DarkButtonUI.KEY_CORNER, null); + } else { + button.putClientProperty(DarkButtonUI.KEY_CORNER, AlignmentExt.valueOf(e.getItem().toString())); + } + }); + }}); controlPanel.add(new JCheckBox("Icon Only") {{ setSelected(false); addActionListener(e -> button.setText(isSelected() ? null : "Test Button")); diff --git a/utils/src/main/java/com/github/weisj/darklaf/util/Alignment.java b/utils/src/main/java/com/github/weisj/darklaf/util/Alignment.java index 5e562b43..3688ec1a 100644 --- a/utils/src/main/java/com/github/weisj/darklaf/util/Alignment.java +++ b/utils/src/main/java/com/github/weisj/darklaf/util/Alignment.java @@ -235,32 +235,57 @@ public enum Alignment { } } - public Insets maskInsets(final Insets insets) { + return maskInsets(insets, 0); + } + + + public Insets maskInsets(final Insets insets, final int maskValue) { + return maskInsets(insets.top, insets.left, insets.bottom, insets.right, maskValue); + } + + public Insets maskInsets(final int top, final int left, final int bottom, final int right, final int mask) { switch (this) { case NORTH: - return new Insets(insets.top, 0, 0, 0); + return new Insets(top, mask, mask, mask); case NORTH_EAST: - return new Insets(insets.top, 0, 0, insets.right); + return new Insets(top, mask, mask, right); case EAST: - return new Insets(0, 0, 0, insets.right); + return new Insets(mask, mask, mask, right); case SOUTH_EAST: - return new Insets(0, 0, insets.bottom, insets.right); + return new Insets(mask, mask, bottom, right); case SOUTH: - return new Insets(0, 0, insets.bottom, 0); + return new Insets(mask, mask, bottom, mask); case SOUTH_WEST: - return new Insets(0, insets.left, insets.bottom, 0); + return new Insets(mask, left, bottom, mask); case WEST: - return new Insets(0, insets.left, 0, 0); + return new Insets(mask, left, mask, mask); case NORTH_WEST: - return new Insets(insets.top, insets.left, 0, 0); + return new Insets(top, left, mask, mask); case CENTER: - return new Insets(0, 0, 0, 0); + return new Insets(mask, mask, mask, mask); default: throw new IllegalArgumentException(); } } + public Insets maskInsetsInverted(final Insets insets) { + return maskInsetsInverted(insets, 0); + } + + public Insets maskInsetsInverted(final Insets insets, final int mask) { + return maskInsetsInverted(insets.top, insets.left, insets.bottom, insets.right, mask); + } + + public Insets maskInsetsInverted(final int top, final int left, final int bottom, final int right, final int mask) { + Insets masking = maskInsets(0, 0, 0, 0, 1); + Insets maskVal = maskInsets(mask, mask, mask, mask, 0); + return new Insets(top * masking.top + maskVal.top, + left * masking.left + maskVal.left, + bottom * masking.bottom + maskVal.bottom, + right * masking.right + maskVal.right); + } + /** * Align Rectangle inside other rectangle with respect to the alignment. * diff --git a/utils/src/main/java/com/github/weisj/darklaf/util/AlignmentExt.java b/utils/src/main/java/com/github/weisj/darklaf/util/AlignmentExt.java new file mode 100644 index 00000000..51ebd1c4 --- /dev/null +++ b/utils/src/main/java/com/github/weisj/darklaf/util/AlignmentExt.java @@ -0,0 +1,105 @@ +/* + * MIT License + * + * Copyright (c) 2020 Jannis Weis + * + * 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 com.github.weisj.darklaf.util; + +import java.awt.*; + +public enum AlignmentExt { + NORTH(Alignment.NORTH), + SOUTH(Alignment.SOUTH_WEST), + EAST(Alignment.EAST), + WEST(Alignment.WEST), + NORTH_EAST(Alignment.NORTH_EAST), + NORTH_WEST(Alignment.NORTH_WEST), + SOUTH_EAST(Alignment.SOUTH_EAST), + SOUTH_WEST(Alignment.SOUTH_WEST), + CENTER(Alignment.CENTER), + LEFT(null), + MIDDLE_HORIZONTAL(null), + RIGHT(null), + TOP(null), + MIDDLE_VERTICAL(null), + BOTTOM(null); + + private Alignment parent; + + AlignmentExt(final Alignment parent) { + this.parent = parent; + } + + public Insets maskInsets(final Insets insets) { + return maskInsets(insets, 0); + } + + + public Insets maskInsets(final Insets insets, final int maskValue) { + return maskInsets(insets.top, insets.left, insets.bottom, insets.right, maskValue); + } + + public Insets maskInsets(final int top, final int left, final int bottom, final int right, final int mask) { + switch (this) { + case NORTH: + case NORTH_EAST: + case EAST: + case SOUTH_EAST: + case SOUTH: + case SOUTH_WEST: + case WEST: + case NORTH_WEST: + case CENTER: + return parent.maskInsets(top, left, bottom, right, mask); + case LEFT: + return new Insets(top, left, bottom, mask); + case MIDDLE_HORIZONTAL: + return new Insets(top, mask, bottom, mask); + case RIGHT: + return new Insets(top, mask, bottom, right); + case TOP: + return new Insets(top, left, mask, right); + case MIDDLE_VERTICAL: + return new Insets(mask, left, mask, right); + case BOTTOM: + return new Insets(mask, left, bottom, right); + default: + throw new IllegalArgumentException(); + } + } + + public Insets maskInsetsInverted(final Insets insets) { + return maskInsetsInverted(insets, 0); + } + + public Insets maskInsetsInverted(final Insets insets, final int mask) { + return maskInsetsInverted(insets.top, insets.left, insets.bottom, insets.right, mask); + } + + public Insets maskInsetsInverted(final int top, final int left, final int bottom, final int right, final int mask) { + Insets masking = maskInsets(0, 0, 0, 0, 1); + Insets maskVal = maskInsets(mask, mask, mask, mask, 0); + return new Insets(top * masking.top + maskVal.top, + left * masking.left + maskVal.left, + bottom * masking.bottom + maskVal.bottom, + right * masking.right + maskVal.right); + } +}