diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 438c4aa..b0f2995 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,4 +25,4 @@ - \ No newline at end of file + diff --git a/app/src/main/java/eu/konggdev/strikemaps/factory/AlertDialogFactory.java b/app/src/main/java/eu/konggdev/strikemaps/factory/AlertDialogFactory.java index b55c015..3cefcb0 100644 --- a/app/src/main/java/eu/konggdev/strikemaps/factory/AlertDialogFactory.java +++ b/app/src/main/java/eu/konggdev/strikemaps/factory/AlertDialogFactory.java @@ -13,8 +13,9 @@ import org.maplibre.geojson.Feature; import java.util.List; import java.util.function.Consumer; -//FIXME: Move Item functions into specific classes for specific types - e.g. StyleItem public final class AlertDialogFactory { + private AlertDialogFactory() {} // prevent instantiation + public static AlertDialog pointSelector(AppController app, List features, Consumer callback) { LinearLayout layout = new LinearLayout(app.getActivity()); layout.setOrientation(LinearLayout.VERTICAL); diff --git a/app/src/main/java/eu/konggdev/strikemaps/helper/FileHelper.java b/app/src/main/java/eu/konggdev/strikemaps/helper/FileHelper.java index 3228ab8..2b889c4 100644 --- a/app/src/main/java/eu/konggdev/strikemaps/helper/FileHelper.java +++ b/app/src/main/java/eu/konggdev/strikemaps/helper/FileHelper.java @@ -10,8 +10,10 @@ import java.util.List; import eu.konggdev.strikemaps.app.AppController; -//FIXME: Ugly +//FIXME: Spaghetti code public final class FileHelper { + private FileHelper() {} // prevent instantiation + public static String loadStringFromAssetFile(String filePath, AppController app) { try (InputStream is = app.getActivity().getAssets().open(filePath)) { int size = is.available(); @@ -106,4 +108,4 @@ public final class FileHelper { return fileList.toArray(new String[0]); } -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/konggdev/strikemaps/map/MapComponent.java b/app/src/main/java/eu/konggdev/strikemaps/map/MapComponent.java index 422c4cf..b64a91f 100644 --- a/app/src/main/java/eu/konggdev/strikemaps/map/MapComponent.java +++ b/app/src/main/java/eu/konggdev/strikemaps/map/MapComponent.java @@ -18,8 +18,9 @@ public class MapComponent implements Component { MapRenderer mapRenderer; AppController app; - public String style; + public MapStyle currentStyle; public Map, MapOverlay> overlays = new HashMap<>(); + public MapComponent(AppController ref) { this.app = ref; switch(UserPrefsHelper.mapRenderer(app.getPrefs())) { @@ -37,9 +38,9 @@ public class MapComponent implements Component { return new FragmentLayoutContentMap(mapRenderer.getView()); } - public void setStyle(String style) { + public void setStyle(MapStyle style) { this.style = style; - mapRenderer.reload(); + update(); } public void switchOverlay(MapOverlay overlay) { diff --git a/app/src/main/java/eu/konggdev/strikemaps/map/layer/MapLayer.java b/app/src/main/java/eu/konggdev/strikemaps/map/layer/MapLayer.java index 667338a..efc1e35 100644 --- a/app/src/main/java/eu/konggdev/strikemaps/map/layer/MapLayer.java +++ b/app/src/main/java/eu/konggdev/strikemaps/map/layer/MapLayer.java @@ -1,16 +1,29 @@ -package eu.konggdev.strikemaps.map.layer; +import org.json.JSONObject; -import org.maplibre.android.style.layers.Layer; -import org.maplibre.android.style.sources.GeoJsonSource; - -import java.util.List; - -//TOOD: Make not strictly MapLibre reliant public class MapLayer { - public GeoJsonSource source; - public Layer layer; - public MapLayer(GeoJsonSource source, Layer layer) { + private final String id; + private final String type; + private final MapSource source; + private final String sourceLayer; + private final JSONObject paint; + private final JSONObject filter; + private final JSONObject layout; + + public MapLayer(String id, String type, MapSource source, String sourceLayer, JSONObject paint, JSONObject filter, JSONObject layout) { + this.id = id; + this.type = type; this.source = source; - this.layer = layer; + this.sourceLayer = sourceLayer; + this.paint = paint; + this.filter = filter; + this.layout = layout; } + + public String getId() { return id; } + public String getType() { return type; } + public MapSource getSource() { return source; } + public String getSourceLayer() { return sourceLayer; } + public JSONObject getPaint() { return paint; } + public JSONObject getFilter() { return filter; } + public JSONObject getLayout() { return layout; } } diff --git a/app/src/main/java/eu/konggdev/strikemaps/map/renderer/implementation/MapLibreNativeRenderer.java b/app/src/main/java/eu/konggdev/strikemaps/map/renderer/implementation/MapLibreNativeRenderer.java index a8da472..81ed3f7 100644 --- a/app/src/main/java/eu/konggdev/strikemaps/map/renderer/implementation/MapLibreNativeRenderer.java +++ b/app/src/main/java/eu/konggdev/strikemaps/map/renderer/implementation/MapLibreNativeRenderer.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import eu.konggdev.strikemaps.helper.FileHelper; import eu.konggdev.strikemaps.helper.UserPrefsHelper; +import eu.konggdev.strikemaps.map.renderer.implementation.additionals.MapLibreLayerFactory; import eu.konggdev.strikemaps.map.overlay.MapOverlay; import eu.konggdev.strikemaps.map.layer.MapLayer; import eu.konggdev.strikemaps.map.renderer.MapRenderer; @@ -38,17 +39,31 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback { } void passLayer(MapLayer layer) { + map.getStyle(). map.getStyle().addSource(layer.source); map.getStyle().addLayer(layer.layer); } @Override public void reload() { - map.setStyle(new Style.Builder().fromJson(controller.style), style -> { - for(MapOverlay overlay : controller.overlays.values()) { - passLayer(overlay.makeLayer()); - } - }); + map.setStyle( + new Style.Builder() + .withLayers( + controller.style.layers.stream() + .map(layer -> MapLibreLayerFactory.parseLayer(layer)) + .collect(Collectors.toList()) + ) + .withSources( + controller.style.sources.stream() + .map(source -> MapLibreLayerFactory.parseSource(source)) + .collect(Collectors.toList()) + ), + style -> { + for (MapOverlay overlay : controller.overlays.values()) { + passLayer(overlay.makeLayer()); + } + } + ); } @Override diff --git a/app/src/main/java/eu/konggdev/strikemaps/map/renderer/implementation/additionals/MapLibreLayerFactory.java b/app/src/main/java/eu/konggdev/strikemaps/map/renderer/implementation/additionals/MapLibreLayerFactory.java new file mode 100644 index 0000000..ba20c86 --- /dev/null +++ b/app/src/main/java/eu/konggdev/strikemaps/map/renderer/implementation/additionals/MapLibreLayerFactory.java @@ -0,0 +1,292 @@ +package eu.konggdev.strikemaps.map.renderer.implementation.additionals; + +import org.maplibre.android.style.layers.*; +import org.maplibre.android.style.sources.*; +import org.maplibre.android.maps.MapLibreMap; +import org.json.JSONObject; +import org.json.JSONArray; +import org.json.JSONException; + +import java.util.ArrayList; +import java.util.List; + +public class MapLibreLayerFactory { + private MapLibreLayerFactory() {} // prevent instantiation + + public static Source parseSource(MapSource mapSource) { + switch (mapSource.type.toLowerCase()) { + case "vector": + return new VectorSource(mapSource.id, mapSource.defUrl); + case "raster": + return new RasterSource(mapSource.id, mapSource.defUrl); + case "geojson": + return new GeoJsonSource(mapSource.id, mapSource.defUrl); + case "raster-dem": + return new RasterDemSource(mapSource.id, mapSource.defUrl); + default: + throw new IllegalArgumentException("Unsupported source type: " + mapSource.type); + } + } + + public static Layer parseLayer(MapLayer mapLayer) { + String id = mapLayer.getId(); + String sourceId = mapLayer.getSource() != null ? mapLayer.getSource().id : null; + String sourceLayer = mapLayer.getSourceLayer(); + JSONObject paint = mapLayer.getPaint(); + JSONObject layout = mapLayer.getLayout(); + JSONObject filter = mapLayer.getFilter(); + + Layer layer; + + switch (mapLayer.getType().toLowerCase()) { + case "fill": + layer = buildFillLayer(id, sourceId, sourceLayer, paint, layout); + break; + case "line": + layer = buildLineLayer(id, sourceId, sourceLayer, paint, layout); + break; + case "symbol": + layer = buildSymbolLayer(id, sourceId, sourceLayer, paint, layout); + break; + case "circle": + layer = buildCircleLayer(id, sourceId, sourceLayer, paint, layout); + break; + case "raster": + layer = buildRasterLayer(id, sourceId, paint, layout); + break; + case "fill-extrusion": + layer = buildFillExtrusionLayer(id, sourceId, sourceLayer, paint, layout); + break; + case "heatmap": + layer = buildHeatmapLayer(id, sourceId, sourceLayer, paint, layout); + break; + case "hillshade": + layer = buildHillshadeLayer(id, sourceId, paint, layout); + break; + case "background": + layer = buildBackgroundLayer(id, paint, layout); + break; + default: + throw new IllegalArgumentException("Unsupported layer type: " + mapLayer.getType()); + } + + if (filter != null && layer instanceof BaseLayer) { + layer.setFilter(parseFilter(filter)); + } + + return layer; + } + + private static FillLayer buildFillLayer(String id, String sourceId, String sourceLayer, JSONObject paint, JSONObject layout) { + FillLayer layer = new FillLayer(id, sourceId); + if (sourceLayer != null) layer.setSourceLayer(sourceLayer); + + List> props = new ArrayList<>(); + if (paint != null) { + safeColor(paint, "fill-color", v -> props.add(PropertyFactory.fillColor(v))); + safeFloat (paint, "fill-opacity", v -> props.add(PropertyFactory.fillOpacity(v))); + safeColor(paint, "fill-outline-color", v -> props.add(PropertyFactory.fillOutlineColor(v))); + safeString(paint, "fill-translate-anchor", v -> props.add(PropertyFactory.fillTranslateAnchor(v))); + } + if (layout != null) { + safeString(layout, "visibility", v -> props.add(PropertyFactory.visibility(v))); + } + layer.setProperties(props.toArray(new PropertyValue[0])); + return layer; + } + + private static LineLayer buildLineLayer(String id, String sourceId, String sourceLayer, JSONObject paint, JSONObject layout) { + LineLayer layer = new LineLayer(id, sourceId); + if (sourceLayer != null) layer.setSourceLayer(sourceLayer); + + List> props = new ArrayList<>(); + if (paint != null) { + safeColor(paint, "line-color", v -> props.add(PropertyFactory.lineColor(v))); + safeFloat (paint, "line-width", v -> props.add(PropertyFactory.lineWidth(v))); + safeFloat (paint, "line-opacity", v -> props.add(PropertyFactory.lineOpacity(v))); + safeFloat (paint, "line-blur", v -> props.add(PropertyFactory.lineBlur(v))); + safeFloat (paint, "line-gap-width", v -> props.add(PropertyFactory.lineGapWidth(v))); + safeFloat (paint, "line-offset", v -> props.add(PropertyFactory.lineOffset(v))); + safeColor(paint, "line-translate", v -> {}); // handled below + } + if (layout != null) { + safeString(layout, "line-cap", v -> props.add(PropertyFactory.lineCap(v))); + safeString(layout, "line-join", v -> props.add(PropertyFactory.lineJoin(v))); + safeFloat (layout, "line-miter-limit", v -> props.add(PropertyFactory.lineMiterLimit(v))); + safeFloat (layout, "line-round-limit", v -> props.add(PropertyFactory.lineRoundLimit(v))); + safeString(layout, "visibility", v -> props.add(PropertyFactory.visibility(v))); + } + layer.setProperties(props.toArray(new PropertyValue[0])); + return layer; + } + + private static SymbolLayer buildSymbolLayer(String id, String sourceId, String sourceLayer, JSONObject paint, JSONObject layout) { + SymbolLayer layer = new SymbolLayer(id, sourceId); + if (sourceLayer != null) layer.setSourceLayer(sourceLayer); + + List> props = new ArrayList<>(); + if (paint != null) { + safeColor(paint, "text-color", v -> props.add(PropertyFactory.textColor(v))); + safeFloat (paint, "text-opacity", v -> props.add(PropertyFactory.textOpacity(v))); + safeColor(paint, "text-halo-color", v -> props.add(PropertyFactory.textHaloColor(v))); + safeFloat (paint, "text-halo-width", v -> props.add(PropertyFactory.textHaloWidth(v))); + safeColor(paint, "icon-color", v -> props.add(PropertyFactory.iconColor(v))); + safeFloat (paint, "icon-opacity", v -> props.add(PropertyFactory.iconOpacity(v))); + safeColor(paint, "icon-halo-color", v -> props.add(PropertyFactory.iconHaloColor(v))); + safeFloat (paint, "icon-halo-width", v -> props.add(PropertyFactory.iconHaloWidth(v))); + } + if (layout != null) { + safeString(layout, "text-field", v -> props.add(PropertyFactory.textField(v))); + safeFloat (layout, "text-size", v -> props.add(PropertyFactory.textSize(v))); + safeString(layout, "icon-image", v -> props.add(PropertyFactory.iconImage(v))); + safeFloat (layout, "icon-size", v -> props.add(PropertyFactory.iconSize(v))); + safeString(layout, "symbol-placement", v -> props.add(PropertyFactory.symbolPlacement(v))); + safeString(layout, "text-anchor", v -> props.add(PropertyFactory.textAnchor(v))); + safeFloat (layout, "text-max-width", v -> props.add(PropertyFactory.textMaxWidth(v))); + safeString(layout, "visibility", v -> props.add(PropertyFactory.visibility(v))); + } + layer.setProperties(props.toArray(new PropertyValue[0])); + return layer; + } + + private static CircleLayer buildCircleLayer(String id, String sourceId, String sourceLayer, JSONObject paint, JSONObject layout) { + CircleLayer layer = new CircleLayer(id, sourceId); + if (sourceLayer != null) layer.setSourceLayer(sourceLayer); + + List> props = new ArrayList<>(); + if (paint != null) { + safeColor(paint, "circle-color", v -> props.add(PropertyFactory.circleColor(v))); + safeFloat (paint, "circle-radius", v -> props.add(PropertyFactory.circleRadius(v))); + safeFloat (paint, "circle-opacity", v -> props.add(PropertyFactory.circleOpacity(v))); + safeFloat (paint, "circle-blur", v -> props.add(PropertyFactory.circleBlur(v))); + safeFloat (paint, "circle-stroke-width", v -> props.add(PropertyFactory.circleStrokeWidth(v))); + safeColor(paint, "circle-stroke-color", v -> props.add(PropertyFactory.circleStrokeColor(v))); + } + if (layout != null) { + safeString(layout, "visibility", v -> props.add(PropertyFactory.visibility(v))); + } + layer.setProperties(props.toArray(new PropertyValue[0])); + return layer; + } + + private static RasterLayer buildRasterLayer(String id, String sourceId, + JSONObject paint, JSONObject layout) { + RasterLayer layer = new RasterLayer(id, sourceId); + + List> props = new ArrayList<>(); + if (paint != null) { + safeFloat(paint, "raster-opacity", v -> props.add(PropertyFactory.rasterOpacity(v))); + safeFloat(paint, "raster-hue-rotate", v -> props.add(PropertyFactory.rasterHueRotate(v))); + safeFloat(paint, "raster-brightness-min", v -> props.add(PropertyFactory.rasterBrightnessMin(v))); + safeFloat(paint, "raster-brightness-max", v -> props.add(PropertyFactory.rasterBrightnessMax(v))); + safeFloat(paint, "raster-saturation", v -> props.add(PropertyFactory.rasterSaturation(v))); + safeFloat(paint, "raster-contrast", v -> props.add(PropertyFactory.rasterContrast(v))); + } + if (layout != null) { + safeString(layout, "visibility", v -> props.add(PropertyFactory.visibility(v))); + } + layer.setProperties(props.toArray(new PropertyValue[0])); + return layer; + } + + private static FillExtrusionLayer buildFillExtrusionLayer(String id, String sourceId, String sourceLayer, + JSONObject paint, JSONObject layout) { + FillExtrusionLayer layer = new FillExtrusionLayer(id, sourceId); + if (sourceLayer != null) layer.setSourceLayer(sourceLayer); + + List> props = new ArrayList<>(); + if (paint != null) { + safeColor(paint, "fill-extrusion-color", v -> props.add(PropertyFactory.fillExtrusionColor(v))); + safeFloat (paint, "fill-extrusion-height", v -> props.add(PropertyFactory.fillExtrusionHeight(v))); + safeFloat (paint, "fill-extrusion-base", v -> props.add(PropertyFactory.fillExtrusionBase(v))); + safeFloat (paint, "fill-extrusion-opacity", v -> props.add(PropertyFactory.fillExtrusionOpacity(v))); + } + if (layout != null) { + safeString(layout, "visibility", v -> props.add(PropertyFactory.visibility(v))); + } + layer.setProperties(props.toArray(new PropertyValue[0])); + return layer; + } + + private static HeatmapLayer buildHeatmapLayer(String id, String sourceId, String sourceLayer, + JSONObject paint, JSONObject layout) { + HeatmapLayer layer = new HeatmapLayer(id, sourceId); + if (sourceLayer != null) layer.setSourceLayer(sourceLayer); + + List> props = new ArrayList<>(); + if (paint != null) { + safeFloat(paint, "heatmap-weight", v -> props.add(PropertyFactory.heatmapWeight(v))); + safeFloat(paint, "heatmap-intensity", v -> props.add(PropertyFactory.heatmapIntensity(v))); + safeFloat(paint, "heatmap-radius", v -> props.add(PropertyFactory.heatmapRadius(v))); + safeFloat(paint, "heatmap-opacity", v -> props.add(PropertyFactory.heatmapOpacity(v))); + } + if (layout != null) { + safeString(layout, "visibility", v -> props.add(PropertyFactory.visibility(v))); + } + layer.setProperties(props.toArray(new PropertyValue[0])); + return layer; + } + + private static HillshadeLayer buildHillshadeLayer(String id, String sourceId, JSONObject paint, JSONObject layout) { + HillshadeLayer layer = new HillshadeLayer(id, sourceId); + + List> props = new ArrayList<>(); + if (paint != null) { + safeFloat(paint, "hillshade-illumination-direction", v -> props.add(PropertyFactory.hillshadeIlluminationDirection(v))); + safeFloat(paint, "hillshade-exaggeration", v -> props.add(PropertyFactory.hillshadeExaggeration(v))); + safeColor(paint, "hillshade-shadow-color", v -> props.add(PropertyFactory.hillshadeShadowColor(v))); + safeColor(paint, "hillshade-highlight-color", v -> props.add(PropertyFactory.hillshadeHighlightColor(v))); + safeColor(paint, "hillshade-accent-color", v -> props.add(PropertyFactory.hillshadeAccentColor(v))); + } + if (layout != null) { + safeString(layout, "visibility", v -> props.add(PropertyFactory.visibility(v))); + } + layer.setProperties(props.toArray(new PropertyValue[0])); + return layer; + } + + private static BackgroundLayer buildBackgroundLayer(String id, JSONObject paint, JSONObject layout) { + BackgroundLayer layer = new BackgroundLayer(id); + + List> props = new ArrayList<>(); + if (paint != null) { + safeColor(paint, "background-color", v -> props.add(PropertyFactory.backgroundColor(v))); + safeFloat (paint, "background-opacity", v -> props.add(PropertyFactory.backgroundOpacity(v))); + } + if (layout != null) { + safeString(layout, "visibility", v -> props.add(PropertyFactory.visibility(v))); + } + layer.setProperties(props.toArray(new PropertyValue[0])); + return layer; + } + + public static Expression parseFilter(JSONObject filterObj) { + try { + if (filterObj.has("expr")) { + return Expression.raw(filterObj.getJSONArray("expr").toString()); + } + return Expression.raw(filterObj.toString()); + } catch (JSONException e) { + throw new IllegalArgumentException("Failed to parse filter: " + e.getMessage(), e); + } + } + + @FunctionalInterface + private interface Consumer { void accept(T t); } + + private static void safeString(JSONObject obj, String key, Consumer action) { + if (obj.has(key)) { + try { action.accept(obj.getString(key)); } catch (JSONException ignored) {} + } + } + + private static void safeFloat(JSONObject obj, String key, Consumer action) { + if (obj.has(key)) { + try { action.accept((float) obj.getDouble(key)); } catch (JSONException ignored) {} + } + } + + private static void safeColor(JSONObject obj, String key, Consumer action) { + safeString(obj, key, action); + } +} diff --git a/app/src/main/java/eu/konggdev/strikemaps/map/source/MapSource.java b/app/src/main/java/eu/konggdev/strikemaps/map/source/MapSource.java index 22fcb50..1288991 100644 --- a/app/src/main/java/eu/konggdev/strikemaps/map/source/MapSource.java +++ b/app/src/main/java/eu/konggdev/strikemaps/map/source/MapSource.java @@ -1,11 +1,14 @@ package eu.konggdev.strikemaps.map.source; public class MapSource { - public final String url; + public final String id; + public final String defUrl; public final String type; public final String schema; - public MapSource(String url, String type, String schema) { - this.url = url; + + public MapSource(String id, String url, String type, String schema) { + this.id = id; + this.defUrl = url; this.type = type; this.schema = schema; } diff --git a/app/src/main/java/eu/konggdev/strikemaps/map/style/MapStyle.java b/app/src/main/java/eu/konggdev/strikemaps/map/style/MapStyle.java new file mode 100644 index 0000000..b7f8793 --- /dev/null +++ b/app/src/main/java/eu/konggdev/strikemaps/map/style/MapStyle.java @@ -0,0 +1,90 @@ +package eu.konggdev.strikemaps; + +import android.graphics.Bitmap; + +import androidx.annotation.NonNull; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MapStyle { + @NonNull public final String name; + public Bitmap icon; + public final List sources; + public final List layers; + + public MapStyle(String name, List sources, List layers) { + this.name = name; + this.sources = sources; + this.layers = layers; + } + + public MapStyle(String name, Bitmap icon, List sources, List layers) { + this.name = name; + this.icon = icon; + this.sources = sources; + this.layers = layers; + } + + //FIXME + public static MapStyle fromMapLibreJsonFile(String filename, AppController app) { + try { + String styleContents; + if (filename.startsWith("/storage")) { + styleContents = FileHelper.loadStringFromUserFile(filename); + } else { + styleContents = FileHelper.loadStringFromAssetFile(filename, app); + } + + JSONObject styleJson = new JSONObject(styleContents); + String name = styleJson.optString("name", "Unknown"); + + Map thisSources = new HashMap<>(); + JSONObject sourcesObject = styleJson.optJSONObject("sources"); + if (sourcesObject != null) { + for (String key : sourcesObject.keySet()) { + JSONObject sourceObject = sourcesObject.optJSONObject(key); + if (sourceObject == null) continue; + thisSources.put( + key, + new MapSource( + key, + sourceObject.optString("url", "unknown"), + sourceObject.optString("type", "unknown"), + sourceObject.optString("schema", "unknown") + ) + ); + } + } + + List thisLayers = new ArrayList<>(); + JSONArray layersArray = styleJson.optJSONArray("layers"); + if (layersArray != null) { + for (int i = 0; i < layersArray.length(); i++) { + JSONObject layer = layersArray.optJSONObject(i); + if (layer == null) continue; + String sourceKey = layer.optString("source", ""); + thisLayers.add(new MapLayer( + layer.optString("id", "unknown"), + layer.optString("type", "unknown"), + thisSources.computeIfAbsent(sourceKey, k -> new MapSource(k, "unknown", "unknown", "unknown", null)), + layer.optString("source-layer", "unknown"), + layer.optJSONObject("paint"), + layer.optJSONObject("filter"), + layer.optJSONObject("layout") + )); + } + } + + return new MapStyle(name, thisSources, thisLayers); + } catch (Exception e) { + e.printStackTrace(); + return new MapStyle("Name parsing Exception!", new HashMap<>(), new ArrayList<>()); + } + } +} diff --git a/app/src/main/java/eu/konggdev/strikemaps/ui/element/item/GenericItem.java b/app/src/main/java/eu/konggdev/strikemaps/ui/element/item/GenericItem.java index af2512e..9e1ca67 100644 --- a/app/src/main/java/eu/konggdev/strikemaps/ui/element/item/GenericItem.java +++ b/app/src/main/java/eu/konggdev/strikemaps/ui/element/item/GenericItem.java @@ -12,7 +12,6 @@ import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.helper.FileHelper; import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.ui.UIComponent; -import org.json.JSONObject; import java.io.InputStream; @@ -21,6 +20,7 @@ public class GenericItem implements UIItem { public Bitmap image; public Runnable onClick; boolean hasImage; + public GenericItem(String refName) { this.name = refName; hasImage = false; @@ -42,29 +42,12 @@ public class GenericItem implements UIItem { hasImage = true; } - //FIXME: Ugly glue static constructor - public final static GenericItem fromStyle(String style, AppController app, MapComponent map) { - try { - JSONObject styleJson = new JSONObject(style); - String name = "Unknown"; //Fallback name - if (styleJson.has("name")) name = styleJson.getString("name"); - if (styleJson.has("icon")) { - switch(styleJson.getString("icon").split("//")[0]) { - //TODO: https - case "assets:": - Bitmap icon = BitmapFactory.decodeStream(FileHelper.openAssetStream("bundled/icon/" + styleJson.getString("icon").split("//")[1], app)); - return new GenericItem(name, icon, () -> map.setStyle(style)); - default: - app.logcat("Unimplemented icon source requested in style: " + name); - return new GenericItem(name, () -> map.setStyle(style)); - } - } - return new GenericItem(name, () -> map.setStyle(style)); - } catch (Exception e) { - e.printStackTrace(); - return new GenericItem("Exception!", () -> map.setStyle(style)); - } + public final static GenericItem fromStyle(MapStyle style, MapComponent map) { + if(style.icon != null) + return new GenericItem(style.name, style.icon, () -> map.setStyle(style)); + return new GenericItem(style,name, () -> map.setStyle(style)) } + public View makeView(UIComponent spawner) { View v = spawner.inflateUi(R.layout.item_generic); //FIXME: These shouldn't be casted like that! diff --git a/app/src/main/java/eu/konggdev/strikemaps/ui/fragment/popup/FragmentMapChangePopup.java b/app/src/main/java/eu/konggdev/strikemaps/ui/fragment/popup/FragmentMapChangePopup.java index 8bf547f..b147c7b 100644 --- a/app/src/main/java/eu/konggdev/strikemaps/ui/fragment/popup/FragmentMapChangePopup.java +++ b/app/src/main/java/eu/konggdev/strikemaps/ui/fragment/popup/FragmentMapChangePopup.java @@ -35,6 +35,7 @@ public class FragmentMapChangePopup extends Fragment implements Popup { this.ui = app.getUi(); this.region = region; } + @Override public Integer getRegion() { return region; @@ -51,11 +52,7 @@ public class FragmentMapChangePopup extends Fragment implements Popup { setupButton(view, R.id.closeButton, click(() -> ui.getCurrentScreen().closePopup())); setupDragHandle(view, view, () -> ui.getCurrentScreen().closePopup()); String[] stylePaths = ArrayUtils.addAll(FileHelper.getAssetFiles("bundled/style", ".style.json", app), FileHelper.getUserFiles("style", ".style.json", app)); - List views = new ArrayList<>(); LinearLayout stylesLayout = view.findViewById(R.id.stylesLayout); - for(String i : stylePaths) { - if(i.startsWith("/storage")) stylesLayout.addView(GenericItem.fromStyle(FileHelper.loadStringFromUserFile(i), app, map).makeView(ui)); - else stylesLayout.addView(GenericItem.fromStyle(FileHelper.loadStringFromAssetFile(i, app), app, map).makeView(ui)); - } + stylePaths.forEach(style -> stylesLayout.addView(GenericItem.fromStyle(MapStyle.fromMapLibreJsonFile(style, app), map).makeView(ui))); } }