mirror of
https://github.com/ME1312/SubServers-2.git
synced 2024-11-22 02:08:27 +01:00
Update SubServers.Console
This commit is contained in:
parent
de0e9a676d
commit
910b504af8
@ -18,8 +18,8 @@
|
||||
<dependency>
|
||||
<groupId>org.fusesource.jansi</groupId>
|
||||
<artifactId>jansi</artifactId>
|
||||
<version>1.17.1</version>
|
||||
<scope>provided</scope>
|
||||
<version>1.18</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.intellij</groupId>
|
||||
|
@ -1,4 +1,4 @@
|
||||
name: SubServers-Console
|
||||
main: net.ME1312.SubServers.Console.ConsolePlugin
|
||||
version: 2.16a
|
||||
version: 2.17a
|
||||
author: ME1312
|
Binary file not shown.
@ -5,6 +5,7 @@ import net.ME1312.SubServers.Bungee.Event.SubCreateEvent;
|
||||
import net.ME1312.SubServers.Bungee.Event.SubSendCommandEvent;
|
||||
import net.ME1312.SubServers.Bungee.Event.SubStartEvent;
|
||||
import net.ME1312.SubServers.Bungee.Host.Host;
|
||||
import net.ME1312.SubServers.Bungee.Host.RemotePlayer;
|
||||
import net.ME1312.SubServers.Bungee.Host.SubCreator;
|
||||
import net.ME1312.SubServers.Bungee.Host.SubServer;
|
||||
import net.ME1312.SubServers.Bungee.SubAPI;
|
||||
@ -19,6 +20,7 @@ import net.md_5.bungee.event.EventPriority;
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
||||
@ -103,7 +105,8 @@ public final class ConsolePlugin extends Plugin implements Listener {
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onServerCommand(SubSendCommandEvent event) {
|
||||
if (!event.isCancelled() && sCurrent.keySet().contains(event.getServer().getName().toLowerCase())) {
|
||||
sCurrent.get(event.getServer().getName().toLowerCase()).log('<' + ((event.getPlayer() == null)?"CONSOLE":((getProxy().getPlayer(event.getPlayer()) == null)?event.getPlayer().toString():getProxy().getPlayer(event.getPlayer()).getName())) + "> /" + event.getCommand());
|
||||
RemotePlayer player = (event.getPlayer() == null)? null : SubAPI.getInstance().getRemotePlayer(event.getPlayer());
|
||||
sCurrent.get(event.getServer().getName().toLowerCase()).log(((player == null)? "CONSOLE" : player.getName()) + "> /" + event.getCommand());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,11 +24,15 @@ import java.io.*;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
public final class ConsoleWindow implements SubLogFilter {
|
||||
private static final int MAX_SCROLLBACK = (Integer.getInteger("subservers.console.max_scrollback", 0) >= 128)?Integer.getInteger("subservers.console.max_scrollback"):7500;
|
||||
private static final String RESET_VALUE = "\n\u00A0\n\u00A0";
|
||||
private static final int MAX_SCROLLBACK = (Integer.getInteger("subservers.console.max_scrollback", 0) > 0)?Integer.getInteger("subservers.console.max_scrollback"):7500;
|
||||
private ConsolePlugin plugin;
|
||||
private JFrame window;
|
||||
private double scale = 1.0;
|
||||
@ -48,53 +52,56 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
private int findO = 0;
|
||||
private int findI = 0;
|
||||
private boolean open = false;
|
||||
private boolean running = true;
|
||||
private LinkedList<Object> messages = new LinkedList<Object>();
|
||||
private ExecutorService thread;
|
||||
private SubLogger logger;
|
||||
private int fontSize;
|
||||
private File file = null;
|
||||
private FileOutputStream filewriter = null;
|
||||
private List<Runnable> spost = new LinkedList<Runnable>();
|
||||
private ByteArrayOutputStream scache = new ByteArrayOutputStream();
|
||||
private AnsiUIOutputStream stream = AnsiUIOutputStream.wrap(new OutputStream() {
|
||||
private long sbytes = -Long.MAX_VALUE;
|
||||
private LinkedList<Long> slines = new LinkedList<Long>();
|
||||
private LinkedList<Runnable> spost = new LinkedList<Runnable>();
|
||||
private AnsiUIOutputStream stream = HTMLogger.wrap(new OutputStream() {
|
||||
private final ByteArrayOutputStream scache = new ByteArrayOutputStream();
|
||||
|
||||
private int countLines(String str) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < str.length(); i++) if (str.charAt(i) == '\n') count++;
|
||||
for (int i = 1; i < str.codePoints().count(); i++) if (str.codePointAt(i) == '\n') count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
scache.write(b);
|
||||
if (b == '\n') {
|
||||
try {
|
||||
HTMLEditorKit kit = (HTMLEditorKit) log.getEditorKit();
|
||||
HTMLDocument doc = (HTMLDocument) log.getDocument();
|
||||
kit.insertHTML(doc, doc.getLength() - 2, new String(scache.toByteArray(), "UTF-8"), 0, 0, null);
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
hScroll();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {} try {
|
||||
int lines;
|
||||
String content;
|
||||
if (log.getSelectionStart() == log.getSelectionEnd() && (lines = countLines(content = log.getDocument().getText(0, log.getDocument().getLength()))) > MAX_SCROLLBACK + 2) {
|
||||
int lineBreak = 1;
|
||||
for (lines -= MAX_SCROLLBACK; lines > 0; lines--) lineBreak = content.indexOf('\n', lineBreak + 1);
|
||||
if (lineBreak <= log.getDocument().getLength() - 2 && log.getSelectionStart() == log.getSelectionEnd()) {
|
||||
log.getDocument().remove(0, lineBreak);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
try {
|
||||
HTMLDocument doc = (HTMLDocument) log.getDocument();
|
||||
((HTMLEditorKit) log.getEditorKit()).insertHTML(doc, doc.getLength() - 2, new String(scache.toByteArray(), UTF_8), 0, 0, null);
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
hScroll();
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
for (Runnable post : spost) try {
|
||||
post.run();
|
||||
} catch (Throwable e) {}
|
||||
spost.clear();
|
||||
scache = new ByteArrayOutputStream();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {} try {
|
||||
int lines;
|
||||
String content;
|
||||
HTMLDocument doc = (HTMLDocument) log.getDocument();
|
||||
if (log.getSelectionStart() == log.getSelectionEnd() && (lines = countLines(content = doc.getText(2, doc.getLength() - 2))) > MAX_SCROLLBACK) {
|
||||
int lfl = 0;
|
||||
for (lines -= MAX_SCROLLBACK; lines > 0; --lines) lfl = content.indexOf('\n', lfl + 1);
|
||||
if (log.getSelectionStart() == log.getSelectionEnd()) {
|
||||
doc.remove(2, lfl);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
for (Runnable post : spost) try {
|
||||
post.run();
|
||||
} catch (Throwable e) {}
|
||||
spost.clear();
|
||||
scache.reset();
|
||||
}
|
||||
}, new HTMLogger.HTMConstructor<AnsiUIOutputStream>() {
|
||||
@Override
|
||||
@ -193,6 +200,7 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
ConsoleWindow.this.clear();
|
||||
ConsoleWindow.this.hScroll();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
@ -201,8 +209,9 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
item.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
log.setText(RESET_VALUE);
|
||||
ConsoleWindow.this.clear();
|
||||
ConsoleWindow.this.loadContent();
|
||||
ConsoleWindow.this.hScroll();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
@ -315,8 +324,9 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
stream.ansi(((AbstractButton) event.getSource()).getModel().isSelected());
|
||||
log.setText(RESET_VALUE);
|
||||
ConsoleWindow.this.clear();
|
||||
ConsoleWindow.this.loadContent();
|
||||
ConsoleWindow.this.hScroll();
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
@ -325,7 +335,7 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
HTMLDocument doc = (HTMLDocument) log.getDocument();
|
||||
fontSize = (int) (12 * scale);
|
||||
fontSize = (int) (13 * scale);
|
||||
doc.getStyleSheet().addRule("body {font-size: " + fontSize + ";}\n");
|
||||
ConsoleWindow.this.hScroll();
|
||||
}
|
||||
@ -337,7 +347,7 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
HTMLDocument doc = (HTMLDocument) log.getDocument();
|
||||
fontSize += 2 * scale;
|
||||
fontSize += scale;
|
||||
doc.getStyleSheet().addRule("body {font-size: " + fontSize + ";}\n");
|
||||
ConsoleWindow.this.hScroll();
|
||||
}
|
||||
@ -349,7 +359,7 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
HTMLDocument doc = (HTMLDocument) log.getDocument();
|
||||
fontSize -= 2 * scale;
|
||||
fontSize -= scale;
|
||||
doc.getStyleSheet().addRule("body {font-size: " + fontSize + ";}\n");
|
||||
ConsoleWindow.this.hScroll();
|
||||
}
|
||||
@ -367,11 +377,10 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
}
|
||||
});
|
||||
window.setTitle(logger.getName() + " \u2014 SubServers 2");
|
||||
window.setSize(1024, 576);
|
||||
window.setSize((int) (1024 * scale), (int) (576 * scale));
|
||||
window.setSize((int) (1280 * scale), (int) (720 * scale));
|
||||
window.setLocation(
|
||||
(int) ((screen.getWidth() - window.getWidth()) / 2),
|
||||
(int) ((screen.getHeight() - window.getHeight()) / 2)
|
||||
(int) Math.abs((screen.getWidth() - window.getWidth()) / 2),
|
||||
(int) Math.abs((screen.getHeight() - window.getHeight()) / 2)
|
||||
);
|
||||
window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
window.addWindowListener(new WindowAdapter() {
|
||||
@ -391,13 +400,13 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
log.setContentType("text/html");
|
||||
log.setEditorKit(new HTMLEditorKit());
|
||||
StyleSheet style = new StyleSheet();
|
||||
fontSize = (int) (12 * scale);
|
||||
fontSize = (int) (13 * scale);
|
||||
String font;
|
||||
try {
|
||||
Font f = Font.createFont(Font.TRUETYPE_FONT, ConsoleWindow.class.getResourceAsStream("/net/ME1312/SubServers/Console/ConsoleFont.ttf"));
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(f);
|
||||
font = f.getFontName();
|
||||
input.setFont(f.deriveFont((float) (14 * scale)));
|
||||
input.setFont(f);
|
||||
} catch (Exception e) {
|
||||
font = "Courier";
|
||||
}
|
||||
@ -447,11 +456,13 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
if (offset < 1) {
|
||||
return;
|
||||
}
|
||||
string = string.replace("\n", "\\n");
|
||||
super.insertString(fb, offset, string, attr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
|
||||
text = text.replace("\n", "\\n");
|
||||
if (offset < 1) {
|
||||
length = Math.max(0, length - 1);
|
||||
offset = input.getDocument().getLength();
|
||||
@ -552,7 +563,6 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
}
|
||||
});
|
||||
findP.setBorder(new ButtonBorder(40, 44, 45, (int) (4 * scale)));
|
||||
findN.setFont(findN.getFont().deriveFont((float) (findN.getFont().getSize() * scale)));
|
||||
findP.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
@ -567,6 +577,7 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
}
|
||||
});
|
||||
findN.setBorder(new ButtonBorder(40, 44, 45, (int) (4 * scale)));
|
||||
findN.setFont(findN.getFont().deriveFont((float) (findN.getFont().getSize() * scale)));
|
||||
findN.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
@ -600,32 +611,116 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
vScroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
}
|
||||
|
||||
thread = Executors.newSingleThreadExecutor(new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
return new Thread(r, "SubServers.Console::Log_Spooler(" + logger.getName() + ")");
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
clear();
|
||||
slines.add(sbytes);
|
||||
stream.write("\u00A0".getBytes(UTF_8));
|
||||
} catch (IOException e) {}
|
||||
|
||||
logger.registerFilter(this);
|
||||
log.setText(RESET_VALUE);
|
||||
loadContent();
|
||||
log();
|
||||
hScroll();
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(keys);
|
||||
}
|
||||
private void hScroll() {
|
||||
hScroll.setMaximum(vScroll.getHorizontalScrollBar().getMaximum());
|
||||
hScroll.setMinimum(vScroll.getHorizontalScrollBar().getMinimum());
|
||||
hScroll.setVisibleAmount(vScroll.getHorizontalScrollBar().getVisibleAmount());
|
||||
hScroll.setVisible(input.isVisible() && hScroll.getVisibleAmount() < hScroll.getMaximum());
|
||||
|
||||
@Override
|
||||
public void start() {}
|
||||
public void open() {
|
||||
if (!open) {
|
||||
window.setVisible(true);
|
||||
this.open = true;
|
||||
}
|
||||
window.toFront();
|
||||
}
|
||||
|
||||
public SubLogger getLogger() {
|
||||
return logger;
|
||||
private void loadContent() {
|
||||
this.sbytes = (slines.size() > 0) ? slines.getFirst() : -Long.MAX_VALUE;
|
||||
this.slines.clear();
|
||||
this.slines.add(sbytes);
|
||||
|
||||
try (FileInputStream reader = new FileInputStream(file)) {
|
||||
if (sbytes > -Long.MAX_VALUE) {
|
||||
if (sbytes > 0) {
|
||||
reader.skip(sbytes);
|
||||
reader.skip(Long.MAX_VALUE);
|
||||
} else {
|
||||
reader.skip(sbytes + Long.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
int i;
|
||||
byte[] b = new byte[1024];
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
while ((i = reader.read(b)) != -1) {
|
||||
stream.write(b, 0, i);
|
||||
}
|
||||
|
||||
submit(stream.toString(UTF_8.name()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void log(Date date, String message) {
|
||||
private void submit(final String s) {
|
||||
thread.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int begin = 0;
|
||||
int end, i, bytes;
|
||||
do {
|
||||
i = s.indexOf('\n', begin);
|
||||
end = (i == -1) ? s.length() : i + 1;
|
||||
|
||||
// Submit the text (without any newlines)
|
||||
stream.write(s.substring(begin, (i == -1) ? s.length() : i).getBytes(UTF_8));
|
||||
|
||||
// Count the bytes (with 1 possible newline)
|
||||
bytes = s.substring(begin, end).getBytes(UTF_8).length;
|
||||
if (sbytes + bytes < sbytes) sbytes = Long.MAX_VALUE;
|
||||
else sbytes += bytes;
|
||||
|
||||
// Submit a newline if necessary
|
||||
if (i != -1) {
|
||||
stream.closeAttributes();
|
||||
stream.write("\u00A0".getBytes(UTF_8));
|
||||
stream.flush();
|
||||
stream.write("\n\u00A0".getBytes(UTF_8));
|
||||
slines.add(sbytes);
|
||||
while (slines.size() > MAX_SCROLLBACK + 1) {
|
||||
slines.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
// Continue to the next line if available
|
||||
begin = end;
|
||||
} while (begin < s.length());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
public void log(String message) {
|
||||
message += '\n';
|
||||
try {
|
||||
messages.add(('\u00A0' + new SimpleDateFormat("hh:mm:ss").format(date) + ' ' + message + "\u00A0\n").getBytes("UTF-8"));
|
||||
filewriter.write(message.getBytes(UTF_8));
|
||||
filewriter.flush();
|
||||
|
||||
submit(message);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public void log(String message) {
|
||||
log(Calendar.getInstance().getTime(), message);
|
||||
public void log(Date date, String message) {
|
||||
log(new SimpleDateFormat("hh:mm:ss").format(date) + ' ' + message);
|
||||
}
|
||||
public void log(Date date, Level level, String message) {
|
||||
log(date, "[" + level.getLocalizedName() + "] " + message);
|
||||
@ -636,64 +731,16 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
return !open;
|
||||
}
|
||||
|
||||
private void log() {
|
||||
new Thread("SubServers.Console::Log_Spooler(" + logger.getName() + ")") {
|
||||
@Override
|
||||
public void run() {
|
||||
while (running) {
|
||||
while (running && messages.size() > 0) try {
|
||||
byte[] msg = (byte[]) Util.getDespiteException(new ExceptionReturnRunnable<Object>() {
|
||||
@Override
|
||||
public Object run() throws Throwable {
|
||||
return messages.get(0);
|
||||
}
|
||||
}, null);
|
||||
if (msg != null) {
|
||||
filewriter.write(msg);
|
||||
stream.write(msg);
|
||||
}
|
||||
try { ConsoleWindow.this.messages.remove(0); } catch (Throwable e) {}
|
||||
} catch (Throwable e) {
|
||||
try { ConsoleWindow.this.messages.remove(0); } catch (Throwable ex) {}
|
||||
e.printStackTrace();
|
||||
}
|
||||
try { Thread.sleep(32); } catch (Throwable e) {}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
log.setText(RESET_VALUE);
|
||||
hScroll();
|
||||
}
|
||||
|
||||
public void open() {
|
||||
if (!open) {
|
||||
window.setVisible(true);
|
||||
this.open = true;
|
||||
}
|
||||
window.toFront();
|
||||
log.setText("\n\u00A0\n\u00A0");
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return open;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {}
|
||||
private void loadContent() {
|
||||
if (file != null) {
|
||||
try (FileInputStream reader = new FileInputStream(file)) {
|
||||
int b;
|
||||
while ((b = reader.read()) != -1) {
|
||||
stream.write(b);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
hScroll();
|
||||
}
|
||||
public SubLogger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -715,7 +762,7 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
|
||||
public void destroy() {
|
||||
close();
|
||||
running = false;
|
||||
thread.shutdown();
|
||||
logger.unregisterFilter(this);
|
||||
if (filewriter != null) try {
|
||||
filewriter.close();
|
||||
@ -724,6 +771,13 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(keys);
|
||||
}
|
||||
|
||||
private void hScroll() {
|
||||
hScroll.setMaximum(vScroll.getHorizontalScrollBar().getMaximum());
|
||||
hScroll.setMinimum(vScroll.getHorizontalScrollBar().getMinimum());
|
||||
hScroll.setVisibleAmount(vScroll.getHorizontalScrollBar().getVisibleAmount());
|
||||
hScroll.setVisible(input.isVisible() && hScroll.getVisibleAmount() < hScroll.getMaximum());
|
||||
}
|
||||
|
||||
private void find(boolean direction) {
|
||||
if (!direction) findI -= findO + 1;
|
||||
String find = findT.getText().toLowerCase();
|
||||
@ -887,6 +941,7 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
private class AnsiUIOutputStream extends HTMLogger {
|
||||
public AnsiUIOutputStream(OutputStream raw, OutputStream wrapped) {
|
||||
super(raw, wrapped);
|
||||
nbsp = true;
|
||||
}
|
||||
|
||||
public void ansi(boolean value) {
|
||||
@ -908,7 +963,8 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
if (ansi) spost.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
log.setText(RESET_VALUE);
|
||||
ConsoleWindow.this.clear();
|
||||
ConsoleWindow.this.hScroll();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -940,11 +996,11 @@ public final class ConsoleWindow implements SubLogFilter {
|
||||
}
|
||||
}
|
||||
private class SmartScroller implements AdjustmentListener {
|
||||
public final static int HORIZONTAL = 0;
|
||||
public final static int VERTICAL = 1;
|
||||
private final static int HORIZONTAL = 0;
|
||||
private final static int VERTICAL = 1;
|
||||
|
||||
public final static int START = 0;
|
||||
public final static int END = 1;
|
||||
private final static int START = 0;
|
||||
private final static int END = 1;
|
||||
|
||||
private int viewportPosition;
|
||||
|
||||
|
@ -1,82 +1,74 @@
|
||||
package net.ME1312.SubServers.Console.Library;
|
||||
|
||||
import net.ME1312.Galaxi.Library.Container.Container;
|
||||
import net.ME1312.Galaxi.Library.Container.Value;
|
||||
|
||||
import org.fusesource.jansi.AnsiOutputStream;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
* HTML Log Stream Class
|
||||
*/
|
||||
public class HTMLogger extends AnsiOutputStream {
|
||||
private static final String[] ANSI_COLOR_MAP = new String[]{"000000", "cd0000", "25bc24", "d7d700", "0000c3", "be00be", "00a5dc", "cccccc"};
|
||||
private static final String[] ANSI_BRIGHT_COLOR_MAP = new String[]{"808080", "ff0000", "31e722", "ffff00", "0000ff", "ff00ff", "00c8ff", "ffffff"};
|
||||
private static final byte[] BYTES_NBSP = " ".getBytes();
|
||||
private static final byte[] BYTES_QUOT = """.getBytes();
|
||||
private static final byte[] BYTES_AMP = "&".getBytes();
|
||||
private static final byte[] BYTES_LT = "<".getBytes();
|
||||
private static final byte[] BYTES_GT = ">".getBytes();
|
||||
private LinkedList<String> closingAttributes = new LinkedList<String>();
|
||||
private static final byte[] BYTES_NBSP = "\u00A0".getBytes(UTF_8);
|
||||
private static final byte[] BYTES_AMP = "&".getBytes(UTF_8);
|
||||
private static final byte[] BYTES_LT = "<".getBytes(UTF_8);
|
||||
private LinkedList<String> currentAttributes = new LinkedList<String>();
|
||||
private LinkedList<String> queue = new LinkedList<String>();
|
||||
private OutputStream raw;
|
||||
protected boolean ansi = true;
|
||||
protected boolean nbsp = false;
|
||||
private boolean underline = false;
|
||||
private boolean strikethrough = false;
|
||||
|
||||
/**
|
||||
* Parse data from an OutputStream
|
||||
*
|
||||
* @param raw OutputStream
|
||||
* @return HTMLogger
|
||||
*/
|
||||
public static HTMLogger wrap(OutputStream raw) {
|
||||
return wrap(raw, new HTMConstructor<HTMLogger>() {
|
||||
@Override
|
||||
public HTMLogger construct(OutputStream raw1, OutputStream wrapped) {
|
||||
return new HTMLogger(raw1, wrapped);
|
||||
public HTMLogger construct(OutputStream raw, OutputStream wrapped) {
|
||||
return new HTMLogger(raw, wrapped);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse data from an OutputStream
|
||||
*
|
||||
* @param raw OutputStream
|
||||
* @param constructor Implementing Constructor
|
||||
* @param <T> Logger Type
|
||||
* @return HTMLogger
|
||||
*/
|
||||
public static <T extends HTMLogger> T wrap(final OutputStream raw, HTMConstructor<T> constructor) {
|
||||
final Value<T> html = new Container<T>(null);
|
||||
final Container<T> html = new Container<T>(null);
|
||||
html.value(constructor.construct(raw, new OutputStream() {
|
||||
private boolean nbsp = false;
|
||||
|
||||
@Override
|
||||
public void write(int data) throws IOException {
|
||||
HTMLogger htm = html.value();
|
||||
if (htm.queue.size() > 0) {
|
||||
LinkedList<String> queue = htm.queue;
|
||||
htm.queue = new LinkedList<>();
|
||||
for (String attr : queue) {
|
||||
htm.write('<' + attr + '>');
|
||||
htm.currentAttributes.addFirst(attr);
|
||||
}
|
||||
}
|
||||
|
||||
if (data == 32) {
|
||||
if (nbsp) raw.write(BYTES_NBSP);
|
||||
else raw.write(data);
|
||||
nbsp = !nbsp;
|
||||
if (htm.nbsp) {
|
||||
if (nbsp) raw.write(BYTES_NBSP);
|
||||
else raw.write(data);
|
||||
nbsp = !nbsp;
|
||||
} else raw.write(data);
|
||||
} else {
|
||||
nbsp = false;
|
||||
switch(data) {
|
||||
case 34:
|
||||
raw.write(BYTES_QUOT);
|
||||
break;
|
||||
case 38:
|
||||
case '&':
|
||||
raw.write(BYTES_AMP);
|
||||
break;
|
||||
case 60:
|
||||
case '<':
|
||||
raw.write(BYTES_LT);
|
||||
break;
|
||||
case 62:
|
||||
raw.write(BYTES_GT);
|
||||
break;
|
||||
case 10:
|
||||
html.value().closeAttributes();
|
||||
case '\n':
|
||||
htm.closeAttributes();
|
||||
default:
|
||||
raw.write(data);
|
||||
}
|
||||
@ -85,7 +77,7 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
}));
|
||||
return html.value();
|
||||
}
|
||||
protected HTMLogger(final OutputStream raw, OutputStream wrapped) {
|
||||
public HTMLogger(final OutputStream raw, OutputStream wrapped) {
|
||||
super(wrapped);
|
||||
this.raw = raw;
|
||||
}
|
||||
@ -94,46 +86,62 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
}
|
||||
|
||||
private void write(String s) throws IOException {
|
||||
raw.write(s.getBytes());
|
||||
raw.write(s.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
private void writeAttribute(String s) throws IOException {
|
||||
write("<" + s + ">");
|
||||
closingAttributes.add(0, s);
|
||||
private void writeAttribute(String attr) throws IOException {
|
||||
queue.add(attr);
|
||||
}
|
||||
|
||||
protected void closeAttribute(String s) throws IOException {
|
||||
public void closeAttribute(String s) throws IOException {
|
||||
|
||||
// Try to remove a tag that doesn't exist yet first
|
||||
String[] queue = this.queue.toArray(new String[0]);
|
||||
for (int i = queue.length; i > 0;) {
|
||||
String attr = queue[--i];
|
||||
if (attr.toLowerCase().startsWith(s.toLowerCase())) {
|
||||
this.queue.removeLastOccurrence(attr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Close a tag that we've already written
|
||||
LinkedList<String> closedAttributes = new LinkedList<String>();
|
||||
LinkedList<String> closingAttributes = new LinkedList<String>();
|
||||
LinkedList<String> currentAttributes = new LinkedList<String>(this.currentAttributes);
|
||||
LinkedList<String> unclosedAttributes = new LinkedList<String>();
|
||||
|
||||
closingAttributes.addAll(closingAttributes);
|
||||
for (String attr : closingAttributes) {
|
||||
for (String attr : currentAttributes) {
|
||||
if (attr.toLowerCase().startsWith(s.toLowerCase())) {
|
||||
for (String a : unclosedAttributes) {
|
||||
closedAttributes.add(0, a);
|
||||
write("</" + a.split(" ", 2)[0] + ">");
|
||||
closedAttributes.add(a);
|
||||
this.currentAttributes.removeFirst();
|
||||
write("</" + a.split(" ", 2)[0] + '>');
|
||||
}
|
||||
closingAttributes.removeFirstOccurrence(attr);
|
||||
unclosedAttributes.clear();
|
||||
write("</" + attr.split(" ", 2)[0] + ">");
|
||||
this.currentAttributes.removeFirst();
|
||||
write("</" + attr.split(" ", 2)[0] + '>');
|
||||
break;
|
||||
} else {
|
||||
unclosedAttributes.add(attr);
|
||||
}
|
||||
}
|
||||
|
||||
// Queue unrelated tags to be re-opened
|
||||
for (String attr : closedAttributes) {
|
||||
write("<" + attr + ">");
|
||||
this.queue.addFirst(attr);
|
||||
}
|
||||
}
|
||||
|
||||
protected void closeAttributes() throws IOException {
|
||||
for (String attr : closingAttributes) {
|
||||
public void closeAttributes() throws IOException {
|
||||
queue.clear();
|
||||
|
||||
for (String attr : currentAttributes) {
|
||||
write("</" + attr.split(" ", 2)[0] + ">");
|
||||
}
|
||||
|
||||
underline = false;
|
||||
strikethrough = false;
|
||||
closingAttributes.clear();
|
||||
currentAttributes.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -141,13 +149,13 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
super.processDeleteLine(amount);
|
||||
}
|
||||
|
||||
private String parseTextDecoration() {
|
||||
private void renderTextDecoration() throws IOException {
|
||||
String dec = "";
|
||||
if (underline) dec += " underline";
|
||||
if (strikethrough) dec += " line-through";
|
||||
if (dec.length() <= 0) dec += " none";
|
||||
|
||||
return dec.substring(1);
|
||||
closeAttribute("span style=\"text-decoration:");
|
||||
if (dec.length() != 0) writeAttribute("span style=\"text-decoration:" + dec.substring(1) + "\"");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -162,14 +170,12 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
writeAttribute("i");
|
||||
break;
|
||||
case 4:
|
||||
closeAttribute("span class=\"ansi-decoration");
|
||||
underline = true;
|
||||
writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
|
||||
renderTextDecoration();
|
||||
break;
|
||||
case 9:
|
||||
closeAttribute("span class=\"ansi-decoration");
|
||||
strikethrough = true;
|
||||
writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
|
||||
renderTextDecoration();
|
||||
break;
|
||||
case 22:
|
||||
closeAttribute("b");
|
||||
@ -178,14 +184,23 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
closeAttribute("i");
|
||||
break;
|
||||
case 24:
|
||||
closeAttribute("span class=\"ansi-decoration");
|
||||
underline = false;
|
||||
writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
|
||||
renderTextDecoration();
|
||||
break;
|
||||
case 29:
|
||||
closeAttribute("span class=\"ansi-decoration");
|
||||
strikethrough = false;
|
||||
writeAttribute("span class=\"ansi-decoration\" style=\"text-decoration: " + parseTextDecoration() + ";\"");
|
||||
renderTextDecoration();
|
||||
break;
|
||||
case 73:
|
||||
closeAttribute("su");
|
||||
writeAttribute("sup");
|
||||
break;
|
||||
case 74:
|
||||
closeAttribute("su");
|
||||
writeAttribute("sub");
|
||||
break;
|
||||
case 75:
|
||||
closeAttribute("su");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -193,24 +208,30 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
@Override
|
||||
protected void processUnknownOperatingSystemCommand(int label, String arg) {
|
||||
try {
|
||||
if (ansi) switch (label) {
|
||||
case 99900: // Galaxi Console Exclusives 99900-99999
|
||||
closeAttribute("a");
|
||||
writeAttribute("a href=\"" + arg + "\" target=\"_blank\"");
|
||||
break;
|
||||
case 99901:
|
||||
closeAttribute("a");
|
||||
break;
|
||||
if (ansi && label == 8) {
|
||||
closeAttribute("a");
|
||||
String[] args = arg.split(";", 3);
|
||||
if (args.length > 1 && args[1].length() > 0 && allowHyperlink(args[1])) {
|
||||
writeAttribute("a href=\"" + args[1].replace("&", "&").replace("<", "<").replace("\"", """) + "\" target=\"_blank\"");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
protected boolean allowHyperlink(String link) {
|
||||
if (link.toLowerCase(Locale.ENGLISH).startsWith("mailto:execute@galaxi.engine")) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processAttributeRest() throws IOException {
|
||||
closeAttributes();
|
||||
}
|
||||
|
||||
private String parse8BitColor(int color) throws IOException {
|
||||
private String parse256(int color) throws IOException {
|
||||
if (color < 8) {
|
||||
return ANSI_COLOR_MAP[color];
|
||||
} else if (color < 16) {
|
||||
@ -230,7 +251,7 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
|
||||
@Override
|
||||
protected void processDefaultTextColor() throws IOException {
|
||||
closeAttribute("span class=\"ansi-foreground");
|
||||
closeAttribute("span style=\"color:");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -242,7 +263,8 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
protected void processSetForegroundColor(int color, boolean bright) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultTextColor();
|
||||
writeAttribute("span class=\"ansi-foreground\" style=\"color: #" + ((!bright)?ANSI_COLOR_MAP:ANSI_BRIGHT_COLOR_MAP)[color] + ";\"");
|
||||
writeAttribute("span style=\"color:#" + ((!bright)?ANSI_COLOR_MAP:ANSI_BRIGHT_COLOR_MAP)[color] + "\"");
|
||||
renderTextDecoration();
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,7 +272,8 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
protected void processSetForegroundColorExt(int index) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultTextColor();
|
||||
writeAttribute("span class=\"ansi-foreground\" style=\"color: #" + parse8BitColor(index) + ";\"");
|
||||
writeAttribute("span style=\"color:#" + parse256(index) + "\"");
|
||||
renderTextDecoration();
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,13 +281,14 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
protected void processSetForegroundColorExt(int r, int g, int b) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultTextColor();
|
||||
writeAttribute("span class=\"ansi-foreground\" style=\"color: #" + ((r >= 16)?"":"0") + Integer.toString(r, 16) + ((g >= 16)?"":"0") + Integer.toString(g, 16) + ((b >= 16)?"":"0") + Integer.toString(b, 16) + ";\"");
|
||||
writeAttribute("span style=\"color:#" + ((r >= 16)?"":"0") + Integer.toString(r, 16) + ((g >= 16)?"":"0") + Integer.toString(g, 16) + ((b >= 16)?"":"0") + Integer.toString(b, 16) + "\"");
|
||||
renderTextDecoration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processDefaultBackgroundColor() throws IOException {
|
||||
closeAttribute("span class=\"ansi-background");
|
||||
closeAttribute("span style=\"background-color:");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -276,7 +300,7 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
protected void processSetBackgroundColor(int color, boolean bright) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultBackgroundColor();
|
||||
writeAttribute("span class=\"ansi-background\" style=\"background-color: #" + ((!bright)?ANSI_COLOR_MAP:ANSI_BRIGHT_COLOR_MAP)[color] + ";\"");
|
||||
writeAttribute("span style=\"background-color:#" + ((!bright)?ANSI_COLOR_MAP:ANSI_BRIGHT_COLOR_MAP)[color] + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,7 +308,7 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
protected void processSetBackgroundColorExt(int index) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultBackgroundColor();
|
||||
writeAttribute("span class=\"ansi-background\" style=\"background-color: #" + parse8BitColor(index) + ";\"");
|
||||
writeAttribute("span style=\"background-color:#" + parse256(index) + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,10 +316,16 @@ public class HTMLogger extends AnsiOutputStream {
|
||||
protected void processSetBackgroundColorExt(int r, int g, int b) throws IOException {
|
||||
if (ansi) {
|
||||
processDefaultBackgroundColor();
|
||||
writeAttribute("span class=\"ansi-background\" style=\"background-color: #" + ((r >= 16)?"":"0") + Integer.toString(r, 16) + ((g >= 16)?"":"0") + Integer.toString(g, 16) + ((b >= 16)?"":"0") + Integer.toString(b, 16) + ";\"");
|
||||
writeAttribute("span style=\"background-color:#" + ((r >= 16)?"":"0") + Integer.toString(r, 16) + ((g >= 16)?"":"0") + Integer.toString(g, 16) + ((b >= 16)?"":"0") + Integer.toString(b, 16) + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
super.flush();
|
||||
raw.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
closeAttributes();
|
||||
|
Loading…
Reference in New Issue
Block a user