refactor: hold components inside activity

This commit is contained in:
2026-09-13 16:25:39 +02:00
parent abb6713798
commit ecf3e4052a
30 changed files with 412 additions and 414 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ android {
defaultConfig { defaultConfig {
applicationId = "eu.konggdev.strikemaps" applicationId = "eu.konggdev.strikemaps"
minSdk = 24 minSdk = 24
targetSdk = 35 targetSdk = 36
versionCode = 1 versionCode = 1
versionName = "1.0" versionName = "1.0"
@@ -3,7 +3,7 @@
"name": "Satellite", "name": "Satellite",
"icon": "assets://satellite.bmp", "icon": "assets://satellite.bmp",
"sources": { "sources": {
"satelite": { "imagery": {
"type": "raster", "type": "raster",
"schema" : "raster", "schema" : "raster",
"tiles": [ "tiles": [
@@ -17,9 +17,9 @@
}, },
"layers": [ "layers": [
{ {
"id": "satelite", "id": "background",
"type": "raster", "type": "raster",
"source": "satelite" "source": "imagery"
} }
], ],
"id": "satellite" "id": "satellite"
@@ -1,35 +0,0 @@
package eu.konggdev.strikemaps;
import eu.konggdev.strikemaps.app.AppController;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
AppController app;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = new AppController(this);
setContentView(R.layout.view_main);
app.init();
}
public void logcat(String tag, String log) {
Log.i(tag, log);
}
public void logcat(String log) {
Log.i("LogcatGeneric", log);
}
@Override
public void onBackPressed() {
if (!app.getUi().back())
super.onBackPressed();
}
}
@@ -0,0 +1,45 @@
package eu.konggdev.strikemaps.activity;
import android.content.SharedPreferences;
import eu.konggdev.strikemaps.Component;
import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import android.os.Bundle;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.ui.UIComponent;
import eu.konggdev.strikemaps.ui.screen.definition.DefinedScreen;
import java.util.List;
public class MainActivity extends ComponentHolderActivity {
private List<Component> components;
private UIComponent ui;
private List<Component> initComponents() {
SharedPreferences userPrefs = getSharedPreferences("user_prefs", MODE_PRIVATE);
RegistryStorageComponent registry = new RegistryStorageComponent(this, userPrefs);
MapComponent mapComponent = new MapComponent(this, registry, userPrefs);
this.ui = new UIComponent(this, mapComponent, registry, userPrefs, DefinedScreen.MAIN);
return List.of(
mapComponent,
ui,
registry
);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
components = initComponents();
setContentView(R.layout.view_main);
}
@Override
public void onBackPressed() {
if (ui.back())
super.onBackPressed();
}
}
@@ -1,60 +0,0 @@
package eu.konggdev.strikemaps.app;
import android.content.SharedPreferences;
import androidx.appcompat.app.AppCompatActivity;
import eu.konggdev.strikemaps.MainActivity;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.ui.UIComponent;
import eu.konggdev.strikemaps.ui.screen.definition.DefinedScreen;
import static android.content.Context.MODE_PRIVATE;
public class AppController {
private final MainActivity appActivity;
private MapComponent map;
private UIComponent ui;
private RegistryStorageComponent registry;
public AppController(MainActivity appActivity) { this.appActivity = appActivity;}
public void logcat(String log) {
appActivity.logcat(log);
}
public UIComponent getUi() {
if (ui == null) init();
return ui;
}
public MapComponent getMap() {
if (map == null) init();
return map;
}
public RegistryStorageComponent getRegistry() {
if (registry == null) init();
return registry;
}
public SharedPreferences getPrefs() {
return getActivity().getSharedPreferences("user_prefs", MODE_PRIVATE);
}
public AppCompatActivity getActivity() { return appActivity; }
public void init() {
if (getActivity().getSupportActionBar() != null)
getActivity().getSupportActionBar().show();
if(registry == null) registry = new RegistryStorageComponent(this);
if(map == null) map = new MapComponent(this);
if(ui == null) {
ui = new UIComponent(this, map);
ui.swapScreen(DefinedScreen.MAIN); //Initial
}
}
}
@@ -0,0 +1,24 @@
package eu.konggdev.strikemaps.app;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import eu.konggdev.strikemaps.Component;
import java.util.ArrayList;
import java.util.List;
public abstract class ComponentHolderActivity extends AppCompatActivity {
private List<Component> components = new ArrayList<>();
public final <T extends Component> T getComponent(Class<T> type) {
return components.stream()
.filter(type::isInstance)
.findFirst()
.map(type::cast)
.orElse(null);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
@@ -3,12 +3,13 @@ package eu.konggdev.strikemaps.helper;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.source.MapSource; import eu.konggdev.strikemaps.map.source.MapSource;
import eu.konggdev.strikemaps.map.source.tiles.SourceTiles; import eu.konggdev.strikemaps.map.source.tiles.SourceTiles;
import eu.konggdev.strikemaps.map.style.MapStyle; import eu.konggdev.strikemaps.map.style.MapStyle;
import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata; import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata;
import eu.konggdev.strikemaps.map.style.options.StyleOptions; import eu.konggdev.strikemaps.map.style.options.StyleOptions;
import eu.konggdev.strikemaps.util.file.FileTools;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@@ -32,11 +33,11 @@ public final class UserPrefsHelper {
private static final boolean DEFAULT_PERSIST_LOCATION_ENABLED = true; private static final boolean DEFAULT_PERSIST_LOCATION_ENABLED = true;
private static final boolean DEFAULT_LAST_LOCATION_ENABLED = false; private static final boolean DEFAULT_LAST_LOCATION_ENABLED = false;
public static Map<Integer, MapStyle> DEFAULT_STYLES(AppController app) { public static Map<Integer, MapStyle> DEFAULT_STYLES(ComponentHolderActivity app) {
Map<Integer, MapStyle> styles = new HashMap<>(); Map<Integer, MapStyle> styles = new HashMap<>();
String[] styleAssets = FileHelper.getAssetFiles("bundled/style", ".style.json", app); String[] styleAssets = FileTools.getAssetFiles("bundled/style", ".style.json", app);
for (int i = 0; i < styleAssets.length; i++) { for (int i = 0; i < styleAssets.length; i++) {
String styleContents = FileHelper.loadStringFromAssetFile(styleAssets[i], app); String styleContents = FileTools.loadStringFromAssetFile(styleAssets[i], app);
styles.put( i, styles.put( i,
new MapStyle( new MapStyle(
styleContents, styleContents,
@@ -92,7 +93,7 @@ public final class UserPrefsHelper {
return prefs.edit().putBoolean(KEY_LAST_LOCATION_ENABLED, status).commit(); return prefs.edit().putBoolean(KEY_LAST_LOCATION_ENABLED, status).commit();
} }
public static Map<Integer, MapStyle> styles(SharedPreferences prefs, AppController app) { public static Map<Integer, MapStyle> styles(SharedPreferences prefs, ComponentHolderActivity app) {
String json = prefs.getString(KEY_STYLES, null); String json = prefs.getString(KEY_STYLES, null);
if (json == null) return DEFAULT_STYLES(app); if (json == null) return DEFAULT_STYLES(app);
Type type = new TypeToken<Map<Integer, MapStyle.StoredRepresentation>>() {}.getType(); Type type = new TypeToken<Map<Integer, MapStyle.StoredRepresentation>>() {}.getType();
@@ -2,45 +2,60 @@ package eu.konggdev.strikemaps.map;
import java.util.*; import java.util.*;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import eu.konggdev.strikemaps.Component; import eu.konggdev.strikemaps.Component;
import eu.konggdev.strikemaps.map.renderer.implementation.MapLibreGLJSRenderer; import eu.konggdev.strikemaps.map.renderer.implementation.MapLibreGLJSRenderer;
import eu.konggdev.strikemaps.map.style.MapStyle; import eu.konggdev.strikemaps.map.style.document.StyleDocument;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.ui.UIComponent;
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory; import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
import eu.konggdev.strikemaps.helper.UserPrefsHelper; import eu.konggdev.strikemaps.helper.UserPrefsHelper;
import eu.konggdev.strikemaps.map.renderer.implementation.VtmRenderer; import eu.konggdev.strikemaps.map.renderer.implementation.VtmRenderer;
import org.maplibre.android.geometry.LatLng; import org.maplibre.android.geometry.LatLng;
import org.maplibre.geojson.Feature; import org.maplibre.geojson.Feature;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.overlay.MapOverlay; import eu.konggdev.strikemaps.map.overlay.MapOverlay;
import eu.konggdev.strikemaps.map.renderer.implementation.MapLibreNativeRenderer; import eu.konggdev.strikemaps.map.renderer.implementation.MapLibreNativeRenderer;
import eu.konggdev.strikemaps.map.renderer.MapRenderer; import eu.konggdev.strikemaps.map.renderer.MapRenderer;
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentMap; import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentMap;
public class MapComponent implements Component { public class MapComponent implements Component {
private final MapRenderer mapRenderer; private final String TAG = "MapComponent";
private final AppController app;
private final MapRenderer mapRenderer;
private final ComponentHolderActivity activity;
private final RegistryStorageComponent registry;
private final SharedPreferences userPrefs;
//Current style
public Integer styleId; public Integer styleId;
public Map<Class<? extends MapOverlay>, MapOverlay> overlays = new HashMap<>(); public Map<Class<? extends MapOverlay>, MapOverlay> overlays = new HashMap<>();
public MapComponent(AppController ref) { public MapComponent(ComponentHolderActivity activity, RegistryStorageComponent registry, SharedPreferences userPrefs) {
this.app = ref; this.activity = activity;
switch(UserPrefsHelper.mapRenderer(app.getPrefs())) { this.registry = registry;
this.userPrefs = userPrefs;
switch(UserPrefsHelper.mapRenderer(userPrefs)) {
case 0: case 0:
this.mapRenderer = new MapLibreGLJSRenderer(app, this); this.mapRenderer = new MapLibreGLJSRenderer(activity, this);
break; break;
case 1: case 1:
this.mapRenderer = new MapLibreNativeRenderer(app, this); this.mapRenderer = new MapLibreNativeRenderer(activity, this);
break; break;
case 2: case 2:
this.mapRenderer = new VtmRenderer(app, this); this.mapRenderer = new VtmRenderer(activity, this);
break; break;
default: //This shouldn't happen default: //This shouldn't happen
Toast.makeText(app.getActivity(), "Invalid renderer value in preferences\nFalling back to MapLibre GL JS", Toast.LENGTH_SHORT).show(); Toast.makeText(activity, "Invalid renderer value in preferences\nFalling back to MapLibre GL JS", Toast.LENGTH_SHORT).show();
this.mapRenderer = new MapLibreGLJSRenderer(app, this); Log.e(TAG, "Invalid renderer value in preferences\nFalling back to MapLibre GL JS");
this.mapRenderer = new MapLibreGLJSRenderer(activity, this);
break; break;
}; };
} }
@@ -51,6 +66,14 @@ public class MapComponent implements Component {
public void setStyle(Integer id) { public void setStyle(Integer id) {
styleId = id; styleId = id;
//Pass to renderer
StyleDocument document = registry.getStyle(styleId)
.effectiveDocument(registry);
if (document == null) {
Log.e(TAG, "Received null style from registry");
return;
}
mapRenderer.styleUpdate(document);
} }
public void switchOverlay(MapOverlay overlay) { public void switchOverlay(MapOverlay overlay) {
@@ -87,10 +110,12 @@ public class MapComponent implements Component {
selectPoint(features.get(0)); selectPoint(features.get(0));
break; break;
default: default:
app.getUi().alert( UIComponent ui = activity.getComponent(UIComponent.class);
AlertDialogFactory.pointSelector(app, features, selectedItem -> { if (ui != null) {
selectPoint(selectedItem); ui.alert(
})); AlertDialogFactory.pointSelector(activity, ui, features, this::selectPoint)
);
}
} }
return true; return true;
} }
@@ -102,7 +127,7 @@ public class MapComponent implements Component {
public void onMapInit() { public void onMapInit() {
setStyle( setStyle(
UserPrefsHelper.startupMapStyle(app.getPrefs()) UserPrefsHelper.startupMapStyle(userPrefs)
); );
} }
} }
@@ -1,10 +1,12 @@
package eu.konggdev.strikemaps.map.offline; package eu.konggdev.strikemaps.map.offline;
import okhttp3.*;
import java.io.IOException; import java.io.IOException;
public final class OfflineTileResolver {
public byte[] resolve(String url) throws IOException {
//byte[] data = getOfflineTile(); public final class OfflineTileResolver {
public static byte[] resolve(String url) throws IOException {
//TODO
return null; return null;
} }
} }
@@ -3,8 +3,9 @@ package eu.konggdev.strikemaps.map.overlay.implementation;
import android.location.Location; import android.location.Location;
import android.location.LocationListener; import android.location.LocationListener;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.overlay.MapOverlay; import eu.konggdev.strikemaps.map.overlay.MapOverlay;
@@ -16,15 +17,13 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
public class LocationOverlay implements MapOverlay, LocationListener { public class LocationOverlay implements MapOverlay, LocationListener {
LocationDataProvider locationDataProvider; LocationDataProvider locationDataProvider;
AppController app;
MapComponent map; MapComponent map;
public Location currentLocation = null; public Location currentLocation = null;
public LocationOverlay(AppController app) { public LocationOverlay(MapComponent map, AppCompatActivity activity) {
this.app = app; this.map = map;
this.map = app.getMap(); this.locationDataProvider = new LocationDataProvider(activity, this);
this.locationDataProvider = new LocationDataProvider(app.getActivity(), this);
} }
@Override @Override
@@ -1,12 +1,12 @@
package eu.konggdev.strikemaps.map.overlay.implementation; package eu.konggdev.strikemaps.map.overlay.implementation;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.overlay.MapOverlay; import eu.konggdev.strikemaps.map.overlay.MapOverlay;
public class PointSelectionOverlay implements MapOverlay { public class PointSelectionOverlay implements MapOverlay {
AppController app; ComponentHolderActivity app;
MapComponent map; MapComponent map;
@Override @Override
public JsonNode makePatch() { public JsonNode makePatch() {
@@ -1,19 +1,20 @@
package eu.konggdev.strikemaps.map.renderer.implementation; package eu.konggdev.strikemaps.map.renderer.implementation;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.webkit.WebChromeClient; import android.webkit.WebChromeClient;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.app.util.JsonPatcher; import eu.konggdev.strikemaps.util.json.JsonPatcher;
import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.overlay.MapOverlay; import eu.konggdev.strikemaps.map.overlay.MapOverlay;
import eu.konggdev.strikemaps.map.renderer.MapRenderer; import eu.konggdev.strikemaps.map.renderer.MapRenderer;
@@ -27,19 +28,20 @@ import java.util.List;
//Stub for now //Stub for now
public class MapLibreGLJSRenderer implements MapRenderer { public class MapLibreGLJSRenderer implements MapRenderer {
@NonNull AppController app; private final static String TAG = "MapLibreGLJSRenderer";
private final AppCompatActivity activity;
@NonNull MapComponent controller; private final MapComponent controller;
final WebView webView; final WebView webView;
private JsonNode origin; private JsonNode origin;
@SuppressLint({"JavascriptInterface", "SetJavaScriptEnabled"}) @SuppressLint({"JavascriptInterface", "SetJavaScriptEnabled"})
public MapLibreGLJSRenderer(AppController app, MapComponent controller) { public MapLibreGLJSRenderer(ComponentHolderActivity activity, MapComponent controller) {
this.app = app; this.activity = activity;
this.controller = controller; this.controller = controller;
webView = new WebView(app.getActivity()); webView = new WebView(activity);
webView.setLayoutParams( webView.setLayoutParams(
new ViewGroup.LayoutParams( new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
@@ -86,7 +88,7 @@ public class MapLibreGLJSRenderer implements MapRenderer {
root.set("layers", layers); root.set("layers", layers);
this.origin = root; this.origin = root;
} catch (Exception e) { } catch (Exception e) {
app.logcat("Failed to parse style: " + style.name); Log.e(TAG, "Failed to parse style: " + style.name);
e.printStackTrace(); e.printStackTrace();
} }
} }
@@ -96,7 +98,7 @@ public class MapLibreGLJSRenderer implements MapRenderer {
webView.evaluateJavascript("map.setStyle(" + mapped + ", { diff: false });", null); webView.evaluateJavascript("map.setStyle(" + mapped + ", { diff: false });", null);
webView.evaluateJavascript("map.redraw()", null); //Force redraw to make the style change visible webView.evaluateJavascript("map.redraw()", null); //Force redraw to make the style change visible
} catch (Exception e) { } catch (Exception e) {
app.logcat("Failed to set style: " + style.name); Log.e(TAG, "Failed to set style: " + style.name);
e.printStackTrace(); e.printStackTrace();
} }
@@ -127,7 +129,7 @@ public class MapLibreGLJSRenderer implements MapRenderer {
webView.evaluateJavascript("map.setStyle(" + mapped + ", { diff: false });", null); webView.evaluateJavascript("map.setStyle(" + mapped + ", { diff: false });", null);
webView.evaluateJavascript("map.redraw()", null); //Force redraw to make the style change visible webView.evaluateJavascript("map.redraw()", null); //Force redraw to make the style change visible
} catch (Exception e) { } catch (Exception e) {
app.logcat("Failed to patch overlay: " + overlay.toString()); Log.e(TAG, "Failed to patch overlay: " + overlay.toString());
e.printStackTrace(); e.printStackTrace();
} }
} }
@@ -1,16 +1,17 @@
package eu.konggdev.strikemaps.map.renderer.implementation; package eu.konggdev.strikemaps.map.renderer.implementation;
import android.util.Log;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
import eu.konggdev.strikemaps.app.util.JsonPatcher; import eu.konggdev.strikemaps.util.json.JsonPatcher;
import eu.konggdev.strikemaps.map.offline.OfflineTileResolver;
import eu.konggdev.strikemaps.map.overlay.MapOverlay; import eu.konggdev.strikemaps.map.overlay.MapOverlay;
import eu.konggdev.strikemaps.map.renderer.MapRenderer; import eu.konggdev.strikemaps.map.renderer.MapRenderer;
import eu.konggdev.strikemaps.map.style.document.StyleDocument; import eu.konggdev.strikemaps.map.style.document.StyleDocument;
@@ -21,27 +22,26 @@ import org.maplibre.android.maps.MapLibreMap;
import org.maplibre.android.maps.MapView; import org.maplibre.android.maps.MapView;
import org.maplibre.android.maps.OnMapReadyCallback; import org.maplibre.android.maps.OnMapReadyCallback;
import org.maplibre.android.maps.Style; 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 org.maplibre.geojson.Feature;
import java.util.List; import java.util.List;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.map.MapComponent;
public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback { public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
@NonNull AppController app; private final static String TAG = "MapLibreNativeRenderer";
@NonNull MapComponent controller; private final AppCompatActivity activity;
private final MapComponent controller;
MapLibreMap map; MapLibreMap map;
final MapView mapView; final MapView mapView;
private JsonNode origin; private JsonNode origin;
public MapLibreNativeRenderer(AppController app, MapComponent controller) { public MapLibreNativeRenderer(ComponentHolderActivity activity, MapComponent controller) {
this.app = app; this.activity = activity;
this.controller = controller; this.controller = controller;
MapLibre.getInstance(app.getActivity()); MapLibre.getInstance(activity);
this.mapView = new MapView(app.getActivity()); this.mapView = new MapView(activity);
//TODO: Investigate if we might want to restore any savedInstanceState for MapLibre //TODO: Investigate if we might want to restore any savedInstanceState for MapLibre
mapView.onCreate(null); mapView.onCreate(null);
//We need this to get the onMapReady callback //We need this to get the onMapReady callback
@@ -75,7 +75,7 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
root.set("layers", layers); root.set("layers", layers);
this.origin = root; this.origin = root;
} catch (Exception e) { } catch (Exception e) {
app.logcat("Failed to parse style: " + style.name); Log.e(TAG, "Failed to parse style: " + style.name);
e.printStackTrace(); e.printStackTrace();
} }
} }
@@ -83,7 +83,7 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
try { try {
map.setStyle(new Style.Builder().fromJson(mapper.writeValueAsString(origin))); map.setStyle(new Style.Builder().fromJson(mapper.writeValueAsString(origin)));
} catch (Exception e) { } catch (Exception e) {
app.logcat("Failed to set style: " + style.name); Log.e(TAG, "Failed to set style: " + style.name);
e.printStackTrace(); e.printStackTrace();
} }
@@ -115,7 +115,7 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
map.setStyle(new Style.Builder().fromJson(mapper.writeValueAsString(merged))); map.setStyle(new Style.Builder().fromJson(mapper.writeValueAsString(merged)));
} catch (Exception e) { } catch (Exception e) {
app.logcat("Failed to patch overlay: " + overlay.toString()); Log.e(TAG, "Failed to patch overlay: " + overlay.toString());
e.printStackTrace(); e.printStackTrace();
} }
} }
@@ -1,7 +1,7 @@
package eu.konggdev.strikemaps.map.renderer.implementation; package eu.konggdev.strikemaps.map.renderer.implementation;
import android.view.View; import android.view.View;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.overlay.MapOverlay; import eu.konggdev.strikemaps.map.overlay.MapOverlay;
import eu.konggdev.strikemaps.map.renderer.MapRenderer; import eu.konggdev.strikemaps.map.renderer.MapRenderer;
@@ -19,16 +19,16 @@ import java.util.List;
public class VtmRenderer implements MapRenderer { public class VtmRenderer implements MapRenderer {
AppController app; ComponentHolderActivity activity;
MapComponent controller; MapComponent controller;
Map map; Map map;
final MapView mapView; final MapView mapView;
public VtmRenderer(AppController app, MapComponent controller) { public VtmRenderer(ComponentHolderActivity activity, MapComponent controller) {
this.app = app; this.activity = activity;
this.controller = controller; this.controller = controller;
this.mapView = new MapView(app.getActivity()); this.mapView = new MapView(activity);
this.map = mapView.map(); this.map = mapView.map();
} }
@@ -2,7 +2,6 @@ package eu.konggdev.strikemaps.map.style;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.map.style.document.StyleDocument; import eu.konggdev.strikemaps.map.style.document.StyleDocument;
import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata; import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata;
import eu.konggdev.strikemaps.map.style.options.StyleOptions; import eu.konggdev.strikemaps.map.style.options.StyleOptions;
@@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.map.source.MapSource; import eu.konggdev.strikemaps.map.source.MapSource;
import eu.konggdev.strikemaps.map.style.options.StyleOptions; import eu.konggdev.strikemaps.map.style.options.StyleOptions;
import eu.konggdev.strikemaps.map.style.source.StyleSource; import eu.konggdev.strikemaps.map.style.source.StyleSource;
@@ -71,24 +70,6 @@ public class StyleDocument {
if (effectiveSource != null) source.current = effectiveSource; if (effectiveSource != null) source.current = effectiveSource;
} }
for (JsonNode layer : result.layerDefinitions) {
JsonNode option = layer.get("option");
if (option == null)
continue;
if ("enable".equals(option.path("type").asText())) {
String id = layer.path("id").asText();
boolean enabled = options.getBoolean(
id,
option.path("default").asBoolean(true)
);
}
}
return result; return result;
} }
} }
@@ -1,31 +1,32 @@
package eu.konggdev.strikemaps.storage; package eu.konggdev.strikemaps.storage;
import android.content.SharedPreferences;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import eu.konggdev.strikemaps.Component; import eu.konggdev.strikemaps.Component;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.source.MapSource; import eu.konggdev.strikemaps.map.source.MapSource;
import eu.konggdev.strikemaps.map.style.MapStyle; import eu.konggdev.strikemaps.map.style.MapStyle;
import eu.konggdev.strikemaps.helper.UserPrefsHelper; import eu.konggdev.strikemaps.helper.UserPrefsHelper;
import java.util.Map; import java.util.Map;
import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata;
import org.apache.commons.codec.digest.DigestUtils;
public class RegistryStorageComponent implements Component { public class RegistryStorageComponent implements Component {
private AppController app; private final ComponentHolderActivity activity;
private final SharedPreferences userPrefs;
private Map<Integer, MapStyle> styles; private Map<Integer, MapStyle> styles;
private Map<Integer, MapSource> sources; private Map<Integer, MapSource> sources;
public RegistryStorageComponent(AppController app) { public RegistryStorageComponent(ComponentHolderActivity activity, SharedPreferences userPrefs) {
this.app = app; this.activity = activity;
styles(); this.userPrefs = userPrefs;
initAll();
} }
private Map<Integer, MapSource> sources() { private Map<Integer, MapSource> sources() {
if (sources == null) sources = UserPrefsHelper.sources(app.getPrefs()); if (sources == null) sources = UserPrefsHelper.sources(userPrefs);
return sources; return sources;
} }
@@ -38,7 +39,7 @@ public class RegistryStorageComponent implements Component {
} }
private Map<Integer, MapStyle> styles() { private Map<Integer, MapStyle> styles() {
if (styles == null) styles = UserPrefsHelper.styles(app.getPrefs(), app); if (styles == null) styles = UserPrefsHelper.styles(userPrefs, activity);
return styles; return styles;
} }
@@ -73,10 +74,14 @@ public class RegistryStorageComponent implements Component {
} }
private void save() { private void save() {
UserPrefsHelper.styles(app.getPrefs(), styles); UserPrefsHelper.styles(userPrefs, styles);
} }
public void checkForUpdates() { public void checkForUpdates() {
// //
} }
private void initAll() {
styles(); sources();
}
} }
@@ -1,13 +1,13 @@
package eu.konggdev.strikemaps.ui; package eu.konggdev.strikemaps.ui;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.SharedPreferences;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import eu.konggdev.strikemaps.Component; import eu.konggdev.strikemaps.Component;
import eu.konggdev.strikemaps.R; import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.ui.element.region.content.MainContentRegion; import eu.konggdev.strikemaps.ui.element.region.content.MainContentRegion;
import eu.konggdev.strikemaps.ui.element.region.UIRegion; import eu.konggdev.strikemaps.ui.element.region.UIRegion;
import eu.konggdev.strikemaps.ui.fragment.layout.FragmentLayoutControls; import eu.konggdev.strikemaps.ui.fragment.layout.FragmentLayoutControls;
@@ -19,45 +19,50 @@ import eu.konggdev.strikemaps.ui.screen.definition.DefinedScreen;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer;
public class UIComponent implements Component { public class UIComponent implements Component {
@NonNull AppController app; private final ComponentHolderActivity activity;
MapComponent map; private final MapComponent map;
private final RegistryStorageComponent registry;
private final SharedPreferences userPrefs;
private final ArrayDeque<Screen> screenStack = new ArrayDeque<>(); private final ArrayDeque<Screen> screenStack = new ArrayDeque<>();
public UIComponent(AppController app, MapComponent map) { public UIComponent(ComponentHolderActivity activity, MapComponent map, RegistryStorageComponent registry, SharedPreferences userPrefs, DefinedScreen firstScreen) {
this.app = app; this.activity = activity;
this.map = map; this.map = map;
this.registry = registry;
this.userPrefs = userPrefs;
swapScreen(firstScreen);
} }
public Map<DefinedScreen, Screen> getScreens(MapComponent map) { public Map<DefinedScreen, Screen> getScreens(MapComponent map) {
return Map.of( return Map.of(
//Main screen //Main screen
DefinedScreen.MAIN, new Screen( DefinedScreen.MAIN, new Screen(
//App reference activity,
app,
//Main screen init regions definition //Main screen init regions definition
Map.of( Map.of(
R.id.mainContentView, new MainContentRegion(map.toFragment(), R.id.mainContentView), R.id.mainContentView, new MainContentRegion(map.toFragment(), R.id.mainContentView),
R.id.bottomUi, new UIRegion(new FragmentLayoutControls(app, R.id.bottomUi), R.id.bottomUi), R.id.bottomUi, new UIRegion(new FragmentLayoutControls(activity, this, map, registry, userPrefs, R.id.bottomUi), R.id.bottomUi),
R.id.topUi, new UIRegion(new FragmentLayoutSearch(app, R.id.topUi), R.id.topUi) R.id.topUi, new UIRegion(new FragmentLayoutSearch(activity, this, R.id.topUi), R.id.topUi)
) //TODO: Probably stop referencing layout 3(!) times everytime ) //TODO: Probably stop referencing layout 3(!) times everytime
), ),
//Settings screen //Settings screen
DefinedScreen.SETTINGS, new Screen( DefinedScreen.SETTINGS, new Screen(
app, activity,
//Just the settings content fragment //Just the settings content fragment
Map.of( Map.of(
R.id.mainContentView, new MainContentRegion(new FragmentLayoutContentSettings(app), R.id.mainContentView) R.id.mainContentView, new MainContentRegion(new FragmentLayoutContentSettings(activity, this, userPrefs), R.id.mainContentView)
) )
), ),
//Offline maps screen //Offline maps screen
DefinedScreen.OFFLINE, new Screen( DefinedScreen.OFFLINE, new Screen(
app, activity,
Map.of( Map.of(
R.id.mainContentView, new MainContentRegion(new FragmentLayoutContentOfflineMaps(app), R.id.mainContentView) R.id.mainContentView, new MainContentRegion(new FragmentLayoutContentOfflineMaps(activity), R.id.mainContentView)
) )
) )
); );
@@ -86,11 +91,7 @@ public class UIComponent implements Component {
dialog.show(); dialog.show();
} }
public <T> void alert(AlertDialog dialog, Consumer<T> callback) {
dialog.show();
}
public View inflateUi(int layout) { public View inflateUi(int layout) {
return app.getActivity().getLayoutInflater().inflate(layout, null); return activity.getLayoutInflater().inflate(layout, null);
} }
} }
@@ -6,74 +6,71 @@ import android.widget.ImageButton;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import eu.konggdev.strikemaps.R; import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.helper.FileHelper; import eu.konggdev.strikemaps.util.file.FileTools;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.style.document.StyleDocument; import eu.konggdev.strikemaps.map.style.document.StyleDocument;
import eu.konggdev.strikemaps.ui.UIComponent; import eu.konggdev.strikemaps.ui.UIComponent;
public class GenericItem implements UIItem { public class GenericItem implements UIItem {
@NonNull public String name; public String name;
public Bitmap image; public Bitmap image;
public Runnable onClick; public Runnable onClick;
public Runnable onLongClick; public Runnable onLongClick;
boolean hasImage; boolean hasImage;
public GenericItem(String refName) { public GenericItem(String name) {
this.name = refName; this.name = name;
hasImage = false; hasImage = false;
} }
public GenericItem(String refName, Runnable onClick) {
this.name = refName; public GenericItem(String name, Runnable onClick) {
this.name = name;
this.onClick = onClick; this.onClick = onClick;
hasImage = false; hasImage = false;
} }
public GenericItem(String refName, Runnable onClick, Runnable onLongClick) {
this.name = refName; public GenericItem(String name, Runnable onClick, Runnable onLongClick) {
this.name = name;
this.onClick = onClick; this.onClick = onClick;
this.onLongClick = onLongClick; this.onLongClick = onLongClick;
hasImage = false; hasImage = false;
} }
public GenericItem(String refName, Bitmap refImage) {
this.name = refName; public GenericItem(String name, Bitmap Image) {
this.image = refImage; this.name = name;
this.image = Image;
hasImage = true; hasImage = true;
} }
public GenericItem(String refName, Bitmap refImage, Runnable onClick) {
this.name = refName; public GenericItem(String name, Bitmap Image, Runnable onClick) {
this.image = refImage; this.name = name;
this.image = Image;
this.onClick = onClick; this.onClick = onClick;
hasImage = true; hasImage = true;
} }
public GenericItem(String refName, Bitmap refImage, Runnable onClick, Runnable onLongClick) { public GenericItem(String name, Bitmap Image, Runnable onClick, Runnable onLongClick) {
this.name = refName; this.name = name;
this.image = refImage; this.image = Image;
this.onClick = onClick; this.onClick = onClick;
this.onLongClick = onLongClick; this.onLongClick = onLongClick;
hasImage = true; hasImage = true;
} }
public GenericItem(StyleDocument style, AppController app, Runnable onClick) { public GenericItem(StyleDocument style, Runnable onClick, AppCompatActivity activity) {
if (style == null) { if (style == null) return;
this.name = "Unknown";
return;
}
this.name = style.name; this.name = style.name;
this.image = style.icon != null ? FileHelper.getIcon(style.icon, app) : null; this.image = style.icon != null ? FileTools.getIcon(style.icon, activity) : null;
this.onClick = onClick; this.onClick = onClick;
} }
public GenericItem(StyleDocument style, AppController app, Runnable onClick, Runnable onLongClick) { public GenericItem(StyleDocument style, Runnable onClick, Runnable onLongClick, AppCompatActivity activity) {
if (style == null) { if (style == null) return;
this.name = "Unknown";
return;
}
this.name = style.name; this.name = style.name;
this.image = style.icon != null ? FileHelper.getIcon(style.icon, app) : null; this.image = style.icon != null ? FileTools.getIcon(style.icon, activity) : null;
this.onClick = onClick; this.onClick = onClick;
this.onLongClick = onLongClick; this.onLongClick = onLongClick;
} }
@@ -8,11 +8,13 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.view.View; import android.view.View;
import android.widget.*; import android.widget.*;
import androidx.appcompat.app.AppCompatActivity;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.app.util.JsonPatcher; import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.util.json.JsonPatcher;
import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.style.MapStyle; import eu.konggdev.strikemaps.map.style.MapStyle;
import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata; import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata;
@@ -27,10 +29,7 @@ import java.util.function.Consumer;
//FIXME: Cleaner architecture would be having a class for each AlertDialog type //FIXME: Cleaner architecture would be having a class for each AlertDialog type
public final class AlertDialogFactory { public final class AlertDialogFactory {
public static AlertDialog styleManagementOptions( public static AlertDialog styleManagementOptions(AppCompatActivity activity, StyleManagementMetadata metadata) {
AppController app,
StyleManagementMetadata metadata
) {
String[] options = { String[] options = {
"Update style", "Update style",
"Update automatically" "Update automatically"
@@ -41,7 +40,7 @@ public final class AlertDialogFactory {
metadata.autoUpdate metadata.autoUpdate
}; };
return new AlertDialog.Builder(app.getActivity()) return new AlertDialog.Builder(activity)
.setTitle("Built-in Style") .setTitle("Built-in Style")
.setMultiChoiceItems(options, checked, (dialog, which, isChecked) -> { .setMultiChoiceItems(options, checked, (dialog, which, isChecked) -> {
if (which == 0) { if (which == 0) {
@@ -55,16 +54,16 @@ public final class AlertDialogFactory {
.create(); .create();
} }
public static AlertDialog copyBuiltInStyle(AppController app, MapComponent map, UIComponent ui, FragmentMapChangePopup mapChangePopup) { public static AlertDialog copyBuiltInStyle(AppCompatActivity activity, MapComponent map, UIComponent ui, FragmentMapChangePopup mapChangePopup) {
//TODO: Use an UI element that's supposed to be vertical, instead of GenericItem //TODO: Use an UI element that's supposed to be vertical, instead of GenericItem
LinearLayout container = new LinearLayout(app.getActivity()); LinearLayout container = new LinearLayout(activity);
container.setOrientation(LinearLayout.VERTICAL); container.setOrientation(LinearLayout.VERTICAL);
ScrollView scrollView = new ScrollView(app.getActivity()); ScrollView scrollView = new ScrollView(activity);
scrollView.addView(container); scrollView.addView(container);
AlertDialog dialog = new AlertDialog.Builder(app.getActivity()) AlertDialog dialog = new AlertDialog.Builder(activity)
.setTitle("Copy from") .setTitle("Copy from")
.setView(scrollView) .setView(scrollView)
.setNegativeButton("Cancel", null) .setNegativeButton("Cancel", null)
@@ -72,19 +71,20 @@ public final class AlertDialogFactory {
return dialog; return dialog;
} }
public static AlertDialog createStyle(AppController app, String baseStyleContents, FragmentMapChangePopup mapChangePopup) {
final EditText nameInput = new EditText(app.getActivity()); public static AlertDialog createStyle(AppCompatActivity activity, RegistryStorageComponent registry, String baseStyleContents, FragmentMapChangePopup mapChangePopup) {
final EditText nameInput = new EditText(activity);
nameInput.setHint("Name"); nameInput.setHint("Name");
LinearLayout container = new LinearLayout(app.getActivity()); LinearLayout container = new LinearLayout(activity);
container.setOrientation(LinearLayout.VERTICAL); container.setOrientation(LinearLayout.VERTICAL);
int padding = (int) (20 * app.getActivity().getResources().getDisplayMetrics().density); int padding = (int) (20 * activity.getResources().getDisplayMetrics().density);
container.setPadding(padding, padding, padding, 0); container.setPadding(padding, padding, padding, 0);
container.addView(nameInput); container.addView(nameInput);
AlertDialog dialog = new AlertDialog.Builder(app.getActivity()) AlertDialog dialog = new AlertDialog.Builder(activity)
.setTitle("Create") .setTitle("Create")
.setView(container) .setView(container)
.setPositiveButton("Create", null) .setPositiveButton("Create", null)
@@ -95,12 +95,12 @@ public final class AlertDialogFactory {
Button createButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); Button createButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
createButton.setOnClickListener(v -> { createButton.setOnClickListener(v -> {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mactivityer = new ObjectMapper();
boolean nameEntryRequired = true; boolean nameEntryRequired = true;
String styleContentName = ""; String styleContentName = "";
if (baseStyleContents != null) { if (baseStyleContents != null) {
try { try {
JsonNode root = mapper.readTree(baseStyleContents); JsonNode root = mactivityer.readTree(baseStyleContents);
if (!root.path("name").asText().isEmpty()) { if (!root.path("name").asText().isEmpty()) {
nameEntryRequired = false; //We can take the name from the style nameEntryRequired = false; //We can take the name from the style
styleContentName = root.path("name").asText(); styleContentName = root.path("name").asText();
@@ -125,28 +125,28 @@ public final class AlertDialogFactory {
JsonNode root; JsonNode root;
if(baseStyleContents != null) { if(baseStyleContents != null) {
if(!baseStyleContents.isEmpty()) { if(!baseStyleContents.isEmpty()) {
root = mapper.readTree(baseStyleContents); root = mactivityer.readTree(baseStyleContents);
} else { } else {
root = mapper.createObjectNode(); root = mactivityer.createObjectNode();
} }
} else { } else {
root = mapper.createObjectNode(); root = mactivityer.createObjectNode();
} }
if (!root.path("name").asText().isEmpty()) { if (!root.path("name").asText().isEmpty()) {
ObjectNode node = mapper.createObjectNode(); ObjectNode node = mactivityer.createObjectNode();
node.put("name", name); node.put("name", name);
root = JsonPatcher.patch(root, node); root = JsonPatcher.patch(root, node);
} }
app.getRegistry().addStyle(new MapStyle( registry.addStyle(new MapStyle(
mapper.writeValueAsString(root), mactivityer.writeValueAsString(root),
new StyleOptions(), new StyleOptions(),
null null
)); ));
dialog.dismiss(); dialog.dismiss();
} catch (Exception e) { } catch (Exception e) {
Toast.makeText(app.getActivity(), "Failed to create", Toast.LENGTH_SHORT).show(); Toast.makeText(activity, "Failed to create", Toast.LENGTH_SHORT).show();
e.printStackTrace(); e.printStackTrace();
} }
@@ -157,20 +157,20 @@ public final class AlertDialogFactory {
return dialog; return dialog;
} }
public static AlertDialog pointSelector(AppController app, List<Feature> features, Consumer<Feature> callback) { public static AlertDialog pointSelector(ComponentHolderActivity activity, UIComponent ui, List<Feature> features, Consumer<Feature> callback) {
LinearLayout layout = new LinearLayout(app.getActivity()); LinearLayout layout = new LinearLayout(activity);
layout.setOrientation(LinearLayout.VERTICAL); layout.setOrientation(LinearLayout.VERTICAL);
ScrollView scrollView = new ScrollView(app.getActivity()); ScrollView scrollView = new ScrollView(activity);
scrollView.addView(layout); scrollView.addView(layout);
AlertDialog dialog = new AlertDialog.Builder(app.getActivity()) AlertDialog dialog = new AlertDialog.Builder(activity)
.setView(scrollView) .setView(scrollView)
.create(); .create();
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#000000"))); dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#000000")));
for (Feature feature : features) { for (Feature feature : features) {
View itemView = PreviewItem.fromFeature(feature).makeView(app.getUi(), v -> { View itemView = PreviewItem.fromFeature(feature).makeView(ui, v -> {
dialog.dismiss(); dialog.dismiss();
new Handler(Looper.getMainLooper()) new Handler(Looper.getMainLooper())
.post(() -> callback.accept(feature)); .post(() -> callback.accept(feature));
@@ -181,30 +181,30 @@ public final class AlertDialogFactory {
return dialog; return dialog;
} }
public static AlertDialog searchSettings(AppController app) { public static AlertDialog searchSettings(AppCompatActivity activity) {
return new AlertDialog.Builder(app.getActivity()) return new AlertDialog.Builder(activity)
.setTitle("Configure Search") .setTitle("Configure Search")
.setPositiveButton("OK", null) .setPositiveButton("OK", null)
.create(); .create();
} }
public static AlertDialog restartDialog(AppController app) { public static AlertDialog restartDialog(AppCompatActivity activity) {
return new AlertDialog.Builder(app.getActivity()) return new AlertDialog.Builder(activity)
.setTitle("Restart required") .setTitle("Restart required")
.setMessage("Restart the app to apply changes.") .setMessage("Restart the activity to activityly changes.")
.setCancelable(false) .setCancelable(false)
.setNegativeButton("Cancel", (d, w) -> { .setNegativeButton("Cancel", (d, w) -> {
Toast.makeText(app.getActivity(), Toast.makeText(activity,
"Changes will be applied on next restart", "Changes will be activitylied on next restart",
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
d.dismiss(); d.dismiss();
}) })
.setPositiveButton("Restart", (d, w) -> { .setPositiveButton("Restart", (d, w) -> {
Intent i = app.getActivity().getPackageManager() Intent i = activity.getPackageManager()
.getLaunchIntentForPackage(app.getActivity().getPackageName()); .getLaunchIntentForPackage(activity.getPackageName());
if (i != null) { if (i != null) {
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
app.getActivity().startActivity(i); activity.startActivity(i);
} }
Runtime.getRuntime().exit(0); Runtime.getRuntime().exit(0);
}) })
@@ -14,13 +14,15 @@ import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment; import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.card.MaterialCardView; import com.google.android.material.card.MaterialCardView;
import eu.konggdev.strikemaps.R; import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.style.MapStyle; import eu.konggdev.strikemaps.map.style.MapStyle;
import eu.konggdev.strikemaps.map.style.options.StyleOptions; import eu.konggdev.strikemaps.map.style.options.StyleOptions;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.ui.UIComponent; import eu.konggdev.strikemaps.ui.UIComponent;
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory; import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup; import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup;
@@ -30,11 +32,15 @@ import java.io.*;
public class NewStyleBottomSheet extends BottomSheetDialogFragment { public class NewStyleBottomSheet extends BottomSheetDialogFragment {
private final String styleBase = "{\"name\":\"None\"}"; private final String styleBase = "{\"name\":\"None\"}";
@NonNull AppController app; private AppCompatActivity activity;
@NonNull MapComponent map;
@NonNull UIComponent ui; private MapComponent map;
@NonNull
FragmentMapChangePopup mapChangePopup; private UIComponent ui;
private RegistryStorageComponent registry;
private FragmentMapChangePopup mapChangePopup;
private final ActivityResultLauncher<Intent> importLauncher = private final ActivityResultLauncher<Intent> importLauncher =
registerForActivityResult( registerForActivityResult(
@@ -72,15 +78,16 @@ public class NewStyleBottomSheet extends BottomSheetDialogFragment {
String content = contentBuilder.toString(); String content = contentBuilder.toString();
if (fileName != null && !fileName.endsWith(".style.json")) { if (fileName != null && !fileName.endsWith(".style.json")) {
app.getUi().alert( ui.alert(
AlertDialogFactory.createStyle( AlertDialogFactory.createStyle(
app, activity,
registry,
content, content,
mapChangePopup mapChangePopup
) )
); );
} else { } else {
app.getRegistry().addStyle( registry.addStyle(
new MapStyle( new MapStyle(
content, content,
new StyleOptions(), new StyleOptions(),
@@ -108,10 +115,11 @@ public class NewStyleBottomSheet extends BottomSheetDialogFragment {
importLauncher.launch(intent); importLauncher.launch(intent);
} }
public NewStyleBottomSheet(AppController app, MapComponent map, UIComponent ui, FragmentMapChangePopup mapChangePopup) { public NewStyleBottomSheet(AppCompatActivity activity, MapComponent map, UIComponent ui, RegistryStorageComponent registry, FragmentMapChangePopup mapChangePopup) {
this.app = app; this.activity = activity;
this.map = map; this.map = map;
this.ui = ui; this.ui = ui;
this.registry = registry;
this.mapChangePopup = mapChangePopup; this.mapChangePopup = mapChangePopup;
} }
@@ -126,7 +134,7 @@ public class NewStyleBottomSheet extends BottomSheetDialogFragment {
MaterialCardView emptyBtn = view.findViewById(R.id.buttonCreateEmpty); MaterialCardView emptyBtn = view.findViewById(R.id.buttonCreateEmpty);
builtInBtn.setOnClickListener(v -> { builtInBtn.setOnClickListener(v -> {
app.getUi().alert(AlertDialogFactory.copyBuiltInStyle(app, map, ui, mapChangePopup)); ui.alert(AlertDialogFactory.copyBuiltInStyle(activity, map, ui, mapChangePopup));
}); });
fileBtn.setOnClickListener(v -> { fileBtn.setOnClickListener(v -> {
@@ -134,7 +142,7 @@ public class NewStyleBottomSheet extends BottomSheetDialogFragment {
}); });
emptyBtn.setOnClickListener(v -> { emptyBtn.setOnClickListener(v -> {
app.getUi().alert(AlertDialogFactory.createStyle(app, styleBase, mapChangePopup)); ui.alert(AlertDialogFactory.createStyle(activity, registry, styleBase, mapChangePopup));
}); });
return view; return view;
@@ -14,10 +14,11 @@ import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment; import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.card.MaterialCardView; import com.google.android.material.card.MaterialCardView;
import eu.konggdev.strikemaps.R; import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.style.MapStyle; import eu.konggdev.strikemaps.map.style.MapStyle;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent; import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
@@ -29,16 +30,15 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
public class StyleDetailsBottomSheet extends BottomSheetDialogFragment { public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
@NonNull private final AppCompatActivity activity;
AppController app;
@NonNull private final MapComponent map;
MapComponent map;
@NonNull private final UIComponent ui;
UIComponent ui;
@NonNull private final RegistryStorageComponent registry;
RegistryStorageComponent registry;
@NonNull private final FragmentMapChangePopup mapChangePopup;
final FragmentMapChangePopup mapChangePopup;
private final Integer styleId; private final Integer styleId;
@@ -58,11 +58,11 @@ public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
exportLauncher.launch(intent); exportLauncher.launch(intent);
} }
public StyleDetailsBottomSheet(AppController app, FragmentMapChangePopup mapChangePopup, Integer styleId) { public StyleDetailsBottomSheet(AppCompatActivity activity, MapComponent map, UIComponent ui, RegistryStorageComponent registry, FragmentMapChangePopup mapChangePopup, Integer styleId) {
this.app = app; this.activity = activity;
this.map = app.getMap(); this.map = map;
this.ui = app.getUi(); this.ui = ui;
this.registry = app.getRegistry(); this.registry = registry;
this.mapChangePopup = mapChangePopup; this.mapChangePopup = mapChangePopup;
this.styleId = styleId; this.styleId = styleId;
} }
@@ -118,7 +118,7 @@ public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
managedStyleIndicator.setVisibility(View.VISIBLE); managedStyleIndicator.setVisibility(View.VISIBLE);
styleManagementInfo.setOnClickListener(v -> styleManagementInfo.setOnClickListener(v ->
ui.alert( ui.alert(
AlertDialogFactory.styleManagementOptions(app, style.managementMetadata) AlertDialogFactory.styleManagementOptions(activity, style.managementMetadata)
) )
); );
@@ -127,7 +127,7 @@ public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
} }
editButtonLayout.setOnClickListener(v -> Toast.makeText(requireContext(), "Editor not implemented yet\nWait for release", Toast.LENGTH_SHORT).show()); editButtonLayout.setOnClickListener(v -> Toast.makeText(requireContext(), "Editor not implemented yet\nWait for release", Toast.LENGTH_SHORT).show());
copyButtonLayout.setOnClickListener(v -> ui.alert(AlertDialogFactory.createStyle(app, style.json, mapChangePopup))); copyButtonLayout.setOnClickListener(v -> ui.alert(AlertDialogFactory.createStyle(activity, registry, style.json, mapChangePopup)));
exportButtonLayout.setOnClickListener(v -> showExportDialog()); exportButtonLayout.setOnClickListener(v -> showExportDialog());
deleteButtonLayout.setOnClickListener(v -> deleteStyle()); deleteButtonLayout.setOnClickListener(v -> deleteStyle());
@@ -2,31 +2,42 @@ package eu.konggdev.strikemaps.ui.fragment.layout;
import android.Manifest; import android.Manifest;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Color; import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import eu.konggdev.strikemaps.R; import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.helper.UserPrefsHelper; import eu.konggdev.strikemaps.helper.UserPrefsHelper;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.overlay.implementation.LocationOverlay; import eu.konggdev.strikemaps.map.overlay.implementation.LocationOverlay;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.ui.UIComponent;
import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup; import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup;
public class FragmentLayoutControls extends Fragment implements Layout { public class FragmentLayoutControls extends Fragment implements Layout {
AppController app; private final AppCompatActivity activity;
private final UIComponent ui;
private final MapComponent map;
private final RegistryStorageComponent registry;
private final SharedPreferences userPrefs;
View rootView; View rootView;
private final Integer region; private final Integer region;
// Action definitions
//*//
public void notImplemented() { //Should never be called in release public void notImplemented() { //Should never be called in release
Toast.makeText(requireContext(), "Not implemented yet\nWait for release", Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), "Not implemented yet\nWait for release", Toast.LENGTH_SHORT).show();
} }
@@ -35,29 +46,32 @@ public class FragmentLayoutControls extends Fragment implements Layout {
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1); requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
} else { } else {
app.getMap().switchOverlay(new LocationOverlay(app)); map.switchOverlay(new LocationOverlay(map, activity));
setupView(); setupView();
} }
} }
public void zoomToLocation() { public void zoomToLocation() {
if(!app.getMap().hasOverlay(LocationOverlay.class)) { if(map.hasOverlay(LocationOverlay.class)) {
Toast.makeText(requireContext(), "Hold to enable location", Toast.LENGTH_SHORT).show(); Toast.makeText(requireContext(), "Hold to enable location", Toast.LENGTH_SHORT).show();
return; return;
} }
} }
public void attributtionDialog() { public void attributtionDialog() {
AlertDialog dialog = new AlertDialog.Builder(app.getActivity()) AlertDialog dialog = new AlertDialog.Builder(activity)
.setTitle(app.getActivity().getString(R.string.attribution_title)) .setTitle(activity.getString(R.string.attribution_title))
.setMessage(app.getActivity().getString(R.string.shipped_attribution)) .setMessage(activity.getString(R.string.shipped_attribution))
.setPositiveButton("OK", null).show(); .setPositiveButton("OK", null).show();
} }
//*//
public FragmentLayoutControls(AppController app, Integer region) { public FragmentLayoutControls(AppCompatActivity activity, UIComponent ui, MapComponent map, RegistryStorageComponent registry, SharedPreferences userPrefs, Integer region) {
super(R.layout.fragment_controls); super(R.layout.fragment_controls);
this.app = app; this.activity = activity;
this.ui = ui;
this.map = map;
this.registry = registry;
this.userPrefs = userPrefs;
this.region = region; this.region = region;
} }
@@ -78,7 +92,7 @@ public class FragmentLayoutControls extends Fragment implements Layout {
/* Restores location enabled status from user prefs, /* Restores location enabled status from user prefs,
TODO: Should be moved out of UI code in the future */ TODO: Should be moved out of UI code in the future */
if(UserPrefsHelper.persistLocationEnabled(app.getPrefs()) && UserPrefsHelper.lastLocationEnabled(app.getPrefs()) && !app.getMap().hasOverlay(LocationOverlay.class)) if(UserPrefsHelper.persistLocationEnabled(userPrefs) && UserPrefsHelper.lastLocationEnabled(userPrefs) && !map.hasOverlay(LocationOverlay.class))
toggleLocationService(); toggleLocationService();
this.setupView(); this.setupView();
@@ -86,7 +100,7 @@ public class FragmentLayoutControls extends Fragment implements Layout {
public void setupView() { public void setupView() {
if (rootView == null) return; if (rootView == null) return;
setupButton(rootView, R.id.layersButton, click(() -> app.getUi().getCurrentScreen().open(new FragmentMapChangePopup(app, R.id.bottomUi)))); setupButton(rootView, R.id.layersButton, click(() -> ui.getCurrentScreen().open(new FragmentMapChangePopup(activity, ui, map, registry, R.id.bottomUi))));
setupButton(rootView, R.id.attributionButton, click(this::attributtionDialog)); setupButton(rootView, R.id.attributionButton, click(this::attributtionDialog));
setupButton(rootView, R.id.locationButton, click(this::zoomToLocation), longClick(this::toggleLocationService)); setupButton(rootView, R.id.locationButton, click(this::zoomToLocation), longClick(this::toggleLocationService));
@@ -97,14 +111,14 @@ public class FragmentLayoutControls extends Fragment implements Layout {
setupButton(rootView, R.id.modeButton, click(this::notImplemented)); setupButton(rootView, R.id.modeButton, click(this::notImplemented));
TextView locationServiceStatusIndicator = rootView.findViewById(R.id.locationServiceStatusIndicator); TextView locationServiceStatusIndicator = rootView.findViewById(R.id.locationServiceStatusIndicator);
if (app.getMap().hasOverlay(LocationOverlay.class)) { if (map.hasOverlay(LocationOverlay.class)) {
locationServiceStatusIndicator.setBackgroundColor(Color.parseColor("#00FF00")); //green locationServiceStatusIndicator.setBackgroundColor(Color.parseColor("#00FF00")); //green
} else { } else {
locationServiceStatusIndicator.setBackgroundColor(Color.parseColor("#FB0303")); //red locationServiceStatusIndicator.setBackgroundColor(Color.parseColor("#FB0303")); //red
} }
if(UserPrefsHelper.persistLocationEnabled(app.getPrefs())) if(UserPrefsHelper.persistLocationEnabled(userPrefs))
UserPrefsHelper.lastLocationEnabled(app.getPrefs(), app.getMap().hasOverlay(LocationOverlay.class)); UserPrefsHelper.lastLocationEnabled(userPrefs, map.hasOverlay(LocationOverlay.class));
} }
@Override @Override
@@ -8,20 +8,24 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.PopupWindow; import android.widget.PopupWindow;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import eu.konggdev.strikemaps.R; import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.ui.UIComponent;
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory; import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
import eu.konggdev.strikemaps.ui.screen.definition.DefinedScreen; import eu.konggdev.strikemaps.ui.screen.definition.DefinedScreen;
public class FragmentLayoutSearch extends Fragment implements Layout { public class FragmentLayoutSearch extends Fragment implements Layout {
AppController app; private final AppCompatActivity activity;
private final UIComponent ui;
private final Integer region; private final Integer region;
public FragmentLayoutSearch(AppController app, Integer region) { public FragmentLayoutSearch(AppCompatActivity activity, UIComponent ui, Integer region) {
super(R.layout.fragment_search); super(R.layout.fragment_search);
this.app = app; this.activity = activity;
this.ui = ui;
this.region = region; this.region = region;
} }
@@ -55,12 +59,12 @@ public class FragmentLayoutSearch extends Fragment implements Layout {
popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
setupButton(menuView, R.id.menuSearchSettings, click(() -> { setupButton(menuView, R.id.menuSearchSettings, click(() -> {
app.getUi().alert(AlertDialogFactory.searchSettings(app)); ui.alert(AlertDialogFactory.searchSettings(activity));
})); }));
setupButton(menuView, R.id.menuSettings, click(() -> { setupButton(menuView, R.id.menuSettings, click(() -> {
popupWindow.dismiss(); popupWindow.dismiss();
app.getUi().swapScreen(DefinedScreen.SETTINGS); ui.swapScreen(DefinedScreen.SETTINGS);
})); }));
menuView.findViewById(R.id.menuSearchSettings).setOnClickListener(v -> popupWindow.dismiss()); menuView.findViewById(R.id.menuSearchSettings).setOnClickListener(v -> popupWindow.dismiss());
@@ -5,12 +5,13 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import eu.konggdev.strikemaps.R; import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
public class FragmentLayoutContentOfflineMaps extends Fragment implements MainContentLayout { public class FragmentLayoutContentOfflineMaps extends Fragment implements MainContentLayout {
@NonNull AppController app; @NonNull
ComponentHolderActivity app;
public FragmentLayoutContentOfflineMaps(AppController app) { public FragmentLayoutContentOfflineMaps(ComponentHolderActivity app) {
super(R.layout.fragment_offline_maps); super(R.layout.fragment_offline_maps);
this.app = app; this.app = app;
} }
@@ -1,5 +1,6 @@
package eu.konggdev.strikemaps.ui.fragment.layout.content.main; package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
@@ -7,21 +8,26 @@ import android.widget.Spinner;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import eu.konggdev.strikemaps.R; import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.helper.UserPrefsHelper; import eu.konggdev.strikemaps.helper.UserPrefsHelper;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.ui.UIComponent; import eu.konggdev.strikemaps.ui.UIComponent;
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory; import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
public class FragmentLayoutContentSettings extends Fragment implements MainContentLayout { public class FragmentLayoutContentSettings extends Fragment implements MainContentLayout {
@NonNull AppController app; private final AppCompatActivity activity;
@NonNull UIComponent ui; private final UIComponent ui;
public FragmentLayoutContentSettings(AppController app) {
private final SharedPreferences userPrefs;
public FragmentLayoutContentSettings(AppCompatActivity activity, UIComponent ui, SharedPreferences userPrefs) {
super(R.layout.fragment_settings); super(R.layout.fragment_settings);
this.app = app; this.activity = activity;
this.ui = app.getUi(); this.ui = ui;
this.userPrefs = userPrefs;
} }
@Override @Override
@@ -39,7 +45,7 @@ public class FragmentLayoutContentSettings extends Fragment implements MainConte
); );
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mapRendererSelector.setAdapter(adapter); mapRendererSelector.setAdapter(adapter);
mapRendererSelector.setSelection(UserPrefsHelper.mapRenderer(app.getPrefs())); mapRendererSelector.setSelection(UserPrefsHelper.mapRenderer(userPrefs));
final boolean[] ignoreFirst = {true}; final boolean[] ignoreFirst = {true};
mapRendererSelector.setOnItemSelectedListener( mapRendererSelector.setOnItemSelectedListener(
new AdapterView.OnItemSelectedListener() { new AdapterView.OnItemSelectedListener() {
@@ -50,8 +56,8 @@ public class FragmentLayoutContentSettings extends Fragment implements MainConte
return; return;
} }
UserPrefsHelper.mapRenderer(app.getPrefs(), position); UserPrefsHelper.mapRenderer(userPrefs, position);
ui.alert(AlertDialogFactory.restartDialog(app)); ui.alert(AlertDialogFactory.restartDialog(activity));
} }
@Override @Override
@@ -10,14 +10,14 @@ import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import eu.konggdev.strikemaps.R; import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.MapComponent; import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.style.MapStyle;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent; import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.ui.UIComponent; import eu.konggdev.strikemaps.ui.UIComponent;
import eu.konggdev.strikemaps.ui.fragment.dialog.NewStyleBottomSheet; import eu.konggdev.strikemaps.ui.fragment.dialog.NewStyleBottomSheet;
@@ -28,10 +28,10 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
public class FragmentMapChangePopup extends Fragment implements Popup { public class FragmentMapChangePopup extends Fragment implements Popup {
@NonNull AppController app; private final AppCompatActivity activity;
@NonNull MapComponent map; private final MapComponent map;
@NonNull UIComponent ui; private final UIComponent ui;
@NonNull RegistryStorageComponent registry; private final RegistryStorageComponent registry;
private final Integer region; private final Integer region;
@@ -52,17 +52,16 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
public void reloadStyles() { public void reloadStyles() {
LinearLayout stylesLayout = view.findViewById(R.id.stylesLayout); LinearLayout stylesLayout = view.findViewById(R.id.stylesLayout);
stylesLayout.removeAllViews(); stylesLayout.removeAllViews();
app.getRegistry().getStyles().forEach((id, style) -> { registry.getStyles().forEach((id, style) -> {
View item = new GenericItem( View item = new GenericItem(
style.document, style.document,
app,
() -> this.setStyle(id), () -> this.setStyle(id),
() -> this.styleDetails(id)).makeView(ui); () -> this.styleDetails(id), activity).makeView(ui);
if (Objects.equals(map.styleId, id)) item.findViewById(R.id.indicator) if (Objects.equals(map.styleId, id)) item.findViewById(R.id.indicator)
.setVisibility(View.VISIBLE); .setVisibility(View.VISIBLE);
stylesLayout.addView(item); stylesLayout.addView(item);
}); });
Bitmap addNewIcon = BitmapFactory.decodeResource(app.getActivity().getResources(), android.R.drawable.ic_menu_add); Bitmap addNewIcon = BitmapFactory.decodeResource(activity.getResources(), android.R.drawable.ic_menu_add);
stylesLayout.addView(new GenericItem("", stylesLayout.addView(new GenericItem("",
addNewIcon, addNewIcon,
this::newStyleFlow).makeView(ui)); this::newStyleFlow).makeView(ui));
@@ -95,11 +94,11 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
} }
void newStyleFlow() { void newStyleFlow() {
new NewStyleBottomSheet(app, map, ui, this).show(app.getActivity().getSupportFragmentManager(), "NewStyleBottomSheet"); new NewStyleBottomSheet(activity, map, ui, registry, this).show(activity.getSupportFragmentManager(), "NewStyleBottomSheet");
} }
void styleDetails(Integer id) { void styleDetails(Integer id) {
new StyleDetailsBottomSheet(app, this, id).show(app.getActivity().getSupportFragmentManager(), "StyleDetailsBottomSheet"); new StyleDetailsBottomSheet(activity, map, ui, registry, this, id).show(activity.getSupportFragmentManager(), "StyleDetailsBottomSheet");
} }
void setStyle(Integer id) { void setStyle(Integer id) {
@@ -107,12 +106,12 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
reloadStyles(); reloadStyles();
} }
public FragmentMapChangePopup(AppController app, Integer region) { public FragmentMapChangePopup(AppCompatActivity activity, UIComponent ui, MapComponent map, RegistryStorageComponent registry, Integer region) {
super(R.layout.popup_map_change); super(R.layout.popup_map_change);
this.app = app; this.activity = activity;
this.map = app.getMap(); this.ui = ui;
this.ui = app.getUi(); this.map = map;
this.registry = app.getRegistry(); this.registry = registry;
this.region = region; this.region = region;
} }
@@ -1,23 +1,22 @@
package eu.konggdev.strikemaps.ui.screen; package eu.konggdev.strikemaps.ui.screen;
import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import java.util.Map; import java.util.Map;
import eu.konggdev.strikemaps.app.AppController; import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.ui.fragment.ContainerFragment; import eu.konggdev.strikemaps.ui.fragment.ContainerFragment;
import eu.konggdev.strikemaps.ui.fragment.FragmentEmptyPlaceholder; import eu.konggdev.strikemaps.ui.fragment.FragmentEmptyPlaceholder;
import eu.konggdev.strikemaps.ui.fragment.popup.Popup; import eu.konggdev.strikemaps.ui.fragment.popup.Popup;
import eu.konggdev.strikemaps.ui.element.region.UIRegion; import eu.konggdev.strikemaps.ui.element.region.UIRegion;
public class Screen { public class Screen {
@NonNull AppController app; private final ComponentHolderActivity activity;
Toolbar toolbar;
public Screen(AppController app, Map<Integer, UIRegion> regions) { public Screen(ComponentHolderActivity activity, Map<Integer, UIRegion> regions) {
this.app = app; this.activity = activity;
this.uiRegions = regions; this.uiRegions = regions;
} }
Map<Integer, UIRegion> uiRegions; Map<Integer, UIRegion> uiRegions;
@@ -55,7 +54,7 @@ public class Screen {
} }
public void fragmentTransaction(int layoutId, Fragment fragment) { public void fragmentTransaction(int layoutId, Fragment fragment) {
app.getActivity().getSupportFragmentManager() activity.getSupportFragmentManager()
.beginTransaction() .beginTransaction()
.replace(layoutId, fragment) .replace(layoutId, fragment)
.commit(); .commit();
@@ -1,4 +1,4 @@
package eu.konggdev.strikemaps.helper; package eu.konggdev.strikemaps.util.file;
import android.content.res.AssetManager; import android.content.res.AssetManager;
@@ -7,25 +7,29 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import android.util.Log;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import eu.konggdev.strikemaps.app.AppController; import androidx.appcompat.app.AppCompatActivity;
//FIXME: Ugly //FIXME: Ugly
public final class FileHelper { public final class FileTools {
public static Bitmap getIcon(String iconLocator, AppController app) { private static final String TAG = "FileUtils";
public static Bitmap getIcon(String iconLocator, AppCompatActivity activity) {
switch (iconLocator.split("//")[0]) { switch (iconLocator.split("//")[0]) {
//TODO: https //TODO: https
case "assets:": case "assets:":
return BitmapFactory.decodeStream(FileHelper.openAssetStream("bundled/icon/" + iconLocator.split("//")[1], app)); return BitmapFactory.decodeStream(FileTools.openAssetStream("bundled/icon/" + iconLocator.split("//")[1], activity));
default: default:
app.logcat("Unimplemented icon locator space: " + iconLocator); Log.e(TAG, "Unimplemented icon locator space: " + iconLocator);
return null; return null;
} }
} }
public static String loadStringFromAssetFile(String filePath, AppController app) { public static String loadStringFromAssetFile(String filePath, AppCompatActivity activity) {
try (InputStream is = app.getActivity().getAssets().open(filePath)) { try (InputStream is = activity.getAssets().open(filePath)) {
int size = is.available(); int size = is.available();
byte[] buffer = new byte[size]; byte[] buffer = new byte[size];
is.read(buffer); is.read(buffer);
@@ -36,31 +40,8 @@ public final class FileHelper {
} }
} }
public static void writeUserFile(String path, String fileName, String content, AppController app) throws IOException { public static String[] getAssetFiles(String path, String fileExt, AppCompatActivity activity) {
try { AssetManager assetManager = activity.getAssets();
File userDirectory = new File(app.getActivity().getExternalFilesDir(null), path);
if (!userDirectory.exists() && !userDirectory.mkdirs()) {
app.logcat("Failed to create directory: " + userDirectory.getAbsolutePath());
return;
}
File file = new File(userDirectory, fileName);
try (FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {
writer.write(content);
writer.flush();
}
} catch (IOException e) {
throw e;
}
}
public static String[] getAssetFiles(String path, String fileExt, AppController app) {
AssetManager assetManager = app.getActivity().getAssets();
try { try {
if (path != null && path.startsWith("/")) { if (path != null && path.startsWith("/")) {
path = path.substring(1); path = path.substring(1);
@@ -90,9 +71,9 @@ public final class FileHelper {
} }
} }
public static InputStream openAssetStream(String path, AppController app) { public static InputStream openAssetStream(String path, AppCompatActivity activity) {
try { try {
return app.getActivity().getAssets().open(path); return activity.getAssets().open(path);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -1,4 +1,4 @@
package eu.konggdev.strikemaps.app.util; package eu.konggdev.strikemaps.util.json;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;