173 lines
4.7 KiB
Java
173 lines
4.7 KiB
Java
/* Author: UnlegitDqrk
|
|
* Feb. 2 2026
|
|
* */
|
|
|
|
package org.openautonomousconnection.oacswing.component;
|
|
|
|
import lombok.Getter;
|
|
import lombok.Setter;
|
|
|
|
import javax.swing.*;
|
|
import javax.swing.border.EmptyBorder;
|
|
import java.awt.*;
|
|
import java.awt.event.ComponentEvent;
|
|
import java.awt.event.MouseAdapter;
|
|
import java.awt.event.MouseEvent;
|
|
import java.awt.event.WindowEvent;
|
|
|
|
/**
|
|
* Custom title bar with tabs and window control buttons.
|
|
*/
|
|
public class OACTitleBar extends OACPanel {
|
|
|
|
@Getter
|
|
@Setter
|
|
private static int HEIGHT = 42;
|
|
|
|
private final OACFrame frame;
|
|
private final OACTabbedPane tabs;
|
|
|
|
private Point dragStartOnScreen;
|
|
private Point dragStartFrameLocation;
|
|
|
|
/**
|
|
* Creates a title bar for the given frame.
|
|
*
|
|
* @param frame owning frame
|
|
*/
|
|
public OACTitleBar(OACFrame frame) {
|
|
super(new BorderLayout());
|
|
this.frame = frame;
|
|
|
|
setPreferredSize(new Dimension(1, HEIGHT));
|
|
setBorder(new EmptyBorder(6, 10, 6, 10));
|
|
|
|
tabs = createTabs();
|
|
OACPanel left = new OACPanel(new BorderLayout());
|
|
left.setOpaque(false);
|
|
left.add(tabs, BorderLayout.CENTER);
|
|
|
|
OACPanel right = createWindowControls();
|
|
|
|
add(left, BorderLayout.CENTER);
|
|
add(right, BorderLayout.EAST);
|
|
|
|
installDragToMove();
|
|
installDoubleClickMaximize();
|
|
}
|
|
|
|
/**
|
|
* Returns the tab component.
|
|
*
|
|
* @return tabbed pane
|
|
*/
|
|
public OACTabbedPane getTabs() {
|
|
return tabs;
|
|
}
|
|
|
|
/**
|
|
* Adds a new tab.
|
|
*
|
|
* @param title tab title
|
|
* @param panel tab body
|
|
*/
|
|
public void addTab(String title, OACPanel panel) {
|
|
tabs.addTab(title, panel);
|
|
}
|
|
|
|
private OACTabbedPane createTabs() {
|
|
OACTabbedPane tp = new OACTabbedPane(OACTabbedPane.TOP, OACTabbedPane.SCROLL_TAB_LAYOUT);
|
|
tp.setOpaque(false);
|
|
|
|
tp.setFocusable(false);
|
|
|
|
return tp;
|
|
}
|
|
|
|
private OACPanel createWindowControls() {
|
|
OACPanel p = new OACPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0));
|
|
p.setOpaque(false);
|
|
|
|
OACButton min = createTitleButton("—");
|
|
OACButton max = createTitleButton("▢");
|
|
OACButton close = createTitleButton("✕");
|
|
|
|
min.addActionListener(e -> frame.setState(Frame.ICONIFIED));
|
|
max.addActionListener(e -> toggleMaximize());
|
|
close.addActionListener(e -> frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)));
|
|
|
|
p.add(min);
|
|
p.add(max);
|
|
p.add(close);
|
|
|
|
return p;
|
|
}
|
|
|
|
private OACButton createTitleButton(String text) {
|
|
OACButton b = new OACButton(text);
|
|
b.setFocusable(false);
|
|
b.setBorderPainted(false);
|
|
b.setContentAreaFilled(true);
|
|
b.setOpaque(true);
|
|
b.setBorder(null);
|
|
b.setPreferredSize(new Dimension(42, 28));
|
|
|
|
return b;
|
|
}
|
|
|
|
private void installDragToMove() {
|
|
MouseAdapter drag = new MouseAdapter() {
|
|
@Override
|
|
public void mousePressed(MouseEvent e) {
|
|
dragStartOnScreen = e.getLocationOnScreen();
|
|
dragStartFrameLocation = frame.getLocation();
|
|
}
|
|
|
|
@Override
|
|
public void mouseDragged(MouseEvent e) {
|
|
if (dragStartOnScreen == null || dragStartFrameLocation == null) {
|
|
return;
|
|
}
|
|
Point now = e.getLocationOnScreen();
|
|
int dx = now.x - dragStartOnScreen.x;
|
|
int dy = now.y - dragStartOnScreen.y;
|
|
|
|
if ((frame.getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH) {
|
|
return;
|
|
}
|
|
|
|
frame.setLocation(dragStartFrameLocation.x + dx, dragStartFrameLocation.y + dy);
|
|
|
|
frame.dispatchEvent(new ComponentEvent(e.getComponent(), ComponentEvent.COMPONENT_MOVED));
|
|
|
|
}
|
|
};
|
|
|
|
addMouseListener(drag);
|
|
addMouseMotionListener(drag);
|
|
}
|
|
|
|
private void installDoubleClickMaximize() {
|
|
addMouseListener(new MouseAdapter() {
|
|
@Override
|
|
public void mouseClicked(MouseEvent e) {
|
|
if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
|
|
toggleMaximize();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private void toggleMaximize() {
|
|
int state = frame.getExtendedState();
|
|
boolean maximized = (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH;
|
|
|
|
if (maximized) {
|
|
frame.setExtendedState(state & ~Frame.MAXIMIZED_BOTH);
|
|
} else {
|
|
frame.setExtendedState(state | Frame.MAXIMIZED_BOTH);
|
|
}
|
|
|
|
frame.dispatchEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED));
|
|
}
|
|
} |