Implement multi-selection for RecordedModelsTab

This commit is contained in:
0xboobface 2018-11-29 20:56:42 +01:00
parent 0bd655bf95
commit 0c825237b2
1 changed files with 90 additions and 142 deletions

View File

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