Skip to content

Commit

Permalink
[google_maps_flutter] Converts map configuration and platform view cr…
Browse files Browse the repository at this point in the history
…eation params to Pigeon (#7207)

For both Android and iOS, convert the platform view creation parameters to a typed structure using Pigeon, via the ability to set a custom codec for the parameter, instead of a JSON dictionary, as well as converting the map configuration structure used in both those params and `updateMapConfiguration`.

This change removes the last high-level use of non-Pigeon code in the plugin. The remaining uses of JSON are now internal to individual maps objects, which means that it should now be the case that all future changes to this plugin use Pigeon structures rather than JSON. (The individual objects don't change often, if at all, and it would be reasonable if someone does want to add a new parameter to one of those objects to require converting that specific object, as that would not require sweeping changes or knowledge of how to do a more holistic Pigeon conversion.)

Part of flutter/flutter#117907
  • Loading branch information
stuartmorgan authored Aug 8, 2024
1 parent bd8db03 commit bb797b9
Show file tree
Hide file tree
Showing 62 changed files with 3,697 additions and 1,252 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.14.0

* Updates map configuration and platform view creation parameters to use Pigeon.

## 2.13.0

* Adds support for heatmap layers.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,6 @@ void setGoogleMap(GoogleMap googleMap) {
this.googleMap = googleMap;
}

void addJsonCircles(List<Object> circlesToAdd) {
if (circlesToAdd != null) {
for (Object circleToAdd : circlesToAdd) {
@SuppressWarnings("unchecked")
Map<String, ?> circleMap = (Map<String, ?>) circleToAdd;
addJsonCircle(circleMap);
}
}
}

void addCircles(@NonNull List<Messages.PlatformCircle> circlesToAdd) {
for (Messages.PlatformCircle circleToAdd : circlesToAdd) {
addJsonCircle(circleToAdd.getJson());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,6 @@ private void initListenersForClusterManager(
clusterManager.setOnClusterItemClickListener(clusterItemClickListener);
}

/** Adds new ClusterManagers to the controller. */
void addJsonClusterManagers(@NonNull List<Object> clusterManagersToAdd) {
for (Object clusterToAdd : clusterManagersToAdd) {
String clusterManagerId = getClusterManagerId(clusterToAdd);
if (clusterManagerId == null) {
throw new IllegalArgumentException("clusterManagerId was null");
}
addClusterManager(clusterManagerId);
}
}

/** Adds new ClusterManagers to the controller. */
void addClusterManagers(@NonNull List<Messages.PlatformClusterManager> clusterManagersToAdd) {
for (Messages.PlatformClusterManager clusterToAdd : clusterManagersToAdd) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@

package io.flutter.plugins.googlemaps;

import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_HYBRID;
import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_NONE;
import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_NORMAL;
import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_SATELLITE;
import static com.google.android.gms.maps.GoogleMap.MAP_TYPE_TERRAIN;

import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
Expand Down Expand Up @@ -44,7 +50,6 @@
/** Conversions between JSON-like values and GoogleMaps data types. */
class Convert {
// These constants must match the corresponding constants in serialization.dart
public static final String HEATMAPS_TO_ADD_KEY = "heatmapsToAdd";
public static final String HEATMAP_ID_KEY = "heatmapId";
public static final String HEATMAP_DATA_KEY = "data";
public static final String HEATMAP_GRADIENT_KEY = "gradient";
Expand Down Expand Up @@ -313,6 +318,16 @@ private static boolean toBoolean(Object o) {
return (Boolean) o;
}

static @NonNull CameraPosition cameraPositionFromPigeon(
@NonNull Messages.PlatformCameraPosition position) {
final CameraPosition.Builder builder = CameraPosition.builder();
builder.bearing(position.getBearing().floatValue());
builder.target(latLngFromPigeon(position.getTarget()));
builder.tilt(position.getTilt().floatValue());
builder.zoom(position.getZoom().floatValue());
return builder.build();
}

static CameraPosition toCameraPosition(Object o) {
final Map<?, ?> data = toMap(o);
final CameraPosition.Builder builder = CameraPosition.builder();
Expand Down Expand Up @@ -364,14 +379,30 @@ private static float toFloat(Object o) {
return ((Number) o).floatValue();
}

private static Float toFloatWrapper(Object o) {
return (o == null) ? null : toFloat(o);
private static @Nullable Float nullableDoubleToFloat(@Nullable Double d) {
return (d == null) ? null : d.floatValue();
}

private static int toInt(Object o) {
return ((Number) o).intValue();
}

static int toMapType(@NonNull Messages.PlatformMapType type) {
switch (type) {
case NONE:
return MAP_TYPE_NONE;
case NORMAL:
return MAP_TYPE_NORMAL;
case SATELLITE:
return MAP_TYPE_SATELLITE;
case TERRAIN:
return MAP_TYPE_TERRAIN;
case HYBRID:
return MAP_TYPE_HYBRID;
}
return MAP_TYPE_NORMAL;
}

static @Nullable MapsInitializer.Renderer toMapRendererType(
@Nullable Messages.PlatformRendererType type) {
if (type == null) {
Expand All @@ -396,49 +427,17 @@ private static int toInt(Object o) {
.build();
}

static Object latLngBoundsToJson(LatLngBounds latLngBounds) {
final Map<String, Object> arguments = new HashMap<>(2);
arguments.put("southwest", latLngToJson(latLngBounds.southwest));
arguments.put("northeast", latLngToJson(latLngBounds.northeast));
return arguments;
}

static Messages.PlatformLatLngBounds latLngBoundsToPigeon(LatLngBounds latLngBounds) {
return new Messages.PlatformLatLngBounds.Builder()
.setNortheast(latLngToPigeon(latLngBounds.northeast))
.setSouthwest(latLngToPigeon(latLngBounds.southwest))
.build();
}

static Object markerIdToJson(String markerId) {
if (markerId == null) {
return null;
}
final Map<String, Object> data = new HashMap<>(1);
data.put("markerId", markerId);
return data;
}

static Object polygonIdToJson(String polygonId) {
if (polygonId == null) {
return null;
}
final Map<String, Object> data = new HashMap<>(1);
data.put("polygonId", polygonId);
return data;
}

static Object polylineIdToJson(String polylineId) {
if (polylineId == null) {
return null;
}
final Map<String, Object> data = new HashMap<>(1);
data.put("polylineId", polylineId);
return data;
}

static Object latLngToJson(LatLng latLng) {
return Arrays.asList(latLng.latitude, latLng.longitude);
static @NonNull LatLngBounds latLngBoundsFromPigeon(
@NonNull Messages.PlatformLatLngBounds bounds) {
return new LatLngBounds(
latLngFromPigeon(bounds.getSouthwest()), latLngFromPigeon(bounds.getNortheast()));
}

static Messages.PlatformLatLng latLngToPigeon(LatLng latLng) {
Expand Down Expand Up @@ -571,92 +570,90 @@ private static String toString(Object o) {
return (String) o;
}

static void interpretGoogleMapOptions(Object o, GoogleMapOptionsSink sink) {
final Map<?, ?> data = toMap(o);
final Object cameraTargetBounds = data.get("cameraTargetBounds");
static void interpretMapConfiguration(
@NonNull Messages.PlatformMapConfiguration config, @NonNull GoogleMapOptionsSink sink) {
final Messages.PlatformCameraTargetBounds cameraTargetBounds = config.getCameraTargetBounds();
if (cameraTargetBounds != null) {
final List<?> targetData = toList(cameraTargetBounds);
sink.setCameraTargetBounds(toLatLngBounds(targetData.get(0)));
final @Nullable Messages.PlatformLatLngBounds bounds = cameraTargetBounds.getBounds();
sink.setCameraTargetBounds(bounds == null ? null : latLngBoundsFromPigeon(bounds));
}
final Object compassEnabled = data.get("compassEnabled");
final Boolean compassEnabled = config.getCompassEnabled();
if (compassEnabled != null) {
sink.setCompassEnabled(toBoolean(compassEnabled));
sink.setCompassEnabled(compassEnabled);
}
final Object mapToolbarEnabled = data.get("mapToolbarEnabled");
final Boolean mapToolbarEnabled = config.getMapToolbarEnabled();
if (mapToolbarEnabled != null) {
sink.setMapToolbarEnabled(toBoolean(mapToolbarEnabled));
sink.setMapToolbarEnabled(mapToolbarEnabled);
}
final Object mapType = data.get("mapType");
final Messages.PlatformMapType mapType = config.getMapType();
if (mapType != null) {
sink.setMapType(toInt(mapType));
sink.setMapType(toMapType(mapType));
}
final Object minMaxZoomPreference = data.get("minMaxZoomPreference");
final Messages.PlatformZoomRange minMaxZoomPreference = config.getMinMaxZoomPreference();
if (minMaxZoomPreference != null) {
final List<?> zoomPreferenceData = toList(minMaxZoomPreference);
sink.setMinMaxZoomPreference( //
toFloatWrapper(zoomPreferenceData.get(0)), //
toFloatWrapper(zoomPreferenceData.get(1)));
sink.setMinMaxZoomPreference(
nullableDoubleToFloat(minMaxZoomPreference.getMin()),
nullableDoubleToFloat(minMaxZoomPreference.getMax()));
}
final Object padding = data.get("padding");
final Messages.PlatformEdgeInsets padding = config.getPadding();
if (padding != null) {
final List<?> paddingData = toList(padding);
sink.setPadding(
toFloat(paddingData.get(0)),
toFloat(paddingData.get(1)),
toFloat(paddingData.get(2)),
toFloat(paddingData.get(3)));
padding.getTop().floatValue(),
padding.getLeft().floatValue(),
padding.getBottom().floatValue(),
padding.getRight().floatValue());
}
final Object rotateGesturesEnabled = data.get("rotateGesturesEnabled");
final Boolean rotateGesturesEnabled = config.getRotateGesturesEnabled();
if (rotateGesturesEnabled != null) {
sink.setRotateGesturesEnabled(toBoolean(rotateGesturesEnabled));
sink.setRotateGesturesEnabled(rotateGesturesEnabled);
}
final Object scrollGesturesEnabled = data.get("scrollGesturesEnabled");
final Boolean scrollGesturesEnabled = config.getScrollGesturesEnabled();
if (scrollGesturesEnabled != null) {
sink.setScrollGesturesEnabled(toBoolean(scrollGesturesEnabled));
sink.setScrollGesturesEnabled(scrollGesturesEnabled);
}
final Object tiltGesturesEnabled = data.get("tiltGesturesEnabled");
final Boolean tiltGesturesEnabled = config.getTiltGesturesEnabled();
if (tiltGesturesEnabled != null) {
sink.setTiltGesturesEnabled(toBoolean(tiltGesturesEnabled));
sink.setTiltGesturesEnabled(tiltGesturesEnabled);
}
final Object trackCameraPosition = data.get("trackCameraPosition");
final Boolean trackCameraPosition = config.getTrackCameraPosition();
if (trackCameraPosition != null) {
sink.setTrackCameraPosition(toBoolean(trackCameraPosition));
sink.setTrackCameraPosition(trackCameraPosition);
}
final Object zoomGesturesEnabled = data.get("zoomGesturesEnabled");
final Boolean zoomGesturesEnabled = config.getZoomGesturesEnabled();
if (zoomGesturesEnabled != null) {
sink.setZoomGesturesEnabled(toBoolean(zoomGesturesEnabled));
sink.setZoomGesturesEnabled(zoomGesturesEnabled);
}
final Object liteModeEnabled = data.get("liteModeEnabled");
final Boolean liteModeEnabled = config.getLiteModeEnabled();
if (liteModeEnabled != null) {
sink.setLiteModeEnabled(toBoolean(liteModeEnabled));
sink.setLiteModeEnabled(liteModeEnabled);
}
final Object myLocationEnabled = data.get("myLocationEnabled");
final Boolean myLocationEnabled = config.getMyLocationEnabled();
if (myLocationEnabled != null) {
sink.setMyLocationEnabled(toBoolean(myLocationEnabled));
sink.setMyLocationEnabled(myLocationEnabled);
}
final Object zoomControlsEnabled = data.get("zoomControlsEnabled");
final Boolean zoomControlsEnabled = config.getZoomControlsEnabled();
if (zoomControlsEnabled != null) {
sink.setZoomControlsEnabled(toBoolean(zoomControlsEnabled));
sink.setZoomControlsEnabled(zoomControlsEnabled);
}
final Object myLocationButtonEnabled = data.get("myLocationButtonEnabled");
final Boolean myLocationButtonEnabled = config.getMyLocationButtonEnabled();
if (myLocationButtonEnabled != null) {
sink.setMyLocationButtonEnabled(toBoolean(myLocationButtonEnabled));
sink.setMyLocationButtonEnabled(myLocationButtonEnabled);
}
final Object indoorEnabled = data.get("indoorEnabled");
final Boolean indoorEnabled = config.getIndoorViewEnabled();
if (indoorEnabled != null) {
sink.setIndoorEnabled(toBoolean(indoorEnabled));
sink.setIndoorEnabled(indoorEnabled);
}
final Object trafficEnabled = data.get("trafficEnabled");
final Boolean trafficEnabled = config.getTrafficEnabled();
if (trafficEnabled != null) {
sink.setTrafficEnabled(toBoolean(trafficEnabled));
sink.setTrafficEnabled(trafficEnabled);
}
final Object buildingsEnabled = data.get("buildingsEnabled");
final Boolean buildingsEnabled = config.getBuildingsEnabled();
if (buildingsEnabled != null) {
sink.setBuildingsEnabled(toBoolean(buildingsEnabled));
sink.setBuildingsEnabled(buildingsEnabled);
}
final Object style = data.get("style");
final String style = config.getStyle();
if (style != null) {
sink.setMapStyle(toString(style));
sink.setMapStyle(style);
}
}

Expand Down Expand Up @@ -869,7 +866,7 @@ static String interpretCircleOptions(Map<String, ?> data, CircleOptionsSink sink
/**
* Set the options in the given heatmap object to the given sink.
*
* @param o the object expected to be a Map containing the heatmap options. The options map is
* @param data the object expected to be a Map containing the heatmap options. The options map is
* expected to have the following structure:
* <pre>{@code
* {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

import android.content.Context;
import android.graphics.Rect;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.maps.GoogleMapOptions;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLngBounds;
import io.flutter.plugin.common.BinaryMessenger;
import java.util.List;
import java.util.Map;

class GoogleMapBuilder implements GoogleMapOptionsSink {
private final GoogleMapOptions options = new GoogleMapOptions();
Expand All @@ -22,13 +22,13 @@ class GoogleMapBuilder implements GoogleMapOptionsSink {
private boolean indoorEnabled = true;
private boolean trafficEnabled = false;
private boolean buildingsEnabled = true;
private Object initialMarkers;
private Object initialClusterManagers;
private Object initialPolygons;
private Object initialPolylines;
private Object initialCircles;
private Object initialHeatmaps;
private List<Map<String, ?>> initialTileOverlays;
private List<Messages.PlatformMarker> initialMarkers;
private List<Messages.PlatformClusterManager> initialClusterManagers;
private List<Messages.PlatformPolygon> initialPolygons;
private List<Messages.PlatformPolyline> initialPolylines;
private List<Messages.PlatformCircle> initialCircles;
private List<Messages.PlatformHeatmap> initialHeatmaps;
private List<Messages.PlatformTileOverlay> initialTileOverlays;
private Rect padding = new Rect(0, 0, 0, 0);
private @Nullable String style;

Expand Down Expand Up @@ -162,37 +162,38 @@ public void setMyLocationButtonEnabled(boolean myLocationButtonEnabled) {
}

@Override
public void setInitialMarkers(Object initialMarkers) {
public void setInitialMarkers(@NonNull List<Messages.PlatformMarker> initialMarkers) {
this.initialMarkers = initialMarkers;
}

@Override
public void setInitialClusterManagers(Object initialClusterManagers) {
public void setInitialClusterManagers(
@NonNull List<Messages.PlatformClusterManager> initialClusterManagers) {
this.initialClusterManagers = initialClusterManagers;
}

@Override
public void setInitialPolygons(Object initialPolygons) {
public void setInitialPolygons(@NonNull List<Messages.PlatformPolygon> initialPolygons) {
this.initialPolygons = initialPolygons;
}

@Override
public void setInitialPolylines(Object initialPolylines) {
public void setInitialPolylines(@NonNull List<Messages.PlatformPolyline> initialPolylines) {
this.initialPolylines = initialPolylines;
}

@Override
public void setInitialCircles(Object initialCircles) {
public void setInitialCircles(@NonNull List<Messages.PlatformCircle> initialCircles) {
this.initialCircles = initialCircles;
}

@Override
public void setInitialHeatmaps(Object initialHeatmaps) {
public void setInitialHeatmaps(@NonNull List<Messages.PlatformHeatmap> initialHeatmaps) {
this.initialHeatmaps = initialHeatmaps;
}

@Override
public void setInitialTileOverlays(List<Map<String, ?>> initialTileOverlays) {
public void setInitialTileOverlays(
@NonNull List<Messages.PlatformTileOverlay> initialTileOverlays) {
this.initialTileOverlays = initialTileOverlays;
}

Expand Down
Loading

0 comments on commit bb797b9

Please sign in to comment.