From e45ae7fdd44b205569320d775a884eceb7e5c3a9 Mon Sep 17 00:00:00 2001 From: UnlegitDqrk Date: Sun, 8 Feb 2026 16:40:54 +0100 Subject: [PATCH] Finished Rounded Border --- .../oacswing/border/RoundedBorder.java | 89 +++++++------------ .../oacswing/component/OACButton.java | 87 +++++++++++++++--- .../component/design/DesignManager.java | 7 +- 3 files changed, 112 insertions(+), 71 deletions(-) diff --git a/src/main/java/org/openautonomousconnection/oacswing/border/RoundedBorder.java b/src/main/java/org/openautonomousconnection/oacswing/border/RoundedBorder.java index c6c938a..9154ad4 100644 --- a/src/main/java/org/openautonomousconnection/oacswing/border/RoundedBorder.java +++ b/src/main/java/org/openautonomousconnection/oacswing/border/RoundedBorder.java @@ -1,75 +1,52 @@ package org.openautonomousconnection.oacswing.border; +import lombok.Getter; + import javax.swing.border.AbstractBorder; import java.awt.*; -/** - * A rounded border that does NOT affect layout (zero insets). - * Use this for root/content panes where layout must not shift. - */ -public final class RoundedBorder extends AbstractBorder { +@Getter +public class RoundedBorder extends AbstractBorder { - private final int radius; - private final int strokeWidth; private final Color color; + private final int radius; + private final int thickness; - /** - * Creates an overlay rounded border. - * - * @param radius corner radius in pixels (must be >= 0) - * @param strokeWidth stroke width in pixels (must be >= 1) - * @param color border color (not null) - */ - public RoundedBorder(int radius, int strokeWidth, Color color) { - if (radius < 0) throw new IllegalArgumentException("radius must be >= 0"); - if (strokeWidth < 1) throw new IllegalArgumentException("strokeWidth must be >= 1"); - if (color == null) throw new IllegalArgumentException("color must not be null"); - this.radius = radius; - this.strokeWidth = strokeWidth; + public RoundedBorder(Color color, int radius, int thickness) { this.color = color; + this.radius = radius; + this.thickness = thickness; + } + + @Override + public void paintBorder(Component c, Graphics g, + int x, int y, int w, int h) { + + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + g2.setColor(color); + g2.setStroke(new BasicStroke(thickness)); + g2.drawRoundRect( + x + thickness / 2, + y + thickness / 2, + w - thickness, + h - thickness, + radius, + radius + ); + + g2.dispose(); } @Override public Insets getBorderInsets(Component c) { - return new Insets(0, 0, 0, 0); - } - - @Override - public Insets getBorderInsets(Component c, Insets insets) { - insets.top = 0; - insets.left = 0; - insets.bottom = 0; - insets.right = 0; - return insets; + return new Insets(thickness, thickness, thickness, thickness); } @Override public boolean isBorderOpaque() { return false; } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Graphics2D g2 = (Graphics2D) g.create(); - try { - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setColor(color); - g2.setStroke(new BasicStroke(strokeWidth)); - - int offset = strokeWidth / 2; - int w = width - strokeWidth; - int h = height - strokeWidth; - - g2.drawRoundRect( - x + offset, - y + offset, - w - 1, - h - 1, - radius * 2, - radius * 2 - ); - } finally { - g2.dispose(); - } - } -} \ No newline at end of file +} diff --git a/src/main/java/org/openautonomousconnection/oacswing/component/OACButton.java b/src/main/java/org/openautonomousconnection/oacswing/component/OACButton.java index 8d200df..6c11efd 100644 --- a/src/main/java/org/openautonomousconnection/oacswing/component/OACButton.java +++ b/src/main/java/org/openautonomousconnection/oacswing/component/OACButton.java @@ -3,9 +3,13 @@ package org.openautonomousconnection.oacswing.component; import lombok.Getter; import lombok.NonNull; import lombok.Setter; +import org.openautonomousconnection.oacswing.border.RoundedBorder; +import org.openautonomousconnection.oacswing.component.design.DesignManager; import org.openautonomousconnection.oacswing.component.design.OACColor; import javax.swing.*; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; import javax.swing.plaf.basic.BasicButtonUI; import java.awt.*; import java.awt.event.ComponentEvent; @@ -28,8 +32,20 @@ public class OACButton extends JButton implements OACPressable { @Getter @Setter private Color disabledColor; - @Getter @Setter + @Setter private int cornerRadius = 10; + + private Shape shape; + + private int getCornerRadius() { + Border b = getBorder(); + if (b instanceof RoundedBorder rb) { + return rb.getRadius(); + } + return cornerRadius; // Fallback + } + + public OACButton() { super(null, null); } @@ -51,44 +67,71 @@ public class OACButton extends JButton implements OACPressable { super(text, icon); } + private Color original; + + @Override + public void setBackground(Color bg) { + original = bg; + super.setBackground(bg); + } + + private void updateBackground(Color bg) { + super.setBackground(bg); + } + @Override public void init() { - Color original = getBackground(); + setContentAreaFilled(false); + setOpaque(false); + setFocusPainted(false); if (!isEnabled() && getDisabledColor() != null) { - setBackground(getDisabledColor()); + super.setBackground(getDisabledColor()); } addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { if (!isEnabled() && getDisabledColor() != null) { - setBackground(getDisabledColor()); - } else setBackground(getHoveredColor()); + updateBackground(getDisabledColor()); + } else updateBackground(getHoveredColor()); } @Override public void mouseExited(MouseEvent e) { if (!isEnabled() && getDisabledColor() != null) { - setBackground(getDisabledColor()); - } else setBackground(original); + updateBackground(getDisabledColor()); + } else updateBackground(original); } @Override public void mousePressed(MouseEvent e) { if (!isEnabled() && getDisabledColor() != null) { - setBackground(getDisabledColor()); - } else setBackground(getPressedColor()); + updateBackground(getDisabledColor()); + } else updateBackground(getPressedColor()); } @Override public void mouseReleased(MouseEvent e) { if (!isEnabled() && getDisabledColor() != null) { - setBackground(getDisabledColor()); - } else setBackground(original); + updateBackground(getDisabledColor()); + } else updateBackground(original); } }); } + @Override + public boolean contains(int x, int y) { + int r = getCornerRadius(); + + if (shape == null || !shape.getBounds().equals(getBounds())) { + shape = new RoundRectangle2D.Float( + 0, 0, + getWidth(), getHeight(), + r, r + ); + } + return shape.contains(x, y); + } @Override public Component add(Component comp) { @@ -119,4 +162,26 @@ public class OACButton extends JButton implements OACPressable { initOther(comp); super.add(comp, constraints, index); } + + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + int r = getCornerRadius(); + + Color bg = getBackground(); + if (!isEnabled() && disabledColor != null) + bg = disabledColor; + else if (getModel().isPressed() && pressedColor != null) + bg = pressedColor; + + g2.setColor(bg); + g2.fillRoundRect(0, 0, getWidth(), getHeight(), r, r); + + super.paintComponent(g2); + g2.dispose(); + } + } \ No newline at end of file diff --git a/src/main/java/org/openautonomousconnection/oacswing/component/design/DesignManager.java b/src/main/java/org/openautonomousconnection/oacswing/component/design/DesignManager.java index cde3c74..cc0277f 100644 --- a/src/main/java/org/openautonomousconnection/oacswing/component/design/DesignManager.java +++ b/src/main/java/org/openautonomousconnection/oacswing/component/design/DesignManager.java @@ -53,8 +53,6 @@ public class DesignManager { boolean hasBorder = designFlags.hasBorder(); - Border border = globalDesign.getBorder(); - if(backgroundColour == null) throw new NullPointerException("Background color cannot be null; please exclude the component from your design instead"); @@ -72,7 +70,8 @@ public class DesignManager { } if (hasBorder) { - jComponent.setBorder(new RoundedBorder(12, 1, OACColor.DARK_BORDERS.getColor())); + jComponent.setBorder(globalDesign.getBorder()); + jComponent.setOpaque(false); } component.init(); @@ -135,7 +134,7 @@ public class DesignManager { Design.DARK.getElements().put(OACRadioButton.class, new DesignFlags(OACColor.DARK_BUTTON)); Design.DARK.getElements().put(OACTitleBar.class, new DesignFlags(OACColor.DARK_SECTION)); - Design.DARK.border = new RoundedBorder(10, 1, OACColor.DARK_BORDERS.getColor()); + Design.DARK.border = new RoundedBorder(OACColor.DARK_BORDERS.getColor(), 20, 2); //Design.DARK.border = new BevelBorder(BevelBorder.LOWERED, OACColor.DARK_BORDERS.getColor(), OACColor.DARK_SHADOW.getColor());