diff --git a/G-Earth-UI/src/main/java/gearth/ui/Logger.fxml b/G-Earth-UI/src/main/java/gearth/ui/Logger.fxml
new file mode 100644
index 0000000..1e68b34
--- /dev/null
+++ b/G-Earth-UI/src/main/java/gearth/ui/Logger.fxml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/G-Earth-UI/src/main/java/gearth/ui/LoggerController.java b/G-Earth-UI/src/main/java/gearth/ui/LoggerController.java
new file mode 100644
index 0000000..59668e9
--- /dev/null
+++ b/G-Earth-UI/src/main/java/gearth/ui/LoggerController.java
@@ -0,0 +1,118 @@
+package gearth.ui;
+
+import gearth.protocol.HPacket;
+import gearth.ui.logger.loggerdisplays.PacketLogger;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Label;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.FlowPane;
+import org.fxmisc.flowless.VirtualizedScrollPane;
+import org.fxmisc.richtext.StyleClassedTextArea;
+import org.fxmisc.richtext.model.StyleSpansBuilder;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.ResourceBundle;
+
+public class LoggerController implements Initializable {
+ public FlowPane flowPane;
+ public BorderPane borderPane;
+ public Label lblViewIncoming;
+ public Label lblViewOutgoing;
+
+ private StyleClassedTextArea area;
+
+ private boolean viewIncoming = true;
+ private boolean viewOutgoing = true;
+
+ @Override
+ public void initialize(URL arg0, ResourceBundle arg1) {
+ area = new StyleClassedTextArea();
+ area.getStyleClass().add("dark");
+ area.setWrapText(true);
+
+ VirtualizedScrollPane vsPane = new VirtualizedScrollPane<>(area);
+ borderPane.setCenter(vsPane);
+ }
+
+ public void appendMessage(HPacket packet, int types) {
+ boolean isBlocked = (types & PacketLogger.MESSAGE_TYPE.BLOCKED.getValue()) != 0;
+ boolean isReplaced = (types & PacketLogger.MESSAGE_TYPE.REPLACED.getValue()) != 0;
+ boolean isIncoming = (types & PacketLogger.MESSAGE_TYPE.INCOMING.getValue()) != 0;
+
+ if (isIncoming && !viewIncoming) return;
+ if (!isIncoming && !viewOutgoing) return;
+
+ ArrayList elements = new ArrayList<>();
+
+ String expr = packet.toExpression();
+
+ if (isBlocked) elements.add(new Element("[Blocked]\n", "blocked"));
+ else if (isReplaced) elements.add(new Element("[Replaced]\n", "replaced"));
+
+ if (isIncoming) {
+ // handle skipped eventually
+ elements.add(new Element("Incoming[", "incoming"));
+ elements.add(new Element(String.valueOf(packet.headerId()), ""));
+ elements.add(new Element("]", "incoming"));
+
+ elements.add(new Element(" <- ", ""));
+ elements.add(new Element(packet.toString(), "incoming"));
+
+ if (!expr.equals(""))
+ elements.add(new Element("\n" + expr, "incoming"));
+ } else {
+ elements.add(new Element("Outgoing[", "outgoing"));
+ elements.add(new Element(String.valueOf(packet.headerId()), ""));
+ elements.add(new Element("]", "outgoing"));
+
+ elements.add(new Element(" -> ", ""));
+ elements.add(new Element(packet.toString(), "outgoing"));
+
+ if (!expr.equals(""))
+ elements.add(new Element("\n" + expr, "outgoing"));
+ }
+
+ elements.add(new Element("\n--------------------\n", ""));
+ AppendLog(elements);
+ }
+
+ private void AppendLog(ArrayList elements) {
+ StringBuilder sb = new StringBuilder();
+ StyleSpansBuilder> styleSpansBuilder = new StyleSpansBuilder<>(0);
+
+ for (Element element : elements) {
+ sb.append(element.text);
+ styleSpansBuilder.add(Collections.singleton(element.className), element.text.length());
+ }
+
+ int oldLen = area.getLength();
+ area.appendText(sb.toString());
+ area.setStyleSpans(oldLen, styleSpansBuilder.create());
+
+ area.moveTo(area.getLength());
+ area.requestFollowCaret();
+ }
+
+ public void toggleViewIncoming() {
+ viewIncoming = !viewIncoming;
+ lblViewIncoming.setText("View Incoming: " + (viewIncoming ? "True" : "False"));
+ }
+
+ public void toggleViewOutgoing() {
+ viewOutgoing = !viewOutgoing;
+ lblViewOutgoing.setText("View Outgoing: " + (viewOutgoing ? "True" : "False"));
+ }
+}
+
+class Element {
+ final String text;
+ final String className;
+
+ Element(String text, String className) {
+ this.text = text;
+ this.className = className;
+ }
+}
\ No newline at end of file
diff --git a/G-Earth-UI/src/main/java/gearth/ui/logger.css b/G-Earth-UI/src/main/java/gearth/ui/logger.css
new file mode 100644
index 0000000..b759d42
--- /dev/null
+++ b/G-Earth-UI/src/main/java/gearth/ui/logger.css
@@ -0,0 +1,29 @@
+/* packet logger css */
+.text {
+ -fx-fill: #a9a9a9;
+}
+
+.blocked, .replaced {
+ -fx-fill: #ffff00;
+}
+
+.incoming {
+ -fx-fill: #b22222;
+}
+
+.outgoing {
+ -fx-fill: #0066cc;
+}
+
+.dark {
+ -fx-background-color: #000000;
+}
+
+.caret {
+ -fx-stroke: #ffffff;
+}
+
+.label {
+ -fx-color-label-visible: #000000 !important;
+ -fx-text-fill: #000000 !important;
+}
\ No newline at end of file
diff --git a/G-Earth-UI/src/main/java/gearth/ui/logger/Logger.java b/G-Earth-UI/src/main/java/gearth/ui/logger/Logger.java
index 30f4909..9d9ec12 100644
--- a/G-Earth-UI/src/main/java/gearth/ui/logger/Logger.java
+++ b/G-Earth-UI/src/main/java/gearth/ui/logger/Logger.java
@@ -1,5 +1,6 @@
package gearth.ui.logger;
+import gearth.ui.logger.loggerdisplays.UiLogger;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
diff --git a/G-Earth-UI/src/main/java/gearth/ui/logger/loggerdisplays/PacketLoggerFactory.java b/G-Earth-UI/src/main/java/gearth/ui/logger/loggerdisplays/PacketLoggerFactory.java
index 0c810eb..c12fd5f 100644
--- a/G-Earth-UI/src/main/java/gearth/ui/logger/loggerdisplays/PacketLoggerFactory.java
+++ b/G-Earth-UI/src/main/java/gearth/ui/logger/loggerdisplays/PacketLoggerFactory.java
@@ -8,13 +8,15 @@ import gearth.misc.OSValidator;
public class PacketLoggerFactory {
public static PacketLogger get() {
- if (OSValidator.isUnix()) {
- return new LinuxTerminalLogger();
- }
+// if (OSValidator.isUnix()) {
+// return new LinuxTerminalLogger();
+// }
// if (System.getenv("XDG_CURRENT_DESKTOP") != null && System.getenv("XDG_CURRENT_DESKTOP").toLowerCase().contains("gnome")) {
// return new GnomeTerminalLogger();
// }
- return new SimpleTerminalLogger();
+// return new SimpleTerminalLogger();
+
+ return new UiLogger();
}
}
diff --git a/G-Earth-UI/src/main/java/gearth/ui/logger/loggerdisplays/UiLogger.java b/G-Earth-UI/src/main/java/gearth/ui/logger/loggerdisplays/UiLogger.java
new file mode 100644
index 0000000..1c54569
--- /dev/null
+++ b/G-Earth-UI/src/main/java/gearth/ui/logger/loggerdisplays/UiLogger.java
@@ -0,0 +1,87 @@
+package gearth.ui.logger.loggerdisplays;
+
+import gearth.protocol.HPacket;
+import gearth.ui.LoggerController;
+import javafx.application.Platform;
+import javafx.event.Event;
+import javafx.event.EventHandler;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.KeyCodeCombination;
+import javafx.scene.input.KeyCombination;
+import javafx.scene.input.KeyEvent;
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+
+import java.io.IOException;
+
+public class UiLogger implements PacketLogger {
+ private Stage stage;
+ private LoggerController controller;
+
+ @Override
+ public void start() {
+ FXMLLoader loader = new FXMLLoader(getClass().getResource("/gearth/ui/Logger.fxml"));
+
+ try {
+ Parent root = loader.load();
+ controller = loader.getController();
+ stage = new Stage();
+ stage.setTitle("G-Earth | Packet Logger");
+ stage.initModality(Modality.NONE);
+
+ Scene scene = new Scene(root);
+ scene.getStylesheets().add("/gearth/ui/bootstrap3.css");
+ scene.getStylesheets().add("/gearth/ui/logger.css");
+
+ scene.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler() {
+ final KeyCombination keyCombIncoming = new KeyCodeCombination(KeyCode.I,
+ KeyCombination.CONTROL_DOWN);
+ final KeyCombination keyCombOutgoing = new KeyCodeCombination(KeyCode.O,
+ KeyCombination.CONTROL_DOWN);
+
+ public void handle(KeyEvent ke) {
+ if (keyCombIncoming.match(ke)) {
+ controller.toggleViewIncoming();
+ ke.consume();
+ } else if (keyCombOutgoing.match(ke)) {
+ controller.toggleViewOutgoing();
+ ke.consume();
+ }
+ }
+ });
+
+ stage.setScene(scene);
+
+ // don't let the user close this window on their own
+ stage.setOnCloseRequest(Event::consume);
+
+ stage.show();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void stop() {
+ stage.close();
+ }
+
+ @Override
+ public void appendSplitLine() {
+ // don't use this, we can't discern incoming/outgoing
+ //Platform.runLater(() -> controller.appendSplitLine());
+ }
+
+ @Override
+ public void appendMessage(HPacket packet, int types) {
+ Platform.runLater(() -> controller.appendMessage(packet, types));
+ }
+
+ @Override
+ public void appendStructure(HPacket packet) {
+
+ }
+}