289 lines
12 KiB
Java
289 lines
12 KiB
Java
/* Author: Maple
|
|
* Feb. 2 2026
|
|
* */
|
|
|
|
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() {
|
|
super();
|
|
}
|
|
|
|
public OACOptionPane(Object message) {
|
|
super(message);
|
|
}
|
|
|
|
public OACOptionPane(Object message, int messageType) {
|
|
super(message, messageType);
|
|
}
|
|
|
|
public OACOptionPane(Object message, int messageType, int optionType) {
|
|
super(message, messageType, optionType);
|
|
}
|
|
|
|
public OACOptionPane(Object message, int messageType, int optionType, Icon icon) {
|
|
super(message, messageType, optionType, icon);
|
|
}
|
|
|
|
public OACOptionPane(Object message, int messageType, int optionType, Icon icon, Object[] options) {
|
|
super(message, messageType, optionType, icon, options);
|
|
}
|
|
|
|
public OACOptionPane(Object message, int messageType, int optionType, Icon icon, Object[] options, Object initialValue) {
|
|
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), null, 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();
|
|
}
|
|
|
|
public static int showConfirmDialog(Component parentComponent, Object message) throws HeadlessException {
|
|
return showConfirmDialog(parentComponent, message, "Select an Option", YES_NO_CANCEL_OPTION);
|
|
}
|
|
|
|
public static int showConfirmDialog(Component parentComponent,
|
|
Object message,
|
|
String title,
|
|
int optionType) throws HeadlessException {
|
|
return showConfirmDialog(parentComponent, message, title, optionType, QUESTION_MESSAGE);
|
|
}
|
|
|
|
public static int showConfirmDialog(Component parentComponent,
|
|
Object message,
|
|
String title,
|
|
int optionType,
|
|
int messageType) throws HeadlessException {
|
|
return showConfirmDialog(parentComponent, message, title, optionType, messageType, null);
|
|
}
|
|
|
|
public static int showConfirmDialog(Component parentComponent,
|
|
Object message,
|
|
String title,
|
|
int optionType,
|
|
int messageType,
|
|
Icon icon) throws HeadlessException {
|
|
return showOptionDialog(
|
|
parentComponent,
|
|
message,
|
|
title,
|
|
optionType,
|
|
messageType,
|
|
icon != null ? icon : resolveDefaultIcon(messageType),
|
|
null,
|
|
null
|
|
);
|
|
}
|
|
|
|
public static void showMessageDialog(Component parentComponent, Object message) throws HeadlessException {
|
|
showMessageDialog(parentComponent, message, "Message", INFORMATION_MESSAGE);
|
|
}
|
|
|
|
public static void showMessageDialog(Component parentComponent,
|
|
Object message,
|
|
String title,
|
|
int messageType) throws HeadlessException {
|
|
showMessageDialog(parentComponent, message, title, messageType, null);
|
|
}
|
|
|
|
public static void showMessageDialog(Component parentComponent,
|
|
Object message,
|
|
String title,
|
|
int messageType,
|
|
Icon icon) throws HeadlessException {
|
|
showOptionDialog(
|
|
parentComponent,
|
|
message,
|
|
title,
|
|
DEFAULT_OPTION,
|
|
messageType,
|
|
icon != null ? icon : resolveDefaultIcon(messageType),
|
|
new Object[]{"OK"},
|
|
"OK"
|
|
);
|
|
}
|
|
|
|
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 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(0, 12, 8, 12));
|
|
header.setBackground(background);
|
|
|
|
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);
|
|
}
|
|
|
|
if (message instanceof Component messageComponent) {
|
|
if (messageComponent instanceof OACComponent oacComponent) {
|
|
oacComponent.initDesign();
|
|
} else {
|
|
messageComponent.setBackground(background);
|
|
messageComponent.setForeground(foreground);
|
|
}
|
|
center.add(messageComponent, BorderLayout.CENTER);
|
|
} else {
|
|
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;
|
|
};
|
|
}
|
|
|
|
private static Icon resolveDefaultIcon(int messageType) {
|
|
return switch (messageType) {
|
|
case ERROR_MESSAGE -> UIManager.getIcon("OptionPane.errorIcon");
|
|
case WARNING_MESSAGE -> UIManager.getIcon("OptionPane.warningIcon");
|
|
case QUESTION_MESSAGE -> UIManager.getIcon("OptionPane.questionIcon");
|
|
default -> UIManager.getIcon("OptionPane.informationIcon");
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public Component add(Component comp) {
|
|
this.initOther(comp);
|
|
return super.add(comp);
|
|
}
|
|
|
|
@Override
|
|
public Component add(Component comp, int index) {
|
|
this.initOther(comp);
|
|
return super.add(comp, index);
|
|
}
|
|
|
|
@Override
|
|
public void add(@NonNull Component comp, Object constraints) {
|
|
this.initOther(comp);
|
|
super.add(comp, constraints);
|
|
}
|
|
|
|
@Override
|
|
public Component add(String name, Component comp) {
|
|
this.initOther(comp);
|
|
return super.add(name, comp);
|
|
}
|
|
|
|
@Override
|
|
public void add(Component comp, Object constraints, int index) {
|
|
this.initOther(comp);
|
|
super.add(comp, constraints, index);
|
|
}
|
|
}
|