diff --git a/pom.xml b/pom.xml
index 542bdd9..f7a73de 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
org.openautonomousconnection
OACSwing
- 1.0.0-BETA.1.0
+ 1.0.0-BETA.1.1
Open Autonomous Connection
https://open-autonomous-connection.org/
diff --git a/src/main/java/org/openautonomousconnection/oacswing/component/OACButton.java b/src/main/java/org/openautonomousconnection/oacswing/component/OACButton.java
index 84dfb29..8ef7699 100644
--- a/src/main/java/org/openautonomousconnection/oacswing/component/OACButton.java
+++ b/src/main/java/org/openautonomousconnection/oacswing/component/OACButton.java
@@ -81,6 +81,7 @@ public class OACButton extends JButton implements OACPressable {
setContentAreaFilled(false);
setOpaque(false);
setFocusPainted(false);
+ setBorderPainted(false);
if (!isEnabled() && getDisabledColor() != null) {
super.setBackground(getDisabledColor());
@@ -182,4 +183,4 @@ public class OACButton extends JButton implements OACPressable {
g2.dispose();
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/openautonomousconnection/oacswing/component/OACFrame.java b/src/main/java/org/openautonomousconnection/oacswing/component/OACFrame.java
index c97da88..a5b4584 100644
--- a/src/main/java/org/openautonomousconnection/oacswing/component/OACFrame.java
+++ b/src/main/java/org/openautonomousconnection/oacswing/component/OACFrame.java
@@ -3,6 +3,8 @@ package org.openautonomousconnection.oacswing.component;
import org.openautonomousconnection.oacswing.component.design.DesignManager;
import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
@@ -64,6 +66,7 @@ public class OACFrame extends JFrame {
setBackground(new Color(0, 0, 0, 1));
roundedRoot.setLayout(new BorderLayout());
+ roundedRoot.setBorder(new EmptyBorder(TITLE_BAR_HEIGHT, 0, 0, 0));
setContentPane(roundedRoot);
titleBar = new OACTitleBar(this);
@@ -79,16 +82,20 @@ public class OACFrame extends JFrame {
@Override
public void componentResized(ComponentEvent e) {
titleRoot.setBounds(0, 0, getWidth(), TITLE_BAR_HEIGHT);
+ updateWindowChrome();
roundedRoot.repaint();
}
@Override
public void componentShown(ComponentEvent e) {
titleRoot.setBounds(0, 0, getWidth(), TITLE_BAR_HEIGHT);
+ updateWindowChrome();
roundedRoot.repaint();
}
});
+ addWindowStateListener(e -> updateWindowChrome());
+
setSize(900, 600);
SwingUtilities.invokeLater(() -> {
@@ -99,6 +106,7 @@ public class OACFrame extends JFrame {
installResizeHandling();
DesignManager.apply(this);
+ updateWindowChrome();
}
@Override
@@ -142,18 +150,29 @@ public class OACFrame extends JFrame {
MouseAdapter adapter = new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
+ if (isInFullscreenState()) {
+ resizeCursor = Cursor.DEFAULT_CURSOR;
+ setCursor(Cursor.getDefaultCursor());
+ return;
+ }
resizeCursor = getResizeCursor(e);
setCursor(Cursor.getPredefinedCursor(resizeCursor));
}
@Override
public void mousePressed(MouseEvent e) {
+ if (isInFullscreenState()) {
+ dragStart = null;
+ startBounds = null;
+ return;
+ }
dragStart = e.getLocationOnScreen();
startBounds = getBounds();
}
@Override
public void mouseDragged(MouseEvent e) {
+ if (isInFullscreenState()) return;
if (resizeCursor == Cursor.DEFAULT_CURSOR) return;
Point dragNow = e.getLocationOnScreen();
@@ -207,6 +226,10 @@ public class OACFrame extends JFrame {
}
private int getResizeCursor(MouseEvent e) {
+ if (isInFullscreenState()) {
+ return Cursor.DEFAULT_CURSOR;
+ }
+
int x = e.getX();
int y = e.getY();
int w = e.getComponent().getWidth();
@@ -229,13 +252,29 @@ public class OACFrame extends JFrame {
return Cursor.DEFAULT_CURSOR;
}
+ private boolean isInFullscreenState() {
+ return (getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH;
+ }
+
/**
* Root panel that paints a near-transparent full-window layer (alpha=1)
* to prevent click-through, then paints the rounded background and clips children.
*/
+ private void updateWindowChrome() {
+ boolean fullscreen = isInFullscreenState();
+ roundedRoot.setArc(fullscreen ? 0 : CORNER_ARC);
+ if (fullscreen) {
+ getRootPane().setBorder(new LineBorder(DesignManager.resolveBorderColor(Color.GRAY), 1));
+ setCursor(Cursor.getDefaultCursor());
+ } else {
+ getRootPane().setBorder(new EmptyBorder(0, 0, 0, 0));
+ }
+ repaint();
+ }
+
private static final class RoundedRootPanel extends OACPanel {
- private final int arc;
+ private int arc;
private RoundedRootPanel(int arc) {
super(new BorderLayout());
@@ -243,6 +282,10 @@ public class OACFrame extends JFrame {
setOpaque(false);
}
+ private void setArc(int arc) {
+ this.arc = Math.max(0, arc);
+ }
+
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
@@ -292,4 +335,4 @@ public class OACFrame extends JFrame {
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/openautonomousconnection/oacswing/component/OACOptionPane.java b/src/main/java/org/openautonomousconnection/oacswing/component/OACOptionPane.java
index a4bd9aa..519b407 100644
--- a/src/main/java/org/openautonomousconnection/oacswing/component/OACOptionPane.java
+++ b/src/main/java/org/openautonomousconnection/oacswing/component/OACOptionPane.java
@@ -5,9 +5,14 @@
package org.openautonomousconnection.oacswing.component;
import lombok.NonNull;
+import org.openautonomousconnection.oacswing.component.design.DesignManager;
import javax.swing.*;
+import javax.swing.border.EmptyBorder;
import java.awt.*;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.atomic.AtomicInteger;
public class OACOptionPane extends JOptionPane implements OACComponent {
public OACOptionPane() {
@@ -38,6 +43,140 @@ public class OACOptionPane extends JOptionPane implements OACComponent {
super(message, messageType, optionType, icon, options, initialValue);
}
+ @Override
+ public void init() {
+ setOpaque(true);
+ setBackground(DesignManager.resolveBackground(OACOptionPane.class, getBackground()));
+ setForeground(DesignManager.resolveForeground(OACOptionPane.class, getForeground()));
+ }
+
+ public static int showOptionDialog(Component parentComponent,
+ Object message,
+ String title,
+ int optionType,
+ int messageType,
+ Icon icon,
+ Object[] options,
+ Object initialValue) throws HeadlessException {
+ AtomicInteger result = new AtomicInteger(CLOSED_OPTION);
+ OACDialog dialog = new OACDialog(JOptionPane.getFrameForComponent(parentComponent), title, true);
+ dialog.setUndecorated(true);
+ dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ dialog.setContentPane(buildDialogContent(title, message, icon, optionType, options, result, dialog));
+ dialog.setResizable(false);
+ dialog.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ result.set(CLOSED_OPTION);
+ }
+ });
+ dialog.pack();
+ dialog.setMinimumSize(new Dimension(420, dialog.getHeight()));
+ dialog.setLocationRelativeTo(parentComponent);
+ dialog.setVisible(true);
+ dialog.dispose();
+ return result.get();
+ }
+
+ private static Container buildDialogContent(String title,
+ Object message,
+ Icon icon,
+ int optionType,
+ Object[] options,
+ AtomicInteger result,
+ OACDialog dialog) {
+ OACPanel root = new OACPanel(new BorderLayout());
+ Color background = DesignManager.resolveBackground(OACOptionPane.class, root.getBackground());
+ Color headerBackground = DesignManager.resolveBackground(OACTitleBar.class, background.darker());
+ Color foreground = DesignManager.resolveForeground(OACOptionPane.class, Color.LIGHT_GRAY);
+ Color borderColor = DesignManager.resolveBorderColor(foreground.darker());
+
+ root.setBackground(background);
+ root.setBorder(BorderFactory.createLineBorder(borderColor, 1));
+
+ OACPanel header = new OACPanel(new BorderLayout());
+ header.setBorder(new EmptyBorder(10, 12, 10, 12));
+ header.setBackground(headerBackground);
+ JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL);
+ separator.setForeground(borderColor);
+ separator.setBackground(borderColor);
+ header.add(separator, BorderLayout.SOUTH);
+
+ OACLabel titleLabel = new OACLabel(title == null ? "" : title);
+ titleLabel.setForeground(foreground);
+ header.add(titleLabel, BorderLayout.WEST);
+
+ OACPanel center = new OACPanel(new BorderLayout(10, 0));
+ center.setBackground(background);
+ center.setBorder(new EmptyBorder(14, 12, 12, 12));
+
+ if (icon != null) {
+ OACLabel iconLabel = new OACLabel(icon);
+ iconLabel.setForeground(foreground);
+ center.add(iconLabel, BorderLayout.WEST);
+ }
+
+ JTextArea messageArea = new JTextArea(String.valueOf(message));
+ messageArea.setEditable(false);
+ messageArea.setLineWrap(true);
+ messageArea.setWrapStyleWord(true);
+ messageArea.setOpaque(false);
+ messageArea.setForeground(foreground);
+ messageArea.setBorder(null);
+ center.add(messageArea, BorderLayout.CENTER);
+
+ OACPanel buttons = new OACPanel(new FlowLayout(FlowLayout.RIGHT, 8, 8));
+ buttons.setBackground(background);
+
+ Object[] displayOptions = resolveOptions(optionType, options);
+ for (int i = 0; i < displayOptions.length; i++) {
+ final int index = i;
+ OACButton button = new OACButton(String.valueOf(displayOptions[i]));
+ button.initDesign();
+ button.setBackground(DesignManager.resolveBackground(OACButton.class, button.getBackground()));
+ button.setForeground(DesignManager.resolveForeground(OACButton.class, button.getForeground()));
+ button.setHoveredColor(DesignManager.resolveHovered(OACButton.class, button.getBackground().brighter()));
+ button.setPressedColor(DesignManager.resolvePressed(OACButton.class, button.getBackground().darker()));
+ button.setBorder(BorderFactory.createLineBorder(borderColor, 1, true));
+ button.setPreferredSize(new Dimension(100, 32));
+ button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ button.addActionListener(e -> {
+ result.set(mapResult(optionType, options, index));
+ dialog.dispose();
+ });
+ buttons.add(button);
+ }
+
+ root.add(header, BorderLayout.NORTH);
+ root.add(center, BorderLayout.CENTER);
+ root.add(buttons, BorderLayout.SOUTH);
+ return root;
+ }
+
+ private static Object[] resolveOptions(int optionType, Object[] options) {
+ if (options != null && options.length > 0) {
+ return options;
+ }
+ return switch (optionType) {
+ case YES_NO_OPTION -> new Object[]{"Yes", "No"};
+ case YES_NO_CANCEL_OPTION -> new Object[]{"Yes", "No", "Cancel"};
+ case OK_CANCEL_OPTION -> new Object[]{"OK", "Cancel"};
+ default -> new Object[]{"OK"};
+ };
+ }
+
+ private static int mapResult(int optionType, Object[] providedOptions, int clickedIndex) {
+ if (providedOptions != null && providedOptions.length > 0) {
+ return clickedIndex;
+ }
+ return switch (optionType) {
+ case YES_NO_OPTION -> clickedIndex == 0 ? YES_OPTION : NO_OPTION;
+ case YES_NO_CANCEL_OPTION -> clickedIndex == 0 ? YES_OPTION : (clickedIndex == 1 ? NO_OPTION : CANCEL_OPTION);
+ case OK_CANCEL_OPTION -> clickedIndex == 0 ? OK_OPTION : CANCEL_OPTION;
+ default -> OK_OPTION;
+ };
+ }
+
@Override
public Component add(Component comp) {
this.initOther(comp);
diff --git a/src/main/java/org/openautonomousconnection/oacswing/component/OACPasswordField.java b/src/main/java/org/openautonomousconnection/oacswing/component/OACPasswordField.java
index a236e1c..08da179 100644
--- a/src/main/java/org/openautonomousconnection/oacswing/component/OACPasswordField.java
+++ b/src/main/java/org/openautonomousconnection/oacswing/component/OACPasswordField.java
@@ -5,8 +5,10 @@
package org.openautonomousconnection.oacswing.component;
import lombok.NonNull;
+import org.openautonomousconnection.oacswing.component.design.DesignManager;
import javax.swing.*;
+import javax.swing.border.EmptyBorder;
import javax.swing.text.Document;
import java.awt.*;
@@ -31,6 +33,39 @@ public class OACPasswordField extends JPasswordField implements OACComponent {
super(doc, txt, columns);
}
+ @Override
+ public void init() {
+ setOpaque(true);
+ applyInputBorder();
+ setCaretColor(getForeground());
+ setSelectionColor(getForeground().darker());
+ setSelectedTextColor(getBackground().brighter());
+ setPreferredSize(new Dimension(Math.max(160, getPreferredSize().width), 34));
+ }
+
+ @Override
+ public void updateUI() {
+ super.updateUI();
+ applyInputBorder();
+ }
+
+ private void applyInputBorder() {
+ setBorder(new EmptyBorder(6, 10, 6, 10));
+ }
+
+ @Override
+ protected void paintBorder(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g.create();
+ try {
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.setColor(DesignManager.resolveBorderColor(getForeground()));
+ g2.setStroke(new BasicStroke(2f));
+ g2.drawRoundRect(1, 1, getWidth() - 3, getHeight() - 3, 10, 10);
+ } finally {
+ g2.dispose();
+ }
+ }
+
@Override
public Component add(Component comp) {
this.initOther(comp);
diff --git a/src/main/java/org/openautonomousconnection/oacswing/component/OACTextArea.java b/src/main/java/org/openautonomousconnection/oacswing/component/OACTextArea.java
index 12af7ee..d7ac742 100644
--- a/src/main/java/org/openautonomousconnection/oacswing/component/OACTextArea.java
+++ b/src/main/java/org/openautonomousconnection/oacswing/component/OACTextArea.java
@@ -5,6 +5,7 @@
package org.openautonomousconnection.oacswing.component;
import lombok.NonNull;
+import org.openautonomousconnection.oacswing.component.design.DesignManager;
import javax.swing.*;
import javax.swing.text.Document;
@@ -35,6 +36,16 @@ public class OACTextArea extends JTextArea implements OACComponent {
super(doc, text, rows, columns);
}
+ @Override
+ public void init() {
+ setOpaque(true);
+ setMargin(new Insets(6, 10, 6, 10));
+ setBorder(DesignManager.createTextComponentBorder());
+ setCaretColor(getForeground());
+ setSelectionColor(getForeground().darker());
+ setSelectedTextColor(getBackground().brighter());
+ }
+
@Override
public Component add(Component comp) {
this.initOther(comp);
diff --git a/src/main/java/org/openautonomousconnection/oacswing/component/OACTextField.java b/src/main/java/org/openautonomousconnection/oacswing/component/OACTextField.java
index a1c7a33..0c6f5ef 100644
--- a/src/main/java/org/openautonomousconnection/oacswing/component/OACTextField.java
+++ b/src/main/java/org/openautonomousconnection/oacswing/component/OACTextField.java
@@ -4,7 +4,12 @@
package org.openautonomousconnection.oacswing.component;
+import org.openautonomousconnection.oacswing.border.RoundedBorder;
+import org.openautonomousconnection.oacswing.component.design.DesignManager;
+
import javax.swing.*;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
import javax.swing.text.Document;
import java.awt.*;
@@ -29,6 +34,29 @@ public class OACTextField extends JTextField implements OACComponent {
super(doc, text, columns);
}
+ @Override
+ public void init() {
+ setOpaque(true);
+ applyInputBorder();
+ setCaretColor(getForeground());
+ setSelectionColor(getForeground().darker());
+ setSelectedTextColor(getBackground().brighter());
+ setPreferredSize(new Dimension(Math.max(160, getPreferredSize().width), 34));
+ }
+
+ @Override
+ public void updateUI() {
+ super.updateUI();
+ applyInputBorder();
+ }
+
+ private void applyInputBorder() {
+ setBorder(new CompoundBorder(
+ new RoundedBorder(DesignManager.resolveBorderColor(getForeground()), 10, 2),
+ new EmptyBorder(6, 10, 6, 10)
+ ));
+ }
+
@Override
public Component add(Component comp) {
this.initOther(comp);
diff --git a/src/main/java/org/openautonomousconnection/oacswing/component/OACTextPane.java b/src/main/java/org/openautonomousconnection/oacswing/component/OACTextPane.java
index 650c73f..3ef36fb 100644
--- a/src/main/java/org/openautonomousconnection/oacswing/component/OACTextPane.java
+++ b/src/main/java/org/openautonomousconnection/oacswing/component/OACTextPane.java
@@ -5,6 +5,7 @@
package org.openautonomousconnection.oacswing.component;
import lombok.NonNull;
+import org.openautonomousconnection.oacswing.component.design.DesignManager;
import javax.swing.*;
import javax.swing.text.StyledDocument;
@@ -18,6 +19,16 @@ public class OACTextPane extends JTextPane implements OACComponent {
super(doc);
}
+ @Override
+ public void init() {
+ setOpaque(true);
+ setMargin(new Insets(6, 10, 6, 10));
+ setBorder(DesignManager.createTextComponentBorder());
+ setCaretColor(getForeground());
+ setSelectionColor(getForeground().darker());
+ setSelectedTextColor(getBackground().brighter());
+ }
+
@Override
public Component add(Component comp) {
this.initOther(comp);
diff --git a/src/main/java/org/openautonomousconnection/oacswing/component/OACTitleBar.java b/src/main/java/org/openautonomousconnection/oacswing/component/OACTitleBar.java
index ea95e62..6e35a9e 100644
--- a/src/main/java/org/openautonomousconnection/oacswing/component/OACTitleBar.java
+++ b/src/main/java/org/openautonomousconnection/oacswing/component/OACTitleBar.java
@@ -6,6 +6,7 @@ package org.openautonomousconnection.oacswing.component;
import lombok.Getter;
import lombok.Setter;
+import org.openautonomousconnection.oacswing.component.design.DesignManager;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
@@ -39,6 +40,9 @@ public class OACTitleBar extends OACPanel {
super(new BorderLayout());
this.frame = frame;
+ setOpaque(true);
+ setBackground(DesignManager.resolveBackground(OACTitleBar.class, getBackground()));
+ setForeground(DesignManager.resolveForeground(OACTitleBar.class, getForeground()));
setPreferredSize(new Dimension(1, HEIGHT));
setBorder(new EmptyBorder(6, 10, 6, 10));
@@ -170,4 +174,4 @@ public class OACTitleBar extends OACPanel {
frame.dispatchEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED));
}
-}
\ 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 b335364..af7dbf9 100644
--- a/src/main/java/org/openautonomousconnection/oacswing/component/design/DesignManager.java
+++ b/src/main/java/org/openautonomousconnection/oacswing/component/design/DesignManager.java
@@ -10,11 +10,23 @@ import org.openautonomousconnection.oacswing.border.RoundedBorder;
import org.openautonomousconnection.oacswing.component.*;
import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.LineBorder;
+import javax.swing.text.JTextComponent;
+import java.awt.*;
+import java.awt.event.ContainerAdapter;
+import java.awt.event.ContainerEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class DesignManager {
+ private static final String OAC_INIT_PROPERTY = "oac.design.initialized";
+ private static final String OAC_LISTENER_PROPERTY = "oac.design.listener";
+ private static final Border INVISIBLE_BORDER = new EmptyBorder(0, 0, 0, 0);
+
@Getter
@Setter
private static Design globalDesign;
@@ -27,13 +39,13 @@ public class DesignManager {
OACColor.DARK_INPUT_BUTTON_HOVER,
OACColor.DARK_INPUT_BUTTON_HOVER,
OACColor.DARK_INACTIVE_BUTTON,
- true
+ false
));
Design.DARK.getElements().put(OACCheckBox.class, new DesignFlags(OACColor.DARK_INPUT_FIELD));
Design.DARK.getElements().put(OACCheckBoxMenuItem.class, new DesignFlags(OACColor.DARK_ITEM));
- Design.DARK.getElements().put(OACTextField.class, new DesignFlags(OACColor.DARK_ITEM, OACColor.DARK_TEXT));
- Design.DARK.getElements().put(OACTextArea.class, new DesignFlags(OACColor.DARK_ITEM, OACColor.DARK_TEXT));
+ Design.DARK.getElements().put(OACTextField.class, new DesignFlags(OACColor.DARK_INPUT_FIELD, OACColor.DARK_TEXT));
+ Design.DARK.getElements().put(OACTextArea.class, new DesignFlags(OACColor.DARK_INPUT_FIELD, OACColor.DARK_TEXT));
Design.DARK.getElements().put(OACColorChooser.class, new DesignFlags(OACColor.DARK_SECTION));
Design.DARK.getElements().put(OACComboBox.class, new DesignFlags(OACColor.DARK_INPUT_FIELD));
Design.DARK.getElements().put(OACFrame.class, new DesignFlags(OACColor.DARK_BACKGROUND));
@@ -44,14 +56,16 @@ public class DesignManager {
Design.DARK.getElements().put(OACMenuBar.class, new DesignFlags(OACColor.DARK_SECTION));
Design.DARK.getElements().put(OACMenuItem.class, new DesignFlags(OACColor.DARK_ITEM));
Design.DARK.getElements().put(OACOptionPane.class, new DesignFlags(OACColor.DARK_BACKGROUND));
- Design.DARK.getElements().put(OACPanel.class, new DesignFlags(OACColor.DARK_BACKGROUND, true));
- Design.DARK.getElements().put(OACPasswordField.class, new DesignFlags(OACColor.DARK_INPUT_FIELD));
+ Design.DARK.getElements().put(OACPanel.class, new DesignFlags(OACColor.DARK_BACKGROUND, false));
+ Design.DARK.getElements().put(OACPasswordField.class, new DesignFlags(OACColor.DARK_INPUT_FIELD, OACColor.DARK_TEXT));
Design.DARK.getElements().put(OACPopupMenu.class, new DesignFlags(OACColor.DARK_BACKGROUND));
Design.DARK.getElements().put(OACProgressBar.class, new DesignFlags(OACColor.DARK_ITEM));
Design.DARK.getElements().put(OACRadioButton.class, new DesignFlags(OACColor.DARK_BUTTON));
- Design.DARK.getElements().put(OACTitleBar.class, new DesignFlags(OACColor.DARK_SECTION));
+ Design.DARK.getElements().put(OACDialog.class, new DesignFlags(OACColor.DARK_BACKGROUND));
+ Design.DARK.getElements().put(OACTitleBar.class, new DesignFlags(OACColor.DARK_HEADER));
- Design.DARK.border =new RoundedBorder(OACColor.DARK_BORDERS.getColor(), 18, 1);
+ Design.DARK.border = new RoundedBorder(OACColor.DARK_BORDERS.getColor(), 18, 1);
+ globalDesign = Design.DARK;
DesignManager.getInstance().registerDesign(Design.DARK);
}
@@ -73,7 +87,7 @@ public class DesignManager {
if (globalDesign == null)
return;
- DesignFlags designFlags = globalDesign.getElements().get(component.getClass());
+ DesignFlags designFlags = resolveFlags(component.getClass());
if (designFlags == null)
return;
@@ -96,22 +110,101 @@ public class DesignManager {
if (disabled != null) pressable.setDisabledColor(disabled.getColor());
}
- if (component instanceof JComponent jComponent) {
- jComponent.setBackground(backgroundColour.getColor());
+ if (component instanceof Component awtComponent) {
+ awtComponent.setBackground(backgroundColour.getColor());
if (foregroundColour != null) {
- jComponent.setForeground(foregroundColour.getColor());
+ awtComponent.setForeground(foregroundColour.getColor());
}
+ }
+ if (component instanceof JComponent jComponent) {
if (hasBorder) {
jComponent.setBorder(globalDesign.getBorder());
jComponent.setOpaque(false);
+ } else if (!(jComponent instanceof OACTitleBar) && !(jComponent instanceof JTextComponent)) {
+ Border currentBorder = jComponent.getBorder();
+ if (currentBorder == null || hasZeroInsets(currentBorder, jComponent)) {
+ jComponent.setBorder(INVISIBLE_BORDER);
+ }
}
+ if (jComponent instanceof JTextComponent textComponent) {
+ textComponent.setOpaque(true);
+ textComponent.setBorder(createTextComponentBorder());
+ }
+
+ if (!Boolean.TRUE.equals(jComponent.getClientProperty(OAC_INIT_PROPERTY))) {
+ component.init();
+ jComponent.putClientProperty(OAC_INIT_PROPERTY, Boolean.TRUE);
+ }
+ } else {
component.init();
}
}
+ private static boolean hasZeroInsets(Border border, JComponent component) {
+ Insets insets = border.getBorderInsets(component);
+ return insets.top == 0 && insets.left == 0 && insets.bottom == 0 && insets.right == 0;
+ }
+
+ public static DesignFlags getFlagsFor(Class> type) {
+ if (globalDesign == null) {
+ return null;
+ }
+ return resolveFlags(type);
+ }
+
+ public static Color resolveBackground(Class> type, Color fallback) {
+ DesignFlags flags = getFlagsFor(type);
+ if (flags != null && flags.background() != null) {
+ return flags.background().getColor();
+ }
+ return fallback;
+ }
+
+ public static Color resolveForeground(Class> type, Color fallback) {
+ DesignFlags flags = getFlagsFor(type);
+ if (flags != null && flags.foreground() != null) {
+ return flags.foreground().getColor();
+ }
+ if (globalDesign != null && globalDesign.getForegroundColour() != null) {
+ return globalDesign.getForegroundColour().getColor();
+ }
+ return fallback;
+ }
+
+ public static Color resolveHovered(Class> type, Color fallback) {
+ DesignFlags flags = getFlagsFor(type);
+ if (flags != null && flags.hovered() != null) {
+ return flags.hovered().getColor();
+ }
+ return fallback;
+ }
+
+ public static Color resolvePressed(Class> type, Color fallback) {
+ DesignFlags flags = getFlagsFor(type);
+ if (flags != null && flags.pressed() != null) {
+ return flags.pressed().getColor();
+ }
+ return fallback;
+ }
+
+ public static Border createTextComponentBorder() {
+ Color borderColor = resolveBorderColor(new Color(120, 120, 120));
+ return new CompoundBorder(
+ new LineBorder(borderColor, 2, true),
+ new EmptyBorder(4, 8, 4, 8)
+ );
+ }
+
+ public static Color resolveBorderColor(Color fallback) {
+ if (globalDesign != null && globalDesign.getBorder() instanceof RoundedBorder roundedBorder) {
+ return roundedBorder.getColor();
+ }
+ return fallback;
+ }
+
public static void apply(OACFrame frame) {
DesignFlags designFlags;
@@ -122,8 +215,50 @@ public class DesignManager {
frame.getContentPane().setBackground(designFlags.background().getColor());
}
+ applyTree(frame.getRootPane());
+ applyTree(frame.getLayeredPane());
+ installAutoApply(frame.getRootPane());
+ installAutoApply(frame.getLayeredPane());
+ }
+ private static DesignFlags resolveFlags(Class> type) {
+ Class> current = type;
+ while (current != null) {
+ DesignFlags flags = globalDesign.getElements().get(current);
+ if (flags != null) {
+ return flags;
+ }
+ current = current.getSuperclass();
+ }
+ return null;
+ }
+ private static void applyTree(Component component) {
+ if (component instanceof OACComponent oacComponent) {
+ oacComponent.initDesign();
+ }
+ if (component instanceof Container container) {
+ installAutoApply(container);
+ for (Component child : container.getComponents()) {
+ applyTree(child);
+ }
+ }
+ }
+
+ private static void installAutoApply(Container container) {
+ if (!(container instanceof JComponent jComponent)) {
+ return;
+ }
+ if (Boolean.TRUE.equals(jComponent.getClientProperty(OAC_LISTENER_PROPERTY))) {
+ return;
+ }
+ container.addContainerListener(new ContainerAdapter() {
+ @Override
+ public void componentAdded(ContainerEvent e) {
+ applyTree(e.getChild());
+ }
+ });
+ jComponent.putClientProperty(OAC_LISTENER_PROPERTY, Boolean.TRUE);
}
public void registerDesign(Design design) {
diff --git a/src/test/java/org/openautonomousconnection/oacswing/test/CustomizedTests.java b/src/test/java/org/openautonomousconnection/oacswing/test/CustomizedTests.java
index 11b88b4..6a2ffa5 100644
--- a/src/test/java/org/openautonomousconnection/oacswing/test/CustomizedTests.java
+++ b/src/test/java/org/openautonomousconnection/oacswing/test/CustomizedTests.java
@@ -5,13 +5,11 @@
package org.openautonomousconnection.oacswing.test;
import org.junit.jupiter.api.Test;
-import org.openautonomousconnection.oacswing.component.OACButton;
-import org.openautonomousconnection.oacswing.component.OACFrame;
-import org.openautonomousconnection.oacswing.component.OACPanel;
-import org.openautonomousconnection.oacswing.component.OACTextField;
+import org.openautonomousconnection.oacswing.component.*;
import org.openautonomousconnection.oacswing.component.design.Design;
import org.openautonomousconnection.oacswing.component.design.DesignManager;
+import javax.swing.*;
import java.awt.*;
public class CustomizedTests {
@@ -29,9 +27,19 @@ public class CustomizedTests {
navBar.add(textField, BorderLayout.CENTER);
frame.getContentPane().add(navBar, BorderLayout.NORTH);
-
+frame.add(navBar);
frame.setVisible(true);
-
- wait(15000);
+ Object[] options = {"Continue", "Cancel"};
+ OACOptionPane.showOptionDialog(
+ frame,
+ "You never connected to this INS before!\n" +
+ "Fingerprint: " + "caFingerprint" + "\nDo you want to connect?",
+ "INS Connection",
+ OACOptionPane.YES_NO_OPTION,
+ OACOptionPane.INFORMATION_MESSAGE,
+ null,
+ options,
+ options[0]
+ ); wait(15000);
}
}