package ctbrec.ui.settings; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.util.Optional; import ctbrec.Config; import ctbrec.recorder.postprocessing.Copy; import ctbrec.recorder.postprocessing.DeleteOriginal; import ctbrec.recorder.postprocessing.DeleteTooShort; import ctbrec.recorder.postprocessing.Move; import ctbrec.recorder.postprocessing.PostProcessor; import ctbrec.recorder.postprocessing.RemoveKeepFile; import ctbrec.recorder.postprocessing.Remux; import ctbrec.recorder.postprocessing.Rename; import ctbrec.recorder.postprocessing.Script; import ctbrec.ui.controls.Dialogs; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.scene.control.Button; import javafx.scene.control.ChoiceDialog; import javafx.scene.control.ListView; import javafx.scene.control.Tooltip; import javafx.scene.image.Image; import javafx.scene.layout.GridPane; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class PostProcessingStepPanel extends GridPane { private Config config; private static final Class[] POST_PROCESSOR_CLASSES = new Class[] { // @formatter: off Copy.class, Rename.class, Move.class, Remux.class, Script.class, DeleteOriginal.class, DeleteTooShort.class, RemoveKeepFile.class }; // @formatter: on ListView stepListView; ObservableList stepList; Button up; Button down; Button add; Button remove; Button edit; public PostProcessingStepPanel(Config config) { this.config = config; initGui(); } private void initGui() { setHgap(5); vgapProperty().bind(hgapProperty()); up = createUpButton(); down = createDownButton(); add = createAddButton(); remove = createRemoveButton(); edit = createEditButton(); VBox buttons = new VBox(5, add, edit, up, down, remove); stepList = FXCollections.observableList(config.getSettings().postProcessors); stepList.addListener((ListChangeListener) change -> { try { config.save(); } catch (IOException e) { Dialogs.showError(getScene(), "Couldn't save configuration", "An error occurred while saving the configuration", e); } }); stepListView = new ListView<>(stepList); GridPane.setHgrow(stepListView, Priority.ALWAYS); add(stepListView, 0, 0); add(buttons, 1, 0); stepListView.getSelectionModel().selectedIndexProperty().addListener((obs, oldV, newV) -> { int idx = newV.intValue(); boolean noSelection = idx == -1; up.setDisable(noSelection || idx == 0); down.setDisable(noSelection || idx == stepList.size() - 1); edit.setDisable(noSelection); remove.setDisable(noSelection); }); } private Button createUpButton() { Button up = createButton("\u25B4", "Move step up"); up.setOnAction(evt -> { int idx = stepListView.getSelectionModel().getSelectedIndex(); PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem(); stepList.remove(idx); stepList.add(idx - 1, selectedItem); stepListView.getSelectionModel().select(idx - 1); }); return up; } private Button createDownButton() { Button down = createButton("\u25BE", "Move step down"); down.setOnAction(evt -> { int idx = stepListView.getSelectionModel().getSelectedIndex(); PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem(); stepList.remove(idx); stepList.add(idx + 1, selectedItem); stepListView.getSelectionModel().select(idx + 1); }); return down; } private Button createAddButton() { Button add = createButton("+", "Add a new step"); add.setDisable(false); add.setOnAction(evt -> { PostProcessor[] options = createOptions(); ChoiceDialog choice = new ChoiceDialog<>(options[0], options); choice.setTitle("New Post-Processing Step"); choice.setHeaderText("Select the new step type"); choice.setResizable(true); choice.setWidth(600); choice.getDialogPane().setMinWidth(400); Stage stage = (Stage) choice.getDialogPane().getScene().getWindow(); stage.getScene().getStylesheets().addAll(getScene().getStylesheets()); InputStream icon = Dialogs.class.getResourceAsStream("/icon.png"); stage.getIcons().add(new Image(icon)); Optional result = choice.showAndWait(); result.ifPresent(pp -> PostProcessingDialogFactory.openNewDialog(pp, config, getScene(), stepList)); saveConfig(); }); return add; } private void saveConfig() { try { config.save(); } catch (IOException e) { Dialogs.showError("Post-Processing", "Couldn't save post-processing step", e); } } private PostProcessor[] createOptions() { try { PostProcessor[] options = new PostProcessor[POST_PROCESSOR_CLASSES.length]; for (int i = 0; i < POST_PROCESSOR_CLASSES.length; i++) { Class cls = POST_PROCESSOR_CLASSES[i]; PostProcessor pp; pp = (PostProcessor) cls.getDeclaredConstructor().newInstance(); options[i] = pp; } return options; } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { Dialogs.showError(getScene(), "Create post-processor selection", "Error while reaing in post-processing options", e); return new PostProcessor[0]; } } private Button createRemoveButton() { Button remove = createButton("-", "Remove selected step"); remove.setOnAction(evt -> { PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem(); if (selectedItem != null) { stepList.remove(selectedItem); } }); return remove; } private Button createEditButton() { Button edit = createButton("\u270E", "Edit selected step"); edit.setOnAction(evt -> { PostProcessor selectedItem = stepListView.getSelectionModel().getSelectedItem(); PostProcessingDialogFactory.openEditDialog(selectedItem, config, getScene(), stepList); stepListView.refresh(); saveConfig(); }); return edit; } private Button createButton(String text, String tooltip) { Button b = new Button(text); b.setTooltip(new Tooltip(tooltip)); b.setDisable(true); b.setPrefSize(32, 32); return b; } }