diff --git a/src/main/extensions/Extension.java b/src/main/extensions/Extension.java index 3acf65c..0c3a22b 100644 --- a/src/main/extensions/Extension.java +++ b/src/main/extensions/Extension.java @@ -121,7 +121,7 @@ public abstract class Extension { .appendString(info.Version()) .appendString(info.Description()) .appendBoolean(isOnClickMethodUsed()) - .appendBoolean(file == null) + .appendBoolean(file != null) .appendString(file == null ? "": file) .appendBoolean(CANLEAVE) .appendBoolean(CANDELETE); diff --git a/src/main/misc/ConfirmationDialog.java b/src/main/misc/ConfirmationDialog.java index e2e2415..cc75890 100644 --- a/src/main/misc/ConfirmationDialog.java +++ b/src/main/misc/ConfirmationDialog.java @@ -1,7 +1,50 @@ package main.misc; +import javafx.scene.Group; +import javafx.scene.Node; +import javafx.scene.control.Alert; +import javafx.scene.control.ButtonType; +import javafx.scene.control.CheckBox; +import javafx.scene.control.DialogPane; + /** * Created by Jonas on 27/09/18. */ public class ConfirmationDialog { + + public static boolean showDialog = true; + + public static Alert createAlertWithOptOut(Alert.AlertType type, String title, String headerText, + String message, String optOutMessage, /*Callback optOutAction,*/ + ButtonType... buttonTypes) { + Alert alert = new Alert(type); + // Need to force the alert to layout in order to grab the graphic, + // as we are replacing the dialog pane with a custom pane + alert.getDialogPane().applyCss(); + Node graphic = alert.getDialogPane().getGraphic(); + // Create a new dialog pane that has a checkbox instead of the hide/show details button + // Use the supplied callback for the action of the checkbox + alert.setDialogPane(new DialogPane() { + @Override + protected Node createDetailsButton() { + CheckBox optOut = new CheckBox(); + optOut.setText(optOutMessage); + optOut.setOnAction(event -> showDialog = !optOut.isSelected()); + return optOut; + } + }); + alert.getDialogPane().getButtonTypes().addAll(buttonTypes); + alert.getDialogPane().setContentText(message); + // Fool the dialog into thinking there is some expandable content + // a Group won't take up any space if it has no children + alert.getDialogPane().setExpandableContent(new Group()); + alert.getDialogPane().setExpanded(true); + // Reset the dialog graphic using the default style + alert.getDialogPane().setGraphic(graphic); + alert.setTitle(title); + alert.setHeaderText(headerText); + return alert; + } + + } diff --git a/src/main/ui/extensions/ExtensionItemContainer.java b/src/main/ui/extensions/ExtensionItemContainer.java index 55396a6..820ab7e 100644 --- a/src/main/ui/extensions/ExtensionItemContainer.java +++ b/src/main/ui/extensions/ExtensionItemContainer.java @@ -1,34 +1,53 @@ package main.ui.extensions; +import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.geometry.Pos; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.Tooltip; +import javafx.scene.control.*; import javafx.scene.input.MouseEvent; import javafx.scene.layout.*; +import javafx.scene.paint.Paint; import javafx.scene.text.Font; +import main.extensions.Extension; +import main.misc.ConfirmationDialog; import main.ui.buttons.*; +import main.ui.extensions.executer.ExecutionInfo; +import main.ui.extensions.executer.ExtensionRunner; +import main.ui.extensions.executer.ExtensionRunnerFactory; +import main.ui.extensions.executer.NormalExtensionRunner; import main.ui.scheduler.ScheduleItem; +import javax.tools.Tool; +import java.nio.file.Path; +import java.nio.file.Paths; + /** * Created by Jonas on 19/07/18. */ public class ExtensionItemContainer extends GridPane { public static final int[] columnWidths = {22, 34, 18, 13, 11}; - GEarthExtension item; + private GEarthExtension item; - Label titleLabel; - Label descriptionLabel; - Label authorLabel; - Label versionLabel; + private Label titleLabel; + private Label descriptionLabel; + private Label authorLabel; + private Label versionLabel; - VBox parent; + private VBox parent; - ExtensionItemContainer(GEarthExtension item, VBox parent, ScrollPane scrollPane) { + private volatile int port; + + private HBox buttonsBox = null; + private HBox additionalButtonBox = null; + + private ExitButton exitButton; + private SimpleClickButton clickButton; + private ReloadButton reloadButton; + + ExtensionItemContainer(GEarthExtension item, VBox parent, ScrollPane scrollPane, int port) { super(); + this.port = port; setGridLinesVisible(true); VBox.setMargin(this, new Insets(2, -2, -2, -2)); @@ -60,29 +79,72 @@ public class ExtensionItemContainer extends GridPane { add(authorLabel, 2, 0); add(versionLabel, 3, 0); - ExitButton exitButton = new ExitButton(); + exitButton = new ExitButton(); Tooltip delete = new Tooltip("Close connection with this extension"); Tooltip.install(exitButton,delete); exitButton.show(); exitButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> item.isRemoveClickTrigger()); - SimpleClickButton clickButton = new SimpleClickButton(); + clickButton = new SimpleClickButton(); clickButton.show(); clickButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> item.isClickTrigger()); - HBox buttonsBox = new HBox(clickButton, exitButton); + buttonsBox = new HBox(clickButton, exitButton); + + reloadButton = new ReloadButton(); + Tooltip reload = new Tooltip("Restart this extension"); + Tooltip.install(reloadButton, reload); + reloadButton.show(); + reloadButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { + reloadButton.setVisible(false); + ExtensionRunner runner = ExtensionRunnerFactory.get(); + runner.tryRunExtension(Paths.get(NormalExtensionRunner.JARPATH, ExecutionInfo.EXTENSIONSDIRECTORY, item.getFileName()).toString(), port); + }); + + DeleteButton deleteButton = new DeleteButton(); + Tooltip uninstall = new Tooltip("Uninstall this extension"); + Tooltip.install(deleteButton, uninstall); + deleteButton.show(); + GridPane this2 = this; + deleteButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { + boolean delet_dis = true; + + if (ConfirmationDialog.showDialog) { + Alert alert = ConfirmationDialog.createAlertWithOptOut(Alert.AlertType.CONFIRMATION, + "Confirmation Dialog", null, + "Are you sure want to uninstall this extension?", "Do not ask again", + ButtonType.YES, ButtonType.NO + ); + + if (!(alert.showAndWait().filter(t -> t == ButtonType.YES).isPresent())) { + delet_dis = false; + } + } + + if (delet_dis) { + ExtensionRunner runner = ExtensionRunnerFactory.get(); + runner.uninstallExtension(item.getFileName()); + parent.getChildren().remove(this2); + } + }); + + additionalButtonBox = new HBox(reloadButton, deleteButton); clickButton.setVisible(item.isFireButtonUsed()); exitButton.setVisible(item.isLeaveButtonVisible()); + deleteButton.setVisible(item.isDeleteButtonVisible()); + buttonsBox.setSpacing(8); buttonsBox.setAlignment(Pos.CENTER); + additionalButtonBox.setSpacing(8); + additionalButtonBox.setAlignment(Pos.CENTER); + GridPane.setMargin(buttonsBox, new Insets(0, 5, 0, 5)); + GridPane.setMargin(additionalButtonBox, new Insets(0, 5, 0, 5)); add(buttonsBox, 4, 0); parent.getChildren().add(this); - - GridPane this2 = this; - item.onDelete(observable -> parent.getChildren().remove(this2)); + initExtension(); } private Label initNewLabelColumn(String text) { @@ -92,4 +154,51 @@ public class ExtensionItemContainer extends GridPane { label.setText(text); return label; } + + private EventHandler onExit = null; + private EventHandler onClick = null; + + void initExtension(){ + if (onExit != null) { + exitButton.removeEventHandler(MouseEvent.MOUSE_CLICKED, onExit); + clickButton.removeEventHandler(MouseEvent.MOUSE_CLICKED, onClick); + } + onExit = event -> item.isRemoveClickTrigger(); + onClick = event -> item.isClickTrigger(); + + exitButton.addEventHandler(MouseEvent.MOUSE_CLICKED, onExit); + clickButton.addEventHandler(MouseEvent.MOUSE_CLICKED, onClick); + + ExtensionItemContainer this2 = this; + item.onDelete(observable -> { + if (item.isInstalledExtension()) { + setBackground(new Background(new BackgroundFill(Paint.valueOf("#cccccc"),null, null))); + getChildren().remove(buttonsBox); + add(additionalButtonBox, 4, 0); + reloadButton.setVisible(true); + } + else { + parent.getChildren().remove(this2); + } + }); + } + + void hasReconnected(GEarthExtension extension) { + item = extension; + initExtension(); + + setBackground(new Background(new BackgroundFill(Paint.valueOf("#ffffff"),null, null))); + getChildren().remove(additionalButtonBox); + if (buttonsBox != null) { + add(buttonsBox, 4, 0); + } + } + + //returns null if there is none + String getExtensionFileName() { + if (item.isInstalledExtension()) { + return item.getFileName(); + } + return null; + } } diff --git a/src/main/ui/extensions/ExtensionItemContainerProducer.java b/src/main/ui/extensions/ExtensionItemContainerProducer.java index afd0b32..ba3a9f4 100644 --- a/src/main/ui/extensions/ExtensionItemContainerProducer.java +++ b/src/main/ui/extensions/ExtensionItemContainerProducer.java @@ -1,5 +1,6 @@ package main.ui.extensions; +import javafx.scene.Node; import javafx.scene.control.ScrollPane; import javafx.scene.layout.VBox; @@ -11,11 +12,34 @@ public class ExtensionItemContainerProducer { private VBox parent; private ScrollPane scrollPane; + private final Object lock = new Object(); + private int port = -1; + public ExtensionItemContainerProducer(VBox parent, ScrollPane scrollPane) { this.parent = parent; this.scrollPane = scrollPane; } + void extensionConnected(GEarthExtension extension) { + synchronized (lock) { + if (extension.isInstalledExtension()) { + for (Node n : parent.getChildren()) { + if (n instanceof ExtensionItemContainer) { + ExtensionItemContainer container = (ExtensionItemContainer) n; + if (container.getExtensionFileName().equals(extension.getFileName())) { + container.hasReconnected(extension); + return; + } + } + } + } + new ExtensionItemContainer(extension, parent, scrollPane, port); + } + } + + void setPort(int port) { + this.port = port; + } } diff --git a/src/main/ui/extensions/Extensions.java b/src/main/ui/extensions/Extensions.java index 336ef03..c70ef01 100644 --- a/src/main/ui/extensions/Extensions.java +++ b/src/main/ui/extensions/Extensions.java @@ -150,7 +150,7 @@ public class Extensions extends SubForm { } protected void onParentSet() { - + ExtensionItemContainerProducer producer = new ExtensionItemContainerProducer(extensioncontainer, scroller); getHConnection().addStateChangeListener((oldState, newState) -> { if (newState == HConnection.State.CONNECTED) { @@ -272,7 +272,7 @@ public class Extensions extends SubForm { if (getHConnection().getState() == HConnection.State.CONNECTED) { extension.sendMessage(new HPacket(OUTGOING_MESSAGES_IDS.CONNECTIONSTART)); } - Platform.runLater(() -> new ExtensionItemContainer(extension, extensioncontainer, scroller)); + Platform.runLater(() -> producer.extensionConnected(extension)); extension.onRemoveClick(observable -> { try { extension.getConnection().close(); @@ -298,6 +298,7 @@ public class Extensions extends SubForm { e.printStackTrace(); } + producer.setPort(extensionsRegistrer.getPort()); ext_port.setText(extensionsRegistrer.getPort()+""); // System.out.println("Extension server registered on port: " + extensionsRegistrer.getPort()); diff --git a/src/main/ui/extensions/executer/ExtensionRunner.java b/src/main/ui/extensions/executer/ExtensionRunner.java index 2ae533a..9489895 100644 --- a/src/main/ui/extensions/executer/ExtensionRunner.java +++ b/src/main/ui/extensions/executer/ExtensionRunner.java @@ -15,4 +15,7 @@ public interface ExtensionRunner { void installAndRunExtension(String path, int port); + void tryRunExtension(String path, int port); + + void uninstallExtension(String path); } diff --git a/src/main/ui/extensions/executer/NormalExtensionRunner.java b/src/main/ui/extensions/executer/NormalExtensionRunner.java index b825a93..dbec268 100644 --- a/src/main/ui/extensions/executer/NormalExtensionRunner.java +++ b/src/main/ui/extensions/executer/NormalExtensionRunner.java @@ -13,13 +13,13 @@ import java.util.Random; */ public class NormalExtensionRunner implements ExtensionRunner { - String jarPath = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParent(); + public static final String JARPATH = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParent(); @Override public void runAllExtensions(int port) { if (dirExists(ExecutionInfo.EXTENSIONSDIRECTORY)){ File folder = - new File(jarPath + + new File(JARPATH + FileSystems.getDefault().getSeparator()+ ExecutionInfo.EXTENSIONSDIRECTORY); @@ -47,7 +47,7 @@ public class NormalExtensionRunner implements ExtensionRunner { Path originalPath = Paths.get(path); Path newPath = Paths.get( - jarPath, + JARPATH, ExecutionInfo.EXTENSIONSDIRECTORY, newname ); @@ -81,6 +81,19 @@ public class NormalExtensionRunner implements ExtensionRunner { } } + @Override + public void uninstallExtension(String filename) { + try { + Files.delete(Paths.get( + JARPATH, + ExecutionInfo.EXTENSIONSDIRECTORY, + filename + )); + } catch (IOException e) { + e.printStackTrace(); + } + } + private void addExecPermission(String path) { //not needed at first sight } @@ -92,12 +105,12 @@ public class NormalExtensionRunner implements ExtensionRunner { } private boolean dirExists(String dir) { - return Files.isDirectory(Paths.get(jarPath, dir)); + return Files.isDirectory(Paths.get(JARPATH, dir)); } private void createDirectory(String dir) { if (!dirExists(dir)) { try { - Files.createDirectories(Paths.get(jarPath, dir)); + Files.createDirectories(Paths.get(JARPATH, dir)); } catch (IOException e) { e.printStackTrace(); }