Seperate style source fields from MapSource
This commit is contained in:
@@ -61,6 +61,7 @@ dependencies {
|
||||
implementation("com.caverock:androidsvg:1.4")
|
||||
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.0")
|
||||
implementation("commons-codec:commons-codec:1.17.2")
|
||||
implementation("org.apache.commons:commons-lang3:3.14.0")
|
||||
|
||||
testImplementation(libs.junit)
|
||||
|
||||
@@ -5,12 +5,11 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import eu.konggdev.strikemaps.app.AppController;
|
||||
import eu.konggdev.strikemaps.map.source.MapSource;
|
||||
import eu.konggdev.strikemaps.map.source.MapSource.MapSourceContractType;
|
||||
import eu.konggdev.strikemaps.map.source.model.TileSource;
|
||||
import eu.konggdev.strikemaps.map.source.tiles.SourceTiles;
|
||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
||||
import eu.konggdev.strikemaps.map.style.document.StyleDocument;
|
||||
import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata;
|
||||
import eu.konggdev.strikemaps.map.style.options.StyleOptions;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
@@ -36,11 +35,15 @@ public final class UserPrefsHelper {
|
||||
public static Map<Integer, MapStyle> DEFAULT_STYLES(AppController app) {
|
||||
Map<Integer, MapStyle> styles = new HashMap<>();
|
||||
String[] styleAssets = FileHelper.getAssetFiles("bundled/style", ".style.json", app);
|
||||
for (int i = 0; i < styleAssets.length; i++) { styles.put( i,
|
||||
for (int i = 0; i < styleAssets.length; i++) {
|
||||
String styleContents = FileHelper.loadStringFromAssetFile(styleAssets[i], app);
|
||||
styles.put( i,
|
||||
new MapStyle(
|
||||
FileHelper.loadStringFromAssetFile(styleAssets[i], app),
|
||||
styleContents,
|
||||
new StyleOptions(),
|
||||
new StyleManagementMetadata()
|
||||
new StyleManagementMetadata( //Set the style to automatically update from assets
|
||||
false, true, true,
|
||||
"assets://" + styleAssets[i], DigestUtils.sha256Hex(styleContents))
|
||||
));
|
||||
}
|
||||
return styles;
|
||||
@@ -48,16 +51,14 @@ public final class UserPrefsHelper {
|
||||
|
||||
private static final Map<Integer, MapSource> DEFAULT_SOURCES = Map.of(
|
||||
0, new MapSource(
|
||||
MapSourceContractType.DEFINITION,
|
||||
"Strike Maps Planet",
|
||||
new TileSource("https://tiles.strikemaps.eu/planet"),
|
||||
new SourceTiles("https://tiles.strikemaps.eu/planet"),
|
||||
"vector",
|
||||
"smts"
|
||||
),
|
||||
1, new MapSource(
|
||||
MapSourceContractType.DEFINITION,
|
||||
"ArcGIS Imagery",
|
||||
new TileSource(new String[]{"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"}),
|
||||
new SourceTiles(new String[]{"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"}),
|
||||
"raster",
|
||||
"raster"
|
||||
)
|
||||
|
||||
@@ -22,7 +22,8 @@ public class MapComponent implements Component {
|
||||
private final MapRenderer mapRenderer;
|
||||
private final AppController app;
|
||||
|
||||
public MapStyle style;
|
||||
public Integer styleId;
|
||||
|
||||
public Map<Class<? extends MapOverlay>, MapOverlay> overlays = new HashMap<>();
|
||||
|
||||
public MapComponent(AppController ref) {
|
||||
@@ -48,9 +49,8 @@ public class MapComponent implements Component {
|
||||
return new FragmentLayoutContentMap(mapRenderer.getView());
|
||||
}
|
||||
|
||||
public void setStyle(MapStyle style) {
|
||||
this.style = style;
|
||||
mapRenderer.styleUpdate(style.effectiveDocument());
|
||||
public void setStyle(Integer id) {
|
||||
styleId = id;
|
||||
}
|
||||
|
||||
public void switchOverlay(MapOverlay overlay) {
|
||||
@@ -102,9 +102,7 @@ public class MapComponent implements Component {
|
||||
|
||||
public void onMapInit() {
|
||||
setStyle(
|
||||
app.getRegistry().getStyle(
|
||||
UserPrefsHelper.startupMapStyle(app.getPrefs())
|
||||
)
|
||||
UserPrefsHelper.startupMapStyle(app.getPrefs())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -17,8 +17,8 @@ import eu.konggdev.strikemaps.app.util.JsonPatcher;
|
||||
import eu.konggdev.strikemaps.map.MapComponent;
|
||||
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
||||
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
||||
import eu.konggdev.strikemaps.map.source.MapSource;
|
||||
import eu.konggdev.strikemaps.map.style.document.StyleDocument;
|
||||
import eu.konggdev.strikemaps.map.style.source.StyleSource;
|
||||
import org.maplibre.android.geometry.LatLng;
|
||||
import org.maplibre.geojson.Feature;
|
||||
|
||||
@@ -72,8 +72,9 @@ public class MapLibreGLJSRenderer implements MapRenderer {
|
||||
//Sources
|
||||
ObjectNode sources = mapper.createObjectNode();
|
||||
if (style.sources != null)
|
||||
for (MapSource source : style.sources)
|
||||
sources.set(source.name, source.makeJson());
|
||||
for (StyleSource source : style.sources)
|
||||
sources.set(source.key,
|
||||
source.current.makeJson());
|
||||
|
||||
//Layers
|
||||
ArrayNode layers = mapper.createArrayNode();
|
||||
|
||||
+9
-3
@@ -10,16 +10,19 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import eu.konggdev.strikemaps.app.util.JsonPatcher;
|
||||
import eu.konggdev.strikemaps.map.offline.OfflineTileResolver;
|
||||
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
||||
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
||||
import eu.konggdev.strikemaps.map.source.MapSource;
|
||||
import eu.konggdev.strikemaps.map.style.document.StyleDocument;
|
||||
import eu.konggdev.strikemaps.map.style.source.StyleSource;
|
||||
import org.maplibre.android.MapLibre;
|
||||
import org.maplibre.android.geometry.LatLng;
|
||||
import org.maplibre.android.maps.MapLibreMap;
|
||||
import org.maplibre.android.maps.MapView;
|
||||
import org.maplibre.android.maps.OnMapReadyCallback;
|
||||
import org.maplibre.android.maps.Style;
|
||||
import org.maplibre.android.module.http.HttpRequestUtil;
|
||||
import org.maplibre.android.offline.OfflineManager;
|
||||
import org.maplibre.geojson.Feature;
|
||||
|
||||
import java.util.List;
|
||||
@@ -39,7 +42,9 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
|
||||
this.controller = controller;
|
||||
MapLibre.getInstance(app.getActivity());
|
||||
this.mapView = new MapView(app.getActivity());
|
||||
//TODO: Investigate if we might want to restore any savedInstanceState for MapLibre
|
||||
mapView.onCreate(null);
|
||||
//We need this to get the onMapReady callback
|
||||
mapView.getMapAsync(this);
|
||||
}
|
||||
|
||||
@@ -56,8 +61,9 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
|
||||
//Sources
|
||||
ObjectNode sources = mapper.createObjectNode();
|
||||
if (style.sources != null)
|
||||
for (MapSource source : style.sources)
|
||||
sources.set(source.name, source.makeJson());
|
||||
for (StyleSource source : style.sources)
|
||||
sources.set(source.key,
|
||||
source.current.makeJson());
|
||||
|
||||
//Layers
|
||||
ArrayNode layers = mapper.createArrayNode();
|
||||
|
||||
@@ -1,52 +1,14 @@
|
||||
package eu.konggdev.strikemaps.map.source;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import eu.konggdev.strikemaps.map.source.model.TileSource;
|
||||
import eu.konggdev.strikemaps.map.source.tiles.SourceTiles;
|
||||
|
||||
public class MapSource {
|
||||
public enum MapSourceContractType {
|
||||
REQUEST,
|
||||
DEFINITION
|
||||
}
|
||||
|
||||
/*
|
||||
* Contract describes the "purpose" of the source.
|
||||
*
|
||||
* This exists because we effectively have two types
|
||||
* of sources:
|
||||
* - Sources that are the style asking for a specific type of source
|
||||
* and defining a fallback, which is also used as a default for
|
||||
*
|
||||
* and
|
||||
* - Sources that are the actual source
|
||||
*/
|
||||
@NonNull
|
||||
public final MapSourceContractType contract;
|
||||
|
||||
/*
|
||||
* For a request contract:
|
||||
* name is the internal key used by the style.
|
||||
*
|
||||
* For a definition contract:
|
||||
* name is the user-facing source name
|
||||
* (e.g. "ArcGIS Imagery").
|
||||
*
|
||||
* When converting a request into a definition
|
||||
* (when importing a style whose requests
|
||||
* cannot be satisfied), we look for a name
|
||||
* field and fall back to normalizing the key instead
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/*
|
||||
* For a request contract, this is the fallback
|
||||
* for when we absolutely cannot satisfy the requirement,
|
||||
* or the defaults for converting into a definition contract.
|
||||
*/
|
||||
public TileSource tileSource;
|
||||
public SourceTiles tileSource;
|
||||
|
||||
public String type;
|
||||
public String schema;
|
||||
@@ -59,41 +21,33 @@ public class MapSource {
|
||||
|
||||
public String encoding;
|
||||
|
||||
public MapSource(@NonNull MapSourceContractType contract, String name, TileSource tileSource, String type, String schema) {
|
||||
this.contract = contract;
|
||||
public MapSource(String name, SourceTiles tileSource, String type, String schema) {
|
||||
this.name = name;
|
||||
this.tileSource = tileSource;
|
||||
this.type = type;
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
private MapSource(@NonNull MapSourceContractType contract) {
|
||||
this.contract = contract;
|
||||
public MapSource(String key, JsonNode sourceNode) {
|
||||
this.name = key;
|
||||
|
||||
this.type = sourceNode.path("type").asText(null);
|
||||
this.schema = sourceNode.path("schema").asText(null);
|
||||
this.scheme = sourceNode.path("scheme").asText(null);
|
||||
this.encoding = sourceNode.path("encoding").asText(null);
|
||||
|
||||
this.minzoom = sourceNode.path("minZoom").asInt(0);
|
||||
this.maxzoom = sourceNode.path("maxZoom").asInt(24);
|
||||
this.tileSize = sourceNode.path("tileSize").asInt(256);
|
||||
|
||||
this.tileSource = handleJsonTileSource(sourceNode);
|
||||
}
|
||||
|
||||
public static MapSource fromJson(MapSourceContractType contract, String key, JsonNode sourceNode) {
|
||||
MapSource result = new MapSource(contract);
|
||||
result.name = key;
|
||||
|
||||
result.schema = sourceNode.path("schema").asText(null);
|
||||
result.scheme = sourceNode.path("scheme").asText(null);
|
||||
result.encoding = sourceNode.path("encoding").asText(null);
|
||||
result.type = sourceNode.path("type").asText(null);
|
||||
|
||||
result.minzoom = sourceNode.path("minZoom").asInt(0);
|
||||
result.maxzoom = sourceNode.path("maxZoom").asInt(24);
|
||||
result.tileSize = sourceNode.path("tileSize").asInt(256);
|
||||
|
||||
result.tileSource = handleJsonTileSource(contract, sourceNode);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static TileSource handleJsonTileSource(MapSourceContractType contract, JsonNode sourceNode) {
|
||||
private static SourceTiles handleJsonTileSource(JsonNode sourceNode) {
|
||||
// By design, a source must use either "url" or "tiles", never both
|
||||
// In case both are present, we prefer URL over tiles... because I don't know, we just do, m'kay?
|
||||
if (sourceNode.has("url"))
|
||||
return new TileSource(sourceNode.get("url").asText());
|
||||
return new SourceTiles(sourceNode.get("url").asText());
|
||||
|
||||
if (sourceNode.has("tiles")) {
|
||||
String[] tiles = new String[0];
|
||||
@@ -105,15 +59,12 @@ public class MapSource {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return new TileSource(tiles);
|
||||
return new SourceTiles(tiles);
|
||||
}
|
||||
|
||||
if (contract == MapSourceContractType.REQUEST) //No tile source is only acceptable for a request contract
|
||||
//TODO: Define an empty tile source?
|
||||
return null;
|
||||
|
||||
//TODO: Decide what to do when we have a definition that doesn't define the most important part - the tile source
|
||||
//Maybe throwing some custom exception, catching it in fromJson calls and propagating it back to the user would be appropriate
|
||||
//Maybe throwing some custom exception and propagating it back to the user would be appropriate
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package eu.konggdev.strikemaps.map.source.properties;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
public class SourceProperties {
|
||||
public String type;
|
||||
public String schema;
|
||||
|
||||
// Json constructor
|
||||
public SourceProperties(JsonNode sourceNode) {
|
||||
this.type = sourceNode.path("type").asText(null);
|
||||
this.schema = sourceNode.path("schema").asText(null);
|
||||
}
|
||||
}
|
||||
+11
-10
@@ -1,35 +1,36 @@
|
||||
package eu.konggdev.strikemaps.map.source.model;
|
||||
package eu.konggdev.strikemaps.map.source.tiles;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
public class TileSource {
|
||||
public enum TileSourceType {
|
||||
public class SourceTiles {
|
||||
public enum TilesType {
|
||||
URL,
|
||||
TILES,
|
||||
DATA
|
||||
}
|
||||
private TileSourceType type;
|
||||
|
||||
private final TilesType type;
|
||||
private String url;
|
||||
private String[] tiles;
|
||||
|
||||
private JsonNode data;
|
||||
|
||||
public TileSource(String url) {
|
||||
public SourceTiles(String url) {
|
||||
this.url = url;
|
||||
this.type = TileSourceType.URL;
|
||||
this.type = TilesType.URL;
|
||||
}
|
||||
|
||||
public TileSource(String[] tiles) {
|
||||
public SourceTiles(String[] tiles) {
|
||||
this.tiles = tiles;
|
||||
this.type = TileSourceType.TILES;
|
||||
this.type = TilesType.TILES;
|
||||
}
|
||||
|
||||
public TileSource(JsonNode data) {
|
||||
public SourceTiles(JsonNode data) {
|
||||
this.data = data;
|
||||
this.type = TileSourceType.DATA;
|
||||
this.type = TilesType.DATA;
|
||||
}
|
||||
|
||||
public void makeJson(ObjectMapper mapper, ObjectNode node) {
|
||||
@@ -2,9 +2,11 @@ package eu.konggdev.strikemaps.map.style;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import eu.konggdev.strikemaps.app.AppController;
|
||||
import eu.konggdev.strikemaps.map.style.document.StyleDocument;
|
||||
import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata;
|
||||
import eu.konggdev.strikemaps.map.style.options.StyleOptions;
|
||||
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
|
||||
|
||||
public class MapStyle {
|
||||
public static final class StoredRepresentation {
|
||||
@@ -20,13 +22,11 @@ public class MapStyle {
|
||||
}
|
||||
|
||||
public MapStyle restore() {
|
||||
MapStyle style = new MapStyle(
|
||||
return new MapStyle(
|
||||
json,
|
||||
options,
|
||||
managementMetadata
|
||||
);
|
||||
|
||||
return style;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ public class MapStyle {
|
||||
// Original json representation of the style document, as we got it
|
||||
@NonNull public final String json;
|
||||
|
||||
|
||||
public MapStyle(@NonNull String json, @NonNull StyleOptions styleOptions, @Nullable StyleManagementMetadata managementMetadata) {
|
||||
this.json = json;
|
||||
this.document = new StyleDocument(json);
|
||||
@@ -58,7 +57,7 @@ public class MapStyle {
|
||||
return new StoredRepresentation(json, options, managementMetadata);
|
||||
}
|
||||
|
||||
public StyleDocument effectiveDocument() {
|
||||
return document.effectiveDocument(options);
|
||||
public StyleDocument effectiveDocument(RegistryStorageComponent registry) {
|
||||
return document.effectiveDocument(options, registry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
package eu.konggdev.strikemaps.map.style.document;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import eu.konggdev.strikemaps.app.AppController;
|
||||
import eu.konggdev.strikemaps.helper.FileHelper;
|
||||
import eu.konggdev.strikemaps.map.source.MapSource;
|
||||
import eu.konggdev.strikemaps.map.style.options.StyleOptions;
|
||||
import eu.konggdev.strikemaps.map.style.source.StyleSource;
|
||||
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class StyleDocument {
|
||||
|
||||
//Only local data
|
||||
public String name;
|
||||
public String icon;
|
||||
|
||||
public JsonNode metadata; // everything except layers + sources
|
||||
public List<MapSource> sources;
|
||||
public List<StyleSource> sources;
|
||||
public ArrayNode layerDefinitions; // "layers" array
|
||||
|
||||
// Json constructor
|
||||
@@ -35,9 +33,9 @@ public class StyleDocument {
|
||||
this.icon = root.path("icon").asText();
|
||||
|
||||
JsonNode jsonSources = root.path("sources");
|
||||
List<MapSource> sources = new ArrayList<>();
|
||||
List<StyleSource> sources = new ArrayList<>();
|
||||
jsonSources.fields().forEachRemaining(entry -> {
|
||||
sources.add(MapSource.fromJson(MapSource.MapSourceContractType.REQUEST, entry.getKey(), entry.getValue()));
|
||||
sources.add(new StyleSource(entry.getKey(), entry.getValue()));
|
||||
});
|
||||
this.sources = sources;
|
||||
|
||||
@@ -47,8 +45,8 @@ public class StyleDocument {
|
||||
metadata.remove("layers");
|
||||
metadata.remove("sources");
|
||||
this.metadata = metadata;
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new IllegalArgumentException("Invalid style document", e);
|
||||
}
|
||||
}
|
||||
@@ -63,8 +61,16 @@ public class StyleDocument {
|
||||
}
|
||||
|
||||
// The style that is presented to the renderer, with its options applied
|
||||
public StyleDocument effectiveDocument(StyleOptions options) {
|
||||
public StyleDocument effectiveDocument(StyleOptions options, RegistryStorageComponent registry) {
|
||||
StyleDocument result = new StyleDocument(this); //Copy
|
||||
for (int i = 0; i < sources.size(); i++) {
|
||||
StyleSource source = sources.get(i);
|
||||
MapSource effectiveSource = registry.getSource(
|
||||
options.getInteger(source.key, 0)
|
||||
);
|
||||
if (effectiveSource != null) source.current = effectiveSource;
|
||||
}
|
||||
|
||||
for (JsonNode layer : result.layerDefinitions) {
|
||||
JsonNode option = layer.get("option");
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package eu.konggdev.strikemaps.map.style.source;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import eu.konggdev.strikemaps.map.source.MapSource;
|
||||
import eu.konggdev.strikemaps.map.source.properties.SourceProperties;
|
||||
|
||||
// Stores a source currently used by a style
|
||||
// Along with requirements of what source the style needs here
|
||||
public class StyleSource {
|
||||
public String key;
|
||||
|
||||
// Requirement properties
|
||||
public SourceProperties properties;
|
||||
|
||||
// In an effective style, this is the actual source matched to the
|
||||
// style's requirements according to user's preferences (StyleOptions).
|
||||
// Otherwise, this is the fallback source.
|
||||
// It also preserves the default source defined by the JSON for non-effective style documents
|
||||
@NonNull public MapSource current;
|
||||
|
||||
// Json constructor
|
||||
public StyleSource(String key, JsonNode sourceNode) {
|
||||
this.key = key;
|
||||
this.properties = new SourceProperties(sourceNode);
|
||||
this.current = new MapSource(key, sourceNode);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.konggdev.strikemaps.storage;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import eu.konggdev.strikemaps.Component;
|
||||
import eu.konggdev.strikemaps.app.AppController;
|
||||
import eu.konggdev.strikemaps.map.source.MapSource;
|
||||
@@ -8,6 +9,9 @@ import eu.konggdev.strikemaps.helper.UserPrefsHelper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
public class RegistryStorageComponent implements Component {
|
||||
private AppController app;
|
||||
|
||||
@@ -29,6 +33,10 @@ public class RegistryStorageComponent implements Component {
|
||||
return sources();
|
||||
}
|
||||
|
||||
@Nullable public MapSource getSource(Integer id) {
|
||||
return sources().get(id);
|
||||
}
|
||||
|
||||
private Map<Integer, MapStyle> styles() {
|
||||
if (styles == null) styles = UserPrefsHelper.styles(app.getPrefs(), app);
|
||||
return styles;
|
||||
@@ -38,7 +46,7 @@ public class RegistryStorageComponent implements Component {
|
||||
return styles();
|
||||
}
|
||||
|
||||
public MapStyle getStyle(Integer id) {
|
||||
@Nullable public MapStyle getStyle(Integer id) {
|
||||
return styles().get(id);
|
||||
}
|
||||
|
||||
|
||||
+24
-13
@@ -6,6 +6,8 @@ import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
@@ -18,6 +20,7 @@ import eu.konggdev.strikemaps.R;
|
||||
import eu.konggdev.strikemaps.app.AppController;
|
||||
import eu.konggdev.strikemaps.map.MapComponent;
|
||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
||||
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
|
||||
import eu.konggdev.strikemaps.ui.UIComponent;
|
||||
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
|
||||
import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup;
|
||||
@@ -33,15 +36,16 @@ public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
|
||||
@NonNull
|
||||
UIComponent ui;
|
||||
@NonNull
|
||||
RegistryStorageComponent registry;
|
||||
@NonNull
|
||||
final FragmentMapChangePopup mapChangePopup;
|
||||
|
||||
private final MapStyle style;
|
||||
private final Integer id;
|
||||
private final Integer styleId;
|
||||
|
||||
private ActivityResultLauncher<Intent> exportLauncher;
|
||||
|
||||
void deleteStyle() {
|
||||
app.getRegistry().deleteStyle(id);
|
||||
registry.deleteStyle(styleId);
|
||||
|
||||
mapChangePopup.reloadStyles();
|
||||
dismiss();
|
||||
@@ -54,13 +58,13 @@ public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
|
||||
exportLauncher.launch(intent);
|
||||
}
|
||||
|
||||
public StyleDetailsBottomSheet(AppController app, MapComponent map, UIComponent ui, FragmentMapChangePopup mapChangePopup, MapStyle style, Integer id) {
|
||||
public StyleDetailsBottomSheet(AppController app, FragmentMapChangePopup mapChangePopup, Integer styleId) {
|
||||
this.app = app;
|
||||
this.map = map;
|
||||
this.ui = ui;
|
||||
this.map = app.getMap();
|
||||
this.ui = app.getUi();
|
||||
this.registry = app.getRegistry();
|
||||
this.mapChangePopup = mapChangePopup;
|
||||
this.style = style;
|
||||
this.id = id;
|
||||
this.styleId = styleId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,7 +85,8 @@ public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
|
||||
.openOutputStream(uri)) {
|
||||
|
||||
if (out != null) {
|
||||
out.write(style.json.getBytes());
|
||||
String styleJson = registry.getStyle(styleId).json;
|
||||
if (styleJson != null) out.write(styleJson.getBytes());
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
@@ -96,20 +101,27 @@ public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.dialog_style_details, container, false);
|
||||
|
||||
MapStyle style = registry.getStyle(styleId);
|
||||
TextView styleNameView = view.findViewById(R.id.styleName);
|
||||
LinearLayout styleManagementInfo = view.findViewById(R.id.styleManagementInfo);
|
||||
TextView styleTypeView = view.findViewById(R.id.styleType);
|
||||
ImageView managedStyleIndicator = view.findViewById(R.id.managedStyleIndicator);
|
||||
|
||||
TextView builtInStyleAlert = view.findViewById(R.id.builtInStyleAlert);
|
||||
MaterialCardView editButtonLayout = view.findViewById(R.id.editButton);
|
||||
MaterialCardView copyButtonLayout = view.findViewById(R.id.copyButton);
|
||||
MaterialCardView exportButtonLayout = view.findViewById(R.id.exportButton);
|
||||
MaterialCardView deleteButtonLayout = view.findViewById(R.id.deleteButton);
|
||||
MaterialCardView closeButtonLayout = view.findViewById(R.id.closeButton);
|
||||
|
||||
styleNameView.setText(style.document.name);
|
||||
|
||||
if (style.managementMetadata != null) {
|
||||
styleTypeView.setText("Built-In Style");
|
||||
managedStyleIndicator.setVisibility(View.VISIBLE);
|
||||
styleManagementInfo.setOnClickListener(v ->
|
||||
ui.alert(
|
||||
AlertDialogFactory.styleManagementOptions(app, style.managementMetadata)
|
||||
)
|
||||
);
|
||||
|
||||
} else {
|
||||
styleTypeView.setText("User Style");
|
||||
}
|
||||
@@ -118,7 +130,6 @@ public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
|
||||
copyButtonLayout.setOnClickListener(v -> ui.alert(AlertDialogFactory.createStyle(app, style.json, mapChangePopup)));
|
||||
exportButtonLayout.setOnClickListener(v -> showExportDialog());
|
||||
deleteButtonLayout.setOnClickListener(v -> deleteStyle());
|
||||
closeButtonLayout.setOnClickListener(v -> dismiss());
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
+18
-7
@@ -18,17 +18,20 @@ import eu.konggdev.strikemaps.app.AppController;
|
||||
import eu.konggdev.strikemaps.map.MapComponent;
|
||||
|
||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
||||
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
|
||||
import eu.konggdev.strikemaps.ui.UIComponent;
|
||||
import eu.konggdev.strikemaps.ui.fragment.dialog.NewStyleBottomSheet;
|
||||
import eu.konggdev.strikemaps.ui.fragment.dialog.StyleDetailsBottomSheet;
|
||||
import eu.konggdev.strikemaps.ui.element.item.GenericItem;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class FragmentMapChangePopup extends Fragment implements Popup {
|
||||
@NonNull AppController app;
|
||||
@NonNull MapComponent map;
|
||||
@NonNull UIComponent ui;
|
||||
@NonNull RegistryStorageComponent registry;
|
||||
|
||||
private final Integer region;
|
||||
|
||||
@@ -49,11 +52,13 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
|
||||
public void reloadStyles() {
|
||||
LinearLayout stylesLayout = view.findViewById(R.id.stylesLayout);
|
||||
stylesLayout.removeAllViews();
|
||||
app.getRegistry().getStyles().forEach((id, style) ->
|
||||
stylesLayout.addView(GenericItem.fromStyle(style.document, app,
|
||||
() -> map.setStyle(style),
|
||||
() -> this.styleDetails(style, id)).makeView(ui))
|
||||
);
|
||||
app.getRegistry().getStyles().forEach((id, style) -> {
|
||||
View item = new GenericItem(
|
||||
style.document,
|
||||
app,
|
||||
() -> this.setStyle(id),
|
||||
() -> this.styleDetails(id)).makeView(ui);
|
||||
});
|
||||
Bitmap addNewIcon = BitmapFactory.decodeResource(app.getActivity().getResources(), android.R.drawable.ic_menu_add);
|
||||
stylesLayout.addView(new GenericItem("",
|
||||
addNewIcon,
|
||||
@@ -90,8 +95,13 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
|
||||
new NewStyleBottomSheet(app, map, ui, this).show(app.getActivity().getSupportFragmentManager(), "NewStyleBottomSheet");
|
||||
}
|
||||
|
||||
void styleDetails(MapStyle entry, Integer id) {
|
||||
new StyleDetailsBottomSheet(app, map, ui, this, entry, id).show(app.getActivity().getSupportFragmentManager(), "StyleDetailsBottomSheet");
|
||||
void styleDetails(Integer id) {
|
||||
new StyleDetailsBottomSheet(app, this, id).show(app.getActivity().getSupportFragmentManager(), "StyleDetailsBottomSheet");
|
||||
}
|
||||
|
||||
void setStyle(Integer id) {
|
||||
map.setStyle(id);
|
||||
reloadStyles();
|
||||
}
|
||||
|
||||
public FragmentMapChangePopup(AppController app, Integer region) {
|
||||
@@ -99,6 +109,7 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
|
||||
this.app = app;
|
||||
this.map = app.getMap();
|
||||
this.ui = app.getUi();
|
||||
this.registry = app.getRegistry();
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user