Finished Rounded Border

This commit is contained in:
UnlegitDqrk
2026-02-08 16:40:54 +01:00
parent f00666ace5
commit e45ae7fdd4
3 changed files with 112 additions and 71 deletions

View File

@@ -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();
}
}
}
}

View File

@@ -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();
}
}

View File

@@ -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());