From 89c2a84598d65b851e9f2bef3edddb0d6dca4a07 Mon Sep 17 00:00:00 2001 From: Riegel <alexander.riegel@hft-stuttgart.de> Date: Wed, 13 Nov 2024 11:26:34 +0100 Subject: [PATCH] Expand ContextMenu functionality for FeatureTabs --- .../datastructure/CompositeCollection.java | 1 + .../CityDoctorLocalization.properties | 8 +- .../CityDoctorLocalization_de.properties | 8 +- .../citydoctor2/gui/CityDoctorController.java | 6 +- .../stuttgart/citydoctor2/gui/MainWindow.java | 157 +++++++++++++++++- 5 files changed, 169 insertions(+), 11 deletions(-) diff --git a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CompositeCollection.java b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CompositeCollection.java index 25dd97b..852349a 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CompositeCollection.java +++ b/CityDoctorParent/CityDoctorModel/src/main/java/de/hft/stuttgart/citydoctor2/datastructure/CompositeCollection.java @@ -32,6 +32,7 @@ public final class CompositeCollection implements Serializable { return childComposites; } + //TODO stream public List<ConcretePolygon> getCompositeMembers() { List<ConcretePolygon> copy = new ArrayList<>(compositeMembers); for (CompositeCollection c : childComposites) { diff --git a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties index ddba244..353fd02 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties +++ b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization.properties @@ -18,6 +18,7 @@ CheckDialog.parameterValue=Value CheckDialog.parameterUnit=Unit CityDoctorController.noDatamodel=Datamodel is null, no checks could be done CityDoctorController.noSourceFile=Source file is null, no checks could be done +CityDoctorController.exportSuccess=Successfully exported feature ExceptionDialog.stacktrace=The exception stacktrace was: FilterPane.buildings=Buildings FilterPane.bridges=Bridges @@ -43,7 +44,12 @@ MainWindow.finishedPdf=Finished pdf report MainWindow.loadFailed=Failed to load given gml file: {} MainWindow.all=All MainWindow.withErrors=With errors -MainWindow.export=Export +MainWindow.export=Export feature +MainWindow.copyId=Copy GML-ID +MainWindow.delete=Delete feature +MainWindow.infoTopLevelExport=Only top-level object can be exported! +MainWindow.infoTopLevelCopyID=GML-ID can only be copied from top-level object! +mainWindow.warnCopyIdFailed=Could not copy GML-ID! OpenFileDialog.select=Select CityGML file MainWindow.languageChange=For the change in language to apply, restart CityDoctor2. MainWindow.buildingsTab=Buildings diff --git a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties index b93a141..58c4a4c 100644 --- a/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties +++ b/CityDoctorParent/CityDoctorModel/src/main/resources/CityDoctorLocalization_de.properties @@ -16,6 +16,7 @@ CheckDialog.parameterValue=Wert CheckDialog.parameterUnit=Einheit CityDoctorController.noDatamodel=Datenmodell ist null, keine Pr\u00fcfungen konnten ausgef\u00fchrt werden CityDoctorController.noSourceFile=Quelldatei ist null, keine Pr\u00fcfungen konnten ausgef\u00fchrt werden +CityDoctorController.exportSuccess=Feature export erfolgreich abgeschlossen ExceptionDialog.stacktrace=Der Stacktrace des Fehlers war: FilterPane.buildings=Geb\u00e4ude FilterPane.bridges=Br\u00fccken @@ -41,7 +42,12 @@ MainWindow.finishedPdf=Pdf Report abgeschlossen MainWindow.loadFailed=Konnte GML-Datei nicht laden: {} MainWindow.all=Alle MainWindow.withErrors=Mit Fehlern -MainWindow.export=Exportieren +MainWindow.export=Feature Exportieren +MainWindow.copyId=GML-ID kopieren +MainWindow.delete=Feature L\u00f6schen +MainWindow.infoTopLevelExport=Export ist nur f\u00fcr Featureobjekt basis m\u00f6glich! +MainWindow.infoTopLevelCopyID=GML-ID kann nur von Featureobjekt basis kopiert werden! +mainWindow.warnCopyIdFailed=Kopieren der ID fehlgeschlagen! OpenFileDialog.select=W\u00e4hle CityGML Datei aus MainWindow.languageChange=Um die Spracheinstellung zu \u00fcbernehmen muss CityDoctor2 neugestartet werden. MainWindow.buildingsTab=Geb\u00e4ude diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java index 0f7be6b..3c89ad0 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/CityDoctorController.java @@ -798,13 +798,14 @@ public class CityDoctorController { } } - public void export(Building b) { + public void export(CityObject co) { if (model == null) { return; } CityDoctorModel newModel = new CityDoctorModel(model.getParserConfig(), model.getFile()); newModel.setCityModel(new CityModel()); - newModel.addBuilding(b); + newModel.addCityObject(co); + newModel.setParsedCityGMLVersion(model.getCityGMLVersion()); FileChooser fc = new FileChooser(); fc.getExtensionFilters().add(new ExtensionFilter("CityGML", "*.gml")); @@ -819,7 +820,6 @@ public class CityDoctorController { if (f != null) { Settings.set(Settings.LAST_OPEN_FOLDER, f.getParent()); try { - newModel.saveAs(f.getAbsolutePath(), true); } catch (CityDoctorWriteException e) { logger.error(e); diff --git a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java index d6f77f6..dcac59b 100644 --- a/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java +++ b/CityDoctorParent/Extensions/CityDoctorGUI/src/main/java/de/hft/stuttgart/citydoctor2/gui/MainWindow.java @@ -5,7 +5,7 @@ import de.hft.stuttgart.citydoctor2.check.ValidationConfiguration; import de.hft.stuttgart.citydoctor2.datastructure.BoundingBox; import de.hft.stuttgart.citydoctor2.datastructure.FeatureType; import de.hft.stuttgart.citydoctor2.gui.logger.GuiLogger; -import de.hft.stuttgart.citydoctor2.gui.tree.BuildingNode; +import de.hft.stuttgart.citydoctor2.gui.tree.FeatureNode; import de.hft.stuttgart.citydoctor2.gui.tree.Renderable; import de.hft.stuttgart.citydoctor2.gui.tree.RenderableTreeCell; import de.hft.stuttgart.citydoctor2.parameter.ArgumentParser; @@ -25,10 +25,7 @@ import javafx.scene.control.Alert.AlertType; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.image.WritableImage; -import javafx.scene.input.Dragboard; -import javafx.scene.input.MouseButton; -import javafx.scene.input.MouseEvent; -import javafx.scene.input.TransferMode; +import javafx.scene.input.*; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; @@ -46,6 +43,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.util.*; +import static javafx.scene.input.Clipboard.getSystemClipboard; + public class MainWindow extends Application { private static final Logger logger = LogManager.getLogger(MainWindow.class); @@ -734,6 +733,8 @@ public class MainWindow extends Application { buildingsView.setShowRoot(true); setupSelectListener(buildingsView); buildingsView.setCellFactory(param -> new RenderableTreeCell()); + setupBuildingTabContextMenu(); + /* ContextMenu cMenu = new ContextMenu(); MenuItem mi = new MenuItem(Localization.getText("MainWindow.export")); mi.setOnAction(ea -> { @@ -743,29 +744,44 @@ public class MainWindow extends Application { } }); cMenu.getItems().add(mi); + MenuItem clipMi = new MenuItem(Localization.getText("MainWindow.copyId")); + clipMi.setOnAction(ea -> { + Renderable render = buildingsView.getSelectionModel().getSelectedItem().getValue(); + if (render instanceof BuildingNode node) { + Clipboard clipboard = getSystemClipboard(); + ClipboardContent content = new ClipboardContent(); + content.putString(node.getBuilding().getGmlId().toString()); + clipboard.setContent(content); + } + }); + cMenu.getItems().add(clipMi); MenuItem deleteMi = new MenuItem("Delete"); deleteMi.setOnAction(ae -> controller.delete(buildingsView.getSelectionModel().getSelectedItem())); cMenu.getItems().add(deleteMi); buildingsView.setContextMenu(cMenu); + */ vegetationView.setShowRoot(true); setupSelectListener(vegetationView); vegetationView.setCellFactory(param -> new RenderableTreeCell()); - vegetationView.setContextMenu(cMenu); + setupVegetationTabContextMenu(); transView.setShowRoot(true); setupSelectListener(transView); transView.setCellFactory(param -> new RenderableTreeCell()); + tunnelView.setShowRoot(true); setupSelectListener(tunnelView); tunnelView.setCellFactory(param -> new RenderableTreeCell()); + setupFeatureTabContextMenu(tunnelView); bridgeView.setShowRoot(true); setupSelectListener(bridgeView); bridgeView.setCellFactory(param -> new RenderableTreeCell()); + setupFeatureTabContextMenu(bridgeView); waterView.setShowRoot(true); setupSelectListener(waterView); @@ -778,10 +794,12 @@ public class MainWindow extends Application { cityFurnitureView.setShowRoot(true); setupSelectListener(cityFurnitureView); cityFurnitureView.setCellFactory(param -> new RenderableTreeCell()); + setupFeatureTabContextMenu(cityFurnitureView); otherObjectsView.setShowRoot(true); setupSelectListener(otherObjectsView); otherObjectsView.setCellFactory(param -> new RenderableTreeCell()); + setupFeatureTabContextMenu(otherObjectsView); setupSelectListener(vertexView); vertexView.setRoot(new TreeItem<>()); @@ -798,6 +816,133 @@ public class MainWindow extends Application { setupSelectListener(attributeView); attributeView.setRoot(new TreeItem<>()); attributeView.setCellFactory(param -> new RenderableTreeCell()); + + } + + private void setupBuildingTabContextMenu() { + ContextMenu menu = new ContextMenu(); + MenuItem mi = new MenuItem(Localization.getText("MainWindow.export")); + mi.setOnAction(ea -> { + Renderable render = buildingsView.getSelectionModel().getSelectedItem().getValue(); + if (render instanceof FeatureNode node) { + try { + controller.export(node.getFeature()); + logger.info(Localization.getText("CityDoctorController.export")); + } catch (Exception e) { + logger.error("Export failed: Unexpected error occurred"); + logger.error(e); + } + } else { + logger.info(Localization.getText("MainWindow.infoTopLevelExport")); + } + }); + menu.getItems().add(mi); + + MenuItem clipMi = new MenuItem(Localization.getText("MainWindow.copyId")); + clipMi.setOnAction(ea -> { + Renderable render = buildingsView.getSelectionModel().getSelectedItem().getValue(); + if (render instanceof FeatureNode node) { + Clipboard clipboard = getSystemClipboard(); + ClipboardContent content = new ClipboardContent(); + content.putString(node.getFeature().getGmlId().toString()); + if (!clipboard.setContent(content)) { + logger.warn(Localization.getText("MainWindow.warnCopyIdFailed")); + } + } else { + logger.info(Localization.getText("MainWindow.infoTopLevelCopyID")); + } + + }); + menu.getItems().add(clipMi); + + MenuItem deleteMi = new MenuItem(Localization.getText("MainWindow.delete")); + deleteMi.setOnAction(ae -> controller.delete(buildingsView.getSelectionModel().getSelectedItem())); + menu.getItems().add(deleteMi); + buildingsView.setContextMenu(menu); + } + + private void setupVegetationTabContextMenu() { + ContextMenu menu = new ContextMenu(); + MenuItem mi = new MenuItem(Localization.getText("MainWindow.export")); + mi.setOnAction(ea -> { + Renderable render = vegetationView.getSelectionModel().getSelectedItem().getValue(); + if (render instanceof FeatureNode node) { + try { + controller.export(node.getFeature()); + logger.info(Localization.getText("CityDoctorController.export")); + } catch (Exception e) { + logger.error("Export failed: Unexpected error occurred"); + logger.error(e); + } + } else { + logger.info(Localization.getText("MainWindow.infoTopLevelExport")); + } + }); + menu.getItems().add(mi); + + MenuItem clipMi = new MenuItem(Localization.getText("MainWindow.copyId")); + clipMi.setOnAction(ea -> { + Renderable render = vegetationView.getSelectionModel().getSelectedItem().getValue(); + if (render instanceof FeatureNode node) { + Clipboard clipboard = getSystemClipboard(); + ClipboardContent content = new ClipboardContent(); + content.putString(node.getFeature().getGmlId().toString()); + if (!clipboard.setContent(content)) { + logger.warn(Localization.getText("MainWindow.warnCopyIdFailed")); + } + } else { + logger.info(Localization.getText("MainWindow.infoTopLevelCopyID")); + } + + }); + menu.getItems().add(clipMi); + + MenuItem deleteMi = new MenuItem(Localization.getText("MainWindow.delete")); + deleteMi.setOnAction(ae -> controller.delete(vegetationView.getSelectionModel().getSelectedItem())); + menu.getItems().add(deleteMi); + vegetationView.setContextMenu(menu); + } + + private void setupFeatureTabContextMenu(TreeView<Renderable> featureView) { + ContextMenu menu = new ContextMenu(); + MenuItem mi = new MenuItem(Localization.getText("MainWindow.export")); + mi.setOnAction(ea -> { + Renderable render = featureView.getSelectionModel().getSelectedItem().getValue(); + if (render instanceof FeatureNode node) { + try { + controller.export(node.getFeature()); + logger.info(Localization.getText("CityDoctorController.export")); + } catch (Exception e) { + logger.error("Export failed: Unexpected error occurred"); + logger.error(e); + } + } else { + logger.info(Localization.getText("MainWindow.infoTopLevelExport")); + } + }); + menu.getItems().add(mi); + + MenuItem clipMi = new MenuItem(Localization.getText("MainWindow.copyId")); + clipMi.setOnAction(ea -> { + Renderable render = featureView.getSelectionModel().getSelectedItem().getValue(); + if (render instanceof FeatureNode node) { + Clipboard clipboard = getSystemClipboard(); + ClipboardContent content = new ClipboardContent(); + content.putString(node.getFeature().getGmlId().toString()); + if (!clipboard.setContent(content)) { + logger.warn(Localization.getText("MainWindow.warnCopyIdFailed")); + } + } else { + logger.info(Localization.getText("MainWindow.infoTopLevelCopyID")); + } + + }); + menu.getItems().add(clipMi); + + MenuItem deleteMi = new MenuItem(Localization.getText("MainWindow.delete")); + deleteMi.setOnAction(ae -> controller.delete(featureView.getSelectionModel().getSelectedItem())); + menu.getItems().add(deleteMi); + featureView.setContextMenu(menu); } private void setupSelectListener(TreeView<Renderable> view) { -- GitLab