Add feature state functionality to Android (#4219)
This commit is contained in:
@@ -8,6 +8,7 @@ import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.maplibre.geojson.Feature;
|
||||
import org.maplibre.geojson.Geometry;
|
||||
import org.maplibre.android.annotations.Marker;
|
||||
@@ -190,6 +191,21 @@ interface NativeMap {
|
||||
@Nullable String[] layerIds,
|
||||
@Nullable Expression filter);
|
||||
|
||||
void setFeatureState(@NonNull String sourceId,
|
||||
@Nullable String sourceLayerId,
|
||||
@NonNull String featureId,
|
||||
@NonNull JsonObject state);
|
||||
|
||||
@Nullable
|
||||
JsonObject getFeatureState(@NonNull String sourceId,
|
||||
@Nullable String sourceLayerId,
|
||||
@NonNull String featureId);
|
||||
|
||||
void removeFeatureState(@NonNull String sourceId,
|
||||
@Nullable String sourceLayerId,
|
||||
@Nullable String featureId,
|
||||
@Nullable String stateKey);
|
||||
|
||||
//
|
||||
// Projection API
|
||||
//
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.annotation.Keep;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.maplibre.geojson.Feature;
|
||||
import org.maplibre.geojson.Geometry;
|
||||
import org.maplibre.android.LibraryLoader;
|
||||
@@ -1123,6 +1124,39 @@ final class NativeMapView implements NativeMap {
|
||||
return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFeatureState(@NonNull String sourceId,
|
||||
@Nullable String sourceLayerId,
|
||||
@NonNull String featureId,
|
||||
@NonNull JsonObject state) {
|
||||
if (checkState("setFeatureState")) {
|
||||
return;
|
||||
}
|
||||
nativeSetFeatureState(sourceId, sourceLayerId, featureId, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JsonObject getFeatureState(@NonNull String sourceId,
|
||||
@Nullable String sourceLayerId,
|
||||
@NonNull String featureId) {
|
||||
if (checkState("getFeatureState")) {
|
||||
return null;
|
||||
}
|
||||
return nativeGetFeatureState(sourceId, sourceLayerId, featureId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFeatureState(@NonNull String sourceId,
|
||||
@Nullable String sourceLayerId,
|
||||
@Nullable String featureId,
|
||||
@Nullable String stateKey) {
|
||||
if (checkState("removeFeatureState")) {
|
||||
return;
|
||||
}
|
||||
nativeRemoveFeatureState(sourceId, sourceLayerId, featureId, stateKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApiBaseUrl(String baseUrl) {
|
||||
if (checkState("setApiBaseUrl")) {
|
||||
@@ -1711,6 +1745,24 @@ final class NativeMapView implements NativeMap {
|
||||
String[] layerIds,
|
||||
Object[] filter);
|
||||
|
||||
@Keep
|
||||
private native void nativeSetFeatureState(String sourceId,
|
||||
String sourceLayerId,
|
||||
String featureId,
|
||||
JsonObject state);
|
||||
|
||||
@Nullable
|
||||
@Keep
|
||||
private native JsonObject nativeGetFeatureState(String sourceId,
|
||||
String sourceLayerId,
|
||||
String featureId);
|
||||
|
||||
@Keep
|
||||
private native void nativeRemoveFeatureState(String sourceId,
|
||||
String sourceLayerId,
|
||||
String featureId,
|
||||
String stateKey);
|
||||
|
||||
@NonNull
|
||||
@Keep
|
||||
private native Light nativeGetLight();
|
||||
|
||||
@@ -1439,6 +1439,16 @@ public class Expression {
|
||||
return new Expression("id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value from feature state.
|
||||
*
|
||||
* @param property the state property to read
|
||||
* @return the expression
|
||||
*/
|
||||
public static Expression featureState(@NonNull String property) {
|
||||
return new Expression("feature-state", literal(property));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a cluster property accumulated so far. Can only be used in the clusterProperties
|
||||
* option of a clustered GeoJSON source.
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.maplibre.android.style.sources
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import androidx.annotation.UiThread
|
||||
import com.google.gson.JsonObject
|
||||
import org.maplibre.geojson.Feature
|
||||
import org.maplibre.geojson.FeatureCollection
|
||||
import org.maplibre.geojson.Geometry
|
||||
@@ -404,6 +405,67 @@ class GeoJsonSource : Source {
|
||||
return nativeGetUrl()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of a feature in this source.
|
||||
*
|
||||
* Feature state can be read in style expressions through `["feature-state", key]`.
|
||||
* The target feature must already have an id in the underlying source data.
|
||||
*
|
||||
* @param featureId the id of the feature whose state to set
|
||||
* @param state a JSON object with the state key-value pairs to merge
|
||||
* @return true if the source is attached to a map and the update was dispatched
|
||||
*/
|
||||
fun setFeatureState(featureId: String, state: JsonObject): Boolean {
|
||||
checkThread()
|
||||
return nativeSetFeatureState(null, featureId, state)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current state of a feature in this source.
|
||||
*
|
||||
* The target feature must already have an id in the underlying source data.
|
||||
*
|
||||
* @param featureId the id of the feature whose state to get
|
||||
* @return the feature state, or null
|
||||
*/
|
||||
fun getFeatureState(featureId: String): JsonObject? {
|
||||
checkThread()
|
||||
return nativeGetFeatureState(null, featureId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes state from a feature in this source, or from all features when [featureId] is null.
|
||||
*
|
||||
* @param featureId the id of the feature, or null to target all features
|
||||
* @param stateKey the state key to remove, or null to remove all keys
|
||||
* @return true if the source is attached to a map and the update was dispatched
|
||||
*/
|
||||
fun removeFeatureState(featureId: String?, stateKey: String?): Boolean {
|
||||
checkThread()
|
||||
return nativeRemoveFeatureState(null, featureId, stateKey)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all state from a single feature in this source.
|
||||
*
|
||||
* @param featureId the id of the feature
|
||||
* @return true if the source is attached to a map and the update was dispatched
|
||||
*/
|
||||
fun removeFeatureState(featureId: String): Boolean {
|
||||
checkThread()
|
||||
return nativeRemoveFeatureState(null, featureId, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all feature state entries from this source.
|
||||
*
|
||||
* @return true if the source is attached to a map and the update was dispatched
|
||||
*/
|
||||
fun resetFeatureStates(): Boolean {
|
||||
checkThread()
|
||||
return nativeRemoveFeatureState(null, null, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the source for features.
|
||||
*
|
||||
|
||||
@@ -4,6 +4,7 @@ import androidx.annotation.Keep;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import org.maplibre.android.LibraryLoader;
|
||||
import org.maplibre.android.utils.ThreadUtils;
|
||||
|
||||
@@ -198,6 +199,21 @@ public abstract class Source {
|
||||
@Keep
|
||||
protected native Long nativeGetMinimumTileUpdateInterval();
|
||||
|
||||
@Keep
|
||||
protected native boolean nativeSetFeatureState(@Nullable String sourceLayerId,
|
||||
@NonNull String featureId,
|
||||
@NonNull JsonObject state);
|
||||
|
||||
@Nullable
|
||||
@Keep
|
||||
protected native JsonObject nativeGetFeatureState(@Nullable String sourceLayerId,
|
||||
@NonNull String featureId);
|
||||
|
||||
@Keep
|
||||
protected native boolean nativeRemoveFeatureState(@Nullable String sourceLayerId,
|
||||
@Nullable String featureId,
|
||||
@Nullable String stateKey);
|
||||
|
||||
public void setDetached() {
|
||||
detached = true;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.net.Uri
|
||||
import androidx.annotation.Keep
|
||||
import androidx.annotation.Size
|
||||
import androidx.annotation.UiThread
|
||||
import com.google.gson.JsonObject
|
||||
import org.maplibre.geojson.Feature
|
||||
import org.maplibre.android.style.expressions.Expression
|
||||
import java.net.URL
|
||||
@@ -102,6 +103,73 @@ class VectorSource : Source {
|
||||
initialize(id, tileSet.toValueObject())
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of a feature in this source.
|
||||
*
|
||||
* Feature state can be read in style expressions through `["feature-state", key]`.
|
||||
* The target feature must already have an id in the underlying source data.
|
||||
*
|
||||
* @param sourceLayerId the source layer id
|
||||
* @param featureId the id of the feature whose state to set
|
||||
* @param state a JSON object with the state key-value pairs to merge
|
||||
* @return true if the source is attached to a map and the update was dispatched
|
||||
*/
|
||||
fun setFeatureState(sourceLayerId: String, featureId: String, state: JsonObject): Boolean {
|
||||
checkThread()
|
||||
return nativeSetFeatureState(sourceLayerId, featureId, state)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current state of a feature in this source.
|
||||
*
|
||||
* The target feature must already have an id in the underlying source data.
|
||||
*
|
||||
* @param sourceLayerId the source layer id
|
||||
* @param featureId the id of the feature whose state to get
|
||||
* @return the feature state, or null
|
||||
*/
|
||||
fun getFeatureState(sourceLayerId: String, featureId: String): JsonObject? {
|
||||
checkThread()
|
||||
return nativeGetFeatureState(sourceLayerId, featureId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes state from a feature in this source, or from all features in a source layer
|
||||
* when [featureId] is null.
|
||||
*
|
||||
* @param sourceLayerId the source layer id
|
||||
* @param featureId the id of the feature, or null to target all features
|
||||
* @param stateKey the state key to remove, or null to remove all keys
|
||||
* @return true if the source is attached to a map and the update was dispatched
|
||||
*/
|
||||
fun removeFeatureState(sourceLayerId: String, featureId: String?, stateKey: String?): Boolean {
|
||||
checkThread()
|
||||
return nativeRemoveFeatureState(sourceLayerId, featureId, stateKey)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all state from a single feature in this source.
|
||||
*
|
||||
* @param sourceLayerId the source layer id
|
||||
* @param featureId the id of the feature
|
||||
* @return true if the source is attached to a map and the update was dispatched
|
||||
*/
|
||||
fun removeFeatureState(sourceLayerId: String, featureId: String): Boolean {
|
||||
checkThread()
|
||||
return nativeRemoveFeatureState(sourceLayerId, featureId, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all feature state entries from the given source layer.
|
||||
*
|
||||
* @param sourceLayerId the source layer id
|
||||
* @return true if the source is attached to a map and the update was dispatched
|
||||
*/
|
||||
fun resetFeatureStates(sourceLayerId: String): Boolean {
|
||||
checkThread()
|
||||
return nativeRemoveFeatureState(sourceLayerId, null, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the source for features.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user