Adds context menu for subtitles table

This commit is contained in:
Guillaume Tâche
2024-09-26 21:41:02 +02:00
parent c59619da2d
commit 0a2f9e0c31
9 changed files with 130 additions and 197 deletions

View File

@@ -19,12 +19,15 @@ import javafx.collections.MapChangeListener;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.KeyCode;
import javafx.stage.FileChooser;
import javafx.stage.Window;
@@ -131,38 +134,44 @@ public class FXSubtitlesController extends AbstractFXController implements Subti
}
});
translationsCombobox.setOnAction(e -> {
final var value = translationsCombobox.getValue();
if (value != null && !model.collections().containsKey(value)) {
model.setTranslating(true);
CompletableFuture.supplyAsync(() -> {
final var mainCollection = model.collections().get(model.videoLanguage());
try {
if (mainCollection == null) {
return translator.translate(model.selectedCollection(), value);
} else {
return translator.translate(mainCollection, value);
}
} catch (final TranslationException ex) {
throw new CompletionException(ex);
}
}).whenCompleteAsync((r, t) -> {
if (t == null) {
loadCollection(r);
model.setSelectedCollection(model.collections().get(value));
} else {
logger.error("Error while translating to {}", value, t);
final var newCollection = new ObservableSubtitleCollectionImpl();
loadCollection(newCollection);
model.setSelectedCollection(newCollection);
}
model.setTranslating(false);
}, Platform::runLater);
}
});
translationsCombobox.setOnAction(e -> translateToNewLanguage());
binder.createBindings();
}
private void translateToNewLanguage() {
final var value = translationsCombobox.getValue();
if (value != null && !model.collections().containsKey(value)) {
model.setTranslating(true);
CompletableFuture.supplyAsync(() -> {
final var mainCollection = model.collections().get(model.videoLanguage());
try {
if (mainCollection == null) {
if (model.selectedCollection() == null) {
return null;
} else {
return translator.translate(model.selectedCollection(), value);
}
} else {
return translator.translate(mainCollection, value);
}
} catch (final TranslationException ex) {
throw new CompletionException(ex);
}
}).whenCompleteAsync((r, t) -> {
if (r == null) {
logger.error("Error while translating to {}", value, t);
final var newCollection = new ObservableSubtitleCollectionImpl();
loadCollection(newCollection);
model.setSelectedCollection(newCollection);
} else {
loadCollection(r);
model.setSelectedCollection(model.collections().get(value));
}
model.setTranslating(false);
}, Platform::runLater);
}
}
private void bindTable() {
subtitlesTable.setItems(model.selectedSubtitles());
subtitlesTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
@@ -182,9 +191,7 @@ public class FXSubtitlesController extends AbstractFXController implements Subti
e.consume();
}
});
subtitlesTable.setOnContextMenuRequested(e -> {
//TODO menu with copy, delete
});
subtitlesTable.setOnContextMenuRequested(this::showContextMenu);
startColumn.setCellFactory(TextFieldTableCell.forTableColumn(new TimeStringConverter(timeFormatter)));
startColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue() == null ? null : param.getValue().start()));
startColumn.setOnEditCommit(e -> {
@@ -214,6 +221,30 @@ public class FXSubtitlesController extends AbstractFXController implements Subti
}
private void showContextMenu(final ContextMenuEvent e) {
if (model.selectedCollection() != null) {
final var deleteMenuItem = new MenuItem(resources.getString("subtitles.menu.delete.label"));
deleteMenuItem.setOnAction(ignored -> deleteSelectedSubtitles());
final var addMenuItem = new MenuItem(resources.getString("subtitles.menu.add.label"));
addMenuItem.setOnAction(ignored -> addNewSubtitle());
final var duplicateMenuItem = new MenuItem(resources.getString("subtitles.menu.duplicate.label"));
duplicateMenuItem.setOnAction(ignored -> duplicateSelectedSubtitles());
final var menu = new ContextMenu(addMenuItem);
if (!model.selectedSubtitles().isEmpty()) {
menu.getItems().addAll(duplicateMenuItem, deleteMenuItem);
}
menu.show(subtitlesTable, e.getScreenX(), e.getScreenY());
}
}
private void duplicateSelectedSubtitles() {
final var selected = model.selectedSubtitles();
if (!selected.isEmpty()) {
model.selectedCollection().observableSubtitles().addAll(selected.stream().map(ObservableSubtitleImpl::new).toList());
model.selectedCollection().observableSubtitles().sort(Comparator.comparingLong(ObservableSubtitleImpl::start));
}
}
private void manageTabs() {
final var toRemove = new ArrayList<Tab>();
final var toAdd = new ArrayList<Tab>();
@@ -247,7 +278,13 @@ public class FXSubtitlesController extends AbstractFXController implements Subti
@FXML
private void addPressed() {
model.selectedCollection().subtitles().add(new ObservableSubtitleImpl(resources.getString("subtitles.add.prompt.label")));
addNewSubtitle();
}
private void addNewSubtitle() {
if (model.selectedCollection() != null) {
model.selectedCollection().subtitles().add(new ObservableSubtitleImpl(resources.getString("subtitles.add.prompt.label")));
}
}
@FXML