2026-02-07 18:54:19 +01:00
|
|
|
/* Author: Maple
|
|
|
|
|
* Feb. 2 2026
|
|
|
|
|
* */
|
|
|
|
|
|
|
|
|
|
package org.openautonomousconnection.oacswing.component;
|
|
|
|
|
|
2026-02-07 21:56:05 +01:00
|
|
|
import lombok.NonNull;
|
2026-02-14 22:09:04 +01:00
|
|
|
import org.openautonomousconnection.oacswing.component.design.DesignManager;
|
2026-02-07 18:54:19 +01:00
|
|
|
|
|
|
|
|
import javax.swing.*;
|
2026-02-14 22:09:04 +01:00
|
|
|
import javax.swing.plaf.basic.BasicTabbedPaneUI;
|
2026-02-07 18:54:19 +01:00
|
|
|
import java.awt.*;
|
|
|
|
|
|
|
|
|
|
public class OACTabbedPane extends JTabbedPane implements OACComponent {
|
2026-02-14 22:09:04 +01:00
|
|
|
private boolean selectionSyncInstalled;
|
|
|
|
|
|
2026-02-07 18:54:19 +01:00
|
|
|
public OACTabbedPane() {
|
|
|
|
|
super();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public OACTabbedPane(int tabPlacement) {
|
|
|
|
|
super(tabPlacement);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public OACTabbedPane(int tabPlacement, int tabLayoutPolicy) {
|
|
|
|
|
super(tabPlacement, tabLayoutPolicy);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-14 22:09:04 +01:00
|
|
|
@Override
|
|
|
|
|
public void init() {
|
|
|
|
|
applyDesignColors();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void updateUI() {
|
|
|
|
|
super.updateUI();
|
|
|
|
|
applyDesignColors();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void applyDesignColors() {
|
|
|
|
|
Color bg = DesignManager.resolveBackground(OACTabbedPane.class, getBackground());
|
|
|
|
|
Color fg = DesignManager.resolveForeground(OACTabbedPane.class, getForeground());
|
|
|
|
|
Color selectedBg = DesignManager.resolveHovered(OACButton.class, bg.darker());
|
|
|
|
|
Color selectedFg = fg;
|
|
|
|
|
Color border = DesignManager.resolveBorderColor(bg.darker());
|
|
|
|
|
|
|
|
|
|
setOpaque(true);
|
|
|
|
|
setBackground(bg);
|
|
|
|
|
setForeground(fg);
|
|
|
|
|
setUI(new DesignTabbedPaneUI(bg, selectedBg, border));
|
|
|
|
|
applyTabItemColors(bg, fg, selectedBg, selectedFg);
|
|
|
|
|
installSelectionSyncIfNeeded();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void applyTabItemColors(Color bg, Color fg, Color selectedBg, Color selectedFg) {
|
|
|
|
|
int selectedIndex = getSelectedIndex();
|
|
|
|
|
for (int i = 0; i < getTabCount(); i++) {
|
|
|
|
|
boolean selected = i == selectedIndex;
|
|
|
|
|
setBackgroundAt(i, selected ? selectedBg : bg);
|
|
|
|
|
setForegroundAt(i, selected ? selectedFg : fg);
|
|
|
|
|
}
|
|
|
|
|
repaint();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void installSelectionSyncIfNeeded() {
|
|
|
|
|
if (selectionSyncInstalled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
addChangeListener(e -> {
|
|
|
|
|
Color bg = DesignManager.resolveBackground(OACTabbedPane.class, getBackground());
|
|
|
|
|
Color fg = DesignManager.resolveForeground(OACTabbedPane.class, getForeground());
|
|
|
|
|
Color selectedBg = DesignManager.resolveHovered(OACButton.class, bg.darker());
|
|
|
|
|
applyTabItemColors(bg, fg, selectedBg, fg);
|
|
|
|
|
});
|
|
|
|
|
selectionSyncInstalled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final class DesignTabbedPaneUI extends BasicTabbedPaneUI {
|
|
|
|
|
private final Color background;
|
|
|
|
|
private final Color selectedBackground;
|
|
|
|
|
private final Color borderColor;
|
|
|
|
|
|
|
|
|
|
private DesignTabbedPaneUI(Color background, Color selectedBackground, Color borderColor) {
|
|
|
|
|
this.background = background;
|
|
|
|
|
this.selectedBackground = selectedBackground;
|
|
|
|
|
this.borderColor = borderColor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex,
|
|
|
|
|
int x, int y, int w, int h, boolean isSelected) {
|
|
|
|
|
g.setColor(isSelected ? selectedBackground : background);
|
|
|
|
|
g.fillRect(x, y, w, h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex,
|
|
|
|
|
int x, int y, int w, int h, boolean isSelected) {
|
|
|
|
|
g.setColor(borderColor);
|
|
|
|
|
g.drawRect(x, y, w, h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintFocusIndicator(Graphics g, int tabPlacement, Rectangle[] rects,
|
|
|
|
|
int tabIndex, Rectangle iconRect, Rectangle textRect, boolean isSelected) {
|
|
|
|
|
// no-op to avoid bright LAF focus ring
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintContentBorder(Graphics g, int tabPlacement, int selectedIndex) {
|
|
|
|
|
int width = tabPane.getWidth();
|
|
|
|
|
int height = tabPane.getHeight();
|
|
|
|
|
Insets insets = tabPane.getInsets();
|
|
|
|
|
|
|
|
|
|
int x = insets.left;
|
|
|
|
|
int y = insets.top;
|
|
|
|
|
int w = width - insets.right - insets.left;
|
|
|
|
|
int h = height - insets.top - insets.bottom;
|
|
|
|
|
|
|
|
|
|
switch (tabPlacement) {
|
|
|
|
|
case LEFT -> {
|
|
|
|
|
x += calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
|
|
|
|
|
w -= (x - insets.left);
|
|
|
|
|
}
|
|
|
|
|
case RIGHT -> w -= calculateTabAreaWidth(tabPlacement, runCount, maxTabWidth);
|
|
|
|
|
case BOTTOM -> h -= calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
|
|
|
|
|
default -> {
|
|
|
|
|
y += calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight);
|
|
|
|
|
h -= (y - insets.top);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g.setColor(background);
|
|
|
|
|
g.fillRect(x, y, w, h);
|
|
|
|
|
g.setColor(borderColor);
|
|
|
|
|
g.drawRect(x, y, Math.max(0, w - 1), Math.max(0, h - 1));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-08 12:14:58 +01:00
|
|
|
@Override
|
|
|
|
|
public void addTab(String title, Component component) {
|
|
|
|
|
this.initOther(component);
|
|
|
|
|
super.addTab(title, component);
|
2026-02-14 22:09:04 +01:00
|
|
|
applyDesignColors();
|
2026-02-08 12:14:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void addTab(String title, Icon icon, Component component) {
|
|
|
|
|
this.initOther(component);
|
|
|
|
|
super.addTab(title, icon, component);
|
2026-02-14 22:09:04 +01:00
|
|
|
applyDesignColors();
|
2026-02-08 12:14:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void addTab(String title, Icon icon, Component component, String tip) {
|
|
|
|
|
this.initOther(component);
|
|
|
|
|
super.addTab(title, icon, component, tip);
|
2026-02-14 22:09:04 +01:00
|
|
|
applyDesignColors();
|
2026-02-08 12:14:58 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-07 18:54:19 +01:00
|
|
|
@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
|
2026-02-07 21:56:05 +01:00
|
|
|
public void add(@NonNull Component comp, Object constraints) {
|
2026-02-07 18:54:19 +01:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|