From 98f63726dc29c36560be01e8362024970da57dd6 Mon Sep 17 00:00:00 2001 From: Matti Tahvonen Date: Mon, 26 Feb 2024 19:41:43 +0200 Subject: [PATCH] Refactoring & global base map configuration * Zero parameter LibreMap constructor (drawing base map configuration from context) * All fields now inherit the same base class * Fields create map with zero param constructor if not explicitly set + one bugfix --- .../addons/maplibre/AbstractFeatureField.java | 34 ++++++++++---- .../addons/maplibre/LineStringField.java | 17 ++++--- .../org/vaadin/addons/maplibre/MapLibre.java | 28 +++++++++-- .../maplibre/MapLibreBaseMapProvider.java | 13 ++++++ .../vaadin/addons/maplibre/PointField.java | 46 +++++-------------- .../vaadin/addons/maplibre/PolygonField.java | 24 +++++----- .../maplibre/BinderCompatibleFields.java | 11 +++-- 7 files changed, 99 insertions(+), 74 deletions(-) create mode 100644 src/main/java/org/vaadin/addons/maplibre/MapLibreBaseMapProvider.java diff --git a/src/main/java/org/vaadin/addons/maplibre/AbstractFeatureField.java b/src/main/java/org/vaadin/addons/maplibre/AbstractFeatureField.java index ac3e2c7..a175140 100644 --- a/src/main/java/org/vaadin/addons/maplibre/AbstractFeatureField.java +++ b/src/main/java/org/vaadin/addons/maplibre/AbstractFeatureField.java @@ -5,35 +5,53 @@ @StyleSheet("context://org/vaadin/addons/maplibre/maplibre-addon.css") public abstract class AbstractFeatureField extends CustomField { - DrawControl drawControl; - MapLibre map; + private DrawControl drawControl; + private MapLibre map; public AbstractFeatureField() { } public AbstractFeatureField(String label) { + this(); setLabel(label); } - public AbstractFeatureField withStyleUrl(String styleUrl) { - this.map = new MapLibre(styleUrl); - this.drawControl = new DrawControl(map); - add(map); + public AbstractFeatureField initWithBaseLayer(String styleUrl) { + setMap(new MapLibre(styleUrl)); return this; } + public MapLibre getMap() { + if(map == null) { + setMap(new MapLibre()); + } + return map; + } + + protected void setMap(MapLibre map) { + this.map = map; + add(map); + drawControl = null; + } + + public DrawControl getDrawControl() { + if(drawControl == null) { + drawControl = new DrawControl(map); + } + return drawControl; + } @Override public void setHeight(String height) { super.setHeight(height); addClassName("maplibre-field-has-size"); - map.setHeightFull(); + getMap().setHeightFull(); } @Override public void setWidth(String width) { super.setWidth(width); - map.setWidth(width); + getMap().setWidth(width); } } diff --git a/src/main/java/org/vaadin/addons/maplibre/LineStringField.java b/src/main/java/org/vaadin/addons/maplibre/LineStringField.java index 79db4c9..5e459dc 100644 --- a/src/main/java/org/vaadin/addons/maplibre/LineStringField.java +++ b/src/main/java/org/vaadin/addons/maplibre/LineStringField.java @@ -18,21 +18,20 @@ public LineStringField(String label) { } @Override - public LineStringField withStyleUrl(String styleUrl) { - super.withStyleUrl(styleUrl); - this.drawControl.addGeometryChangeListener(e -> { + protected void setMap(MapLibre map) { + super.setMap(map); + getDrawControl().addGeometryChangeListener(e -> { GeometryCollection geom = e.getGeom(); lineString = (LineString) geom.getGeometryN(0); updateValue(); }); - return this; } @Override protected void onAttach(AttachEvent attachEvent) { super.onAttach(attachEvent); if(lineString == null) { - drawControl.setMode(DrawControl.DrawMode.DRAW_LINE_STRING); + getDrawControl().setMode(DrawControl.DrawMode.DRAW_LINE_STRING); } } @@ -46,12 +45,12 @@ protected void setPresentationValue(LineString lineString) { this.lineString = lineString; if (lineString == null) { // put into drawing mode - drawControl.setMode(DrawControl.DrawMode.DRAW_POLYGON); + getDrawControl().setMode(DrawControl.DrawMode.DRAW_POLYGON); } else { // edit existing - drawControl.setGeometry(lineString); - drawControl.directSelectFirst(); - map.fitBounds(lineString); + getDrawControl().setGeometry(lineString); + getDrawControl().directSelectFirst(); + getMap().fitBounds(lineString); } } } diff --git a/src/main/java/org/vaadin/addons/maplibre/MapLibre.java b/src/main/java/org/vaadin/addons/maplibre/MapLibre.java index 6684b7b..58d8429 100644 --- a/src/main/java/org/vaadin/addons/maplibre/MapLibre.java +++ b/src/main/java/org/vaadin/addons/maplibre/MapLibre.java @@ -7,15 +7,15 @@ import com.vaadin.flow.component.Tag; import com.vaadin.flow.component.page.PendingJavaScriptResult; import com.vaadin.flow.dom.DomEvent; +import com.vaadin.flow.server.VaadinContext; +import com.vaadin.flow.server.VaadinService; import elemental.json.JsonObject; -import elemental.json.JsonValue; import org.apache.commons.io.IOUtils; import org.apache.velocity.VelocityContext; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; -import org.locationtech.jts.geom.LinearRing; import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.geom.PrecisionModel; @@ -50,6 +50,22 @@ public class MapLibre extends AbstractVelocityJsComponent implements HasSize, Ha private HashMap jsCallbacks = new HashMap<>(); private List mapClickListeners; + public MapLibre() { + VaadinContext context = VaadinService.getCurrent().getContext(); + Object o = context.getAttribute(MapLibreBaseMapProvider.class).provideBaseStyle(); + if (o instanceof String url) { + init(null, url); + } else if(o instanceof InputStream styleJson) { + try { + init(IOUtils.toString(styleJson, Charset.defaultCharset()), null); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else if (o instanceof URI uri) { + init(null, uri.toString()); + } + } + public MapLibre(URI styleUrl) { init(null, styleUrl.toString()); } @@ -469,13 +485,15 @@ public String toString() { } public class MapClickEvent { - private final Layer layer; + private Layer layer; private final Coordinate point; private final Coordinate pixelCoordinate; public MapClickEvent(DomEvent domEvent) { - String fId = domEvent.getEventData().getString("event.featureId"); - this.layer = idToLayer.get(fId); + if(domEvent.getEventData().hasKey("event.featureId")) { + String fId = domEvent.getEventData().getString("event.featureId"); + this.layer = idToLayer.get(fId); + } try { LngLatRecord ll = AbstractKebabCasedDto.mapper.readValue( domEvent.getEventData().getString("event.lngLat"), LngLatRecord.class); diff --git a/src/main/java/org/vaadin/addons/maplibre/MapLibreBaseMapProvider.java b/src/main/java/org/vaadin/addons/maplibre/MapLibreBaseMapProvider.java new file mode 100644 index 0000000..6b481a9 --- /dev/null +++ b/src/main/java/org/vaadin/addons/maplibre/MapLibreBaseMapProvider.java @@ -0,0 +1,13 @@ +package org.vaadin.addons.maplibre; + +/** + * Used configure the default base map styles application wide. + */ +public interface MapLibreBaseMapProvider { + + /** + * @return the base map style as String, URI or InputStream + */ + Object provideBaseStyle(); + +} diff --git a/src/main/java/org/vaadin/addons/maplibre/PointField.java b/src/main/java/org/vaadin/addons/maplibre/PointField.java index ca75fa7..a9c37c7 100644 --- a/src/main/java/org/vaadin/addons/maplibre/PointField.java +++ b/src/main/java/org/vaadin/addons/maplibre/PointField.java @@ -1,15 +1,9 @@ package org.vaadin.addons.maplibre; -import com.vaadin.flow.component.AttachEvent; -import com.vaadin.flow.component.customfield.CustomField; import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.GeometryCollection; -import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; -import org.locationtech.jts.geom.Polygon; -public class PointField extends CustomField implements Marker.DragEndListener { - MapLibre map; +public class PointField extends AbstractFeatureField implements Marker.DragEndListener { private Point point; private Marker marker; @@ -21,23 +15,6 @@ public PointField(String label) { public PointField() { } - public void setHeight(String height) { - super.setHeight(height); - addClassName("maplibre-field-has-size"); - map.setHeightFull(); - } - - @Override - public void setWidth(String width) { - super.setWidth(width); - map.setWidth(width); - } - - @Override - protected void onAttach(AttachEvent attachEvent) { - super.onAttach(attachEvent); - } - @Override protected Point generateModelValue() { return point; @@ -51,39 +28,38 @@ protected void setPresentationValue(Point point) { } else { // edit existing if(marker == null) { - marker = map.addMarker(point) + marker = getMap().addMarker(point) .addDragEndListener(this); } else { marker.setPoint(point); } - map.setCenter(point.getX(), point.getY()); + getMap().setCenter(point.getX(), point.getY()); } } - public PointField withStyleUrl(String styleUrl) { - this.map = new MapLibre(styleUrl); - map.addMapClickListener(event -> { + @Override + protected void setMap(MapLibre map) { + super.setMap(map); + getMap().addMapClickListener(event -> { Coordinate coordinate = event.getPoint(); - assingPointFromCoordinate(coordinate); + assignPointFromCoordinate(coordinate); if(marker == null) { - marker = map.addMarker(point) + marker = getMap().addMarker(point) .addDragEndListener(this); } else { marker.setPoint(point); } updateValue(); }); - add(map); - return this; } - private void assingPointFromCoordinate(Coordinate coordinate) { + private void assignPointFromCoordinate(Coordinate coordinate) { point = MapLibre.gf.createPoint(coordinate); } @Override public void dragEnd(Coordinate coordinate) { - assingPointFromCoordinate(coordinate); + assignPointFromCoordinate(coordinate); updateValue(); } } diff --git a/src/main/java/org/vaadin/addons/maplibre/PolygonField.java b/src/main/java/org/vaadin/addons/maplibre/PolygonField.java index 158ee43..e88fb84 100644 --- a/src/main/java/org/vaadin/addons/maplibre/PolygonField.java +++ b/src/main/java/org/vaadin/addons/maplibre/PolygonField.java @@ -24,7 +24,7 @@ public PolygonField() { cutHole.addClassName("maplibre-cut-hole"); cutHole.setTooltipText("Cut a new whole to the current polygon."); cutHole.addClickListener(e -> { - drawControl.setMode(DrawControl.DrawMode.DRAW_POLYGON); + getDrawControl().setMode(DrawControl.DrawMode.DRAW_POLYGON); cuttingHole = true; }); } @@ -35,9 +35,9 @@ public PolygonField(String label) { } @Override - public PolygonField withStyleUrl(String styleUrl) { - super.withStyleUrl(styleUrl); - this.drawControl.addGeometryChangeListener(e -> { + protected void setMap(MapLibre map) { + super.setMap(map); + getDrawControl().addGeometryChangeListener(e -> { GeometryCollection geom = e.getGeom(); if(cuttingHole) { cuttingHole = false; @@ -47,13 +47,13 @@ public PolygonField withStyleUrl(String styleUrl) { } catch (Exception ex) { Notification.show("Cutting hole failed, make sure it is withing the existing Polygon and doesn't conflict other holes."); } - drawControl.setGeometry(polygon); + getDrawControl().setGeometry(polygon); } else { polygon = (Polygon) geom.getGeometryN(0); + cutHole.setVisible(allowCuttingHoles && polygon != null); } updateValue(); }); - return this; } public PolygonField withAllowCuttingHoles(boolean allow) { @@ -65,7 +65,7 @@ public PolygonField withAllowCuttingHoles(boolean allow) { protected void onAttach(AttachEvent attachEvent) { super.onAttach(attachEvent); if(polygon == null) { - drawControl.setMode(DrawControl.DrawMode.DRAW_POLYGON); + getDrawControl().setMode(DrawControl.DrawMode.DRAW_POLYGON); } } @@ -80,13 +80,13 @@ protected void setPresentationValue(Polygon polygon) { cutHole.setVisible(allowCuttingHoles && polygon != null); if (polygon == null) { // put into drawing mode - drawControl.setMode(DrawControl.DrawMode.DRAW_POLYGON); + getDrawControl().setMode(DrawControl.DrawMode.DRAW_POLYGON); } else { // edit existing - drawControl.setGeometry(polygon); - drawControl.setMode(DrawControl.DrawMode.SIMPLE_SELECT); - drawControl.directSelectFirst(); - map.fitBounds(polygon); + getDrawControl().setGeometry(polygon); + getDrawControl().setMode(DrawControl.DrawMode.SIMPLE_SELECT); + getDrawControl().directSelectFirst(); + getMap().fitBounds(polygon); } } diff --git a/src/test/java/org/vaadin/addons/maplibre/BinderCompatibleFields.java b/src/test/java/org/vaadin/addons/maplibre/BinderCompatibleFields.java index 3b9c198..3b76cba 100644 --- a/src/test/java/org/vaadin/addons/maplibre/BinderCompatibleFields.java +++ b/src/test/java/org/vaadin/addons/maplibre/BinderCompatibleFields.java @@ -8,6 +8,7 @@ import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.data.binder.Binder; import com.vaadin.flow.router.Route; +import com.vaadin.flow.server.VaadinService; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.Polygon; @@ -26,15 +27,15 @@ public class BinderCompatibleFields extends VVerticalLayout { private final Binder binder; private TextField name = new TextField("Name (just as a reference)"); private PolygonField polygon = new PolygonField("Polygon (org.locationtech.jts.geom.Polygon)") - .withStyleUrl(basemapStyle) .withAllowCuttingHoles(true); - private LineStringField line = new LineStringField("LineString") - .withStyleUrl(basemapStyle); - private PointField point = new PointField("Point") - .withStyleUrl(basemapStyle); + private LineStringField line = new LineStringField("LineString"); + private PointField point = new PointField("Point"); public BinderCompatibleFields() { + // Typically you should set this in some configuration bean + VaadinService.getCurrent().getContext().setAttribute(MapLibreBaseMapProvider.class, () -> basemapStyle); + configure(polygon); configure(line); configure(point);