package ctbrec.ui.action; import static ctbrec.SubsequentAction.*; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.concurrent.CompletableFuture; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ctbrec.GlobalThreadPool; import ctbrec.Model; import ctbrec.SubsequentAction; import ctbrec.recorder.Recorder; import ctbrec.ui.controls.DateTimePicker; import ctbrec.ui.controls.Dialogs; import ctbrec.ui.tasks.StartRecordingTask; import javafx.application.Platform; import javafx.geometry.Insets; import javafx.scene.Cursor; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.RadioButton; import javafx.scene.control.ToggleGroup; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; public class SetStopDateAction { private static final Logger LOG = LoggerFactory.getLogger(SetStopDateAction.class); private Node source; private Model model; private Recorder recorder; private RadioButton pauseButton; private DateTimePicker datePicker; public SetStopDateAction(Node source, Model model, Recorder recorder) { this.source = source; this.model = model; this.recorder = recorder; } public CompletableFuture execute() { source.setCursor(Cursor.WAIT); datePicker = new DateTimePicker(); var gridPane = new GridPane(); gridPane.setHgap(10); gridPane.setVgap(10); gridPane.setPadding(new Insets(20, 150, 10, 10)); gridPane.add(new Label("Stop at"), 0, 0); gridPane.add(datePicker, 1, 0); gridPane.add(new Label("And then"), 0, 1); var toggleGroup = new ToggleGroup(); pauseButton = new RadioButton("pause recording"); pauseButton.setSelected(model.getRecordUntilSubsequentAction() == PAUSE); pauseButton.setToggleGroup(toggleGroup); var removeButton = new RadioButton("remove model"); removeButton.setSelected(model.getRecordUntilSubsequentAction() == REMOVE); removeButton.setToggleGroup(toggleGroup); var row = new HBox(); row.getChildren().addAll(pauseButton, removeButton); HBox.setMargin(pauseButton, new Insets(5)); HBox.setMargin(removeButton, new Insets(5)); gridPane.add(row, 1, 1); if (model.isRecordingTimeLimited()) { var localDate = LocalDateTime.ofInstant(model.getRecordUntil(), ZoneId.systemDefault()); datePicker.setDateTimeValue(localDate); } boolean userClickedOk = Dialogs.showCustomInput(source.getScene(), "Stop Recording of " + model.getDisplayName() + " at", gridPane); return createAsyncTask(userClickedOk); } private CompletableFuture createAsyncTask(boolean userClickedOk) { return CompletableFuture.supplyAsync(() -> { if (userClickedOk) { setRecordingTimeLimit(); } return true; }, GlobalThreadPool.get()).whenComplete((r, e) -> { Platform.runLater(() -> source.setCursor(Cursor.DEFAULT)); if (e != null) { LOG.error("Error", e); } }); } private void setRecordingTimeLimit() { SubsequentAction action = pauseButton.isSelected() ? PAUSE : REMOVE; LOG.info("Stop at {} and {}", datePicker.getDateTimeValue(), action); var stopAt = Instant.from(datePicker.getDateTimeValue().atZone(ZoneId.systemDefault())); model.setRecordUntil(stopAt); model.setRecordUntilSubsequentAction(action); try { if (!recorder.isTracked(model) || model.isMarkedForLaterRecording()) { new StartRecordingTask(recorder).executeSync(model) .thenAccept(m -> { try { recorder.stopRecordingAt(m); } catch (InvalidKeyException | NoSuchAlgorithmException | IOException e1) { showError(e1); } }).exceptionally(ex -> { showError(ex); return null; }); } else { recorder.stopRecordingAt(model); } } catch (InvalidKeyException | NoSuchAlgorithmException | IOException e) { showError(e); } } private void showError(Throwable t) { Platform.runLater(() -> Dialogs.showError(source.getScene(), "Error", "Couln't set stop date", t)); } }