diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java index 1c1e842d59ad628abd29ea5161016c47d760e788..62ccb3b7e99017263ab8b9fb1618b2644baba4ff 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java @@ -2,6 +2,7 @@ package cz.it4i.fiji.haas_spim_benchmark.ui; import java.awt.Desktop; import java.awt.Window; +import java.awt.event.WindowAdapter; import java.io.IOException; import java.util.EnumSet; import java.util.HashSet; @@ -50,21 +51,21 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont private TableView<ObservableBenchmarkJob> jobs; private final BenchmarkJobManager manager; - + private final ExecutorService executorServiceJobState = Executors.newWorkStealingPool(); - + private final Executor executorServiceFX = new FXFrameExecutorService(); - + private Window root; private ExecutorService executorServiceUI; - + private ExecutorService executorServiceWS; - + private Timer timer; - + private ObservableBenchmarkJobRegistry registry; - + private static Logger log = LoggerFactory .getLogger(cz.it4i.fiji.haas_spim_benchmark.ui.BenchmarkSPIMController.class); @@ -102,7 +103,7 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont private void initMenu() { TableViewContextMenu<ObservableBenchmarkJob> menu = new TableViewContextMenu<>(jobs); - menu.addItem("Create job", x -> executeWSCallAsync("Creating job", p -> manager.createJob()), j -> true); + menu.addItem("Create job", x -> createJob(), j -> true); menu.addItem("Start job", job -> executeWSCallAsync("Starting job", p -> { job.getValue().startJob(p); job.getValue().update(); @@ -112,7 +113,8 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont menu.addItem("Cancel job", job -> executeWSCallAsync("Canceling job", p -> { job.getValue().cancelJob(); job.getValue().update(); - }), job -> JavaFXRoutines.notNullValue(job, j -> j.getState() == JobState.Running || j.getState() == JobState.Queued )); + }), job -> JavaFXRoutines.notNullValue(job, + j -> j.getState() == JobState.Running || j.getState() == JobState.Queued)); menu.addItem("Execution details", job -> { try { @@ -128,14 +130,14 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont job -> executeWSCallAsync("Stop uploading data", p -> job.getValue().stopUpload()), job -> JavaFXRoutines.notNullValue(job, j -> !EnumSet.of(JobState.Running).contains(j.getState())), job -> job.getUploadProgress().isWorking()); - - + menu.addItem("Download result", job -> executeWSCallAsync("Downloading data", p -> job.getValue().startDownload()), job -> executeWSCallAsync("Stop downloading data", p -> job.getValue().stopDownload()), - job -> JavaFXRoutines.notNullValue(job, - j -> EnumSet.of(JobState.Failed, JobState.Finished, JobState.Canceled).contains(j.getState()) - && j.canBeDownloaded()), + job -> JavaFXRoutines + .notNullValue(job, + j -> EnumSet.of(JobState.Failed, JobState.Finished, JobState.Canceled) + .contains(j.getState()) && j.canBeDownloaded()), job -> job.getDownloadProgress().isWorking()); menu.addItem("Download statistics", @@ -148,6 +150,13 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont menu.addItem("Open working directory", j -> open(j.getValue()), x -> JavaFXRoutines.notNullValue(x, j -> true)); } + private void createJob() { + NewJobWindow newJobWindow = new NewJobWindow(null); + ModalDialogs.doModal(newJobWindow, WindowConstants.DISPOSE_ON_CLOSE); + newJobWindow.setCreatePressedNotifier((Runnable) () -> executeWSCallAsync("Creating job", p -> manager.createJob())); + + } + private void open(BenchmarkJob j) { executorServiceUI.execute(() -> { Desktop desktop = Desktop.getDesktop(); @@ -201,7 +210,7 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont } registry.update(); Set<ObservableValue<BenchmarkJob>> actual = new HashSet<>(this.jobs.getItems()); - + executorServiceFX.execute(() -> { for (ObservableBenchmarkJob value : registry.getAllItems()) { if (!actual.contains(value)) { @@ -252,12 +261,10 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont @SuppressWarnings("unchecked") private void setCellValueFactoryCompletable(int index, Function<BenchmarkJob, CompletableFuture<String>> mapper) { JavaFXRoutines.setCellValueFactory(jobs, index, mapper); - ((TableColumn<ObservableBenchmarkJob, CompletableFuture<String>>) jobs.getColumns().get(index)) - .setCellFactory( - column -> new JavaFXRoutines.TableCellAdapter<ObservableBenchmarkJob, CompletableFuture<String>>( - new JavaFXRoutines.FutureValueUpdater<ObservableBenchmarkJob, String, CompletableFuture<String>>( - new JavaFXRoutines.StringValueUpdater<ObservableBenchmarkJob>(), - executorServiceFX))); + ((TableColumn<ObservableBenchmarkJob, CompletableFuture<String>>) jobs.getColumns().get(index)).setCellFactory( + column -> new JavaFXRoutines.TableCellAdapter<ObservableBenchmarkJob, CompletableFuture<String>>( + new JavaFXRoutines.FutureValueUpdater<ObservableBenchmarkJob, String, CompletableFuture<String>>( + new JavaFXRoutines.StringValueUpdater<ObservableBenchmarkJob>(), executorServiceFX))); } private interface P_JobAction { diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobController.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobController.java index 2631710eacb6be38d1be30a8342a7fb9972ba00c..2792549a674af07471f6fed22e0995a5562a9ca6 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobController.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobController.java @@ -1,6 +1,9 @@ package cz.it4i.fiji.haas_spim_benchmark.ui; import java.awt.Window; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -8,36 +11,68 @@ import org.slf4j.LoggerFactory; import cz.it4i.fiji.haas.ui.CloseableControl; import cz.it4i.fiji.haas.ui.InitiableControl; import cz.it4i.fiji.haas.ui.JavaFXRoutines; +import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; +import javafx.scene.Parent; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; +import javafx.scene.control.RadioButton; +import javafx.scene.control.TextField; +import javafx.scene.control.Toggle; +import javafx.scene.control.ToggleGroup; import javafx.scene.layout.BorderPane; public class NewJobController extends BorderPane implements CloseableControl, InitiableControl { + + public enum DataLocation { + DEMONSTRATION_ON_SERVER, WORK_DIRECTORY, CUSTOM_DIRECTORY + } + + private static final Runnable EMPTY_NOTIFIER = () -> {}; + @SuppressWarnings("unused") private static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas_spim_benchmark.ui.NewJobController.class); @FXML - private Button btnCreate; - - private boolean create = false; + private Button bt_create; + + @FXML + private ToggleGroup tg_inputDataLocation; + + @FXML + private ToggleGroup tg_outputDataLocation; + + @FXML + private RadioButton rb_ownInput; + + @FXML + private RadioButton rb_ownOutput; + + @FXML + private TextField et_inputDirectory; + + @FXML + private TextField et_outputDirectory; + + private DataLocation inputDataLocation; + + private DataLocation outputDataLocation; private Window ownerWindow; + private Runnable createPressedNotifier; + public NewJobController() { JavaFXRoutines.initRootAndController("NewJobView.fxml", this); getStylesheets().add(getClass().getResource("NewJobView.css").toExternalForm()); - btnCreate.setOnMouseClicked(X -> createPressed()); - } - - private void createPressed() { - create = true; - ownerWindow.setVisible(false); - ownerWindow.dispose(); + bt_create.setOnMouseClicked(X -> createPressed()); + tg_inputDataLocation.selectedToggleProperty().addListener((v, old, n) -> selected(v, old, n, rb_ownInput)); + tg_outputDataLocation.selectedToggleProperty().addListener((v, o, n) -> selected(v, o, n, rb_ownOutput)); } @Override public void close() { - log.info("close"); } @Override @@ -45,4 +80,78 @@ public class NewJobController extends BorderPane implements CloseableControl, In ownerWindow = parameter; } + public Path getInputDirectory(Path workingDirectory) { + return getDirectory(inputDataLocation, et_inputDirectory.getText(), workingDirectory); + } + + public Path getOutputDirectory(Path workingDirectory) { + return getDirectory(outputDataLocation, et_outputDirectory.getText(), workingDirectory); + } + + public void setCreatePressedNotifier(Runnable createPressedNotifier) { + if(createPressedNotifier != null) { + this.createPressedNotifier = createPressedNotifier; + } else { + this.createPressedNotifier = EMPTY_NOTIFIER; + } + } + + private Path getDirectory(DataLocation dataLocation, String selectedDirectory, Path workingDirectory) { + switch (dataLocation) { + case DEMONSTRATION_ON_SERVER: + return null; + case WORK_DIRECTORY: + return workingDirectory; + case CUSTOM_DIRECTORY: + return Paths.get(selectedDirectory).toAbsolutePath(); + default: + throw new UnsupportedOperationException("Not support " + dataLocation); + } + } + + private void createPressed() { + obtainValues(); + if (checkDirectoryLocationIfNeeded()) { + ownerWindow.setVisible(false); + ownerWindow.dispose(); + createPressedNotifier.run(); + } + } + + private boolean checkDirectoryLocationIfNeeded() { + return checkDataLocationValue(inputDataLocation, et_inputDirectory.getText(), "input") + && checkDataLocationValue(outputDataLocation, et_outputDirectory.getText(), "output"); + + } + + private boolean checkDataLocationValue(DataLocation dataLocation, String directory, String type) { + Path directoryPath = Paths.get(directory); + if (dataLocation == DataLocation.CUSTOM_DIRECTORY && (!Files.exists(directoryPath) || directory.isEmpty())) { + Alert alert = new Alert(AlertType.WARNING); + alert.setTitle("Invalid input provided"); + alert.setHeaderText(null); + String message = !directory.isEmpty() ? "Directory %s for %s not exists" + : "Directory for %2$s is not selected."; + alert.setContentText(String.format(message, directoryPath.toAbsolutePath(), type)); + alert.showAndWait(); + return false; + } + return true; + } + + private void obtainValues() { + inputDataLocation = obtainDataLocation(tg_inputDataLocation); + outputDataLocation = obtainDataLocation(tg_outputDataLocation); + } + + private DataLocation obtainDataLocation(ToggleGroup group) { + int backawardOrderOfSelected = group.getToggles().size() + - group.getToggles().indexOf(group.getSelectedToggle()); + return DataLocation.values()[DataLocation.values().length - backawardOrderOfSelected]; + } + + private void selected(ObservableValue<? extends Toggle> v, Toggle o, Toggle n, Parent disableIfNotSelected) { + disableIfNotSelected.getChildrenUnmodifiable().forEach(node -> node.setDisable(n != disableIfNotSelected)); + } + } diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobView.fxml b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobView.fxml index 41c00072e9e19c9dd0b7309ee1c6237ea065a5aa..5aa539c3f1535446c5be2a6530878adb701dc6f7 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobView.fxml +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobView.fxml @@ -24,22 +24,22 @@ <children> <RadioButton mnemonicParsing="false" selected="true"> <toggleGroup> - <ToggleGroup fx:id="Group" /> + <ToggleGroup fx:id="tg_inputDataLocation" /> </toggleGroup> <graphic> <Label maxHeight="1.7976931348623157E308" text="Demonstration data" /> </graphic> </RadioButton> - <RadioButton maxHeight="1.7976931348623157E308" mnemonicParsing="false" toggleGroup="$Group"> + <RadioButton maxHeight="1.7976931348623157E308" mnemonicParsing="false" toggleGroup="$tg_inputDataLocation"> <graphic> <Label maxHeight="1.7976931348623157E308" text="Working directory" /> </graphic> </RadioButton> - <RadioButton mnemonicParsing="false" toggleGroup="$Group"> + <RadioButton fx:id="rb_ownInput" mnemonicParsing="false" toggleGroup="$tg_inputDataLocation"> <graphic> - <HBox> + <HBox disable="true"> <children> - <TextField /> + <TextField fx:id="et_inputDirectory" /> <Button mnemonicParsing="false" text="Select" /> </children> </HBox> @@ -61,7 +61,7 @@ <children> <RadioButton maxHeight="1.7976931348623157E308" mnemonicParsing="false" selected="true"> <toggleGroup> - <ToggleGroup fx:id="Group1" /> + <ToggleGroup fx:id="tg_outputDataLocation" /> </toggleGroup> <graphic> <Label maxHeight="1.7976931348623157E308" text="Working directory" /> @@ -71,11 +71,11 @@ </HBox> <HBox> <children> - <RadioButton mnemonicParsing="false" toggleGroup="$Group1"> + <RadioButton fx:id="rb_ownOutput" mnemonicParsing="false" toggleGroup="$tg_outputDataLocation"> <graphic> - <HBox> + <HBox disable="true"> <children> - <TextField /> + <TextField fx:id="et_outputDirectory" /> <Button mnemonicParsing="false" text="Select" /> </children> </HBox> @@ -95,7 +95,7 @@ <bottom> <BorderPane BorderPane.alignment="CENTER"> <right> - <Button fx:id="btnCreate" mnemonicParsing="false" prefHeight="22.0" prefWidth="71.0" text="Start" BorderPane.alignment="CENTER"> + <Button fx:id="bt_create" mnemonicParsing="false" prefHeight="22.0" prefWidth="71.0" text="Create" BorderPane.alignment="CENTER"> <BorderPane.margin> <Insets right="3.0" /> </BorderPane.margin></Button> diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobWindow.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobWindow.java index 102f5f432d09503f2baabd0848a76b7cf27ef068..7d62083e06f1ff9712c663c13e2f1a9098805f64 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobWindow.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/NewJobWindow.java @@ -1,7 +1,7 @@ package cz.it4i.fiji.haas_spim_benchmark.ui; import java.awt.Window; -import java.io.IOException; +import java.nio.file.Path; import cz.it4i.fiji.haas.ui.FXFrame; @@ -11,7 +11,7 @@ public class NewJobWindow extends FXFrame<NewJobController>{ - public NewJobWindow(Window parentWindow) throws IOException { + public NewJobWindow(Window parentWindow) { super(parentWindow,()->{ return new NewJobController(); @@ -19,4 +19,16 @@ public class NewJobWindow extends FXFrame<NewJobController>{ setTitle("Create job"); } + public Path getInputDirectory(Path workingDirectory) { + return getFxPanel().getControl().getInputDirectory(workingDirectory); + } + + public Path getOutputDirectory(Path workingDirectory) { + return getFxPanel().getControl().getOutputDirectory(workingDirectory); + } + + + public void setCreatePressedNotifier(Runnable runnable) { + getFxPanel().getControl().setCreatePressedNotifier(runnable); + } } \ No newline at end of file