From bc72aca69ed80458281b205458cf76b4014f95f9 Mon Sep 17 00:00:00 2001 From: 0xb00bface <0xboobface@gmail.com> Date: Fri, 14 May 2021 12:13:48 +0200 Subject: [PATCH] Add more model group relatedfunctionality --- client/src/main/java/ctbrec/ui/Icon.java | 7 +- .../ctbrec/ui/action/AddToGroupAction.java | 1 - .../ctbrec/ui/action/EditGroupAction.java | 16 +++-- .../ctbrec/ui/menu/ModelGroupMenuBuilder.java | 6 +- .../java/ctbrec/ui/tabs/RecordingsTab.java | 45 +++++++------ .../main/java/ctbrec/ui/tabs/ThumbCell.java | 63 +++++++++++++----- .../ui/tabs/recorded/RecordLaterTab.java | 11 ++- .../ui/tabs/recorded/RecordedModelsTab.java | 2 +- .../bookmark-new.png} | Bin .../media-playback-pause.png} | Bin .../media-record.png} | Bin ...AbstractPlaceholderAwarePostProcessor.java | 2 +- 12 files changed, 102 insertions(+), 51 deletions(-) rename client/src/main/resources/{bookmark-new-16.png => 16/bookmark-new.png} (100%) rename client/src/main/resources/{media-playback-pause-16.png => 16/media-playback-pause.png} (100%) rename client/src/main/resources/{media-record-16.png => 16/media-record.png} (100%) diff --git a/client/src/main/java/ctbrec/ui/Icon.java b/client/src/main/java/ctbrec/ui/Icon.java index 22a6788e..42051ff8 100644 --- a/client/src/main/java/ctbrec/ui/Icon.java +++ b/client/src/main/java/ctbrec/ui/Icon.java @@ -3,9 +3,12 @@ package ctbrec.ui; public enum Icon { BLANK_16(Icon.class.getResource("/16/blank.png").toExternalForm()), - GROUP_16(Icon.class.getResource("/16/users.png").toExternalForm()), + BOOKMARK_16(Icon.class.getResource("/16/bookmark-new.png").toExternalForm()), CHECK_16(Icon.class.getResource("/16/check-small.png").toExternalForm()), - CLOCK_16(Icon.class.getResource("/16/clock.png").toExternalForm()); + CLOCK_16(Icon.class.getResource("/16/clock.png").toExternalForm()), + GROUP_16(Icon.class.getResource("/16/users.png").toExternalForm()), + MEDIA_PLAYBACK_PAUSE_16(Icon.class.getResource("/16/media-playback-pause.png").toExternalForm()), + MEDIA_RECORD_16(Icon.class.getResource("/16/media-record.png").toExternalForm()); private String url; diff --git a/client/src/main/java/ctbrec/ui/action/AddToGroupAction.java b/client/src/main/java/ctbrec/ui/action/AddToGroupAction.java index 29ce46d4..f903cf83 100644 --- a/client/src/main/java/ctbrec/ui/action/AddToGroupAction.java +++ b/client/src/main/java/ctbrec/ui/action/AddToGroupAction.java @@ -85,7 +85,6 @@ public class AddToGroupAction { } void requestFocus() { - System.err.println("request focus"); editor.requestFocus(); editor.positionCaret(0); editor.selectAll(); diff --git a/client/src/main/java/ctbrec/ui/action/EditGroupAction.java b/client/src/main/java/ctbrec/ui/action/EditGroupAction.java index 59682185..d082ed50 100644 --- a/client/src/main/java/ctbrec/ui/action/EditGroupAction.java +++ b/client/src/main/java/ctbrec/ui/action/EditGroupAction.java @@ -103,8 +103,9 @@ public class EditGroupAction { groupName = new TextField(modelGroup.getName()); var up = createUpButton(); var down = createDownButton(); + var add = createAddButton(); var remove = createRemoveButton(); - var buttons = new VBox(3, up, down, remove); + var buttons = new VBox(3, up, down, add, remove); urlList = FXCollections.observableList(modelGroup.getModelUrls()); urlList.addListener((ListChangeListener) change -> urls = new ArrayList<>(urlList)); urlListView = new ListView<>(urlList); @@ -126,7 +127,7 @@ public class EditGroupAction { } private Button createUpButton() { - var button = createButton("\u25B4", "Move step up"); + var button = createButton("\u25B4", "Move up"); button.setOnAction(evt -> { int idx = urlListView.getSelectionModel().getSelectedIndex(); String selectedItem = urlListView.getSelectionModel().getSelectedItem(); @@ -138,7 +139,7 @@ public class EditGroupAction { } private Button createDownButton() { - var button = createButton("\u25BE", "Move step down"); + var button = createButton("\u25BE", "Move down"); button.setOnAction(evt -> { int idx = urlListView.getSelectionModel().getSelectedIndex(); String selectedItem = urlListView.getSelectionModel().getSelectedItem(); @@ -149,8 +150,15 @@ public class EditGroupAction { return button; } + private Button createAddButton() { + var button = createButton("+", "Add selected URL"); + button.setDisable(false); + button.setOnAction(evt -> Dialogs.showTextInput(getScene(), "Add URL", "Add new model URL", "").ifPresent(urlList::add)); + return button; + } + private Button createRemoveButton() { - var button = createButton("-", "Remove selected step"); + var button = createButton("-", "Remove selected URL"); button.setOnAction(evt -> { String selectedItem = urlListView.getSelectionModel().getSelectedItem(); if (selectedItem != null) { diff --git a/client/src/main/java/ctbrec/ui/menu/ModelGroupMenuBuilder.java b/client/src/main/java/ctbrec/ui/menu/ModelGroupMenuBuilder.java index 4b8bb240..03307196 100644 --- a/client/src/main/java/ctbrec/ui/menu/ModelGroupMenuBuilder.java +++ b/client/src/main/java/ctbrec/ui/menu/ModelGroupMenuBuilder.java @@ -50,13 +50,13 @@ public class ModelGroupMenuBuilder { var editGroup = new MenuItem("Edit group"); editGroup.setOnAction(e -> new EditGroupAction(source, recorder, model).execute(callback)); - var resumeAllOfGroup = new MenuItem("Resume all"); + var resumeAllOfGroup = new MenuItem("Resume all in group"); resumeAllOfGroup.setOnAction(e -> new ResumeGroupAction(source, recorder, model).execute(callback)); - var pauseAllOfGroup = new MenuItem("Pause all"); + var pauseAllOfGroup = new MenuItem("Pause all in group"); pauseAllOfGroup.setOnAction(e -> new PauseGroupAction(source, recorder, model).execute(callback)); - var stopAllOfGroup = new MenuItem("Remove all"); + var stopAllOfGroup = new MenuItem("Stop all in group"); stopAllOfGroup.setOnAction(e -> new StopGroupAction(source, recorder, model).execute(callback)); menu.getItems().addAll(editGroup, resumeAllOfGroup, pauseAllOfGroup, stopAllOfGroup); diff --git a/client/src/main/java/ctbrec/ui/tabs/RecordingsTab.java b/client/src/main/java/ctbrec/ui/tabs/RecordingsTab.java index 51a5f509..01f45da6 100644 --- a/client/src/main/java/ctbrec/ui/tabs/RecordingsTab.java +++ b/client/src/main/java/ctbrec/ui/tabs/RecordingsTab.java @@ -56,9 +56,9 @@ import ctbrec.ui.controls.CustomMouseBehaviorContextMenu; import ctbrec.ui.controls.DateTimeCellFactory; import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Toast; +import ctbrec.ui.tabs.recorded.RecordedModelsTab.ModelName; import javafx.application.Platform; import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.property.SimpleStringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.concurrent.ScheduledService; @@ -136,10 +136,13 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown table.setEditable(false); table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); - TableColumn name = new TableColumn<>("Model"); + TableColumn name = new TableColumn<>("Model"); name.setId("name"); name.setPrefWidth(200); - name.setCellValueFactory(cdf -> new SimpleStringProperty(cdf.getValue().getModel().getName())); + name.setCellValueFactory(param -> { + var modelName = new ModelName(param.getValue().getModel(), recorder); + return new SimpleObjectProperty<>(modelName); + }); TableColumn date = new TableColumn<>("Date"); date.setId("date"); date.setCellValueFactory(cdf -> { @@ -663,23 +666,27 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown } private void download(Recording recording) { - LOG.debug("Path {}", recording.getAbsoluteFile()); - String filename = proposeTargetFilename(recording); - var chooser = new FileChooser(); - chooser.setInitialFileName(filename); - if (config.getSettings().lastDownloadDir != null && !config.getSettings().lastDownloadDir.equals("")) { - var dir = new File(config.getSettings().lastDownloadDir); - while (!dir.exists()) { - dir = dir.getParentFile(); + try { + LOG.debug("Path {}", recording.getAbsoluteFile()); + String filename = proposeTargetFilename(recording); + var chooser = new FileChooser(); + chooser.setInitialFileName(filename); + if (config.getSettings().lastDownloadDir != null && !config.getSettings().lastDownloadDir.equals("")) { + var dir = new File(config.getSettings().lastDownloadDir); + while (!dir.exists()) { + dir = dir.getParentFile(); + } + chooser.setInitialDirectory(dir); } - chooser.setInitialDirectory(dir); - } - File target = chooser.showSaveDialog(null); - if (target != null) { - config.getSettings().lastDownloadDir = target.getParent(); - startDownloadThread(target, recording); - recording.setStatus(DOWNLOADING); - recording.setProgress(0); + File target = chooser.showSaveDialog(null); + if (target != null) { + config.getSettings().lastDownloadDir = target.getParent(); + startDownloadThread(target, recording); + recording.setStatus(DOWNLOADING); + recording.setProgress(0); + } + } catch (Exception e) { + e.printStackTrace(); } } diff --git a/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java b/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java index 05682868..677cc3b7 100644 --- a/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java +++ b/client/src/main/java/ctbrec/ui/tabs/ThumbCell.java @@ -2,6 +2,7 @@ package ctbrec.ui.tabs; import static ctbrec.Model.State.*; import static ctbrec.io.HttpConstants.*; +import static ctbrec.ui.Icon.*; import java.io.IOException; import java.util.Locale; @@ -10,6 +11,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.function.Function; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,13 +23,14 @@ import com.google.common.cache.LoadingCache; import ctbrec.Config; import ctbrec.GlobalThreadPool; import ctbrec.Model; -import ctbrec.Model.State; import ctbrec.io.HttpException; import ctbrec.recorder.Recorder; import ctbrec.ui.AutosizeAlert; import ctbrec.ui.CamrecApplication; +import ctbrec.ui.Icon; import ctbrec.ui.SiteUiFactory; import ctbrec.ui.StreamSourceSelectionDialog; +import ctbrec.ui.action.EditGroupAction; import ctbrec.ui.action.PlayAction; import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.RecordingIndicator; @@ -47,6 +50,7 @@ import javafx.scene.Cursor; import javafx.scene.Node; import javafx.scene.control.Alert; import javafx.scene.control.ContextMenu; +import javafx.scene.control.Label; import javafx.scene.control.Tooltip; import javafx.scene.image.Image; import javafx.scene.image.ImageView; @@ -72,9 +76,10 @@ public class ThumbCell extends StackPane { private static final Logger LOG = LoggerFactory.getLogger(ThumbCell.class); private static final Duration ANIMATION_DURATION = new Duration(250); - private static Image imgRecordIndicator = new Image(ThumbCell.class.getResource("/media-record-16.png").toExternalForm()); - private static Image imgPauseIndicator = new Image(ThumbCell.class.getResource("/media-playback-pause-16.png").toExternalForm()); - private static Image imgBookmarkIndicator = new Image(ThumbCell.class.getResource("/bookmark-new-16.png").toExternalForm()); + private static Image imgRecordIndicator = new Image(MEDIA_RECORD_16.url()); + private static Image imgPauseIndicator = new Image(MEDIA_PLAYBACK_PAUSE_16.url()); + private static Image imgBookmarkIndicator = new Image(BOOKMARK_16.url()); + private static Image imgGroupIndicator = new Image(Icon.GROUP_16.url()); private ModelRecordingState modelRecordingState = ModelRecordingState.NOT; private Model model; @@ -93,6 +98,8 @@ public class ThumbCell extends StackPane { private RecordingIndicator recordingIndicator; private Tooltip recordingIndicatorTooltip; private StackPane previewTrigger; + private Label groupIndicatorTooltipTrigger; + private ImageView groupIndicator; private int index = 0; ContextMenu popup; private static final Color colorNormal = Color.BLACK; @@ -170,7 +177,7 @@ public class ThumbCell extends StackPane { topic.setFont(new Font("Sansserif", 13)); topic.setTextAlignment(TextAlignment.LEFT); topic.setOpacity(0); - int margin = 4; + var margin = 4; StackPane.setMargin(topic, new Insets(margin)); StackPane.setAlignment(topic, Pos.TOP_CENTER); getChildren().add(topic); @@ -191,6 +198,21 @@ public class ThumbCell extends StackPane { StackPane.setAlignment(recordingIndicator, Pos.TOP_LEFT); getChildren().add(recordingIndicator); + groupIndicator = new ImageView(imgGroupIndicator); + groupIndicator.setVisible(false); + groupIndicatorTooltipTrigger = new Label(); + groupIndicatorTooltipTrigger.setPrefSize(16, 16); + groupIndicatorTooltipTrigger.setMinSize(16, 16); + groupIndicatorTooltipTrigger.visibleProperty().bind(groupIndicator.visibleProperty()); + groupIndicatorTooltipTrigger.setCursor(Cursor.HAND); + groupIndicatorTooltipTrigger.setOnMouseClicked(e -> new EditGroupAction(this, recorder, model).execute()); + StackPane.setMargin(groupIndicatorTooltipTrigger, new Insets(0, 3, 23, 0)); + StackPane.setAlignment(groupIndicatorTooltipTrigger, Pos.BOTTOM_RIGHT); + StackPane.setMargin(groupIndicator, new Insets(0, 3, 23, 0)); + StackPane.setAlignment(groupIndicator, Pos.BOTTOM_RIGHT); + getChildren().add(groupIndicator); + getChildren().add(groupIndicatorTooltipTrigger); + if (Config.getInstance().getSettings().livePreviews) { getChildren().add(createPreviewTrigger()); } @@ -244,18 +266,18 @@ public class ThumbCell extends StackPane { } private Node createPreviewTrigger() { - int s = 32; + var s = 32; previewTrigger = new StackPane(); previewTrigger.setStyle("-fx-background-color: white;"); previewTrigger.setOpacity(.8); previewTrigger.setMaxSize(s, s); - Polygon play = new Polygon(16, 8, 26, 15, 16, 22); + var play = new Polygon(16, 8, 26, 15, 16, 22); StackPane.setMargin(play, new Insets(0, 0, 0, 3)); play.setStyle("-fx-background-color: black;"); previewTrigger.getChildren().add(play); - Circle clip = new Circle(s / 2.0); + var clip = new Circle(s / 2.0); clip.setTranslateX(clip.getRadius()); clip.setTranslateY(clip.getRadius()); previewTrigger.setClip(clip); @@ -336,7 +358,7 @@ public class ThumbCell extends StackPane { final int w = resolution[1]; tagText = w != Integer.MAX_VALUE ? Integer.toString(w) : "HD"; if (w == 0) { - State state = model.getOnlineState(false); + var state = model.getOnlineState(false); tagText = state.name(); if (model.isOnline() && state == ONLINE) { resolutionCache.invalidate(model); @@ -348,7 +370,7 @@ public class ThumbCell extends StackPane { } } } else { - State state = model.getOnlineState(true); + var state = model.getOnlineState(true); if (state != ONLINE) { tagText = state.name(); resolutionBackgroundColor = resolutionOfflineColor; @@ -403,7 +425,7 @@ public class ThumbCell extends StackPane { if (resp.isSuccessful()) { double width = 480; double height = width * imgAspectRatio; - Image img = new Image(resp.body().byteStream(), width, height, preserveAspectRatio.get(), true); + var img = new Image(resp.body().byteStream(), width, height, preserveAspectRatio.get(), true); if (img.progressProperty().get() == 1.0) { Platform.runLater(() -> { iv.setImage(img); @@ -431,13 +453,13 @@ public class ThumbCell extends StackPane { } private Transition changeColor(Shape shape, Color from, Color to) { - FillTransition transition = new FillTransition(ANIMATION_DURATION, from, to); + var transition = new FillTransition(ANIMATION_DURATION, from, to); transition.setShape(shape); return transition; } private Transition changeOpacity(Shape shape, double opacity) { - FadeTransition transition = new FadeTransition(ANIMATION_DURATION, shape); + var transition = new FadeTransition(ANIMATION_DURATION, shape); transition.setFromValue(shape.getOpacity()); transition.setToValue(opacity); return transition; @@ -623,6 +645,12 @@ public class ThumbCell extends StackPane { String txt = (modelRecordingState != ModelRecordingState.NOT) ? " " : ""; txt += model.getDescription() != null ? model.getDescription() : ""; topic.setText(txt); + recorder.getModelGroup(model).ifPresentOrElse(group -> { + var tooltip = group.getName() + ": " + group.getModelUrls().size() + " models:\n"; + tooltip += group.getModelUrls().stream().collect(Collectors.joining("\n")); + groupIndicatorTooltipTrigger.setTooltip(new Tooltip(tooltip)); + groupIndicator.setVisible(true); + }, () -> groupIndicator.setVisible(false)); if (Config.getInstance().getSettings().determineResolution) { updateResolutionTag(); @@ -630,13 +658,14 @@ public class ThumbCell extends StackPane { resolutionBackground.setVisible(false); resolutionTag.setVisible(false); } + requestLayout(); } @Override public int hashCode() { - final int prime = 31; - int result = 1; + final var prime = 31; + var result = 1; result = prime * result + ((model == null) ? 0 : model.hashCode()); return result; } @@ -682,13 +711,13 @@ public class ThumbCell extends StackPane { topicBackground.setHeight(h - nameBackground.getHeight()); topic.prefHeight(getHeight() - 25); topic.maxHeight(getHeight() - 25); - int margin = 4; + var margin = 4; topic.maxWidth(w - margin * 2.0); topic.setWrappingWidth(w - margin * 2.0); streamPreview.resizeTo(w, h); - Rectangle clip = new Rectangle(w, h); + var clip = new Rectangle(w, h); clip.setArcWidth(10); clip.arcHeightProperty().bind(clip.arcWidthProperty()); this.setClip(clip); diff --git a/client/src/main/java/ctbrec/ui/tabs/recorded/RecordLaterTab.java b/client/src/main/java/ctbrec/ui/tabs/recorded/RecordLaterTab.java index f7a2148e..9b73a4fd 100644 --- a/client/src/main/java/ctbrec/ui/tabs/recorded/RecordLaterTab.java +++ b/client/src/main/java/ctbrec/ui/tabs/recorded/RecordLaterTab.java @@ -38,7 +38,9 @@ import ctbrec.ui.controls.SearchBox; import ctbrec.ui.controls.autocomplete.AutoFillTextField; import ctbrec.ui.controls.autocomplete.ObservableListSuggester; import ctbrec.ui.tabs.TabSelectionListener; +import ctbrec.ui.tabs.recorded.RecordedModelsTab.ModelName; import javafx.application.Platform; +import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringPropertyBase; import javafx.collections.FXCollections; @@ -136,10 +138,13 @@ public class RecordLaterTab extends Tab implements TabSelectionListener { if (!Config.getInstance().getSettings().livePreviews) { preview.setVisible(false); } - TableColumn name = new TableColumn<>("Model"); + TableColumn name = new TableColumn<>("Model"); name.setPrefWidth(200); - name.setCellValueFactory(new PropertyValueFactory<>("displayName")); - name.setCellFactory(new ClickableCellFactory<>()); + name.setCellValueFactory(param -> { + var modelName = new ModelName(param.getValue(), recorder); + return new SimpleObjectProperty<>(modelName); + }); + name.setCellFactory(param -> new ModelNameTableCell(recorder)); name.setEditable(false); name.setId("name"); TableColumn url = new TableColumn<>("URL"); diff --git a/client/src/main/java/ctbrec/ui/tabs/recorded/RecordedModelsTab.java b/client/src/main/java/ctbrec/ui/tabs/recorded/RecordedModelsTab.java index da0eba87..dc026e47 100644 --- a/client/src/main/java/ctbrec/ui/tabs/recorded/RecordedModelsTab.java +++ b/client/src/main/java/ctbrec/ui/tabs/recorded/RecordedModelsTab.java @@ -174,7 +174,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener { TableColumn name = new TableColumn<>("Model"); name.setPrefWidth(200); name.setCellValueFactory(param -> { - ModelName modelName = new ModelName(param.getValue(), recorder); + var modelName = new ModelName(param.getValue(), recorder); return new SimpleObjectProperty<>(modelName); }); name.setCellFactory(param -> new ModelNameTableCell(recorder)); diff --git a/client/src/main/resources/bookmark-new-16.png b/client/src/main/resources/16/bookmark-new.png similarity index 100% rename from client/src/main/resources/bookmark-new-16.png rename to client/src/main/resources/16/bookmark-new.png diff --git a/client/src/main/resources/media-playback-pause-16.png b/client/src/main/resources/16/media-playback-pause.png similarity index 100% rename from client/src/main/resources/media-playback-pause-16.png rename to client/src/main/resources/16/media-playback-pause.png diff --git a/client/src/main/resources/media-record-16.png b/client/src/main/resources/16/media-record.png similarity index 100% rename from client/src/main/resources/media-record-16.png rename to client/src/main/resources/16/media-record.png diff --git a/common/src/main/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessor.java b/common/src/main/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessor.java index 91b22142..8081df8a 100644 --- a/common/src/main/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessor.java +++ b/common/src/main/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessor.java @@ -27,7 +27,7 @@ public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPost public String fillInPlaceHolders(String input, PostProcessingContext ctx) { Recording rec = ctx.getRecording(); Config config = ctx.getConfig(); - Optional modelGroup = ctx.getRecorder().getModelGroup(rec.getModel()); + Optional modelGroup = Optional.ofNullable(ctx.getRecorder()).flatMap(r -> r.getModelGroup(rec.getModel())); Map>> placeholderValueSuppliers = new HashMap<>(); placeholderValueSuppliers.put("modelName", r -> ofNullable(rec.getModel().getName()));