Implement multi-selection for RecordedModelsTab
This commit is contained in:
parent
0bd655bf95
commit
0c825237b2
|
@ -14,6 +14,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -42,6 +43,7 @@ import javafx.scene.control.ContextMenu;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.MenuItem;
|
import javafx.scene.control.MenuItem;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
|
import javafx.scene.control.SelectionMode;
|
||||||
import javafx.scene.control.Tab;
|
import javafx.scene.control.Tab;
|
||||||
import javafx.scene.control.TableColumn;
|
import javafx.scene.control.TableColumn;
|
||||||
import javafx.scene.control.TableColumn.SortType;
|
import javafx.scene.control.TableColumn.SortType;
|
||||||
|
@ -103,6 +105,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
BorderPane.setMargin(scrollPane, new Insets(5));
|
BorderPane.setMargin(scrollPane, new Insets(5));
|
||||||
|
|
||||||
table.setEditable(false);
|
table.setEditable(false);
|
||||||
|
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
||||||
TableColumn<JavaFxModel, String> name = new TableColumn<>("Model");
|
TableColumn<JavaFxModel, String> name = new TableColumn<>("Model");
|
||||||
name.setPrefWidth(200);
|
name.setPrefWidth(200);
|
||||||
name.setCellValueFactory(new PropertyValueFactory<JavaFxModel, String>("name"));
|
name.setCellValueFactory(new PropertyValueFactory<JavaFxModel, String>("name"));
|
||||||
|
@ -137,19 +140,9 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
});
|
});
|
||||||
table.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
table.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||||
if(event.getCode() == KeyCode.DELETE) {
|
if(event.getCode() == KeyCode.DELETE) {
|
||||||
stopAction();
|
stopAction(table.getSelectionModel().getSelectedItems());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
table.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
|
||||||
if(event.getCode() == KeyCode.S) {
|
|
||||||
for (TableColumn<JavaFxModel, ?> col : table.getSortOrder()) {
|
|
||||||
System.out.println(col.getText());
|
|
||||||
System.out.println(col.getSortType());
|
|
||||||
System.out.println(col.getComparator());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
scrollPane.setContent(table);
|
scrollPane.setContent(table);
|
||||||
|
|
||||||
HBox addModelBox = new HBox(5);
|
HBox addModelBox = new HBox(5);
|
||||||
|
@ -252,56 +245,38 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pauseAll(ActionEvent evt) {
|
private void pauseAll(ActionEvent evt) {
|
||||||
getTabPane().setCursor(Cursor.WAIT);
|
List<Model> models = recorder.getModelsRecording();
|
||||||
threadPool.submit(() -> {
|
Consumer<Model> action = (m) -> {
|
||||||
List<Model> models = recorder.getModelsRecording();
|
try {
|
||||||
Exception ex = null;
|
recorder.suspendRecording(m);
|
||||||
for (Model model : models) {
|
} catch(Exception e) {
|
||||||
try {
|
Platform.runLater(() ->
|
||||||
recorder.suspendRecording(model);
|
showErrorDialog(e, "Couldn't suspend recording of model", "Suspending recording of " + m.getName() + " failed"));
|
||||||
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
|
|
||||||
LOG.error("Couldn't suspend model {}: {}", model, e.getMessage());
|
|
||||||
ex = e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
final Exception exc = ex; // stupid compiler
|
};
|
||||||
Platform.runLater(() -> {
|
massEdit(models, action);
|
||||||
getTabPane().setCursor(Cursor.DEFAULT);
|
|
||||||
if(exc != null) {
|
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR);
|
|
||||||
alert.setTitle("Pause Model");
|
|
||||||
alert.setHeaderText("Couldn't pause recording");
|
|
||||||
alert.setContentText("At least one recording couldn't be paused: " + exc.getMessage());
|
|
||||||
alert.showAndWait();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resumeAll(ActionEvent evt) {
|
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<Model> models, Consumer<Model> action) {
|
||||||
getTabPane().setCursor(Cursor.WAIT);
|
getTabPane().setCursor(Cursor.WAIT);
|
||||||
threadPool.submit(() -> {
|
threadPool.submit(() -> {
|
||||||
List<Model> models = recorder.getModelsRecording();
|
|
||||||
Exception ex = null;
|
|
||||||
for (Model model : models) {
|
for (Model model : models) {
|
||||||
try {
|
action.accept(model);
|
||||||
recorder.resumeRecording(model);
|
|
||||||
} catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | IOException e) {
|
|
||||||
LOG.error("Couldn't resume model {}: {}", model, e.getMessage());
|
|
||||||
ex = e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
final Exception exc = ex; // stupid compiler
|
Platform.runLater(() -> getTabPane().setCursor(Cursor.DEFAULT));
|
||||||
Platform.runLater(() -> {
|
|
||||||
getTabPane().setCursor(Cursor.DEFAULT);
|
|
||||||
if(exc != null) {
|
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR);
|
|
||||||
alert.setTitle("Resume Model");
|
|
||||||
alert.setHeaderText("Couldn't resume recording");
|
|
||||||
alert.setContentText("At least one recording couldn't be resumed: " + exc.getMessage());
|
|
||||||
alert.showAndWait();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,16 +380,16 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContextMenu createContextMenu() {
|
private ContextMenu createContextMenu() {
|
||||||
JavaFxModel selectedModel = table.getSelectionModel().getSelectedItem();
|
ObservableList<JavaFxModel> selectedModels = table.getSelectionModel().getSelectedItems();
|
||||||
if(selectedModel == null) {
|
if(selectedModels.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
MenuItem stop = new MenuItem("Remove Model");
|
MenuItem stop = new MenuItem("Remove Model");
|
||||||
stop.setOnAction((e) -> stopAction());
|
stop.setOnAction((e) -> stopAction(selectedModels));
|
||||||
|
|
||||||
MenuItem copyUrl = new MenuItem("Copy URL");
|
MenuItem copyUrl = new MenuItem("Copy URL");
|
||||||
copyUrl.setOnAction((e) -> {
|
copyUrl.setOnAction((e) -> {
|
||||||
Model selected = selectedModel;
|
Model selected = selectedModels.get(0);
|
||||||
final Clipboard clipboard = Clipboard.getSystemClipboard();
|
final Clipboard clipboard = Clipboard.getSystemClipboard();
|
||||||
final ClipboardContent content = new ClipboardContent();
|
final ClipboardContent content = new ClipboardContent();
|
||||||
content.putString(selected.getUrl());
|
content.putString(selected.getUrl());
|
||||||
|
@ -422,19 +397,31 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
});
|
});
|
||||||
|
|
||||||
MenuItem pauseRecording = new MenuItem("Pause Recording");
|
MenuItem pauseRecording = new MenuItem("Pause Recording");
|
||||||
pauseRecording.setOnAction((e) -> pauseRecording());
|
pauseRecording.setOnAction((e) -> pauseRecording(selectedModels));
|
||||||
MenuItem resumeRecording = new MenuItem("Resume Recording");
|
MenuItem resumeRecording = new MenuItem("Resume Recording");
|
||||||
resumeRecording.setOnAction((e) -> resumeRecording());
|
resumeRecording.setOnAction((e) -> resumeRecording(selectedModels));
|
||||||
MenuItem openInBrowser = new MenuItem("Open in Browser");
|
MenuItem openInBrowser = new MenuItem("Open in Browser");
|
||||||
openInBrowser.setOnAction((e) -> DesktopIntegration.open(selectedModel.getUrl()));
|
openInBrowser.setOnAction((e) -> DesktopIntegration.open(selectedModels.get(0).getUrl()));
|
||||||
MenuItem openInPlayer = new MenuItem("Open in Player");
|
MenuItem openInPlayer = new MenuItem("Open in Player");
|
||||||
openInPlayer.setOnAction((e) -> openInPlayer(selectedModel));
|
openInPlayer.setOnAction((e) -> openInPlayer(selectedModels.get(0)));
|
||||||
MenuItem switchStreamSource = new MenuItem("Switch resolution");
|
MenuItem switchStreamSource = new MenuItem("Switch resolution");
|
||||||
switchStreamSource.setOnAction((e) -> switchStreamSource(selectedModel));
|
switchStreamSource.setOnAction((e) -> switchStreamSource(selectedModels.get(0)));
|
||||||
|
|
||||||
ContextMenu menu = new ContextMenu(stop);
|
ContextMenu menu = new ContextMenu(stop);
|
||||||
menu.getItems().add(selectedModel.isSuspended() ? resumeRecording : pauseRecording);
|
if(selectedModels.size() == 1) {
|
||||||
|
menu.getItems().add(selectedModels.get(0).isSuspended() ? resumeRecording : pauseRecording);
|
||||||
|
} else {
|
||||||
|
menu.getItems().addAll(resumeRecording, pauseRecording);
|
||||||
|
}
|
||||||
menu.getItems().addAll(copyUrl, openInPlayer, openInBrowser, switchStreamSource);
|
menu.getItems().addAll(copyUrl, openInPlayer, openInBrowser, switchStreamSource);
|
||||||
|
|
||||||
|
if(selectedModels.size() > 1) {
|
||||||
|
copyUrl.setDisable(true);
|
||||||
|
openInPlayer.setDisable(true);
|
||||||
|
openInBrowser.setDisable(true);
|
||||||
|
switchStreamSource.setDisable(true);
|
||||||
|
}
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,94 +475,55 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showStreamSwitchErrorDialog(Throwable throwable) {
|
private void showStreamSwitchErrorDialog(Throwable throwable) {
|
||||||
|
showErrorDialog(throwable, "Couldn't switch stream resolution", "Error while switching stream resolution");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showErrorDialog(Throwable throwable, String header, String msg) {
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR);
|
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR);
|
||||||
alert.setTitle("Error");
|
alert.setTitle("Error");
|
||||||
alert.setHeaderText("Couldn't switch stream resolution");
|
alert.setHeaderText(header);
|
||||||
alert.setContentText("Error while switching stream resolution: " + throwable.getLocalizedMessage());
|
alert.setContentText(msg + ": " + throwable.getLocalizedMessage());
|
||||||
alert.showAndWait();
|
alert.showAndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopAction() {
|
private void stopAction(ObservableList<JavaFxModel> selectedModels) {
|
||||||
Model selected = table.getSelectionModel().getSelectedItem().getDelegate();
|
Consumer<Model> action = (m) -> {
|
||||||
if (selected != null) {
|
try {
|
||||||
table.setCursor(Cursor.WAIT);
|
recorder.stopRecording(m);
|
||||||
new Thread() {
|
observableModels.remove(m);
|
||||||
@Override
|
} catch(Exception e) {
|
||||||
public void run() {
|
Platform.runLater(() ->
|
||||||
try {
|
showErrorDialog(e, "Couldn't stop recording", "Stopping recording of " + m.getName() + " failed"));
|
||||||
recorder.stopRecording(selected);
|
}
|
||||||
observableModels.remove(selected);
|
};
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e1) {
|
List<Model> models = selectedModels.stream().map(jfxm -> jfxm.getDelegate()).collect(Collectors.toList());
|
||||||
LOG.error("Couldn't stop recording", e1);
|
massEdit(models, action);
|
||||||
Platform.runLater(() -> {
|
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR);
|
|
||||||
alert.setTitle("Error");
|
|
||||||
alert.setHeaderText("Couldn't stop recording");
|
|
||||||
alert.setContentText("Error while stopping the recording: " + e1.getLocalizedMessage());
|
|
||||||
alert.showAndWait();
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
table.setCursor(Cursor.DEFAULT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private void pauseRecording() {
|
private void pauseRecording(ObservableList<JavaFxModel> selectedModels) {
|
||||||
JavaFxModel model = table.getSelectionModel().getSelectedItem();
|
Consumer<Model> action = (m) -> {
|
||||||
Model delegate = table.getSelectionModel().getSelectedItem().getDelegate();
|
try {
|
||||||
if (delegate != null) {
|
recorder.suspendRecording(m);
|
||||||
table.setCursor(Cursor.WAIT);
|
} catch(Exception e) {
|
||||||
new Thread() {
|
Platform.runLater(() ->
|
||||||
@Override
|
showErrorDialog(e, "Couldn't pause recording of model", "Pausing recording of " + m.getName() + " failed"));
|
||||||
public void run() {
|
}
|
||||||
try {
|
};
|
||||||
recorder.suspendRecording(delegate);
|
List<Model> models = selectedModels.stream().map(jfxm -> jfxm.getDelegate()).collect(Collectors.toList());
|
||||||
Platform.runLater(() -> model.setSuspended(true));
|
massEdit(models, action);
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e1) {
|
|
||||||
LOG.error("Couldn't pause recording", e1);
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR);
|
|
||||||
alert.setTitle("Error");
|
|
||||||
alert.setHeaderText("Couldn't pause recording");
|
|
||||||
alert.setContentText("Error while pausing the recording: " + e1.getLocalizedMessage());
|
|
||||||
alert.showAndWait();
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
table.setCursor(Cursor.DEFAULT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private void resumeRecording() {
|
private void resumeRecording(ObservableList<JavaFxModel> selectedModels) {
|
||||||
JavaFxModel model = table.getSelectionModel().getSelectedItem();
|
Consumer<Model> action = (m) -> {
|
||||||
Model delegate = table.getSelectionModel().getSelectedItem().getDelegate();
|
try {
|
||||||
if (delegate != null) {
|
recorder.resumeRecording(m);
|
||||||
table.setCursor(Cursor.WAIT);
|
} catch(Exception e) {
|
||||||
new Thread() {
|
Platform.runLater(() ->
|
||||||
@Override
|
showErrorDialog(e, "Couldn't resume recording of model", "Resuming recording of " + m.getName() + " failed"));
|
||||||
public void run() {
|
}
|
||||||
try {
|
};
|
||||||
recorder.resumeRecording(delegate);
|
List<Model> models = selectedModels.stream().map(jfxm -> jfxm.getDelegate()).collect(Collectors.toList());
|
||||||
Platform.runLater(() -> model.setSuspended(false));
|
massEdit(models, action);
|
||||||
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e1) {
|
|
||||||
LOG.error("Couldn't resume recording", e1);
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
Alert alert = new AutosizeAlert(Alert.AlertType.ERROR);
|
|
||||||
alert.setTitle("Error");
|
|
||||||
alert.setHeaderText("Couldn't resume recording");
|
|
||||||
alert.setContentText("Error while resuming the recording: " + e1.getLocalizedMessage());
|
|
||||||
alert.showAndWait();
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
table.setCursor(Cursor.DEFAULT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveState() {
|
public void saveState() {
|
||||||
|
|
Loading…
Reference in New Issue