Commit a5a82382 authored by Riegel's avatar Riegel
Browse files

Open Source release of CityDoctor-GUI

parent 7a22ca9c
Pipeline #10028 failed with stage
in 7 seconds
package de.hft.stuttgart.citydoctor2.gui;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import de.hft.stuttgart.citydoctor2.check.ExcludeFilterConfiguration;
import de.hft.stuttgart.citydoctor2.check.FilterConfiguration;
import de.hft.stuttgart.citydoctor2.check.IncludeFilterConfiguration;
import de.hft.stuttgart.citydoctor2.datastructure.FeatureType;
import de.hft.stuttgart.citydoctor2.gui.filter.TypeFilterSelection;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
public class FilterPane {
@FXML
private VBox inclFeatureBox;
@FXML
private ImageView addInclFeatureView;
@FXML
private VBox inclMatchBox;
@FXML
private ImageView addInclMatchView;
@FXML
private Button addInclFeatureBtn;
@FXML
private Button addInclMatchBtn;
@FXML
private VBox exclFeatureBox;
@FXML
private ImageView addExclFeatureView;
@FXML
private VBox exclMatchBox;
@FXML
private ImageView addExclMatchView;
@FXML
private Button addExclFeatureBtn;
@FXML
private Button addExclMatchBtn;
private ScrollPane pane;
private Image deleteImg;
private List<ComboBox<TypeFilterSelection>> includeTypeBoxes = new ArrayList<>();
private List<TextField> includeMatcherFields = new ArrayList<>();
private List<TextField> excludeMatcherFields = new ArrayList<>();
private List<ComboBox<TypeFilterSelection>> excludeTypeBoxes = new ArrayList<>();
private List<TypeFilterSelection> availableFilters;
public FilterPane() throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(FilterPane.class.getResource("FilterPane.fxml"));
fxmlLoader.setController(this);
pane = fxmlLoader.load();
}
public void initialize() {
loadImages();
availableFilters = new ArrayList<>();
availableFilters.add(new TypeFilterSelection(FeatureType.BUILDING, Localization.getText("FilterPane.buildings")));
availableFilters.add(new TypeFilterSelection(FeatureType.BRIDGE, Localization.getText("FilterPane.bridges")));
availableFilters.add(new TypeFilterSelection(FeatureType.LAND, Localization.getText("FilterPane.landUse")));
availableFilters.add(new TypeFilterSelection(FeatureType.TRANSPORTATION, Localization.getText("FilterPane.transportation")));
availableFilters.add(new TypeFilterSelection(FeatureType.VEGETATION, Localization.getText("FilterPane.vegetation")));
availableFilters.add(new TypeFilterSelection(FeatureType.WATER, Localization.getText("FilterPane.water")));
setupIncludeFeatureButton();
setupIncludeMatchButton();
setupExcludeFeatureButton();
setupExcludeMatchButton();
}
private void setupExcludeMatchButton() {
addExclMatchBtn.setOnAction(ae -> addExcludeMatchField());
}
private TextField addExcludeMatchField() {
TextField tf = new TextField();
tf.setPrefWidth(400);
excludeMatcherFields.add(tf);
HBox box = new HBox(10);
box.getChildren().add(tf);
ImageView imgView = new ImageView(deleteImg);
imgView.setFitHeight(25);
imgView.setFitWidth(25);
box.getChildren().add(imgView);
imgView.setOnMouseClicked(me2 -> {
excludeMatcherFields.remove(tf);
exclMatchBox.getChildren().remove(box);
});
exclMatchBox.getChildren().add(box);
return tf;
}
private void setupExcludeFeatureButton() {
addExclFeatureBtn.setOnAction(ae -> addExcludeTypeFilterBox());
}
private ComboBox<TypeFilterSelection> addExcludeTypeFilterBox() {
ComboBox<TypeFilterSelection> cBox = new ComboBox<>();
cBox.setPrefWidth(400);
cBox.getItems().addAll(availableFilters);
cBox.getSelectionModel().select(0);
excludeTypeBoxes.add(cBox);
HBox box = new HBox(10);
box.getChildren().add(cBox);
ImageView imgView = new ImageView(deleteImg);
imgView.setFitHeight(25);
imgView.setFitWidth(25);
box.getChildren().add(imgView);
imgView.setOnMouseClicked(me2 -> {
excludeTypeBoxes.remove(cBox);
exclFeatureBox.getChildren().remove(box);
});
exclFeatureBox.getChildren().add(box);
return cBox;
}
private void setupIncludeMatchButton() {
addInclMatchBtn.setOnAction(ae -> addIncludeMatchField());
}
private TextField addIncludeMatchField() {
TextField tf = new TextField();
tf.setPrefWidth(400);
includeMatcherFields.add(tf);
HBox box = new HBox(10);
box.getChildren().add(tf);
ImageView imgView = new ImageView(deleteImg);
imgView.setFitHeight(25);
imgView.setFitWidth(25);
box.getChildren().add(imgView);
imgView.setOnMouseClicked(me2 -> {
includeMatcherFields.remove(tf);
inclMatchBox.getChildren().remove(box);
});
inclMatchBox.getChildren().add(box);
return tf;
}
public void applyFilterConfig(FilterConfiguration filter) {
includeMatcherFields.clear();
inclMatchBox.getChildren().clear();
includeTypeBoxes.clear();
inclFeatureBox.getChildren().clear();
excludeMatcherFields.clear();
exclMatchBox.getChildren().clear();
excludeTypeBoxes.clear();
exclFeatureBox.getChildren().clear();
applyExcludeFilters(filter);
applyIncludeFilters(filter);
}
private void applyIncludeFilters(FilterConfiguration filter) {
IncludeFilterConfiguration include = filter.getInclude();
if (include != null) {
for (String s : include.getIds()) {
addIncludeMatchField().setText(s);
}
for (FeatureType type : include.getTypes()) {
ComboBox<TypeFilterSelection> box = addIncludeTypeFilterBox();
for (TypeFilterSelection tfs : box.getItems()) {
if (tfs.getType() == type) {
box.getSelectionModel().select(tfs);
}
}
}
}
}
private void applyExcludeFilters(FilterConfiguration filter) {
ExcludeFilterConfiguration exclude = filter.getExclude();
if (exclude != null) {
for (String s : exclude.getIds()) {
addExcludeMatchField().setText(s);
}
for (FeatureType type : exclude.getTypes()) {
ComboBox<TypeFilterSelection> box = addExcludeTypeFilterBox();
for (TypeFilterSelection tfs : box.getItems()) {
if (tfs.getType() == type) {
box.getSelectionModel().select(tfs);
}
}
}
}
}
private void setupIncludeFeatureButton() {
addInclFeatureBtn.setOnAction(ae -> addIncludeTypeFilterBox());
}
private ComboBox<TypeFilterSelection> addIncludeTypeFilterBox() {
ComboBox<TypeFilterSelection> cBox = new ComboBox<>();
cBox.setPrefWidth(400);
cBox.getItems().addAll(availableFilters);
cBox.getSelectionModel().select(0);
includeTypeBoxes.add(cBox);
HBox box = new HBox(10);
box.getChildren().add(cBox);
ImageView imgView = new ImageView(deleteImg);
imgView.setFitHeight(25);
imgView.setFitWidth(25);
box.getChildren().add(imgView);
imgView.setOnMouseClicked(me2 -> {
includeTypeBoxes.remove(cBox);
inclFeatureBox.getChildren().remove(box);
});
inclFeatureBox.getChildren().add(box);
return cBox;
}
public FilterConfiguration getConfiguration() {
IncludeFilterConfiguration includeFilters = new IncludeFilterConfiguration();
List<FeatureType> featureTypes = new ArrayList<>();
for (ComboBox<TypeFilterSelection> box : includeTypeBoxes) {
featureTypes.add(box.getSelectionModel().getSelectedItem().getType());
}
includeFilters.setTypes(featureTypes);
List<String> ids = new ArrayList<>();
for (TextField tf : includeMatcherFields) {
ids.add(tf.getText());
}
includeFilters.setIds(ids);
ExcludeFilterConfiguration excludeFilters = new ExcludeFilterConfiguration();
List<FeatureType> excludeFeatureTypes = new ArrayList<>();
for (ComboBox<TypeFilterSelection> box : excludeTypeBoxes) {
excludeFeatureTypes.add(box.getSelectionModel().getSelectedItem().getType());
}
excludeFilters.setTypes(excludeFeatureTypes);
List<String> excludeIds = new ArrayList<>();
for (TextField tf : excludeMatcherFields) {
excludeIds.add(tf.getText());
}
excludeFilters.setIds(excludeIds);
FilterConfiguration fConfig = new FilterConfiguration();
fConfig.setInclude(includeFilters);
fConfig.setExclude(excludeFilters);
return fConfig;
}
private void loadImages() {
try {
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/Add.png")) {
Image img = new Image(inStream);
addInclFeatureView.setImage(img);
addInclMatchView.setImage(img);
addExclFeatureView.setImage(img);
addExclMatchView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/Delete.png")) {
deleteImg = new Image(inStream);
}
} catch (IOException e) {
// ignore close exception
}
}
public ScrollPane getPane() {
return pane;
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.gui;
import java.io.Serializable;
import de.hft.stuttgart.citydoctor2.check.Unit;
public class GlobalParameter implements Serializable {
private static final long serialVersionUID = 1423983452743345752L;
private String name;
private String value;
private Unit unit;
public GlobalParameter(String name, String value, Unit unit) {
super();
this.name = name;
this.value = value;
this.unit = unit;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((unit == null) ? 0 : unit.hashCode());
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
GlobalParameter other = (GlobalParameter) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (unit != other.unit)
return false;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
}
@Override
public String toString() {
return "GlobalParameter [name=" + name + ", value=" + value + ", unit=" + unit + "]";
}
public Unit getUnit() {
return unit;
}
public void setUnit(Unit unit) {
this.unit = unit;
}
}
package de.hft.stuttgart.citydoctor2.gui;
import java.util.List;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing.LinearRingType;
import de.hft.stuttgart.citydoctor2.math.Triangle3d;
import de.hft.stuttgart.citydoctor2.math.Vector3d;
import javafx.application.Platform;
import javafx.geometry.Point3D;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Cylinder;
import javafx.scene.shape.Sphere;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
public class HighlightController {
private double scale;
private Group points;
private Group edges;
private Group highlights;
public HighlightController(Group world) {
highlights = new Group();
points = new Group();
edges = new Group();
highlights.getChildren().add(edges);
highlights.getChildren().add(points);
Platform.runLater(() -> world.getChildren().add(highlights));
}
public void clearHighlights() {
points.getChildren().clear();
edges.getChildren().clear();
}
public void changeScaling(double translateZ) {
scale = Math.abs(translateZ);
scale = Math.min(150, scale);
scale = Math.max(10, scale);
scale = scale * 0.01;
for (Node n : points.getChildren()) {
n.setScaleX(scale);
n.setScaleY(scale);
n.setScaleZ(scale);
}
double edgeSize = scale / 10;
for (Node n : edges.getChildren()) {
if (n instanceof Cylinder) {
Cylinder cy = (Cylinder) n;
cy.setRadius(edgeSize);
}
}
}
public void highlight(Polygon p, TriangulatedGeometry currentTriGeom) {
clearHighlights();
addHighlight(p, currentTriGeom, Color.RED, Color.BLUE);
}
private void addHighlight(Polygon p, TriangulatedGeometry currentTriGeom, Color extColor, Color intColor) {
if (currentTriGeom == null || p == null) {
return;
}
addHighlight(p.getExteriorRing(), currentTriGeom, extColor);
for (LinearRing intRing : p.getInnerRings()) {
addHighlight(intRing, currentTriGeom, intColor);
}
}
public void highlight(LinearRing ring, TriangulatedGeometry currentTriGeom) {
clearHighlights();
if (ring.getType() == LinearRingType.EXTERIOR) {
addHighlight(ring, currentTriGeom, Color.RED);
} else {
addHighlight(ring, currentTriGeom, Color.BLUE);
}
}
public void highlight(List<LinearRing> rings, TriangulatedGeometry currentTriGeom) {
clearHighlights();
for (LinearRing lr : rings) {
if (lr.getType() == LinearRingType.EXTERIOR) {
addHighlight(lr, currentTriGeom, Color.RED);
} else {
addHighlight(lr, currentTriGeom, Color.BLUE);
}
}
}
private void addHighlight(LinearRing ring, TriangulatedGeometry currentTriGeom, Color pointColor) {
if (currentTriGeom == null || ring == null) {
return;
}
Vector3d movedBy = currentTriGeom.getMovedBy();
for (Vertex v : ring.getVertices()) {
highlightPoint(movedBy, v, pointColor);
}
for (int i = 0; i < ring.getVertices().size() - 1; i++) {
Vertex v1 = ring.getVertices().get(i + 0);
Vertex v2 = ring.getVertices().get(i + 1);
highlightEdge(v1, v2, movedBy);
}
}
public void highlight(Edge e, TriangulatedGeometry currentTriGeom) {
clearHighlights();
addHighlight(e, currentTriGeom);
}
private void addHighlight(Edge e, TriangulatedGeometry currentTriGeom) {
if (currentTriGeom == null || e == null) {
return;
}
Vector3d movedBy = currentTriGeom.getMovedBy();
highlightEdge(e.getFrom(), e.getTo(), movedBy);
highlightPoint(movedBy, e.getFrom(), Color.RED);
highlightPoint(movedBy, e.getTo(), Color.RED);
}
public void highlight(Vertex v, TriangulatedGeometry currentTriGeom) {
clearHighlights();
addHighlight(v, currentTriGeom, Color.RED);
}
public void addHighlight(Vertex v, TriangulatedGeometry currentTriGeom, Color c) {
if (currentTriGeom == null || v == null) {
return;
}
Vector3d movedBy = currentTriGeom.getMovedBy();
highlightPoint(movedBy, v, c);
}
private void highlightPoint(Vector3d movedBy, Vertex v, Color color) {
Sphere sp = new Sphere(0.5);
sp.setMaterial(new PhongMaterial(color));
sp.setTranslateX(v.getX() - movedBy.getX());
sp.setTranslateY(v.getY() - movedBy.getY());
sp.setTranslateZ(v.getZ() - movedBy.getZ());
sp.setScaleX(scale);
sp.setScaleY(scale);
sp.setScaleZ(scale);
sp.setUserData(new VertexClickDispatcher(v));
points.getChildren().add(sp);
}
private void highlightEdge(Vector3d v1, Vector3d v2, Vector3d movedBy) {
Point3D origin = new Point3D(v1.getX() - movedBy.getX(), v1.getY() - movedBy.getY(),
v1.getZ() - movedBy.getZ());
Point3D target = new Point3D(v2.getX() - movedBy.getX(), v2.getY() - movedBy.getY(),
v2.getZ() - movedBy.getZ());
Point3D yAxis = new Point3D(0, 1, 0);
Point3D diff = target.subtract(origin);
double height = diff.magnitude();
Point3D mid = target.midpoint(origin);
Translate moveToMidpoint = new Translate(mid.getX(), mid.getY(), mid.getZ());
Point3D axisOfRotation = diff.crossProduct(yAxis);
double angle = Math.acos(diff.normalize().dotProduct(yAxis));
Rotate rotateAroundCenter = new Rotate(-Math.toDegrees(angle), axisOfRotation);
Cylinder cy = new Cylinder(scale / 10, height);
cy.setMaterial(new PhongMaterial(Color.ORANGE));
cy.getTransforms().addAll(moveToMidpoint, rotateAroundCenter);
edges.getChildren().add(cy);
}
public void highlightEdges(List<Edge> errorEdges, TriangulatedGeometry currentTriGeom) {
clearHighlights();
for (Edge e : errorEdges) {
addHighlight(e, currentTriGeom);
}
}
public void highlightPolygons(List<List<Polygon>> components, TriangulatedGeometry currentTriGeom) {
clearHighlights();
for (int i = 0; i < components.size(); i++) {
Color extColor;
Color intColor;
// select some color pairs for exterior and inner rings
switch (i % 3) {
case 1:
extColor = Color.GREEN;
intColor = Color.YELLOW;
break;
case 2:
extColor = Color.BROWN;
intColor = Color.VIOLET;
break;
default:
extColor = Color.RED;
intColor = Color.BLUE;
}
List<Polygon> component = components.get(i);
for (Polygon p : component) {
addHighlight(p, currentTriGeom, extColor, intColor);
}
}
}
public void addHighlight(Polygon p, TriangulatedGeometry currentTriGeom) {
addHighlight(p, currentTriGeom, Color.RED, Color.BLUE);
}
public void highlight(Triangle3d t, TriangulatedGeometry currentTriGeom) {
highlightEdge(t.getP1(), t.getP2(), currentTriGeom.getMovedBy());
highlightEdge(t.getP2(), t.getP3(), currentTriGeom.getMovedBy());
highlightEdge(t.getP3(), t.getP1(), currentTriGeom.getMovedBy());
}
}
/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see <https://www.gnu.org/licenses/>.
*/
package de.hft.stuttgart.citydoctor2.gui;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javafx.scene.control.ListCell;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
public class LanguageSelectorCell extends ListCell<Locale> {
private static Map<String, Image> imageCache = new HashMap<>();
@Override
protected void updateItem(Locale item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
String country = item.getLanguage().toLowerCase(Locale.US);
Image iconRef = imageCache.computeIfAbsent(country, key -> {
String iconPath = "icons/icon_" + country + ".png";
return new Image(MainWindow.class.getResourceAsStream(iconPath));
});
ImageView iconImageView = new ImageView(iconRef);
setGraphic(iconImageView);
}
}
}
package de.hft.stuttgart.citydoctor2.gui;
import java.util.ArrayList;
import java.util.List;
import de.hft.stuttgart.citydoctor2.check.CheckError;
import de.hft.stuttgart.citydoctor2.check.ErrorVisitor;
import de.hft.stuttgart.citydoctor2.check.error.AllPolygonsWrongOrientationError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeInvalidError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeMissingError;
import de.hft.stuttgart.citydoctor2.check.error.AttributeValueWrongError;
import de.hft.stuttgart.citydoctor2.check.error.ConsecutivePointSameError;
import de.hft.stuttgart.citydoctor2.check.error.DependenciesNotMetError;
import de.hft.stuttgart.citydoctor2.check.error.MultipleConnectedComponentsError;
import de.hft.stuttgart.citydoctor2.check.error.NestedRingError;
import de.hft.stuttgart.citydoctor2.check.error.NonManifoldEdgeError;
import de.hft.stuttgart.citydoctor2.check.error.NonManifoldVertexError;
import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonDistancePlaneError;
import de.hft.stuttgart.citydoctor2.check.error.NonPlanarPolygonNormalsDeviation;
import de.hft.stuttgart.citydoctor2.check.error.NotCeilingError;
import de.hft.stuttgart.citydoctor2.check.error.NotFloorError;
import de.hft.stuttgart.citydoctor2.check.error.NotGroundError;
import de.hft.stuttgart.citydoctor2.check.error.NotWallError;
import de.hft.stuttgart.citydoctor2.check.error.NullAreaError;
import de.hft.stuttgart.citydoctor2.check.error.PointTouchesEdgeError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonHoleOutsideError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonInteriorDisconnectedError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonIntersectingRingsError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonSameOrientationError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonWithoutSurfaceError;
import de.hft.stuttgart.citydoctor2.check.error.PolygonWrongOrientationError;
import de.hft.stuttgart.citydoctor2.check.error.RingDuplicatePointError;
import de.hft.stuttgart.citydoctor2.check.error.RingEdgeIntersectionError;
import de.hft.stuttgart.citydoctor2.check.error.RingNotClosedError;
import de.hft.stuttgart.citydoctor2.check.error.RingTooFewPointsError;
import de.hft.stuttgart.citydoctor2.check.error.SchematronError;
import de.hft.stuttgart.citydoctor2.check.error.SolidNotClosedError;
import de.hft.stuttgart.citydoctor2.check.error.SolidSelfIntError;
import de.hft.stuttgart.citydoctor2.check.error.SurfaceUnfragmentedError;
import de.hft.stuttgart.citydoctor2.check.error.DegeneratedRingError;
import de.hft.stuttgart.citydoctor2.check.error.TooFewPolygonsError;
import de.hft.stuttgart.citydoctor2.check.error.UnknownCheckError;
import de.hft.stuttgart.citydoctor2.datastructure.Edge;
import de.hft.stuttgart.citydoctor2.datastructure.LinearRing;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import javafx.scene.paint.Color;
public class ListErrorVisitor implements ErrorVisitor {
private HighlightController controller;
private TriangulatedGeometry geom;
public ListErrorVisitor(HighlightController controller) {
this.controller = controller;
}
public void setGeometry(TriangulatedGeometry geom) {
this.geom = geom;
}
@Override
public void visit(PolygonHoleOutsideError err) {
List<LinearRing> highlightedRings = new ArrayList<>();
highlightedRings.add(err.getPolygon().getExteriorRing());
highlightedRings.addAll(err.getHolesOutside());
controller.highlight(highlightedRings, geom);
}
@Override
public void visit(NonManifoldEdgeError err) {
controller.highlightEdges(err.getEdges(), geom);
}
@Override
public void visit(MultipleConnectedComponentsError err) {
controller.highlightPolygons(err.getComponents(), geom);
}
@Override
public void visit(NestedRingError err) {
List<LinearRing> highlightedRings = new ArrayList<>();
highlightedRings.add(err.getPolygon().getExteriorRing());
highlightedRings.add(err.getInnerRing());
controller.highlight(highlightedRings, geom);
}
@Override
public void visit(NonManifoldVertexError err) {
controller.highlightPolygons(err.getComponents(), geom);
controller.addHighlight(err.getVertex(), geom, Color.BLUEVIOLET);
}
@Override
public void visit(PolygonWrongOrientationError err) {
controller.highlightEdges(err.getEdges(), geom);
}
@Override
public void visit(PolygonSameOrientationError err) {
List<LinearRing> highlightedRings = new ArrayList<>();
highlightedRings.add(err.getPolygon().getExteriorRing());
highlightedRings.add(err.getInnerRing());
controller.highlight(highlightedRings, geom);
}
@Override
public void visit(SolidNotClosedError err) {
controller.highlightEdges(err.getErrorEdges(), geom);
}
@Override
public void visit(DependenciesNotMetError err) {
// don't display
}
@Override
public void visit(UnknownCheckError err) {
// don't display
}
@Override
public void visit(RingNotClosedError err) {
controller.highlight(err.getRing(), geom);
}
@Override
public void visit(ConsecutivePointSameError err) {
controller.highlight(err.getRing(), geom);
controller.addHighlight(err.getVertex1(), geom, Color.BLACK);
controller.addHighlight(err.getVertex2(), geom, Color.BLACK);
}
@Override
public void visit(AllPolygonsWrongOrientationError err) {
// don't display
}
@Override
public void visit(PolygonInteriorDisconnectedError err) {
controller.highlight(err.getConnectedRings(), geom);
}
@Override
public void visit(NullAreaError err) {
// don't display
}
@Override
public void visit(RingTooFewPointsError err) {
controller.highlight(err.getRing(), geom);
}
@Override
public void visit(NonPlanarPolygonNormalsDeviation err) {
controller.highlight(err.getPolygon(), geom);
}
@Override
public void visit(NonPlanarPolygonDistancePlaneError err) {
controller.highlight(err.getPolygon(), geom);
controller.addHighlight(err.getVertex(), geom, Color.BLACK);
}
@Override
public void visit(PolygonIntersectingRingsError err) {
List<LinearRing> rings = new ArrayList<>();
rings.add(err.getIntersectingRings().getValue0());
rings.add(err.getIntersectingRings().getValue1());
controller.highlight(rings, geom);
}
@Override
public void visit(SolidSelfIntError err) {
// nothing to display for now
}
@Override
public void visit(TooFewPolygonsError err) {
// don't display
}
@Override
public void visit(RingDuplicatePointError err) {
controller.highlight(err.getRing(), geom);
controller.addHighlight(err.getVertex1(), geom, Color.BLACK);
controller.addHighlight(err.getVertex2(), geom, Color.BLACK);
}
@Override
public void visit(RingEdgeIntersectionError err) {
List<Edge> list = new ArrayList<>();
list.add(err.getEdge1());
list.add(err.getEdge2());
controller.highlightEdges(list, geom);
controller.addHighlight(new Vertex(err.getIntersection()), geom, Color.BLACK);
}
@Override
public void visit(PointTouchesEdgeError err) {
controller.highlight(err.getEdge(), geom);
controller.addHighlight(err.getVertex(), geom, Color.BLACK);
}
@Override
public void visit(CheckError err) {
// nothing to display
}
@Override
public void visit(NotCeilingError err) {
// nothing to display
}
@Override
public void visit(NotFloorError err) {
// nothing to display
}
@Override
public void visit(NotWallError err) {
// nothing to display
}
@Override
public void visit(NotGroundError err) {
// nothing to display
}
@Override
public void visit(SchematronError err) {
// nothing to display
}
@Override
public void visit(SurfaceUnfragmentedError err) {
// nothing to display
}
@Override
public void visit(DegeneratedRingError err) {
controller.highlight(err.getRing(), geom);
}
@Override
public void visit(AttributeMissingError err) {
// nothing to display
}
@Override
public void visit(AttributeValueWrongError err) {
// nothing to display
}
@Override
public void visit(AttributeInvalidError err) {
// nothing to display
}
@Override
public void visit(PolygonWithoutSurfaceError err) {
controller.highlight(err.getPolygon(), geom);
}
}
package de.hft.stuttgart.citydoctor2.gui;
import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;
public class LoadingInfoDialog {
private Stage stage;
public LoadingInfoDialog(Window parent) throws IOException {
FXMLLoader loader = new FXMLLoader(LoadingInfoDialog.class.getResource("CreateRenderDataDialog.fxml"));
loader.setController(this);
VBox box = loader.load();
stage = new Stage(StageStyle.UNDECORATED);
Scene scene = new Scene(box);
scene.setFill(null);
stage.setScene(scene);
stage.initOwner(parent);
stage.initModality(Modality.APPLICATION_MODAL);
}
public void show() {
stage.show();
}
public void hide() {
stage.hide();
}
}
package de.hft.stuttgart.citydoctor2.gui;
import java.io.IOException;
import java.io.InputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.hft.stuttgart.citydoctor2.gui.tree.Renderable;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.Tooltip;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class MainToolBar {
private static final Logger logger = LogManager.getLogger(MainToolBar.class);
@FXML
private Button saveBtn;
@FXML
private ImageView saveView;
@FXML
private Button openBtn;
@FXML
private ImageView openImageView;
@FXML
private Button checkBtn;
@FXML
private ImageView checkImageView;
@FXML
private Button showWorldBtn;
@FXML
private ImageView showWorldImageView;
@FXML
private Button schematronBtn;
@FXML
private ImageView schematronImgView;
@FXML
private ToggleButton lod1Btn;
@FXML
private ImageView lod1View;
@FXML
private ToggleButton lod2Btn;
@FXML
private ImageView lod2View;
@FXML
private ToggleButton lod3Btn;
@FXML
private ImageView lod3View;
@FXML
private ToggleButton lod4Btn;
@FXML
private ImageView lod4View;
@FXML
private Button aboutBtn;
@FXML
private ImageView aboutImgView;
@FXML
private ToggleButton gridButton;
@FXML
private ToggleButton cullingButton;
@FXML
private ImageView cullingImageView;
@FXML
private ImageView gridImageView;
@FXML
private Button reportBtn;
@FXML
private ImageView reportImageView;
private OpenFileDialog fileDialog;
private CheckDialog checkDialog;
private WriteReportDialog writeDialog;
private AboutDialog aboutDialog;
private CityDoctorController controller;
private TabPane featurePane;
private Stage stage;
private Renderer renderer;
private MainWindow mainWindow;
private HBox toolBar;
public MainToolBar(Stage stage, CityDoctorController controller, TabPane featurePane, Renderer renderer,
MainWindow mainWindow) throws IOException {
this.controller = controller;
this.featurePane = featurePane;
this.renderer = renderer;
this.stage = stage;
this.mainWindow = mainWindow;
FXMLLoader loader = new FXMLLoader(MainToolBar.class.getResource("MainToolBar.fxml"));
loader.setController(this);
toolBar = loader.load();
fileDialog = new OpenFileDialog(stage, controller);
}
public void initialize() {
openBtn.setOnAction(ae -> fileDialog.show());
setupSaveBtn();
setupCheckButton();
setupLodButtons();
setupAboutButton();
setupReportButton();
loadImages();
gridButton.setOnAction(ae -> renderer.showWireFrame(gridButton.isSelected()));
gridButton.setTooltip(new Tooltip(Localization.getText("MainToolBar.wireframe")));
cullingButton.setOnAction(ae -> renderer.enableCulling(cullingButton.isSelected()));
cullingButton.setTooltip(new Tooltip(Localization.getText("MainToolBar.culling")));
showWorldBtn.setOnAction(ar -> {
Tab selectedItem = featurePane.getSelectionModel().getSelectedItem();
if (selectedItem.getContent() instanceof TreeView) {
@SuppressWarnings("unchecked")
TreeView<Renderable> content = (TreeView<Renderable>) selectedItem.getContent();
content.getSelectionModel().clearSelection();
}
controller.showWorld();
});
}
private void loadImages() {
try {
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/openFolderIcon.png")) {
Image img = new Image(inStream);
openImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/check32x32.png")) {
Image img = new Image(inStream);
checkImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/wireframe32x32.png")) {
Image img = new Image(inStream);
gridImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/Culling.png")) {
Image img = new Image(inStream);
cullingImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/error_stat32x32.png")) {
Image img = new Image(inStream);
reportImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/scene.png")) {
Image img = new Image(inStream);
showWorldImageView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/lod1_32x32.png")) {
Image img = new Image(inStream);
lod1View.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/lod2_32x32.png")) {
Image img = new Image(inStream);
lod2View.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/lod3_32x32.png")) {
Image img = new Image(inStream);
lod3View.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/lod4_32x32.png")) {
Image img = new Image(inStream);
lod4View.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/about.png")) {
Image img = new Image(inStream);
aboutImgView.setImage(img);
}
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/save.png")) {
Image img = new Image(inStream);
saveView.setImage(img);
}
} catch (IOException e) {
// ignore close exception
}
}
private void setupReportButton() {
reportBtn.setDisable(true);
reportBtn.setTooltip(new Tooltip(Localization.getText("MainToolBar.writeReports")));
reportBtn.setOnAction(ae -> {
if (writeDialog == null) {
try {
writeDialog = new WriteReportDialog(stage, controller, mainWindow);
} catch (IOException e) {
logger.catching(e);
mainWindow.showExceptionDialog(e);
}
}
if (writeDialog != null) {
// writeDialog can be null if creation of said dialog fails
writeDialog.show();
}
});
}
private void setupAboutButton() {
aboutBtn.setOnAction(ae -> {
if (aboutDialog == null) {
try {
aboutDialog = new AboutDialog(stage);
aboutDialog.show();
} catch (IOException e) {
logger.error("Could not load about dialog.", e);
}
} else {
aboutDialog.show();
}
});
}
private void setupLodButtons() {
lod1Btn.setOnAction(ae -> {
if (lod1Btn.isSelected()) {
renderer.enableLod1();
} else {
renderer.disableLod1();
}
});
lod2Btn.setOnAction(ae -> {
if (lod2Btn.isSelected()) {
renderer.enableLod2();
} else {
renderer.disableLod2();
}
});
lod3Btn.setOnAction(ae -> {
if (lod3Btn.isSelected()) {
renderer.enableLod3();
} else {
renderer.disableLod3();
}
});
lod4Btn.setOnAction(ae -> {
if (lod4Btn.isSelected()) {
renderer.enableLod4();
} else {
renderer.disableLod4();
}
});
}
private void setupSaveBtn() {
saveBtn.setOnAction(ae -> controller.askAndSave());
}
private void setupCheckButton() {
checkBtn.setDisable(true);
checkBtn.setTooltip(new Tooltip(Localization.getText("MainToolBar.executeChecks")));
checkBtn.setOnAction(ae -> {
if (checkDialog == null) {
try {
checkDialog = new CheckDialog(mainWindow, stage, controller);
} catch (IOException e) {
mainWindow.showExceptionDialog(e);
logger.catching(e);
}
}
checkDialog.show();
});
}
public Button getCheckButton() {
return checkBtn;
}
public ToggleButton getGridButton() {
return gridButton;
}
public ToggleButton getCullingButton() {
return cullingButton;
}
public Button getWriteReportButton() {
return reportBtn;
}
public ToggleButton getLod1Btn() {
return lod1Btn;
}
public ToggleButton getLod2Btn() {
return lod2Btn;
}
public ToggleButton getLod3Btn() {
return lod3Btn;
}
public ToggleButton getLod4Btn() {
return lod4Btn;
}
public Button getWorldBtn() {
return showWorldBtn;
}
public Button getSaveBtn() {
return saveBtn;
}
public HBox getToolBar() {
return toolBar;
}
public Button getOpenBtn() {
return openBtn;
}
}
package de.hft.stuttgart.citydoctor2.gui;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
public class ModelProvider {
private CityDoctorController controller;
public ModelProvider(CityDoctorController controller) {
this.controller = controller;
}
public CityDoctorModel getModel() {
return controller.getModel();
}
}
package de.hft.stuttgart.citydoctor2.gui;
import java.io.File;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.hft.stuttgart.citydoctor2.utils.Localization;
import javafx.application.Platform;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TitledPane;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
public class OpenFileDialog {
private static final Logger logger = LogManager.getLogger(OpenFileDialog.class);
private Stage stage;
@FXML
private Button loadBtn;
@FXML
private Button cancelBtn;
@FXML
private Button selectBtn;
@FXML
private TextField precisionField;
@FXML
private TextField pathField;
@FXML
private ProgressBar progress;
@FXML
private CheckBox useValidationBox;
@FXML
private Label fileLabel;
@FXML
private TitledPane settingsPane;
@FXML
private Label roundingPlacesLabel;
@FXML
private Label xmlValidationLabel;
@FXML
private Label lowMemoryLabel;
@FXML
private CheckBox lowMemoryBox;
private CityDoctorController controller;
private ExceptionDialog exDialog;
private FileChooser fc;
public OpenFileDialog(Window parent, CityDoctorController controller) throws IOException {
FXMLLoader loader = new FXMLLoader(OpenFileDialog.class.getResource("OpenFileDialog.fxml"));
loader.setController(this);
VBox box = loader.load();
this.controller = controller;
stage = new Stage();
stage.getIcons().add(new Image(MainWindow.class.getResourceAsStream("icons/CityDoctor-Logo-rot_klein.jpg")));
stage.setScene(new Scene(box));
stage.initOwner(parent);
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle("Open File");
stage.getScene().addEventFilter(KeyEvent.KEY_PRESSED, (KeyEvent event) -> {
if (event.getCode() == KeyCode.ESCAPE) {
stage.close();
}
});
}
public void initialize() {
cancelBtn.setOnAction(ae -> stage.close());
setupPrecisionField();
setupLoadButton();
setupSelectButton();
applyLanguageToControls();
}
private void applyLanguageToControls() {
fileLabel.setText(Localization.getText("OpenFileDialog.fileLabel"));
selectBtn.setText(Localization.getText("OpenFileDialog.selectBtn"));
loadBtn.setText(Localization.getText("OpenFileDialog.loadBtn"));
settingsPane.setText(Localization.getText("OpenFileDialog.settingsPane"));
roundingPlacesLabel.setText(Localization.getText("OpenFileDialog.roundingPlacesLabel"));
xmlValidationLabel.setText(Localization.getText("OpenFileDialog.xmlValidationLabel"));
cancelBtn.setText(Localization.getText("OpenFileDialog.cancelBtn"));
lowMemoryLabel.setText(Localization.getText("OpenFileDialog.lowMemoryLabel"));
}
private void setupSelectButton() {
selectBtn.setOnAction(ae -> {
if (fc == null) {
fc = new FileChooser();
fc.setTitle(Localization.getText("OpenFileDialog.select"));
fc.getExtensionFilters().add(new ExtensionFilter("GML/XML", "*.gml", "*.xml"));
fc.getExtensionFilters().add(new ExtensionFilter(Localization.getText("MainWindow.all"), "*.*"));
}
File dir = new File(Settings.get(Settings.LAST_OPEN_FOLDER, ""));
if (dir.exists() && dir.isDirectory()) {
fc.setInitialDirectory(dir);
} else {
String userDir = System.getProperty("user.dir");
Settings.set(Settings.LAST_OPEN_FOLDER, userDir);
fc.setInitialDirectory(new File(userDir));
}
File f = fc.showOpenDialog(stage);
if (f != null) {
Settings.set(Settings.LAST_OPEN_FOLDER, f.getParent());
pathField.setText(f.getAbsolutePath());
}
});
}
private void setupLoadButton() {
loadBtn.setOnAction(ae -> {
int numberOfRoundingPlaces = Integer.parseInt(precisionField.getText());
boolean useValidation = useValidationBox.isSelected();
boolean lowMemory = lowMemoryBox.isSelected();
String path = pathField.getText();
cancelBtn.setDisable(true);
loadBtn.setDisable(true);
pathField.setDisable(true);
selectBtn.setDisable(true);
stage.setOnCloseRequest(Event::consume);
Thread t = new Thread(() -> {
try {
controller.loadCityGml(path, numberOfRoundingPlaces, progress::setProgress, useValidation,
lowMemory);
Platform.runLater(() -> stage.close());
} catch (Exception e) {
if (logger.isErrorEnabled()) {
logger.error(Localization.getText("OpenFileDialog.loadFailed"), e);
}
Platform.runLater(() -> {
if (exDialog == null) {
exDialog = new ExceptionDialog();
}
exDialog.show(e);
});
} finally {
selectBtn.setDisable(false);
pathField.setDisable(false);
cancelBtn.setDisable(false);
loadBtn.setDisable(false);
stage.setOnCloseRequest(null);
}
});
t.start();
});
}
private void setupPrecisionField() {
TextFormatter<String> formatter = new TextFormatter<>(change -> {
if (!change.isContentChange()) {
return change;
}
String text = change.getControlNewText();
try {
Integer.parseInt(text);
return change;
} catch (NumberFormatException e) {
return null;
}
});
precisionField.setTextFormatter(formatter);
}
public void show() {
Platform.runLater(() -> {
progress.setProgress(0d);
stage.showAndWait();
});
}
}
package de.hft.stuttgart.citydoctor2.gui;
import de.hft.stuttgart.citydoctor2.datastructure.Polygon;
import javafx.scene.input.MouseEvent;
public class PolygonClickDispatcher implements ClickDispatcher {
private Polygon p;
public PolygonClickDispatcher(Polygon p) {
this.p = p;
}
@Override
public void click(MouseEvent me, ClickHandler handler) {
handler.onPolygonClick(p, me);
}
}
package de.hft.stuttgart.citydoctor2.gui;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Settings {
private static Logger logger = LogManager.getLogger(Settings.class);
public static final String LAST_OPEN_FOLDER = "lastOpenFolder";
public static final String MAXIMIZED = "maximized";
public static final String FRAME_HEIGHT = "frameHeight";
public static final String FRAME_WIDTH = "frameWidth";
public static final String FRAME_X = "frameX";
public static final String FRAME_Y = "frameY";
public static final String LANGUAGE = "language";
private static Properties props;
static {
props = new Properties();
File propFile = new File("GUISettings.properties");
if (propFile.exists()) {
try (BufferedReader bis = new BufferedReader(new FileReader(propFile))) {
props.load(bis);
} catch (IOException e) {
logger.error("Failed to load settings", e);
}
}
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(propFile))) {
props.store(bw, "GUI configuration");
} catch (IOException e) {
logger.error("Failed to save settings", e);
}
}));
}
private Settings() {
}
public static String get(String name) {
return props.getProperty(name);
}
public static void set(String name, String value) {
props.setProperty(name, value);
}
public static String get(String name, String defaultV) {
return props.getProperty(name, defaultV);
}
}
package de.hft.stuttgart.citydoctor2.gui;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.hft.stuttgart.citydoctor2.check.Checker;
import de.hft.stuttgart.citydoctor2.datastructure.CityDoctorModel;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.layout.HBox;
public class ValidationView extends View {
private static final Logger logger = LogManager.getLogger(ValidationView.class);
private Image viewLogo;
private MainWindow mainWindow;
private CityDoctorController controller;
public ValidationView(MainWindow mainWindow, CityDoctorController controller) {
this.mainWindow = mainWindow;
this.controller = controller;
try (InputStream inStream = MainWindow.class.getResourceAsStream("icons/error_stat32x32.png")) {
viewLogo = new Image(inStream);
} catch (IOException e) {
logger.catching(e);
}
}
@Override
public Node getMainScreen() {
return mainWindow.getMainContainer();
}
@Override
public Optional<HBox> getToolbar() {
return Optional.of(mainWindow.getMainToolbar().getToolBar());
}
@Override
public void onHide() {
Platform.runLater(() -> {
mainWindow.unselectEverything();
mainWindow.getMeshGroup().getChildren().clear();
mainWindow.clearHighlights();
mainWindow.getErrorTree().getRoot().getChildren().clear();
mainWindow.getPolygonsView().getRoot().getChildren().clear();
mainWindow.getVertexView().getRoot().getChildren().clear();
mainWindow.getEdgeView().getRoot().getChildren().clear();
});
}
@Override
public void onShow(CityDoctorModel model, Checker checker) {
if (model == null) {
return;
}
controller.buildTrees();
controller.updateFeatureTrees();
}
@Override
public Image getViewLogo() {
return viewLogo;
}
@Override
public void initializeView(MainWindow mainWindow) {
// already initialized
}
}
package de.hft.stuttgart.citydoctor2.gui;
import de.hft.stuttgart.citydoctor2.datastructure.Vertex;
import javafx.scene.input.MouseEvent;
public class VertexClickDispatcher implements ClickDispatcher {
private Vertex v;
public VertexClickDispatcher(Vertex v) {
this.v = v;
}
@Override
public void click(MouseEvent me, ClickHandler handler) {
handler.onVertexClick(v, me);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment