Set up basic UI
This commit is contained in:
6
pom.xml
6
pom.xml
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>org.openautonomousconnection</groupId>
|
<groupId>org.openautonomousconnection</groupId>
|
||||||
<artifactId>WebClient</artifactId>
|
<artifactId>WebClient</artifactId>
|
||||||
<version>1.0.0-BETA.1.3</version>
|
<version>1.0.0-BETA.1.2</version>
|
||||||
<organization>
|
<organization>
|
||||||
<name>Open Autonomous Connection</name>
|
<name>Open Autonomous Connection</name>
|
||||||
<url>https://open-autonomous-connection.org/</url>
|
<url>https://open-autonomous-connection.org/</url>
|
||||||
@@ -107,8 +107,8 @@
|
|||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openautonomousconnection</groupId>
|
<groupId>org.openautonomousconnection</groupId>
|
||||||
<artifactId>Protocol</artifactId>
|
<artifactId>protocol</artifactId>
|
||||||
<version>1.0.0-BETA.6.0</version>
|
<version>1.0.0-BETA.5.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package org.openautonomousconnection.webclient;
|
|||||||
|
|
||||||
import dev.unlegitdqrk.unlegitlibrary.event.EventManager;
|
import dev.unlegitdqrk.unlegitlibrary.event.EventManager;
|
||||||
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
|
import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler;
|
||||||
|
import org.openautonomousconnection.infonamelib.InfoNames;
|
||||||
import org.openautonomousconnection.protocol.ProtocolBridge;
|
import org.openautonomousconnection.protocol.ProtocolBridge;
|
||||||
import org.openautonomousconnection.protocol.ProtocolValues;
|
import org.openautonomousconnection.protocol.ProtocolValues;
|
||||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||||
@@ -34,6 +35,8 @@ public class Main {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
initProtocol();
|
initProtocol();
|
||||||
|
|
||||||
|
InfoNames.registerOACInfoNameProtocols();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
registerEventHandlers();
|
registerEventHandlers();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import org.openautonomousconnection.webclient.network.type.NetTransmitFile;
|
|||||||
|
|
||||||
import javax.swing.text.Document;
|
import javax.swing.text.Document;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -34,6 +35,25 @@ public class WebClient extends ProtocolWebClient {
|
|||||||
*/
|
*/
|
||||||
public static final int TIMEOUT = 30;
|
public static final int TIMEOUT = 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to Webserver with URLs (info name based)
|
||||||
|
* @param url url containing host and port (port optional)
|
||||||
|
*/
|
||||||
|
public void connectToServer(URL url) {
|
||||||
|
String host = url.getHost();
|
||||||
|
|
||||||
|
// port 200 is the default port
|
||||||
|
int port = url.getPort() != -1 ? url.getPort() : 200;
|
||||||
|
|
||||||
|
this.connectToServer(host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give promise a non-null reference
|
||||||
|
* @param type type of file
|
||||||
|
* @param object serialized object
|
||||||
|
* @param <T> java object type
|
||||||
|
*/
|
||||||
public <T> void fulfillPromise(NTFType type, T object) {
|
public <T> void fulfillPromise(NTFType type, T object) {
|
||||||
if(!this.outstandingPromises.containsKey(type))
|
if(!this.outstandingPromises.containsKey(type))
|
||||||
return;
|
return;
|
||||||
@@ -49,6 +69,12 @@ public class WebClient extends ProtocolWebClient {
|
|||||||
@Getter
|
@Getter
|
||||||
private final Map<NTFType, Object> outstandingPromises = new HashMap<>();
|
private final Map<NTFType, Object> outstandingPromises = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Promise a serialized object that will be delivered as a file by the server
|
||||||
|
* @param type type of file
|
||||||
|
* @return object promise
|
||||||
|
* @param <T> java object type
|
||||||
|
*/
|
||||||
private <T> Promise<? extends NetTransmitFile<T>> promise(NTFType type) {
|
private <T> Promise<? extends NetTransmitFile<T>> promise(NTFType type) {
|
||||||
NetTransmitFile<T> ntf = NetTransmitFile.of(type, null);
|
NetTransmitFile<T> ntf = NetTransmitFile.of(type, null);
|
||||||
|
|
||||||
@@ -61,6 +87,14 @@ public class WebClient extends ProtocolWebClient {
|
|||||||
public void onResponse(INSResponseStatus insResponseStatus, List<INSRecord> list) {
|
public void onResponse(INSResponseStatus insResponseStatus, List<INSRecord> list) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a get request for a file from the currently connected server
|
||||||
|
* @param type type of file requested (UNKNOWN for files not supported by the protocol)
|
||||||
|
* @param path path to file
|
||||||
|
* @param test idfk
|
||||||
|
* @return resolved file
|
||||||
|
* @param <T> java object type
|
||||||
|
*/
|
||||||
public <T> Promise<? extends NetTransmitFile<T>> get(NTFType type, String path, T test) {
|
public <T> Promise<? extends NetTransmitFile<T>> get(NTFType type, String path, T test) {
|
||||||
try {
|
try {
|
||||||
this.getClientServerConnection().sendPacket(new WebRequestPacket(
|
this.getClientServerConnection().sendPacket(new WebRequestPacket(
|
||||||
@@ -77,6 +111,7 @@ public class WebClient extends ProtocolWebClient {
|
|||||||
return this.promise(type);
|
return this.promise(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
public void post(String path) {
|
public void post(String path) {
|
||||||
try {
|
try {
|
||||||
this.getClientServerConnection().sendPacket(new WebRequestPacket(
|
this.getClientServerConnection().sendPacket(new WebRequestPacket(
|
||||||
@@ -90,6 +125,10 @@ public class WebClient extends ProtocolWebClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get index.html Document of current site
|
||||||
|
* @return index.html
|
||||||
|
*/
|
||||||
public Promise<NetTransmitFile<Document>> getIndex() {
|
public Promise<NetTransmitFile<Document>> getIndex() {
|
||||||
try {
|
try {
|
||||||
this.getClientServerConnection().sendPacket(new WebRequestPacket(
|
this.getClientServerConnection().sendPacket(new WebRequestPacket(
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ package org.openautonomousconnection.webclient.network.website.tab;
|
|||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.openautonomousconnection.webclient.Main;
|
||||||
|
import org.openautonomousconnection.webclient.network.WebClient;
|
||||||
import org.openautonomousconnection.webclient.network.website.WebSite;
|
import org.openautonomousconnection.webclient.network.website.WebSite;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
@@ -19,18 +21,24 @@ public final class Tab {
|
|||||||
private WebSite webSite;
|
private WebSite webSite;
|
||||||
|
|
||||||
public Tab(URL infoName, Icon favicon) {
|
public Tab(URL infoName, Icon favicon) {
|
||||||
|
Main.client.connectToServer(infoName);
|
||||||
|
|
||||||
this.infoName = infoName;
|
this.infoName = infoName;
|
||||||
this.favicon = favicon;
|
this.favicon = favicon;
|
||||||
this.webSite = new WebSite(infoName);
|
this.webSite = new WebSite(infoName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tab(URL infoName) {
|
public Tab(URL infoName) {
|
||||||
|
Main.client.connectToServer(infoName);
|
||||||
|
|
||||||
this.infoName = infoName;
|
this.infoName = infoName;
|
||||||
this.favicon = WebSite.getFavIcon(infoName);
|
this.favicon = WebSite.getFavIcon(infoName);
|
||||||
this.webSite = new WebSite(infoName);
|
this.webSite = new WebSite(infoName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tab(WebSite webSite) {
|
public Tab(WebSite webSite) {
|
||||||
|
Main.client.connectToServer(webSite.getInfoName());
|
||||||
|
|
||||||
this.infoName = webSite.getInfoName();
|
this.infoName = webSite.getInfoName();
|
||||||
this.favicon = webSite.getFavIcon();
|
this.favicon = webSite.getFavIcon();
|
||||||
this.webSite = webSite;
|
this.webSite = webSite;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import org.openautonomousconnection.webclient.network.type.NTFType;
|
|||||||
import org.openautonomousconnection.webclient.network.type.NetTransmitFile;
|
import org.openautonomousconnection.webclient.network.type.NetTransmitFile;
|
||||||
import org.openautonomousconnection.webclient.network.type.image.NetTransmitIcon;
|
import org.openautonomousconnection.webclient.network.type.image.NetTransmitIcon;
|
||||||
import org.openautonomousconnection.webclient.network.type.text.NetTransmitDocument;
|
import org.openautonomousconnection.webclient.network.type.text.NetTransmitDocument;
|
||||||
import org.openautonomousconnection.webclient.network.website.tab.Tab;
|
|
||||||
import org.openautonomousconnection.webclient.packetlistener.PacketListener;
|
import org.openautonomousconnection.webclient.packetlistener.PacketListener;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|||||||
@@ -4,10 +4,152 @@
|
|||||||
|
|
||||||
package org.openautonomousconnection.webclient.ui;
|
package org.openautonomousconnection.webclient.ui;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ComponentAdapter;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
|
||||||
public abstract class BrowserFrame extends JFrame {
|
public abstract class BrowserFrame extends JFrame {
|
||||||
public BrowserFrame() {
|
private static final int RESIZE_MARGIN = 8;
|
||||||
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
|
||||||
|
private Point dragStart;
|
||||||
|
private Rectangle startBounds;
|
||||||
|
private int resizeCursor = Cursor.DEFAULT_CURSOR;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
protected TopBar topBar;
|
||||||
|
|
||||||
|
protected BrowserFrame() {
|
||||||
|
this(new TopBar());
|
||||||
|
|
||||||
|
this.topBar.initButtonPanel(BorderLayout.NORTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected BrowserFrame(TopBar topBar) {
|
||||||
|
|
||||||
|
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||||
|
|
||||||
|
this.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
this.setUndecorated(true);
|
||||||
|
|
||||||
|
this.topBar = topBar;
|
||||||
|
|
||||||
|
this.setShape(new RoundRectangle2D.Double(
|
||||||
|
0, 0,
|
||||||
|
this.getWidth(),
|
||||||
|
this.getHeight(),
|
||||||
|
30, 30
|
||||||
|
));
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
this.addComponentListener(new ComponentAdapter() {
|
||||||
|
@Override
|
||||||
|
public void componentResized(ComponentEvent e) {
|
||||||
|
setShape(new RoundRectangle2D.Double(
|
||||||
|
0, 0,
|
||||||
|
getWidth(),
|
||||||
|
getHeight(),
|
||||||
|
30, 30
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
MouseAdapter adapter = new MouseAdapter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(MouseEvent e) {
|
||||||
|
resizeCursor = getResizeCursor(e);
|
||||||
|
|
||||||
|
setCursor(Cursor.getPredefinedCursor(resizeCursor));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mousePressed(MouseEvent e) {
|
||||||
|
dragStart = e.getLocationOnScreen();
|
||||||
|
startBounds = getBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDragged(MouseEvent e) {
|
||||||
|
if (resizeCursor == Cursor.DEFAULT_CURSOR) return;
|
||||||
|
|
||||||
|
Point dragNow = e.getLocationOnScreen();
|
||||||
|
int dx = dragNow.x - dragStart.x;
|
||||||
|
int dy = dragNow.y - dragStart.y;
|
||||||
|
|
||||||
|
Rectangle newBounds = new Rectangle(startBounds);
|
||||||
|
|
||||||
|
switch (resizeCursor) {
|
||||||
|
case Cursor.E_RESIZE_CURSOR -> newBounds.width += dx;
|
||||||
|
case Cursor.S_RESIZE_CURSOR -> newBounds.height += dy;
|
||||||
|
case Cursor.SE_RESIZE_CURSOR -> {
|
||||||
|
newBounds.width += dx;
|
||||||
|
newBounds.height += dy;
|
||||||
|
}
|
||||||
|
case Cursor.W_RESIZE_CURSOR -> {
|
||||||
|
newBounds.x += dx;
|
||||||
|
newBounds.width -= dx;
|
||||||
|
}
|
||||||
|
case Cursor.N_RESIZE_CURSOR -> {
|
||||||
|
newBounds.y += dy;
|
||||||
|
newBounds.height -= dy;
|
||||||
|
}
|
||||||
|
case Cursor.NW_RESIZE_CURSOR -> {
|
||||||
|
newBounds.x += dx;
|
||||||
|
newBounds.y += dy;
|
||||||
|
newBounds.width -= dx;
|
||||||
|
newBounds.height -= dy;
|
||||||
|
}
|
||||||
|
case Cursor.NE_RESIZE_CURSOR -> {
|
||||||
|
newBounds.y += dy;
|
||||||
|
newBounds.width += dx;
|
||||||
|
newBounds.height -= dy;
|
||||||
|
}
|
||||||
|
case Cursor.SW_RESIZE_CURSOR -> {
|
||||||
|
newBounds.x += dx;
|
||||||
|
newBounds.width -= dx;
|
||||||
|
newBounds.height += dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setBounds(newBounds);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
addMouseListener(adapter);
|
||||||
|
addMouseMotionListener(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getResizeCursor(MouseEvent e) {
|
||||||
|
int x = e.getX();
|
||||||
|
int y = e.getY();
|
||||||
|
int w = e.getComponent().getWidth();
|
||||||
|
int h = e.getComponent().getHeight();
|
||||||
|
|
||||||
|
boolean left = x < RESIZE_MARGIN;
|
||||||
|
boolean right = x > w - RESIZE_MARGIN;
|
||||||
|
boolean top = y < RESIZE_MARGIN;
|
||||||
|
boolean bottom = y > h - RESIZE_MARGIN;
|
||||||
|
|
||||||
|
if (left && top) return Cursor.NW_RESIZE_CURSOR;
|
||||||
|
if (right && top) return Cursor.NE_RESIZE_CURSOR;
|
||||||
|
if (left && bottom) return Cursor.SW_RESIZE_CURSOR;
|
||||||
|
if (right && bottom) return Cursor.SE_RESIZE_CURSOR;
|
||||||
|
if (left) return Cursor.W_RESIZE_CURSOR;
|
||||||
|
if (right) return Cursor.E_RESIZE_CURSOR;
|
||||||
|
if (top) return Cursor.N_RESIZE_CURSOR;
|
||||||
|
if (bottom) return Cursor.S_RESIZE_CURSOR;
|
||||||
|
|
||||||
|
return Cursor.DEFAULT_CURSOR;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
/* Author: Maple
|
|
||||||
* Dec. 12 2025
|
|
||||||
* */
|
|
||||||
|
|
||||||
package org.openautonomousconnection.webclient.ui;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
public class DOMPanel extends JPanel {
|
|
||||||
}
|
|
||||||
@@ -6,15 +6,26 @@ package org.openautonomousconnection.webclient.ui;
|
|||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.openautonomousconnection.webclient.network.website.tab.Tab;
|
import org.openautonomousconnection.webclient.network.website.tab.Tab;
|
||||||
|
import org.openautonomousconnection.webclient.ui.dom.DOMContainerPanel;
|
||||||
|
import org.openautonomousconnection.webclient.ui.tab.TabButton;
|
||||||
|
import org.openautonomousconnection.webclient.ui.tab.TabButtonView;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
public final class MainFrame extends BrowserFrame{
|
public final class MainFrame extends BrowserFrame {
|
||||||
@Getter
|
@Getter
|
||||||
private Tab openTab;
|
private Tab openTab;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private DOMContainerPanel domContainerPanel;
|
||||||
|
|
||||||
public MainFrame() {
|
public MainFrame() {
|
||||||
|
super(new TabButtonView());
|
||||||
|
|
||||||
this.setSize(800, 600);
|
this.setSize(800, 600);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -24,5 +35,47 @@ public final class MainFrame extends BrowserFrame{
|
|||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.add(this.topBar, BorderLayout.NORTH);
|
||||||
|
this.domContainerPanel = new DOMContainerPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
this.open(this.openTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TabButtonView getTopBar() {
|
||||||
|
return (TabButtonView) this.topBar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenTab(int index) {
|
||||||
|
this.openTab = this.getTopBar().getButton(index).getTab();
|
||||||
|
|
||||||
|
this.getTopBar().getButton(index).grabFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenTab(Tab tab) {
|
||||||
|
for(TabButton button : this.getTopBar().getTabButtons())
|
||||||
|
if(button.getTab().equals(tab)) {
|
||||||
|
this.openTab = button.getTab();
|
||||||
|
button.grabFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(URL url) {
|
||||||
|
TabButton button = new TabButton(url);
|
||||||
|
|
||||||
|
this.getTopBar().addButton(button);
|
||||||
|
|
||||||
|
button.grabFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(Tab tab) {
|
||||||
|
TabButton button = new TabButton(tab);
|
||||||
|
|
||||||
|
this.getTopBar().addButton(button);
|
||||||
|
|
||||||
|
button.grabFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/* Author: Maple
|
||||||
|
* Jan. 18 2026
|
||||||
|
* */
|
||||||
|
|
||||||
|
package org.openautonomousconnection.webclient.ui;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.openautonomousconnection.webclient.Main;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.FocusEvent;
|
||||||
|
import java.awt.event.FocusListener;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.event.MouseListener;
|
||||||
|
|
||||||
|
public class MenuButton extends JButton {
|
||||||
|
@Getter
|
||||||
|
private ClickAction clickAction;
|
||||||
|
|
||||||
|
public MenuButton(Icon icon, ClickAction clickAction) {
|
||||||
|
this.setIcon(icon);
|
||||||
|
|
||||||
|
this.clickAction = clickAction;
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MenuButton(String text, ClickAction clickAction) {
|
||||||
|
this.setText(text);
|
||||||
|
|
||||||
|
this.clickAction = clickAction;
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
this.setBackground(Color.gray);
|
||||||
|
|
||||||
|
this.setForeground(Color.lightGray);
|
||||||
|
|
||||||
|
this.setBorderPainted(false);
|
||||||
|
|
||||||
|
this.addActionListener(e -> {
|
||||||
|
|
||||||
|
|
||||||
|
switch (this.clickAction) {
|
||||||
|
case CLOSE -> Main.mainFrame.dispose();
|
||||||
|
case MINIMIZE -> Main.mainFrame.setState(JFrame.ICONIFIED);
|
||||||
|
case MAXIMIZE -> {
|
||||||
|
if(Main.mainFrame.getExtendedState() == JFrame.NORMAL) {
|
||||||
|
this.setText("(_)");
|
||||||
|
|
||||||
|
Main.mainFrame.setExtendedState(
|
||||||
|
Main.mainFrame.getExtendedState() | JFrame.MAXIMIZED_BOTH
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setText("[]");
|
||||||
|
Main.mainFrame.setExtendedState(JFrame.NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addFocusListener(new FocusListener() {
|
||||||
|
@Override
|
||||||
|
public void focusGained(FocusEvent e) {
|
||||||
|
setBorderPainted(false);
|
||||||
|
// setBackground(Color.getHSBColor(0.65f, 0.5f, 0.6f));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusLost(FocusEvent e) {
|
||||||
|
// setBackground(Color.gray);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addMouseListener(new MouseListener() {
|
||||||
|
@Override
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mousePressed(MouseEvent e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseReleased(MouseEvent e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseEntered(MouseEvent e) {
|
||||||
|
setBackground(Color.getHSBColor(0.65f, 0.3f, 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseExited(MouseEvent e) {
|
||||||
|
setBackground(Color.gray);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ClickAction {
|
||||||
|
CLOSE,
|
||||||
|
MINIMIZE,
|
||||||
|
MAXIMIZE
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/* Author: Maple
|
||||||
|
* Jan. 19 2026
|
||||||
|
* */
|
||||||
|
|
||||||
|
package org.openautonomousconnection.webclient.ui;
|
||||||
|
|
||||||
|
import javax.swing.border.Border;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
|
||||||
|
public class RoundedBorder implements Border {
|
||||||
|
|
||||||
|
private final int radius;
|
||||||
|
|
||||||
|
public RoundedBorder(int radius) {
|
||||||
|
this.radius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Insets getBorderInsets(Component c) {
|
||||||
|
return new Insets(radius, radius, radius, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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();
|
||||||
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||||
|
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
|
g2.setColor(c.getForeground());
|
||||||
|
g2.draw(new RoundRectangle2D.Double(
|
||||||
|
x, y,
|
||||||
|
width - 1, height - 1,
|
||||||
|
radius, radius
|
||||||
|
));
|
||||||
|
|
||||||
|
g2.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/* Author: Maple
|
||||||
|
* Jan. 18 2026
|
||||||
|
* */
|
||||||
|
|
||||||
|
package org.openautonomousconnection.webclient.ui;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.openautonomousconnection.webclient.Main;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.event.MouseMotionAdapter;
|
||||||
|
|
||||||
|
public class TopBar extends JPanel {
|
||||||
|
@Getter
|
||||||
|
private MenuButton closeButton, minimizeButton, maximizeButton;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private JPanel buttonPanel;
|
||||||
|
|
||||||
|
private Point dragOffset;
|
||||||
|
|
||||||
|
public TopBar() {
|
||||||
|
this.setPreferredSize(new Dimension(0, 40));
|
||||||
|
|
||||||
|
this.buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||||
|
|
||||||
|
this.closeButton = new MenuButton("X", MenuButton.ClickAction.CLOSE);
|
||||||
|
this.minimizeButton = new MenuButton("-", MenuButton.ClickAction.MINIMIZE);
|
||||||
|
this.maximizeButton = new MenuButton("[]", MenuButton.ClickAction.MAXIMIZE);
|
||||||
|
|
||||||
|
this.buttonPanel.add(this.closeButton);
|
||||||
|
this.buttonPanel.add(this.minimizeButton);
|
||||||
|
this.buttonPanel.add(this.maximizeButton);
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
this.addMouseListener(new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mousePressed(MouseEvent e) {
|
||||||
|
Point mouseOnScreen = e.getLocationOnScreen();
|
||||||
|
Point frameLocation = Main.mainFrame.getLocation();
|
||||||
|
|
||||||
|
dragOffset = new Point(
|
||||||
|
mouseOnScreen.x - frameLocation.x,
|
||||||
|
mouseOnScreen.y - frameLocation.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseReleased(MouseEvent e) {
|
||||||
|
dragOffset = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addMouseMotionListener(new MouseMotionAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseDragged(MouseEvent e) {
|
||||||
|
if (dragOffset != null) {
|
||||||
|
Point mouseOnScreen = e.getLocationOnScreen();
|
||||||
|
|
||||||
|
int newX = mouseOnScreen.x - dragOffset.x;
|
||||||
|
int newY = mouseOnScreen.y - dragOffset.y;
|
||||||
|
|
||||||
|
Main.mainFrame.setLocation(newX, newY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initButtonPanel(String alignment) {
|
||||||
|
this.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
this.add(this.buttonPanel, alignment);
|
||||||
|
|
||||||
|
this.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/* Author: Maple
|
||||||
|
* Dec. 12 2025
|
||||||
|
* */
|
||||||
|
|
||||||
|
package org.openautonomousconnection.webclient.ui.dom;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class DOMContainerPanel extends JPanel {
|
||||||
|
@Getter
|
||||||
|
JPanel dom;
|
||||||
|
|
||||||
|
public DOMContainerPanel() {
|
||||||
|
this.setBackground(Color.LIGHT_GRAY);
|
||||||
|
|
||||||
|
this.dom = HTMLRenderer.render(Jsoup.parse("""
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p> hello world! </p> \s
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
\s
|
||||||
|
\s
|
||||||
|
\s"""));
|
||||||
|
|
||||||
|
this.add(this.dom);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package org.openautonomousconnection.webclient.ui.dom;
|
||||||
|
|
||||||
|
import org.jsoup.nodes.Attributes;
|
||||||
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.openautonomousconnection.webclient.ui.dom.renderers.HTMLTextRenderer;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class HTMLRenderer {
|
||||||
|
public static JPanel render(Document html) {
|
||||||
|
JPanel panel = new JPanel();
|
||||||
|
|
||||||
|
for(JComponent component : renderHead(html.head()))
|
||||||
|
panel.add(component);
|
||||||
|
|
||||||
|
for(JComponent component : renderBody(html.body()))
|
||||||
|
panel.add(component);
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<JComponent> renderHead(Element head) {
|
||||||
|
List<JComponent> result = new ArrayList<>();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<JComponent> renderBody(Element body) {
|
||||||
|
return renderAndChildren(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<JComponent> renderAndChildren(Element element) {
|
||||||
|
List<JComponent> result = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
element.children().forEach(e -> {
|
||||||
|
if(!e.children().isEmpty())
|
||||||
|
result.addAll(renderAndChildren(e));
|
||||||
|
|
||||||
|
result.add(renderElement(e));
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JComponent renderElement(Element element) {
|
||||||
|
String tagName = element.tagName().toLowerCase();
|
||||||
|
|
||||||
|
String text = element.text();
|
||||||
|
|
||||||
|
Attributes attributes = element.attributes();
|
||||||
|
|
||||||
|
String className = element.className();
|
||||||
|
|
||||||
|
switch (tagName) {
|
||||||
|
case "p":
|
||||||
|
case "u":
|
||||||
|
case "var":
|
||||||
|
case "span":
|
||||||
|
case "h1":
|
||||||
|
case "h2":
|
||||||
|
case "h3":
|
||||||
|
case "em":
|
||||||
|
case "del":
|
||||||
|
case "ins":
|
||||||
|
case "q":
|
||||||
|
case "sub":
|
||||||
|
case "sup":
|
||||||
|
case "cite":
|
||||||
|
case "code":
|
||||||
|
case "b":
|
||||||
|
case "i":
|
||||||
|
case "strong":
|
||||||
|
case "blockquote":
|
||||||
|
return HTMLTextRenderer.render(
|
||||||
|
HTMLTextRenderer.TEXTTYPE.of(tagName),
|
||||||
|
text,
|
||||||
|
attributes,
|
||||||
|
className
|
||||||
|
);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return new JPanel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package org.openautonomousconnection.webclient.ui.dom.renderers;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.jsoup.nodes.Attributes;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class HTMLTextRenderer {
|
||||||
|
|
||||||
|
|
||||||
|
public static JComponent render(TEXTTYPE texttype, String text, Attributes attributes, String className) {
|
||||||
|
// TODO: Implementation
|
||||||
|
return switch (texttype) {
|
||||||
|
case P, VAR, SPAN, H1, H2, H3 -> renderSimple(text, "", attributes, className);
|
||||||
|
case U -> renderSimple(text, "underlined", attributes, className);
|
||||||
|
case INS -> null;
|
||||||
|
case Q -> null;
|
||||||
|
case SUB -> null;
|
||||||
|
case SUP -> null;
|
||||||
|
case CITE -> null;
|
||||||
|
case CODE -> null;
|
||||||
|
// remember: b = bold text, Strong = bold & emphasized, like with TTS
|
||||||
|
case B, STRONG -> renderSimple(text, "bold", attributes, className);
|
||||||
|
case I -> renderSimple(text, "italic", attributes, className);
|
||||||
|
case EM -> renderSimple(text, "bold italic", attributes, className);
|
||||||
|
case DEL -> renderSimple(text, "strikethrough", attributes, className);
|
||||||
|
case BLOCKQUOTE -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JComponent renderSimple(String text, String decoration, Attributes attributes, String className) {
|
||||||
|
JLabel label = new JLabel(text);
|
||||||
|
|
||||||
|
int d = Font.PLAIN;
|
||||||
|
|
||||||
|
Font font = new Font(Font.SERIF, Font.PLAIN, 10);
|
||||||
|
|
||||||
|
|
||||||
|
// try { TODO: implement css
|
||||||
|
// font = new Font(
|
||||||
|
// attributes.get("font"),
|
||||||
|
// Font.PLAIN,
|
||||||
|
// 0);
|
||||||
|
// } catch (Exception ignored) {
|
||||||
|
// font = new Font(Font.SERIF, Font.PLAIN, 0);
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
label.setFont(font);
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TEXTTYPE {
|
||||||
|
P("p"),
|
||||||
|
U("u"),
|
||||||
|
VAR("var"),
|
||||||
|
SPAN("span"),
|
||||||
|
H1("h1"),
|
||||||
|
H2("h2"),
|
||||||
|
H3("h3"),
|
||||||
|
EM("em"),
|
||||||
|
DEL("del"),
|
||||||
|
INS("ins"),
|
||||||
|
Q("q"),
|
||||||
|
SUB("sub"),
|
||||||
|
SUP("sup"),
|
||||||
|
CITE("cite"),
|
||||||
|
CODE("code"),
|
||||||
|
B("b"),
|
||||||
|
I("i"),
|
||||||
|
STRONG("strong"),
|
||||||
|
BLOCKQUOTE("blockquote");
|
||||||
|
|
||||||
|
public static TEXTTYPE of(String name) {
|
||||||
|
for(TEXTTYPE texttype : values())
|
||||||
|
if(texttype.name.equals(name))
|
||||||
|
return texttype;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
TEXTTYPE(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,4 +28,8 @@ public class TabButton extends JButton {
|
|||||||
public TabButton(@NonNull URL infoName) {
|
public TabButton(@NonNull URL infoName) {
|
||||||
this.tab = new Tab(infoName);
|
this.tab = new Tab(infoName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TabButton(@NonNull Tab tab) {
|
||||||
|
this.tab = tab;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,22 +5,22 @@
|
|||||||
package org.openautonomousconnection.webclient.ui.tab;
|
package org.openautonomousconnection.webclient.ui.tab;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.openautonomousconnection.webclient.ui.TopBar;
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View at the top of the screen that contains the tabs
|
* View at the top of the screen that contains the tabs
|
||||||
*/
|
*/
|
||||||
public class TabButtonView extends JPanel {
|
public class TabButtonView extends TopBar {
|
||||||
@Getter
|
@Getter
|
||||||
private final List<TabButton> tabButtons;
|
private final List<TabButton> tabButtons;
|
||||||
|
|
||||||
public TabButtonView() {
|
public TabButtonView() {
|
||||||
this(Collections.emptyList());
|
this(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,12 +28,18 @@ public class TabButtonView extends JPanel {
|
|||||||
* @param tabButtons already created buttons
|
* @param tabButtons already created buttons
|
||||||
*/
|
*/
|
||||||
public TabButtonView(Collection<TabButton> tabButtons) {
|
public TabButtonView(Collection<TabButton> tabButtons) {
|
||||||
|
super();
|
||||||
this.tabButtons = (List<TabButton>) tabButtons;
|
this.tabButtons = (List<TabButton>) tabButtons;
|
||||||
|
|
||||||
FlowLayout layoutStyle = new FlowLayout(FlowLayout.LEFT, 0, 0);
|
FlowLayout layoutStyle = new FlowLayout(FlowLayout.RIGHT, 0, 0);
|
||||||
|
|
||||||
this.setLayout(layoutStyle);
|
this.setLayout(layoutStyle);
|
||||||
|
|
||||||
|
this.setBackground(Color.gray);
|
||||||
|
|
||||||
|
this.add(this.getButtonPanel());
|
||||||
|
|
||||||
|
this.getButtonPanel().setBackground(this.getBackground());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addButton(TabButton tabButton) {
|
public void addButton(TabButton tabButton) {
|
||||||
|
|||||||
Reference in New Issue
Block a user