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,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 com.google.gson.Gson;
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.tiles.SourceTiles;
import eu.konggdev.strikemaps.map.style.MapStyle;
import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata;
import eu.konggdev.strikemaps.map.style.options.StyleOptions;
import eu.konggdev.strikemaps.util.file.FileTools;
import org.apache.commons.codec.digest.DigestUtils;
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_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<>();
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++) {
String styleContents = FileHelper.loadStringFromAssetFile(styleAssets[i], app);
String styleContents = FileTools.loadStringFromAssetFile(styleAssets[i], app);
styles.put( i,
new MapStyle(
styleContents,
@@ -92,7 +93,7 @@ public final class UserPrefsHelper {
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);
if (json == null) return DEFAULT_STYLES(app);
Type type = new TypeToken<Map<Integer, MapStyle.StoredRepresentation>>() {}.getType();
@@ -2,45 +2,60 @@ package eu.konggdev.strikemaps.map;
import java.util.*;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.Toast;
import eu.konggdev.strikemaps.Component;
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.helper.UserPrefsHelper;
import eu.konggdev.strikemaps.map.renderer.implementation.VtmRenderer;
import org.maplibre.android.geometry.LatLng;
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.renderer.implementation.MapLibreNativeRenderer;
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentMap;
public class MapComponent implements Component {
private final MapRenderer mapRenderer;
private final AppController app;
private final String TAG = "MapComponent";
private final MapRenderer mapRenderer;
private final ComponentHolderActivity activity;
private final RegistryStorageComponent registry;
private final SharedPreferences userPrefs;
//Current style
public Integer styleId;
public Map<Class<? extends MapOverlay>, MapOverlay> overlays = new HashMap<>();
public MapComponent(AppController ref) {
this.app = ref;
switch(UserPrefsHelper.mapRenderer(app.getPrefs())) {
public MapComponent(ComponentHolderActivity activity, RegistryStorageComponent registry, SharedPreferences userPrefs) {
this.activity = activity;
this.registry = registry;
this.userPrefs = userPrefs;
switch(UserPrefsHelper.mapRenderer(userPrefs)) {
case 0:
this.mapRenderer = new MapLibreGLJSRenderer(app, this);
this.mapRenderer = new MapLibreGLJSRenderer(activity, this);
break;
case 1:
this.mapRenderer = new MapLibreNativeRenderer(app, this);
this.mapRenderer = new MapLibreNativeRenderer(activity, this);
break;
case 2:
this.mapRenderer = new VtmRenderer(app, this);
this.mapRenderer = new VtmRenderer(activity, this);
break;
default: //This shouldn't happen
Toast.makeText(app.getActivity(), "Invalid renderer value in preferences\nFalling back to MapLibre GL JS", Toast.LENGTH_SHORT).show();
this.mapRenderer = new MapLibreGLJSRenderer(app, this);
Toast.makeText(activity, "Invalid renderer value in preferences\nFalling back to MapLibre GL JS", Toast.LENGTH_SHORT).show();
Log.e(TAG, "Invalid renderer value in preferences\nFalling back to MapLibre GL JS");
this.mapRenderer = new MapLibreGLJSRenderer(activity, this);
break;
};
}
@@ -51,6 +66,14 @@ public class MapComponent implements Component {
public void setStyle(Integer 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) {
@@ -87,10 +110,12 @@ public class MapComponent implements Component {
selectPoint(features.get(0));
break;
default:
app.getUi().alert(
AlertDialogFactory.pointSelector(app, features, selectedItem -> {
selectPoint(selectedItem);
}));
UIComponent ui = activity.getComponent(UIComponent.class);
if (ui != null) {
ui.alert(
AlertDialogFactory.pointSelector(activity, ui, features, this::selectPoint)
);
}
}
return true;
}
@@ -102,7 +127,7 @@ public class MapComponent implements Component {
public void onMapInit() {
setStyle(
UserPrefsHelper.startupMapStyle(app.getPrefs())
UserPrefsHelper.startupMapStyle(userPrefs)
);
}
}
@@ -1,10 +1,12 @@
package eu.konggdev.strikemaps.map.offline;
import okhttp3.*;
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;
}
}
@@ -3,8 +3,9 @@ package eu.konggdev.strikemaps.map.overlay.implementation;
import android.location.Location;
import android.location.LocationListener;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
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.overlay.MapOverlay;
@@ -16,15 +17,13 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
public class LocationOverlay implements MapOverlay, LocationListener {
LocationDataProvider locationDataProvider;
AppController app;
MapComponent map;
public Location currentLocation = null;
public LocationOverlay(AppController app) {
this.app = app;
this.map = app.getMap();
this.locationDataProvider = new LocationDataProvider(app.getActivity(), this);
public LocationOverlay(MapComponent map, AppCompatActivity activity) {
this.map = map;
this.locationDataProvider = new LocationDataProvider(activity, this);
}
@Override
@@ -1,12 +1,12 @@
package eu.konggdev.strikemaps.map.overlay.implementation;
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.overlay.MapOverlay;
public class PointSelectionOverlay implements MapOverlay {
AppController app;
ComponentHolderActivity app;
MapComponent map;
@Override
public JsonNode makePatch() {
@@ -1,19 +1,20 @@
package eu.konggdev.strikemaps.map.renderer.implementation;
import android.annotation.SuppressLint;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.app.util.JsonPatcher;
import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.util.json.JsonPatcher;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
@@ -27,19 +28,20 @@ import java.util.List;
//Stub for now
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;
private JsonNode origin;
@SuppressLint({"JavascriptInterface", "SetJavaScriptEnabled"})
public MapLibreGLJSRenderer(AppController app, MapComponent controller) {
this.app = app;
public MapLibreGLJSRenderer(ComponentHolderActivity activity, MapComponent controller) {
this.activity = activity;
this.controller = controller;
webView = new WebView(app.getActivity());
webView = new WebView(activity);
webView.setLayoutParams(
new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
@@ -86,7 +88,7 @@ public class MapLibreGLJSRenderer implements MapRenderer {
root.set("layers", layers);
this.origin = root;
} catch (Exception e) {
app.logcat("Failed to parse style: " + style.name);
Log.e(TAG, "Failed to parse style: " + style.name);
e.printStackTrace();
}
}
@@ -96,7 +98,7 @@ public class MapLibreGLJSRenderer implements MapRenderer {
webView.evaluateJavascript("map.setStyle(" + mapped + ", { diff: false });", null);
webView.evaluateJavascript("map.redraw()", null); //Force redraw to make the style change visible
} catch (Exception e) {
app.logcat("Failed to set style: " + style.name);
Log.e(TAG, "Failed to set style: " + style.name);
e.printStackTrace();
}
@@ -127,7 +129,7 @@ public class MapLibreGLJSRenderer implements MapRenderer {
webView.evaluateJavascript("map.setStyle(" + mapped + ", { diff: false });", null);
webView.evaluateJavascript("map.redraw()", null); //Force redraw to make the style change visible
} catch (Exception e) {
app.logcat("Failed to patch overlay: " + overlay.toString());
Log.e(TAG, "Failed to patch overlay: " + overlay.toString());
e.printStackTrace();
}
}
@@ -1,16 +1,17 @@
package eu.konggdev.strikemaps.map.renderer.implementation;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import eu.konggdev.strikemaps.app.util.JsonPatcher;
import eu.konggdev.strikemaps.map.offline.OfflineTileResolver;
import eu.konggdev.strikemaps.util.json.JsonPatcher;
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
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.OnMapReadyCallback;
import org.maplibre.android.maps.Style;
import org.maplibre.android.module.http.HttpRequestUtil;
import org.maplibre.android.offline.OfflineManager;
import org.maplibre.geojson.Feature;
import java.util.List;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.map.MapComponent;
public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
@NonNull AppController app;
@NonNull MapComponent controller;
private final static String TAG = "MapLibreNativeRenderer";
private final AppCompatActivity activity;
private final MapComponent controller;
MapLibreMap map;
final MapView mapView;
private JsonNode origin;
public MapLibreNativeRenderer(AppController app, MapComponent controller) {
this.app = app;
public MapLibreNativeRenderer(ComponentHolderActivity activity, MapComponent controller) {
this.activity = activity;
this.controller = controller;
MapLibre.getInstance(app.getActivity());
this.mapView = new MapView(app.getActivity());
MapLibre.getInstance(activity);
this.mapView = new MapView(activity);
//TODO: Investigate if we might want to restore any savedInstanceState for MapLibre
mapView.onCreate(null);
//We need this to get the onMapReady callback
@@ -75,7 +75,7 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
root.set("layers", layers);
this.origin = root;
} catch (Exception e) {
app.logcat("Failed to parse style: " + style.name);
Log.e(TAG, "Failed to parse style: " + style.name);
e.printStackTrace();
}
}
@@ -83,7 +83,7 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
try {
map.setStyle(new Style.Builder().fromJson(mapper.writeValueAsString(origin)));
} catch (Exception e) {
app.logcat("Failed to set style: " + style.name);
Log.e(TAG, "Failed to set style: " + style.name);
e.printStackTrace();
}
@@ -115,7 +115,7 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
map.setStyle(new Style.Builder().fromJson(mapper.writeValueAsString(merged)));
} catch (Exception e) {
app.logcat("Failed to patch overlay: " + overlay.toString());
Log.e(TAG, "Failed to patch overlay: " + overlay.toString());
e.printStackTrace();
}
}
@@ -1,7 +1,7 @@
package eu.konggdev.strikemaps.map.renderer.implementation;
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.overlay.MapOverlay;
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
@@ -19,16 +19,16 @@ import java.util.List;
public class VtmRenderer implements MapRenderer {
AppController app;
ComponentHolderActivity activity;
MapComponent controller;
Map map;
final MapView mapView;
public VtmRenderer(AppController app, MapComponent controller) {
this.app = app;
public VtmRenderer(ComponentHolderActivity activity, MapComponent controller) {
this.activity = activity;
this.controller = controller;
this.mapView = new MapView(app.getActivity());
this.mapView = new MapView(activity);
this.map = mapView.map();
}
@@ -2,7 +2,6 @@ package eu.konggdev.strikemaps.map.style;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.map.style.document.StyleDocument;
import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata;
import eu.konggdev.strikemaps.map.style.options.StyleOptions;
@@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.map.source.MapSource;
import eu.konggdev.strikemaps.map.style.options.StyleOptions;
import eu.konggdev.strikemaps.map.style.source.StyleSource;
@@ -71,24 +70,6 @@ public class StyleDocument {
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;
}
}
@@ -1,31 +1,32 @@
package eu.konggdev.strikemaps.storage;
import android.content.SharedPreferences;
import androidx.annotation.Nullable;
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.style.MapStyle;
import eu.konggdev.strikemaps.helper.UserPrefsHelper;
import java.util.Map;
import eu.konggdev.strikemaps.map.style.management.StyleManagementMetadata;
import org.apache.commons.codec.digest.DigestUtils;
public class RegistryStorageComponent implements Component {
private AppController app;
private final ComponentHolderActivity activity;
private final SharedPreferences userPrefs;
private Map<Integer, MapStyle> styles;
private Map<Integer, MapSource> sources;
public RegistryStorageComponent(AppController app) {
this.app = app;
styles();
public RegistryStorageComponent(ComponentHolderActivity activity, SharedPreferences userPrefs) {
this.activity = activity;
this.userPrefs = userPrefs;
initAll();
}
private Map<Integer, MapSource> sources() {
if (sources == null) sources = UserPrefsHelper.sources(app.getPrefs());
if (sources == null) sources = UserPrefsHelper.sources(userPrefs);
return sources;
}
@@ -38,7 +39,7 @@ public class RegistryStorageComponent implements Component {
}
private Map<Integer, MapStyle> styles() {
if (styles == null) styles = UserPrefsHelper.styles(app.getPrefs(), app);
if (styles == null) styles = UserPrefsHelper.styles(userPrefs, activity);
return styles;
}
@@ -73,10 +74,14 @@ public class RegistryStorageComponent implements Component {
}
private void save() {
UserPrefsHelper.styles(app.getPrefs(), styles);
UserPrefsHelper.styles(userPrefs, styles);
}
public void checkForUpdates() {
//
}
private void initAll() {
styles(); sources();
}
}
@@ -1,13 +1,13 @@
package eu.konggdev.strikemaps.ui;
import android.app.AlertDialog;
import android.content.SharedPreferences;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import eu.konggdev.strikemaps.Component;
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.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.ui.element.region.content.MainContentRegion;
import eu.konggdev.strikemaps.ui.element.region.UIRegion;
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.Map;
import java.util.function.Consumer;
public class UIComponent implements Component {
@NonNull AppController app;
MapComponent map;
private final ComponentHolderActivity activity;
private final MapComponent map;
private final RegistryStorageComponent registry;
private final SharedPreferences userPrefs;
private final ArrayDeque<Screen> screenStack = new ArrayDeque<>();
public UIComponent(AppController app, MapComponent map) {
this.app = app;
public UIComponent(ComponentHolderActivity activity, MapComponent map, RegistryStorageComponent registry, SharedPreferences userPrefs, DefinedScreen firstScreen) {
this.activity = activity;
this.map = map;
this.registry = registry;
this.userPrefs = userPrefs;
swapScreen(firstScreen);
}
public Map<DefinedScreen, Screen> getScreens(MapComponent map) {
return Map.of(
//Main screen
DefinedScreen.MAIN, new Screen(
//App reference
app,
activity,
//Main screen init regions definition
Map.of(
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.topUi, new UIRegion(new FragmentLayoutSearch(app, R.id.topUi), R.id.topUi)
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(activity, this, R.id.topUi), R.id.topUi)
) //TODO: Probably stop referencing layout 3(!) times everytime
),
//Settings screen
DefinedScreen.SETTINGS, new Screen(
app,
activity,
//Just the settings content fragment
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
DefinedScreen.OFFLINE, new Screen(
app,
activity,
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();
}
public <T> void alert(AlertDialog dialog, Consumer<T> callback) {
dialog.show();
}
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 androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.helper.FileHelper;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.util.file.FileTools;
import eu.konggdev.strikemaps.map.style.document.StyleDocument;
import eu.konggdev.strikemaps.ui.UIComponent;
public class GenericItem implements UIItem {
@NonNull public String name;
public String name;
public Bitmap image;
public Runnable onClick;
public Runnable onLongClick;
boolean hasImage;
public GenericItem(String refName) {
this.name = refName;
public GenericItem(String name) {
this.name = name;
hasImage = false;
}
public GenericItem(String refName, Runnable onClick) {
this.name = refName;
public GenericItem(String name, Runnable onClick) {
this.name = name;
this.onClick = onClick;
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.onLongClick = onLongClick;
hasImage = false;
}
public GenericItem(String refName, Bitmap refImage) {
this.name = refName;
this.image = refImage;
public GenericItem(String name, Bitmap Image) {
this.name = name;
this.image = Image;
hasImage = true;
}
public GenericItem(String refName, Bitmap refImage, Runnable onClick) {
this.name = refName;
this.image = refImage;
public GenericItem(String name, Bitmap Image, Runnable onClick) {
this.name = name;
this.image = Image;
this.onClick = onClick;
hasImage = true;
}
public GenericItem(String refName, Bitmap refImage, Runnable onClick, Runnable onLongClick) {
this.name = refName;
this.image = refImage;
public GenericItem(String name, Bitmap Image, Runnable onClick, Runnable onLongClick) {
this.name = name;
this.image = Image;
this.onClick = onClick;
this.onLongClick = onLongClick;
hasImage = true;
}
public GenericItem(StyleDocument style, AppController app, Runnable onClick) {
if (style == null) {
this.name = "Unknown";
return;
}
public GenericItem(StyleDocument style, Runnable onClick, AppCompatActivity activity) {
if (style == null) return;
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;
}
public GenericItem(StyleDocument style, AppController app, Runnable onClick, Runnable onLongClick) {
if (style == null) {
this.name = "Unknown";
return;
}
public GenericItem(StyleDocument style, Runnable onClick, Runnable onLongClick, AppCompatActivity activity) {
if (style == null) return;
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.onLongClick = onLongClick;
}
@@ -8,11 +8,13 @@ import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.*;
import androidx.appcompat.app.AppCompatActivity;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.app.util.JsonPatcher;
import eu.konggdev.strikemaps.app.ComponentHolderActivity;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.util.json.JsonPatcher;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.style.MapStyle;
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
public final class AlertDialogFactory {
public static AlertDialog styleManagementOptions(
AppController app,
StyleManagementMetadata metadata
) {
public static AlertDialog styleManagementOptions(AppCompatActivity activity, StyleManagementMetadata metadata) {
String[] options = {
"Update style",
"Update automatically"
@@ -41,7 +40,7 @@ public final class AlertDialogFactory {
metadata.autoUpdate
};
return new AlertDialog.Builder(app.getActivity())
return new AlertDialog.Builder(activity)
.setTitle("Built-in Style")
.setMultiChoiceItems(options, checked, (dialog, which, isChecked) -> {
if (which == 0) {
@@ -55,16 +54,16 @@ public final class AlertDialogFactory {
.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
LinearLayout container = new LinearLayout(app.getActivity());
LinearLayout container = new LinearLayout(activity);
container.setOrientation(LinearLayout.VERTICAL);
ScrollView scrollView = new ScrollView(app.getActivity());
ScrollView scrollView = new ScrollView(activity);
scrollView.addView(container);
AlertDialog dialog = new AlertDialog.Builder(app.getActivity())
AlertDialog dialog = new AlertDialog.Builder(activity)
.setTitle("Copy from")
.setView(scrollView)
.setNegativeButton("Cancel", null)
@@ -72,19 +71,20 @@ public final class AlertDialogFactory {
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");
LinearLayout container = new LinearLayout(app.getActivity());
LinearLayout container = new LinearLayout(activity);
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.addView(nameInput);
AlertDialog dialog = new AlertDialog.Builder(app.getActivity())
AlertDialog dialog = new AlertDialog.Builder(activity)
.setTitle("Create")
.setView(container)
.setPositiveButton("Create", null)
@@ -95,12 +95,12 @@ public final class AlertDialogFactory {
Button createButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
createButton.setOnClickListener(v -> {
ObjectMapper mapper = new ObjectMapper();
ObjectMapper mactivityer = new ObjectMapper();
boolean nameEntryRequired = true;
String styleContentName = "";
if (baseStyleContents != null) {
try {
JsonNode root = mapper.readTree(baseStyleContents);
JsonNode root = mactivityer.readTree(baseStyleContents);
if (!root.path("name").asText().isEmpty()) {
nameEntryRequired = false; //We can take the name from the style
styleContentName = root.path("name").asText();
@@ -125,28 +125,28 @@ public final class AlertDialogFactory {
JsonNode root;
if(baseStyleContents != null) {
if(!baseStyleContents.isEmpty()) {
root = mapper.readTree(baseStyleContents);
root = mactivityer.readTree(baseStyleContents);
} else {
root = mapper.createObjectNode();
root = mactivityer.createObjectNode();
}
} else {
root = mapper.createObjectNode();
root = mactivityer.createObjectNode();
}
if (!root.path("name").asText().isEmpty()) {
ObjectNode node = mapper.createObjectNode();
ObjectNode node = mactivityer.createObjectNode();
node.put("name", name);
root = JsonPatcher.patch(root, node);
}
app.getRegistry().addStyle(new MapStyle(
mapper.writeValueAsString(root),
registry.addStyle(new MapStyle(
mactivityer.writeValueAsString(root),
new StyleOptions(),
null
));
dialog.dismiss();
} 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();
}
@@ -157,20 +157,20 @@ public final class AlertDialogFactory {
return dialog;
}
public static AlertDialog pointSelector(AppController app, List<Feature> features, Consumer<Feature> callback) {
LinearLayout layout = new LinearLayout(app.getActivity());
public static AlertDialog pointSelector(ComponentHolderActivity activity, UIComponent ui, List<Feature> features, Consumer<Feature> callback) {
LinearLayout layout = new LinearLayout(activity);
layout.setOrientation(LinearLayout.VERTICAL);
ScrollView scrollView = new ScrollView(app.getActivity());
ScrollView scrollView = new ScrollView(activity);
scrollView.addView(layout);
AlertDialog dialog = new AlertDialog.Builder(app.getActivity())
AlertDialog dialog = new AlertDialog.Builder(activity)
.setView(scrollView)
.create();
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#000000")));
for (Feature feature : features) {
View itemView = PreviewItem.fromFeature(feature).makeView(app.getUi(), v -> {
View itemView = PreviewItem.fromFeature(feature).makeView(ui, v -> {
dialog.dismiss();
new Handler(Looper.getMainLooper())
.post(() -> callback.accept(feature));
@@ -181,30 +181,30 @@ public final class AlertDialogFactory {
return dialog;
}
public static AlertDialog searchSettings(AppController app) {
return new AlertDialog.Builder(app.getActivity())
public static AlertDialog searchSettings(AppCompatActivity activity) {
return new AlertDialog.Builder(activity)
.setTitle("Configure Search")
.setPositiveButton("OK", null)
.create();
}
public static AlertDialog restartDialog(AppController app) {
return new AlertDialog.Builder(app.getActivity())
public static AlertDialog restartDialog(AppCompatActivity activity) {
return new AlertDialog.Builder(activity)
.setTitle("Restart required")
.setMessage("Restart the app to apply changes.")
.setMessage("Restart the activity to activityly changes.")
.setCancelable(false)
.setNegativeButton("Cancel", (d, w) -> {
Toast.makeText(app.getActivity(),
"Changes will be applied on next restart",
Toast.makeText(activity,
"Changes will be activitylied on next restart",
Toast.LENGTH_SHORT).show();
d.dismiss();
})
.setPositiveButton("Restart", (d, w) -> {
Intent i = app.getActivity().getPackageManager()
.getLaunchIntentForPackage(app.getActivity().getPackageName());
Intent i = activity.getPackageManager()
.getLaunchIntentForPackage(activity.getPackageName());
if (i != null) {
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
app.getActivity().startActivity(i);
activity.startActivity(i);
}
Runtime.getRuntime().exit(0);
})
@@ -14,13 +14,15 @@ import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.card.MaterialCardView;
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.style.MapStyle;
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.factory.AlertDialogFactory;
import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup;
@@ -30,11 +32,15 @@ import java.io.*;
public class NewStyleBottomSheet extends BottomSheetDialogFragment {
private final String styleBase = "{\"name\":\"None\"}";
@NonNull AppController app;
@NonNull MapComponent map;
@NonNull UIComponent ui;
@NonNull
FragmentMapChangePopup mapChangePopup;
private AppCompatActivity activity;
private MapComponent map;
private UIComponent ui;
private RegistryStorageComponent registry;
private FragmentMapChangePopup mapChangePopup;
private final ActivityResultLauncher<Intent> importLauncher =
registerForActivityResult(
@@ -72,15 +78,16 @@ public class NewStyleBottomSheet extends BottomSheetDialogFragment {
String content = contentBuilder.toString();
if (fileName != null && !fileName.endsWith(".style.json")) {
app.getUi().alert(
ui.alert(
AlertDialogFactory.createStyle(
app,
activity,
registry,
content,
mapChangePopup
)
);
} else {
app.getRegistry().addStyle(
registry.addStyle(
new MapStyle(
content,
new StyleOptions(),
@@ -108,10 +115,11 @@ public class NewStyleBottomSheet extends BottomSheetDialogFragment {
importLauncher.launch(intent);
}
public NewStyleBottomSheet(AppController app, MapComponent map, UIComponent ui, FragmentMapChangePopup mapChangePopup) {
this.app = app;
public NewStyleBottomSheet(AppCompatActivity activity, MapComponent map, UIComponent ui, RegistryStorageComponent registry, FragmentMapChangePopup mapChangePopup) {
this.activity = activity;
this.map = map;
this.ui = ui;
this.registry = registry;
this.mapChangePopup = mapChangePopup;
}
@@ -126,7 +134,7 @@ public class NewStyleBottomSheet extends BottomSheetDialogFragment {
MaterialCardView emptyBtn = view.findViewById(R.id.buttonCreateEmpty);
builtInBtn.setOnClickListener(v -> {
app.getUi().alert(AlertDialogFactory.copyBuiltInStyle(app, map, ui, mapChangePopup));
ui.alert(AlertDialogFactory.copyBuiltInStyle(activity, map, ui, mapChangePopup));
});
fileBtn.setOnClickListener(v -> {
@@ -134,7 +142,7 @@ public class NewStyleBottomSheet extends BottomSheetDialogFragment {
});
emptyBtn.setOnClickListener(v -> {
app.getUi().alert(AlertDialogFactory.createStyle(app, styleBase, mapChangePopup));
ui.alert(AlertDialogFactory.createStyle(activity, registry, styleBase, mapChangePopup));
});
return view;
@@ -14,10 +14,11 @@ import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.card.MaterialCardView;
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.style.MapStyle;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
@@ -29,16 +30,15 @@ import java.io.IOException;
import java.io.OutputStream;
public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
@NonNull
AppController app;
@NonNull
MapComponent map;
@NonNull
UIComponent ui;
@NonNull
RegistryStorageComponent registry;
@NonNull
final FragmentMapChangePopup mapChangePopup;
private final AppCompatActivity activity;
private final MapComponent map;
private final UIComponent ui;
private final RegistryStorageComponent registry;
private final FragmentMapChangePopup mapChangePopup;
private final Integer styleId;
@@ -58,11 +58,11 @@ public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
exportLauncher.launch(intent);
}
public StyleDetailsBottomSheet(AppController app, FragmentMapChangePopup mapChangePopup, Integer styleId) {
this.app = app;
this.map = app.getMap();
this.ui = app.getUi();
this.registry = app.getRegistry();
public StyleDetailsBottomSheet(AppCompatActivity activity, MapComponent map, UIComponent ui, RegistryStorageComponent registry, FragmentMapChangePopup mapChangePopup, Integer styleId) {
this.activity = activity;
this.map = map;
this.ui = ui;
this.registry = registry;
this.mapChangePopup = mapChangePopup;
this.styleId = styleId;
}
@@ -118,7 +118,7 @@ public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
managedStyleIndicator.setVisibility(View.VISIBLE);
styleManagementInfo.setOnClickListener(v ->
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());
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());
deleteButtonLayout.setOnClickListener(v -> deleteStyle());
@@ -2,31 +2,42 @@ package eu.konggdev.strikemaps.ui.fragment.layout;
import android.Manifest;
import android.app.AlertDialog;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import android.widget.TextView;
import android.widget.Toast;
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.map.MapComponent;
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;
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;
private final Integer region;
// Action definitions
//*//
public void notImplemented() { //Should never be called in release
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) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
} else {
app.getMap().switchOverlay(new LocationOverlay(app));
map.switchOverlay(new LocationOverlay(map, activity));
setupView();
}
}
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();
return;
}
}
public void attributtionDialog() {
AlertDialog dialog = new AlertDialog.Builder(app.getActivity())
.setTitle(app.getActivity().getString(R.string.attribution_title))
.setMessage(app.getActivity().getString(R.string.shipped_attribution))
AlertDialog dialog = new AlertDialog.Builder(activity)
.setTitle(activity.getString(R.string.attribution_title))
.setMessage(activity.getString(R.string.shipped_attribution))
.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);
this.app = app;
this.activity = activity;
this.ui = ui;
this.map = map;
this.registry = registry;
this.userPrefs = userPrefs;
this.region = region;
}
@@ -78,7 +92,7 @@ public class FragmentLayoutControls extends Fragment implements Layout {
/* Restores location enabled status from user prefs,
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();
this.setupView();
@@ -86,7 +100,7 @@ public class FragmentLayoutControls extends Fragment implements Layout {
public void setupView() {
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.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));
TextView locationServiceStatusIndicator = rootView.findViewById(R.id.locationServiceStatusIndicator);
if (app.getMap().hasOverlay(LocationOverlay.class)) {
if (map.hasOverlay(LocationOverlay.class)) {
locationServiceStatusIndicator.setBackgroundColor(Color.parseColor("#00FF00")); //green
} else {
locationServiceStatusIndicator.setBackgroundColor(Color.parseColor("#FB0303")); //red
}
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));
}
@Override
@@ -8,20 +8,24 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
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.screen.definition.DefinedScreen;
public class FragmentLayoutSearch extends Fragment implements Layout {
AppController app;
private final AppCompatActivity activity;
private final UIComponent ui;
private final Integer region;
public FragmentLayoutSearch(AppController app, Integer region) {
public FragmentLayoutSearch(AppCompatActivity activity, UIComponent ui, Integer region) {
super(R.layout.fragment_search);
this.app = app;
this.activity = activity;
this.ui = ui;
this.region = region;
}
@@ -55,12 +59,12 @@ public class FragmentLayoutSearch extends Fragment implements Layout {
popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
setupButton(menuView, R.id.menuSearchSettings, click(() -> {
app.getUi().alert(AlertDialogFactory.searchSettings(app));
ui.alert(AlertDialogFactory.searchSettings(activity));
}));
setupButton(menuView, R.id.menuSettings, click(() -> {
popupWindow.dismiss();
app.getUi().swapScreen(DefinedScreen.SETTINGS);
ui.swapScreen(DefinedScreen.SETTINGS);
}));
menuView.findViewById(R.id.menuSearchSettings).setOnClickListener(v -> popupWindow.dismiss());
@@ -5,12 +5,13 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.app.ComponentHolderActivity;
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);
this.app = app;
}
@@ -1,5 +1,6 @@
package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
@@ -7,21 +8,26 @@ import android.widget.Spinner;
import android.widget.ArrayAdapter;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import eu.konggdev.strikemaps.R;
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.factory.AlertDialogFactory;
public class FragmentLayoutContentSettings extends Fragment implements MainContentLayout {
@NonNull AppController app;
@NonNull UIComponent ui;
public FragmentLayoutContentSettings(AppController app) {
private final AppCompatActivity activity;
private final UIComponent ui;
private final SharedPreferences userPrefs;
public FragmentLayoutContentSettings(AppCompatActivity activity, UIComponent ui, SharedPreferences userPrefs) {
super(R.layout.fragment_settings);
this.app = app;
this.ui = app.getUi();
this.activity = activity;
this.ui = ui;
this.userPrefs = userPrefs;
}
@Override
@@ -39,7 +45,7 @@ public class FragmentLayoutContentSettings extends Fragment implements MainConte
);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mapRendererSelector.setAdapter(adapter);
mapRendererSelector.setSelection(UserPrefsHelper.mapRenderer(app.getPrefs()));
mapRendererSelector.setSelection(UserPrefsHelper.mapRenderer(userPrefs));
final boolean[] ignoreFirst = {true};
mapRendererSelector.setOnItemSelectedListener(
new AdapterView.OnItemSelectedListener() {
@@ -50,8 +56,8 @@ public class FragmentLayoutContentSettings extends Fragment implements MainConte
return;
}
UserPrefsHelper.mapRenderer(app.getPrefs(), position);
ui.alert(AlertDialogFactory.restartDialog(app));
UserPrefsHelper.mapRenderer(userPrefs, position);
ui.alert(AlertDialogFactory.restartDialog(activity));
}
@Override
@@ -10,14 +10,14 @@ import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import android.widget.LinearLayout;
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.style.MapStyle;
import eu.konggdev.strikemaps.storage.RegistryStorageComponent;
import eu.konggdev.strikemaps.ui.UIComponent;
import eu.konggdev.strikemaps.ui.fragment.dialog.NewStyleBottomSheet;
@@ -28,10 +28,10 @@ import java.util.Map;
import java.util.Objects;
public class FragmentMapChangePopup extends Fragment implements Popup {
@NonNull AppController app;
@NonNull MapComponent map;
@NonNull UIComponent ui;
@NonNull RegistryStorageComponent registry;
private final AppCompatActivity activity;
private final MapComponent map;
private final UIComponent ui;
private final RegistryStorageComponent registry;
private final Integer region;
@@ -52,17 +52,16 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
public void reloadStyles() {
LinearLayout stylesLayout = view.findViewById(R.id.stylesLayout);
stylesLayout.removeAllViews();
app.getRegistry().getStyles().forEach((id, style) -> {
registry.getStyles().forEach((id, style) -> {
View item = new GenericItem(
style.document,
app,
() -> 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)
.setVisibility(View.VISIBLE);
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("",
addNewIcon,
this::newStyleFlow).makeView(ui));
@@ -95,11 +94,11 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
}
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) {
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) {
@@ -107,12 +106,12 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
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);
this.app = app;
this.map = app.getMap();
this.ui = app.getUi();
this.registry = app.getRegistry();
this.activity = activity;
this.ui = ui;
this.map = map;
this.registry = registry;
this.region = region;
}
@@ -1,23 +1,22 @@
package eu.konggdev.strikemaps.ui.screen;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.appcompat.widget.Toolbar;
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.FragmentEmptyPlaceholder;
import eu.konggdev.strikemaps.ui.fragment.popup.Popup;
import eu.konggdev.strikemaps.ui.element.region.UIRegion;
public class Screen {
@NonNull AppController app;
Toolbar toolbar;
public Screen(AppController app, Map<Integer, UIRegion> regions) {
this.app = app;
private final ComponentHolderActivity activity;
public Screen(ComponentHolderActivity activity, Map<Integer, UIRegion> regions) {
this.activity = activity;
this.uiRegions = regions;
}
Map<Integer, UIRegion> uiRegions;
@@ -55,7 +54,7 @@ public class Screen {
}
public void fragmentTransaction(int layoutId, Fragment fragment) {
app.getActivity().getSupportFragmentManager()
activity.getSupportFragmentManager()
.beginTransaction()
.replace(layoutId, fragment)
.commit();
@@ -1,4 +1,4 @@
package eu.konggdev.strikemaps.helper;
package eu.konggdev.strikemaps.util.file;
import android.content.res.AssetManager;
@@ -7,25 +7,29 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import android.util.Log;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import eu.konggdev.strikemaps.app.AppController;
import androidx.appcompat.app.AppCompatActivity;
//FIXME: Ugly
public final class FileHelper {
public static Bitmap getIcon(String iconLocator, AppController app) {
public final class FileTools {
private static final String TAG = "FileUtils";
public static Bitmap getIcon(String iconLocator, AppCompatActivity activity) {
switch (iconLocator.split("//")[0]) {
//TODO: https
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:
app.logcat("Unimplemented icon locator space: " + iconLocator);
Log.e(TAG, "Unimplemented icon locator space: " + iconLocator);
return null;
}
}
public static String loadStringFromAssetFile(String filePath, AppController app) {
try (InputStream is = app.getActivity().getAssets().open(filePath)) {
public static String loadStringFromAssetFile(String filePath, AppCompatActivity activity) {
try (InputStream is = activity.getAssets().open(filePath)) {
int size = is.available();
byte[] buffer = new byte[size];
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 {
try {
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();
public static String[] getAssetFiles(String path, String fileExt, AppCompatActivity activity) {
AssetManager assetManager = activity.getAssets();
try {
if (path != null && path.startsWith("/")) {
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 {
return app.getActivity().getAssets().open(path);
return activity.getAssets().open(path);
} catch (IOException 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.node.ArrayNode;