diff --git a/client/src/main/java/ctbrec/ui/RecordedModelsTab.java b/client/src/main/java/ctbrec/ui/RecordedModelsTab.java index 130ac211..e53c8bd8 100644 --- a/client/src/main/java/ctbrec/ui/RecordedModelsTab.java +++ b/client/src/main/java/ctbrec/ui/RecordedModelsTab.java @@ -26,6 +26,7 @@ import ctbrec.Recording; import ctbrec.StringUtil; import ctbrec.recorder.Recorder; import ctbrec.sites.Site; +import ctbrec.ui.action.EditNotesAction; import ctbrec.ui.action.FollowAction; import ctbrec.ui.action.PauseAction; import ctbrec.ui.action.PlayAction; @@ -34,6 +35,7 @@ import ctbrec.ui.action.StopRecordingAction; import ctbrec.ui.controls.AutoFillTextField; import ctbrec.ui.controls.SearchBox; import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringPropertyBase; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.concurrent.ScheduledService; @@ -152,7 +154,30 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener { paused.setCellFactory(CheckBoxTableCell.forTableColumn(paused)); paused.setPrefWidth(100); paused.setEditable(true); - table.getColumns().addAll(preview, name, url, online, recording, paused); + TableColumn notes = new TableColumn<>("Notes"); + notes.setCellValueFactory(cdf -> { + JavaFxModel m = cdf.getValue(); + return new StringPropertyBase() { + @Override + public String getName() { + return "Model Notes"; + } + + @Override + public Object getBean() { + return null; + }; + + @Override + public String get() { + String modelNotes = Config.getInstance().getSettings().modelNotes.getOrDefault(m.getUrl(), ""); + return modelNotes; + } + }; + }); + notes.setPrefWidth(400); + notes.setEditable(false); + table.getColumns().addAll(preview, name, url, online, recording, paused, notes); table.setItems(observableModels); table.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> { popup = createContextMenu(); @@ -502,6 +527,8 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener { switchStreamSource.setOnAction((e) -> switchStreamSource(selectedModels.get(0))); MenuItem follow = new MenuItem("Follow"); follow.setOnAction((e) -> follow(selectedModels)); + MenuItem notes = new MenuItem("Notes"); + notes.setOnAction((e) -> notes(selectedModels)); ContextMenu menu = new ContextMenu(stop); if (selectedModels.size() == 1) { @@ -509,13 +536,14 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener { } else { menu.getItems().addAll(resumeRecording, pauseRecording); } - menu.getItems().addAll(copyUrl, openInPlayer, openInBrowser, switchStreamSource, follow); + menu.getItems().addAll(copyUrl, openInPlayer, openInBrowser, switchStreamSource, follow, notes); if (selectedModels.size() > 1) { copyUrl.setDisable(true); openInPlayer.setDisable(true); openInBrowser.setDisable(true); switchStreamSource.setDisable(true); + notes.setDisable(true); } return menu; @@ -525,6 +553,10 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener { new FollowAction(getTabPane(), new ArrayList(selectedModels)).execute(); } + private void notes(ObservableList selectedModels) { + new EditNotesAction(getTabPane(), selectedModels.get(0), table).execute(); + } + private void openInPlayer(JavaFxModel selectedModel) { new PlayAction(getTabPane(), selectedModel).execute(); } diff --git a/client/src/main/java/ctbrec/ui/action/EditNotesAction.java b/client/src/main/java/ctbrec/ui/action/EditNotesAction.java new file mode 100644 index 00000000..5358ea3c --- /dev/null +++ b/client/src/main/java/ctbrec/ui/action/EditNotesAction.java @@ -0,0 +1,38 @@ +package ctbrec.ui.action; + +import java.util.Optional; + +import ctbrec.Config; +import ctbrec.Model; +import ctbrec.ui.JavaFxModel; +import ctbrec.ui.controls.Dialogs; +import javafx.application.Platform; +import javafx.scene.Cursor; +import javafx.scene.Node; +import javafx.scene.control.TableView; + +public class EditNotesAction { + + private Node source; + private Model model; + private TableView table; + + public EditNotesAction(Node source, Model selectedModel, TableView table) { + this.source = source; + this.model = selectedModel; + this.table = table; + } + + public void execute() { + source.setCursor(Cursor.WAIT); + new Thread(() -> { + Platform.runLater(() -> { + String notes = Config.getInstance().getSettings().modelNotes.getOrDefault(model.getUrl(), ""); + Optional newNotes = Dialogs.showTextInput("Model Notes", "Notes for " + model.getName(), notes); + newNotes.ifPresent(n -> Config.getInstance().getSettings().modelNotes.put(model.getUrl(), n)); + table.refresh(); + source.setCursor(Cursor.DEFAULT); + }); + }).start(); + } +} diff --git a/client/src/main/java/ctbrec/ui/controls/Dialogs.java b/client/src/main/java/ctbrec/ui/controls/Dialogs.java index 653bbc91..8d411927 100644 --- a/client/src/main/java/ctbrec/ui/controls/Dialogs.java +++ b/client/src/main/java/ctbrec/ui/controls/Dialogs.java @@ -1,8 +1,19 @@ package ctbrec.ui.controls; +import java.io.InputStream; +import java.util.Optional; + import ctbrec.ui.AutosizeAlert; import javafx.application.Platform; +import javafx.geometry.Insets; import javafx.scene.control.Alert; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Dialog; +import javafx.scene.control.TextArea; +import javafx.scene.image.Image; +import javafx.scene.layout.GridPane; +import javafx.stage.Modality; +import javafx.stage.Stage; public class Dialogs { public static void showError(String header, String text, Throwable t) { @@ -24,4 +35,37 @@ public class Dialogs { Platform.runLater(r); } } + + public static Optional showTextInput(String title, String header, String text) { + Dialog dialog = new Dialog<>(); + dialog.setTitle(title); + dialog.setHeaderText(header); + dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); + dialog.initModality(Modality.APPLICATION_MODAL); + dialog.setResizable(true); + InputStream icon = Dialogs.class.getResourceAsStream("/icon.png"); + Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image(icon)); + + GridPane grid = new GridPane(); + grid.setHgap(10); + grid.setVgap(10); + grid.setPadding(new Insets(20, 150, 10, 10)); + + TextArea notes = new TextArea(text); + notes.setPrefRowCount(3); + grid.add(notes, 0, 0); + dialog.getDialogPane().setContent(grid); + + Platform.runLater(() -> notes.requestFocus()); + + dialog.setResultConverter(dialogButton -> { + if (dialogButton == ButtonType.OK) { + return notes.getText(); + } + return null; + }); + + return dialog.showAndWait(); + } } diff --git a/common/src/main/java/ctbrec/Settings.java b/common/src/main/java/ctbrec/Settings.java index 03229332..9378ed15 100644 --- a/common/src/main/java/ctbrec/Settings.java +++ b/common/src/main/java/ctbrec/Settings.java @@ -2,7 +2,9 @@ package ctbrec; import java.io.File; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import ctbrec.event.EventHandlerConfiguration; @@ -109,4 +111,5 @@ public class Settings { public String recordingsSortType = ""; public double[] recordingsColumnWidths = new double[0]; public boolean generatePlaylist = true; + public Map modelNotes = new HashMap<>(); }