Remove Live Previews
This commit is contained in:
parent
97c6d5d915
commit
303ca2c9e5
|
@ -1,190 +0,0 @@
|
||||||
package ctbrec.ui;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
|
||||||
import ctbrec.ui.controls.StreamPreview;
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.event.EventHandler;
|
|
||||||
import javafx.geometry.Insets;
|
|
||||||
import javafx.geometry.Point2D;
|
|
||||||
import javafx.scene.Node;
|
|
||||||
import javafx.scene.control.TableColumn;
|
|
||||||
import javafx.scene.control.TableRow;
|
|
||||||
import javafx.scene.control.TableView;
|
|
||||||
import javafx.scene.input.MouseButton;
|
|
||||||
import javafx.scene.input.MouseEvent;
|
|
||||||
import javafx.scene.layout.StackPane;
|
|
||||||
import javafx.stage.Popup;
|
|
||||||
|
|
||||||
public class PreviewPopupHandler implements EventHandler<MouseEvent> {
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(PreviewPopupHandler.class);
|
|
||||||
|
|
||||||
private static final int offset = 10;
|
|
||||||
private long timeForPopupOpen = TimeUnit.SECONDS.toMillis(1);
|
|
||||||
private long timeForPopupClose = 400;
|
|
||||||
private Popup popup = new Popup();
|
|
||||||
private Node parent;
|
|
||||||
private StreamPreview streamPreview;
|
|
||||||
private JavaFxModel model;
|
|
||||||
private volatile long openCountdown = -1;
|
|
||||||
private volatile long closeCountdown = -1;
|
|
||||||
private volatile long lastModelChange = -1;
|
|
||||||
private volatile boolean changeModel = false;
|
|
||||||
|
|
||||||
public PreviewPopupHandler(Node parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
|
|
||||||
streamPreview = new StreamPreview();
|
|
||||||
streamPreview.setStyle("-fx-background-color: -fx-outer-border, -fx-inner-border, -fx-base;"+
|
|
||||||
"-fx-background-insets: 0 0 -1 0, 0, 1, 2;" +
|
|
||||||
"-fx-background-radius: 10px, 10px, 10px, 10px;" +
|
|
||||||
"-fx-padding: 1;" +
|
|
||||||
"-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.8), 20, 0, 0, 0);");
|
|
||||||
popup.getContent().add(streamPreview);
|
|
||||||
StackPane.setMargin(streamPreview, new Insets(5));
|
|
||||||
|
|
||||||
createTimerThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(MouseEvent event) {
|
|
||||||
if(!isInPreviewColumn(event) || !Config.getInstance().getSettings().livePreviews) {
|
|
||||||
closeCountdown = timeForPopupClose;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(event.getEventType() == MouseEvent.MOUSE_CLICKED && event.getButton() == MouseButton.PRIMARY) {
|
|
||||||
model = getModel(event);
|
|
||||||
popup.setX(event.getScreenX()+ offset);
|
|
||||||
popup.setY(event.getScreenY()+ offset);
|
|
||||||
showPopup();
|
|
||||||
openCountdown = -1;
|
|
||||||
} else if(event.getEventType() == MouseEvent.MOUSE_ENTERED) {
|
|
||||||
popup.setX(event.getScreenX()+ offset);
|
|
||||||
popup.setY(event.getScreenY()+ offset);
|
|
||||||
JavaFxModel newModel = getModel(event);
|
|
||||||
if(newModel != null) {
|
|
||||||
closeCountdown = -1;
|
|
||||||
boolean modelChanged = newModel != this.model;
|
|
||||||
this.model = newModel;
|
|
||||||
if(popup.isShowing()) {
|
|
||||||
openCountdown = -1;
|
|
||||||
if(modelChanged) {
|
|
||||||
lastModelChange = System.currentTimeMillis();
|
|
||||||
changeModel = true;
|
|
||||||
streamPreview.stop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
openCountdown = timeForPopupOpen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(event.getEventType() == MouseEvent.MOUSE_EXITED) {
|
|
||||||
openCountdown = -1;
|
|
||||||
closeCountdown = timeForPopupClose;
|
|
||||||
model = null;
|
|
||||||
} else if(event.getEventType() == MouseEvent.MOUSE_MOVED) {
|
|
||||||
popup.setX(event.getScreenX() + offset);
|
|
||||||
popup.setY(event.getScreenY() + offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInPreviewColumn(MouseEvent event) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
TableRow<JavaFxModel> row = (TableRow<JavaFxModel>) event.getSource();
|
|
||||||
TableView<JavaFxModel> table = row.getTableView();
|
|
||||||
double columnOffset = 0;
|
|
||||||
double width = 0;
|
|
||||||
for (TableColumn<JavaFxModel, ?> col : table.getColumns()) {
|
|
||||||
columnOffset += width;
|
|
||||||
width = col.getWidth();
|
|
||||||
if(Objects.equals(col.getId(), "preview")) {
|
|
||||||
Point2D screenToLocal = table.screenToLocal(event.getScreenX(), event.getScreenY());
|
|
||||||
double x = screenToLocal.getX();
|
|
||||||
return x >= columnOffset && x <= columnOffset + width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JavaFxModel getModel(MouseEvent event) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
TableRow<JavaFxModel> row = (TableRow<JavaFxModel>) event.getSource();
|
|
||||||
TableView<JavaFxModel> table = row.getTableView();
|
|
||||||
int rowIndex = row.getIndex();
|
|
||||||
if(rowIndex < table.getItems().size()) {
|
|
||||||
return table.getItems().get(rowIndex);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showPopup() {
|
|
||||||
startStream(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startStream(JavaFxModel model) {
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
streamPreview.startStream(model);
|
|
||||||
popup.show(parent.getScene().getWindow());
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hidePopup() {
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
popup.setX(-1000);
|
|
||||||
popup.setY(-1000);
|
|
||||||
popup.hide();
|
|
||||||
streamPreview.stop();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createTimerThread() {
|
|
||||||
Thread timerThread = new Thread(() -> {
|
|
||||||
while(true) {
|
|
||||||
openCountdown--;
|
|
||||||
if(openCountdown == 0) {
|
|
||||||
openCountdown = -1;
|
|
||||||
if(model != null) {
|
|
||||||
showPopup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closeCountdown--;
|
|
||||||
if(closeCountdown == 0) {
|
|
||||||
hidePopup();
|
|
||||||
closeCountdown = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
openCountdown = Math.max(openCountdown, -1);
|
|
||||||
closeCountdown = Math.max(closeCountdown, -1);
|
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
long diff = (now - lastModelChange);
|
|
||||||
if(changeModel && diff > 400) {
|
|
||||||
changeModel = false;
|
|
||||||
if(model != null) {
|
|
||||||
startStream(model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Thread.sleep(100);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
LOG.error("PreviewPopupTimer interrupted");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
timerThread.setDaemon(true);
|
|
||||||
timerThread.setPriority(Thread.MIN_PRIORITY);
|
|
||||||
timerThread.setName("PreviewPopupTimer");
|
|
||||||
timerThread.start();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -72,7 +72,6 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
||||||
private SimpleBooleanProperty determineResolution;
|
private SimpleBooleanProperty determineResolution;
|
||||||
private SimpleBooleanProperty chooseStreamQuality;
|
private SimpleBooleanProperty chooseStreamQuality;
|
||||||
private SimpleBooleanProperty confirmationDialogs;
|
private SimpleBooleanProperty confirmationDialogs;
|
||||||
private SimpleBooleanProperty livePreviews;
|
|
||||||
private SimpleBooleanProperty monitorClipboard;
|
private SimpleBooleanProperty monitorClipboard;
|
||||||
private SimpleListProperty<String> startTab;
|
private SimpleListProperty<String> startTab;
|
||||||
private SimpleFileProperty mediaPlayer;
|
private SimpleFileProperty mediaPlayer;
|
||||||
|
@ -162,7 +161,6 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
||||||
updateThumbnails = new SimpleBooleanProperty(null, "updateThumbnails", settings.updateThumbnails);
|
updateThumbnails = new SimpleBooleanProperty(null, "updateThumbnails", settings.updateThumbnails);
|
||||||
determineResolution = new SimpleBooleanProperty(null, "determineResolution", settings.determineResolution);
|
determineResolution = new SimpleBooleanProperty(null, "determineResolution", settings.determineResolution);
|
||||||
chooseStreamQuality = new SimpleBooleanProperty(null, "chooseStreamQuality", settings.chooseStreamQuality);
|
chooseStreamQuality = new SimpleBooleanProperty(null, "chooseStreamQuality", settings.chooseStreamQuality);
|
||||||
livePreviews = new SimpleBooleanProperty(null, "livePreviews", settings.livePreviews);
|
|
||||||
monitorClipboard = new SimpleBooleanProperty(null, "monitorClipboard", settings.monitorClipboard);
|
monitorClipboard = new SimpleBooleanProperty(null, "monitorClipboard", settings.monitorClipboard);
|
||||||
startTab = new SimpleListProperty<>(null, "startTab", FXCollections.observableList(getTabNames()));
|
startTab = new SimpleListProperty<>(null, "startTab", FXCollections.observableList(getTabNames()));
|
||||||
mediaPlayer = new SimpleFileProperty(null, "mediaPlayer", settings.mediaPlayer);
|
mediaPlayer = new SimpleFileProperty(null, "mediaPlayer", settings.mediaPlayer);
|
||||||
|
@ -253,7 +251,6 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
||||||
"The overviews will still be updated, but the thumbnails won't be changed. This is useful for less powerful systems."),
|
"The overviews will still be updated, but the thumbnails won't be changed. This is useful for less powerful systems."),
|
||||||
Setting.of("Thumbnails cache size", new CacheSettingsPane(this, config)).needsRestart(),
|
Setting.of("Thumbnails cache size", new CacheSettingsPane(this, config)).needsRestart(),
|
||||||
Setting.of("Manually select stream quality", chooseStreamQuality, "Opens a dialog to select the video resolution before recording"),
|
Setting.of("Manually select stream quality", chooseStreamQuality, "Opens a dialog to select the video resolution before recording"),
|
||||||
Setting.of("Enable live previews (experimental)", livePreviews),
|
|
||||||
Setting.of("Enable recently watched tab", recentlyWatched).needsRestart(),
|
Setting.of("Enable recently watched tab", recentlyWatched).needsRestart(),
|
||||||
Setting.of("Minimize to tray", minimizeToTray, "Removes the app from the task bar, if minimized"),
|
Setting.of("Minimize to tray", minimizeToTray, "Removes the app from the task bar, if minimized"),
|
||||||
Setting.of("Start minimized", startMinimized, "Start the app minimized to the tray, automatically activates \"Minimize to tray\""),
|
Setting.of("Start minimized", startMinimized, "Start the app minimized to the tray, automatically activates \"Minimize to tray\""),
|
||||||
|
|
|
@ -219,10 +219,6 @@ public class ThumbCell extends StackPane {
|
||||||
StackPane.setAlignment(groupIndicator, Pos.BOTTOM_RIGHT);
|
StackPane.setAlignment(groupIndicator, Pos.BOTTOM_RIGHT);
|
||||||
getChildren().add(groupIndicator);
|
getChildren().add(groupIndicator);
|
||||||
|
|
||||||
if (Config.getInstance().getSettings().livePreviews) {
|
|
||||||
getChildren().add(createPreviewTrigger());
|
|
||||||
}
|
|
||||||
|
|
||||||
selectionOverlay = new Rectangle();
|
selectionOverlay = new Rectangle();
|
||||||
selectionOverlay.visibleProperty().bind(selectionProperty);
|
selectionOverlay.visibleProperty().bind(selectionProperty);
|
||||||
selectionOverlay.widthProperty().bind(widthProperty());
|
selectionOverlay.widthProperty().bind(widthProperty());
|
||||||
|
@ -728,9 +724,6 @@ public class ThumbCell extends StackPane {
|
||||||
topicBackground.setHeight(getHeight() - nameBackground.getHeight());
|
topicBackground.setHeight(getHeight() - nameBackground.getHeight());
|
||||||
|
|
||||||
StackPane.setMargin(groupIndicator, new Insets(0, 3, nameBackground.getHeight() + 4, 0));
|
StackPane.setMargin(groupIndicator, new Insets(0, 3, nameBackground.getHeight() + 4, 0));
|
||||||
if (Config.getInstance().getSettings().livePreviews) {
|
|
||||||
StackPane.setMargin(previewTrigger, new Insets(0, 0, nameBackground.getHeight() + 4, 4));
|
|
||||||
}
|
|
||||||
super.layoutChildren();
|
super.layoutChildren();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import ctbrec.sites.Site;
|
||||||
import ctbrec.ui.AutosizeAlert;
|
import ctbrec.ui.AutosizeAlert;
|
||||||
import ctbrec.ui.CamrecApplication;
|
import ctbrec.ui.CamrecApplication;
|
||||||
import ctbrec.ui.JavaFxModel;
|
import ctbrec.ui.JavaFxModel;
|
||||||
import ctbrec.ui.PreviewPopupHandler;
|
|
||||||
import ctbrec.ui.action.AbstractPortraitAction.PortraitChangedEvent;
|
import ctbrec.ui.action.AbstractPortraitAction.PortraitChangedEvent;
|
||||||
import ctbrec.ui.action.MarkForLaterRecordingAction;
|
import ctbrec.ui.action.MarkForLaterRecordingAction;
|
||||||
import ctbrec.ui.action.PlayAction;
|
import ctbrec.ui.action.PlayAction;
|
||||||
|
@ -140,12 +139,6 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
|
||||||
table.setStyle("-fx-table-cell-border-color: transparent;");
|
table.setStyle("-fx-table-cell-border-color: transparent;");
|
||||||
}
|
}
|
||||||
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
||||||
var previewPopupHandler = new PreviewPopupHandler(table);
|
|
||||||
table.setRowFactory(tableview -> {
|
|
||||||
TableRow<JavaFxModel> row = new TableRow<>();
|
|
||||||
row.addEventHandler(MouseEvent.ANY, previewPopupHandler);
|
|
||||||
return row;
|
|
||||||
});
|
|
||||||
table.setItems(observableModels);
|
table.setItems(observableModels);
|
||||||
table.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> {
|
table.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> {
|
||||||
popup = createContextMenu();
|
popup = createContextMenu();
|
||||||
|
@ -284,12 +277,6 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addPreviewColumn(int columnIdx) {
|
|
||||||
TableColumn<JavaFxModel, String> preview = addTableColumn("preview", "🎥", columnIdx, 35);
|
|
||||||
preview.setCellValueFactory(cdf -> new SimpleStringProperty(" ▶ "));
|
|
||||||
preview.setEditable(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addPortraitColumn(int columnIdx) {
|
protected void addPortraitColumn(int columnIdx) {
|
||||||
TableColumn<JavaFxModel, Image> portrait = addTableColumn("portrait", "Portrait", columnIdx, 80);
|
TableColumn<JavaFxModel, Image> portrait = addTableColumn("portrait", "Portrait", columnIdx, 80);
|
||||||
portrait.setCellValueFactory(param -> {
|
portrait.setCellValueFactory(param -> {
|
||||||
|
@ -550,7 +537,6 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
|
||||||
|
|
||||||
protected void restoreState() {
|
protected void restoreState() {
|
||||||
table.restoreState();
|
table.restoreState();
|
||||||
table.getColumns().stream().filter(tc -> Objects.equals(tc.getId(), "preview")).findFirst().ifPresent(tc -> tc.setVisible(config.getSettings().livePreviews));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class ClickableCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
|
protected class ClickableCellFactory<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
|
||||||
|
|
|
@ -45,7 +45,6 @@ public class RecordLaterTab extends AbstractRecordedModelsTab implements TabSele
|
||||||
super.createGui();
|
super.createGui();
|
||||||
|
|
||||||
int columnIdx = 0;
|
int columnIdx = 0;
|
||||||
addPreviewColumn(columnIdx++);
|
|
||||||
addPortraitColumn(columnIdx++);
|
addPortraitColumn(columnIdx++);
|
||||||
addModelColumn(columnIdx++);
|
addModelColumn(columnIdx++);
|
||||||
addUrlColumn(columnIdx++);
|
addUrlColumn(columnIdx++);
|
||||||
|
|
|
@ -74,7 +74,6 @@ public class RecordedModelsTab extends AbstractRecordedModelsTab implements TabS
|
||||||
|
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
addPreviewColumn(idx++);
|
|
||||||
addPortraitColumn(idx++);
|
addPortraitColumn(idx++);
|
||||||
addModelColumn(idx++);
|
addModelColumn(idx++);
|
||||||
addUrlColumn(idx++);
|
addUrlColumn(idx++);
|
||||||
|
|
|
@ -96,7 +96,6 @@ public class Settings {
|
||||||
public byte[] key = null;
|
public byte[] key = null;
|
||||||
public List<String> ignoredModels = new ArrayList<>();
|
public List<String> ignoredModels = new ArrayList<>();
|
||||||
public String lastDownloadDir = "";
|
public String lastDownloadDir = "";
|
||||||
public boolean livePreviews = false;
|
|
||||||
public boolean localRecording = true;
|
public boolean localRecording = true;
|
||||||
public boolean logFFmpegOutput = false;
|
public boolean logFFmpegOutput = false;
|
||||||
public boolean loghlsdlOutput = false;
|
public boolean loghlsdlOutput = false;
|
||||||
|
|
Loading…
Reference in New Issue