WIP
11
.gitignore
vendored
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
*.iml
|
||||||
|
.gradle
|
||||||
|
/local.properties
|
||||||
|
/.idea/
|
||||||
|
DS_Store
|
||||||
|
/build
|
||||||
|
/captures
|
||||||
|
.externalNativeBuild
|
||||||
|
.cxx
|
||||||
|
local.properties
|
||||||
|
/legacy_code/
|
||||||
24
UNLICENSE
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <https://unlicense.org/>
|
||||||
1
app/.gitignore
vendored
Executable file
@@ -0,0 +1 @@
|
|||||||
|
/build
|
||||||
68
app/build.gradle.kts
Executable file
@@ -0,0 +1,68 @@
|
|||||||
|
plugins {
|
||||||
|
alias(libs.plugins.android.application)
|
||||||
|
alias(libs.plugins.kotlin.android)
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "eu.konggdev.strikemaps"
|
||||||
|
compileSdk = 36
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId = "eu.konggdev.strikemaps"
|
||||||
|
minSdk = 24
|
||||||
|
targetSdk = 35
|
||||||
|
versionCode = 1
|
||||||
|
versionName = "1.0"
|
||||||
|
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
compilerOptions {
|
||||||
|
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.appcompat)
|
||||||
|
implementation(libs.material)
|
||||||
|
implementation(libs.activity)
|
||||||
|
implementation(libs.constraintlayout)
|
||||||
|
implementation(libs.viewpager2)
|
||||||
|
|
||||||
|
implementation("org.maplibre.gl:android-sdk:11.13.0")
|
||||||
|
implementation("com.github.mapsforge.vtm:vtm:0.27.0")
|
||||||
|
implementation("com.github.mapsforge.vtm:vtm-android:0.27.0")
|
||||||
|
implementation("com.github.mapsforge.vtm:vtm-http:0.27.0")
|
||||||
|
implementation ("com.github.mapsforge.vtm:vtm-android:0.27.0@jar")
|
||||||
|
runtimeOnly ("com.github.mapsforge.vtm:vtm-android:0.27.0:natives-armeabi-v7a@jar")
|
||||||
|
runtimeOnly("com.github.mapsforge.vtm:vtm-android:0.27.0:natives-arm64-v8a@jar")
|
||||||
|
runtimeOnly("com.github.mapsforge.vtm:vtm-android:0.27.0:natives-x86@jar")
|
||||||
|
runtimeOnly("com.github.mapsforge.vtm:vtm-android:0.27.0:natives-x86_64@jar")
|
||||||
|
implementation("com.google.guava:guava:33.2.1-android")
|
||||||
|
implementation("com.caverock:androidsvg:1.4")
|
||||||
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||||
|
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.0")
|
||||||
|
implementation("org.apache.commons:commons-lang3:3.14.0")
|
||||||
|
implementation(libs.core.ktx)
|
||||||
|
|
||||||
|
testImplementation(libs.junit)
|
||||||
|
androidTestImplementation(libs.ext.junit)
|
||||||
|
androidTestImplementation(libs.espresso.core)
|
||||||
|
}
|
||||||
21
app/proguard-rules.pro
vendored
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
||||||
26
app/src/androidTest/java/eu/konggdev/strikemaps/ExampleInstrumentedTest.java
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
package eu.konggdev.strikemaps;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
public void useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||||
|
assertEquals("eu.konggdev.strikemaps", appContext.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
||||||
28
app/src/main/AndroidManifest.xml
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/Theme.StrikeMaps"
|
||||||
|
tools:targetApi="31">
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
|
</manifest>
|
||||||
BIN
app/src/main/assets/bundled/icon/classic.bmp
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
app/src/main/assets/bundled/icon/satelite.bmp
Normal file
|
After Width: | Height: | Size: 768 KiB |
2262
app/src/main/assets/bundled/style/classic.style.json
Normal file
27
app/src/main/assets/bundled/style/satelite.style.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"version": 8,
|
||||||
|
"name": "Satelite",
|
||||||
|
"icon": "assets://satelite.bmp",
|
||||||
|
"sources": {
|
||||||
|
"satelite": {
|
||||||
|
"type": "raster",
|
||||||
|
"tiles": [
|
||||||
|
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
|
||||||
|
],
|
||||||
|
"minzoom": 0,
|
||||||
|
"maxzoom": 18,
|
||||||
|
"scheme": "xyz",
|
||||||
|
"tileSize": 512
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sprite": "",
|
||||||
|
"glyphs": "https://orangemug.github.io/font-glyphs/glyphs/{fontstack}/{range}.pbf",
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "satelite",
|
||||||
|
"type": "raster",
|
||||||
|
"source": "satelite"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": "satellite"
|
||||||
|
}
|
||||||
5
app/src/main/java/eu/konggdev/strikemaps/Component.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package eu.konggdev.strikemaps;
|
||||||
|
|
||||||
|
public interface Component {
|
||||||
|
//TODO: Implement base component methods
|
||||||
|
}
|
||||||
31
app/src/main/java/eu/konggdev/strikemaps/MainActivity.java
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
package eu.konggdev.strikemaps;
|
||||||
|
|
||||||
|
import static org.maplibre.android.style.layers.PropertyFactory.lineColor;
|
||||||
|
import static org.maplibre.android.style.layers.PropertyFactory.lineWidth;
|
||||||
|
|
||||||
|
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);
|
||||||
|
app.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logcat(String tag, String log) {
|
||||||
|
Log.i(tag, log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logcat(String log) {
|
||||||
|
Log.i("LogcatGeneric", log);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package eu.konggdev.strikemaps.app;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.MainActivity;
|
||||||
|
import eu.konggdev.strikemaps.R;
|
||||||
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
|
import eu.konggdev.strikemaps.ui.UIComponent;
|
||||||
|
|
||||||
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
|
public class AppController {
|
||||||
|
private final MainActivity appActivity;
|
||||||
|
|
||||||
|
private MapComponent map;
|
||||||
|
private UIComponent ui;
|
||||||
|
public AppController(MainActivity refActivity) {
|
||||||
|
appActivity = refActivity;
|
||||||
|
}
|
||||||
|
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 SharedPreferences getPrefs() {
|
||||||
|
return getActivity().getSharedPreferences("user_prefs", MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
public AppCompatActivity getActivity() { return appActivity; }
|
||||||
|
public void init() {
|
||||||
|
if (getActivity().getSupportActionBar() != null)
|
||||||
|
getActivity().getSupportActionBar().hide();
|
||||||
|
|
||||||
|
if(map == null) map = new MapComponent(this);
|
||||||
|
if(ui == null) {
|
||||||
|
ui = new UIComponent(this, map);
|
||||||
|
ui.swapScreen(R.layout.screen_main); //Initial
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package eu.konggdev.strikemaps.factory;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
|
import eu.konggdev.strikemaps.ui.element.item.PreviewItem;
|
||||||
|
import org.maplibre.geojson.Feature;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
//FIXME: Move Item functions into specific classes for specific types - e.g. StyleItem
|
||||||
|
public final class AlertDialogFactory {
|
||||||
|
public static AlertDialog pointSelector(AppController app, List<Feature> features, Consumer<Feature> callback) {
|
||||||
|
LinearLayout layout = new LinearLayout(app.getActivity());
|
||||||
|
layout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
|
||||||
|
ScrollView scrollView = new ScrollView(app.getActivity());
|
||||||
|
scrollView.addView(layout);
|
||||||
|
|
||||||
|
AlertDialog dialog = new AlertDialog.Builder(app.getActivity())
|
||||||
|
.setView(scrollView)
|
||||||
|
.create();
|
||||||
|
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#000000")));
|
||||||
|
|
||||||
|
for (Feature feature : features) {
|
||||||
|
View itemView = PreviewItem.fromFeature(feature).makeView(app.getUi(), v -> {
|
||||||
|
dialog.dismiss();
|
||||||
|
new android.os.Handler(android.os.Looper.getMainLooper())
|
||||||
|
.post(() -> callback.accept(feature));
|
||||||
|
});
|
||||||
|
layout.addView(itemView);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
}
|
||||||
109
app/src/main/java/eu/konggdev/strikemaps/helper/FileHelper.java
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package eu.konggdev.strikemaps.helper;
|
||||||
|
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.os.Environment;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
|
|
||||||
|
//FIXME: Ugly
|
||||||
|
public final class FileHelper {
|
||||||
|
public static String loadStringFromAssetFile(String filePath, AppController app) {
|
||||||
|
try (InputStream is = app.getActivity().getAssets().open(filePath)) {
|
||||||
|
int size = is.available();
|
||||||
|
byte[] buffer = new byte[size];
|
||||||
|
is.read(buffer);
|
||||||
|
return new String(buffer, StandardCharsets.UTF_8);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String loadStringFromUserFile(String filePath) {
|
||||||
|
File file = new File(filePath);
|
||||||
|
|
||||||
|
try (FileInputStream fis = new FileInputStream(file)) {
|
||||||
|
int size = fis.available();
|
||||||
|
byte[] buffer = new byte[size];
|
||||||
|
fis.read(buffer);
|
||||||
|
return new String(buffer, StandardCharsets.UTF_8);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[] getAssetFiles(String path, String fileExt, AppController app) {
|
||||||
|
AssetManager assetManager = app.getActivity().getAssets();
|
||||||
|
try {
|
||||||
|
if (path != null && path.startsWith("/")) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
String fullPath = (path == null || path.isEmpty()) ? "" : path;
|
||||||
|
|
||||||
|
String[] files = assetManager.list(fullPath);
|
||||||
|
|
||||||
|
if (files == null) return new String[0];
|
||||||
|
|
||||||
|
if (fileExt == null || fileExt.isEmpty())
|
||||||
|
return files;
|
||||||
|
|
||||||
|
List<String> filtered = new ArrayList<>();
|
||||||
|
for (String file : files) {
|
||||||
|
if (file.toLowerCase().endsWith(fileExt.toLowerCase())) {
|
||||||
|
filtered.add((fullPath.isEmpty() ? "" : fullPath + "/") + file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered.toArray(new String[0]);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InputStream openAssetStream(String path, AppController app) {
|
||||||
|
try {
|
||||||
|
return app.getActivity().getAssets().open(path);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[] getUserFiles(String path, String fileExt, AppController app) {
|
||||||
|
String packageName = app.getActivity().getPackageName();
|
||||||
|
File userDirectory = new File(Environment.getExternalStorageDirectory(), "Android/data/" + packageName + "/" + path);
|
||||||
|
|
||||||
|
if (!userDirectory.exists() || !userDirectory.isDirectory())
|
||||||
|
return new String[0];
|
||||||
|
|
||||||
|
File[] files = userDirectory.listFiles(new FilenameFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(File dir, String filename) {
|
||||||
|
if (fileExt == null || fileExt.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filename.toLowerCase().endsWith(fileExt.toLowerCase());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (files == null || files.length == 0) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> fileList = new ArrayList<>();
|
||||||
|
for (File file : files) {
|
||||||
|
fileList.add(file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileList.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package eu.konggdev.strikemaps.helper;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
public final class UserPrefsHelper {
|
||||||
|
private UserPrefsHelper() {} // prevent instantiation
|
||||||
|
|
||||||
|
//Keys
|
||||||
|
private static final String KEY_STARTUP_MAP_STYLE = "startupMapStyle";
|
||||||
|
private static final String KEY_MAP_RENDERER = "mapRenderer";
|
||||||
|
private static final String KEY_PERSIST_LOCATION_ENABLED = "persistLocationEnabled";
|
||||||
|
private static final String KEY_LAST_LOCATION_ENABLED = "lastLocationEnabled";
|
||||||
|
|
||||||
|
//Defaults
|
||||||
|
private static final String DEFAULT_MAP_STYLE = "bundled/style/classic.style.json";
|
||||||
|
private static final String DEFAULT_MAP_RENDERER = "mapLibre";
|
||||||
|
private static final boolean DEFAULT_PERSIST_LOCATION_ENABLED = true;
|
||||||
|
private static final boolean DEFAULT_LAST_LOCATION_ENABLED = false;
|
||||||
|
|
||||||
|
|
||||||
|
public static String startupMapStyle(SharedPreferences prefs) {
|
||||||
|
return prefs.getString(KEY_STARTUP_MAP_STYLE, DEFAULT_MAP_STYLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String mapRenderer(SharedPreferences prefs) {
|
||||||
|
return prefs.getString(KEY_MAP_RENDERER, DEFAULT_MAP_RENDERER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean persistLocationEnabled(SharedPreferences prefs) {
|
||||||
|
return prefs.getBoolean(KEY_PERSIST_LOCATION_ENABLED, DEFAULT_PERSIST_LOCATION_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean lastLocationEnabled(SharedPreferences prefs) {
|
||||||
|
return prefs.getBoolean(KEY_LAST_LOCATION_ENABLED, DEFAULT_LAST_LOCATION_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean lastLocationEnabled(SharedPreferences prefs, boolean status) {
|
||||||
|
return prefs.edit().putBoolean(KEY_LAST_LOCATION_ENABLED, status).commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package eu.konggdev.strikemaps.map;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import eu.konggdev.strikemaps.Component;
|
||||||
|
import eu.konggdev.strikemaps.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.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 {
|
||||||
|
MapRenderer mapRenderer;
|
||||||
|
AppController app;
|
||||||
|
|
||||||
|
public String style;
|
||||||
|
public Map<Class<? extends MapOverlay>, MapOverlay> overlays = new HashMap<>();
|
||||||
|
public MapComponent(AppController ref) {
|
||||||
|
this.app = ref;
|
||||||
|
switch(UserPrefsHelper.mapRenderer(app.getPrefs())) {
|
||||||
|
case "vtm":
|
||||||
|
this.mapRenderer = new VtmRenderer(app, this);
|
||||||
|
break;
|
||||||
|
case "mapLibre":
|
||||||
|
default: //This shouldn't happen
|
||||||
|
this.mapRenderer = new MapLibreNativeRenderer(app, this);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public FragmentLayoutContentMap toFragment() {
|
||||||
|
return new FragmentLayoutContentMap(mapRenderer.getView());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStyle(String style) {
|
||||||
|
this.style = style;
|
||||||
|
mapRenderer.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void switchOverlay(MapOverlay overlay) {
|
||||||
|
if (hasOverlay(overlay)) overlays.remove(overlay.getClass());
|
||||||
|
else overlays.put(overlay.getClass(), overlay);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasOverlay(MapOverlay overlay) {
|
||||||
|
return overlays.containsKey(overlay.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasOverlay(Class<? extends MapOverlay> overlay) {
|
||||||
|
return overlays.containsKey(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectPoint(Feature selection) {
|
||||||
|
//FIXME: Put back FragmentPointPreviewPopup (private code atm)
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onOverlayUpdate() {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
if(mapRenderer != null && style != null) mapRenderer.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onMapClick(LatLng point) {
|
||||||
|
List<Feature> features = mapRenderer.featuresAtPoint(point);
|
||||||
|
|
||||||
|
switch (features.size()) {
|
||||||
|
case 0:
|
||||||
|
//TODO: Implement point selection for no POI found (MIGHT be done on long click??)
|
||||||
|
//Maybe collapse UI? (Hide/show UI feature)... could be user configurable
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
selectPoint(features.get(0));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
app.getUi().alert(
|
||||||
|
AlertDialogFactory.pointSelector(app, features, selectedItem -> {
|
||||||
|
selectPoint(selectedItem);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onMapLongClick(LatLng point) {
|
||||||
|
//TODO: Likely Nonfeature(?) point selection
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package eu.konggdev.strikemaps.map.layer;
|
||||||
|
|
||||||
|
import org.maplibre.android.style.layers.Layer;
|
||||||
|
import org.maplibre.android.style.sources.GeoJsonSource;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
//TOOD: Make not strictly MapLibre reliant
|
||||||
|
public class MapLayer {
|
||||||
|
public GeoJsonSource source;
|
||||||
|
public Layer layer;
|
||||||
|
public MapLayer(GeoJsonSource source, Layer layer) {
|
||||||
|
this.source = source;
|
||||||
|
this.layer = layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package eu.konggdev.strikemaps.map.overlay;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.map.layer.MapLayer;
|
||||||
|
|
||||||
|
/* More or less a data-driven layer factory */
|
||||||
|
public interface MapOverlay {
|
||||||
|
public MapLayer makeLayer();
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package eu.konggdev.strikemaps.map.overlay.overlay;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.location.Location;
|
||||||
|
import android.location.LocationListener;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
|
import eu.konggdev.strikemaps.map.layer.MapLayer;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
||||||
|
import eu.konggdev.strikemaps.provider.LocationDataProvider;
|
||||||
|
import org.maplibre.android.style.layers.CircleLayer;
|
||||||
|
import org.maplibre.android.style.layers.Property;
|
||||||
|
import org.maplibre.android.style.sources.GeoJsonSource;
|
||||||
|
import org.maplibre.geojson.Feature;
|
||||||
|
import org.maplibre.geojson.FeatureCollection;
|
||||||
|
import org.maplibre.geojson.Point;
|
||||||
|
|
||||||
|
import static org.maplibre.android.style.layers.PropertyFactory.*;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MapLayer makeLayer() {
|
||||||
|
GeoJsonSource source = new GeoJsonSource(
|
||||||
|
"location",
|
||||||
|
FeatureCollection.fromFeatures(new Feature[]{}) // empty
|
||||||
|
);
|
||||||
|
|
||||||
|
if (currentLocation != null)
|
||||||
|
source.setGeoJson(Feature.fromGeometry(Point.fromLngLat(currentLocation.getLongitude(), currentLocation.getLatitude())));
|
||||||
|
|
||||||
|
CircleLayer layer = new CircleLayer("location", "location");
|
||||||
|
layer.setProperties(
|
||||||
|
circleRadius(5f),
|
||||||
|
circleColor(Color.parseColor("#1E88E5")),
|
||||||
|
circleStrokeColor(Color.WHITE),
|
||||||
|
circleStrokeWidth(1.5f),
|
||||||
|
circlePitchAlignment(Property.CIRCLE_PITCH_ALIGNMENT_MAP)
|
||||||
|
);
|
||||||
|
|
||||||
|
return new MapLayer(source, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLocationChanged(@NonNull Location location) {
|
||||||
|
this.currentLocation = location;
|
||||||
|
map.onOverlayUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package eu.konggdev.strikemaps.map.overlay.overlay;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.map.layer.MapLayer;
|
||||||
|
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
||||||
|
|
||||||
|
public class PointSelectionOverlay implements MapOverlay {
|
||||||
|
@Override
|
||||||
|
public MapLayer makeLayer() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package eu.konggdev.strikemaps.map.renderer;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.map.layer.MapLayer;
|
||||||
|
import org.maplibre.android.style.layers.Layer;
|
||||||
|
import org.maplibre.android.geometry.LatLng;
|
||||||
|
import org.maplibre.geojson.Feature;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface MapRenderer {
|
||||||
|
void reload();
|
||||||
|
|
||||||
|
View getView();
|
||||||
|
|
||||||
|
List<Feature> featuresAtPoint(LatLng point);
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package eu.konggdev.strikemaps.map.renderer.implementation;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.helper.FileHelper;
|
||||||
|
import eu.konggdev.strikemaps.helper.UserPrefsHelper;
|
||||||
|
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
||||||
|
import eu.konggdev.strikemaps.map.layer.MapLayer;
|
||||||
|
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
||||||
|
import org.maplibre.android.MapLibre;
|
||||||
|
import org.maplibre.android.geometry.LatLng;
|
||||||
|
import org.maplibre.android.maps.MapLibreMap;
|
||||||
|
import org.maplibre.android.maps.MapView;
|
||||||
|
import org.maplibre.android.maps.OnMapReadyCallback;
|
||||||
|
import org.maplibre.android.maps.Style;
|
||||||
|
import org.maplibre.geojson.Feature;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
|
|
||||||
|
public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
|
||||||
|
AppController app;
|
||||||
|
MapComponent controller;
|
||||||
|
MapLibreMap map;
|
||||||
|
final MapView mapView;
|
||||||
|
|
||||||
|
public MapLibreNativeRenderer(AppController app, MapComponent controller) {
|
||||||
|
this.app = app;
|
||||||
|
this.controller = controller;
|
||||||
|
MapLibre.getInstance(app.getActivity());
|
||||||
|
this.mapView = new MapView(app.getActivity());
|
||||||
|
mapView.onCreate(null);
|
||||||
|
mapView.getMapAsync(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void passLayer(MapLayer layer) {
|
||||||
|
map.getStyle().addSource(layer.source);
|
||||||
|
map.getStyle().addLayer(layer.layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
map.setStyle(new Style.Builder().fromJson(controller.style), style -> {
|
||||||
|
for(MapOverlay overlay : controller.overlays.values()) {
|
||||||
|
passLayer(overlay.makeLayer());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView() {
|
||||||
|
return mapView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Feature> featuresAtPoint(LatLng point) {
|
||||||
|
return map.queryRenderedFeatures(map.getProjection().toScreenLocation(point));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMapReady(@NonNull MapLibreMap maplibreMap) {
|
||||||
|
this.map = maplibreMap;
|
||||||
|
|
||||||
|
controller.style = FileHelper.loadStringFromAssetFile(UserPrefsHelper.startupMapStyle(app.getPrefs()), app);
|
||||||
|
|
||||||
|
//I have my own implementation of attribution that credits MapLibre among others, it's not as bad as it looks :)
|
||||||
|
map.getUiSettings().setLogoEnabled(false);
|
||||||
|
map.getUiSettings().setAttributionEnabled(false);
|
||||||
|
|
||||||
|
map.addOnMapClickListener(point -> controller.onMapClick(point));
|
||||||
|
map.addOnMapLongClickListener(point -> controller.onMapLongClick(point));
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package eu.konggdev.strikemaps.map.renderer.implementation;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
|
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import org.maplibre.android.geometry.LatLng;
|
||||||
|
import org.maplibre.geojson.Feature;
|
||||||
|
import org.oscim.android.MapView;
|
||||||
|
import org.oscim.map.Map;
|
||||||
|
import org.oscim.tiling.source.OkHttpEngine;
|
||||||
|
import org.oscim.tiling.source.oscimap4.OSciMap4TileSource;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class VtmRenderer implements MapRenderer {
|
||||||
|
AppController app;
|
||||||
|
MapComponent controller;
|
||||||
|
|
||||||
|
Map map;
|
||||||
|
final MapView mapView;
|
||||||
|
|
||||||
|
public VtmRenderer(AppController app, MapComponent controller) {
|
||||||
|
this.app = app;
|
||||||
|
this.controller = controller;
|
||||||
|
this.mapView = new MapView(app.getActivity());
|
||||||
|
this.map = mapView.map();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
//TODO
|
||||||
|
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||||
|
OSciMap4TileSource tileSource = OSciMap4TileSource.builder().httpFactory(new OkHttpEngine.OkHttpFactory(builder)).build();
|
||||||
|
|
||||||
|
map.setBaseMap(tileSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView() {
|
||||||
|
return mapView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Feature> featuresAtPoint(LatLng point) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package eu.konggdev.strikemaps.map.source;
|
||||||
|
|
||||||
|
public class MapSource {
|
||||||
|
public final String url;
|
||||||
|
public final String type;
|
||||||
|
public final String schema;
|
||||||
|
public MapSource(String url, String type, String schema) {
|
||||||
|
this.url = url;
|
||||||
|
this.type = type;
|
||||||
|
this.schema = schema;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package eu.konggdev.strikemaps.provider;
|
||||||
|
|
||||||
|
public class HttpDataProvider implements Provider {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package eu.konggdev.strikemaps.provider;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.location.Location;
|
||||||
|
import android.location.LocationListener;
|
||||||
|
import android.location.LocationManager;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class LocationDataProvider implements Provider {
|
||||||
|
private LocationManager locationManager;
|
||||||
|
|
||||||
|
private List<String> locationManagerProviders = List.of(LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER);
|
||||||
|
public LocationDataProvider(AppCompatActivity activity, LocationListener listener) {
|
||||||
|
locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
|
||||||
|
|
||||||
|
//TODO: Move permission request to UI
|
||||||
|
if(ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Location initLocation = null;
|
||||||
|
|
||||||
|
for (String provider : locationManagerProviders) {
|
||||||
|
if(locationManager.isProviderEnabled(provider)) {
|
||||||
|
if (initLocation == null) {
|
||||||
|
initLocation = locationManager.getLastKnownLocation(provider);
|
||||||
|
if (initLocation != null)
|
||||||
|
listener.onLocationChanged(initLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
locationManager.requestLocationUpdates(
|
||||||
|
provider,
|
||||||
|
1000,
|
||||||
|
1,
|
||||||
|
listener
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package eu.konggdev.strikemaps.provider;
|
||||||
|
|
||||||
|
public interface Provider {
|
||||||
|
|
||||||
|
}
|
||||||
77
app/src/main/java/eu/konggdev/strikemaps/ui/UIComponent.java
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.view.View;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import eu.konggdev.strikemaps.Component;
|
||||||
|
import eu.konggdev.strikemaps.R;
|
||||||
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
|
import eu.konggdev.strikemaps.ui.element.UIRegion;
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.layout.FragmentLayoutControls;
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentSettings;
|
||||||
|
import eu.konggdev.strikemaps.ui.screen.Screen;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class UIComponent implements Component {
|
||||||
|
@NonNull AppController app;
|
||||||
|
private Map<Integer, Screen> screens;
|
||||||
|
private Integer currentScreen;
|
||||||
|
|
||||||
|
public UIComponent(AppController app, MapComponent map) {
|
||||||
|
this.app = app;
|
||||||
|
this.screens = Map.of(
|
||||||
|
//Main screen
|
||||||
|
R.layout.screen_main, new Screen(
|
||||||
|
//App reference
|
||||||
|
app,
|
||||||
|
//Map view
|
||||||
|
map.toFragment(), //FragmentLayoutContentMap
|
||||||
|
//Main screen init regions definition
|
||||||
|
Map.of(R.id.bottomUi, new UIRegion(new FragmentLayoutControls(app, R.id.bottomUi), R.id.bottomUi)), //TODO: Probably stop referencing layout 3(!) times everytime
|
||||||
|
//Layout
|
||||||
|
R.layout.screen_main //TODO: Define this for the Screen without duplicating the reference
|
||||||
|
),
|
||||||
|
//Settings screen
|
||||||
|
R.layout.screen_settings, new Screen(
|
||||||
|
app,
|
||||||
|
//Settings
|
||||||
|
new FragmentLayoutContentSettings(),
|
||||||
|
/* No regions defined in settings
|
||||||
|
Entire screen is just the main view */
|
||||||
|
new HashMap<>(),
|
||||||
|
//Layout
|
||||||
|
R.layout.screen_settings
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void swapScreen(Integer screen) {
|
||||||
|
currentScreen = screen;
|
||||||
|
getCurrentScreen().attachAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Screen getCurrentScreen() {
|
||||||
|
return getScreen(currentScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Screen getScreen(Integer screen) {
|
||||||
|
return screens.get(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void alert(AlertDialog dialog) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.element;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.layout.Layout;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
|
||||||
|
public class UIRegion {
|
||||||
|
private final ArrayDeque<Fragment> previousFragments = new ArrayDeque<>();
|
||||||
|
|
||||||
|
private Fragment stockFragment;
|
||||||
|
private Fragment currentFragment;
|
||||||
|
public Integer layoutId;
|
||||||
|
|
||||||
|
public UIRegion(@NonNull Fragment initFragment, Integer refLayoutId) {
|
||||||
|
this.currentFragment = initFragment;
|
||||||
|
this.stockFragment = initFragment;
|
||||||
|
|
||||||
|
this.layoutId = refLayoutId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Fragment getFragment() {
|
||||||
|
return currentFragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFragment(Fragment fragment) {
|
||||||
|
previousFragments.add(currentFragment);
|
||||||
|
currentFragment = fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void overwriteStockFragment(Fragment fragment) {
|
||||||
|
stockFragment = fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void back() {
|
||||||
|
if (!previousFragments.isEmpty()) {
|
||||||
|
currentFragment = previousFragments.pop();
|
||||||
|
} else {
|
||||||
|
currentFragment = stockFragment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.element.item;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
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.ui.UIComponent;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class GenericItem implements UIItem {
|
||||||
|
@NonNull public String name;
|
||||||
|
public Bitmap image;
|
||||||
|
public Runnable onClick;
|
||||||
|
boolean hasImage;
|
||||||
|
public GenericItem(String refName) {
|
||||||
|
this.name = refName;
|
||||||
|
hasImage = false;
|
||||||
|
}
|
||||||
|
public GenericItem(String refName, Runnable onClick) {
|
||||||
|
this.name = refName;
|
||||||
|
this.onClick = onClick;
|
||||||
|
hasImage = false;
|
||||||
|
}
|
||||||
|
public GenericItem(String refName, Bitmap refImage) {
|
||||||
|
this.name = refName;
|
||||||
|
this.image = refImage;
|
||||||
|
hasImage = true;
|
||||||
|
}
|
||||||
|
public GenericItem(String refName, Bitmap refImage, Runnable onClick) {
|
||||||
|
this.name = refName;
|
||||||
|
this.image = refImage;
|
||||||
|
this.onClick = onClick;
|
||||||
|
hasImage = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: Ugly glue static constructor
|
||||||
|
public final static GenericItem fromStyle(String style, AppController app, MapComponent map) {
|
||||||
|
try {
|
||||||
|
JSONObject styleJson = new JSONObject(style);
|
||||||
|
String name = "Unknown"; //Fallback name
|
||||||
|
if (styleJson.has("name")) name = styleJson.getString("name");
|
||||||
|
if (styleJson.has("icon")) {
|
||||||
|
switch(styleJson.getString("icon").split("//")[0]) {
|
||||||
|
//TODO: https
|
||||||
|
case "assets:":
|
||||||
|
Bitmap icon = BitmapFactory.decodeStream(FileHelper.openAssetStream("bundled/icon/" + styleJson.getString("icon").split("//")[1], app));
|
||||||
|
return new GenericItem(name, icon, () -> map.setStyle(style));
|
||||||
|
default:
|
||||||
|
app.logcat("Unimplemented icon source requested in style: " + name);
|
||||||
|
return new GenericItem(name, () -> map.setStyle(style));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new GenericItem(name, () -> map.setStyle(style));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new GenericItem("Exception!", () -> map.setStyle(style));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public View makeView(UIComponent spawner) {
|
||||||
|
View v = spawner.inflateUi(R.layout.item_generic);
|
||||||
|
//FIXME: These shouldn't be casted like that!
|
||||||
|
((TextView) v.findViewById(R.id.name)).setText(name);
|
||||||
|
if(image != null) ((ImageButton) v.findViewById(R.id.image)).setImageBitmap(image);
|
||||||
|
if(onClick != null) v.findViewById(R.id.image).setOnClickListener(click(onClick));
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.element.item;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.ui.UIComponent;
|
||||||
|
import org.maplibre.geojson.Feature;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.R;
|
||||||
|
public class PreviewItem implements UIItem {
|
||||||
|
public String name;
|
||||||
|
public String type;
|
||||||
|
public Bitmap image;
|
||||||
|
boolean hasImage;
|
||||||
|
public PreviewItem(String refName, String refType) {
|
||||||
|
this.name = refName;
|
||||||
|
this.type = refType;
|
||||||
|
hasImage = false;
|
||||||
|
}
|
||||||
|
public PreviewItem(String refName, String refType, Bitmap refImage) {
|
||||||
|
this.name = refName;
|
||||||
|
this.type = refType;
|
||||||
|
this.image = refImage;
|
||||||
|
hasImage = true;
|
||||||
|
}
|
||||||
|
public static PreviewItem fromFeature(Feature feature) {
|
||||||
|
return new PreviewItem(feature.getStringProperty("name"), feature.getStringProperty("class"));
|
||||||
|
}
|
||||||
|
public View makeView(UIComponent spawner) {
|
||||||
|
View view = spawner.inflateUi(R.layout.item_preview);
|
||||||
|
((TextView) view.findViewById(R.id.choiceName)).setText(name);
|
||||||
|
((TextView) view.findViewById(R.id.type)).setText(type);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
public View makeView(UIComponent spawner, View.OnClickListener onClick) {
|
||||||
|
View view = makeView(spawner);
|
||||||
|
view.setOnClickListener(onClick);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.element.item;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.ui.UIComponent;
|
||||||
|
|
||||||
|
public interface UIItem {
|
||||||
|
abstract View makeView(UIComponent spawner);
|
||||||
|
|
||||||
|
default View.OnClickListener click(Runnable action) {
|
||||||
|
return v -> action.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
default View.OnLongClickListener longClick(Runnable action) { return v -> { action.run(); return true; };}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.fragment;
|
||||||
|
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import eu.konggdev.strikemaps.ui.element.UIRegion;
|
||||||
|
|
||||||
|
public interface ContainerFragment {
|
||||||
|
abstract public Integer getRegion();
|
||||||
|
|
||||||
|
abstract public Fragment toFragment();
|
||||||
|
|
||||||
|
|
||||||
|
//Helper methods (ugly)
|
||||||
|
//FIXME
|
||||||
|
default void setupButton(View view, int button, View.OnClickListener onClick) {
|
||||||
|
view.findViewById(button)
|
||||||
|
.setOnClickListener(onClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void setupButton(View view, int button, View.OnClickListener onClick, View.OnLongClickListener onLongClick) {
|
||||||
|
View buttonView = view.findViewById(button);
|
||||||
|
buttonView.setOnClickListener(onClick);
|
||||||
|
buttonView.setOnLongClickListener(onLongClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void setupButton(View view, int button, View.OnLongClickListener onLongClick) {
|
||||||
|
view.findViewById(button)
|
||||||
|
.setOnLongClickListener(onLongClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
default View.OnClickListener click(Runnable action) {
|
||||||
|
return v -> action.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
default View.OnLongClickListener longClick(Runnable action) { return v -> { action.run(); return true; };}
|
||||||
|
|
||||||
|
//TODO: Make animation less wonky
|
||||||
|
default void setupDragHandle(View dragHandle, View layout, Runnable closeAction) {
|
||||||
|
final float[] dY = new float[1];
|
||||||
|
dragHandle.setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
switch (event.getActionMasked()) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
dY[0] = event.getRawY() - layout.getY();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
float newY = event.getRawY() - dY[0];
|
||||||
|
if (newY >= 0) {
|
||||||
|
layout.setY(newY);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
if (layout.getY() > layout.getHeight() / 4) {
|
||||||
|
layout.animate()
|
||||||
|
.scaleX(0f)
|
||||||
|
.scaleY(0f)
|
||||||
|
.alpha(0f)
|
||||||
|
.setDuration(300)
|
||||||
|
.withEndAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
layout.setVisibility(View.GONE);
|
||||||
|
closeAction.run();
|
||||||
|
layout.setScaleX(1f);
|
||||||
|
layout.setScaleY(1f);
|
||||||
|
layout.setAlpha(1f);
|
||||||
|
layout.setY(0f);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.start();
|
||||||
|
} else {
|
||||||
|
layout.animate()
|
||||||
|
.translationY(0f)
|
||||||
|
.setDuration(200)
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.fragment;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
public class FragmentEmptyPlaceholder extends Fragment {
|
||||||
|
//:)
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.fragment.layout;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
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.helper.UserPrefsHelper;
|
||||||
|
import eu.konggdev.strikemaps.map.overlay.overlay.LocationOverlay;
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup;
|
||||||
|
|
||||||
|
public class FragmentLayoutControls extends Fragment implements Layout {
|
||||||
|
AppController app;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleLocationService() {
|
||||||
|
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));
|
||||||
|
setupView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void zoomToLocation() {
|
||||||
|
if(!app.getMap().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))
|
||||||
|
.setPositiveButton("OK", null).show();
|
||||||
|
}
|
||||||
|
//*//
|
||||||
|
|
||||||
|
public FragmentLayoutControls(AppController app, Integer region) {
|
||||||
|
super(R.layout.fragment_controls);
|
||||||
|
this.app = app;
|
||||||
|
this.region = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getRegion() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment toFragment() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
this.rootView = view;
|
||||||
|
|
||||||
|
/* 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))
|
||||||
|
toggleLocationService();
|
||||||
|
|
||||||
|
this.setupView();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.attributionButton, click(this::attributtionDialog));
|
||||||
|
setupButton(rootView, R.id.locationButton, click(this::zoomToLocation), longClick(this::toggleLocationService));
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
setupButton(rootView, R.id.placesButton, click(this::notImplemented));
|
||||||
|
setupButton(rootView, R.id.placesButton, click(this::notImplemented));
|
||||||
|
setupButton(rootView, R.id.routeButton, click(this::notImplemented));
|
||||||
|
setupButton(rootView, R.id.modeButton, click(this::notImplemented));
|
||||||
|
|
||||||
|
TextView locationServiceStatusIndicator = rootView.findViewById(R.id.locationServiceStatusIndicator);
|
||||||
|
if (app.getMap().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));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
|
||||||
|
switch (requestCode) {
|
||||||
|
case 1:
|
||||||
|
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) toggleLocationService();
|
||||||
|
else Toast.makeText(requireContext(), "You need to grant location permission", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.fragment.layout;
|
||||||
|
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.ContainerFragment;
|
||||||
|
|
||||||
|
public interface Layout extends ContainerFragment {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.fragment.layout.content;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.layout.Layout;
|
||||||
|
|
||||||
|
public interface ContentLayout extends Layout {
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.ui.element.UIRegion;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.R;
|
||||||
|
|
||||||
|
public class FragmentLayoutContentMap extends Fragment implements MainContentLayout {
|
||||||
|
View mapView;
|
||||||
|
|
||||||
|
public FragmentLayoutContentMap(View refMapView) {
|
||||||
|
super(R.layout.fragment_map);
|
||||||
|
this.mapView = refMapView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment toFragment() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
LinearLayout layout = (LinearLayout) view;
|
||||||
|
layout.addView(mapView);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
public class FragmentLayoutContentSettings implements MainContentLayout {
|
||||||
|
@Override
|
||||||
|
public Fragment toFragment() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.R;
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.layout.content.ContentLayout;
|
||||||
|
|
||||||
|
public interface MainContentLayout extends ContentLayout {
|
||||||
|
default Integer getRegion() {
|
||||||
|
return R.id.mainContentView;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.fragment.popup;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.R;
|
||||||
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
|
import eu.konggdev.strikemaps.helper.FileHelper;
|
||||||
|
import eu.konggdev.strikemaps.factory.AlertDialogFactory;
|
||||||
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.ui.UIComponent;
|
||||||
|
import eu.konggdev.strikemaps.ui.element.item.GenericItem;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public class FragmentMapChangePopup extends Fragment implements Popup {
|
||||||
|
@NonNull AppController app;
|
||||||
|
@NonNull MapComponent map;
|
||||||
|
@NonNull UIComponent ui;
|
||||||
|
|
||||||
|
private final Integer region;
|
||||||
|
|
||||||
|
public FragmentMapChangePopup(AppController app, Integer region) {
|
||||||
|
super(R.layout.popup_map_change);
|
||||||
|
this.app = app;
|
||||||
|
this.map = app.getMap();
|
||||||
|
this.ui = app.getUi();
|
||||||
|
this.region = region;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Integer getRegion() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment toFragment() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||||
|
//FIXME
|
||||||
|
setupButton(view, R.id.closeButton, click(() -> ui.getCurrentScreen().closePopup()));
|
||||||
|
setupDragHandle(view, view, () -> ui.getCurrentScreen().closePopup());
|
||||||
|
String[] stylePaths = ArrayUtils.addAll(FileHelper.getAssetFiles("bundled/style", ".style.json", app), FileHelper.getUserFiles("style", ".style.json", app));
|
||||||
|
List<View> views = new ArrayList<>();
|
||||||
|
LinearLayout stylesLayout = view.findViewById(R.id.stylesLayout);
|
||||||
|
for(String i : stylePaths) {
|
||||||
|
if(i.startsWith("/storage")) stylesLayout.addView(GenericItem.fromStyle(FileHelper.loadStringFromUserFile(i), app, map).makeView(ui));
|
||||||
|
else stylesLayout.addView(GenericItem.fromStyle(FileHelper.loadStringFromAssetFile(i, app), app, map).makeView(ui));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.fragment.popup;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.ContainerFragment;
|
||||||
|
|
||||||
|
public interface Popup extends ContainerFragment {
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package eu.konggdev.strikemaps.ui.screen;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.R;
|
||||||
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.ContainerFragment;
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.MainContentLayout;
|
||||||
|
import eu.konggdev.strikemaps.ui.fragment.popup.Popup;
|
||||||
|
import eu.konggdev.strikemaps.ui.element.UIRegion;
|
||||||
|
|
||||||
|
public class Screen {
|
||||||
|
@NonNull AppController app;
|
||||||
|
public Screen(AppController app, MainContentLayout mainContent, Map<Integer, UIRegion> regions, Integer layout) {
|
||||||
|
this.app = app;
|
||||||
|
this.layout = layout;
|
||||||
|
this.mainContent = mainContent;
|
||||||
|
this.uiRegions = regions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Integer layout;
|
||||||
|
|
||||||
|
private MainContentLayout mainContent;
|
||||||
|
|
||||||
|
Map<Integer, UIRegion> uiRegions;
|
||||||
|
public Integer popup;
|
||||||
|
|
||||||
|
public void open(ContainerFragment fragment) {
|
||||||
|
if(fragment instanceof Popup && popup != null) return;
|
||||||
|
|
||||||
|
if(fragment instanceof Popup)
|
||||||
|
popup = fragment.getRegion();
|
||||||
|
|
||||||
|
setFragment(uiRegions.get(fragment.getRegion()), fragment.toFragment());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closePopup() {
|
||||||
|
if(popup != null) {
|
||||||
|
UIRegion popupRegion = uiRegions.get(popup);
|
||||||
|
popupRegion.back();
|
||||||
|
/* If newFragment is still a popup, assign the current popup value to the new fragment
|
||||||
|
otherwise, set the current popup value to null */
|
||||||
|
if(popupRegion.getFragment() instanceof Popup) {
|
||||||
|
popup = popupRegion.layoutId;
|
||||||
|
} else {
|
||||||
|
popup = null;
|
||||||
|
}
|
||||||
|
setFragment(popupRegion, popupRegion.getFragment());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFragment(UIRegion region, Fragment fragment) {
|
||||||
|
if (region == null) return;
|
||||||
|
|
||||||
|
region.setFragment(fragment);
|
||||||
|
fragmentTransaction(region.layoutId, fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fragmentTransaction(int layoutId, Fragment fragment) {
|
||||||
|
app.getActivity().getSupportFragmentManager()
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(layoutId, fragment)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void attachAll() {
|
||||||
|
app.getActivity().setContentView(layout);
|
||||||
|
fragmentTransaction(R.id.mainContentView, mainContent.toFragment());
|
||||||
|
for (UIRegion region : uiRegions.values()) {
|
||||||
|
setFragment(region, region.getFragment());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
app/src/main/res/drawable/ic_copy.bmp
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
app/src/main/res/drawable/ic_create.png
Normal file
|
After Width: | Height: | Size: 192 B |
BIN
app/src/main/res/drawable/ic_hamburger_menu.png
Normal file
|
After Width: | Height: | Size: 214 B |
BIN
app/src/main/res/drawable/ic_hide.bmp
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
app/src/main/res/drawable/ic_styles_menu.png
Normal file
|
After Width: | Height: | Size: 281 B |
95
app/src/main/res/layout/fragment_controls.xml
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/routeButton"
|
||||||
|
android:layout_width="65dp"
|
||||||
|
android:layout_height="42dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginBottom="36dp"
|
||||||
|
android:backgroundTint="#000000"
|
||||||
|
android:src="@android:drawable/ic_menu_directions"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/placesButton"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/placesButton"
|
||||||
|
android:layout_width="65dp"
|
||||||
|
android:layout_height="43dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginBottom="36dp"
|
||||||
|
android:backgroundTint="#000000"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/layersButton"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:srcCompat="@android:drawable/ic_menu_myplaces" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/layersButton"
|
||||||
|
android:layout_width="65dp"
|
||||||
|
android:layout_height="42dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:backgroundTint="#000000"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:srcCompat="@drawable/ic_styles_menu" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/modeButton"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="36dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="44dp"
|
||||||
|
android:backgroundTint="#000000"
|
||||||
|
android:src="@android:drawable/ic_menu_manage"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/locationButtonContainer"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/attributionButton"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="31dp"
|
||||||
|
android:layout_marginStart="272dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:backgroundTint="#000000"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.375"
|
||||||
|
app:srcCompat="@android:drawable/ic_menu_info_details" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/locationButtonContainer"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="24dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/attributionButton"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/locationButton"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="47dp"
|
||||||
|
android:backgroundTint="#000000"
|
||||||
|
android:contentDescription="Location"
|
||||||
|
app:srcCompat="@android:drawable/ic_menu_mylocation" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/locationServiceStatusIndicator"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_gravity="center|bottom"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_marginBottom="7dp"
|
||||||
|
android:background="#FB0303"
|
||||||
|
android:textSize="5sp" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
6
app/src/main/res/layout/fragment_map.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
</android.widget.LinearLayout>
|
||||||
27
app/src/main/res/layout/item_generic.xml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/image"
|
||||||
|
android:layout_width="54dp"
|
||||||
|
android:layout_height="47dp"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="Style Image"
|
||||||
|
android:src="@android:drawable/ic_menu_gallery" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="Item Name"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
58
app/src/main/res/layout/item_preview.xml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="#0E0000"
|
||||||
|
android:foregroundTint="#FFFFFF">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/choiceName"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="7dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:text="Choice Item"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:scrollHorizontally="false"
|
||||||
|
android:autoSizeTextType="uniform"
|
||||||
|
android:autoSizeMinTextSize="12sp"
|
||||||
|
android:autoSizeMaxTextSize="24sp"
|
||||||
|
android:autoSizeStepGranularity="1sp"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/poiIcon"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/poiIcon"
|
||||||
|
android:layout_width="55dp"
|
||||||
|
android:layout_height="55dp"
|
||||||
|
android:layout_marginStart="7dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/maplibre_info_bg_selector" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/type"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="7dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:layout_marginBottom="12dp"
|
||||||
|
android:text="Type"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:singleLine="true"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/poiIcon"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/choiceName"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
59
app/src/main/res/layout/popup_map_change.xml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="#000000"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/dragHandle"
|
||||||
|
android:layout_width="170dp"
|
||||||
|
android:layout_height="5dp"
|
||||||
|
android:background="#979797"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/closeButton"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:backgroundTint="#000000"
|
||||||
|
app:srcCompat="@android:drawable/ic_menu_close_clear_cancel"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/stylesLabel"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Styles"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:id="@+id/styles"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/stylesLabel"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/stylesLayout"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal" />
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<!-- Sources selection to be implemented here -->
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
80
app/src/main/res/layout/screen_main.xml
Executable file
@@ -0,0 +1,80 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/constraintLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools" >
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/popupHolder"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/mainContentView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" >
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/bottomUi"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/devIndicator"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="DEVELOPMENT BUILD!"
|
||||||
|
android:textColor="#000000"
|
||||||
|
android:textSize="13sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/searchContainer"
|
||||||
|
android:layout_width="280dp"
|
||||||
|
android:layout_height="33dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:background="#000000"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<SearchView
|
||||||
|
android:id="@+id/searchView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:iconifiedByDefault="false"
|
||||||
|
android:queryHint="Search..."
|
||||||
|
android:background="@android:color/transparent" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/hamburgerButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:contentDescription="Menu"
|
||||||
|
android:src="@drawable/ic_hamburger_menu" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
6
app/src/main/res/layout/screen_settings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
16
app/src/main/res/values-night/themes.xml
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.StrikeMaps" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
|
<!-- Primary brand color. -->
|
||||||
|
<item name="colorPrimary">@color/purple_200</item>
|
||||||
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||||
|
<item name="colorOnPrimary">@color/black</item>
|
||||||
|
<!-- Secondary brand color. -->
|
||||||
|
<item name="colorSecondary">@color/teal_200</item>
|
||||||
|
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||||
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
|
<!-- Status bar color. -->
|
||||||
|
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
10
app/src/main/res/values/colors.xml
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="purple_200">#FFBB86FC</color>
|
||||||
|
<color name="purple_500">#FF6200EE</color>
|
||||||
|
<color name="purple_700">#FF3700B3</color>
|
||||||
|
<color name="teal_200">#FF03DAC5</color>
|
||||||
|
<color name="teal_700">#FF018786</color>
|
||||||
|
<color name="black">#FF000000</color>
|
||||||
|
<color name="white">#FFFFFFFF</color>
|
||||||
|
</resources>
|
||||||
5
app/src/main/res/values/strings.xml
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">Strike Maps</string>
|
||||||
|
<string name="attribution_title"> Attribution </string>
|
||||||
|
<string name="shipped_attribution">Earth map data Included;\n - © OpenStreetMap Contributors\nMap Rendering libraries Included;\n - MapLibre developed by MapLibre Organization\n - Vtm developed by Mapsforge\nStrike Maps made with <3 by konggdev</string>
|
||||||
|
</resources>
|
||||||
16
app/src/main/res/values/themes.xml
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.StrikeMaps" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
|
<!-- Primary brand color. -->
|
||||||
|
<item name="colorPrimary">@color/black</item>
|
||||||
|
<item name="colorPrimaryVariant">@color/black</item>
|
||||||
|
<item name="colorOnPrimary">@color/white</item>
|
||||||
|
<!-- Secondary brand color. -->
|
||||||
|
<item name="colorSecondary">@color/teal_200</item>
|
||||||
|
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||||
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
|
<!-- Status bar color. -->
|
||||||
|
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
13
app/src/main/res/xml/backup_rules.xml
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Sample backup rules file; uncomment and customize as necessary.
|
||||||
|
See https://developer.android.com/guide/topics/data/autobackup
|
||||||
|
for details.
|
||||||
|
Note: This file is ignored for devices older that API 31
|
||||||
|
See https://developer.android.com/about/versions/12/backup-restore
|
||||||
|
-->
|
||||||
|
<full-backup-content>
|
||||||
|
<!--
|
||||||
|
<include domain="sharedpref" path="."/>
|
||||||
|
<exclude domain="sharedpref" path="device.xml"/>
|
||||||
|
-->
|
||||||
|
</full-backup-content>
|
||||||
19
app/src/main/res/xml/data_extraction_rules.xml
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Sample data extraction rules file; uncomment and customize as necessary.
|
||||||
|
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||||
|
for details.
|
||||||
|
-->
|
||||||
|
<data-extraction-rules>
|
||||||
|
<cloud-backup>
|
||||||
|
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||||
|
<include .../>
|
||||||
|
<exclude .../>
|
||||||
|
-->
|
||||||
|
</cloud-backup>
|
||||||
|
<!--
|
||||||
|
<device-transfer>
|
||||||
|
<include .../>
|
||||||
|
<exclude .../>
|
||||||
|
</device-transfer>
|
||||||
|
-->
|
||||||
|
</data-extraction-rules>
|
||||||
17
app/src/test/java/eu/konggdev/strikemaps/ExampleUnitTest.java
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
package eu.konggdev.strikemaps;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
public class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
public void addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
5
build.gradle.kts
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.android.application) apply false
|
||||||
|
alias(libs.plugins.kotlin.android) apply false
|
||||||
|
}
|
||||||
21
gradle.properties
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
# Project-wide Gradle settings.
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. For more details, visit
|
||||||
|
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||||
|
# Android operating system, and which are packaged with your app's APK
|
||||||
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||||
|
android.useAndroidX=true
|
||||||
|
# Enables namespacing of each library's R class so that its R class includes only the
|
||||||
|
# resources declared in the library itself and none from the library's dependencies,
|
||||||
|
# thereby reducing the size of the R class for that library
|
||||||
|
android.nonTransitiveRClass=true
|
||||||
30
gradle/libs.versions.toml
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
[versions]
|
||||||
|
agp = "8.9.1"
|
||||||
|
junit = "4.13.2"
|
||||||
|
junitVersion = "1.1.5"
|
||||||
|
espressoCore = "3.5.1"
|
||||||
|
appcompat = "1.6.1"
|
||||||
|
material = "1.10.0"
|
||||||
|
activity = "1.8.0"
|
||||||
|
constraintlayout = "2.1.4"
|
||||||
|
playServicesMaps = "19.0.0"
|
||||||
|
viewpager2 = "1.1.0"
|
||||||
|
kotlin = "2.3.10"
|
||||||
|
coreKtx = "1.18.0"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
|
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||||
|
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||||
|
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||||
|
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
|
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
||||||
|
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||||
|
play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }
|
||||||
|
viewpager2 = { group = "androidx.viewpager2", name = "viewpager2", version.ref = "viewpager2" }
|
||||||
|
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Executable file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#Wed Feb 19 10:31:32 CET 2025
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
185
gradlew
vendored
Executable file
@@ -0,0 +1,185 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=`expr $i + 1`
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
0) set -- ;;
|
||||||
|
1) set -- "$args0" ;;
|
||||||
|
2) set -- "$args0" "$args1" ;;
|
||||||
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
89
gradlew.bat
vendored
Executable file
@@ -0,0 +1,89 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
19
settings.gradle.kts
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
maven("https://jitpack.io")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.name = "StrikeMaps"
|
||||||
|
include(":app")
|
||||||