Add more model group relatedfunctionality

This commit is contained in:
0xb00bface 2021-05-14 12:13:48 +02:00
parent bcf4ab1d47
commit bc72aca69e
12 changed files with 102 additions and 51 deletions

View File

@ -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;

View File

@ -85,7 +85,6 @@ public class AddToGroupAction {
}
void requestFocus() {
System.err.println("request focus");
editor.requestFocus();
editor.positionCaret(0);
editor.selectAll();

View File

@ -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<String>) 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) {

View File

@ -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);

View File

@ -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<JavaFxRecording, String> name = new TableColumn<>("Model");
TableColumn<JavaFxRecording, ModelName> 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<JavaFxRecording, Instant> 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();
}
}

View File

@ -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);

View File

@ -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<JavaFxModel, String> name = new TableColumn<>("Model");
TableColumn<JavaFxModel, ModelName> 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<JavaFxModel, String> url = new TableColumn<>("URL");

View File

@ -174,7 +174,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
TableColumn<JavaFxModel, ModelName> 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));

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -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> modelGroup = ctx.getRecorder().getModelGroup(rec.getModel());
Optional<ModelGroup> modelGroup = Optional.ofNullable(ctx.getRecorder()).flatMap(r -> r.getModelGroup(rec.getModel()));
Map<String, Function<String, Optional<String>>> placeholderValueSuppliers = new HashMap<>();
placeholderValueSuppliers.put("modelName", r -> ofNullable(rec.getModel().getName()));