From 0a8880d15d604ace5282726a3bdae2020b6c6657 Mon Sep 17 00:00:00 2001 From: Paola De Bartolo Date: Fri, 9 Oct 2026 17:30:20 -0300 Subject: [PATCH 1/6] build: update web component dependency to 3.10.1 --- .../com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java | 2 +- .../flowingcode/vaadin/addons/googlemaps/GoogleMapMarker.java | 2 +- .../flowingcode/vaadin/addons/googlemaps/GoogleMapPoint.java | 2 +- .../com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoly.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java index 8f41cd9..c745eec 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java +++ b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java @@ -51,7 +51,7 @@ @SuppressWarnings("serial") @Tag("google-map") @JsModule("@flowingcode/google-map/google-map.js") -@NpmPackage(value = "@flowingcode/google-map", version = "3.9.0") +@NpmPackage(value = "@flowingcode/google-map", version = "3.10.1") @NpmPackage(value = "@googlemaps/markerclusterer", version = "2.0.8") @JsModule("./googlemaps/geolocation.js") @ExtensionMethod(value = JsonMigration.class, suppressBaseMethods = true) diff --git a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapMarker.java b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapMarker.java index 6c06b48..6a48e16 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapMarker.java +++ b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapMarker.java @@ -41,7 +41,7 @@ @SuppressWarnings("serial") @Tag("google-map-marker") @JsModule("@flowingcode/google-map/google-map-marker.js") -@NpmPackage(value = "@flowingcode/google-map", version = "3.9.0") +@NpmPackage(value = "@flowingcode/google-map", version = "3.10.1") @NpmPackage(value = "@googlemaps/markerclusterer", version = "2.0.8") @ExtensionMethod(value = JsonMigration.class, suppressBaseMethods = true) public class GoogleMapMarker extends Component { diff --git a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoint.java b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoint.java index f22cfdd..d710a9b 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoint.java +++ b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoint.java @@ -28,7 +28,7 @@ @SuppressWarnings("serial") @Tag("google-map-point") @JsModule("@flowingcode/google-map/google-map-point.js") -@NpmPackage(value = "@flowingcode/google-map", version = "3.9.0") +@NpmPackage(value = "@flowingcode/google-map", version = "3.10.1") @NpmPackage(value = "@googlemaps/markerclusterer", version = "2.0.8") public class GoogleMapPoint extends Component { diff --git a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoly.java b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoly.java index c8b1e1d..033889d 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoly.java +++ b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoly.java @@ -41,7 +41,7 @@ @Tag("google-map-poly") @JsModule("@flowingcode/google-map/google-map-poly.js") @JsModule("@flowingcode/google-map/google-map-point.js") -@NpmPackage(value = "@flowingcode/google-map", version = "3.9.0") +@NpmPackage(value = "@flowingcode/google-map", version = "3.10.1") @NpmPackage(value = "@googlemaps/markerclusterer", version = "2.0.8") @ExtensionMethod(value = JsonMigration.class, suppressBaseMethods = true) public abstract class GoogleMapPoly extends Component { From c00d1ff4758a0927d8f755c410d9c3c56887a433 Mon Sep 17 00:00:00 2001 From: Paola De Bartolo Date: Wed, 14 Oct 2026 17:37:53 -0300 Subject: [PATCH 2/6] build: upgrade markerclusterer to 2.6.2 --- .../com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java | 2 +- .../flowingcode/vaadin/addons/googlemaps/GoogleMapMarker.java | 2 +- .../flowingcode/vaadin/addons/googlemaps/GoogleMapPoint.java | 2 +- .../com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoly.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java index c745eec..8cd7411 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java +++ b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java @@ -52,7 +52,7 @@ @Tag("google-map") @JsModule("@flowingcode/google-map/google-map.js") @NpmPackage(value = "@flowingcode/google-map", version = "3.10.1") -@NpmPackage(value = "@googlemaps/markerclusterer", version = "2.0.8") +@NpmPackage(value = "@googlemaps/markerclusterer", version = "2.6.2") @JsModule("./googlemaps/geolocation.js") @ExtensionMethod(value = JsonMigration.class, suppressBaseMethods = true) public class GoogleMap extends Component implements HasSize { diff --git a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapMarker.java b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapMarker.java index 6a48e16..0f57c6f 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapMarker.java +++ b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapMarker.java @@ -42,7 +42,7 @@ @Tag("google-map-marker") @JsModule("@flowingcode/google-map/google-map-marker.js") @NpmPackage(value = "@flowingcode/google-map", version = "3.10.1") -@NpmPackage(value = "@googlemaps/markerclusterer", version = "2.0.8") +@NpmPackage(value = "@googlemaps/markerclusterer", version = "2.6.2") @ExtensionMethod(value = JsonMigration.class, suppressBaseMethods = true) public class GoogleMapMarker extends Component { diff --git a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoint.java b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoint.java index d710a9b..5f44e67 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoint.java +++ b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoint.java @@ -29,7 +29,7 @@ @Tag("google-map-point") @JsModule("@flowingcode/google-map/google-map-point.js") @NpmPackage(value = "@flowingcode/google-map", version = "3.10.1") -@NpmPackage(value = "@googlemaps/markerclusterer", version = "2.0.8") +@NpmPackage(value = "@googlemaps/markerclusterer", version = "2.6.2") public class GoogleMapPoint extends Component { public GoogleMapPoint(LatLon latlon) { diff --git a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoly.java b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoly.java index 033889d..cabe420 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoly.java +++ b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapPoly.java @@ -42,7 +42,7 @@ @JsModule("@flowingcode/google-map/google-map-poly.js") @JsModule("@flowingcode/google-map/google-map-point.js") @NpmPackage(value = "@flowingcode/google-map", version = "3.10.1") -@NpmPackage(value = "@googlemaps/markerclusterer", version = "2.0.8") +@NpmPackage(value = "@googlemaps/markerclusterer", version = "2.6.2") @ExtensionMethod(value = JsonMigration.class, suppressBaseMethods = true) public abstract class GoogleMapPoly extends Component { From 8799f86faeccc5f40b87a9a8bcf26d29ac8c59dc Mon Sep 17 00:00:00 2001 From: Paola De Bartolo Date: Wed, 7 Oct 2026 18:06:17 -0300 Subject: [PATCH 3/6] build: bump version to 2.7.0-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 690b343..c8f7c26 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.flowingcode.vaadin.addons google-maps - 2.6.1-SNAPSHOT + 2.7.0-SNAPSHOT Google Maps Addon Integration of google-map for Vaadin platform From 9efd13d8a288a5579c4f702f5b4023750d82d4c8 Mon Sep 17 00:00:00 2001 From: Paola De Bartolo Date: Fri, 9 Oct 2026 17:30:36 -0300 Subject: [PATCH 4/6] ci(demo): upgrade commons-demo to 5.5.0 in v25 profile --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c8f7c26..7d83e51 100644 --- a/pom.xml +++ b/pom.xml @@ -559,7 +559,7 @@ 21 25.0.0 11.0.26 - 5.2.0 + 5.5.0 From 23ab23bb225e4d128a501d89427d20ac01e0eb30 Mon Sep 17 00:00:00 2001 From: Paola De Bartolo Date: Fri, 9 Oct 2026 17:30:50 -0300 Subject: [PATCH 5/6] feat: add GoogleMapAdvancedMarker Close #121 --- .../vaadin/addons/googlemaps/GoogleMap.java | 32 ++ .../googlemaps/GoogleMapAdvancedMarker.java | 493 ++++++++++++++++++ 2 files changed, 525 insertions(+) create mode 100644 src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapAdvancedMarker.java diff --git a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java index 8cd7411..0e8007c 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java +++ b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMap.java @@ -270,6 +270,38 @@ public void removeMarker(GoogleMapMarker marker) { getElement().executeJs("this._updateMarkers()"); } + /** + * Adds an advanced marker to the map. Advanced markers require the map to have a Map ID (see + * {@link #setMapId(String)}), set before the map is shown. + * + * @param marker The marker to add. + * @throws IllegalStateException if the map is already shown and has no Map ID + * @since 2.7.0 + */ + public void addMarker(GoogleMapAdvancedMarker marker) { + if (isAttached()) { + // checked before adding the marker, so that it isn't left in the map on failure + GoogleMapAdvancedMarker.checkMapId(this); + } + getElement().appendChild(marker.getElement()); + if (getElement().getParent() != null) { + getElement().executeJs("this._updateMarkers()"); + } + } + + /** + * Removes an advanced marker from the map. + * + * @param marker The marker to remove. + * @since 2.7.0 + */ + @SuppressWarnings("squid:S3242") + public void removeMarker(GoogleMapAdvancedMarker marker) { + getElement().removeChild(marker.getElement()); + // markers need to be updated on removal + getElement().executeJs("this._updateMarkers()"); + } + /** * Sets the type of the base map. * diff --git a/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapAdvancedMarker.java b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapAdvancedMarker.java new file mode 100644 index 0000000..6d6d00c --- /dev/null +++ b/src/main/java/com/flowingcode/vaadin/addons/googlemaps/GoogleMapAdvancedMarker.java @@ -0,0 +1,493 @@ +/*- + * #%L + * Google Maps Addon + * %% + * Copyright (C) 2020 - 2026 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +package com.flowingcode.vaadin.addons.googlemaps; + +import com.flowingcode.vaadin.jsonmigration.JsonMigration; +import com.vaadin.flow.component.AttachEvent; +import com.vaadin.flow.component.ClickEvent; +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.DomEvent; +import com.vaadin.flow.component.EventData; +import com.vaadin.flow.component.Synchronize; +import com.vaadin.flow.component.Tag; +import com.vaadin.flow.component.dependency.JsModule; +import com.vaadin.flow.component.dependency.NpmPackage; +import com.vaadin.flow.shared.Registration; +import lombok.experimental.ExtensionMethod; + +/** + * A marker of the Google Map based on Google's Advanced Markers ({@code AdvancedMarkerElement}), + * the replacement for the deprecated markers used by {@link GoogleMapMarker}. Both kinds of + * markers can be used on the same map. + * + *

Advanced Markers require the map to have a Map ID (see {@link GoogleMap#setMapId(String)}), + * set before the map is shown. Otherwise, an {@link IllegalStateException} is thrown when the + * marker is attached. + * + *

These {@link GoogleMapMarker} features are not available, as Advanced Markers have no + * equivalent: animation, optimization, icon sprites, a label together with an icon, and the font + * and CSS class of a label. + * + * @since 2.7.0 + */ +@SuppressWarnings("serial") +@Tag("google-map-advanced-marker") +@JsModule("@flowingcode/google-map/google-map-advanced-marker.js") +@NpmPackage(value = "@flowingcode/google-map", version = "3.10.1") +@NpmPackage(value = "@googlemaps/markerclusterer", version = "2.6.2") +@ExtensionMethod(value = JsonMigration.class, suppressBaseMethods = true) +public class GoogleMapAdvancedMarker extends Component { + + private static long idCounter = 0; + + private long id; + + /** Instantiates a new GoogleMapAdvancedMarker. */ + public GoogleMapAdvancedMarker() { + id = idCounter; + idCounter++; + this.getElement().setAttribute("slot", "markers"); + } + + /** + * Instantiates a new GoogleMapAdvancedMarker. + * + * @param caption The caption to use. + * @param position The position of the marker + * @param draggable Can marker be dragged? + */ + public GoogleMapAdvancedMarker(String caption, LatLon position, boolean draggable) { + this(); + this.setCaption(caption); + this.setPosition(position); + this.setDraggable(draggable); + } + + /** + * Instantiates a new GoogleMapAdvancedMarker. + * + * @param caption The caption to use. + * @param position The position of the marker + * @param draggable Can marker be dragged? + * @param iconUrl the icon url as a string + */ + public GoogleMapAdvancedMarker(String caption, LatLon position, boolean draggable, + String iconUrl) { + this(caption, position, draggable); + this.setIconUrl(iconUrl); + } + + /** + * Instantiates a new GoogleMapAdvancedMarker. + * + * @param caption The caption to use. + * @param position The position of the marker + * @param draggable Can marker be dragged? + * @param icon the icon image for the marker + */ + public GoogleMapAdvancedMarker(String caption, LatLon position, boolean draggable, + GoogleMapIcon icon) { + this(caption, position, draggable); + this.setIcon(icon); + } + + /** + * Sets the content of the info window that is shown when the marker is clicked. + * + * @param htmlContent the HTML content of the info window + */ + public void addInfoWindow(String htmlContent) { + this.getElement().setProperty("innerHTML", htmlContent); + } + + @Synchronize( + value = {"google-map-marker-open", "google-map-marker-close"}, + property = "open") + public boolean isInfoWindowVisible() { + return this.getElement().getProperty("open", false); + } + + public void setInfoWindowVisible(boolean visible) { + this.getElement().setProperty("open", visible); + } + + /** + * Returns the position of the marker. + * + * @return The position of the marker. + */ + public LatLon getPosition() { + final LatLon latLon = new LatLon(); + latLon.setLat(this.getElement().getProperty("latitude", 0d)); + latLon.setLon(this.getElement().getProperty("longitude", 0d)); + return latLon; + } + + /** + * Sets the position of the marker. + * + * @param position The new position of the marker. + */ + public void setPosition(LatLon position) { + this.getElement().setProperty("latitude", position.getLat()); + this.getElement().setProperty("longitude", position.getLon()); + } + + /** + * Gets the caption of the marker. + * + * @return The caption of the marker. + */ + public String getCaption() { + return this.getElement().getProperty("title"); + } + + /** + * Sets the caption of the marker. + * + * @param caption The new caption of the marker. + */ + public void setCaption(String caption) { + this.getElement().setProperty("title", caption != null ? caption : ""); + } + + /** + * Checks if the marker is draggable. + * + * @return true, if it is draggable + */ + public boolean isDraggable() { + return this.getElement().getProperty("draggable", false); + } + + /** + * Enables/disables dragging of the marker. + * + * @param draggable Set to true to enable dragging. + */ + public void setDraggable(boolean draggable) { + this.getElement().setProperty("draggable", draggable); + } + + /** + * Returns the url of the icon of the marker. + * + * @return the url of the icon, default null. + */ + public String getIconUrl() { + return this.getElement().getProperty("icon"); + } + + /** + * Sets the url of the icon of the marker, which is shown instead of the default pin. + * + * @param iconUrl The new url of the icon. + */ + public void setIconUrl(String iconUrl) { + this.getElement().setProperty("icon", iconUrl); + } + + /** + * Sets the icon image of the marker, which is shown instead of the default pin. A + * {@link MarkerIcon} is shown with its url, scaled size and anchor (sprites are not supported); a + * {@link Symbol} is shown with its SVG path. + * + * @param icon the icon image of the marker + */ + public void setIcon(GoogleMapIcon icon) { + this.getElement().setPropertyJson("icon", icon.getJson()); + } + + /** + * Sets the label of the marker, which is shown in the default pin. Only the text and the color + * of the label are used, and the label is not shown when the marker has an icon. + * + * @param label the new marker's label + */ + public void setLabel(MarkerLabel label) { + this.getElement().setPropertyJson("label", label.getJson()); + } + + /** + * Returns the background color of the default pin. + * + * @return the background color, or null if not set + */ + public String getPinBackground() { + return this.getElement().getProperty("pinBackground"); + } + + /** + * Sets the background color of the default pin. + * + * @param color a CSS color + */ + public void setPinBackground(String color) { + this.getElement().setProperty("pinBackground", color); + } + + /** + * Returns the border color of the default pin. + * + * @return the border color, or null if not set + */ + public String getPinBorderColor() { + return this.getElement().getProperty("pinBorderColor"); + } + + /** + * Sets the border color of the default pin. + * + * @param color a CSS color + */ + public void setPinBorderColor(String color) { + this.getElement().setProperty("pinBorderColor", color); + } + + /** + * Returns the color of the default pin's glyph. + * + * @return the glyph color, or null if not set + */ + public String getPinGlyphColor() { + return this.getElement().getProperty("pinGlyphColor"); + } + + /** + * Sets the color of the default pin's glyph (the circle in its center). + * + * @param color a CSS color + */ + public void setPinGlyphColor(String color) { + this.getElement().setProperty("pinGlyphColor", color); + } + + /** + * Returns the scale of the default pin. + * + * @return the scale, 1 if not set + */ + public double getPinScale() { + return this.getElement().getProperty("pinScale", 1d); + } + + /** + * Sets the scale of the default pin. + * + * @param scale the scale, e.g. 1.5 for a pin 50% larger than the default + */ + public void setPinScale(double scale) { + this.getElement().setProperty("pinScale", scale); + } + + /** + * Checks that the map of this marker has a Map ID, which Advanced Markers require. + * + * @throws IllegalStateException if the map has no Map ID + */ + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + getParent().filter(GoogleMap.class::isInstance).map(GoogleMap.class::cast) + .ifPresent(GoogleMapAdvancedMarker::checkMapId); + } + + // Without a Map ID the marker is silently not shown, and the Map ID of a map can't be changed + // after the map is created, so this is reported as soon as possible. + static void checkMapId(GoogleMap map) { + if (map.getMapId() == null || map.getMapId().isEmpty()) { + throw new IllegalStateException("Advanced markers require a Map ID. " + + "Set it with GoogleMap.setMapId(...) before the map is shown."); + } + } + + public long getIdentifier() { + return id; + } + + public void setIdentifier(long id) { + this.id = id; + } + + /** Event that is called on marker's drag end. */ + @DomEvent("google-map-marker-dragend") + public static class DragEndEvent extends ComponentEvent { + + private final double lat; + private final double lon; + + /** + * Creates a new event with the drag end coordinates. + * + * @param source the marker that was dragged + * @param fromClient whether the event originated on the client side + * @param lat the latitude of the drag end + * @param lon the longitude of the drag end + */ + public DragEndEvent( + GoogleMapAdvancedMarker source, + boolean fromClient, + @EventData("event.detail.latLng.lat()") double lat, + @EventData("event.detail.latLng.lng()") double lon) { + super(source, fromClient); + this.lat = lat; + this.lon = lon; + } + + public double getLatitude() { + return this.lat; + } + + public double getLongitude() { + return this.lon; + } + } + + /** + * Adds a DragEndEvent listener. The listener is called when a marker's drag ends. + * + * @param listener a drag end event listener + * @return a handle that can be used for removing the listener + */ + public Registration addDragEndEventListener(ComponentEventListener listener) { + this.getElement().setProperty("dragEvents", true); + return addListener(DragEndEvent.class, listener); + } + + /** Event called on marker's click. */ + @DomEvent("google-map-marker-click") + public static class GoogleMapAdvancedMarkerClickEvent + extends ClickEvent { + + private final double lat; + private final double lon; + + /** + * Creates a new event with the click coordinates. + * + * @param source the marker that was clicked + * @param fromClient whether the event originated on the client side + * @param lat the latitude of the marker + * @param lon the longitude of the marker + */ + public GoogleMapAdvancedMarkerClickEvent(GoogleMapAdvancedMarker source, boolean fromClient, + @EventData("event.detail.latLng.lat()") double lat, + @EventData("event.detail.latLng.lng()") double lon) { + super(source); + this.lat = lat; + this.lon = lon; + } + + public double getLatitude() { + return this.lat; + } + + public double getLongitude() { + return this.lon; + } + } + + /** + * Adds a click event listener to a marker. + * + * @param listener a click event listener + * @return a handle that can be used for removing the listener + */ + public Registration addClickListener( + ComponentEventListener listener) { + this.getElement().setProperty("clickEvents", true); + return addListener(GoogleMapAdvancedMarkerClickEvent.class, listener); + } + + /** + * Event called on marker's right click. On touch devices, a touch-and-hold on the marker fires + * it too. + */ + @DomEvent("google-map-marker-rightclick") + public static class GoogleMapAdvancedMarkerRightClickEvent + extends ClickEvent { + + private final double lat; + private final double lon; + + /** + * Creates a new event with the right click data. + * + * @param source the marker that was right clicked + * @param fromClient whether the event originated on the client side + * @param screenX the screen X coordinate of the click + * @param screenY the screen Y coordinate of the click + * @param clientX the client X coordinate of the click + * @param clientY the client Y coordinate of the click + * @param clickCount the click count + * @param button the mouse button + * @param ctrlKey whether Ctrl key was pressed + * @param shiftKey whether Shift key was pressed + * @param altKey whether Alt key was pressed + * @param metaKey whether Meta key was pressed + * @param lat the latitude of the marker + * @param lon the longitude of the marker + */ + public GoogleMapAdvancedMarkerRightClickEvent(GoogleMapAdvancedMarker source, + boolean fromClient, + @EventData("event.detail.domEvent.screenX") int screenX, + @EventData("event.detail.domEvent.screenY") int screenY, + @EventData("event.detail.domEvent.clientX") int clientX, + @EventData("event.detail.domEvent.clientY") int clientY, + @EventData("event.detail.domEvent.detail") int clickCount, + @EventData("event.detail.domEvent.button") int button, + @EventData("event.detail.domEvent.ctrlKey") boolean ctrlKey, + @EventData("event.detail.domEvent.shiftKey") boolean shiftKey, + @EventData("event.detail.domEvent.altKey") boolean altKey, + @EventData("event.detail.domEvent.metaKey") boolean metaKey, + @EventData("event.detail.latLng.lat()") double lat, + @EventData("event.detail.latLng.lng()") double lon) { + super(source, fromClient, screenX, screenY, clientX, clientY, clickCount, button, ctrlKey, + shiftKey, altKey, metaKey); + this.lat = lat; + this.lon = lon; + } + + public double getLatitude() { + return this.lat; + } + + public double getLongitude() { + return this.lon; + } + } + + /** + * Adds a right click event listener to a marker. On touch devices, a touch-and-hold on the + * marker fires it too. + * + * @param listener a right click event listener + * @return a handle for the listener + */ + public Registration addRightClickListener( + ComponentEventListener listener) { + this.getElement().setProperty("clickEvents", true); + return addListener(GoogleMapAdvancedMarkerRightClickEvent.class, listener); + } + +} From 84ee8c9e932446e45dcdc7ba0fac04872914040f Mon Sep 17 00:00:00 2001 From: Paola De Bartolo Date: Wed, 7 Oct 2026 18:06:19 -0300 Subject: [PATCH 6/6] feat(demo): add advanced markers demos --- .../AdvancedMarkersClusteringDemo.java | 69 ++++++++++ .../googlemaps/AdvancedMarkersDemo.java | 122 ++++++++++++++++++ .../addons/googlemaps/GooglemapsDemoView.java | 2 + 3 files changed, 193 insertions(+) create mode 100644 src/test/java/com/flowingcode/vaadin/addons/googlemaps/AdvancedMarkersClusteringDemo.java create mode 100644 src/test/java/com/flowingcode/vaadin/addons/googlemaps/AdvancedMarkersDemo.java diff --git a/src/test/java/com/flowingcode/vaadin/addons/googlemaps/AdvancedMarkersClusteringDemo.java b/src/test/java/com/flowingcode/vaadin/addons/googlemaps/AdvancedMarkersClusteringDemo.java new file mode 100644 index 0000000..efd742e --- /dev/null +++ b/src/test/java/com/flowingcode/vaadin/addons/googlemaps/AdvancedMarkersClusteringDemo.java @@ -0,0 +1,69 @@ +/*- + * #%L + * Google Maps Addon + * %% + * Copyright (C) 2020 - 2026 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.flowingcode.vaadin.addons.googlemaps; + +import com.flowingcode.vaadin.addons.demo.DemoSource; +import com.flowingcode.vaadin.addons.googlemaps.GoogleMap.MapType; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; + +@PageTitle("Advanced Markers Clustering Demo") +@DemoSource +@Route(value = "googlemaps/advancedmarkersclustering", layout = GooglemapsDemoView.class) +@SuppressWarnings("serial") +public class AdvancedMarkersClusteringDemo extends AbstractGoogleMapsDemo { + + @Override + protected void createGoogleMapsDemo(String apiKey) { + GoogleMap gmaps = new GoogleMap(apiKey, null, null); + gmaps.setMapType(MapType.ROADMAP); + gmaps.setSizeFull(); + gmaps.setZoom(5); + gmaps.setCenter(new LatLon(-31.636036, -60.7055271)); + // Advanced markers require a Map ID. "DEMO_MAP_ID" can be used for testing; use your own Map ID + // in production. + gmaps.setMapId("DEMO_MAP_ID"); + + gmaps.addMarker(createMarker("Marker 1", new LatLon(-31.646036, -60.7055290), true, "#F06292")); + gmaps.addMarker(createMarker("Marker 2", new LatLon(-31.562346, -60.6176364), true, "#F06292")); + gmaps.addMarker(createMarker("Marker 3", new LatLon(-31.531917, -60.8456027), true, "#F06292")); + gmaps.addMarker(createMarker("Marker 4", new LatLon(-31.651667, -60.9555557), true, "#F06292")); + + gmaps.addMarker(createMarker("Marker 5", new LatLon(-30.997815, -65.60542944), false, "#4285F4")); + gmaps.addMarker(createMarker("Marker 6", new LatLon(-31.298693, -66.50630836), false, "#4285F4")); + gmaps.addMarker(createMarker("Marker 7", new LatLon(-31.878914, -66.28658178), false, "#4285F4")); + + gmaps.addMarker(createMarker("Marker 8", new LatLon(-33.138889, -65.95699194), false, "#34A853")); + gmaps.addMarker(createMarker("Marker 9", new LatLon(-33.322683, -65.12203100), false, "#34A853")); + gmaps.addMarker(createMarker("Marker 10", new LatLon(-33.652538, -65.737265381), false, "#34A853")); + + gmaps.enableMarkersClustering(); + + add(gmaps); + } + + private GoogleMapAdvancedMarker createMarker(String caption, LatLon position, boolean draggable, + String color) { + GoogleMapAdvancedMarker marker = new GoogleMapAdvancedMarker(caption, position, draggable); + marker.setPinBackground(color); + return marker; + } + +} diff --git a/src/test/java/com/flowingcode/vaadin/addons/googlemaps/AdvancedMarkersDemo.java b/src/test/java/com/flowingcode/vaadin/addons/googlemaps/AdvancedMarkersDemo.java new file mode 100644 index 0000000..d4044ac --- /dev/null +++ b/src/test/java/com/flowingcode/vaadin/addons/googlemaps/AdvancedMarkersDemo.java @@ -0,0 +1,122 @@ +/*- + * #%L + * Google Maps Addon + * %% + * Copyright (C) 2020 - 2026 Flowing Code + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +package com.flowingcode.vaadin.addons.googlemaps; + +import com.flowingcode.vaadin.addons.demo.DemoSource; +import com.flowingcode.vaadin.addons.googlemaps.GoogleMap.MapType; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.checkbox.Checkbox; +import com.vaadin.flow.component.notification.Notification; +import com.vaadin.flow.component.orderedlayout.FlexLayout; +import com.vaadin.flow.component.orderedlayout.FlexLayout.FlexWrap; +import com.vaadin.flow.component.textfield.TextField; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; + +@PageTitle("Advanced Markers Demo") +@DemoSource +@Route(value = "googlemaps/advancedmarkers", layout = GooglemapsDemoView.class) +@SuppressWarnings("serial") +public class AdvancedMarkersDemo extends AbstractGoogleMapsDemo { + + @Override + protected void createGoogleMapsDemo(String apiKey) { + GoogleMap gmaps = new GoogleMap(apiKey, null, null); + gmaps.setMapType(MapType.ROADMAP); + gmaps.setSizeFull(); + gmaps.setCenter(new LatLon(-31.636036, -60.7055271)); + gmaps.setZoom(14); + // Advanced markers require a Map ID. "DEMO_MAP_ID" can be used for testing; use your own Map ID + // in production. + gmaps.setMapId("DEMO_MAP_ID"); + + // A marker with a customized pin and an info window + GoogleMapAdvancedMarker flowingCode = + new GoogleMapAdvancedMarker("Flowing Code", new LatLon(-31.636036, -60.7055271), false); + flowingCode.setPinBackground("#1a73e8"); + flowingCode.setPinBorderColor("#0b4f9c"); + flowingCode.setPinGlyphColor("white"); + flowingCode.addInfoWindow("Flowing Code"); + gmaps.addMarker(flowingCode); + + // A draggable marker + GoogleMapAdvancedMarker draggable = + new GoogleMapAdvancedMarker("Drag me", new LatLon(-31.6300, -60.6980), true); + draggable.setPinScale(1.4); + draggable.addDragEndEventListener(e -> Notification.show( + "Dragged to -> Latitude: " + e.getLatitude() + " - Longitude: " + e.getLongitude())); + gmaps.addMarker(draggable); + + // A marker with an image as icon + gmaps.addMarker(new GoogleMapAdvancedMarker("Icon", new LatLon(-31.6420, -60.7120), false, + Markers.GREEN)); + + // A marker using a MarkerIcon: url icon image + anchor point + MarkerIcon markerIcon = new MarkerIcon(Markers.PURPLE); + markerIcon.setAnchor(new GoogleMapPoint(15.0, 10.0)); + gmaps.addMarker(new GoogleMapAdvancedMarker("MarkerIcon", new LatLon(-31.6335, -60.7110), false, + markerIcon)); + + // A marker using a Symbol: svg path for the icon's image + customization + Symbol symbol = new Symbol( + "M-1.547 12l6.563-6.609-1.406-1.406-5.156 5.203-2.063-2.109-1.406 1.406zM0 0q2.906 0 4.945 2.039t2.039 4.945q0 1.453-0.727 3.328t-1.758 3.516-2.039 3.070-1.711 2.273l-0.75 0.797q-0.281-0.328-0.75-0.867t-1.688-2.156-2.133-3.141-1.664-3.445-0.75-3.375q0-2.906 2.039-4.945t4.945-2.039z"); + symbol.setFillColor("purple"); + symbol.setFillOpacity(1.0); + symbol.setAnchor(new GoogleMapPoint(20.0, -0.5)); + symbol.setRotation(180.0); + symbol.setScale(1.5); + gmaps.addMarker(new GoogleMapAdvancedMarker("Symbol", new LatLon(-31.6380, -60.7010), false, + symbol)); + + // A marker with a label, that handles clicks and right clicks (touch-and-hold on touch devices) + GoogleMapAdvancedMarker labeled = + new GoogleMapAdvancedMarker("Label", new LatLon(-31.6400, -60.6960), false); + MarkerLabel label = new MarkerLabel("1"); + label.setColor("white"); + labeled.setLabel(label); + labeled.addClickListener(e -> Notification.show("Clicked")); + labeled.addRightClickListener(e -> Notification.show("Right clicked")); + gmaps.addMarker(labeled); + + // Legacy markers can be used on the same map + gmaps.addMarker(new GoogleMapMarker("Legacy marker", new LatLon(-31.6310, -60.7150), false)); + + TextField labelText = new TextField(); + labelText.setPlaceholder("Label Text"); + Checkbox isDraggable = new Checkbox("Draggable"); + Button addMarker = new Button("Add Advanced Marker", ev -> { + GoogleMapAdvancedMarker marker = + new GoogleMapAdvancedMarker("New Marker", gmaps.getCenter(), isDraggable.getValue()); + if (!labelText.getValue().isEmpty()) { + marker.setLabel(new MarkerLabel(labelText.getValue())); + } + gmaps.addMarker(marker); + }); + + FlexLayout layout = new FlexLayout(); + layout.setFlexWrap(FlexWrap.WRAP); // hide-source + layout.getStyle().set("gap", "var(--lumo-space-s, var(--vaadin-gap-m))"); // hide-source + layout.add(labelText, isDraggable, addMarker); + layout.setAlignItems(Alignment.BASELINE); // hide-source + layout.getStyle().set("margin-top", "0"); // hide-source + add(gmaps, layout); + } +} diff --git a/src/test/java/com/flowingcode/vaadin/addons/googlemaps/GooglemapsDemoView.java b/src/test/java/com/flowingcode/vaadin/addons/googlemaps/GooglemapsDemoView.java index 84c3486..cc54241 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/googlemaps/GooglemapsDemoView.java +++ b/src/test/java/com/flowingcode/vaadin/addons/googlemaps/GooglemapsDemoView.java @@ -49,6 +49,8 @@ public GooglemapsDemoView() { addDemo(TrackLocationDemo.class); addDemo(StyleFeaturesDemo.class); addDemo(CustomControlsDemo.class); + addDemo(AdvancedMarkersDemo.class); + addDemo(AdvancedMarkersClusteringDemo.class); setSizeFull(); } }