Lokalisierungseditor wieder in den Editor integriert und Fehler behoben, Funktionsumfang ergänzt
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 238 KiB |
@@ -96,7 +96,7 @@ public class EditorApp extends Application {
|
|||||||
private String contentLastSection = "character";
|
private String contentLastSection = "character";
|
||||||
private ToggleButton contentCharBtn, contentQuestBtn, contentFraktionBtn,
|
private ToggleButton contentCharBtn, contentQuestBtn, contentFraktionBtn,
|
||||||
contentItemBtn, contentRezeptBtn, contentCraftingBtn,
|
contentItemBtn, contentRezeptBtn, contentCraftingBtn,
|
||||||
contentAreaBtn, contentLocationBtn;
|
contentAreaBtn, contentLocationBtn, contentLangBtn;
|
||||||
private CheckMenuItem dualWindowMenuItem;
|
private CheckMenuItem dualWindowMenuItem;
|
||||||
private CheckMenuItem showGridItem;
|
private CheckMenuItem showGridItem;
|
||||||
private Button contentSwitchBtn; // "> Content" in Welt-Toolbar (nur 1-Fenster)
|
private Button contentSwitchBtn; // "> Content" in Welt-Toolbar (nur 1-Fenster)
|
||||||
@@ -9642,7 +9642,13 @@ public class EditorApp extends Application {
|
|||||||
else if (input.ctrlHeld) input.debugNoLightToggle = true;
|
else if (input.ctrlHeld) input.debugNoLightToggle = true;
|
||||||
} else if (input.ctrlHeld) input.debugNoLightToggle = true;
|
} else if (input.ctrlHeld) input.debugNoLightToggle = true;
|
||||||
}
|
}
|
||||||
case F9 -> { if (pressed && "world".equals(currentTool)) Platform.runLater(() -> { if (wasserMergedBtn != null) wasserMergedBtn.fire(); }); }
|
case F9 -> {
|
||||||
|
if (pressed && input.ctrlHeld) Platform.runLater(() -> {
|
||||||
|
if (!dualWindowMode && !"content".equals(currentTool)) switchToContentEditor();
|
||||||
|
if (contentLangBtn != null) contentLangBtn.fire();
|
||||||
|
});
|
||||||
|
else if (pressed && "world".equals(currentTool)) Platform.runLater(() -> { if (wasserMergedBtn != null) wasserMergedBtn.fire(); });
|
||||||
|
}
|
||||||
case F10 -> { if (pressed && "world".equals(currentTool)) Platform.runLater(() -> { if (wegeBtn != null) wegeBtn.fire(); }); }
|
case F10 -> { if (pressed && "world".equals(currentTool)) Platform.runLater(() -> { if (wegeBtn != null) wegeBtn.fire(); }); }
|
||||||
case F11 -> { if (pressed && "world".equals(currentTool)) Platform.runLater(() -> { if (zonenBtn != null) zonenBtn.fire(); }); }
|
case F11 -> { if (pressed && "world".equals(currentTool)) Platform.runLater(() -> { if (zonenBtn != null) zonenBtn.fire(); }); }
|
||||||
case F12 -> { if (pressed && !input.ctrlHeld && "world".equals(currentTool)) Platform.runLater(() -> { if (playToolBtn != null) playToolBtn.fire(); }); }
|
case F12 -> { if (pressed && !input.ctrlHeld && "world".equals(currentTool)) Platform.runLater(() -> { if (playToolBtn != null) playToolBtn.fire(); }); }
|
||||||
@@ -12959,10 +12965,12 @@ public class EditorApp extends Application {
|
|||||||
contentCraftingBtn = new ToggleButton("# Crafting");
|
contentCraftingBtn = new ToggleButton("# Crafting");
|
||||||
contentAreaBtn = new ToggleButton("□ Area");
|
contentAreaBtn = new ToggleButton("□ Area");
|
||||||
contentLocationBtn = new ToggleButton("^ Location");
|
contentLocationBtn = new ToggleButton("^ Location");
|
||||||
|
contentLangBtn = new ToggleButton("≈ Lang");
|
||||||
|
|
||||||
String bold = "-fx-font-weight:bold;";
|
String bold = "-fx-font-weight:bold;";
|
||||||
for (ToggleButton b : new ToggleButton[]{contentCharBtn, contentQuestBtn, contentFraktionBtn,
|
for (ToggleButton b : new ToggleButton[]{contentCharBtn, contentQuestBtn, contentFraktionBtn,
|
||||||
contentItemBtn, contentRezeptBtn, contentCraftingBtn, contentAreaBtn, contentLocationBtn}) {
|
contentItemBtn, contentRezeptBtn, contentCraftingBtn, contentAreaBtn, contentLocationBtn,
|
||||||
|
contentLangBtn}) {
|
||||||
b.setStyle(bold);
|
b.setStyle(bold);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12975,6 +12983,7 @@ public class EditorApp extends Application {
|
|||||||
contentCraftingBtn.setToggleGroup(cg);
|
contentCraftingBtn.setToggleGroup(cg);
|
||||||
contentAreaBtn.setToggleGroup(cg);
|
contentAreaBtn.setToggleGroup(cg);
|
||||||
contentLocationBtn.setToggleGroup(cg);
|
contentLocationBtn.setToggleGroup(cg);
|
||||||
|
contentLangBtn.setToggleGroup(cg);
|
||||||
|
|
||||||
contentCharBtn.setOnAction(e -> {
|
contentCharBtn.setOnAction(e -> {
|
||||||
contentLastSection = "character"; buildCharacterViewInContent();
|
contentLastSection = "character"; buildCharacterViewInContent();
|
||||||
@@ -13000,6 +13009,9 @@ public class EditorApp extends Application {
|
|||||||
contentLocationBtn.setOnAction(e -> {
|
contentLocationBtn.setOnAction(e -> {
|
||||||
contentLastSection = "location"; buildLocationViewInContent();
|
contentLastSection = "location"; buildLocationViewInContent();
|
||||||
});
|
});
|
||||||
|
contentLangBtn.setOnAction(e -> {
|
||||||
|
contentLastSection = "lang"; buildLocalizationViewInContent();
|
||||||
|
});
|
||||||
|
|
||||||
ToolBar tb = new ToolBar();
|
ToolBar tb = new ToolBar();
|
||||||
tb.getItems().addAll(
|
tb.getItems().addAll(
|
||||||
@@ -13008,7 +13020,8 @@ public class EditorApp extends Application {
|
|||||||
new Separator(Orientation.VERTICAL), contentFraktionBtn,
|
new Separator(Orientation.VERTICAL), contentFraktionBtn,
|
||||||
new Separator(Orientation.VERTICAL), contentItemBtn,
|
new Separator(Orientation.VERTICAL), contentItemBtn,
|
||||||
new Separator(Orientation.VERTICAL), contentRezeptBtn, contentCraftingBtn,
|
new Separator(Orientation.VERTICAL), contentRezeptBtn, contentCraftingBtn,
|
||||||
new Separator(Orientation.VERTICAL), contentAreaBtn, contentLocationBtn);
|
new Separator(Orientation.VERTICAL), contentAreaBtn, contentLocationBtn,
|
||||||
|
new Separator(Orientation.VERTICAL), contentLangBtn);
|
||||||
if (includeWeltBtn) {
|
if (includeWeltBtn) {
|
||||||
Button weltBtn = new Button("< Welt");
|
Button weltBtn = new Button("< Welt");
|
||||||
weltBtn.setStyle("-fx-font-weight:bold;");
|
weltBtn.setStyle("-fx-font-weight:bold;");
|
||||||
@@ -13443,6 +13456,7 @@ public class EditorApp extends Application {
|
|||||||
case "crafting" -> contentCraftingBtn.fire();
|
case "crafting" -> contentCraftingBtn.fire();
|
||||||
case "area" -> contentAreaBtn.fire();
|
case "area" -> contentAreaBtn.fire();
|
||||||
case "location" -> contentLocationBtn.fire();
|
case "location" -> contentLocationBtn.fire();
|
||||||
|
case "lang" -> contentLangBtn.fire();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13574,6 +13588,15 @@ public class EditorApp extends Application {
|
|||||||
if (contentLocationNode != null) contentLocationNode.setExpanded(true);
|
if (contentLocationNode != null) contentLocationNode.setExpanded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void buildLocalizationViewInContent() {
|
||||||
|
collapseAllContentSections();
|
||||||
|
onF5 = null;
|
||||||
|
contentTarget().setCenter(new de.blight.editor.ui.LocalizationEditorView(
|
||||||
|
de.blight.editor.ProjectRoot.resolve("blight-lang", "src", "main", "resources", "lang")));
|
||||||
|
contentTarget().setRight(null);
|
||||||
|
contentTarget().setBottom(null);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Baum-Refresh-Methoden ─────────────────────────────────────────────────
|
// ── Baum-Refresh-Methoden ─────────────────────────────────────────────────
|
||||||
|
|
||||||
private void refreshContentQuestTree() {
|
private void refreshContentQuestTree() {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import de.blight.common.model.TextKeyStore;
|
|||||||
import de.blight.common.model.TextRegistry;
|
import de.blight.common.model.TextRegistry;
|
||||||
import de.blight.editor.ProjectRoot;
|
import de.blight.editor.ProjectRoot;
|
||||||
import javafx.animation.PauseTransition;
|
import javafx.animation.PauseTransition;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.collections.transformation.FilteredList;
|
import javafx.collections.transformation.FilteredList;
|
||||||
@@ -24,6 +23,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class LocalizationEditorView extends BorderPane {
|
public class LocalizationEditorView extends BorderPane {
|
||||||
|
|
||||||
@@ -33,10 +33,14 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
private final ComboBox<String> langCombo = new ComboBox<>();
|
private final ComboBox<String> langCombo = new ComboBox<>();
|
||||||
|
|
||||||
// Text-Tab
|
// Text-Tab
|
||||||
private final ObservableList<String[]> tableData = FXCollections.observableArrayList();
|
private final ObservableList<String[]> tableData = FXCollections.observableArrayList();
|
||||||
private final TableView<String[]> table = new TableView<>(tableData);
|
private final FilteredList<String[]> filteredData = new FilteredList<>(tableData, s -> true);
|
||||||
|
private final TableView<String[]> table = new TableView<>(filteredData);
|
||||||
private TextBundle currentBundle = null;
|
private TextBundle currentBundle = null;
|
||||||
|
|
||||||
|
// Cache bekannter Keys für Row-Highlighting (aktualisiert in loadLanguage)
|
||||||
|
private Set<String> knownKeys = new HashSet<>();
|
||||||
|
|
||||||
// Audio-Tab
|
// Audio-Tab
|
||||||
private final ObservableList<String[]> audioData = FXCollections.observableArrayList();
|
private final ObservableList<String[]> audioData = FXCollections.observableArrayList();
|
||||||
private final TableView<String[]> audioTable = new TableView<>(audioData);
|
private final TableView<String[]> audioTable = new TableView<>(audioData);
|
||||||
@@ -59,7 +63,7 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
Label langLbl = new Label("Sprache:");
|
Label langLbl = new Label("Sprache:");
|
||||||
langLbl.setStyle("-fx-text-fill: #aaa;");
|
langLbl.setStyle("-fx-text-fill: #aaa;");
|
||||||
langCombo.setPrefWidth(120);
|
langCombo.setPrefWidth(120);
|
||||||
langCombo.setOnAction(e -> loadLanguage(langCombo.getValue()));
|
langCombo.valueProperty().addListener((obs, o, n) -> loadLanguage(n));
|
||||||
|
|
||||||
Button addLangBtn = new Button("+ Sprache");
|
Button addLangBtn = new Button("+ Sprache");
|
||||||
addLangBtn.setOnAction(e -> addLanguage());
|
addLangBtn.setOnAction(e -> addLanguage());
|
||||||
@@ -87,43 +91,87 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
// Text-Tab
|
// Text-Tab
|
||||||
|
|
||||||
private VBox buildTextTabContent() {
|
private VBox buildTextTabContent() {
|
||||||
Button addKeyBtn = new Button("+ Schluessel");
|
// ── Filter ────────────────────────────────────────────────────────────
|
||||||
|
TextField filterField = new TextField();
|
||||||
|
filterField.setPromptText("Filtern (Schlüssel oder Text)…");
|
||||||
|
filterField.setStyle("-fx-background-color: #252535; -fx-text-fill: #ddd; -fx-prompt-text-fill: #666;" +
|
||||||
|
"-fx-border-color: #444; -fx-border-width: 1; -fx-background-radius: 3; -fx-border-radius: 3;");
|
||||||
|
filterField.textProperty().addListener((obs, o, n) -> {
|
||||||
|
String q = n == null ? "" : n.toLowerCase();
|
||||||
|
filteredData.setPredicate(row ->
|
||||||
|
q.isBlank()
|
||||||
|
|| row[0].toLowerCase().contains(q)
|
||||||
|
|| row[1].toLowerCase().contains(q));
|
||||||
|
});
|
||||||
|
|
||||||
|
HBox filterBar = new HBox(6, new Label(" "), filterField);
|
||||||
|
HBox.setHgrow(filterField, Priority.ALWAYS);
|
||||||
|
filterBar.setPadding(new Insets(5, 12, 5, 12));
|
||||||
|
filterBar.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
filterBar.setStyle("-fx-background-color: #1a1a2a; -fx-border-color: #444; -fx-border-width: 0 0 1 0;");
|
||||||
|
Label filterLbl = new Label("Filter:");
|
||||||
|
filterLbl.setStyle("-fx-text-fill: #aaa;");
|
||||||
|
filterBar.getChildren().set(0, filterLbl);
|
||||||
|
|
||||||
|
// ── Button-Leiste ─────────────────────────────────────────────────────
|
||||||
|
Button addKeyBtn = new Button("+ Schlüssel");
|
||||||
addKeyBtn.setOnAction(e -> addKey());
|
addKeyBtn.setOnAction(e -> addKey());
|
||||||
|
|
||||||
Button delKeyBtn = new Button("- Entfernen");
|
Button delKeyBtn = new Button("- Entfernen");
|
||||||
delKeyBtn.setOnAction(e -> deleteKey());
|
delKeyBtn.setOnAction(e -> deleteKey());
|
||||||
|
|
||||||
Button sortBtn = new Button("A->Z");
|
Button sortBtn = new Button("A→Z");
|
||||||
sortBtn.setOnAction(e -> tableData.sort(Comparator.comparing(r -> r[0])));
|
sortBtn.setOnAction(e -> tableData.sort(Comparator.comparing(r -> r[0])));
|
||||||
|
|
||||||
HBox subBar = new HBox(6, addKeyBtn, delKeyBtn, sortBtn);
|
Button fillBtn = new Button("Fehlende ergänzen");
|
||||||
|
fillBtn.setStyle("-fx-background-color: #2a4a2a; -fx-text-fill: #ccffcc;");
|
||||||
|
fillBtn.setOnAction(e -> fillMissingKeys());
|
||||||
|
|
||||||
|
HBox subBar = new HBox(6, addKeyBtn, delKeyBtn, sortBtn, new Separator(), fillBtn);
|
||||||
subBar.setPadding(new Insets(6, 12, 6, 12));
|
subBar.setPadding(new Insets(6, 12, 6, 12));
|
||||||
|
subBar.setAlignment(Pos.CENTER_LEFT);
|
||||||
subBar.setStyle("-fx-background-color: #1a1a2a; -fx-border-color: #444; -fx-border-width: 0 0 1 0;");
|
subBar.setStyle("-fx-background-color: #1a1a2a; -fx-border-color: #444; -fx-border-width: 0 0 1 0;");
|
||||||
|
|
||||||
|
// ── Tabelle ───────────────────────────────────────────────────────────
|
||||||
table.setEditable(true);
|
table.setEditable(true);
|
||||||
table.setStyle("-fx-background-color: #1a1a2a; -fx-control-inner-background: #1a1a2a;");
|
table.setStyle("-fx-background-color: #1a1a2a; -fx-control-inner-background: #1a1a2a;");
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
var policy = TableView.CONSTRAINED_RESIZE_POLICY;
|
var policy = TableView.CONSTRAINED_RESIZE_POLICY;
|
||||||
table.setColumnResizePolicy(policy);
|
table.setColumnResizePolicy(policy);
|
||||||
|
|
||||||
TableColumn<String[], String> keyCol = new TableColumn<>("Schluessel");
|
// Schlüssel: read-only
|
||||||
keyCol.setCellValueFactory(cd -> new SimpleStringProperty(cd.getValue()[0]));
|
TableColumn<String[], String> keyCol = new TableColumn<>("Schlüssel");
|
||||||
keyCol.setCellFactory(TextFieldTableCell.forTableColumn());
|
keyCol.setCellValueFactory(cd -> new javafx.beans.property.SimpleStringProperty(cd.getValue()[0]));
|
||||||
keyCol.setOnEditCommit(e -> { e.getRowValue()[0] = e.getNewValue().trim(); table.refresh(); scheduleSave(); });
|
keyCol.setEditable(false);
|
||||||
keyCol.setPrefWidth(280);
|
keyCol.setPrefWidth(280);
|
||||||
|
|
||||||
|
// Text: editierbar
|
||||||
TableColumn<String[], String> valCol = new TableColumn<>("Text");
|
TableColumn<String[], String> valCol = new TableColumn<>("Text");
|
||||||
valCol.setCellValueFactory(cd -> new SimpleStringProperty(cd.getValue()[1]));
|
valCol.setCellValueFactory(cd -> new javafx.beans.property.SimpleStringProperty(cd.getValue()[1]));
|
||||||
valCol.setCellFactory(TextFieldTableCell.forTableColumn());
|
valCol.setCellFactory(TextFieldTableCell.forTableColumn());
|
||||||
valCol.setOnEditCommit(e -> { e.getRowValue()[1] = e.getNewValue(); table.refresh(); scheduleSave(); });
|
valCol.setOnEditCommit(e -> { e.getRowValue()[1] = e.getNewValue(); table.refresh(); scheduleSave(); });
|
||||||
|
|
||||||
table.getColumns().addAll(List.of(keyCol, valCol));
|
table.getColumns().addAll(List.of(keyCol, valCol));
|
||||||
|
|
||||||
|
// Row-Factory: unbekannte Schlüssel orange hervorheben
|
||||||
|
table.setRowFactory(tv -> new TableRow<>() {
|
||||||
|
@Override
|
||||||
|
protected void updateItem(String[] item, boolean empty) {
|
||||||
|
super.updateItem(item, empty);
|
||||||
|
if (empty || item == null || item[0].isBlank()) {
|
||||||
|
setStyle("");
|
||||||
|
} else {
|
||||||
|
setStyle(knownKeys.contains(item[0]) ? "" : "-fx-background-color: #3a2510;");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
VBox.setVgrow(table, Priority.ALWAYS);
|
VBox.setVgrow(table, Priority.ALWAYS);
|
||||||
|
|
||||||
Label hint = new Label("Doppelklick zum Bearbeiten eines Eintrags.");
|
Label hint = new Label("Schlüssel (orange = nicht in TextKeyStore registriert). Doppelklick auf Text zum Bearbeiten.");
|
||||||
hint.setStyle("-fx-font-size: 10; -fx-text-fill: #666; -fx-padding: 2 12 4 12;");
|
hint.setStyle("-fx-font-size: 10; -fx-text-fill: #666; -fx-padding: 2 12 4 12;");
|
||||||
|
|
||||||
VBox box = new VBox(subBar, table, hint);
|
VBox box = new VBox(filterBar, subBar, table, hint);
|
||||||
VBox.setVgrow(table, Priority.ALWAYS);
|
VBox.setVgrow(table, Priority.ALWAYS);
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
@@ -131,16 +179,16 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
// Audio-Tab
|
// Audio-Tab
|
||||||
|
|
||||||
private VBox buildAudioTabContent() {
|
private VBox buildAudioTabContent() {
|
||||||
Button addKeyBtn = new Button("+ Schluessel");
|
Button addKeyBtn = new Button("+ Schlüssel");
|
||||||
addKeyBtn.setOnAction(e -> addAudioKey());
|
addKeyBtn.setOnAction(e -> addAudioKey());
|
||||||
|
|
||||||
Button delKeyBtn = new Button("- Entfernen");
|
Button delKeyBtn = new Button("- Entfernen");
|
||||||
delKeyBtn.setOnAction(e -> deleteAudioKey());
|
delKeyBtn.setOnAction(e -> deleteAudioKey());
|
||||||
|
|
||||||
Button sortBtn = new Button("A->Z");
|
Button sortBtn = new Button("A→Z");
|
||||||
sortBtn.setOnAction(e -> audioData.sort(Comparator.comparing(r -> r[0])));
|
sortBtn.setOnAction(e -> audioData.sort(Comparator.comparing(r -> r[0])));
|
||||||
|
|
||||||
Button fillDialogBtn = new Button("Dialog-Schluessel befuellen");
|
Button fillDialogBtn = new Button("Dialog-Schlüssel befüllen");
|
||||||
fillDialogBtn.setStyle("-fx-background-color: #3a4a6a; -fx-text-fill: white;");
|
fillDialogBtn.setStyle("-fx-background-color: #3a4a6a; -fx-text-fill: white;");
|
||||||
fillDialogBtn.setOnAction(e -> autoFillDialogKeys());
|
fillDialogBtn.setOnAction(e -> autoFillDialogKeys());
|
||||||
|
|
||||||
@@ -154,14 +202,14 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
var policy2 = TableView.CONSTRAINED_RESIZE_POLICY;
|
var policy2 = TableView.CONSTRAINED_RESIZE_POLICY;
|
||||||
audioTable.setColumnResizePolicy(policy2);
|
audioTable.setColumnResizePolicy(policy2);
|
||||||
|
|
||||||
TableColumn<String[], String> keyCol = new TableColumn<>("Schluessel");
|
TableColumn<String[], String> keyCol = new TableColumn<>("Schlüssel");
|
||||||
keyCol.setCellValueFactory(cd -> new SimpleStringProperty(cd.getValue()[0]));
|
keyCol.setCellValueFactory(cd -> new javafx.beans.property.SimpleStringProperty(cd.getValue()[0]));
|
||||||
keyCol.setCellFactory(TextFieldTableCell.forTableColumn());
|
keyCol.setCellFactory(TextFieldTableCell.forTableColumn());
|
||||||
keyCol.setOnEditCommit(e -> { e.getRowValue()[0] = e.getNewValue().trim(); audioTable.refresh(); scheduleSave(); });
|
keyCol.setOnEditCommit(e -> { e.getRowValue()[0] = e.getNewValue().trim(); audioTable.refresh(); scheduleSave(); });
|
||||||
keyCol.setPrefWidth(220);
|
keyCol.setPrefWidth(220);
|
||||||
|
|
||||||
TableColumn<String[], String> pathCol = new TableColumn<>("Datei");
|
TableColumn<String[], String> pathCol = new TableColumn<>("Datei");
|
||||||
pathCol.setCellValueFactory(cd -> new SimpleStringProperty(cd.getValue()[1]));
|
pathCol.setCellValueFactory(cd -> new javafx.beans.property.SimpleStringProperty(cd.getValue()[1]));
|
||||||
pathCol.setCellFactory(TextFieldTableCell.forTableColumn());
|
pathCol.setCellFactory(TextFieldTableCell.forTableColumn());
|
||||||
pathCol.setOnEditCommit(e -> { e.getRowValue()[1] = e.getNewValue(); audioTable.refresh(); scheduleSave(); });
|
pathCol.setOnEditCommit(e -> { e.getRowValue()[1] = e.getNewValue(); audioTable.refresh(); scheduleSave(); });
|
||||||
|
|
||||||
@@ -177,7 +225,7 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
int idx = getIndex();
|
int idx = getIndex();
|
||||||
if (idx < 0 || idx >= audioData.size()) return;
|
if (idx < 0 || idx >= audioData.size()) return;
|
||||||
FileChooser fc = new FileChooser();
|
FileChooser fc = new FileChooser();
|
||||||
fc.setTitle("Audio-Datei waehlen");
|
fc.setTitle("Audio-Datei wählen");
|
||||||
fc.getExtensionFilters().addAll(
|
fc.getExtensionFilters().addAll(
|
||||||
new FileChooser.ExtensionFilter("Audio", "*.ogg", "*.wav", "*.mp3"),
|
new FileChooser.ExtensionFilter("Audio", "*.ogg", "*.wav", "*.mp3"),
|
||||||
new FileChooser.ExtensionFilter("Alle Dateien", "*.*")
|
new FileChooser.ExtensionFilter("Alle Dateien", "*.*")
|
||||||
@@ -211,7 +259,7 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
audioTable.getColumns().addAll(List.of(keyCol, pathCol, browseCol));
|
audioTable.getColumns().addAll(List.of(keyCol, pathCol, browseCol));
|
||||||
VBox.setVgrow(audioTable, Priority.ALWAYS);
|
VBox.setVgrow(audioTable, Priority.ALWAYS);
|
||||||
|
|
||||||
Label hint = new Label("Schluessel muss dem AudioReference-Key im Dialog entsprechen.");
|
Label hint = new Label("Schlüssel muss dem AudioReference-Key im Dialog entsprechen.");
|
||||||
hint.setStyle("-fx-font-size: 10; -fx-text-fill: #666; -fx-padding: 2 12 4 12;");
|
hint.setStyle("-fx-font-size: 10; -fx-text-fill: #666; -fx-padding: 2 12 4 12;");
|
||||||
|
|
||||||
VBox box = new VBox(subBar, audioTable, hint);
|
VBox box = new VBox(subBar, audioTable, hint);
|
||||||
@@ -243,6 +291,9 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
}
|
}
|
||||||
tableData.clear();
|
tableData.clear();
|
||||||
currentBundle.getEntries().forEach((k, v) -> tableData.add(new String[]{k, v}));
|
currentBundle.getEntries().forEach((k, v) -> tableData.add(new String[]{k, v}));
|
||||||
|
|
||||||
|
knownKeys = new HashSet<>(TextKeyStore.getKeys());
|
||||||
|
|
||||||
TextRegistry.clear();
|
TextRegistry.clear();
|
||||||
TextRegistry.registerAll(currentBundle.getEntries());
|
TextRegistry.registerAll(currentBundle.getEntries());
|
||||||
|
|
||||||
@@ -254,7 +305,7 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
private void addLanguage() {
|
private void addLanguage() {
|
||||||
TextInputDialog dlg = new TextInputDialog();
|
TextInputDialog dlg = new TextInputDialog();
|
||||||
dlg.initOwner(Dialogs.primaryWindow());
|
dlg.initOwner(Dialogs.primaryWindow());
|
||||||
dlg.setTitle("Sprache hinzufuegen");
|
dlg.setTitle("Sprache hinzufügen");
|
||||||
dlg.setHeaderText("Sprach-Code (z. B. de, en, fr):");
|
dlg.setHeaderText("Sprach-Code (z. B. de, en, fr):");
|
||||||
dlg.showAndWait().ifPresent(lang -> {
|
dlg.showAndWait().ifPresent(lang -> {
|
||||||
lang = lang.trim().toLowerCase();
|
lang = lang.trim().toLowerCase();
|
||||||
@@ -274,7 +325,7 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
String lang = langCombo.getValue();
|
String lang = langCombo.getValue();
|
||||||
if (lang == null) return;
|
if (lang == null) return;
|
||||||
Alert confirm = Dialogs.alert(Alert.AlertType.CONFIRMATION,
|
Alert confirm = Dialogs.alert(Alert.AlertType.CONFIRMATION,
|
||||||
"Sprache '" + lang + "' wirklich loeschen?", ButtonType.YES, ButtonType.NO);
|
"Sprache '" + lang + "' wirklich löschen?", ButtonType.YES, ButtonType.NO);
|
||||||
confirm.showAndWait().ifPresent(bt -> {
|
confirm.showAndWait().ifPresent(bt -> {
|
||||||
if (bt == ButtonType.YES) {
|
if (bt == ButtonType.YES) {
|
||||||
try {
|
try {
|
||||||
@@ -296,23 +347,25 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
|
|
||||||
private void addKey() {
|
private void addKey() {
|
||||||
if (currentBundle == null) return;
|
if (currentBundle == null) return;
|
||||||
Set<String> existing = currentBundle.getEntries().keySet();
|
Set<String> existing = new HashSet<>();
|
||||||
List<String> available = new ArrayList<>(TextKeyStore.getKeys());
|
for (String[] row : tableData) existing.add(row[0]);
|
||||||
available.removeAll(existing);
|
List<String> available = TextKeyStore.getKeys().stream()
|
||||||
|
.filter(k -> !existing.contains(k))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
if (available.isEmpty()) {
|
if (available.isEmpty()) {
|
||||||
TextInputDialog dlg = new TextInputDialog();
|
TextInputDialog dlg = new TextInputDialog();
|
||||||
dlg.initOwner(Dialogs.primaryWindow());
|
dlg.initOwner(Dialogs.primaryWindow());
|
||||||
dlg.setTitle("Schluessel hinzufuegen");
|
dlg.setTitle("Schlüssel hinzufügen");
|
||||||
dlg.setHeaderText("Alle bekannten Schluessel bereits vorhanden.\nNeuen Schluessel eingeben:");
|
dlg.setHeaderText("Alle bekannten Schlüssel bereits vorhanden.\nNeuen Schlüssel eingeben:");
|
||||||
dlg.showAndWait().map(String::trim).filter(s -> !s.isBlank()).ifPresent(this::insertKey);
|
dlg.showAndWait().map(String::trim).filter(s -> !s.isBlank()).ifPresent(this::insertKey);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dialog<String> dlg = new Dialog<>();
|
Dialog<String> dlg = new Dialog<>();
|
||||||
dlg.initOwner(Dialogs.primaryWindow());
|
dlg.initOwner(Dialogs.primaryWindow());
|
||||||
dlg.setTitle("Schluessel waehlen");
|
dlg.setTitle("Schlüssel wählen");
|
||||||
dlg.setHeaderText("Noch nicht uebersetzte Schluessel:");
|
dlg.setHeaderText("Noch nicht übersetzte Schlüssel:");
|
||||||
dlg.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
|
dlg.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
|
||||||
|
|
||||||
ObservableList<String> items = FXCollections.observableArrayList(available);
|
ObservableList<String> items = FXCollections.observableArrayList(available);
|
||||||
@@ -335,8 +388,14 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
|
|
||||||
private void insertKey(String key) {
|
private void insertKey(String key) {
|
||||||
tableData.add(new String[]{key, ""});
|
tableData.add(new String[]{key, ""});
|
||||||
table.scrollTo(tableData.size() - 1);
|
// Scroll zum neuen Eintrag — in filteredData nach Index suchen
|
||||||
table.getSelectionModel().select(tableData.size() - 1);
|
for (int i = 0; i < filteredData.size(); i++) {
|
||||||
|
if (filteredData.get(i)[0].equals(key)) {
|
||||||
|
table.scrollTo(i);
|
||||||
|
table.getSelectionModel().select(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
scheduleSave();
|
scheduleSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,13 +404,36 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
if (sel != null) { tableData.remove(sel); scheduleSave(); }
|
if (sel != null) { tableData.remove(sel); scheduleSave(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fillMissingKeys() {
|
||||||
|
Set<String> existing = new HashSet<>();
|
||||||
|
for (String[] row : tableData) existing.add(row[0]);
|
||||||
|
|
||||||
|
List<String> toAdd = TextKeyStore.getKeys().stream()
|
||||||
|
.filter(k -> !existing.contains(k))
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
for (String k : toAdd) tableData.add(new String[]{k, ""});
|
||||||
|
if (!toAdd.isEmpty()) {
|
||||||
|
tableData.sort(Comparator.comparing(r -> r[0]));
|
||||||
|
knownKeys = new HashSet<>(TextKeyStore.getKeys());
|
||||||
|
scheduleSave();
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialogs.alert(Alert.AlertType.INFORMATION,
|
||||||
|
toAdd.isEmpty()
|
||||||
|
? "Alle bekannten Schlüssel sind bereits vorhanden."
|
||||||
|
: toAdd.size() + " Schlüssel ergänzt.",
|
||||||
|
ButtonType.OK).showAndWait();
|
||||||
|
}
|
||||||
|
|
||||||
// Audio-Eintrags-Verwaltung
|
// Audio-Eintrags-Verwaltung
|
||||||
|
|
||||||
private void addAudioKey() {
|
private void addAudioKey() {
|
||||||
TextInputDialog dlg = new TextInputDialog();
|
TextInputDialog dlg = new TextInputDialog();
|
||||||
dlg.initOwner(Dialogs.primaryWindow());
|
dlg.initOwner(Dialogs.primaryWindow());
|
||||||
dlg.setTitle("Audio-Schluessel hinzufuegen");
|
dlg.setTitle("Audio-Schlüssel hinzufügen");
|
||||||
dlg.setHeaderText("Schluessel eingeben (muss dem AudioReference-Key im Dialog entsprechen):");
|
dlg.setHeaderText("Schlüssel eingeben (muss dem AudioReference-Key im Dialog entsprechen):");
|
||||||
dlg.showAndWait().map(String::trim).filter(s -> !s.isBlank()).ifPresent(key -> {
|
dlg.showAndWait().map(String::trim).filter(s -> !s.isBlank()).ifPresent(key -> {
|
||||||
audioData.add(new String[]{key, ""});
|
audioData.add(new String[]{key, ""});
|
||||||
audioTable.scrollTo(audioData.size() - 1);
|
audioTable.scrollTo(audioData.size() - 1);
|
||||||
@@ -382,8 +464,8 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
scheduleSave();
|
scheduleSave();
|
||||||
}
|
}
|
||||||
Dialogs.alert(Alert.AlertType.INFORMATION,
|
Dialogs.alert(Alert.AlertType.INFORMATION,
|
||||||
added.isEmpty() ? "Alle Dialog-Schluessel bereits vorhanden."
|
added.isEmpty() ? "Alle Dialog-Schlüssel bereits vorhanden."
|
||||||
: added.size() + " Schluessel hinzugefuegt.",
|
: added.size() + " Schlüssel hinzugefügt.",
|
||||||
ButtonType.OK).showAndWait();
|
ButtonType.OK).showAndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,7 +489,7 @@ public class LocalizationEditorView extends BorderPane {
|
|||||||
|
|
||||||
private void saveCurrent() {
|
private void saveCurrent() {
|
||||||
if (currentBundle == null) {
|
if (currentBundle == null) {
|
||||||
Dialogs.alert(Alert.AlertType.WARNING, "Keine Sprache ausgewaehlt.", ButtonType.OK).showAndWait();
|
Dialogs.alert(Alert.AlertType.WARNING, "Keine Sprache ausgewählt.", ButtonType.OK).showAndWait();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Map<String, String> textEntries = new LinkedHashMap<>();
|
Map<String, String> textEntries = new LinkedHashMap<>();
|
||||||
|
|||||||
Reference in New Issue
Block a user