forked from j62/ctbrec
1
0
Fork 0

Created action classes for actions on Recording tab

This commit is contained in:
0xboobface 2018-12-12 16:52:29 +01:00
parent 279852bb33
commit f32990b9d7
8 changed files with 280 additions and 81 deletions

View File

@ -16,7 +16,6 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -29,6 +28,10 @@ import ctbrec.Recording;
import ctbrec.StringUtil;
import ctbrec.recorder.Recorder;
import ctbrec.sites.Site;
import ctbrec.ui.action.FollowAction;
import ctbrec.ui.action.PauseAction;
import ctbrec.ui.action.ResumeAction;
import ctbrec.ui.action.StopRecordingAction;
import ctbrec.ui.controls.AutoFillTextField;
import ctbrec.ui.controls.Toast;
import javafx.application.Platform;
@ -272,39 +275,11 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
}
private void pauseAll(ActionEvent evt) {
List<Model> models = recorder.getModelsRecording();
Consumer<Model> action = (m) -> {
try {
recorder.suspendRecording(m);
} catch(Exception e) {
Platform.runLater(() ->
showErrorDialog(e, "Couldn't suspend recording of model", "Suspending recording of " + m.getName() + " failed"));
}
};
massEdit(models, action);
new PauseAction(getTabPane(), recorder.getModelsRecording(), recorder).execute();
}
private void resumeAll(ActionEvent evt) {
List<Model> models = recorder.getModelsRecording();
Consumer<Model> action = (m) -> {
try {
recorder.resumeRecording(m);
} catch(Exception e) {
Platform.runLater(() ->
showErrorDialog(e, "Couldn't resume recording of model", "Resuming recording of " + m.getName() + " failed"));
}
};
massEdit(models, action);
}
private void massEdit(List<? extends Model> models, Consumer<Model> action) {
table.setCursor(Cursor.WAIT);
threadPool.submit(() -> {
for (Model model : models) {
action.accept(model);
}
Platform.runLater(() -> table.setCursor(Cursor.DEFAULT));
});
new ResumeAction(getTabPane(), recorder.getModelsRecording(), recorder).execute();
}
void initializeUpdateService() {
@ -466,16 +441,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
}
private void follow(ObservableList<JavaFxModel> selectedModels) {
Consumer<Model> action = (m) -> {
try {
m.follow();
} catch(Throwable e) {
LOG.error("Couldn't follow model {}", m, e);
Platform.runLater(() ->
showErrorDialog(e, "Couldn't follow model", "Following " + m.getName() + " failed: " + e.getMessage()));
}
};
massEdit(new ArrayList<JavaFxModel>(selectedModels), action);
new FollowAction(getTabPane(), new ArrayList<JavaFxModel>(selectedModels)).execute();
}
private void openInPlayer(JavaFxModel selectedModel) {
@ -540,45 +506,20 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
}
private void stopAction(List<JavaFxModel> selectedModels) {
Consumer<Model> action = (m) -> {
try {
recorder.stopRecording(m);
observableModels.remove(m);
} catch(Exception e) {
Platform.runLater(() ->
showErrorDialog(e, "Couldn't stop recording", "Stopping recording of " + m.getName() + " failed"));
}
};
List<Model> models = selectedModels.stream().map(jfxm -> jfxm.getDelegate()).collect(Collectors.toList());
massEdit(models, action);
new StopRecordingAction(getTabPane(), models, recorder).execute((m) -> {
observableModels.remove(m);
});
};
private void pauseRecording(List<JavaFxModel> selectedModels) {
Consumer<Model> action = (m) -> {
try {
recorder.suspendRecording(m);
m.setSuspended(true);
} catch(Exception e) {
Platform.runLater(() ->
showErrorDialog(e, "Couldn't pause recording of model", "Pausing recording of " + m.getName() + " failed"));
}
};
List<Model> models = selectedModels.stream().map(jfxm -> jfxm.getDelegate()).collect(Collectors.toList());
massEdit(models, action);
new PauseAction(getTabPane(), models, recorder).execute();
};
private void resumeRecording(List<JavaFxModel> selectedModels) {
Consumer<Model> action = (m) -> {
try {
recorder.resumeRecording(m);
m.setSuspended(false);
} catch(Exception e) {
Platform.runLater(() ->
showErrorDialog(e, "Couldn't resume recording of model", "Resuming recording of " + m.getName() + " failed"));
}
};
List<Model> models = selectedModels.stream().map(jfxm -> jfxm.getDelegate()).collect(Collectors.toList());
massEdit(models, action);
new ResumeAction(getTabPane(), models, recorder).execute();
}
public void saveState() {

View File

@ -0,0 +1,29 @@
package ctbrec.ui.action;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Model;
import ctbrec.ui.controls.Dialogs;
import javafx.application.Platform;
import javafx.scene.Node;
public class FollowAction extends ModelMassEditAction {
private static final transient Logger LOG = LoggerFactory.getLogger(FollowAction.class);
public FollowAction(Node source, List<? extends Model> models) {
super(source, models);
action = (m) -> {
try {
m.follow();
} catch(Exception e) {
LOG.error("Couldn't follow model {}", m, e);
Platform.runLater(() ->
Dialogs.showError("Couldn't follow model", "Following " + m.getName() + " failed: " + e.getMessage(), e));
}
};
}
}

View File

@ -0,0 +1,52 @@
package ctbrec.ui.action;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import ctbrec.Model;
import javafx.application.Platform;
import javafx.scene.Cursor;
import javafx.scene.Node;
public class ModelMassEditAction {
static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
static ExecutorService threadPool = new ThreadPoolExecutor(2, 2, 10, TimeUnit.MINUTES, queue);
protected List<? extends Model> models;
protected Consumer<Model> action;
protected Node source;
protected ModelMassEditAction(Node source, List<? extends Model> models) {
this.source = source;
this.models = models;
}
public ModelMassEditAction(Node source, List<? extends Model> models, Consumer<Model> action) {
this.source = source;
this.models = models;
this.action = action;
}
public void execute() {
execute((m) -> {});
}
public void execute(Consumer<Model> callback) {
Consumer<Model> cb = Objects.requireNonNull(callback);
source.setCursor(Cursor.WAIT);
threadPool.submit(() -> {
for (Model model : models) {
action.accept(model);
cb.accept(model);
}
Platform.runLater(() -> source.setCursor(Cursor.DEFAULT));
});
}
}

View File

@ -0,0 +1,24 @@
package ctbrec.ui.action;
import java.util.List;
import ctbrec.Model;
import ctbrec.recorder.Recorder;
import ctbrec.ui.controls.Dialogs;
import javafx.application.Platform;
import javafx.scene.Node;
public class PauseAction extends ModelMassEditAction {
public PauseAction(Node source, List<? extends Model> models, Recorder recorder) {
super(source, models);
action = (m) -> {
try {
recorder.suspendRecording(m);
} catch(Exception e) {
Platform.runLater(() ->
Dialogs.showError("Couldn't suspend recording of model", "Suspending recording of " + m.getName() + " failed", e));
}
};
}
}

View File

@ -0,0 +1,24 @@
package ctbrec.ui.action;
import java.util.List;
import ctbrec.Model;
import ctbrec.recorder.Recorder;
import ctbrec.ui.controls.Dialogs;
import javafx.application.Platform;
import javafx.scene.Node;
public class ResumeAction extends ModelMassEditAction {
public ResumeAction(Node source, List<? extends Model> models, Recorder recorder) {
super(source, models);
action = (m) -> {
try {
recorder.resumeRecording(m);
} catch(Exception e) {
Platform.runLater(() ->
Dialogs.showError("Couldn't resume recording of model", "Resuming recording of " + m.getName() + " failed", e));
}
};
}
}

View File

@ -0,0 +1,24 @@
package ctbrec.ui.action;
import java.util.List;
import ctbrec.Model;
import ctbrec.recorder.Recorder;
import ctbrec.ui.controls.Dialogs;
import javafx.application.Platform;
import javafx.scene.Node;
public class StopRecordingAction extends ModelMassEditAction {
public StopRecordingAction(Node source, List<? extends Model> models, Recorder recorder) {
super(source, models);
action = (m) -> {
try {
recorder.stopRecording(m);
} catch(Exception e) {
Platform.runLater(() ->
Dialogs.showError("Couldn't stop recording", "Stopping recording of " + m.getName() + " failed", e));
}
};
}
}

View File

@ -307,6 +307,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
GridPane.setMargin(splitAfter, new Insets(0, 0, 0, CHECKBOX_MARGIN));
layout.add(new Label("Post-Processing"), 0, row);
// TODO allow empty strings to remove post-processing scripts
postProcessing = new ProgramSelectionBox(Config.getInstance().getSettings().postProcessing);
postProcessing.fileProperty().addListener((obs, o, n) -> {
String path = n.getAbsolutePath();

View File

@ -16,11 +16,17 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Config;
import ctbrec.Model;
import ctbrec.StringUtil;
import ctbrec.sites.mfc.MyFreeCams;
import ctbrec.sites.mfc.MyFreeCamsModel;
import ctbrec.sites.mfc.SessionState;
import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.Player;
import ctbrec.ui.TabSelectionListener;
import ctbrec.ui.controls.SearchBox;
import ctbrec.ui.controls.Toast;
import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
@ -32,15 +38,21 @@ import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.control.Button;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.SortType;
import javafx.scene.control.TableView;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
@ -58,6 +70,7 @@ public class MyFreeCamsTableTab extends Tab implements TabSelectionListener {
private SearchBox filterInput;
private Label count = new Label("models");
private List<TableColumn<SessionState, ?>> columns = new ArrayList<>();
private ContextMenu popup;
public MyFreeCamsTableTab(MyFreeCams mfc) {
this.mfc = mfc;
@ -140,56 +153,84 @@ public class MyFreeCamsTableTab extends Tab implements TabSelectionListener {
table.setItems(observableModels);
table.getSortOrder().addListener(createSortOrderChangedListener());
table.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> {
popup = createContextMenu();
if (popup != null) {
popup.show(table, event.getScreenX(), event.getScreenY());
}
event.consume();
});
table.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
if (popup != null) {
popup.hide();
}
});
TableColumn<SessionState, String> name = createTableColumn("Name", 200, 0);
int idx = 0;
TableColumn<SessionState, String> name = createTableColumn("Name", 200, idx++);
name.setCellValueFactory(cdf -> {
return new SimpleStringProperty(Optional.ofNullable(cdf.getValue().getNm()).orElse("n/a"));
});
addTableColumnIfEnabled(name);
TableColumn<SessionState, String> state = createTableColumn("State", 130, 1);
TableColumn<SessionState, String> state = createTableColumn("State", 130, idx++);
state.setCellValueFactory(cdf -> {
String st = Optional.ofNullable(cdf.getValue().getVs()).map(vs -> ctbrec.sites.mfc.State.of(vs).toString()).orElse("n/a");
return new SimpleStringProperty(st);
});
addTableColumnIfEnabled(state);
TableColumn<SessionState, Number> camscore = createTableColumn("Score", 75, 2);
TableColumn<SessionState, Number> camscore = createTableColumn("Score", 75, idx++);
camscore.setCellValueFactory(cdf -> {
Double camScore = Optional.ofNullable(cdf.getValue().getM()).map(m -> m.getCamscore()).orElse(0d);
return new SimpleDoubleProperty(camScore);
});
addTableColumnIfEnabled(camscore);
TableColumn<SessionState, String> ethnic = createTableColumn("Ethnicity", 130, 3);
// this is always 0, use https://api.myfreecams.com/missmfc and https://api.myfreecams.com/missmfc/online
// TableColumn<SessionState, Number> missMfc = createTableColumn("Miss MFC", 75, idx++);
// missMfc.setCellValueFactory(cdf -> {
// Integer mmfc = Optional.ofNullable(cdf.getValue().getM()).map(m -> m.getMissmfc()).orElse(-1);
// return new SimpleIntegerProperty(mmfc);
// });
// addTableColumnIfEnabled(missMfc);
TableColumn<SessionState, String> newModel = createTableColumn("New", 60, idx++);
newModel.setCellValueFactory(cdf -> {
Integer nu = Optional.ofNullable(cdf.getValue().getM()).map(m -> m.getNewModel()).orElse(0);
return new SimpleStringProperty(nu == 1 ? "new" : "");
});
addTableColumnIfEnabled(newModel);
TableColumn<SessionState, String> ethnic = createTableColumn("Ethnicity", 130, idx++);
ethnic.setCellValueFactory(cdf -> {
String eth = Optional.ofNullable(cdf.getValue().getU()).map(u -> u.getEthnic()).orElse("n/a");
return new SimpleStringProperty(eth);
});
addTableColumnIfEnabled(ethnic);
TableColumn<SessionState, String> country = createTableColumn("Country", 160, 4);
TableColumn<SessionState, String> country = createTableColumn("Country", 160, idx++);
country.setCellValueFactory(cdf -> {
String c = Optional.ofNullable(cdf.getValue().getU()).map(u -> u.getCountry()).orElse("n/a");
return new SimpleStringProperty(c);
});
addTableColumnIfEnabled(country);
TableColumn<SessionState, String> continent = createTableColumn("Continent", 100, 5);
TableColumn<SessionState, String> continent = createTableColumn("Continent", 100, idx++);
continent.setCellValueFactory(cdf -> {
String c = Optional.ofNullable(cdf.getValue().getM()).map(m -> m.getContinent()).orElse("n/a");
return new SimpleStringProperty(c);
});
addTableColumnIfEnabled(continent);
TableColumn<SessionState, String> occupation = createTableColumn("Occupation", 160, 6);
TableColumn<SessionState, String> occupation = createTableColumn("Occupation", 160, idx++);
occupation.setCellValueFactory(cdf -> {
String occ = Optional.ofNullable(cdf.getValue().getU()).map(u -> u.getOccupation()).orElse("n/a");
return new SimpleStringProperty(occ);
});
addTableColumnIfEnabled(occupation);
TableColumn<SessionState, String> tags = createTableColumn("Tags", 300, 7);
TableColumn<SessionState, String> tags = createTableColumn("Tags", 300, idx++);
tags.setCellValueFactory(cdf -> {
Set<String> tagSet = Optional.ofNullable(cdf.getValue().getM()).map(m -> m.getTags()).orElse(Collections.emptySet());
if(tagSet.isEmpty()) {
@ -204,14 +245,14 @@ public class MyFreeCamsTableTab extends Tab implements TabSelectionListener {
});
addTableColumnIfEnabled(tags);
TableColumn<SessionState, String> blurp = createTableColumn("Blurp", 300, 8);
TableColumn<SessionState, String> blurp = createTableColumn("Blurp", 300, idx++);
blurp.setCellValueFactory(cdf -> {
String blrp = Optional.ofNullable(cdf.getValue().getU()).map(u -> u.getBlurb()).orElse("n/a");
return new SimpleStringProperty(blrp);
});
addTableColumnIfEnabled(blurp);
TableColumn<SessionState, String> topic = createTableColumn("Topic", 600, 9);
TableColumn<SessionState, String> topic = createTableColumn("Topic", 600, idx++);
topic.setCellValueFactory(cdf -> {
String tpc = Optional.ofNullable(cdf.getValue().getM()).map(m -> m.getTopic()).orElse("n/a");
try {
@ -232,6 +273,69 @@ public class MyFreeCamsTableTab extends Tab implements TabSelectionListener {
setContent(layout);
}
private ContextMenu createContextMenu() {
ObservableList<SessionState> selectedStates = table.getSelectionModel().getSelectedItems();
if (selectedStates.isEmpty()) {
return null;
}
List<Model> selectedModels = new ArrayList<>();
for (SessionState sessionState : selectedStates) {
if(sessionState.getNm() != null) {
MyFreeCamsModel model = mfc.createModel(sessionState.getNm());
mfc.getClient().update(model);
selectedModels.add(model);
}
}
MenuItem copyUrl = new MenuItem("Copy URL");
copyUrl.setOnAction((e) -> {
Model selected = selectedModels.get(0);
final Clipboard clipboard = Clipboard.getSystemClipboard();
final ClipboardContent content = new ClipboardContent();
content.putString(selected.getUrl());
clipboard.setContent(content);
});
// MenuItem resumeRecording = new MenuItem("Record");
// resumeRecording.setOnAction((e) -> resumeRecording(selectedModels));
MenuItem openInBrowser = new MenuItem("Open in Browser");
openInBrowser.setOnAction((e) -> DesktopIntegration.open(selectedModels.get(0).getUrl()));
MenuItem openInPlayer = new MenuItem("Open in Player");
openInPlayer.setOnAction((e) -> openInPlayer(selectedModels.get(0)));
MenuItem follow = new MenuItem("Follow");
follow.setOnAction((e) -> follow(selectedModels));
ContextMenu menu = new ContextMenu();
menu.getItems().addAll(copyUrl, openInPlayer, openInBrowser, follow);
if (selectedModels.size() > 1) {
copyUrl.setDisable(true);
openInPlayer.setDisable(true);
openInBrowser.setDisable(true);
}
return menu;
}
private Object follow(List<Model> selectedModels) {
// TODO Auto-generated method stub
return null;
}
private void openInPlayer(Model selectedModel) {
table.setCursor(Cursor.WAIT);
new Thread(() -> {
boolean started = Player.play(selectedModel);
Platform.runLater(() -> {
if (started && Config.getInstance().getSettings().showPlayerStarting) {
Toast.makeText(getTabPane().getScene(), "Starting Player", 2000, 500, 500);
}
table.setCursor(Cursor.DEFAULT);
});
}).start();
}
private void addTableColumnIfEnabled(TableColumn<SessionState, ?> tc) {
if(isColumnEnabled(tc)) {
table.getColumns().add(tc);