diff --git a/G-Earth/src/main/java/gearth/misc/BindingsUtil.java b/G-Earth/src/main/java/gearth/misc/BindingsUtil.java index e87f893..348e1fb 100644 --- a/G-Earth/src/main/java/gearth/misc/BindingsUtil.java +++ b/G-Earth/src/main/java/gearth/misc/BindingsUtil.java @@ -1,12 +1,17 @@ package gearth.misc; +import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.ObjectBinding; import javafx.beans.property.IntegerProperty; import javafx.beans.property.Property; import javafx.beans.property.StringProperty; +import javafx.beans.value.ObservableValue; import javafx.collections.ObservableList; import javafx.util.StringConverter; +import java.util.function.Function; + /** * Provides utility methods for bindings. * @@ -14,6 +19,27 @@ import javafx.util.StringConverter; */ public final class BindingsUtil { + /** + * Creates a binding that is true if the function returns true for the applied string. + */ + public static BooleanBinding stringMatches(ObservableValue stringValue, Function function) { + return Bindings.createBooleanBinding(() -> function.apply(stringValue.getValue()), stringValue); + } + + /** + * Creates a binding that is true if the string is an integer. + */ + public static BooleanBinding isInteger(ObservableValue stringValue) { + return stringMatches(stringValue, StringUtils::isInteger); + } + + /** + * Creates a binding that is true if the string is an UShort. + */ + public static BooleanBinding isUShort(ObservableValue stringValue) { + return stringMatches(stringValue, StringUtils::isUShort); + } + /** * Ensures the list always contains the value of the binding. */ @@ -25,6 +51,20 @@ public final class BindingsUtil { list.add(binding.get()); } + /** + * Sets the value of a property and binds it to another observable value. + */ + public static void setAndBind(Property a, ObservableValue b, boolean unbindPrevious) { + if (unbindPrevious) + a.unbind(); + a.setValue(b.getValue()); + a.bind(b); + } + + public static void setAndBind(Property a, ObservableValue b) { + setAndBind(a, b, false); + } + /** * Sets the value of a property and binds it bidirectionally to another property. */ diff --git a/G-Earth/src/main/java/gearth/misc/HyperLinkUtil.java b/G-Earth/src/main/java/gearth/misc/HyperLinkUtil.java new file mode 100644 index 0000000..8b2d54f --- /dev/null +++ b/G-Earth/src/main/java/gearth/misc/HyperLinkUtil.java @@ -0,0 +1,17 @@ +package gearth.misc; + +import gearth.GEarth; +import javafx.event.ActionEvent; +import javafx.scene.control.Hyperlink; + +public final class HyperLinkUtil { + + public static void showDocumentOnClick(Hyperlink link) { + link.setOnAction((ActionEvent event) -> { + final Hyperlink hyperlink = (Hyperlink) event.getTarget(); + final String url = hyperlink.getTooltip().getText(); + GEarth.main.getHostServices().showDocument(url); + event.consume(); + }); + } +} diff --git a/G-Earth/src/main/java/gearth/misc/StringUtils.java b/G-Earth/src/main/java/gearth/misc/StringUtils.java new file mode 100644 index 0000000..54200b8 --- /dev/null +++ b/G-Earth/src/main/java/gearth/misc/StringUtils.java @@ -0,0 +1,29 @@ +package gearth.misc; + +public final class StringUtils { + + public static boolean isInteger(String string) { + try { + Integer.parseInt(string); + return true; + } + catch (NumberFormatException e){ + return false; + } + } + + public static boolean isUShort(String string) { + try { + int res = Integer.parseInt(string); + return res >= 0 && res < (256 * 256); + } catch (NumberFormatException e) { + return false; + } + } + + public static String cleanTextContent(String text) + { + text = text.replaceAll("\\p{Cntrl}&&[^\n\t]", ""); + return text.trim(); + } +} diff --git a/G-Earth/src/main/java/gearth/services/scheduler/Interval.java b/G-Earth/src/main/java/gearth/services/scheduler/Interval.java index 2c15c15..d706587 100644 --- a/G-Earth/src/main/java/gearth/services/scheduler/Interval.java +++ b/G-Earth/src/main/java/gearth/services/scheduler/Interval.java @@ -1,6 +1,6 @@ package gearth.services.scheduler; -import gearth.ui.subforms.scheduler.SchedulerController; +import gearth.misc.StringUtils; /** * Created by Jonas on 11/04/18. @@ -23,7 +23,7 @@ public class Interval { offset = -1; return; } - if (!SchedulerController.stringIsNumber(split[0]) || (split.length == 2 && !SchedulerController.stringIsNumber(split[1]))) { + if (!StringUtils.isInteger(split[0]) || (split.length == 2 && !StringUtils.isInteger(split[1]))) { delay = -1; offset = -1; return; diff --git a/G-Earth/src/main/java/gearth/ui/buttons/BoxButton.java b/G-Earth/src/main/java/gearth/ui/buttons/BoxButton.java index 0afd90c..0c7bb07 100644 --- a/G-Earth/src/main/java/gearth/ui/buttons/BoxButton.java +++ b/G-Earth/src/main/java/gearth/ui/buttons/BoxButton.java @@ -1,55 +1,50 @@ package gearth.ui.buttons; -import javafx.event.EventHandler; import javafx.scene.Cursor; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import javafx.scene.input.MouseEvent; import javafx.scene.layout.StackPane; -import java.io.File; +import java.util.Objects; public class BoxButton extends StackPane { - private ImageView imageView; - private Image image; - private Image imageOnHover; + private final ImageView imageView; + private final Image image; + private final Image imageOnHover; private boolean isVisible; - //paths zijn relatief aan deze classpath + /** + * Creates a new box button. + * + * @param imageName name of the image file in src/main/java/gearth/ui/buttons/files/ + * @param imageOnHoverName name of the image file in src/main/java/gearth/ui/buttons/files/ + */ public BoxButton(String imageName, String imageOnHoverName) { - this.image = new Image(getClass().getResourceAsStream("files/" + imageName)); - this.imageOnHover = new Image(getClass().getResourceAsStream("files/" + imageOnHoverName)); + this.image = getImageResource(imageName); + this.imageOnHover = getImageResource(imageOnHoverName); this.imageView = new ImageView(); - setCursor(Cursor.DEFAULT); getChildren().add(imageView); - setOnMouseEntered(onMouseHover); - setOnMouseExited(onMouseHoverDone); + setOnMouseEntered(t -> { + if (isVisible) imageView.setImage(imageOnHover); + }); + setOnMouseExited(t -> { + if (isVisible) imageView.setImage(image); + }); } - public void show() { + private Image getImageResource(String imageName) { + return new Image(Objects.requireNonNull(getClass().getResourceAsStream("files/" + imageName))); + } + + public void show() { imageView.setImage(image); isVisible = true; } - public void dispose() { + public void dispose() { imageView.setImage(null); isVisible = false; } - - private EventHandler onMouseHover = - t -> { - if (isVisible) { - imageView.setImage(imageOnHover); - } - }; - - private EventHandler onMouseHoverDone = - t -> { - if (isVisible) { - imageView.setImage(image); - } - }; - } diff --git a/G-Earth/src/main/java/gearth/ui/buttons/ExitButton.java b/G-Earth/src/main/java/gearth/ui/buttons/ExitButton.java index fe5d28b..d391551 100644 --- a/G-Earth/src/main/java/gearth/ui/buttons/ExitButton.java +++ b/G-Earth/src/main/java/gearth/ui/buttons/ExitButton.java @@ -4,6 +4,7 @@ package gearth.ui.buttons; * Created by Jonas on 26/09/18. */ public class ExitButton extends BoxButton { + public ExitButton() { super("ButtonExit.png", "ButtonExitHover.png"); } diff --git a/G-Earth/src/main/java/gearth/ui/buttons/FireButton.java b/G-Earth/src/main/java/gearth/ui/buttons/FireButton.java index 0018d95..17e02c4 100644 --- a/G-Earth/src/main/java/gearth/ui/buttons/FireButton.java +++ b/G-Earth/src/main/java/gearth/ui/buttons/FireButton.java @@ -4,6 +4,7 @@ package gearth.ui.buttons; * Created by Jonas on 26/09/18. */ public class FireButton extends BoxButton { + public FireButton() { super("ButtonFire.png", "ButtonFireHover.png"); } diff --git a/G-Earth/src/main/java/gearth/ui/buttons/PauseResumeButton.java b/G-Earth/src/main/java/gearth/ui/buttons/PauseResumeButton.java index 3df2cff..a4b476d 100644 --- a/G-Earth/src/main/java/gearth/ui/buttons/PauseResumeButton.java +++ b/G-Earth/src/main/java/gearth/ui/buttons/PauseResumeButton.java @@ -10,45 +10,55 @@ import javafx.scene.layout.StackPane; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * Created by Jonas on 11/04/18. */ public class PauseResumeButton extends StackPane{ - private boolean isPaused[] = {false}; + private final boolean[] isPaused = {false}; + private final ImageView imageView; + private final Image imagePause; + private final Image imagePauseOnHover; - private ImageView imageView; - private Image imagePause; - private Image imagePauseOnHover; - - private Image imageResume; - private Image imageResumeOnHover; + private final Image imageResume; + private final Image imageResumeOnHover; private volatile boolean isHovering = false; - private List clickListeners = new ArrayList<>(); + private final List clickListeners = new ArrayList<>(); public PauseResumeButton(boolean isPaused) { this.isPaused[0] = isPaused; - this.imagePause = new Image(getClass().getResourceAsStream("files/ButtonPause.png")); - this.imagePauseOnHover = new Image(getClass().getResourceAsStream("files/ButtonPauseHover.png")); - this.imageResume = new Image(getClass().getResourceAsStream("files/ButtonResume.png")); - this.imageResumeOnHover = new Image(getClass().getResourceAsStream("files/ButtonResumeHover.png")); + this.imagePause = getImageResource("files/ButtonPause.png"); + this.imagePauseOnHover = getImageResource("files/ButtonPauseHover.png"); + this.imageResume = getImageResource("files/ButtonResume.png"); + this.imageResumeOnHover = getImageResource("files/ButtonResumeHover.png"); this.imageView = new ImageView(); setCursor(Cursor.DEFAULT); getChildren().add(imageView); - setOnMouseEntered(onMouseHover); - setOnMouseExited(onMouseHoverDone); + setOnMouseEntered( t -> { + imageView.setImage(isPaused() ? imageResumeOnHover : imagePauseOnHover); + isHovering = true; + }); + setOnMouseExited(t -> { + imageView.setImage(isPaused() ? imageResume : imagePause); + isHovering = false; + }); imageView.setImage(isPaused() ? imageResume : imagePause); setEventHandler(MouseEvent.MOUSE_CLICKED, event -> click()); } + private Image getImageResource(String name) { + return new Image(Objects.requireNonNull(getClass().getResourceAsStream(name))); + } + public boolean isPaused() { return isPaused[0]; } @@ -57,24 +67,8 @@ public class PauseResumeButton extends StackPane{ clickListeners.add(listener); } - - private EventHandler onMouseHover = - t -> { - imageView.setImage(isPaused() ? imageResumeOnHover : imagePauseOnHover); - isHovering = true; - }; - - private EventHandler onMouseHoverDone = - t -> { - imageView.setImage(isPaused() ? imageResume : imagePause); - isHovering = false; - }; - - public void setPaused(boolean paused) { isPaused[0] = paused; - - imageView.setImage(isPaused() ? (isHovering ? imageResumeOnHover : imageResume) : (isHovering ? imagePauseOnHover : imagePause) @@ -86,22 +80,4 @@ public class PauseResumeButton extends StackPane{ clickListeners.get(i).invalidated(null); } } - -// private ImageView imageView; -// private Image image; -// private Image imageOnHover; -// private boolean isVisible; -// -// //paths zijn relatief aan deze classpath -// public BoxButton(String imagePath, String imageOnHoverPath) { -// this.image = new Image(getClass().getResourceAsStream(imagePath)); -// this.imageOnHover = new Image(getClass().getResourceAsStream(imageOnHoverPath)); -// this.imageView = new ImageView(); -// -// setCursor(Cursor.DEFAULT); -// getChildren().add(imageView); -// setOnMouseEntered(onMouseHover); -// setOnMouseExited(onMouseHoverDone); -// } - } diff --git a/G-Earth/src/main/java/gearth/ui/buttons/ReloadButton.java b/G-Earth/src/main/java/gearth/ui/buttons/ReloadButton.java index bad2e99..96b30b5 100644 --- a/G-Earth/src/main/java/gearth/ui/buttons/ReloadButton.java +++ b/G-Earth/src/main/java/gearth/ui/buttons/ReloadButton.java @@ -4,6 +4,8 @@ package gearth.ui.buttons; * Created by Jonas on 26/09/18. */ public class ReloadButton extends BoxButton { + public ReloadButton() { - super("ButtonReload.png", "ButtonReloadHover.png"); } + super("ButtonReload.png", "ButtonReloadHover.png"); + } } diff --git a/G-Earth/src/main/java/gearth/ui/subforms/connection/ConnectionController.java b/G-Earth/src/main/java/gearth/ui/subforms/connection/ConnectionController.java index fe6e093..a61ae8d 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/connection/ConnectionController.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/connection/ConnectionController.java @@ -8,65 +8,260 @@ import gearth.protocol.connection.HState; import gearth.protocol.connection.proxy.ProxyProviderFactory; import gearth.services.Constants; import gearth.ui.GEarthProperties; +import gearth.ui.SubForm; import gearth.ui.translations.TranslatableString; import javafx.application.Platform; -import javafx.event.ActionEvent; +import javafx.fxml.FXML; import javafx.scene.control.*; -import gearth.ui.SubForm; import javafx.scene.layout.GridPane; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; public class ConnectionController extends SubForm { - public ComboBox inpPort; - public ComboBox inpHost; - public Button btnConnect; - public Label lblInpPort, lblInpHost, lblPort, lblHost, lblHotelVersion, lblClient, lblStateHead, lblState; - public TextField outHost; - public TextField outPort; - public CheckBox cbx_autodetect; - public TextField txtfield_hotelversion; + public ComboBox portOptionsBox; + public ComboBox hostOptionsBox; - private final Object lock = new Object(); - private volatile int fullyInitialized = 0; + public Button connectButton; + public Label + portOptionsLabel, + hostOptionsLabel, + connectedPortLabel, + connectedHostLabel, + connectedHotelVersionLabel, + selectedClientLabel, + connectionStateHeaderLabel, + notConnectedStateLabel; + public TextField connectedHostField; + public TextField connectedPortField; + public CheckBox autoDetectBox; + public TextField connectedHotelVersionField; - public ToggleGroup tgl_clientMode; - public RadioButton rd_unity; - public RadioButton rd_flash; - public RadioButton rd_nitro; - public GridPane grd_clientSelection; + public GridPane clientTypeSelectionGrid; + public ToggleGroup clientTypeOptions; + public RadioButton unityOption; + public RadioButton flashOption; + public RadioButton nitroOption; - private volatile int initcount = 0; + private final AtomicInteger initState = new AtomicInteger(0); + private final AtomicInteger initCount = new AtomicInteger(0); private TranslatableString connect, state; public void initialize() { - Constants.UNITY_PACKETS = rd_unity.isSelected(); - tgl_clientMode.selectedToggleProperty().addListener(observable -> { + Constants.UNITY_PACKETS = unityOption.isSelected(); + clientTypeOptions.selectedToggleProperty().addListener(observable -> { changeClientMode(); - Constants.UNITY_PACKETS = rd_unity.isSelected(); + Constants.UNITY_PACKETS = unityOption.isSelected(); }); GEarthProperties.clientTypeProperty .addListener((observable, oldValue, newValue) -> selectClientType(newValue)); selectClientType(GEarthProperties.clientTypeProperty.getValue()); - cbx_autodetect.selectedProperty().addListener(observable -> updateInputUI()); - inpPort.getEditor().textProperty().addListener(observable -> updateInputUI()); + autoDetectBox.selectedProperty().addListener(observable -> updateInputUI()); + portOptionsBox.getEditor().textProperty().addListener(observable -> updateInputUI()); - BindingsUtil.setAndBindBiDirectional(cbx_autodetect.selectedProperty(), GEarthProperties.autoDetectProperty); - BindingsUtil.setAndBindBiDirectional(outHost.textProperty(), GEarthProperties.hostProperty); - BindingsUtil.setAndBindBiDirectional(outPort.textProperty(), GEarthProperties.portProperty); + BindingsUtil.setAndBindBiDirectional(autoDetectBox.selectedProperty(), GEarthProperties.autoDetectProperty); + BindingsUtil.setAndBindBiDirectional(connectedHostField.textProperty(), GEarthProperties.hostProperty); + BindingsUtil.setAndBindBiDirectional(connectedPortField.textProperty(), GEarthProperties.portProperty); - List knownHosts = ProxyProviderFactory.autoDetectHosts; - Set hosts = new HashSet<>(); - Set ports = new HashSet<>(); + initHostSelection(); + + if (initState.incrementAndGet() == 2) + Platform.runLater(this::updateInputUI); + + tryMaybeConnectOnInit(); + initLanguageBinding(); + } + + + @Override + public void onParentSet() { + + if (initState.incrementAndGet() == 2) + Platform.runLater(this::updateInputUI); + + getHConnection().stateProperty().addListener((observable, oldValue, newValue) -> Platform.runLater(() -> { + updateInputUI(); + if (newValue == HState.NOT_CONNECTED) { + state.setKey(0, "tab.connection.state.notconnected"); + connect.setKey(0, "tab.connection.button.connect"); + connectedHostField.setText(""); + connectedPortField.setText(""); + } else if (oldValue == HState.NOT_CONNECTED) + connect.setKey(0, "tab.connection.button.abort"); + if (newValue == HState.CONNECTED) + state.setKey(0, "tab.connection.state.connected"); + if (newValue == HState.WAITING_FOR_CLIENT) + state.setKey(0, "tab.connection.state.waiting"); + if (newValue == HState.CONNECTED && useFlash()) { + final String host = getHConnection().getDomain(); + final int port = getHConnection().getServerPort(); + connectedHostField.setText(host); + connectedPortField.setText(Integer.toString(port)); + GEarthProperties.hostProperty.set(host); + GEarthProperties.portProperty.set(port); + } + })); + + Platform.runLater(this::updateInputUI); + + tryMaybeConnectOnInit(); + } + + @Override + protected void onExit() { + GEarthProperties.clientTypeProperty.set( + flashOption.isSelected() ? HClient.FLASH + : unityOption.isSelected() ? HClient.UNITY + : HClient.NITRO); + getHConnection().abort(); + } + + @FXML + public void onClickConnectButton() { + if (getHConnection().getState() == HState.NOT_CONNECTED) { + + connectButton.setDisable(true); + new Thread(() -> { + if (isClientMode(HClient.FLASH)) { + if (autoDetectBox.isSelected()) { + getHConnection().start(); + } else { + getHConnection().start(hostOptionsBox.getEditor().getText(), Integer.parseInt(portOptionsBox.getEditor().getText())); + } + } else if (isClientMode(HClient.UNITY)) { + getHConnection().startUnity(); + } else if (isClientMode(HClient.NITRO)) { + getHConnection().startNitro(); + } + if (GEarthProperties.isDebugModeEnabled()) + System.out.println("connecting"); + }).start(); + } else { + getHConnection().abort(); + } + } + + private void selectClientType(HClient newValue) { + switch (newValue) { + case FLASH: + flashOption.setSelected(true); + break; + case UNITY: + unityOption.setSelected(true); + break; + case NITRO: + nitroOption.setSelected(true); + break; + } + } + + private void updateInputUI() { + if (parentController == null) return; + + final HConnection hConnection = getHConnection(); + final HState hConnectionState = hConnection.getState(); + + clientTypeSelectionGrid.setDisable(hConnectionState != HState.NOT_CONNECTED); + connectedHotelVersionField.setText(hConnection.getHotelVersion()); + + connectButton.setDisable(hConnectionState == HState.PREPARING || hConnectionState == HState.ABORTING); + + if (!autoDetectBox.isSelected() && !connectButton.isDisable() && useFlash()) { + try { + int i = Integer.parseInt(portOptionsBox.getEditor().getText()); + connectButton.setDisable(i < 0 || i >= 256 * 256); + } catch (Exception e) { + connectButton.setDisable(true); + } + } + + hostOptionsBox.setDisable(hConnectionState != HState.NOT_CONNECTED || autoDetectBox.isSelected()); + portOptionsBox.setDisable(hConnectionState != HState.NOT_CONNECTED || autoDetectBox.isSelected()); + + autoDetectBox.setDisable(!useFlash()); + connectedHostField.setDisable(!useFlash()); + connectedPortField.setDisable(!useFlash()); + + hostOptionsBox.setDisable(!useFlash() || hConnectionState != HState.NOT_CONNECTED || autoDetectBox.isSelected()); + portOptionsBox.setDisable(!useFlash() || hConnectionState != HState.NOT_CONNECTED || autoDetectBox.isSelected()); + } + + private void tryMaybeConnectOnInit() { + if (initCount.incrementAndGet() == 2) + maybeConnectOnInit(); + } + + private void maybeConnectOnInit() { + String connectMode = GEarth.getArgument("--connect", "-c"); + if (connectMode != null) { + switch (connectMode) { + case "flash": + Platform.runLater(() -> flashOption.setSelected(true)); + String host = GEarth.getArgument("--host"); + String port = GEarth.getArgument("--port"); + if (host != null && port != null) { + Platform.runLater(() -> { + if (!hostOptionsBox.getItems().contains(host)) + hostOptionsBox.getItems().add(host); + hostOptionsBox.getSelectionModel().select(host); + if (!portOptionsBox.getItems().contains(port)) + portOptionsBox.getItems().add(port); + portOptionsBox.getSelectionModel().select(port); + autoDetectBox.setSelected(false); + }); + getHConnection().start(host, Integer.parseInt(port)); + } else { + Platform.runLater(() -> autoDetectBox.setSelected(true)); + getHConnection().start(); + } + break; + case "unity": + Platform.runLater(() -> unityOption.setSelected(true)); + getHConnection().startUnity(); + break; + case "nitro": + Platform.runLater(() -> nitroOption.setSelected(true)); + getHConnection().startNitro(); + break; + } + Platform.runLater(this::updateInputUI); + } + } + + public void changeClientMode() { + updateInputUI(); + } + + private boolean useFlash() { + return flashOption.isSelected(); + } + + private boolean isClientMode(HClient client) { + switch (client) { + case FLASH: + return flashOption.isSelected(); + case UNITY: + return unityOption.isSelected(); + case NITRO: + return nitroOption.isSelected(); + } + + return false; + } + + private void initHostSelection() { + final List knownHosts = ProxyProviderFactory.autoDetectHosts; + final Set hosts = new HashSet<>(); + final Set ports = new HashSet<>(); for (String h : knownHosts) { String[] split = h.split(":"); @@ -92,228 +287,30 @@ public class ConnectionController extends SubForm { } - inpPort.getItems().addAll(portsSorted); - inpHost.getItems().addAll(hostsSorted); + portOptionsBox.getItems().addAll(portsSorted); + hostOptionsBox.getItems().addAll(hostsSorted); - inpPort.getSelectionModel().select(portSelectIndex); - inpHost.getSelectionModel().select(hostSelectIndex); - - synchronized (lock) { - fullyInitialized++; - if (fullyInitialized == 2) { - Platform.runLater(this::updateInputUI); - } - } - - synchronized (this) { - tryMaybeConnectOnInit(); - } - - initLanguageBinding(); - } - - private void selectClientType(HClient newValue) { - switch (newValue) { - case FLASH: - rd_flash.setSelected(true); - break; - case UNITY: - rd_unity.setSelected(true); - break; - case NITRO: - rd_nitro.setSelected(true); - break; - } - } - - - private void updateInputUI() { - if (parentController == null) return; - - final HConnection hConnection = getHConnection(); - final HState hConnectionState = hConnection.getState(); - - grd_clientSelection.setDisable(hConnectionState != HState.NOT_CONNECTED); - txtfield_hotelversion.setText(hConnection.getHotelVersion()); - - btnConnect.setDisable(hConnectionState == HState.PREPARING || hConnectionState == HState.ABORTING); - - - if (!cbx_autodetect.isSelected() && !btnConnect.isDisable() && useFlash()) { - try { - int i = Integer.parseInt(inpPort.getEditor().getText()); - btnConnect.setDisable(i < 0 || i >= 256 * 256); - } - catch (Exception e) { - btnConnect.setDisable(true); - } - } - - inpHost.setDisable(hConnectionState != HState.NOT_CONNECTED || cbx_autodetect.isSelected()); - inpPort.setDisable(hConnectionState != HState.NOT_CONNECTED || cbx_autodetect.isSelected()); - - cbx_autodetect.setDisable(!useFlash()); - outHost.setDisable(!useFlash()); - outPort.setDisable(!useFlash()); - - inpHost.setDisable(!useFlash() || hConnectionState != HState.NOT_CONNECTED || cbx_autodetect.isSelected()); - inpPort.setDisable(!useFlash() || hConnectionState != HState.NOT_CONNECTED || cbx_autodetect.isSelected()); - } - - public void onParentSet(){ - synchronized (lock) { - fullyInitialized++; - if (fullyInitialized == 2) { - Platform.runLater(this::updateInputUI); - } - } - - getHConnection().stateProperty().addListener((observable, oldValue, newValue) -> Platform.runLater(() -> { - updateInputUI(); - if (newValue == HState.NOT_CONNECTED) { - state.setKey(0, "tab.connection.state.notconnected"); - connect.setKey(0, "tab.connection.button.connect"); - outHost.setText(""); - outPort.setText(""); - } - else if (oldValue == HState.NOT_CONNECTED) - connect.setKey(0, "tab.connection.button.abort"); - if (newValue == HState.CONNECTED) - state.setKey(0, "tab.connection.state.connected"); - if (newValue == HState.WAITING_FOR_CLIENT) - state.setKey(0, "tab.connection.state.waiting"); - if (newValue == HState.CONNECTED && useFlash()) { - final String host = getHConnection().getDomain(); - final int port = getHConnection().getServerPort(); - outHost.setText(host); - outPort.setText(Integer.toString(port)); - GEarthProperties.hostProperty.set(host); - GEarthProperties.portProperty.set(port); - } - })); - - Platform.runLater(this::updateInputUI); - - synchronized (this) { - tryMaybeConnectOnInit(); - } - } - - - private void tryMaybeConnectOnInit() { - if (++initcount == 2) { - maybeConnectOnInit(); - } - } - - private void maybeConnectOnInit() { - String connectMode = GEarth.getArgument("--connect", "-c"); - if (connectMode != null) { - if (connectMode.equals("flash")) { - Platform.runLater(() -> rd_flash.setSelected(true)); - String host = GEarth.getArgument("--host"); - String port = GEarth.getArgument("--port"); - if (host != null && port != null) { - Platform.runLater(() -> { - if (!inpHost.getItems().contains(host)) - inpHost.getItems().add(host); - inpHost.getSelectionModel().select(host); - if (!inpPort.getItems().contains(port)) - inpPort.getItems().add(port); - inpPort.getSelectionModel().select(port); - cbx_autodetect.setSelected(false); - }); - getHConnection().start(host, Integer.parseInt(port)); - } - else { - Platform.runLater(() -> cbx_autodetect.setSelected(true)); - getHConnection().start(); - } - } - else if (connectMode.equals("unity")) { - Platform.runLater(() -> rd_unity.setSelected(true)); - getHConnection().startUnity(); - } - else if (connectMode.equals("nitro")) { - Platform.runLater(() -> rd_nitro.setSelected(true)); - getHConnection().startNitro(); - } - Platform.runLater(this::updateInputUI); - } - } - - public void btnConnect_clicked(ActionEvent actionEvent) { - if (getHConnection().getState() == HState.NOT_CONNECTED) { - - btnConnect.setDisable(true); - new Thread(() -> { - if (isClientMode(HClient.FLASH)) { - if (cbx_autodetect.isSelected()) { - getHConnection().start(); - } else { - getHConnection().start(inpHost.getEditor().getText(), Integer.parseInt(inpPort.getEditor().getText())); - } - } else if (isClientMode(HClient.UNITY)) { - getHConnection().startUnity(); - } else if (isClientMode(HClient.NITRO)) { - getHConnection().startNitro(); - } - if (GEarthProperties.isDebugModeEnabled()) - System.out.println("connecting"); - }).start(); - } - else { - getHConnection().abort(); - } - } - - @Override - protected void onExit() { - GEarthProperties.clientTypeProperty.set( - rd_flash.isSelected() ? HClient.FLASH - : rd_unity.isSelected() ? HClient.UNITY - : HClient.NITRO); - getHConnection().abort(); - } - - public void changeClientMode() { - updateInputUI(); - } - - private boolean useFlash() { - return rd_flash.isSelected(); - } - - private boolean isClientMode(HClient client) { - switch (client) { - case FLASH: - return rd_flash.isSelected(); - case UNITY: - return rd_unity.isSelected(); - case NITRO: - return rd_nitro.isSelected(); - } - - return false; + portOptionsBox.getSelectionModel().select(portSelectIndex); + hostOptionsBox.getSelectionModel().select(hostSelectIndex); } private void initLanguageBinding() { TranslatableString port = new TranslatableString("%s", "tab.connection.port"); TranslatableString host = new TranslatableString("%s", "tab.connection.host"); - lblInpPort.textProperty().bind(port); - lblInpHost.textProperty().bind(host); - lblPort.textProperty().bind(port); - lblHost.textProperty().bind(host); - cbx_autodetect.textProperty().bind(new TranslatableString("%s", "tab.connection.autodetect")); + portOptionsLabel.textProperty().bind(port); + hostOptionsLabel.textProperty().bind(host); + connectedPortLabel.textProperty().bind(port); + connectedHostLabel.textProperty().bind(host); + autoDetectBox.textProperty().bind(new TranslatableString("%s", "tab.connection.autodetect")); connect = new TranslatableString("%s", "tab.connection.button.connect"); - btnConnect.textProperty().bind(connect); - lblHotelVersion.textProperty().bind(new TranslatableString("%s", "tab.connection.version")); - lblClient.textProperty().bind(new TranslatableString("%s", "tab.connection.client")); - rd_unity.textProperty().bind(new TranslatableString("%s", "tab.connection.client.unity")); - rd_flash.textProperty().bind(new TranslatableString("%s", "tab.connection.client.flash")); - rd_nitro.textProperty().bind(new TranslatableString("%s", "tab.connection.client.nitro")); - lblStateHead.textProperty().bind(new TranslatableString("%s", "tab.connection.state")); + connectButton.textProperty().bind(connect); + connectedHotelVersionLabel.textProperty().bind(new TranslatableString("%s", "tab.connection.version")); + selectedClientLabel.textProperty().bind(new TranslatableString("%s", "tab.connection.client")); + unityOption.textProperty().bind(new TranslatableString("%s", "tab.connection.client.unity")); + flashOption.textProperty().bind(new TranslatableString("%s", "tab.connection.client.flash")); + nitroOption.textProperty().bind(new TranslatableString("%s", "tab.connection.client.nitro")); + connectionStateHeaderLabel.textProperty().bind(new TranslatableString("%s", "tab.connection.state")); state = new TranslatableString("%s", "tab.connection.state.notconnected"); - lblState.textProperty().bind(state); + notConnectedStateLabel.textProperty().bind(state); } } diff --git a/G-Earth/src/main/java/gearth/ui/subforms/extensions/ExtensionItemContainerProducer.java b/G-Earth/src/main/java/gearth/ui/subforms/extensions/ExtensionItemContainerProducer.java index d183e6d..baad4f0 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/extensions/ExtensionItemContainerProducer.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/extensions/ExtensionItemContainerProducer.java @@ -10,8 +10,8 @@ import javafx.scene.layout.VBox; */ public class ExtensionItemContainerProducer { - private VBox parent; - private ScrollPane scrollPane; + private final VBox parent; + private final ScrollPane scrollPane; private final Object lock = new Object(); private int port = -1; diff --git a/G-Earth/src/main/java/gearth/ui/subforms/extensions/ExtensionsController.java b/G-Earth/src/main/java/gearth/ui/subforms/extensions/ExtensionsController.java index a3774fc..417c937 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/extensions/ExtensionsController.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/extensions/ExtensionsController.java @@ -2,8 +2,8 @@ package gearth.ui.subforms.extensions; import gearth.services.extension_handler.ExtensionHandler; import gearth.services.extension_handler.extensions.ExtensionListener; -import gearth.services.extension_handler.extensions.implementations.network.NetworkExtensionServer; import gearth.services.extension_handler.extensions.implementations.network.NetworkExtensionAuthenticator; +import gearth.services.extension_handler.extensions.implementations.network.NetworkExtensionServer; import gearth.services.extension_handler.extensions.implementations.network.executer.ExecutionInfo; import gearth.services.extension_handler.extensions.implementations.network.executer.ExtensionRunner; import gearth.services.extension_handler.extensions.implementations.network.executer.ExtensionRunnerFactory; @@ -14,52 +14,68 @@ import gearth.ui.subforms.extensions.logger.ExtensionLogger; import gearth.ui.translations.LanguageBundle; import gearth.ui.translations.TranslatableString; import javafx.application.Platform; -import javafx.event.ActionEvent; -import javafx.scene.control.*; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; import javafx.scene.layout.GridPane; import javafx.scene.layout.VBox; import javafx.stage.FileChooser; import java.io.File; +import java.net.URL; +import java.util.ResourceBundle; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; /** * Created by Jonas on 06/04/18. */ +public class ExtensionsController extends SubForm implements Initializable { -public class ExtensionsController extends SubForm { + public Button installButton; + public TextField portField; + public GridPane headerGridPane; + public ScrollPane contentScrollPane; + public VBox contentBox; - public Button btn_install; - public TextField ext_port; - public VBox extensioncontainer; - public GridPane header_ext; - public ScrollPane scroller; - public Button btn_viewExtensionConsole; - public Button btn_gpython; + public Button viewLogsButton; + public Button openGPythonShellButton; + + public Label + tableTitleLabel, + tableDescriptionLabel, + tableAuthorLabel, + tableVersionLabel, + tableEditLabel, + portLabel; private ExtensionRunner extensionRunner = null; private ExtensionHandler extensionHandler; private NetworkExtensionServer networkExtensionsProducer; // needed for port private ExtensionLogger extensionLogger = null; - public Label lbl_tableTitle, lbl_tableDesc, lbl_tableAuthor, lbl_tableVersion, lbl_tableEdit, lbl_port; + private final AtomicInteger gpytonShellCounter = new AtomicInteger(1); + private final AtomicBoolean pythonShellLaunching = new AtomicBoolean(false); - - public void initialize() { - scroller.widthProperty().addListener(observable -> header_ext.setPrefWidth(scroller.getWidth())); + @Override + public void initialize(URL location, ResourceBundle resources) { extensionLogger = new ExtensionLogger(); - btn_install.disableProperty().bind(GEarthProperties.enableDeveloperModeProperty.not()); + headerGridPane.prefWidthProperty().bind(contentScrollPane.widthProperty()); + installButton.disableProperty().bind(GEarthProperties.enableDeveloperModeProperty.not()); initLanguageBinding(); } + @Override protected void onParentSet() { - ExtensionItemContainerProducer producer = new ExtensionItemContainerProducer(extensioncontainer, scroller); + ExtensionItemContainerProducer producer = new ExtensionItemContainerProducer(contentBox, contentScrollPane); extensionHandler = new ExtensionHandler(getHConnection()); - extensionHandler.getObservable().addListener((e -> { - Platform.runLater(() -> producer.extensionConnected(e)); - })); + extensionHandler.getObservable().addListener((e -> Platform.runLater(() -> producer.extensionConnected(e)))); //noinspection OptionalGetWithoutIsPresent networkExtensionsProducer @@ -67,42 +83,20 @@ public class ExtensionsController extends SubForm { .filter(producer1 -> producer1 instanceof NetworkExtensionServer) .findFirst().get(); - producer.setPort(networkExtensionsProducer.getPort()); - ext_port.setText(networkExtensionsProducer.getPort()+""); -// System.out.println("Extension server registered on port: " + extensionsRegistrer.getPort()); + portField.setText(Integer.toString(networkExtensionsProducer.getPort())); extensionRunner = ExtensionRunnerFactory.get(); extensionRunner.runAllExtensions(networkExtensionsProducer.getPort()); - - extensionHandler.getObservable().addListener(e -> e.getExtensionObservable().addListener(new ExtensionListener() { - @Override - public void log(String text) { - extensionLogger.log(text); - } - })); - } - - - public void installBtnClicked(ActionEvent actionEvent) { - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle(LanguageBundle.get("tab.extensions.button.install.windowtitle")); - fileChooser.getExtensionFilters().addAll( - new FileChooser.ExtensionFilter(LanguageBundle.get("tab.extensions.button.install.filetype"), ExecutionInfo.ALLOWED_EXTENSION_TYPES)); - File selectedFile = fileChooser.showOpenDialog(parentController.getStage()); - if (selectedFile != null) { - extensionRunner.installAndRunExtension(selectedFile.getPath(), networkExtensionsProducer.getPort()); - } - } - - public void extConsoleBtnClicked(ActionEvent actionEvent) { - if (!extensionLogger.isVisible()) { - extensionLogger.show(); - } - else { - extensionLogger.hide(); - } + extensionHandler.getObservable().addListener(e -> + e.getExtensionObservable().addListener(new ExtensionListener() { + @Override + public void log(String text) { + extensionLogger.log(text); + } + }) + ); } @Override @@ -110,47 +104,63 @@ public class ExtensionsController extends SubForm { updateGPythonStatus(); } - public void updateGPythonStatus() { - if (!pythonShellLaunching) { - btn_gpython.setDisable(!parentController.extraController.useGPython()); - } + @FXML + public void onClickInstallButton() { + final FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle(LanguageBundle.get("tab.extensions.button.install.windowtitle")); + fileChooser.getExtensionFilters().addAll( + new FileChooser.ExtensionFilter(LanguageBundle.get("tab.extensions.button.install.filetype"), ExecutionInfo.ALLOWED_EXTENSION_TYPES)); + final File selectedFile = fileChooser.showOpenDialog(parentController.getStage()); + if (selectedFile != null) + extensionRunner.installAndRunExtension(selectedFile.getPath(), networkExtensionsProducer.getPort()); } - public void setLocalInstallingEnabled(boolean enabled) { - btn_install.setDisable(!enabled); + @FXML + public void onClickLogsButton() { + if (!extensionLogger.isVisible()) + extensionLogger.show(); + else + extensionLogger.hide(); } - private volatile int gpytonShellCounter = 1; - private volatile boolean pythonShellLaunching = false; - public void gpythonBtnClicked(ActionEvent actionEvent) { - pythonShellLaunching = true; - Platform.runLater(() -> btn_gpython.setDisable(true)); + @FXML + public void onClickGPythonShellButton() { + pythonShellLaunching.set(true); + Platform.runLater(() -> openGPythonShellButton.setDisable(true)); GPythonShell shell = new GPythonShell( - String.format("%s %d", LanguageBundle.get("tab.extensions.button.pythonshell.windowtitle"),gpytonShellCounter++), + String.format("%s %d", + LanguageBundle.get("tab.extensions.button.pythonshell.windowtitle"), + gpytonShellCounter.getAndIncrement() + ), networkExtensionsProducer.getPort(), NetworkExtensionAuthenticator.generatePermanentCookie() ); shell.launch((b) -> { - pythonShellLaunching = false; + pythonShellLaunching.set(false); Platform.runLater(this::updateGPythonStatus); }); } + public void updateGPythonStatus() { + if (!pythonShellLaunching.get()) + openGPythonShellButton.setDisable(!parentController.extraController.useGPython()); + } + public ExtensionHandler getExtensionHandler() { return extensionHandler; } private void initLanguageBinding() { - lbl_tableTitle.textProperty().bind(new TranslatableString("%s", "tab.extensions.table.title")); - lbl_tableDesc.textProperty().bind(new TranslatableString("%s", "tab.extensions.table.description")); - lbl_tableAuthor.textProperty().bind(new TranslatableString("%s", "tab.extensions.table.author")); - lbl_tableVersion.textProperty().bind(new TranslatableString("%s", "tab.extensions.table.version")); - lbl_tableEdit.textProperty().bind(new TranslatableString("%s", "tab.extensions.table.edit")); + tableTitleLabel.textProperty().bind(new TranslatableString("%s", "tab.extensions.table.title")); + tableDescriptionLabel.textProperty().bind(new TranslatableString("%s", "tab.extensions.table.description")); + tableAuthorLabel.textProperty().bind(new TranslatableString("%s", "tab.extensions.table.author")); + tableVersionLabel.textProperty().bind(new TranslatableString("%s", "tab.extensions.table.version")); + tableEditLabel.textProperty().bind(new TranslatableString("%s", "tab.extensions.table.edit")); - lbl_port.textProperty().bind(new TranslatableString("%s:", "tab.extensions.port")); + portLabel.textProperty().bind(new TranslatableString("%s:", "tab.extensions.port")); - btn_gpython.textProperty().bind(new TranslatableString("%s", "tab.extensions.button.pythonshell")); - btn_viewExtensionConsole.textProperty().bind(new TranslatableString("%s", "tab.extensions.button.logs")); - btn_install.textProperty().bind(new TranslatableString("%s", "tab.extensions.button.install")); + openGPythonShellButton.textProperty().bind(new TranslatableString("%s", "tab.extensions.button.pythonshell")); + viewLogsButton.textProperty().bind(new TranslatableString("%s", "tab.extensions.button.logs")); + installButton.textProperty().bind(new TranslatableString("%s", "tab.extensions.button.install")); } } diff --git a/G-Earth/src/main/java/gearth/ui/subforms/extensions/logger/ExtensionLogger.java b/G-Earth/src/main/java/gearth/ui/subforms/extensions/logger/ExtensionLogger.java index c821011..48cd027 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/extensions/logger/ExtensionLogger.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/extensions/logger/ExtensionLogger.java @@ -1,14 +1,11 @@ package gearth.ui.subforms.extensions.logger; -import gearth.GEarth; -import gearth.ui.titlebar.DefaultTitleBarConfig; import gearth.ui.titlebar.GEarthThemedTitleBarConfig; import gearth.ui.titlebar.TitleBarController; import gearth.ui.translations.TranslatableString; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; -import javafx.scene.image.Image; import javafx.stage.Modality; import javafx.stage.Stage; @@ -17,6 +14,7 @@ import java.util.ArrayList; import java.util.List; public class ExtensionLogger { + private Stage stage; private ExtensionLoggerController controller = null; diff --git a/G-Earth/src/main/java/gearth/ui/subforms/extensions/logger/ExtensionLoggerController.java b/G-Earth/src/main/java/gearth/ui/subforms/extensions/logger/ExtensionLoggerController.java index bafc3a8..0202cdc 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/extensions/logger/ExtensionLoggerController.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/extensions/logger/ExtensionLoggerController.java @@ -1,5 +1,6 @@ package gearth.ui.subforms.extensions.logger; +import gearth.misc.StringUtils; import javafx.application.Platform; import javafx.fxml.Initializable; import javafx.scene.layout.BorderPane; @@ -12,15 +13,14 @@ import java.net.URL; import java.util.*; public class ExtensionLoggerController implements Initializable { + public BorderPane borderPane; - private Stage stage = null; private StyleClassedTextArea area; private volatile boolean initialized = false; private final List appendOnLoad = new ArrayList<>(); - @Override public void initialize(URL arg0, ResourceBundle arg1) { area = new StyleClassedTextArea(); @@ -44,8 +44,8 @@ public class ExtensionLoggerController implements Initializable { private synchronized void appendLog(List elements) { Platform.runLater(() -> { - StringBuilder sb = new StringBuilder(); - StyleSpansBuilder> styleSpansBuilder = new StyleSpansBuilder<>(0); + final StringBuilder sb = new StringBuilder(); + final StyleSpansBuilder> styleSpansBuilder = new StyleSpansBuilder<>(0); for (Element element : elements) { sb.append(element.text); @@ -66,7 +66,7 @@ public class ExtensionLoggerController implements Initializable { } void log(String s) { - s = cleanTextContent(s); + s = StringUtils.cleanTextContent(s); ArrayList elements = new ArrayList<>(); String classname, text; @@ -98,21 +98,6 @@ public class ExtensionLoggerController implements Initializable { } void setStage(Stage stage) { - this.stage = stage; - } - - private static String cleanTextContent(String text) - { -// // strips off all non-ASCII characters -// text = text.replaceAll("[^\\x00-\\x7F]", ""); -// -// // erases all the ASCII control characters - text = text.replaceAll("[\\p{Cntrl}&&[^\n\t]]", ""); - - // removes non-printable characters from Unicode -// text = text.replaceAll("\\p{C}", ""); - - return text.trim(); } } diff --git a/G-Earth/src/main/java/gearth/ui/subforms/extra/ExtraController.java b/G-Earth/src/main/java/gearth/ui/subforms/extra/ExtraController.java index 1c3d170..3ee1e2f 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/extra/ExtraController.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/extra/ExtraController.java @@ -2,6 +2,7 @@ package gearth.ui.subforms.extra; import gearth.GEarth; import gearth.misc.BindingsUtil; +import gearth.misc.HyperLinkUtil; import gearth.protocol.connection.HState; import gearth.protocol.connection.proxy.ProxyProviderFactory; import gearth.protocol.connection.proxy.SocksConfiguration; @@ -9,79 +10,82 @@ import gearth.services.always_admin.AdminService; import gearth.services.g_python.GPythonVersionUtils; import gearth.ui.GEarthProperties; import gearth.ui.SubForm; -import gearth.ui.subforms.info.InfoController; import gearth.ui.titlebar.TitleBarController; import gearth.ui.translations.LanguageBundle; import gearth.ui.translations.TranslatableString; import javafx.application.Platform; import javafx.beans.binding.Bindings; -import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; import javafx.scene.control.*; import javafx.scene.layout.FlowPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.Region; import java.io.IOException; +import java.net.URL; import java.util.Optional; +import java.util.ResourceBundle; /** * Created by Jonas on 06/04/18. + * TODO: add setup link to g-earth wiki */ -public class ExtraController extends SubForm implements SocksConfiguration { +public class ExtraController extends SubForm implements SocksConfiguration, Initializable { public static final String INFO_URL_GPYTHON = "https://github.com/sirjonasxx/G-Earth/wiki/G-Python-qtConsole"; + public TextArea notepadTextArea; - public TextArea txtarea_notepad; + public CheckBox alwaysOnTopBox; + public Hyperlink troubleshootingLink; - public CheckBox cbx_alwaysOnTop; - public Hyperlink url_troubleshooting; + public CheckBox enableClientSideStaffPermissionsBox; + public CheckBox enableDeveloperModeBox; - //TODO add setup link to g-earth wiki - public CheckBox cbx_gpython; + public CheckBox enableGPythonBox; + public CheckBox enableAdvancedBox; - public CheckBox cbx_advanced; - public GridPane grd_advanced; + public GridPane advancedPane; + public CheckBox advancedDisableDecryptionBox; + public CheckBox advancedEnableDebugBox; + public CheckBox advancedUseSocksBox; + public GridPane advancedSocksInfoGrid; + public TextField advancedSocketProxyIpField; - public CheckBox cbx_disableDecryption; - public CheckBox cbx_debug; - - public CheckBox cbx_useSocks; - public GridPane grd_socksInfo; - public TextField txt_socksIp; - public CheckBox cbx_admin; - public Label lbl_notepad, lbl_proxyIp; - public CheckBox cbx_develop; + public Label notepadLabel, advancedSocksProxyIpLabel; private AdminService adminService; - public void initialize() { - url_troubleshooting.setTooltip(new Tooltip("https://github.com/sirjonasxx/G-Earth/wiki/Troubleshooting")); - InfoController.activateHyperlink(url_troubleshooting); + @Override + public void initialize(URL location, ResourceBundle resources) { - BindingsUtil.setAndBindBiDirectional(txtarea_notepad.textProperty(), GEarthProperties.notesProperty); + troubleshootingLink.setTooltip(new Tooltip("https://github.com/sirjonasxx/G-Earth/wiki/Troubleshooting")); + HyperLinkUtil.showDocumentOnClick(troubleshootingLink); - txt_socksIp.textProperty().set(GEarthProperties.getSocksHost()+":"+GEarthProperties.getSocksPort()); - GEarthProperties.socksHostProperty.bind(Bindings.createStringBinding(this::getSocksHost, txt_socksIp.textProperty())); - GEarthProperties.socksPortProperty.bind(Bindings.createIntegerBinding(this::getSocksPort, txt_socksIp.textProperty())); - grd_socksInfo.disableProperty().bind(GEarthProperties.enableSocksProperty.not()); + BindingsUtil.setAndBindBiDirectional(notepadTextArea.textProperty(), GEarthProperties.notesProperty); - BindingsUtil.setAndBindBiDirectional(cbx_useSocks.selectedProperty(), GEarthProperties.enableSocksProperty); + advancedSocketProxyIpField.textProperty().set(GEarthProperties.getSocksHost()+":"+GEarthProperties.getSocksPort()); + GEarthProperties.socksHostProperty.bind(Bindings.createStringBinding(this::getSocksHost, advancedSocketProxyIpField.textProperty())); + GEarthProperties.socksPortProperty.bind(Bindings.createIntegerBinding(this::getSocksPort, advancedSocketProxyIpField.textProperty())); + advancedSocksInfoGrid.disableProperty().bind(GEarthProperties.enableSocksProperty.not()); + + BindingsUtil.setAndBindBiDirectional(advancedUseSocksBox.selectedProperty(), GEarthProperties.enableSocksProperty); ProxyProviderFactory.setSocksConfig(this); - BindingsUtil.setAndBindBiDirectional(cbx_debug.selectedProperty(), GEarthProperties.enableDebugProperty); - BindingsUtil.setAndBindBiDirectional(cbx_disableDecryption.selectedProperty(), GEarthProperties.disablePacketDecryptionProperty); - BindingsUtil.setAndBindBiDirectional(cbx_alwaysOnTop.selectedProperty(), GEarthProperties.alwaysOnTopProperty); - BindingsUtil.setAndBindBiDirectional(cbx_develop.selectedProperty(), GEarthProperties.enableDeveloperModeProperty); - BindingsUtil.setAndBindBiDirectional(cbx_admin.selectedProperty(), GEarthProperties.alwaysAdminProperty); - BindingsUtil.setAndBindBiDirectional(cbx_gpython.selectedProperty(), GEarthProperties.enableGPythonProperty); + BindingsUtil.setAndBindBiDirectional(advancedEnableDebugBox.selectedProperty(), GEarthProperties.enableDebugProperty); + BindingsUtil.setAndBindBiDirectional(advancedDisableDecryptionBox.selectedProperty(), GEarthProperties.disablePacketDecryptionProperty); + BindingsUtil.setAndBindBiDirectional(alwaysOnTopBox.selectedProperty(), GEarthProperties.alwaysOnTopProperty); + BindingsUtil.setAndBindBiDirectional(enableDeveloperModeBox.selectedProperty(), GEarthProperties.enableDeveloperModeProperty); + BindingsUtil.setAndBindBiDirectional(enableClientSideStaffPermissionsBox.selectedProperty(), GEarthProperties.alwaysAdminProperty); + BindingsUtil.setAndBindBiDirectional(enableGPythonBox.selectedProperty(), GEarthProperties.enableGPythonProperty); initLanguageBinding(); } @Override protected void onParentSet() { - adminService = new AdminService(cbx_admin.isSelected(), getHConnection()); + adminService = new AdminService(enableClientSideStaffPermissionsBox.isSelected(), getHConnection()); getHConnection().addTrafficListener(1, message -> adminService.onMessage(message)); getHConnection().stateProperty().addListener((observable, oldValue, newValue) -> { if (newValue == HState.CONNECTED) @@ -89,31 +93,18 @@ public class ExtraController extends SubForm implements SocksConfiguration { if (oldValue == HState.NOT_CONNECTED || newValue == HState.NOT_CONNECTED) updateAdvancedUI(); }); - cbx_advanced.selectedProperty().addListener(observable -> updateAdvancedUI()); + enableAdvancedBox.selectedProperty().addListener(observable -> updateAdvancedUI()); updateAdvancedUI(); } - private void updateAdvancedUI() { - if (!cbx_advanced.isSelected()) { - cbx_debug.setSelected(false); - cbx_useSocks.setSelected(false); - if (getHConnection().getState() == HState.NOT_CONNECTED) { - cbx_disableDecryption.setSelected(false); - } - } - grd_advanced.setDisable(!cbx_advanced.isSelected()); - - cbx_disableDecryption.setDisable(getHConnection().getState() != HState.NOT_CONNECTED); - } - @Override public boolean useSocks() { - return cbx_useSocks.isSelected(); + return advancedUseSocksBox.isSelected(); } @Override public int getSocksPort() { - String socksString = txt_socksIp.getText(); + String socksString = advancedSocketProxyIpField.getText(); if (socksString.contains(":")) { return Integer.parseInt(socksString.split(":")[1]); } @@ -122,7 +113,7 @@ public class ExtraController extends SubForm implements SocksConfiguration { @Override public String getSocksHost() { - return txt_socksIp.getText().split(":")[0]; + return advancedSocketProxyIpField.getText().split(":")[0]; } @Override @@ -130,17 +121,13 @@ public class ExtraController extends SubForm implements SocksConfiguration { // return cbx_socksUseIfNeeded.isSelected(); return false; } - - public boolean useGPython() { - return cbx_gpython.isSelected(); - } - - public void gpythonCbxClick(ActionEvent actionEvent) { - if (cbx_gpython.isSelected()) { + @FXML + public void onClickGPythonButton() { + if (enableGPythonBox.isSelected()) { new Thread(() -> { Platform.runLater(() -> { - cbx_gpython.setSelected(false); - cbx_gpython.setDisable(true); + enableGPythonBox.setSelected(false); + enableGPythonBox.setDisable(true); }); if (!GPythonVersionUtils.validInstallation()) { Platform.runLater(() -> { @@ -166,13 +153,13 @@ public class ExtraController extends SubForm implements SocksConfiguration { e.printStackTrace(); } - cbx_gpython.setDisable(false); + enableGPythonBox.setDisable(false); }); } else { Platform.runLater(() -> { - cbx_gpython.setSelected(true); - cbx_gpython.setDisable(false); + enableGPythonBox.setSelected(true); + enableGPythonBox.setDisable(false); parentController.extensionsController.updateGPythonStatus(); }); } @@ -183,8 +170,9 @@ public class ExtraController extends SubForm implements SocksConfiguration { } - public void developCbxClick(ActionEvent actionEvent) { - if (cbx_develop.isSelected()) { + @FXML + public void onClickDeveloperModeBox() { + if (enableDeveloperModeBox.isSelected()) { Platform.runLater(() -> { Alert alert = new Alert(Alert.AlertType.WARNING, LanguageBundle.get("tab.extra.options.developmode.alert.title"), ButtonType.NO, ButtonType.YES); alert.setTitle(LanguageBundle.get("tab.extra.options.developmode.alert.title")); @@ -197,7 +185,7 @@ public class ExtraController extends SubForm implements SocksConfiguration { try { Optional result = TitleBarController.create(alert).showAlertAndWait(); if (!result.isPresent() || result.get() == ButtonType.NO) { - cbx_develop.setSelected(false); + enableDeveloperModeBox.setSelected(false); } else { setDevelopMode(true); @@ -212,29 +200,47 @@ public class ExtraController extends SubForm implements SocksConfiguration { } } - private void setDevelopMode(boolean enabled) { - cbx_develop.setSelected(enabled); + @FXML + public void onClickClientSideStaffPermissionsBox() { + adminService.setEnabled(enableClientSideStaffPermissionsBox.isSelected()); } - public void adminCbxClick(ActionEvent actionEvent) { - adminService.setEnabled(cbx_admin.isSelected()); + public boolean useGPython() { + return enableGPythonBox.isSelected(); + } + + private void setDevelopMode(boolean enabled) { + enableDeveloperModeBox.setSelected(enabled); + } + + private void updateAdvancedUI() { + if (!enableAdvancedBox.isSelected()) { + advancedEnableDebugBox.setSelected(false); + advancedUseSocksBox.setSelected(false); + if (getHConnection().getState() == HState.NOT_CONNECTED) { + advancedDisableDecryptionBox.setSelected(false); + } + } + advancedPane.setDisable(!enableAdvancedBox.isSelected()); + + advancedDisableDecryptionBox.setDisable(getHConnection().getState() != HState.NOT_CONNECTED); } private void initLanguageBinding() { - url_troubleshooting.textProperty().bind(new TranslatableString("%s", "tab.extra.troubleshooting")); + troubleshootingLink.textProperty().bind(new TranslatableString("%s", "tab.extra.troubleshooting")); - lbl_notepad.textProperty().bind(new TranslatableString("%s:", "tab.extra.notepad")); - lbl_proxyIp.textProperty().bind(new TranslatableString("%s:", "tab.extra.options.advanced.proxy.ip")); + notepadLabel.textProperty().bind(new TranslatableString("%s:", "tab.extra.notepad")); + advancedSocksProxyIpLabel.textProperty().bind(new TranslatableString("%s:", "tab.extra.options.advanced.proxy.ip")); - cbx_alwaysOnTop.textProperty().bind(new TranslatableString("%s", "tab.extra.options.alwaysontop")); + alwaysOnTopBox.textProperty().bind(new TranslatableString("%s", "tab.extra.options.alwaysontop")); - cbx_develop.textProperty().bind(new TranslatableString("%s", "tab.extra.options.developmode")); - cbx_admin.textProperty().bind(new TranslatableString("%s", "tab.extra.options.staffpermissions")); - cbx_gpython.textProperty().bind(new TranslatableString("%s", "tab.extra.options.pythonscripting")); - cbx_advanced.textProperty().bind(new TranslatableString("%s", "tab.extra.options.advanced")); + enableDeveloperModeBox.textProperty().bind(new TranslatableString("%s", "tab.extra.options.developmode")); + enableClientSideStaffPermissionsBox.textProperty().bind(new TranslatableString("%s", "tab.extra.options.staffpermissions")); + enableGPythonBox.textProperty().bind(new TranslatableString("%s", "tab.extra.options.pythonscripting")); + enableAdvancedBox.textProperty().bind(new TranslatableString("%s", "tab.extra.options.advanced")); - cbx_useSocks.textProperty().bind(new TranslatableString("%s", "tab.extra.options.advanced.socks")); - cbx_disableDecryption.textProperty().bind(new TranslatableString("%s", "tab.extra.options.advanced.disabledecryption")); - cbx_debug.textProperty().bind(new TranslatableString("%s", "tab.extra.options.advanced.debugstdout")); + advancedUseSocksBox.textProperty().bind(new TranslatableString("%s", "tab.extra.options.advanced.socks")); + advancedDisableDecryptionBox.textProperty().bind(new TranslatableString("%s", "tab.extra.options.advanced.disabledecryption")); + advancedEnableDebugBox.textProperty().bind(new TranslatableString("%s", "tab.extra.options.advanced.debugstdout")); } } diff --git a/G-Earth/src/main/java/gearth/ui/subforms/info/InfoController.java b/G-Earth/src/main/java/gearth/ui/subforms/info/InfoController.java index 6c478db..5a69dee 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/info/InfoController.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/info/InfoController.java @@ -1,6 +1,7 @@ package gearth.ui.subforms.info; -import gearth.GEarth; +import gearth.misc.BindingsUtil; +import gearth.misc.HyperLinkUtil; import gearth.ui.GEarthProperties; import gearth.ui.titlebar.TitleBarController; import gearth.ui.translations.LanguageBundle; @@ -21,58 +22,58 @@ import java.util.ResourceBundle; * Created by Jonas on 06/04/18. */ public class InfoController extends SubForm implements Initializable { - public ImageView img_logo; - public Hyperlink link_darkbox; - public Hyperlink link_g_gearth; - public Hyperlink link_g_tanji; - public Hyperlink link_d_gearth; - public Hyperlink link_g_store; - public Hyperlink link_t_gearth; - public Label version, lbl_description, lbl_createdBy, lbl_contrib, lbl_links; - public Button btn_donate; + private static final String PUBKEY = "1GEarthEV9Ua3RcixsKTcuc1PPZd9hqri3"; - public static void activateHyperlink(Hyperlink link) { - link.setOnAction((ActionEvent event) -> { - Hyperlink h = (Hyperlink) event.getTarget(); - String s = h.getTooltip().getText(); - GEarth.main.getHostServices().showDocument(s); - event.consume(); - }); - } + public ImageView logoImageView; + public Hyperlink darkBoxLink; + public Hyperlink githubGEarthLink; + public Hyperlink githubTanjiLink; + public Hyperlink discordGEarthLink; + public Hyperlink githubExtensionStoreLink; + public Hyperlink twitterGEarthLink; + + public Label + themeTitleLabel, + descriptionLabel, + createdByLabel, + contributorsLabel, + linksLabel; + + public Button donateButton; @Override public void initialize(URL location, ResourceBundle resources) { - img_logo.imageProperty().bind(GEarthProperties.logoImageBinding); - version.textProperty().bind(GEarthProperties.themeTitleBinding); + BindingsUtil.setAndBind(logoImageView.imageProperty(), GEarthProperties.logoImageBinding); + BindingsUtil.setAndBind(themeTitleLabel.textProperty(), GEarthProperties.themeTitleBinding); - link_darkbox.setTooltip(new Tooltip("https://darkbox.nl")); - link_d_gearth.setTooltip(new Tooltip("https://discord.gg/AVkcF8y")); - link_g_gearth.setTooltip(new Tooltip("https://github.com/sirjonasxx/G-Earth")); - link_g_tanji.setTooltip(new Tooltip("https://github.com/ArachisH/Tanji")); - link_g_store.setTooltip(new Tooltip("https://github.com/sirjonasxx/G-ExtensionStore")); - link_t_gearth.setTooltip(new Tooltip("https://twitter.com/Scripting_Habbo")); + darkBoxLink.setTooltip(new Tooltip("https://darkbox.nl")); + discordGEarthLink.setTooltip(new Tooltip("https://discord.gg/AVkcF8y")); + githubGEarthLink.setTooltip(new Tooltip("https://github.com/sirjonasxx/G-Earth")); + githubTanjiLink.setTooltip(new Tooltip("https://github.com/ArachisH/Tanji")); + githubExtensionStoreLink.setTooltip(new Tooltip("https://github.com/sirjonasxx/G-ExtensionStore")); + twitterGEarthLink.setTooltip(new Tooltip("https://twitter.com/Scripting_Habbo")); - activateHyperlink(link_darkbox); - activateHyperlink(link_d_gearth); - activateHyperlink(link_g_gearth); - activateHyperlink(link_g_tanji); - activateHyperlink(link_g_store); - activateHyperlink(link_t_gearth); + HyperLinkUtil.showDocumentOnClick(darkBoxLink); + HyperLinkUtil.showDocumentOnClick(discordGEarthLink); + HyperLinkUtil.showDocumentOnClick(githubGEarthLink); + HyperLinkUtil.showDocumentOnClick(githubTanjiLink); + HyperLinkUtil.showDocumentOnClick(githubExtensionStoreLink); + HyperLinkUtil.showDocumentOnClick(twitterGEarthLink); initLanguageBinding(); } - public void donate(ActionEvent actionEvent) { - String pubkey = "1GEarthEV9Ua3RcixsKTcuc1PPZd9hqri3"; - Alert alert = new Alert(Alert.AlertType.INFORMATION, LanguageBundle.get("tab.info.donate.alert.title"), ButtonType.OK); + public void donate(ActionEvent actionEvent) { + + final Alert alert = new Alert(Alert.AlertType.INFORMATION, LanguageBundle.get("tab.info.donate.alert.title"), ButtonType.OK); alert.setHeaderText(LanguageBundle.get("tab.info.donate.alert.title")); - VBox test = new VBox(); + final VBox test = new VBox(); test.getChildren().add(new Label(LanguageBundle.get("tab.info.donate.alert.content"))); - TextArea pubText = new TextArea(pubkey); + final TextArea pubText = new TextArea(PUBKEY); pubText.setPrefHeight(28); pubText.setMaxWidth(250); test.getChildren().add(pubText); @@ -88,12 +89,11 @@ public class InfoController extends SubForm implements Initializable { } private void initLanguageBinding() { - lbl_description.textProperty().bind(new TranslatableString("%s", "tab.info.description")); - lbl_createdBy.textProperty().bind(new TranslatableString("%s:", "tab.info.createdby")); - lbl_contrib.textProperty().bind(new TranslatableString("%s:", "tab.info.contributors")); - lbl_links.textProperty().bind(new TranslatableString("%s:", "tab.info.links")); + descriptionLabel.textProperty().bind(new TranslatableString("%s", "tab.info.description")); + createdByLabel.textProperty().bind(new TranslatableString("%s:", "tab.info.createdby")); + contributorsLabel.textProperty().bind(new TranslatableString("%s:", "tab.info.contributors")); + linksLabel.textProperty().bind(new TranslatableString("%s:", "tab.info.links")); - btn_donate.textProperty().bind(new TranslatableString("%s", "tab.info.donate")); + donateButton.textProperty().bind(new TranslatableString("%s", "tab.info.donate")); } - } diff --git a/G-Earth/src/main/java/gearth/ui/subforms/injection/InjectedPackets.java b/G-Earth/src/main/java/gearth/ui/subforms/injection/InjectedPackets.java index e0bc58c..aa5a75c 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/injection/InjectedPackets.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/injection/InjectedPackets.java @@ -1,6 +1,5 @@ package gearth.ui.subforms.injection; -import gearth.GEarth; import gearth.misc.StringifyAble; import gearth.protocol.HMessage; import gearth.protocol.HPacket; diff --git a/G-Earth/src/main/java/gearth/ui/subforms/injection/InjectionController.java b/G-Earth/src/main/java/gearth/ui/subforms/injection/InjectionController.java index fcc377b..d1280b0 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/injection/InjectionController.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/injection/InjectionController.java @@ -10,150 +10,151 @@ import gearth.ui.translations.LanguageBundle; import gearth.ui.translations.TranslatableString; import javafx.application.Platform; import javafx.beans.InvalidationListener; -import javafx.beans.Observable; -import javafx.beans.binding.Bindings; -import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; import javafx.scene.control.*; import javafx.scene.input.MouseButton; import javafx.scene.paint.Color; import javafx.scene.paint.Paint; import javafx.scene.text.Text; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; +import java.net.URL; +import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; -public class InjectionController extends SubForm { +public class InjectionController extends SubForm implements Initializable { private static final String HISTORY_CACHE_KEY = "INJECTED_HISTORY"; - private static final int historylimit = 69; + private static final int MAX_HISTORY_ENTRIES = 69; - public TextArea inputPacket; - public Text lbl_corruption; - public Text lbl_pcktInfo; - public Button btn_sendToServer; - public Button btn_sendToClient; - public ListView history; - public Label lblHistory; - public Hyperlink lnk_clearHistory; + public TextArea packetTextArea; + public Text packetCorruptedText; + public Text packetInfoText; + public Button sendToServerButton; + public Button sendToClientButton; + public ListView historyView; + public Label historyLabel; + public Hyperlink clearHistoryLink; - private TranslatableString corruption, pcktInfo; + private TranslatableString packetCorruptedString; + private TranslatableString packetInfoString; + @Override protected void onParentSet() { final InvalidationListener updateUI = observable -> Platform.runLater(this::updateUI); GEarthProperties.enableDeveloperModeProperty.addListener(updateUI); getHConnection().stateProperty().addListener(updateUI); - inputPacket.textProperty().addListener(updateUI); + packetTextArea.textProperty().addListener(updateUI); } - public void initialize() { - history.setOnMouseClicked(event -> { - if(event.getButton().equals(MouseButton.PRIMARY) && event.getClickCount() == 2) { - InjectedPackets injectedPackets = history.getSelectionModel().getSelectedItem(); + @Override + public void initialize(URL location, ResourceBundle resources) { + historyView.setOnMouseClicked(event -> { + if (event.getButton().equals(MouseButton.PRIMARY) && event.getClickCount() == 2) { + final InjectedPackets injectedPackets = historyView.getSelectionModel().getSelectedItem(); if (injectedPackets != null) { Platform.runLater(() -> { - inputPacket.setText(injectedPackets.getPacketsAsString()); + packetTextArea.setText(injectedPackets.getPacketsAsString()); updateUI(); }); } } }); - - List rawHistory = Cacher.getList(HISTORY_CACHE_KEY); - if (rawHistory != null) { - List history = rawHistory.stream() - .map(o -> (String)o).limit(historylimit - 1).map(InjectedPackets::new).collect(Collectors.toList()); - updateHistoryView(history); - } - + findInjectedPackets().ifPresent(this::updateHistoryView); initLanguageBinding(); } - private static boolean isPacketIncomplete(String line) { - boolean unmatchedBrace = false; - - boolean ignoreBrace = false; - - for (int i = 0; i < line.length(); i++) { - if (unmatchedBrace && line.charAt(i) == '"' && line.charAt(i - 1) != '\\') { - ignoreBrace = !ignoreBrace; - } - - if (!ignoreBrace) { - if (line.charAt(i) == '{'){ - - unmatchedBrace = true; - } - else if (line.charAt(i) == '}') { - unmatchedBrace = false; - } - } + @FXML + public void onClickSendToServer() { + final HPacket[] packets = parsePackets(packetTextArea.getText()); + for (HPacket packet : packets) { + getHConnection().sendToServer(packet); + writeToLog(Color.BLUE, String.format("SS -> %s: %d", LanguageBundle.get("tab.injection.log.packetwithid"), packet.headerId())); } - - return unmatchedBrace; + addToHistory(packets, packetTextArea.getText(), HMessage.Direction.TOSERVER); } - private static HPacket[] parsePackets(String fullText) { - LinkedList packets = new LinkedList<>(); - String[] lines = fullText.split("\n"); - - for (int i = 0; i < lines.length; i++) { - String line = lines[i]; - while (isPacketIncomplete(line) && i < lines.length - 1) - line += '\n' + lines[++i]; - - packets.add(new HPacket(line)); + @FXML + public void onClickSendToClient() { + final HPacket[] packets = parsePackets(packetTextArea.getText()); + for (HPacket packet : packets) { + getHConnection().sendToClient(packet); + writeToLog(Color.RED, String.format("CS -> %s: %d", LanguageBundle.get("tab.injection.log.packetwithid"), packet.headerId())); } - return packets.toArray(new HPacket[0]); + addToHistory(packets, packetTextArea.getText(), HMessage.Direction.TOCLIENT); + } + + @FXML + public void onClickClearHistory() { + Cacher.put(HISTORY_CACHE_KEY, Collections.emptyList()); + updateHistoryView(Collections.emptyList()); + } + + private void addToHistory(HPacket[] packets, String packetsAsString, HMessage.Direction direction) { + + final InjectedPackets injectedPackets = new InjectedPackets(packetsAsString, packets.length, getHConnection().getPacketInfoManager(), direction); + + final List history = Stream + .concat( + Stream.of(injectedPackets), + findInjectedPackets() + .filter(old -> !old.isEmpty() && !old.get(0).getPacketsAsString().equals(injectedPackets.getPacketsAsString())) + .orElseGet(Collections::emptyList) + .stream()) + .collect(Collectors.toList()); + updateHistoryView(history); + + final List historyAsString = history.stream().map(InjectedPackets::stringify).collect(Collectors.toList()); + Cacher.put(HISTORY_CACHE_KEY, historyAsString); + } + + private void updateHistoryView(List allHistoryItems) { + Platform.runLater(() -> historyView.getItems().setAll(allHistoryItems)); } private void updateUI() { boolean dirty = false; - corruption.setFormat("%s: %s"); - corruption.setKey(1, "tab.injection.corrupted.false"); - lbl_corruption.getStyleClass().clear(); - lbl_corruption.getStyleClass().add("not-corrupted-label"); + packetCorruptedString.setFormat("%s: %s"); + packetCorruptedString.setKey(1, "tab.injection.corrupted.false"); + packetCorruptedText.getStyleClass().setAll("not-corrupted-label"); - HPacket[] packets = parsePackets(inputPacket.getText()); + final HPacket[] packets = parsePackets(packetTextArea.getText()); if (packets.length == 0) { dirty = true; - lbl_corruption.setFill(Paint.valueOf("#ee0404b2")); - lbl_corruption.getStyleClass().clear(); - lbl_corruption.getStyleClass().add("corrupted-label"); + packetCorruptedText.setFill(Paint.valueOf("#ee0404b2")); + packetCorruptedText.getStyleClass().setAll("corrupted-label"); } for (int i = 0; i < packets.length; i++) { if (packets[i].isCorrupted()) { if (!dirty) { - corruption.setFormat("%s: %s -> " + i); - corruption.setKey(1, "tab.injection.corrupted.true"); - lbl_corruption.getStyleClass().clear(); - lbl_corruption.getStyleClass().add("corrupted-label"); + packetCorruptedString.setFormat("%s: %s -> " + i); + packetCorruptedString.setKey(1, "tab.injection.corrupted.true"); + packetCorruptedText.getStyleClass().setAll("corrupted-label"); dirty = true; } else - corruption.setFormat(corruption.getFormat() + ", " + i); + packetCorruptedString.setFormat(packetCorruptedString.getFormat() + ", " + i); } } if (dirty && packets.length == 1) { - corruption.setFormatAndKeys("%s: %s", "tab.injection.corrupted", "tab.injection.corrupted.true"); + packetCorruptedString.setFormatAndKeys("%s: %s", "tab.injection.corrupted", "tab.injection.corrupted.true"); } if (!dirty) { - HConnection connection = getHConnection(); + final HConnection connection = getHConnection(); - boolean canSendToClient = Arrays.stream(packets).allMatch(packet -> + final boolean canSendToClient = Arrays.stream(packets).allMatch(packet -> connection.canSendPacket(HMessage.Direction.TOCLIENT, packet)); - boolean canSendToServer = Arrays.stream(packets).allMatch(packet -> + final boolean canSendToServer = Arrays.stream(packets).allMatch(packet -> connection.canSendPacket(HMessage.Direction.TOSERVER, packet)); - btn_sendToClient.setDisable(!canSendToClient); - btn_sendToServer.setDisable(!canSendToServer); + sendToClientButton.setDisable(!canSendToClient); + sendToServerButton.setDisable(!canSendToServer); // mark packet sending unsafe if there is any packet that is unsafe for both TOSERVER and TOCLIENT boolean isUnsafe = Arrays.stream(packets).anyMatch(packet -> @@ -163,122 +164,87 @@ public class InjectionController extends SubForm { if (packets.length == 1) { HPacket packet = packets[0]; if (isUnsafe) { - pcktInfo.setFormatAndKeys("%s (%s: " + packet.headerId() + ", %s: " + packet.length() + "), %s", + packetInfoString.setFormatAndKeys("%s (%s: " + packet.headerId() + ", %s: " + packet.length() + "), %s", "tab.injection.description.header", "tab.injection.description.id", "tab.injection.description.length", "tab.injection.description.unsafe"); - } - else { - pcktInfo.setFormatAndKeys("%s (%s: " + packet.headerId() + ", %s: " + packet.length() + ")", + } else { + packetInfoString.setFormatAndKeys("%s (%s: " + packet.headerId() + ", %s: " + packet.length() + ")", "tab.injection.description.header", "tab.injection.description.id", "tab.injection.description.length"); } - } - else { + } else { if (isUnsafe) { - pcktInfo.setFormatAndKeys("%s", "tab.injection.description.unsafe"); - } - else { - pcktInfo.setFormatAndKeys(""); + packetInfoString.setFormatAndKeys("%s", "tab.injection.description.unsafe"); + } else { + packetInfoString.setFormatAndKeys(""); } } } else { if (packets.length == 1) { - pcktInfo.setFormatAndKeys("%s (%s:NULL, %s: " + packets[0].getBytesLength() + ")", + packetInfoString.setFormatAndKeys("%s (%s:NULL, %s: " + packets[0].getBytesLength() + ")", "tab.injection.description.header", "tab.injection.description.id", "tab.injection.description.length"); + } else { + packetInfoString.setFormatAndKeys(""); } - else { - pcktInfo.setFormatAndKeys(""); - } - - btn_sendToClient.setDisable(true); - btn_sendToServer.setDisable(true); + sendToClientButton.setDisable(true); + sendToServerButton.setDisable(true); } - - } - - public void sendToServer_clicked(ActionEvent actionEvent) { - HPacket[] packets = parsePackets(inputPacket.getText()); - for (HPacket packet : packets) { - getHConnection().sendToServer(packet); - writeToLog(Color.BLUE, String.format("SS -> %s: %d", LanguageBundle.get("tab.injection.log.packetwithid"), packet.headerId())); - } - - addToHistory(packets, inputPacket.getText(), HMessage.Direction.TOSERVER); - } - - public void sendToClient_clicked(ActionEvent actionEvent) { - HPacket[] packets = parsePackets(inputPacket.getText()); - for (HPacket packet : packets) { - getHConnection().sendToClient(packet); - writeToLog(Color.RED, String.format("CS -> %s: %d", LanguageBundle.get("tab.injection.log.packetwithid"), packet.headerId())); - } - - addToHistory(packets, inputPacket.getText(), HMessage.Direction.TOCLIENT); - } - - private void addToHistory(HPacket[] packets, String packetsAsString, HMessage.Direction direction) { - InjectedPackets injectedPackets = new InjectedPackets(packetsAsString, packets.length, getHConnection().getPacketInfoManager(), direction); - - List newHistory = new ArrayList<>(); - newHistory.add(injectedPackets); - - List rawOldHistory = Cacher.getList(HISTORY_CACHE_KEY); - if (rawOldHistory != null) { - List history = rawOldHistory.stream() - .map(o -> (String)o).limit(historylimit - 1).map(InjectedPackets::new).collect(Collectors.toList()); - - // dont add to history if its equal to the latest added packet - if (history.size() != 0 && history.get(0).getPacketsAsString().equals(injectedPackets.getPacketsAsString())) { - return; - } - - newHistory.addAll(history); - } - - List historyAsStrings = newHistory.stream().map(InjectedPackets::stringify).collect(Collectors.toList()); - Cacher.put(HISTORY_CACHE_KEY, historyAsStrings); - - updateHistoryView(newHistory); - } - - private void updateHistoryView(List allHistoryItems) { - Platform.runLater(() -> { - history.getItems().clear(); - history.getItems().addAll(allHistoryItems); - }); - } - - public void clearHistoryClick(ActionEvent actionEvent) { - Cacher.put(HISTORY_CACHE_KEY, new ArrayList<>()); - updateHistoryView(new ArrayList<>()); } private void initLanguageBinding() { - lblHistory.textProperty().bind(new TranslatableString("%s", "tab.injection.history")); - lblHistory.setTooltip(new Tooltip()); - lblHistory.getTooltip().textProperty().bind(new TranslatableString("%s", "tab.injection.history.tooltip")); + historyLabel.textProperty().bind(new TranslatableString("%s", "tab.injection.history")); + historyLabel.setTooltip(new Tooltip()); + historyLabel.getTooltip().textProperty().bind(new TranslatableString("%s", "tab.injection.history.tooltip")); - corruption = new TranslatableString("%s: %s", "tab.injection.corrupted", "tab.injection.corrupted.true"); - lbl_corruption.textProperty().bind(corruption); + packetCorruptedString = new TranslatableString("%s: %s", "tab.injection.corrupted", "tab.injection.corrupted.true"); + packetCorruptedText.textProperty().bind(packetCorruptedString); - pcktInfo = new TranslatableString("%s (%s:NULL, %s:0)", "tab.injection.description.header", "tab.injection.description.id", "tab.injection.description.length"); - lbl_pcktInfo.textProperty().bind(pcktInfo); + packetInfoString = new TranslatableString("%s (%s:NULL, %s:0)", "tab.injection.description.header", "tab.injection.description.id", "tab.injection.description.length"); + packetInfoText.textProperty().bind(packetInfoString); - btn_sendToServer.textProperty().bind(new TranslatableString("%s", "tab.injection.send.toserver")); - btn_sendToClient.textProperty().bind(new TranslatableString("%s", "tab.injection.send.toclient")); + sendToServerButton.textProperty().bind(new TranslatableString("%s", "tab.injection.send.toserver")); + sendToClientButton.textProperty().bind(new TranslatableString("%s", "tab.injection.send.toclient")); - lnk_clearHistory.textProperty().bind(new TranslatableString("%s", "tab.injection.history.clear")); + clearHistoryLink.textProperty().bind(new TranslatableString("%s", "tab.injection.history.clear")); } - public static void main(String[] args) { - HPacket[] packets = parsePackets("{l}{h:3}{i:967585}{i:9589}{s:\"furni_inscriptionfuckfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\"}{s:\"sirjonasxx-II\"}{s:\"\"}{i:188}{i:0}{i:0}{b:false}"); - System.out.println(new HPacket("{l}{h:2550}{s:\"ClientPerf\"\"ormance\\\"}\"}{s:\"23\"}{s:\"fps\"}{s:\"Avatars: 1, Objects: 0\"}{i:76970180}").toExpression()); + private static Optional> findInjectedPackets() { + return Optional.ofNullable(Cacher.getList(HISTORY_CACHE_KEY)) + .map(rawList -> rawList.stream() + .limit(MAX_HISTORY_ENTRIES - 1) + .map(o -> (String) o) + .map(InjectedPackets::new) + .collect(Collectors.toList())); + } - System.out.println("hi"); + private static HPacket[] parsePackets(String fullText) { + final LinkedList packets = new LinkedList<>(); + final String[] lines = fullText.split("\n"); + + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + while (isPacketIncomplete(line) && i < lines.length - 1) + line += '\n' + lines[++i]; + packets.add(new HPacket(line)); + } + return packets.toArray(new HPacket[0]); + } + + private static boolean isPacketIncomplete(String line) { + boolean unmatchedBrace = false; + boolean ignoreBrace = false; + for (int i = 0; i < line.length(); i++) { + final char c = line.charAt(i); + if (unmatchedBrace && c == '"' && line.charAt(i - 1) != '\\') + ignoreBrace = !ignoreBrace; + if (!ignoreBrace) + unmatchedBrace = c == '{' || (c != '}' && unmatchedBrace); + } + return unmatchedBrace; } } diff --git a/G-Earth/src/main/java/gearth/ui/subforms/logger/LoggerController.java b/G-Earth/src/main/java/gearth/ui/subforms/logger/LoggerController.java index 4f8c581..adba239 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/logger/LoggerController.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/logger/LoggerController.java @@ -20,31 +20,29 @@ import java.util.Calendar; public class LoggerController extends SubForm { - public TextField txtPacketLimit; - public CheckBox cbx_blockIn; - public CheckBox cbx_blockOut; - public CheckBox cbx_showAdditional; - public CheckBox cbx_splitPackets; - public CheckBox cbx_useLog; - public TextFlow txt_logField; - public Button btnUpdate; - public CheckBox cbx_showstruct; + public TextField packetLimitField; + public CheckBox hideIncomingPacketsBox; + public CheckBox hideOutgoingPacketsBox; + public CheckBox showPacketStructureBox; + public CheckBox showAdditionalPacketInfoBox; + public CheckBox splitPacketsBox; + public CheckBox enableLoggingBox; + public TextFlow loggingField; + public Button updateButton; private int packetLimit = 8000; - private PacketLoggerFactory packetLoggerFactory; private PacketLogger packetLogger; - public void onParentSet(){ - packetLoggerFactory = new PacketLoggerFactory(parentController.extensionsController.getExtensionHandler()); - packetLogger = packetLoggerFactory.get(); + public void onParentSet() { + packetLogger = new PacketLoggerFactory(parentController.extensionsController.getExtensionHandler()).get(); getHConnection().getStateObservable().addListener((oldState, newState) -> Platform.runLater(() -> { if (newState == HState.PREPARING) { - miniLogText(Color.ORANGE, "Connecting to "+getHConnection().getDomain() + ":" + getHConnection().getServerPort()); + miniLogText(Color.ORANGE, "Connecting to " + getHConnection().getDomain() + ":" + getHConnection().getServerPort()); } if (newState == HState.CONNECTED) { - miniLogText(Color.GREEN, "Connected to "+getHConnection().getDomain() + ":" + getHConnection().getServerPort()); + miniLogText(Color.GREEN, "Connected to " + getHConnection().getDomain() + ":" + getHConnection().getServerPort()); packetLogger.start(getHConnection()); } if (newState == HState.NOT_CONNECTED) { @@ -53,81 +51,85 @@ public class LoggerController extends SubForm { } })); - getHConnection().addTrafficListener(2, message -> { Platform.runLater(() -> { - if (message.getDestination() == HMessage.Direction.TOCLIENT && cbx_blockIn.isSelected() || - message.getDestination() == HMessage.Direction.TOSERVER && cbx_blockOut.isSelected()) return; + getHConnection().addTrafficListener(2, message -> { + Platform.runLater(() -> { + if (message.getDestination() == HMessage.Direction.TOCLIENT && hideIncomingPacketsBox.isSelected() || + message.getDestination() == HMessage.Direction.TOSERVER && hideOutgoingPacketsBox.isSelected()) + return; - if (cbx_splitPackets.isSelected()) { - packetLogger.appendSplitLine(); - } + if (splitPacketsBox.isSelected()) { + packetLogger.appendSplitLine(); + } - int types = 0; - if (message.getDestination() == HMessage.Direction.TOCLIENT) types |= PacketLogger.MESSAGE_TYPE.INCOMING.getValue(); - else if (message.getDestination() == HMessage.Direction.TOSERVER) types |= PacketLogger.MESSAGE_TYPE.OUTGOING.getValue(); - if (message.getPacket().length() >= packetLimit) types |= PacketLogger.MESSAGE_TYPE.SKIPPED.getValue(); - if (message.isBlocked()) types |= PacketLogger.MESSAGE_TYPE.BLOCKED.getValue(); - if (message.getPacket().isReplaced()) types |= PacketLogger.MESSAGE_TYPE.REPLACED.getValue(); - if (cbx_showAdditional.isSelected()) types |= PacketLogger.MESSAGE_TYPE.SHOW_ADDITIONAL_DATA.getValue(); + int types = 0; + if (message.getDestination() == HMessage.Direction.TOCLIENT) + types |= PacketLogger.MESSAGE_TYPE.INCOMING.getValue(); + else if (message.getDestination() == HMessage.Direction.TOSERVER) + types |= PacketLogger.MESSAGE_TYPE.OUTGOING.getValue(); + if (message.getPacket().length() >= packetLimit) types |= PacketLogger.MESSAGE_TYPE.SKIPPED.getValue(); + if (message.isBlocked()) types |= PacketLogger.MESSAGE_TYPE.BLOCKED.getValue(); + if (message.getPacket().isReplaced()) types |= PacketLogger.MESSAGE_TYPE.REPLACED.getValue(); + if (showAdditionalPacketInfoBox.isSelected()) + types |= PacketLogger.MESSAGE_TYPE.SHOW_ADDITIONAL_DATA.getValue(); - packetLogger.appendMessage(message.getPacket(), types); + packetLogger.appendMessage(message.getPacket(), types); - if (cbx_showstruct.isSelected() && message.getPacket().length() < packetLimit) { - packetLogger.appendStructure(message.getPacket(), message.getDestination()); - } - }); + if (showPacketStructureBox.isSelected() && message.getPacket().length() < packetLimit) { + packetLogger.appendStructure(message.getPacket(), message.getDestination()); + } + }); }); } public void updatePacketLimit(ActionEvent actionEvent) { - packetLimit = Integer.parseInt(txtPacketLimit.getText()); + packetLimit = Integer.parseInt(packetLimitField.getText()); } @SuppressWarnings("Duplicates") public void initialize() { - txtPacketLimit.textProperty().addListener(observable -> { + packetLimitField.textProperty().addListener(observable -> { boolean isInt = true; try { - Integer.parseInt(txtPacketLimit.getText()); + Integer.parseInt(packetLimitField.getText()); } catch (NumberFormatException e) { isInt = false; } - btnUpdate.setDisable(!isInt); + updateButton.setDisable(!isInt); }); - txtPacketLimit.setOnKeyPressed(event -> { - if(event.getCode().equals(KeyCode.ENTER) && !btnUpdate.isDisable()) { + packetLimitField.setOnKeyPressed(event -> { + if (event.getCode().equals(KeyCode.ENTER) && !updateButton.isDisable()) { updatePacketLimit(null); } }); } public void miniLogText(Color color, String text) { - if (cbx_useLog.isSelected()) { - String color2 = "#" + color.toString().substring(2, 8); + if (enableLoggingBox.isSelected()) { + final String color2 = "#" + color.toString().substring(2, 8); - Calendar rightNow = Calendar.getInstance(); - String hour = addToNumber(""+rightNow.get(Calendar.HOUR_OF_DAY)); - String minutes = addToNumber(""+rightNow.get(Calendar.MINUTE)); - String seconds = addToNumber(""+rightNow.get(Calendar.SECOND)); - String timestamp = "["+hour+":"+minutes+":"+seconds+"] "; + final Calendar rightNow = Calendar.getInstance(); + final String hour = addToNumber("" + rightNow.get(Calendar.HOUR_OF_DAY)); + final String minutes = addToNumber("" + rightNow.get(Calendar.MINUTE)); + final String seconds = addToNumber("" + rightNow.get(Calendar.SECOND)); + String timestamp = "[" + hour + ":" + minutes + ":" + seconds + "] "; timestamp = timestamp.replace(" ", "\u00A0"); // disable automatic linebreaks - Text time = new Text(timestamp); - time.setStyle("-fx-opacity: "+0.5+";"); + final Text time = new Text(timestamp); + time.setStyle("-fx-opacity: " + 0.5 + ";"); text = text.replace(" ", "\u00A0"); - Text otherText = new Text(text + "\n"); - otherText.setStyle("-fx-fill: "+color2+";"); + final Text otherText = new Text(text + "\n"); + otherText.setStyle("-fx-fill: " + color2 + ";"); - txt_logField.getChildren().addAll(time, otherText); + loggingField.getChildren().addAll(time, otherText); } } - private String addToNumber(String text) { + private String addToNumber(String text) { if (text.length() == 1) text = "0" + text; return text; } - } diff --git a/G-Earth/src/main/java/gearth/ui/subforms/logger/loggerdisplays/LinuxTerminalLogger.java b/G-Earth/src/main/java/gearth/ui/subforms/logger/loggerdisplays/LinuxTerminalLogger.java index 64c2247..30dfc72 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/logger/loggerdisplays/LinuxTerminalLogger.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/logger/loggerdisplays/LinuxTerminalLogger.java @@ -57,7 +57,7 @@ class LinuxTerminalLogger extends SimpleTerminalLogger { output.append(colorizePackets.get("ENGLISH")); - System.out.println(output.toString()); + System.out.println(output); } @Override diff --git a/G-Earth/src/main/java/gearth/ui/subforms/scheduler/ScheduleItemContainer.java b/G-Earth/src/main/java/gearth/ui/subforms/scheduler/ScheduleItemContainer.java index 89bdaf7..8b626d9 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/scheduler/ScheduleItemContainer.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/scheduler/ScheduleItemContainer.java @@ -40,12 +40,12 @@ public class ScheduleItemContainer extends GridPane { } private void initialize() { - RowConstraints rowConstraints = new RowConstraints(23); + final RowConstraints rowConstraints = new RowConstraints(23); getRowConstraints().addAll(rowConstraints); - for (int i = 0; i < columnWidths.length; i++) { - ColumnConstraints columnConstraints = new ColumnConstraints(20); - columnConstraints.setPercentWidth(columnWidths[i]); + for (int columnWidth : columnWidths) { + final ColumnConstraints columnConstraints = new ColumnConstraints(20); + columnConstraints.setPercentWidth(columnWidth); getColumnConstraints().add(columnConstraints); } @@ -101,7 +101,7 @@ public class ScheduleItemContainer extends GridPane { } private Label initNewLabelColumn(String text) { - Label label = new Label(); + final Label label = new Label(); // label.setMaxWidth(Double.MAX_VALUE); // label.setMinHeight(Double.MAX_VALUE); // label.setAlignment(Pos.CENTER); diff --git a/G-Earth/src/main/java/gearth/ui/subforms/scheduler/SchedulerController.java b/G-Earth/src/main/java/gearth/ui/subforms/scheduler/SchedulerController.java index 4c9d341..e620f78 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/scheduler/SchedulerController.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/scheduler/SchedulerController.java @@ -1,73 +1,87 @@ package gearth.ui.subforms.scheduler; import com.tulskiy.keymaster.common.Provider; -import gearth.extensions.parsers.HDirection; import gearth.protocol.HConnection; -import gearth.protocol.StateChangeListener; -import gearth.protocol.connection.HState; +import gearth.protocol.HMessage; +import gearth.protocol.HPacket; import gearth.services.scheduler.Interval; import gearth.services.scheduler.Scheduler; import gearth.ui.GEarthProperties; +import gearth.ui.SubForm; import gearth.ui.translations.LanguageBundle; import gearth.ui.translations.TranslatableString; import javafx.application.Platform; import javafx.beans.InvalidationListener; -import javafx.beans.binding.Bindings; -import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; import javafx.scene.control.*; import javafx.scene.layout.GridPane; import javafx.scene.layout.VBox; import javafx.stage.FileChooser; -import gearth.protocol.HMessage; -import gearth.protocol.HPacket; -import gearth.ui.SubForm; import javax.swing.*; -import java.io.*; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.net.URL; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; +import java.util.ResourceBundle; /** * Created by Jonas on 06/04/18. */ -public class SchedulerController extends SubForm { +public class SchedulerController extends SubForm implements Initializable { private static final Interval defaultInterval = new Interval(0, 500); private static final HPacket defaultPacket = new HPacket("Chat", HMessage.Direction.TOCLIENT, -1, "Frank loves G-Earth", 0, 33, 0, 0); - public VBox schedulecontainer; - public GridPane header; + public VBox root; + public GridPane headerGrid; public ScrollPane scrollpane; - public Button btn_addoredit; + public Button addOrEditButton; - public TextField txt_delay; - public ToggleGroup scheduler_dest; - public TextField txt_packet; - public RadioButton rb_incoming; - public RadioButton rb_outgoing; + public TextField packetDelayField; + public TextField packetExpressionField; - public Button btn_clear; - public Button btn_save; - public Button btn_load; + public ToggleGroup packetTypeOptions; + public RadioButton packetIncomingOption; + public RadioButton packetOutgoingOption; - public CheckBox cbx_hotkeys; + public Button clearButton; + public Button saveButton; + public Button loadButton; + + public CheckBox enableHotkeysBox; + + public Label + tableIndexLabel, + tablePacketLabel, + tableIntervalLabel, + tableDestinationLabel, + tableEditLabel, + packetExpressionLabel, + packetIntervalLabel; + + private TranslatableString addOrEditString; private InteractableScheduleItem isBeingEdited = null; private Scheduler scheduler = null; - private TranslatableString addoredit; - public Label lbl_tableIndex, lbl_tablePacket, lbl_tableInterval, lbl_tableDest, lbl_tableEdit, lbl_setupPacket, lbl_setupInterval; + @Override + public void initialize(URL location, ResourceBundle resources) { + scrollpane.widthProperty().addListener(observable -> headerGrid.setPrefWidth(scrollpane.getWidth())); + packetTypeOptions.selectToggle(packetTypeOptions.getToggles().get(0)); - public void initialize() { - scrollpane.widthProperty().addListener(observable -> header.setPrefWidth(scrollpane.getWidth())); - scheduler_dest.selectToggle(scheduler_dest.getToggles().get(0)); + packetExpressionField.textProperty().addListener(event -> Platform.runLater(this::updateUI)); + packetDelayField.textProperty().addListener(event -> Platform.runLater(this::updateUI)); - txt_packet.textProperty().addListener(event -> Platform.runLater(this::updateUI)); - txt_delay.textProperty().addListener(event -> Platform.runLater(this::updateUI)); + clearButton.setOnAction(a -> clear()); //register hotkeys //disable some output things @@ -97,65 +111,93 @@ public class SchedulerController extends SubForm { updateUI(); } + @FXML + public void onClickAddOrEditButton() { + if (isBeingEdited == null) { + final HPacket packet = new HPacket(packetExpressionField.getText()); + if (packet.isCorrupted()) + return; + final InteractableScheduleItem newItem = new InteractableScheduleItem( + scheduler.size(), + false, + new Interval(packetDelayField.getText()), + packetExpressionField.getText(), + packetIncomingOption.isSelected() ? HMessage.Direction.TOCLIENT : HMessage.Direction.TOSERVER); + addItem(newItem); + } + else { + isBeingEdited.getPacketAsStringProperty().set(packetExpressionField.getText()); + isBeingEdited.getDelayProperty().set(new Interval(packetDelayField.getText())); + isBeingEdited.getDestinationProperty().set(packetIncomingOption.isSelected() ? HMessage.Direction.TOCLIENT : HMessage.Direction.TOSERVER); + isBeingEdited.isUpdatedTrigger(); + isBeingEdited = null; + setInputDefault(false); + } + } + + @FXML + public void onClickSaveButton() { + final FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle(LanguageBundle.get("tab.scheduler.button.save.windowtitle")); + fileChooser.getExtensionFilters().add(getExtensionFilter()); + final File file = fileChooser.showSaveDialog(parentController.getStage()); + if (file != null) { + final List strings = new ArrayList<>(); + for (int i = 0; i < scheduler.size(); i++) { + strings.add(scheduler.get(i).stringify()); + if (i != scheduler.size() - 1) + strings.add("\n"); + } + try { + Files.write(file.toPath(), strings); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + @FXML + public void onClickLoadButton() { + final FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle(LanguageBundle.get("tab.scheduler.button.load.windowtitle")); + fileChooser.getExtensionFilters().addAll(getExtensionFilter()); + final File selectedFile = fileChooser.showOpenDialog(parentController.getStage()); + if (selectedFile != null) { + try { + clear(); + Files.readAllLines(selectedFile.toPath()) + .stream() + .map(InteractableScheduleItem::new) + .forEach(this::addItem); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + private void switchPauseHotkey(int index) { - if (cbx_hotkeys.isSelected() && index < scheduler.size()) { + if (enableHotkeysBox.isSelected() && index < scheduler.size()) { scheduler.get(index).getPausedProperty().set(!scheduler.get(index).getPausedProperty().get()); } } - public static boolean stringIsNumber(String str) { - try { - Integer.parseInt(str); - return true; - } - catch (Exception e){ - return false; - } - } - private void updateUI() { - HConnection connection = getHConnection(); - if (connection == null) return; - HMessage.Direction direction = rb_incoming.isSelected() ? HMessage.Direction.TOCLIENT : HMessage.Direction.TOSERVER; - HPacket packet = new HPacket(txt_packet.getText()); - boolean isPacketOk = connection.canSendPacket(direction, packet); + final HConnection connection = getHConnection(); - btn_addoredit.setDisable(!Interval.isValid(txt_delay.getText()) || !isPacketOk); - } + if (connection == null) + return; - public void scheduleBtnClicked(ActionEvent actionEvent) { - if (isBeingEdited == null) { - HPacket packet = new HPacket(txt_packet.getText()); - if (packet.isCorrupted()) return; - - InteractableScheduleItem newItem = new InteractableScheduleItem( - scheduler.size(), - false, - new Interval(txt_delay.getText()), - txt_packet.getText(), - rb_incoming.isSelected() ? HMessage.Direction.TOCLIENT : HMessage.Direction.TOSERVER); - - addItem(newItem); - } - else { - - isBeingEdited.getPacketAsStringProperty().set(txt_packet.getText()); - isBeingEdited.getDelayProperty().set(new Interval(txt_delay.getText())); - isBeingEdited.getDestinationProperty().set(rb_incoming.isSelected() ? HMessage.Direction.TOCLIENT : HMessage.Direction.TOSERVER); - isBeingEdited.isUpdatedTrigger(); - - isBeingEdited = null; - setInputDefault(false); - } + final HMessage.Direction direction = packetIncomingOption.isSelected() ? HMessage.Direction.TOCLIENT : HMessage.Direction.TOSERVER; + final HPacket packet = new HPacket(packetExpressionField.getText()); + final boolean isPacketOk = connection.canSendPacket(direction, packet); + addOrEditButton.setDisable(!Interval.isValid(packetDelayField.getText()) || !isPacketOk); } private void addItem(InteractableScheduleItem newItem) { - new ScheduleItemContainer(newItem, schedulecontainer, scrollpane); + new ScheduleItemContainer(newItem, root, scrollpane); scheduler.add(newItem); - - newItem.onDelete(() -> { if (isBeingEdited == newItem) { setInputDefault(false); @@ -172,13 +214,13 @@ public class SchedulerController extends SubForm { } if (isBeingEdited != newItem) { - txt_packet.setText(newItem.getPacketAsStringProperty().get()); - txt_delay.setText(newItem.getDelayProperty().get().toString()); - rb_incoming.setSelected(newItem.getDestinationProperty().get() == HMessage.Direction.TOCLIENT); - rb_outgoing.setSelected(newItem.getDestinationProperty().get() == HMessage.Direction.TOSERVER); + packetExpressionField.setText(newItem.getPacketAsStringProperty().get()); + packetDelayField.setText(newItem.getDelayProperty().get().toString()); + packetIncomingOption.setSelected(newItem.getDestinationProperty().get() == HMessage.Direction.TOCLIENT); + packetOutgoingOption.setSelected(newItem.getDestinationProperty().get() == HMessage.Direction.TOSERVER); isBeingEdited = newItem; - addoredit.setKey(0, "tab.scheduler.button.edit"); + addOrEditString.setKey(0, "tab.scheduler.button.edit"); updateUI(); newItem.onIsBeingUpdatedTrigger(); } @@ -191,127 +233,53 @@ public class SchedulerController extends SubForm { } private void setInputDefault(boolean showDummyPacket) { - txt_delay.setText(defaultInterval.toString()); - txt_packet.setText(showDummyPacket ? defaultPacket.toExpression() : ""); - rb_incoming.setSelected(true); - rb_outgoing.setSelected(false); + packetDelayField.setText(defaultInterval.toString()); + packetExpressionField.setText(showDummyPacket ? defaultPacket.toExpression() : ""); + packetIncomingOption.setSelected(true); + packetOutgoingOption.setSelected(false); - addoredit.setKey(0, "tab.scheduler.button.add"); + addOrEditString.setKey(0, "tab.scheduler.button.add"); updateUI(); } private void clear() { - for (int i = scheduler.size() - 1; i >= 0; i--) { + for (int i = scheduler.size() - 1; i >= 0; i--) scheduler.get(i).delete(); - } - } - private void load(List list) { - clear(); - - for (InteractableScheduleItem item : list) { - addItem(item); - } - } - - - public void clearBtnClicked(ActionEvent actionEvent) { - clear(); - } - - public void saveBtnClicked(ActionEvent actionEvent) { - FileChooser fileChooser = new FileChooser(); - - //Set extension filter - FileChooser.ExtensionFilter extFilter = - new FileChooser.ExtensionFilter(LanguageBundle.get("tab.scheduler.filetype"), "*.sched"); - fileChooser.getExtensionFilters().add(extFilter); - fileChooser.setTitle(LanguageBundle.get("tab.scheduler.button.save.windowtitle")); - - //Show save file dialog - File file = fileChooser.showSaveDialog(parentController.getStage()); - - if(file != null){ - try { - FileWriter fileWriter = new FileWriter(file); - BufferedWriter out = new BufferedWriter(fileWriter); - - for (int i = 0; i < scheduler.size(); i++) { - out.write(scheduler.get(i).stringify()); - if (i != scheduler.size() - 1) out.write("\n"); - } - - out.flush(); - out.close(); - fileWriter.close(); - } catch (IOException ex) { - ex.printStackTrace(); - } - - } - } - - public void loadBtnClicked(ActionEvent actionEvent) { - List list = new ArrayList<>(); - - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle(LanguageBundle.get("tab.scheduler.button.load.windowtitle")); - fileChooser.getExtensionFilters().addAll( - new FileChooser.ExtensionFilter(LanguageBundle.get("tab.scheduler.filetype"), "*.sched")); - File selectedFile = fileChooser.showOpenDialog(parentController.getStage()); - if (selectedFile != null) { - - FileReader fr = null; - try { - fr = new FileReader(selectedFile); - BufferedReader br = new BufferedReader(fr); - String line = null; - - while ((line = br.readLine()) != null) - { - list.add(new InteractableScheduleItem(line)); - } - - fr.close(); - br.close(); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - load(list); - } private void initLanguageBinding() { - addoredit = new TranslatableString("%s", "tab.scheduler.button.add"); - btn_addoredit.textProperty().bind(addoredit); + addOrEditString = new TranslatableString("%s", "tab.scheduler.button.add"); + addOrEditButton.textProperty().bind(addOrEditString); - btn_clear.textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.clear")); - btn_clear.setTooltip(new Tooltip()); - btn_clear.getTooltip().textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.clear.tooltip")); + clearButton.textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.clear")); + clearButton.setTooltip(new Tooltip()); + clearButton.getTooltip().textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.clear.tooltip")); - btn_save.textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.save")); - btn_save.setTooltip(new Tooltip()); - btn_save.getTooltip().textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.save.tooltip")); + saveButton.textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.save")); + saveButton.setTooltip(new Tooltip()); + saveButton.getTooltip().textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.save.tooltip")); - btn_load.textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.load")); - btn_load.setTooltip(new Tooltip()); - btn_load.getTooltip().textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.load.tooltip")); + loadButton.textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.load")); + loadButton.setTooltip(new Tooltip()); + loadButton.getTooltip().textProperty().bind(new TranslatableString("%s", "tab.scheduler.button.load.tooltip")); - lbl_tableIndex.textProperty().bind(new TranslatableString("%s", "tab.scheduler.table.index")); - lbl_tablePacket.textProperty().bind(new TranslatableString("%s", "tab.scheduler.table.packet")); - lbl_tableInterval.textProperty().bind(new TranslatableString("%s", "tab.scheduler.table.interval")); - lbl_tableDest.textProperty().bind(new TranslatableString("%s", "tab.scheduler.table.destination")); - lbl_tableEdit.textProperty().bind(new TranslatableString("%s", "tab.scheduler.table.edit")); + tableIndexLabel.textProperty().bind(new TranslatableString("%s", "tab.scheduler.table.index")); + tablePacketLabel.textProperty().bind(new TranslatableString("%s", "tab.scheduler.table.packet")); + tableIntervalLabel.textProperty().bind(new TranslatableString("%s", "tab.scheduler.table.interval")); + tableDestinationLabel.textProperty().bind(new TranslatableString("%s", "tab.scheduler.table.destination")); + tableEditLabel.textProperty().bind(new TranslatableString("%s", "tab.scheduler.table.edit")); - lbl_setupPacket.textProperty().bind(new TranslatableString("%s:", "tab.scheduler.setup.packet")); - lbl_setupInterval.textProperty().bind(new TranslatableString("%s:", "tab.scheduler.setup.interval")); + packetExpressionLabel.textProperty().bind(new TranslatableString("%s:", "tab.scheduler.setup.packet")); + packetIntervalLabel.textProperty().bind(new TranslatableString("%s:", "tab.scheduler.setup.interval")); - rb_incoming.textProperty().bind(new TranslatableString("%s", "tab.scheduler.direction.in")); - rb_outgoing.textProperty().bind(new TranslatableString("%s", "tab.scheduler.direction.out")); + packetIncomingOption.textProperty().bind(new TranslatableString("%s", "tab.scheduler.direction.in")); + packetOutgoingOption.textProperty().bind(new TranslatableString("%s", "tab.scheduler.direction.out")); - cbx_hotkeys.textProperty().bind(new TranslatableString("%s", "tab.scheduler.hotkeys")); + enableHotkeysBox.textProperty().bind(new TranslatableString("%s", "tab.scheduler.hotkeys")); + } + + private static FileChooser.ExtensionFilter getExtensionFilter() { + return new FileChooser.ExtensionFilter(LanguageBundle.get("tab.scheduler.filetype"), "*.sched"); } } diff --git a/G-Earth/src/main/java/gearth/ui/subforms/tools/ToolsController.java b/G-Earth/src/main/java/gearth/ui/subforms/tools/ToolsController.java index 874283a..b47f237 100644 --- a/G-Earth/src/main/java/gearth/ui/subforms/tools/ToolsController.java +++ b/G-Earth/src/main/java/gearth/ui/subforms/tools/ToolsController.java @@ -1,180 +1,147 @@ package gearth.ui.subforms.tools; -import gearth.services.packet_info.PacketInfoManager; -import gearth.ui.translations.TranslatableString; -import javafx.event.ActionEvent; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.TextArea; -import javafx.scene.control.TextField; -import javafx.scene.input.KeyCode; +import gearth.misc.BindingsUtil; import gearth.protocol.HPacket; +import gearth.services.packet_info.PacketInfoManager; import gearth.ui.SubForm; +import gearth.ui.translations.TranslatableString; +import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanBinding; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.Node; +import javafx.scene.control.*; +import javafx.scene.input.KeyCode; +import java.net.URL; import java.nio.ByteBuffer; +import java.util.ResourceBundle; +public class ToolsController extends SubForm implements Initializable { -public class ToolsController extends SubForm { - public TextField txt_intDecoded; - public TextField txt_intEncoded; - public TextField txt_ushortDecoded; - public TextField txt_ushortEncoded; - public Button btnEncodeInt; - public Button btnDecodeInt; - public Button btnEncodeUShort; - public Button btnDecodeUshort; + public TextField decodedIntegerField; + public TextField encodedIntegerField; + public TextField decodedUShortField; + public TextField encodedUShortField; + public Button encodeIntegerButton; + public Button decodeIntegerButton; + public Button encodeUShortButton; + public Button decodeUShortButton; - public Button btn_toExpr; - public TextArea txt_packetArea; - public Button btn_toPacket; - public TextArea txt_exprArea; + public TextArea packetArea; + public TextArea expressionArea; + public Button convertPacketToExpressionButton; + public Button convertExpressionToPacketButton; - public Label lbl_integer, lbl_uShort, lbl_encodingDecoding, lbl_packetToExpression; + public Label + integerLabel, + uShortLabel, + encodingOrDecodingLabel, + packetToExpressionLabel; //TODO: toExpression() without bytelength limit for this use only - public void initialize() { - txt_packetArea.textProperty().addListener(observable -> { - btn_toExpr.setDisable(new HPacket(txt_packetArea.getText()).isCorrupted()); - }); + @Override + public void initialize(URL location, ResourceBundle resources) { - txt_packetArea.setOnKeyPressed(event -> { - if(event.getCode().equals(KeyCode.ENTER) && !btn_toExpr.isDisable()) { - btn_toExpr_clicked(null); - } - }); + convertPacketToExpressionButton.disableProperty().bind(packetIsCorruptBinding(packetArea)); + convertExpressionToPacketButton.disableProperty().bind(packetIsCorruptBinding(expressionArea)); - txt_exprArea.textProperty().addListener(observable -> { - btn_toPacket.setDisable(new HPacket(txt_exprArea.getText()).isCorrupted()); - }); + encodeIntegerButton.disableProperty().bind(BindingsUtil.isInteger(decodedIntegerField.textProperty()).not()); + decodeIntegerButton.disableProperty().bind(packetLengthEqualsBinding(encodedIntegerField, Integer.BYTES).not()); - txt_exprArea.setOnKeyPressed(event -> { - if(event.getCode().equals(KeyCode.ENTER) && !btn_toPacket.isDisable()) { - btn_toPacket_clicked(null); - } - }); + encodeUShortButton.disableProperty().bind(BindingsUtil.isUShort(decodedUShortField.textProperty()).not()); + decodeUShortButton.disableProperty().bind(packetLengthEqualsBinding(encodedUShortField, Short.BYTES).not()); - - txt_intDecoded.textProperty().addListener(observable -> { - boolean isInt = true; - - try { - Integer.parseInt(txt_intDecoded.getText()); - } catch (NumberFormatException e) { - isInt = false; - } - - btnEncodeInt.setDisable(!isInt); - }); - - txt_intDecoded.setOnKeyPressed(event -> { - if(event.getCode().equals(KeyCode.ENTER) && !btnEncodeInt.isDisable()) { - btnEncodeInt_clicked(null); - } - }); - - //--------------- - - txt_ushortDecoded.textProperty().addListener(observable -> { - boolean isDouble = true; - - try { - int res = Integer.parseInt(txt_ushortDecoded.getText()); - if (res < 0 || res >= (256*256)) isDouble = false; - } catch (NumberFormatException e) { - isDouble = false; - } - btnEncodeUShort.setDisable(!isDouble); - }); - - txt_ushortDecoded.setOnKeyPressed(event -> { - if(event.getCode().equals(KeyCode.ENTER) && !btnEncodeUShort.isDisable()) { - btnEncodeUShort_clicked(null); - } - }); - - //---------------- - - txt_intEncoded.textProperty().addListener(observable -> { - HPacket packet = new HPacket(txt_intEncoded.getText()); - btnDecodeInt.setDisable(packet.getBytesLength() != 4); - }); - - txt_intEncoded.setOnKeyPressed(event -> { - if(event.getCode().equals(KeyCode.ENTER) && !btnDecodeInt.isDisable()) { - btnDecodeInt_clicked(null); - } - }); - - //---------------- - - txt_ushortEncoded.textProperty().addListener(observable -> { - HPacket packet = new HPacket(txt_ushortEncoded.getText()); - btnDecodeUshort.setDisable(packet.getBytesLength() != 2); - }); - - txt_ushortEncoded.setOnKeyPressed(event -> { - if(event.getCode().equals(KeyCode.ENTER) && !btnDecodeUshort.isDisable()) { - btnDecodeUshort_clicked(null); - } - }); + fireButtonOnPressEnter(packetArea, convertPacketToExpressionButton); + fireButtonOnPressEnter(expressionArea, convertExpressionToPacketButton); + fireButtonOnPressEnter(decodedIntegerField, encodeIntegerButton); + fireButtonOnPressEnter(decodedUShortField, encodeUShortButton); + fireButtonOnPressEnter(encodedIntegerField, decodeIntegerButton); + fireButtonOnPressEnter(encodedUShortField, decodeUShortButton); initLanguageBinding(); } - public void btnEncodeInt_clicked(ActionEvent actionEvent) { - ByteBuffer b = ByteBuffer.allocate(4); - b.putInt(Integer.parseInt(txt_intDecoded.getText())); - - HPacket packet = new HPacket(b.array()); - txt_intEncoded.setText(packet.toString()); - } - public void btnDecodeInt_clicked(ActionEvent actionEvent) { - txt_intDecoded.setText(new HPacket(txt_intEncoded.getText()).readInteger(0) + ""); - } - public void btnEncodeUShort_clicked(ActionEvent actionEvent) { - ByteBuffer b = ByteBuffer.allocate(4); - b.putInt(Integer.parseInt(txt_ushortDecoded.getText())); - - HPacket packet = new HPacket(new byte[]{b.array()[2], b.array()[3]}); - txt_ushortEncoded.setText(packet.toString()); - } - public void btnDecodeUshort_clicked(ActionEvent actionEvent) { - txt_ushortDecoded.setText(new HPacket(txt_ushortEncoded.getText()).readUshort(0) + ""); + private BooleanBinding packetIsCorruptBinding(TextInputControl input) { + return Bindings.createBooleanBinding(() -> new HPacket(input.getText()).isCorrupted(), input.textProperty()); } + private BooleanBinding packetLengthEqualsBinding(TextInputControl input, int length) { + return Bindings.createBooleanBinding(() -> new HPacket(input.getText()).getBytesLength() == length, input.textProperty()); + } + + private void fireButtonOnPressEnter(Node node, Button button) { + node.setOnKeyPressed(event -> { + if (event.getCode().equals(KeyCode.ENTER) && !button.isDisable()) + button.fire(); + }); + } + + @FXML + public void onClickEncodeIntegerButton() { + final HPacket packet = new HPacket(ByteBuffer + .allocate(4) + .putInt(Integer.parseInt(decodedIntegerField.getText())) + .array()); + encodedIntegerField.setText(packet.toString()); + } + + @FXML + public void onClickDecodeIntegerButton() { + final HPacket hPacket = new HPacket(encodedIntegerField.getText()); + decodedIntegerField.setText(Integer.toString(hPacket.readInteger(0))); + } + + @FXML + public void onClickEncodeUShortButton() { + final byte[] dst = new byte[2]; + ByteBuffer + .allocate(4) + .putInt(Integer.parseInt(decodedUShortField.getText())) + .get(dst, 2, 2); + final HPacket packet = new HPacket(dst); + encodedUShortField.setText(packet.toString()); + } + + @FXML + public void onClickDecodeUShortButton() { + final HPacket packet = new HPacket(encodedUShortField.getText()); + decodedUShortField.setText(Integer.toString(packet.readUshort(0))); + } + + @FXML + public void onClickPacketToExpressionButton() { + final HPacket packet = parseToPacket(packetArea.getText()); + expressionArea.setText(packet.toExpression(getHConnection().getPacketInfoManager(), true)); + } + + @FXML + public void onClickExpressionToPacketButton() { + final HPacket packet = parseToPacket(expressionArea.getText()); + packetArea.setText(packet.toString()); + } private HPacket parseToPacket(String p) { - PacketInfoManager packetInfoManager = getHConnection().getPacketInfoManager(); - HPacket packet = new HPacket(p); - if (!packet.isPacketComplete() && packetInfoManager != null) { + final PacketInfoManager packetInfoManager = getHConnection().getPacketInfoManager(); + final HPacket packet = new HPacket(p); + if (!packet.isPacketComplete() && packetInfoManager != null) packet.completePacket(packetInfoManager); - } - return packet; } - public void btn_toExpr_clicked(ActionEvent actionEvent) { - txt_exprArea.setText(parseToPacket(txt_packetArea.getText()).toExpression(getHConnection().getPacketInfoManager(), true)); - } - - public void btn_toPacket_clicked(ActionEvent actionEvent) { - txt_packetArea.setText(parseToPacket(txt_exprArea.getText()).toString()); - } - private void initLanguageBinding() { - lbl_integer.textProperty().bind(new TranslatableString("%s:", "tab.tools.type.integer")); - lbl_uShort.textProperty().bind(new TranslatableString("%s:", "tab.tools.type.ushort")); + integerLabel.textProperty().bind(new TranslatableString("%s:", "tab.tools.type.integer")); + uShortLabel.textProperty().bind(new TranslatableString("%s:", "tab.tools.type.ushort")); - TranslatableString encode = new TranslatableString("%s", "tab.tools.button.encode"); - TranslatableString decode = new TranslatableString("%s", "tab.tools.button.decode"); - btnEncodeInt.textProperty().bind(encode); - btnEncodeUShort.textProperty().bind(encode); - btnDecodeInt.textProperty().bind(decode); - btnDecodeUshort.textProperty().bind(decode); + final TranslatableString encode = new TranslatableString("%s", "tab.tools.button.encode"); + final TranslatableString decode = new TranslatableString("%s", "tab.tools.button.decode"); + encodeIntegerButton.textProperty().bind(encode); + encodeUShortButton.textProperty().bind(encode); + decodeIntegerButton.textProperty().bind(decode); + decodeUShortButton.textProperty().bind(decode); - lbl_encodingDecoding.textProperty().bind(new TranslatableString("%s/%s", "tab.tools.encoding", "tab.tools.decoding")); - - lbl_packetToExpression.textProperty().bind(new TranslatableString("%s <-> %s", "tab.tools.packet", "tab.tools.expression")); + encodingOrDecodingLabel.textProperty().bind(new TranslatableString("%s/%s", "tab.tools.encoding", "tab.tools.decoding")); + packetToExpressionLabel.textProperty().bind(new TranslatableString("%s <-> %s", "tab.tools.packet", "tab.tools.expression")); } } diff --git a/G-Earth/src/main/java/gearth/ui/titlebar/TitleBarController.java b/G-Earth/src/main/java/gearth/ui/titlebar/TitleBarController.java index 21186df..aaf44e7 100644 --- a/G-Earth/src/main/java/gearth/ui/titlebar/TitleBarController.java +++ b/G-Earth/src/main/java/gearth/ui/titlebar/TitleBarController.java @@ -1,27 +1,24 @@ package gearth.ui.titlebar; import gearth.GEarth; +import gearth.misc.BindingsUtil; +import gearth.ui.GEarthProperties; import gearth.ui.themes.ThemeFactory; import gearth.ui.translations.Language; import gearth.ui.translations.LanguageBundle; import javafx.application.Platform; -import javafx.beans.InvalidationListener; -import javafx.event.ActionEvent; +import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.*; -import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import javafx.scene.input.ContextMenuEvent; import javafx.scene.input.MouseEvent; import javafx.scene.layout.GridPane; -import javafx.scene.layout.Pane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.stage.Stage; import javafx.stage.StageStyle; -import javafx.stage.WindowEvent; import java.io.IOException; import java.util.Optional; @@ -29,129 +26,127 @@ import java.util.Optional; public class TitleBarController { public Label titleLabel; - public Pane titleBar; public ImageView titleIcon; - public ImageView themeBtn; - public ImageView minimizeBtn; - public MenuButton languagePicker; + public ImageView themeButton; + public ImageView minimizeButton; + public MenuButton languagePickerMenu; private Stage stage; private TitleBarConfig config; private Alert alert = null; + private double xOffset, yOffset; + private boolean isMoving = false; public static TitleBarController create(Stage stage, TitleBarConfig config) throws IOException { - FXMLLoader loader = new FXMLLoader(TitleBarController.class.getResource("Titlebar.fxml")); - Parent titleBar = loader.load(); - TitleBarController controller = initNewController(loader, stage, config); + final FXMLLoader loader = new FXMLLoader(TitleBarController.class.getResource("Titlebar.fxml")); + final Parent titleBar = loader.load(); + final TitleBarController controller = initNewController(loader, stage, config); - VBox newParent = new VBox(titleBar, stage.getScene().getRoot()); + final VBox newParent = new VBox(titleBar, stage.getScene().getRoot()); newParent.setId("titlebar-main-container"); - stage.getScene().setRoot(newParent); + stage.getScene().setRoot(newParent); return controller; } public static TitleBarController create(Alert alert) throws IOException { + GEarth.setAlertOwner(alert); - FXMLLoader loader = new FXMLLoader(TitleBarController.class.getResource("Titlebar.fxml")); - Parent titleBar = loader.load(); - Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + final FXMLLoader loader = new FXMLLoader(TitleBarController.class.getResource("Titlebar.fxml")); + final Parent titleBar = loader.load(); + final Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); - TitleBarConfig config = new GEarthThemedTitleBarConfig(stage) { + final TitleBarConfig config = new GEarthThemedTitleBarConfig(stage) { @Override public boolean displayMinimizeButton() { return false; } }; - TitleBarController controller = initNewController(loader, stage, config); + final TitleBarController controller = initNewController(loader, stage, config); controller.alert = alert; - Parent parent = alert.getDialogPane().getScene().getRoot(); - VBox newParent = new VBox(titleBar, parent); + + final Parent parent = alert.getDialogPane().getScene().getRoot(); + final VBox newParent = new VBox(titleBar, parent); newParent.setId("titlebar-main-container"); + stage.setScene(new Scene(newParent)); stage.getScene().setFill(Color.TRANSPARENT); return controller; } - private static TitleBarController initNewController(FXMLLoader loader, Stage stage, TitleBarConfig config) throws IOException { - TitleBarController controller = loader.getController(); + private static TitleBarController initNewController(FXMLLoader loader, Stage stage, TitleBarConfig config) { - controller.stage = stage; - controller.config = config; stage.initStyle(StageStyle.TRANSPARENT); - stage.titleProperty().addListener((i) -> controller.setTitle(stage.getTitle())); - controller.setTitle(stage.getTitle()); + final TitleBarController controller = loader.getController(); + controller.stage = stage; + controller.config = config; + controller.languagePickerMenu.getItems().setAll(Language.getMenuItems()); + controller.languagePickerMenu.setGraphic(LanguageBundle.getLanguage().getIcon()); - controller.languagePicker.getItems().addAll(Language.getMenuItems()); - controller.languagePicker.setGraphic(LanguageBundle.getLanguage().getIcon()); + BindingsUtil.setAndBind( + controller.titleLabel.textProperty(), + GEarthProperties.themeTitleBinding, + true); - stage.getIcons().addListener((InvalidationListener) observable -> controller.updateIcon()); - controller.updateIcon(); + BindingsUtil.setAndBind( + controller.titleIcon.imageProperty(), + GEarthProperties.logoSmallImageBinding, + true); Platform.runLater(() -> { stage.getScene().setFill(Color.TRANSPARENT); stage.getScene().getRoot().getStyleClass().add("root-node"); if (!config.displayMinimizeButton()) { - ((GridPane) controller.minimizeBtn.getParent()).getChildren().remove(controller.minimizeBtn); + ((GridPane) controller.minimizeButton.getParent()).getChildren().remove(controller.minimizeButton); } if (!config.displayThemePicker()) { - ((GridPane) controller.themeBtn.getParent()).getChildren().remove(controller.themeBtn); - ((GridPane) controller.languagePicker.getParent()).getChildren().remove(controller.languagePicker); + ((GridPane) controller.themeButton.getParent()).getChildren().remove(controller.themeButton); + ((GridPane) controller.languagePickerMenu.getParent()).getChildren().remove(controller.languagePickerMenu); } }); + return controller; } - private static void initLanguagePicker() { - - } - - public void updateIcon() { - Platform.runLater(() -> titleIcon.setImage(stage.getIcons().size() > 0 ? stage.getIcons().get(0) : - new Image(GEarth.class.getResourceAsStream( - String.format("/gearth/ui/themes/%s/logoSmall.png", ThemeFactory.getDefaultTheme().internalName()))))); - } - - public void setTitle(String title) { - Platform.runLater(() -> titleLabel.setText(title)); - } - - public void handleCloseAction(MouseEvent event) { + @FXML + public void onClickCloseButton() { config.onCloseClicked(); } - public void handleMinimizeAction(MouseEvent event) { + @FXML + public void onClickMinimizeButton() { config.onMinimizeClicked(); } - private double xOffset, yOffset; - private boolean isMoving = false; - - public void handleClickAction(MouseEvent event) { + @FXML + public void onClick(MouseEvent event) { xOffset = event.getSceneX(); yOffset = event.getSceneY(); isMoving = true; } - public void handleMovementAction(MouseEvent event) { + @FXML + public void onMovement(MouseEvent event) { if (isMoving) { stage.setX(event.getScreenX() - xOffset); stage.setY(event.getScreenY() - yOffset); } } - public void handleClickReleaseAction(MouseEvent mouseEvent) { + @FXML + public void onPressReleased() { isMoving = false; } - public void toggleTheme(MouseEvent event) { + @FXML + public void toggleTheme() { int themeIndex = ThemeFactory.allThemes().indexOf(config.getCurrentTheme()); config.setTheme(ThemeFactory.allThemes().get((themeIndex + 1) % ThemeFactory.allThemes().size())); } diff --git a/G-Earth/src/main/resources/gearth/ui/subforms/connection/Connection.fxml b/G-Earth/src/main/resources/gearth/ui/subforms/connection/Connection.fxml index 90b708b..4ae2830 100644 --- a/G-Earth/src/main/resources/gearth/ui/subforms/connection/Connection.fxml +++ b/G-Earth/src/main/resources/gearth/ui/subforms/connection/Connection.fxml @@ -45,8 +45,8 @@ -