Compare commits
8
Commits
master
..
61a1f588c0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61a1f588c0 | ||
|
|
4698f9dcb6 | ||
|
|
549e2e3b67 | ||
|
|
92d685021b | ||
|
|
1e9a421df2 | ||
|
|
b4bc8feec5 | ||
|
|
4a625323d4 | ||
|
|
9c9d74d5e4 |
@@ -9,4 +9,3 @@ DS_Store
|
|||||||
.cxx
|
.cxx
|
||||||
local.properties
|
local.properties
|
||||||
/legacy_code/
|
/legacy_code/
|
||||||
maptiler*
|
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_15
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
targetCompatibility = JavaVersion.VERSION_15
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
@@ -46,8 +46,6 @@ dependencies {
|
|||||||
implementation(libs.constraintlayout)
|
implementation(libs.constraintlayout)
|
||||||
implementation(libs.viewpager2)
|
implementation(libs.viewpager2)
|
||||||
|
|
||||||
implementation("androidx.core:core-ktx:1.17.0")
|
|
||||||
implementation("org.osmdroid:osmdroid-android:6.1.20")
|
|
||||||
implementation("org.maplibre.gl:android-sdk:11.13.0")
|
implementation("org.maplibre.gl:android-sdk:11.13.0")
|
||||||
implementation("com.github.mapsforge.vtm:vtm:0.27.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-android:0.27.0")
|
||||||
@@ -62,6 +60,7 @@ dependencies {
|
|||||||
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.0")
|
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.0")
|
||||||
implementation("org.apache.commons:commons-lang3:3.14.0")
|
implementation("org.apache.commons:commons-lang3:3.14.0")
|
||||||
|
implementation(libs.core.ktx)
|
||||||
|
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.ext.junit)
|
androidTestImplementation(libs.ext.junit)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
"sources": {
|
"sources": {
|
||||||
"satelite": {
|
"satelite": {
|
||||||
"type": "raster",
|
"type": "raster",
|
||||||
"schema" : "raster",
|
|
||||||
"tiles": [
|
"tiles": [
|
||||||
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
|
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
|
||||||
],
|
],
|
||||||
@@ -15,6 +14,8 @@
|
|||||||
"tileSize": 512
|
"tileSize": 512
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sprite": "",
|
||||||
|
"glyphs": "https://orangemug.github.io/font-glyphs/glyphs/{fontstack}/{range}.pbf",
|
||||||
"layers": [
|
"layers": [
|
||||||
{
|
{
|
||||||
"id": "satelite",
|
"id": "satelite",
|
||||||
|
|||||||
@@ -1,126 +0,0 @@
|
|||||||
#
|
|
||||||
Builds included inside /dist correspond to MapLibre GL JS version 5.24.0 <br>
|
|
||||||
The source for these builds is available on https://github.com/maplibre/maplibre-gl-js
|
|
||||||
#
|
|
||||||
|
|
||||||
All files inside the /dist folder are under the following license
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
Copyright (c) 2023, MapLibre contributors
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of MapLibre GL JS nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Contains code from mapbox-gl-js v1.13 and earlier
|
|
||||||
|
|
||||||
Version v1.13 of mapbox-gl-js and earlier are licensed under a BSD-3-Clause license
|
|
||||||
|
|
||||||
Copyright (c) 2020, Mapbox
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of Mapbox GL JS nor the names of its contributors
|
|
||||||
may be used to endorse or promote products derived from this software
|
|
||||||
without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
||||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Contains code from glfx.js
|
|
||||||
|
|
||||||
Copyright (C) 2011 by Evan Wallace
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
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 OR COPYRIGHT HOLDERS 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.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Contains a portion of d3-color https://github.com/d3/d3-color
|
|
||||||
|
|
||||||
Copyright 2010-2016 Mike Bostock
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
* Neither the name of the author nor the names of contributors may be used to
|
|
||||||
endorse or promote products derived from this software without specific prior
|
|
||||||
written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,29 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<script src="dist/maplibre-gl.js"></script>
|
|
||||||
<link href="dist/maplibre-gl.css" rel="stylesheet"/>
|
|
||||||
<style>
|
|
||||||
html, body, #map {
|
|
||||||
margin: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div id="map" style="width: 100%; height: 100%"></div>
|
|
||||||
<script>
|
|
||||||
const map = new maplibregl.Map({
|
|
||||||
center: [13.388, 52.517],
|
|
||||||
zoom: 9.5,
|
|
||||||
container: 'map',
|
|
||||||
attributionControl: false
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -18,7 +18,6 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
app = new AppController(this);
|
app = new AppController(this);
|
||||||
setContentView(R.layout.view_main);
|
|
||||||
app.init();
|
app.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,10 +28,4 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
public void logcat(String log) {
|
public void logcat(String log) {
|
||||||
Log.i("LogcatGeneric", log);
|
Log.i("LogcatGeneric", log);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed() {
|
|
||||||
if (!app.getUi().back())
|
|
||||||
super.onBackPressed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import eu.konggdev.strikemaps.MainActivity;
|
|||||||
import eu.konggdev.strikemaps.R;
|
import eu.konggdev.strikemaps.R;
|
||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
import eu.konggdev.strikemaps.ui.UIComponent;
|
import eu.konggdev.strikemaps.ui.UIComponent;
|
||||||
import eu.konggdev.strikemaps.ui.screen.definition.DefinedScreen;
|
|
||||||
|
|
||||||
import static android.content.Context.MODE_PRIVATE;
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
public class AppController {
|
public class AppController {
|
||||||
@@ -35,11 +34,12 @@ public class AppController {
|
|||||||
public AppCompatActivity getActivity() { return appActivity; }
|
public AppCompatActivity getActivity() { return appActivity; }
|
||||||
public void init() {
|
public void init() {
|
||||||
if (getActivity().getSupportActionBar() != null)
|
if (getActivity().getSupportActionBar() != null)
|
||||||
getActivity().getSupportActionBar().show();
|
getActivity().getSupportActionBar().hide();
|
||||||
|
|
||||||
if(map == null) map = new MapComponent(this);
|
if(map == null) map = new MapComponent(this);
|
||||||
if(ui == null) {
|
if(ui == null) {
|
||||||
ui = new UIComponent(this, map);
|
ui = new UIComponent(this, map);
|
||||||
ui.swapScreen(DefinedScreen.MAIN); //Initial
|
ui.swapScreen(R.layout.screen_main); //Initial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.app.util;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
public final class JsonPatcher {
|
|
||||||
//Takes a json and a patch and applies it
|
|
||||||
public static JsonNode patch(JsonNode current, JsonNode patch) throws Exception {
|
|
||||||
if (current.isObject()) {
|
|
||||||
ObjectNode result = current.deepCopy();
|
|
||||||
|
|
||||||
patch.fields().forEachRemaining(entry -> { //For each
|
|
||||||
String key = entry.getKey();
|
|
||||||
JsonNode patchValue = entry.getValue();
|
|
||||||
if(!result.has(key)) { //Not at all in current
|
|
||||||
result.set(key, patchValue); //Just append it to result
|
|
||||||
} else if (result.has(key) && !patchValue.isEmpty()) { //Deeper depth possible
|
|
||||||
try {
|
|
||||||
result.set(key, patch(result.get(key), patchValue)); //Patch iteration with patch's value (traverse deeper)
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
} else if (result.has(key) && patchValue.isEmpty() && result.get(key).isEmpty()) { //Max depth match
|
|
||||||
result.set(key, patchValue); //Replace with patch's value
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current.isArray()) {
|
|
||||||
ArrayNode result = current.deepCopy();
|
|
||||||
for (JsonNode entry : patch) {
|
|
||||||
if (StreamSupport.stream(result.spliterator(), false)
|
|
||||||
.noneMatch(node -> node.equals(entry))) { //If no exact entry, add entry (prevents duplicates)
|
|
||||||
result.add(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Takes an original json, a patched json and a patch and removes that specific patch's changes from it
|
|
||||||
public static JsonNode unpatch(JsonNode original, JsonNode current, JsonNode patch) throws Exception {
|
|
||||||
if (current.isObject()) {
|
|
||||||
ObjectNode result = current.deepCopy(); //Current contains the patch, deepcopy it and operate on the copy
|
|
||||||
|
|
||||||
current.fields().forEachRemaining(entry -> {
|
|
||||||
String key = entry.getKey();
|
|
||||||
JsonNode value = entry.getValue();
|
|
||||||
|
|
||||||
if (!original.has(key) && patch.has(key)) { //Value is in patch and current but was not at all in the original
|
|
||||||
result.remove(key); //Just remove the value
|
|
||||||
} else if (!value.isEmpty() && patch.has(key)) { //Depper depth possible
|
|
||||||
try {
|
|
||||||
result.set(key, unpatch(original.get(key), result.get(key), patch.get(key))); //Replace with further unpatch of deeper level
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
} else if (value.isEmpty() && patch.has(key)) { //Max depth match
|
|
||||||
result.set(key, original.get(key)); //Replace with original unpatched value
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current.isArray()) {
|
|
||||||
ArrayNode result = current.deepCopy();
|
|
||||||
for (int i = 0; i < result.size(); i++) {
|
|
||||||
JsonNode entry = result.get(i);
|
|
||||||
if (StreamSupport.stream(original.spliterator(), false)
|
|
||||||
.noneMatch(on -> on.equals(entry)) //If not in original
|
|
||||||
&&
|
|
||||||
StreamSupport.stream(patch.spliterator(), false)
|
|
||||||
.noneMatch(rn -> rn.equals(entry))) { //But also in patch
|
|
||||||
|
|
||||||
result.remove(i); //Remove from result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -26,6 +26,7 @@ public final class FileHelper {
|
|||||||
|
|
||||||
public static String loadStringFromUserFile(String filePath) {
|
public static String loadStringFromUserFile(String filePath) {
|
||||||
File file = new File(filePath);
|
File file = new File(filePath);
|
||||||
|
|
||||||
try (FileInputStream fis = new FileInputStream(file)) {
|
try (FileInputStream fis = new FileInputStream(file)) {
|
||||||
int size = fis.available();
|
int size = fis.available();
|
||||||
byte[] buffer = new byte[size];
|
byte[] buffer = new byte[size];
|
||||||
@@ -37,39 +38,6 @@ public final class FileHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writeUserFile(String path, String fileName, String content, AppController app) throws IOException {
|
|
||||||
try {
|
|
||||||
File userDirectory = new File(app.getActivity().getExternalFilesDir(null), path);
|
|
||||||
|
|
||||||
if (!userDirectory.exists() && !userDirectory.mkdirs()) {
|
|
||||||
app.logcat("Failed to create directory: " + userDirectory.getAbsolutePath());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
File file = new File(userDirectory, fileName);
|
|
||||||
|
|
||||||
try (FileOutputStream fos = new FileOutputStream(file);
|
|
||||||
OutputStreamWriter writer = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {
|
|
||||||
|
|
||||||
writer.write(content);
|
|
||||||
writer.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean deleteFile(String filePath) {
|
|
||||||
File file = new File(filePath);
|
|
||||||
|
|
||||||
if (!file.exists() || !file.isFile()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return file.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String[] getAssetFiles(String path, String fileExt, AppController app) {
|
public static String[] getAssetFiles(String path, String fileExt, AppController app) {
|
||||||
AssetManager assetManager = app.getActivity().getAssets();
|
AssetManager assetManager = app.getActivity().getAssets();
|
||||||
try {
|
try {
|
||||||
@@ -109,20 +77,9 @@ public final class FileHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean userFileExists(String path, String fileName, AppController app) {
|
|
||||||
File userDirectory = new File(app.getActivity().getExternalFilesDir(null), path);
|
|
||||||
|
|
||||||
if (!userDirectory.exists() || !userDirectory.isDirectory()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
File file = new File(userDirectory, fileName);
|
|
||||||
|
|
||||||
return file.exists() && file.isFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String[] getUserFiles(String path, String fileExt, AppController app) {
|
public static String[] getUserFiles(String path, String fileExt, AppController app) {
|
||||||
File userDirectory = new File(app.getActivity().getExternalFilesDir(null), path);
|
String packageName = app.getActivity().getPackageName();
|
||||||
|
File userDirectory = new File(Environment.getExternalStorageDirectory(), "Android/data/" + packageName + "/" + path);
|
||||||
|
|
||||||
if (!userDirectory.exists() || !userDirectory.isDirectory())
|
if (!userDirectory.exists() || !userDirectory.isDirectory())
|
||||||
return new String[0];
|
return new String[0];
|
||||||
|
|||||||
@@ -13,24 +13,17 @@ public final class UserPrefsHelper {
|
|||||||
|
|
||||||
//Defaults
|
//Defaults
|
||||||
private static final String DEFAULT_MAP_STYLE = "bundled/style/classic.style.json";
|
private static final String DEFAULT_MAP_STYLE = "bundled/style/classic.style.json";
|
||||||
private static final Integer DEFAULT_MAP_RENDERER = 0;
|
private static final String DEFAULT_MAP_RENDERER = "mapLibre";
|
||||||
private static final boolean DEFAULT_PERSIST_LOCATION_ENABLED = true;
|
private static final boolean DEFAULT_PERSIST_LOCATION_ENABLED = true;
|
||||||
private static final boolean DEFAULT_LAST_LOCATION_ENABLED = false;
|
private static final boolean DEFAULT_LAST_LOCATION_ENABLED = false;
|
||||||
|
|
||||||
|
|
||||||
public static String startupMapStyle(SharedPreferences prefs) {
|
public static String startupMapStyle(SharedPreferences prefs) {
|
||||||
return prefs.getString(KEY_STARTUP_MAP_STYLE, DEFAULT_MAP_STYLE);
|
return prefs.getString(KEY_STARTUP_MAP_STYLE, DEFAULT_MAP_STYLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean startupMapStyle(SharedPreferences prefs, String updated) {
|
public static String mapRenderer(SharedPreferences prefs) {
|
||||||
return prefs.edit().putString(KEY_STARTUP_MAP_STYLE, updated).commit();
|
return prefs.getString(KEY_MAP_RENDERER, DEFAULT_MAP_RENDERER);
|
||||||
}
|
|
||||||
|
|
||||||
public static Integer mapRenderer(SharedPreferences prefs) {
|
|
||||||
return prefs.getInt(KEY_MAP_RENDERER, DEFAULT_MAP_RENDERER);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean mapRenderer(SharedPreferences prefs, Integer updated) {
|
|
||||||
return prefs.edit().putInt(KEY_MAP_RENDERER, updated).commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean persistLocationEnabled(SharedPreferences prefs) {
|
public static boolean persistLocationEnabled(SharedPreferences prefs) {
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
package eu.konggdev.strikemaps.map;
|
package eu.konggdev.strikemaps.map;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import android.widget.Toast;
|
|
||||||
import eu.konggdev.strikemaps.Component;
|
import eu.konggdev.strikemaps.Component;
|
||||||
import eu.konggdev.strikemaps.map.renderer.implementation.MapLibreGLJSRenderer;
|
|
||||||
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
|
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
|
||||||
import eu.konggdev.strikemaps.data.helper.UserPrefsHelper;
|
import eu.konggdev.strikemaps.data.helper.UserPrefsHelper;
|
||||||
import eu.konggdev.strikemaps.map.renderer.implementation.VtmRenderer;
|
import eu.konggdev.strikemaps.map.renderer.implementation.VtmRenderer;
|
||||||
@@ -18,28 +15,21 @@ import eu.konggdev.strikemaps.map.renderer.implementation.MapLibreNativeRenderer
|
|||||||
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
||||||
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentMap;
|
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentMap;
|
||||||
|
|
||||||
public class MapComponent implements Component {
|
public class MapComponent implements Component {
|
||||||
MapRenderer mapRenderer;
|
MapRenderer mapRenderer;
|
||||||
AppController app;
|
AppController app;
|
||||||
|
|
||||||
public MapStyle style;
|
public MapStyle style;
|
||||||
public Map<Class<? extends MapOverlay>, MapOverlay> overlays = new HashMap<>();
|
public Map<Class<? extends MapOverlay>, MapOverlay> overlays = new HashMap<>();
|
||||||
|
|
||||||
public MapComponent(AppController ref) {
|
public MapComponent(AppController ref) {
|
||||||
this.app = ref;
|
this.app = ref;
|
||||||
switch(UserPrefsHelper.mapRenderer(app.getPrefs())) {
|
switch(UserPrefsHelper.mapRenderer(app.getPrefs())) {
|
||||||
case 0:
|
case "vtm":
|
||||||
this.mapRenderer = new MapLibreGLJSRenderer(app, this);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
this.mapRenderer = new MapLibreNativeRenderer(app, this);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
this.mapRenderer = new VtmRenderer(app, this);
|
this.mapRenderer = new VtmRenderer(app, this);
|
||||||
break;
|
break;
|
||||||
|
case "mapLibre":
|
||||||
default: //This shouldn't happen
|
default: //This shouldn't happen
|
||||||
Toast.makeText(app.getActivity(), "Invalid renderer value in preferences\nFalling back to MapLibre GL JS", Toast.LENGTH_SHORT).show();
|
this.mapRenderer = new MapLibreNativeRenderer(app, this);
|
||||||
this.mapRenderer = new MapLibreGLJSRenderer(app, this);
|
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -50,13 +40,13 @@ public class MapComponent implements Component {
|
|||||||
|
|
||||||
public void setStyle(MapStyle style) {
|
public void setStyle(MapStyle style) {
|
||||||
this.style = style;
|
this.style = style;
|
||||||
mapRenderer.styleUpdate(style);
|
mapRenderer.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void switchOverlay(MapOverlay overlay) {
|
public void switchOverlay(MapOverlay overlay) {
|
||||||
if (hasOverlay(overlay)) overlays.remove(overlay.getClass());
|
if (hasOverlay(overlay)) overlays.remove(overlay.getClass());
|
||||||
else overlays.put(overlay.getClass(), overlay);
|
else overlays.put(overlay.getClass(), overlay);
|
||||||
overlayUpdate(overlay);
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasOverlay(MapOverlay overlay) {
|
public boolean hasOverlay(MapOverlay overlay) {
|
||||||
@@ -71,8 +61,12 @@ public class MapComponent implements Component {
|
|||||||
//FIXME: Put back FragmentPointPreviewPopup (private code atm)
|
//FIXME: Put back FragmentPointPreviewPopup (private code atm)
|
||||||
}
|
}
|
||||||
|
|
||||||
public void overlayUpdate(MapOverlay in) {
|
public void onOverlayUpdate() {
|
||||||
mapRenderer.overlayUpdate(in);
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
if(mapRenderer != null && style != null) mapRenderer.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onMapClick(LatLng point) {
|
public boolean onMapClick(LatLng point) {
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package eu.konggdev.strikemaps.map.layer;
|
||||||
|
|
||||||
|
import org.maplibre.android.style.layers.Layer;
|
||||||
|
import org.maplibre.android.style.sources.GeoJsonSource;
|
||||||
|
|
||||||
|
|
||||||
|
//FIXME: Get rid of reliance on MapLibre!
|
||||||
|
//Most likely implement an "AdditionalMapLayer" or something of that sorts (?)
|
||||||
|
public class MapLayer {
|
||||||
|
public GeoJsonSource source;
|
||||||
|
public Layer layer;
|
||||||
|
public MapLayer(GeoJsonSource source, Layer layer) {
|
||||||
|
this.source = source;
|
||||||
|
this.layer = layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.map.offline;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
public final class OfflineTileResolver {
|
|
||||||
public byte[] resolve(String url) throws IOException {
|
|
||||||
|
|
||||||
//byte[] data = getOfflineTile();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.map.offline.download;
|
|
||||||
|
|
||||||
import eu.konggdev.strikemaps.map.source.MapSource;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
public final class OfflineDownloader {
|
|
||||||
|
|
||||||
public static String[] fetchAvailableExports(MapSource source) {
|
|
||||||
URI uri = URI.create(source.url);
|
|
||||||
String host = uri.getHost();
|
|
||||||
return new String[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void download(MapSource source, String export) {
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void download(MapSource source, int[] bounds) {
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package eu.konggdev.strikemaps.map.overlay;
|
package eu.konggdev.strikemaps.map.overlay;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import eu.konggdev.strikemaps.map.layer.MapLayer;
|
||||||
|
|
||||||
/* More or less a data-driven layer factory */
|
/* More or less a data-driven layer factory */
|
||||||
public interface MapOverlay {
|
public interface MapOverlay {
|
||||||
public JsonNode makePatch();
|
public MapLayer makeLayer();
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-55
@@ -1,19 +1,23 @@
|
|||||||
package eu.konggdev.strikemaps.map.overlay.implementation;
|
package eu.konggdev.strikemaps.map.overlay.implementation;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.location.LocationListener;
|
import android.location.LocationListener;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
|
import eu.konggdev.strikemaps.map.layer.MapLayer;
|
||||||
|
|
||||||
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
||||||
import eu.konggdev.strikemaps.map.source.MapSource;
|
|
||||||
|
|
||||||
import eu.konggdev.strikemaps.data.provider.LocationDataProvider;
|
import eu.konggdev.strikemaps.data.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 com.fasterxml.jackson.databind.ObjectMapper;
|
import static org.maplibre.android.style.layers.PropertyFactory.*;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
||||||
|
|
||||||
public class LocationOverlay implements MapOverlay, LocationListener {
|
public class LocationOverlay implements MapOverlay, LocationListener {
|
||||||
LocationDataProvider locationDataProvider;
|
LocationDataProvider locationDataProvider;
|
||||||
@@ -28,61 +32,31 @@ public class LocationOverlay implements MapOverlay, LocationListener {
|
|||||||
this.locationDataProvider = new LocationDataProvider(app.getActivity(), this);
|
this.locationDataProvider = new LocationDataProvider(app.getActivity(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonNode makePatch() {
|
public MapLayer makeLayer() {
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
GeoJsonSource source = new GeoJsonSource(
|
||||||
|
"location",
|
||||||
|
FeatureCollection.fromFeatures(new Feature[]{}) // empty
|
||||||
|
);
|
||||||
|
|
||||||
ObjectNode root = mapper.createObjectNode();
|
if (currentLocation != null)
|
||||||
|
source.setGeoJson(Feature.fromGeometry(Point.fromLngLat(currentLocation.getLongitude(), currentLocation.getLatitude())));
|
||||||
|
|
||||||
ObjectNode sources = mapper.createObjectNode();
|
CircleLayer layer = new CircleLayer("location", "location");
|
||||||
ObjectNode location = mapper.createObjectNode();
|
layer.setProperties(
|
||||||
ObjectNode data = mapper.createObjectNode();
|
circleRadius(5f),
|
||||||
ObjectNode geometry = mapper.createObjectNode();
|
circleColor(Color.parseColor("#1E88E5")),
|
||||||
ObjectNode properties = mapper.createObjectNode();
|
circleStrokeColor(Color.WHITE),
|
||||||
|
circleStrokeWidth(1.5f),
|
||||||
|
circlePitchAlignment(Property.CIRCLE_PITCH_ALIGNMENT_MAP)
|
||||||
|
);
|
||||||
|
|
||||||
ArrayNode coordinates = mapper.createArrayNode();
|
return new MapLayer(source, layer);
|
||||||
coordinates.add(currentLocation.getLongitude());
|
}
|
||||||
coordinates.add(currentLocation.getLatitude());
|
|
||||||
|
|
||||||
geometry.put("type", "Point");
|
|
||||||
geometry.set("coordinates", coordinates);
|
|
||||||
|
|
||||||
data.put("type", "Feature");
|
|
||||||
data.set("geometry", geometry);
|
|
||||||
data.set("properties", properties);
|
|
||||||
|
|
||||||
location.put("type", "geojson");
|
|
||||||
location.set("data", data);
|
|
||||||
|
|
||||||
sources.set("location", location);
|
|
||||||
root.set("sources", sources);
|
|
||||||
|
|
||||||
// layers
|
|
||||||
ArrayNode layers = mapper.createArrayNode();
|
|
||||||
ObjectNode layer = mapper.createObjectNode();
|
|
||||||
|
|
||||||
layer.put("id", "location");
|
|
||||||
layer.put("type", "circle");
|
|
||||||
layer.put("source", "location");
|
|
||||||
|
|
||||||
ObjectNode paint = mapper.createObjectNode();
|
|
||||||
paint.put("circle-radius", 5);
|
|
||||||
paint.put("circle-color", "#1E88E5");
|
|
||||||
|
|
||||||
paint.put("circle-stroke-color", "#FFFFFF");
|
|
||||||
paint.put("circle-stroke-width", 1.5);
|
|
||||||
|
|
||||||
layer.set("paint", paint);
|
|
||||||
|
|
||||||
layers.add(layer);
|
|
||||||
root.set("layers", layers);
|
|
||||||
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChanged(@NonNull Location location) {
|
public void onLocationChanged(@NonNull Location location) {
|
||||||
this.currentLocation = location;
|
this.currentLocation = location;
|
||||||
map.overlayUpdate(this);
|
map.onOverlayUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-6
@@ -1,15 +1,11 @@
|
|||||||
package eu.konggdev.strikemaps.map.overlay.implementation;
|
package eu.konggdev.strikemaps.map.overlay.implementation;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import eu.konggdev.strikemaps.map.layer.MapLayer;
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
|
||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
|
||||||
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
||||||
|
|
||||||
public class PointSelectionOverlay implements MapOverlay {
|
public class PointSelectionOverlay implements MapOverlay {
|
||||||
AppController app;
|
|
||||||
MapComponent map;
|
|
||||||
@Override
|
@Override
|
||||||
public JsonNode makePatch() {
|
public MapLayer makeLayer() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
package eu.konggdev.strikemaps.map.renderer;
|
package eu.konggdev.strikemaps.map.renderer;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
import eu.konggdev.strikemaps.map.layer.MapLayer;
|
||||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
import org.maplibre.android.style.layers.Layer;
|
||||||
import org.maplibre.android.geometry.LatLng;
|
import org.maplibre.android.geometry.LatLng;
|
||||||
import org.maplibre.geojson.Feature;
|
import org.maplibre.geojson.Feature;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface MapRenderer {
|
public interface MapRenderer {
|
||||||
void styleUpdate(MapStyle style);
|
void reload();
|
||||||
|
|
||||||
void overlayUpdate(MapOverlay overlay);
|
|
||||||
|
|
||||||
View getView();
|
View getView();
|
||||||
|
|
||||||
//TODO: Get rid of MapLibre Feature class dependence
|
|
||||||
List<Feature> featuresAtPoint(LatLng point);
|
List<Feature> featuresAtPoint(LatLng point);
|
||||||
}
|
}
|
||||||
|
|||||||
-149
@@ -1,149 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.map.renderer.implementation;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.webkit.ValueCallback;
|
|
||||||
import android.webkit.WebChromeClient;
|
|
||||||
import android.webkit.WebSettings;
|
|
||||||
import android.webkit.WebView;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
|
||||||
import eu.konggdev.strikemaps.app.util.JsonPatcher;
|
|
||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
|
||||||
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
|
||||||
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
|
||||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
|
||||||
import org.maplibre.android.geometry.LatLng;
|
|
||||||
import org.maplibre.android.maps.Style;
|
|
||||||
import org.maplibre.geojson.Feature;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
//Stub for now
|
|
||||||
public class MapLibreGLJSRenderer implements MapRenderer {
|
|
||||||
@NonNull AppController app;
|
|
||||||
|
|
||||||
@NonNull MapComponent controller;
|
|
||||||
|
|
||||||
final WebView webView;
|
|
||||||
|
|
||||||
private JsonNode origin;
|
|
||||||
|
|
||||||
@SuppressLint({"JavascriptInterface", "SetJavaScriptEnabled"})
|
|
||||||
public MapLibreGLJSRenderer(AppController app, MapComponent controller) {
|
|
||||||
this.app = app;
|
|
||||||
this.controller = controller;
|
|
||||||
webView = new WebView(app.getActivity());
|
|
||||||
webView.setLayoutParams(
|
|
||||||
new ViewGroup.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
WebSettings settings = webView.getSettings();
|
|
||||||
settings.setJavaScriptEnabled(true);
|
|
||||||
settings.setDomStorageEnabled(true);
|
|
||||||
settings.setAllowFileAccess(true);
|
|
||||||
|
|
||||||
webView.setWebChromeClient(new WebChromeClient());
|
|
||||||
|
|
||||||
webView.addJavascriptInterface(new Bridge(), "AndroidBridge");
|
|
||||||
|
|
||||||
webView.loadUrl("file:///android_asset/library/maplibre/gl-js/index.html");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void styleUpdate(MapStyle style) {
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
|
||||||
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
|
|
||||||
|
|
||||||
//Thanks to this, styleUpdate(null) can be used as an origin reload
|
|
||||||
if (style != null) {
|
|
||||||
try {
|
|
||||||
ObjectNode root = style.metadata.deepCopy();
|
|
||||||
|
|
||||||
//Sources
|
|
||||||
ObjectNode sources = mapper.createObjectNode();
|
|
||||||
if (style.sources != null)
|
|
||||||
style.sources.forEach((k, v) -> sources.set(k, mapper.valueToTree(v)));
|
|
||||||
|
|
||||||
//Layers
|
|
||||||
ArrayNode layers = mapper.createArrayNode();
|
|
||||||
if (style.layerDefinitions != null)
|
|
||||||
layers.addAll((ArrayNode) style.layerDefinitions);
|
|
||||||
|
|
||||||
//Set all to root
|
|
||||||
root.set("sources", sources);
|
|
||||||
root.set("layers", layers);
|
|
||||||
this.origin = root;
|
|
||||||
} catch (Exception e) {
|
|
||||||
app.logcat("Failed to parse style: " + style.name);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
final String mapped = mapper.writeValueAsString(origin);
|
|
||||||
webView.evaluateJavascript("map.setStyle(" + mapped + ", { diff: false });", null);
|
|
||||||
webView.evaluateJavascript("map.redraw()", null); //Force redraw to make the style change visible
|
|
||||||
} catch (Exception e) {
|
|
||||||
app.logcat("Failed to set style: " + style.name);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Since we just annihilated all overlays from the face of the earth, lets repatch them
|
|
||||||
if (controller.overlays != null) {
|
|
||||||
for(MapOverlay overlay : controller.overlays.values())
|
|
||||||
overlayUpdate(overlay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void overlayUpdate(MapOverlay overlay) {
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
|
||||||
webView.evaluateJavascript(
|
|
||||||
"JSON.stringify(map.getStyle())",
|
|
||||||
style -> {
|
|
||||||
try {
|
|
||||||
JsonNode current = mapper.readTree(style);
|
|
||||||
|
|
||||||
JsonNode merged;
|
|
||||||
if (controller.hasOverlay(overlay)) {
|
|
||||||
merged = JsonPatcher.patch(current, overlay.makePatch());
|
|
||||||
} else {
|
|
||||||
merged = JsonPatcher.unpatch(origin, current, overlay.makePatch());
|
|
||||||
}
|
|
||||||
|
|
||||||
final String mapped = mapper.writeValueAsString(merged);
|
|
||||||
webView.evaluateJavascript("map.setStyle(" + mapped + ", { diff: false });", null);
|
|
||||||
webView.evaluateJavascript("map.redraw()", null); //Force redraw to make the style change visible
|
|
||||||
} catch (Exception e) {
|
|
||||||
app.logcat("Failed to patch overlay: " + overlay.toString());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView() {
|
|
||||||
return webView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Feature> featuresAtPoint(LatLng point) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
class Bridge { }
|
|
||||||
}
|
|
||||||
+17
-69
@@ -4,14 +4,11 @@ import android.view.View;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
||||||
import eu.konggdev.strikemaps.app.util.JsonPatcher;
|
|
||||||
import eu.konggdev.strikemaps.data.helper.UserPrefsHelper;
|
import eu.konggdev.strikemaps.data.helper.UserPrefsHelper;
|
||||||
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
||||||
|
import eu.konggdev.strikemaps.map.layer.MapLayer;
|
||||||
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
||||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
import eu.konggdev.strikemaps.map.style.MapStyle;
|
||||||
import org.maplibre.android.MapLibre;
|
import org.maplibre.android.MapLibre;
|
||||||
@@ -28,13 +25,11 @@ import eu.konggdev.strikemaps.app.AppController;
|
|||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
|
|
||||||
public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
|
public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
|
||||||
@NonNull AppController app;
|
AppController app;
|
||||||
@NonNull MapComponent controller;
|
MapComponent controller;
|
||||||
MapLibreMap map;
|
MapLibreMap map;
|
||||||
final MapView mapView;
|
final MapView mapView;
|
||||||
|
|
||||||
private JsonNode origin;
|
|
||||||
|
|
||||||
public MapLibreNativeRenderer(AppController app, MapComponent controller) {
|
public MapLibreNativeRenderer(AppController app, MapComponent controller) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
@@ -44,72 +39,25 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
|
|||||||
mapView.getMapAsync(this);
|
mapView.getMapAsync(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void passLayer(MapLayer layer) {
|
||||||
public void styleUpdate(MapStyle style) {
|
map.getStyle().addSource(layer.source);
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
map.getStyle().addLayer(layer.layer);
|
||||||
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
|
|
||||||
|
|
||||||
//Thanks to this, styleUpdate(null) can be used as an origin reload
|
|
||||||
if (style != null) {
|
|
||||||
try {
|
|
||||||
ObjectNode root = style.metadata.deepCopy();
|
|
||||||
|
|
||||||
//Sources
|
|
||||||
ObjectNode sources = mapper.createObjectNode();
|
|
||||||
if (style.sources != null)
|
|
||||||
style.sources.forEach((k, v) -> sources.set(k, mapper.valueToTree(v)));
|
|
||||||
|
|
||||||
//Layers
|
|
||||||
ArrayNode layers = mapper.createArrayNode();
|
|
||||||
if (style.layerDefinitions != null)
|
|
||||||
layers.addAll((ArrayNode) style.layerDefinitions);
|
|
||||||
|
|
||||||
//Set all to root
|
|
||||||
root.set("sources", sources);
|
|
||||||
root.set("layers", layers);
|
|
||||||
this.origin = root;
|
|
||||||
} catch (Exception e) {
|
|
||||||
app.logcat("Failed to parse style: " + style.name);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
map.setStyle(new Style.Builder().fromJson(mapper.writeValueAsString(origin)));
|
|
||||||
} catch (Exception e) {
|
|
||||||
app.logcat("Failed to set style: " + style.name);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Since we just annihilated all overlays from the face of the earth, lets repatch them
|
|
||||||
if (controller.overlays != null) {
|
|
||||||
for(MapOverlay overlay : controller.overlays.values())
|
|
||||||
overlayUpdate(overlay);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void overlayUpdate(MapOverlay overlay) {
|
public void reload() {
|
||||||
if(map == null) return;
|
|
||||||
|
|
||||||
Style style = map.getStyle();
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
MapStyle style = controller.style;
|
||||||
if(style == null) return;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JsonNode current = mapper.readTree(style.getJson());
|
ObjectNode root = style.metadata.deepCopy();
|
||||||
|
root.set("sources", mapper.valueToTree(style.sources));
|
||||||
JsonNode merged;
|
root.set("layers", style.layerDefinitions);
|
||||||
if (controller.hasOverlay(overlay)) {
|
map.setStyle(new Style.Builder().fromJson(mapper.writeValueAsString(root)), intStyle -> {
|
||||||
merged = JsonPatcher.patch(current, overlay.makePatch());
|
for(MapOverlay overlay : controller.overlays.values()) {
|
||||||
} else {
|
passLayer(overlay.makeLayer());
|
||||||
merged = JsonPatcher.unpatch(origin, current, overlay.makePatch());
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
map.setStyle(new Style.Builder().fromJson(mapper.writeValueAsString(merged)));
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
app.logcat("Failed to patch overlay: " + overlay.toString());
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,7 +76,7 @@ public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
|
|||||||
public void onMapReady(@NonNull MapLibreMap maplibreMap) {
|
public void onMapReady(@NonNull MapLibreMap maplibreMap) {
|
||||||
this.map = maplibreMap;
|
this.map = maplibreMap;
|
||||||
|
|
||||||
controller.setStyle(MapStyle.fromFile(UserPrefsHelper.startupMapStyle(app.getPrefs()), app));
|
controller.setStyle(MapStyle.fromMapLibreJsonFile(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 :)
|
//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().setLogoEnabled(false);
|
||||||
|
|||||||
+1
-9
@@ -3,9 +3,7 @@ package eu.konggdev.strikemaps.map.renderer.implementation;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
|
|
||||||
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
|
||||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import org.maplibre.android.geometry.LatLng;
|
import org.maplibre.android.geometry.LatLng;
|
||||||
import org.maplibre.geojson.Feature;
|
import org.maplibre.geojson.Feature;
|
||||||
@@ -18,7 +16,6 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class VtmRenderer implements MapRenderer {
|
public class VtmRenderer implements MapRenderer {
|
||||||
|
|
||||||
AppController app;
|
AppController app;
|
||||||
MapComponent controller;
|
MapComponent controller;
|
||||||
|
|
||||||
@@ -33,12 +30,7 @@ public class VtmRenderer implements MapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void overlayUpdate(MapOverlay overlay) {
|
public void reload() {
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void styleUpdate(MapStyle style) {
|
|
||||||
//TODO
|
//TODO
|
||||||
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||||
OSciMap4TileSource tileSource = OSciMap4TileSource.builder().httpFactory(new OkHttpEngine.OkHttpFactory(builder)).build();
|
OSciMap4TileSource tileSource = OSciMap4TileSource.builder().httpFactory(new OkHttpEngine.OkHttpFactory(builder)).build();
|
||||||
|
|||||||
@@ -4,18 +4,15 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||||||
|
|
||||||
public class MapSource {
|
public class MapSource {
|
||||||
public String url;
|
public String url;
|
||||||
public JsonNode data;
|
|
||||||
public String type;
|
public String type;
|
||||||
public String schema;
|
public String schema;
|
||||||
|
|
||||||
|
public String attribution;
|
||||||
|
|
||||||
|
/* For raster sources */
|
||||||
public JsonNode tiles;
|
public JsonNode tiles;
|
||||||
public int minzoom;
|
public int minzoom;
|
||||||
public int maxzoom;
|
public int maxzoom;
|
||||||
public String scheme;
|
|
||||||
public int tileSize;
|
|
||||||
|
|
||||||
public String attribution;
|
|
||||||
|
|
||||||
public String encoding;
|
|
||||||
public MapSource() { }
|
public MapSource() { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
import eu.konggdev.strikemaps.data.helper.FileHelper;
|
import eu.konggdev.strikemaps.data.helper.FileHelper;
|
||||||
import eu.konggdev.strikemaps.map.source.MapSource;
|
import eu.konggdev.strikemaps.map.source.MapSource;
|
||||||
@@ -20,10 +19,10 @@ public class MapStyle {
|
|||||||
|
|
||||||
public JsonNode metadata; // everything except layers + sources
|
public JsonNode metadata; // everything except layers + sources
|
||||||
public Map<String, MapSource> sources;
|
public Map<String, MapSource> sources;
|
||||||
public ArrayNode layerDefinitions; // "layers" array
|
public JsonNode layerDefinitions; // the "layers" array
|
||||||
|
|
||||||
//FIXME
|
//FIXME
|
||||||
public static MapStyle fromFile(String filename, AppController app) {
|
public static MapStyle fromMapLibreJsonFile(String filename, AppController app) {
|
||||||
String styleContents;
|
String styleContents;
|
||||||
if (filename.startsWith("/storage")) styleContents = FileHelper.loadStringFromUserFile(filename);
|
if (filename.startsWith("/storage")) styleContents = FileHelper.loadStringFromUserFile(filename);
|
||||||
else styleContents = FileHelper.loadStringFromAssetFile(filename, app);
|
else styleContents = FileHelper.loadStringFromAssetFile(filename, app);
|
||||||
@@ -41,7 +40,7 @@ public class MapStyle {
|
|||||||
new TypeReference<Map<String, MapSource>>() {}
|
new TypeReference<Map<String, MapSource>>() {}
|
||||||
);
|
);
|
||||||
|
|
||||||
style.layerDefinitions = root.withArray("layers");
|
style.layerDefinitions = root.path("layers");
|
||||||
|
|
||||||
ObjectNode metadata = root.deepCopy();
|
ObjectNode metadata = root.deepCopy();
|
||||||
metadata.remove("layers");
|
metadata.remove("layers");
|
||||||
|
|||||||
@@ -3,83 +3,64 @@ package eu.konggdev.strikemaps.ui;
|
|||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import com.google.common.collect.BiMap;
|
||||||
import eu.konggdev.strikemaps.Component;
|
import eu.konggdev.strikemaps.Component;
|
||||||
import eu.konggdev.strikemaps.R;
|
import eu.konggdev.strikemaps.R;
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
import eu.konggdev.strikemaps.map.MapComponent;
|
||||||
import eu.konggdev.strikemaps.ui.element.region.content.MainContentRegion;
|
import eu.konggdev.strikemaps.ui.element.UIRegion;
|
||||||
import eu.konggdev.strikemaps.ui.element.region.UIRegion;
|
|
||||||
import eu.konggdev.strikemaps.ui.fragment.layout.FragmentLayoutControls;
|
import eu.konggdev.strikemaps.ui.fragment.layout.FragmentLayoutControls;
|
||||||
import eu.konggdev.strikemaps.ui.fragment.layout.FragmentLayoutSearch;
|
|
||||||
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentOfflineMaps;
|
|
||||||
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentSettings;
|
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentSettings;
|
||||||
import eu.konggdev.strikemaps.ui.screen.Screen;
|
import eu.konggdev.strikemaps.ui.screen.Screen;
|
||||||
import eu.konggdev.strikemaps.ui.screen.definition.DefinedScreen;
|
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class UIComponent implements Component {
|
public class UIComponent implements Component {
|
||||||
@NonNull AppController app;
|
@NonNull AppController app;
|
||||||
MapComponent map;
|
private Map<Integer, Screen> screens;
|
||||||
|
private Integer currentScreen;
|
||||||
private final ArrayDeque<Screen> screenStack = new ArrayDeque<>();
|
|
||||||
|
|
||||||
public UIComponent(AppController app, MapComponent map) {
|
public UIComponent(AppController app, MapComponent map) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.map = map;
|
this.screens = Map.of(
|
||||||
}
|
|
||||||
|
|
||||||
public Map<DefinedScreen, Screen> getScreens(MapComponent map) {
|
|
||||||
return Map.of(
|
|
||||||
//Main screen
|
//Main screen
|
||||||
DefinedScreen.MAIN, new Screen(
|
R.layout.screen_main, new Screen(
|
||||||
//App reference
|
//App reference
|
||||||
app,
|
app,
|
||||||
|
//Map view
|
||||||
|
map.toFragment(), //FragmentLayoutContentMap
|
||||||
//Main screen init regions definition
|
//Main screen init regions definition
|
||||||
Map.of(
|
Map.of(R.id.bottomUi, new UIRegion(new FragmentLayoutControls(app, R.id.bottomUi), R.id.bottomUi)), //TODO: Probably stop referencing layout 3(!) times everytime
|
||||||
R.id.mainContentView, new MainContentRegion(map.toFragment(), R.id.mainContentView),
|
//Layout
|
||||||
R.id.bottomUi, new UIRegion(new FragmentLayoutControls(app, R.id.bottomUi), R.id.bottomUi),
|
R.layout.screen_main //TODO: Define this for the Screen without duplicating the reference
|
||||||
R.id.topUi, new UIRegion(new FragmentLayoutSearch(app, R.id.topUi), R.id.topUi)
|
|
||||||
) //TODO: Probably stop referencing layout 3(!) times everytime
|
|
||||||
),
|
),
|
||||||
//Settings screen
|
//Settings screen
|
||||||
DefinedScreen.SETTINGS, new Screen(
|
R.layout.screen_settings, new Screen(
|
||||||
app,
|
app,
|
||||||
//Just the settings content fragment
|
//Settings
|
||||||
Map.of(
|
new FragmentLayoutContentSettings(),
|
||||||
R.id.mainContentView, new MainContentRegion(new FragmentLayoutContentSettings(app), R.id.mainContentView)
|
/* No regions defined in settings
|
||||||
)
|
Entire screen is just the main view */
|
||||||
),
|
new HashMap<>(),
|
||||||
//Offline maps screen
|
//Layout
|
||||||
DefinedScreen.OFFLINE, new Screen(
|
R.layout.screen_settings
|
||||||
app,
|
|
||||||
Map.of(
|
|
||||||
R.id.mainContentView, new MainContentRegion(new FragmentLayoutContentOfflineMaps(app), R.id.mainContentView)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void swapScreen(DefinedScreen screenKey) {
|
public void swapScreen(Integer screen) {
|
||||||
if (!screenStack.isEmpty()) getCurrentScreen().detachAll();
|
currentScreen = screen;
|
||||||
screenStack.add(getScreens(map).get(screenKey));
|
|
||||||
getCurrentScreen().attachAll();
|
getCurrentScreen().attachAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean back() {
|
|
||||||
if (screenStack.size() <= 1) return false;
|
|
||||||
getCurrentScreen().detachAll();
|
|
||||||
|
|
||||||
screenStack.removeLast();
|
|
||||||
getCurrentScreen().attachAll();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Screen getCurrentScreen() {
|
public Screen getCurrentScreen() {
|
||||||
return screenStack.getLast();
|
return getScreen(currentScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Screen getScreen(Integer screen) {
|
||||||
|
return screens.get(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void alert(AlertDialog dialog) {
|
public void alert(AlertDialog dialog) {
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,4 @@
|
|||||||
package eu.konggdev.strikemaps.ui.element.region;
|
package eu.konggdev.strikemaps.ui.element;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
@@ -40,4 +40,5 @@ public class UIRegion {
|
|||||||
currentFragment = stockFragment;
|
currentFragment = stockFragment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,6 @@ public class GenericItem implements UIItem {
|
|||||||
@NonNull public String name;
|
@NonNull public String name;
|
||||||
public Bitmap image;
|
public Bitmap image;
|
||||||
public Runnable onClick;
|
public Runnable onClick;
|
||||||
public Runnable onLongClick;
|
|
||||||
boolean hasImage;
|
boolean hasImage;
|
||||||
|
|
||||||
public GenericItem(String refName) {
|
public GenericItem(String refName) {
|
||||||
@@ -27,12 +26,6 @@ public class GenericItem implements UIItem {
|
|||||||
this.onClick = onClick;
|
this.onClick = onClick;
|
||||||
hasImage = false;
|
hasImage = false;
|
||||||
}
|
}
|
||||||
public GenericItem(String refName, Runnable onClick, Runnable onLongClick) {
|
|
||||||
this.name = refName;
|
|
||||||
this.onClick = onClick;
|
|
||||||
this.onLongClick = onLongClick;
|
|
||||||
hasImage = false;
|
|
||||||
}
|
|
||||||
public GenericItem(String refName, Bitmap refImage) {
|
public GenericItem(String refName, Bitmap refImage) {
|
||||||
this.name = refName;
|
this.name = refName;
|
||||||
this.image = refImage;
|
this.image = refImage;
|
||||||
@@ -45,34 +38,18 @@ public class GenericItem implements UIItem {
|
|||||||
hasImage = true;
|
hasImage = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GenericItem(String refName, Bitmap refImage, Runnable onClick, Runnable onLongClick) {
|
public final static GenericItem fromStyle(MapStyle style, MapComponent map) {
|
||||||
this.name = refName;
|
|
||||||
this.image = refImage;
|
|
||||||
this.onClick = onClick;
|
|
||||||
this.onLongClick = onLongClick;
|
|
||||||
hasImage = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final static GenericItem fromStyle(MapStyle style, MapComponent map, Runnable onClick) {
|
|
||||||
if(style == null) return new GenericItem("Unknown");
|
if(style == null) return new GenericItem("Unknown");
|
||||||
if(style.icon != null)
|
if(style.icon != null)
|
||||||
return new GenericItem(style.name, style.icon, onClick);
|
return new GenericItem(style.name, style.icon, () -> map.setStyle(style));
|
||||||
return new GenericItem(style.name, onClick);
|
return new GenericItem(style.name, () -> map.setStyle(style));
|
||||||
}
|
}
|
||||||
public final static GenericItem fromStyle(MapStyle style, MapComponent map, Runnable onClick, Runnable onLongClick) {
|
|
||||||
if(style == null) return new GenericItem("Unknown");
|
|
||||||
if(style.icon != null)
|
|
||||||
return new GenericItem(style.name, style.icon, onClick, onLongClick);
|
|
||||||
return new GenericItem(style.name, onClick, onLongClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
public View makeView(UIComponent spawner) {
|
public View makeView(UIComponent spawner) {
|
||||||
View v = spawner.inflateUi(R.layout.item_generic);
|
View v = spawner.inflateUi(R.layout.item_generic);
|
||||||
//FIXME: These shouldn't be casted like that!
|
//FIXME: These shouldn't be casted like that!
|
||||||
((TextView) v.findViewById(R.id.name)).setText(name);
|
((TextView) v.findViewById(R.id.name)).setText(name);
|
||||||
if(image != null) ((ImageButton) v.findViewById(R.id.image)).setImageBitmap(image);
|
if(image != null) ((ImageButton) v.findViewById(R.id.image)).setImageBitmap(image);
|
||||||
if(onClick != null) v.findViewById(R.id.image).setOnClickListener(click(onClick));
|
if(onClick != null) v.findViewById(R.id.image).setOnClickListener(click(onClick));
|
||||||
if(onLongClick != null) v.findViewById(R.id.image).setOnLongClickListener(longClick(onLongClick));
|
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.ui.element.item;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import eu.konggdev.strikemaps.R;
|
|
||||||
import eu.konggdev.strikemaps.ui.UIComponent;
|
|
||||||
|
|
||||||
public class InlineItem implements UIItem {
|
|
||||||
public String text;
|
|
||||||
public Runnable onClick;
|
|
||||||
|
|
||||||
public InlineItem(String refText) {
|
|
||||||
this.text = refText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InlineItem(String refText, Runnable onClick) {
|
|
||||||
this.text = refText;
|
|
||||||
this.onClick = onClick;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View makeView(UIComponent spawner) {
|
|
||||||
View view = spawner.inflateUi(R.layout.item_inline);
|
|
||||||
((TextView) view.findViewById(R.id.inline)).setText(text);
|
|
||||||
if(onClick != null) view.findViewById(R.id.inline).setOnClickListener(click(onClick));
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,36 +4,33 @@ import android.graphics.Bitmap;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import eu.konggdev.strikemaps.ui.UIComponent;
|
import eu.konggdev.strikemaps.ui.UIComponent;
|
||||||
import org.maplibre.geojson.Feature;
|
import org.maplibre.geojson.Feature;
|
||||||
|
|
||||||
import eu.konggdev.strikemaps.R;
|
import eu.konggdev.strikemaps.R;
|
||||||
public class PreviewItem implements UIItem {
|
public class PreviewItem implements UIItem {
|
||||||
@NonNull public String name;
|
public String name;
|
||||||
public String details;
|
public String type;
|
||||||
public Bitmap image;
|
public Bitmap image;
|
||||||
boolean hasImage;
|
boolean hasImage;
|
||||||
public PreviewItem(String refName, String refType) {
|
public PreviewItem(String refName, String refType) {
|
||||||
this.name = refName;
|
this.name = refName;
|
||||||
this.details = refType;
|
this.type = refType;
|
||||||
hasImage = false;
|
hasImage = false;
|
||||||
}
|
}
|
||||||
public PreviewItem(String refName, String refType, Bitmap refImage) {
|
public PreviewItem(String refName, String refType, Bitmap refImage) {
|
||||||
this.name = refName;
|
this.name = refName;
|
||||||
this.details = refType;
|
this.type = refType;
|
||||||
this.image = refImage;
|
this.image = refImage;
|
||||||
hasImage = true;
|
hasImage = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PreviewItem fromFeature(Feature feature) {
|
public static PreviewItem fromFeature(Feature feature) {
|
||||||
return new PreviewItem(feature.getStringProperty("name"), feature.getStringProperty("class"));
|
return new PreviewItem(feature.getStringProperty("name"), feature.getStringProperty("class"));
|
||||||
}
|
}
|
||||||
public View makeView(UIComponent spawner) {
|
public View makeView(UIComponent spawner) {
|
||||||
View view = spawner.inflateUi(R.layout.item_preview);
|
View view = spawner.inflateUi(R.layout.item_preview);
|
||||||
((TextView) view.findViewById(R.id.choiceName)).setText(name);
|
((TextView) view.findViewById(R.id.choiceName)).setText(name);
|
||||||
if (details != null)
|
((TextView) view.findViewById(R.id.type)).setText(type);
|
||||||
((TextView) view.findViewById(R.id.details)).setText(details);
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
public View makeView(UIComponent spawner, View.OnClickListener onClick) {
|
public View makeView(UIComponent spawner, View.OnClickListener onClick) {
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ public interface UIItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default View.OnLongClickListener longClick(Runnable action) { return v -> { action.run(); return true; };}
|
default View.OnLongClickListener longClick(Runnable action) { return v -> { action.run(); return true; };}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-24
@@ -1,24 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.ui.element.region.content;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import eu.konggdev.strikemaps.ui.element.region.UIRegion;
|
|
||||||
|
|
||||||
public class MainContentRegion extends UIRegion {
|
|
||||||
public Fragment fragment;
|
|
||||||
public Integer layoutId;
|
|
||||||
|
|
||||||
public MainContentRegion(@NonNull Fragment initFragment, Integer refLayoutId) {
|
|
||||||
super(initFragment, refLayoutId);
|
|
||||||
this.fragment = initFragment;
|
|
||||||
this.layoutId = refLayoutId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Fragment getFragment() {
|
|
||||||
return this.fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFragment(Fragment fragment) {
|
|
||||||
this.fragment = fragment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,257 +1,20 @@
|
|||||||
package eu.konggdev.strikemaps.ui.factory;
|
package eu.konggdev.strikemaps.ui.factory;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.widget.LinearLayout;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.widget.ScrollView;
|
||||||
import android.widget.*;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
import eu.konggdev.strikemaps.app.util.JsonPatcher;
|
|
||||||
import eu.konggdev.strikemaps.data.helper.FileHelper;
|
|
||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
|
||||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
|
||||||
import eu.konggdev.strikemaps.ui.UIComponent;
|
|
||||||
import eu.konggdev.strikemaps.ui.element.item.GenericItem;
|
|
||||||
import eu.konggdev.strikemaps.ui.element.item.PreviewItem;
|
import eu.konggdev.strikemaps.ui.element.item.PreviewItem;
|
||||||
import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup;
|
|
||||||
import org.maplibre.geojson.Feature;
|
import org.maplibre.geojson.Feature;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static androidx.core.content.ContextCompat.getSystemService;
|
|
||||||
|
|
||||||
//FIXME: Move Item functions into specific classes for specific types - e.g. StyleItem
|
//FIXME: Move Item functions into specific classes for specific types - e.g. StyleItem
|
||||||
public final class AlertDialogFactory {
|
public final class AlertDialogFactory {
|
||||||
public static AlertDialog copyBuiltInStyle(AppController app, MapComponent map, UIComponent ui, FragmentMapChangePopup mapChangePopup) {
|
|
||||||
//TODO: Use an UI element thats supposed to be vertical, instead of GenericItem
|
|
||||||
List<String> styles = Arrays.asList(FileHelper.getAssetFiles("bundled/style", ".style.json", app));
|
|
||||||
|
|
||||||
LinearLayout container = new LinearLayout(app.getActivity());
|
|
||||||
container.setOrientation(LinearLayout.VERTICAL);
|
|
||||||
|
|
||||||
for (String style : styles) {
|
|
||||||
View itemView = GenericItem
|
|
||||||
.fromStyle(
|
|
||||||
MapStyle.fromFile(style, app),
|
|
||||||
map,
|
|
||||||
() -> ui.alert(AlertDialogFactory.createStyle(app, FileHelper.loadStringFromAssetFile(style, app), mapChangePopup))
|
|
||||||
)
|
|
||||||
.makeView(ui);
|
|
||||||
|
|
||||||
container.addView(itemView);
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollView scrollView = new ScrollView(app.getActivity());
|
|
||||||
scrollView.addView(container);
|
|
||||||
|
|
||||||
AlertDialog dialog = new AlertDialog.Builder(app.getActivity())
|
|
||||||
.setTitle("Copy from")
|
|
||||||
.setView(scrollView)
|
|
||||||
.setNegativeButton("Cancel", null)
|
|
||||||
.create();
|
|
||||||
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AlertDialog createStyle(AppController app, String baseStyleContents, FragmentMapChangePopup mapChangePopup) {
|
|
||||||
final EditText nameInput = new EditText(app.getActivity());
|
|
||||||
nameInput.setHint("Name");
|
|
||||||
|
|
||||||
final CheckBox inferFileName = new CheckBox(app.getActivity());
|
|
||||||
inferFileName.setText("Infer filename automatically");
|
|
||||||
inferFileName.setChecked(true);
|
|
||||||
|
|
||||||
final EditText fileInput = new EditText(app.getActivity());
|
|
||||||
fileInput.setHint("Filename");
|
|
||||||
|
|
||||||
final TextView inferedFileName = new TextView(app.getActivity());
|
|
||||||
inferedFileName.setPadding(0, 2, 0, 0);
|
|
||||||
LinearLayout container = new LinearLayout(app.getActivity());
|
|
||||||
container.setOrientation(LinearLayout.VERTICAL);
|
|
||||||
|
|
||||||
int padding = (int) (20 * app.getActivity().getResources().getDisplayMetrics().density);
|
|
||||||
container.setPadding(padding, padding, padding, 0);
|
|
||||||
|
|
||||||
container.addView(nameInput);
|
|
||||||
container.addView(inferFileName);
|
|
||||||
container.addView(fileInput);
|
|
||||||
container.addView(inferedFileName);
|
|
||||||
|
|
||||||
inferFileName.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
|
||||||
fileInput.setVisibility(isChecked ? View.GONE : View.VISIBLE);
|
|
||||||
inferedFileName.setVisibility(isChecked ? View.VISIBLE : View.GONE);
|
|
||||||
});
|
|
||||||
|
|
||||||
fileInput.setVisibility(inferFileName.isChecked() ? View.GONE : View.VISIBLE);
|
|
||||||
inferedFileName.setVisibility(inferFileName.isChecked() ? View.VISIBLE : View.GONE);
|
|
||||||
|
|
||||||
nameInput.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
|
||||||
String nameText = "";
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
|
||||||
if (!s.isEmpty() && s != null) {
|
|
||||||
nameText = "File name will be: " + s.toString().toLowerCase(Locale.ROOT) + ".style.json";
|
|
||||||
}
|
|
||||||
} else if (s != null) {
|
|
||||||
nameText = "File name will be: " + s.toString().toLowerCase(Locale.ROOT) + ".style.json";
|
|
||||||
}
|
|
||||||
|
|
||||||
inferedFileName.setText(nameText);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {}
|
|
||||||
});
|
|
||||||
|
|
||||||
AlertDialog dialog = new AlertDialog.Builder(app.getActivity())
|
|
||||||
.setTitle("Create")
|
|
||||||
.setView(container)
|
|
||||||
.setPositiveButton("Create", null)
|
|
||||||
.setNegativeButton("Cancel", (d, w) -> d.dismiss())
|
|
||||||
.create();
|
|
||||||
|
|
||||||
dialog.setOnShowListener(d -> {
|
|
||||||
Button createButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
|
||||||
|
|
||||||
createButton.setOnClickListener(v -> {
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
|
||||||
boolean nameEntryRequired = true;
|
|
||||||
String styleContentName = "";
|
|
||||||
if (baseStyleContents != null) {
|
|
||||||
try {
|
|
||||||
JsonNode root = mapper.readTree(baseStyleContents);
|
|
||||||
if (!root.path("name").asText().isEmpty()) {
|
|
||||||
nameEntryRequired = false; //We can take the name from the style
|
|
||||||
styleContentName = root.path("name").asText();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String name = nameInput.getText().toString().trim();
|
|
||||||
|
|
||||||
if (name.isEmpty() && nameEntryRequired) {
|
|
||||||
nameInput.setError("Name required");
|
|
||||||
return;
|
|
||||||
} else if (name.isEmpty() && !nameEntryRequired) {
|
|
||||||
name = styleContentName;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert !name.isEmpty();
|
|
||||||
|
|
||||||
String fileName;
|
|
||||||
if (inferFileName.isChecked()) {
|
|
||||||
fileName = name.toLowerCase(Locale.ROOT) + ".style.json";
|
|
||||||
} else {
|
|
||||||
fileName = fileInput.getText().toString();
|
|
||||||
if (fileName.isEmpty()) {
|
|
||||||
fileInput.setError("File name required");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fileName.endsWith(".style.json")) {
|
|
||||||
fileInput.setError("File must end with .style.json");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
JsonNode root;
|
|
||||||
if(baseStyleContents != null) {
|
|
||||||
if(!baseStyleContents.isEmpty()) {
|
|
||||||
root = mapper.readTree(baseStyleContents);
|
|
||||||
} else {
|
|
||||||
root = mapper.createObjectNode();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
root = mapper.createObjectNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!root.path("name").asText().isEmpty()) {
|
|
||||||
ObjectNode node = mapper.createObjectNode();
|
|
||||||
node.put("name", name);
|
|
||||||
root = JsonPatcher.patch(root, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FileHelper.userFileExists("style", fileName, app)) {
|
|
||||||
app.getUi().alert(askUserOverwriteFile(app, fileName, "style", mapper.writeValueAsString(root), dialog, mapChangePopup));
|
|
||||||
} else {
|
|
||||||
FileHelper.writeUserFile("style", fileName, mapper.writeValueAsString(root), app);
|
|
||||||
}
|
|
||||||
dialog.dismiss();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Toast.makeText(app.getActivity(), "Failed to create", Toast.LENGTH_SHORT).show();
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
mapChangePopup.reloadStyles();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AlertDialog askUserOverwriteFile(AppController app, String fileName, String path, String content, FragmentMapChangePopup mapChangePopup) {
|
|
||||||
return new AlertDialog.Builder(app.getActivity())
|
|
||||||
.setMessage("Style of filename " + fileName + " already exists, do you wish to overwrite it?")
|
|
||||||
.setPositiveButton("Yes", (dialog, which) -> {
|
|
||||||
try {
|
|
||||||
FileHelper.writeUserFile(path, fileName, content, app);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
mapChangePopup.reloadStyles();
|
|
||||||
})
|
|
||||||
.setNegativeButton("No", null)
|
|
||||||
.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AlertDialog askUserOverwriteFile(AppController app, String fileName, String path, String content, AlertDialog originDialog, FragmentMapChangePopup mapChangePopup) {
|
|
||||||
return new AlertDialog.Builder(app.getActivity())
|
|
||||||
.setMessage("Style of filename: " + fileName + " already exists, do you wish to overwrite it?")
|
|
||||||
.setPositiveButton("Yes", (dialog, which) -> {
|
|
||||||
try {
|
|
||||||
FileHelper.writeUserFile(path, fileName, content, app);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (originDialog != null) {
|
|
||||||
originDialog.dismiss();
|
|
||||||
}
|
|
||||||
mapChangePopup.reloadStyles();
|
|
||||||
dialog.dismiss();
|
|
||||||
})
|
|
||||||
.setNegativeButton("No", (dialog, which) -> {
|
|
||||||
if (originDialog != null) {
|
|
||||||
originDialog.dismiss();
|
|
||||||
}
|
|
||||||
dialog.dismiss();
|
|
||||||
})
|
|
||||||
.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AlertDialog pointSelector(AppController app, List<Feature> features, Consumer<Feature> callback) {
|
public static AlertDialog pointSelector(AppController app, List<Feature> features, Consumer<Feature> callback) {
|
||||||
LinearLayout layout = new LinearLayout(app.getActivity());
|
LinearLayout layout = new LinearLayout(app.getActivity());
|
||||||
layout.setOrientation(LinearLayout.VERTICAL);
|
layout.setOrientation(LinearLayout.VERTICAL);
|
||||||
@@ -267,7 +30,7 @@ public final class AlertDialogFactory {
|
|||||||
for (Feature feature : features) {
|
for (Feature feature : features) {
|
||||||
View itemView = PreviewItem.fromFeature(feature).makeView(app.getUi(), v -> {
|
View itemView = PreviewItem.fromFeature(feature).makeView(app.getUi(), v -> {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
new Handler(Looper.getMainLooper())
|
new android.os.Handler(android.os.Looper.getMainLooper())
|
||||||
.post(() -> callback.accept(feature));
|
.post(() -> callback.accept(feature));
|
||||||
});
|
});
|
||||||
layout.addView(itemView);
|
layout.addView(itemView);
|
||||||
@@ -275,34 +38,4 @@ public final class AlertDialogFactory {
|
|||||||
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AlertDialog searchSettings(AppController app) {
|
|
||||||
return new AlertDialog.Builder(app.getActivity())
|
|
||||||
.setTitle("Configure Search")
|
|
||||||
.setPositiveButton("OK", null)
|
|
||||||
.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AlertDialog restartDialog(AppController app) {
|
|
||||||
return new AlertDialog.Builder(app.getActivity())
|
|
||||||
.setTitle("Restart required")
|
|
||||||
.setMessage("Restart the app to apply changes.")
|
|
||||||
.setCancelable(false)
|
|
||||||
.setNegativeButton("Cancel", (d, w) -> {
|
|
||||||
Toast.makeText(app.getActivity(),
|
|
||||||
"Changes will be applied on next restart",
|
|
||||||
Toast.LENGTH_SHORT).show();
|
|
||||||
d.dismiss();
|
|
||||||
})
|
|
||||||
.setPositiveButton("Restart", (d, w) -> {
|
|
||||||
Intent i = app.getActivity().getPackageManager()
|
|
||||||
.getLaunchIntentForPackage(app.getActivity().getPackageName());
|
|
||||||
if (i != null) {
|
|
||||||
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
app.getActivity().startActivity(i);
|
|
||||||
}
|
|
||||||
Runtime.getRuntime().exit(0);
|
|
||||||
})
|
|
||||||
.create();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.view.MotionEvent;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import eu.konggdev.strikemaps.ui.element.UIRegion;
|
||||||
|
|
||||||
public interface ContainerFragment {
|
public interface ContainerFragment {
|
||||||
abstract public Integer getRegion();
|
abstract public Integer getRegion();
|
||||||
|
|||||||
@@ -1,148 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.ui.fragment.dialog;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.provider.OpenableColumns;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.Button;
|
|
||||||
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import androidx.annotation.UiContext;
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
|
||||||
import eu.konggdev.strikemaps.R;
|
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
|
||||||
import eu.konggdev.strikemaps.data.helper.FileHelper;
|
|
||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
|
||||||
import eu.konggdev.strikemaps.ui.UIComponent;
|
|
||||||
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
|
|
||||||
import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class NewStyleBottomSheet extends BottomSheetDialogFragment {
|
|
||||||
private final String styleBase = "{\"name\":\"None\"}";
|
|
||||||
|
|
||||||
@NonNull AppController app;
|
|
||||||
@NonNull MapComponent map;
|
|
||||||
@NonNull UIComponent ui;
|
|
||||||
@NonNull
|
|
||||||
FragmentMapChangePopup mapChangePopup;
|
|
||||||
|
|
||||||
|
|
||||||
private final ActivityResultLauncher<Intent> importLauncher =
|
|
||||||
registerForActivityResult(
|
|
||||||
new ActivityResultContracts.StartActivityForResult(),
|
|
||||||
result -> {
|
|
||||||
if (result.getResultCode() == android.app.Activity.RESULT_OK
|
|
||||||
&& result.getData() != null) {
|
|
||||||
|
|
||||||
Uri uri = result.getData().getData();
|
|
||||||
|
|
||||||
try (InputStream in = requireContext()
|
|
||||||
.getContentResolver()
|
|
||||||
.openInputStream(uri)) {
|
|
||||||
|
|
||||||
try (Cursor cursor = requireContext()
|
|
||||||
.getContentResolver()
|
|
||||||
.query(uri, null, null, null, null)) {
|
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
|
||||||
if (nameIndex >= 0) {
|
|
||||||
String fileName = cursor.getString(nameIndex);
|
|
||||||
|
|
||||||
BufferedReader reader = new BufferedReader(
|
|
||||||
new InputStreamReader(in)
|
|
||||||
);
|
|
||||||
|
|
||||||
StringBuilder contentBuilder = new StringBuilder();
|
|
||||||
String line;
|
|
||||||
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
contentBuilder.append(line).append(System.lineSeparator());
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
String content = contentBuilder.toString();
|
|
||||||
|
|
||||||
if (fileName != null && !fileName.endsWith(".style.json")) {
|
|
||||||
app.getUi().alert(
|
|
||||||
AlertDialogFactory.createStyle(
|
|
||||||
app,
|
|
||||||
content,
|
|
||||||
mapChangePopup
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (!FileHelper.userFileExists("style", fileName, app)) {
|
|
||||||
FileHelper.writeUserFile("style", fileName, content, app);
|
|
||||||
} else {
|
|
||||||
app.getUi().alert(AlertDialogFactory.askUserOverwriteFile(app, fileName, "style", content, mapChangePopup));
|
|
||||||
}
|
|
||||||
|
|
||||||
mapChangePopup.reloadStyles();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
private void showImportDialog() {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
|
||||||
intent.setType("application/json");
|
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
||||||
|
|
||||||
importLauncher.launch(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public NewStyleBottomSheet(AppController app, MapComponent map, UIComponent ui, FragmentMapChangePopup mapChangePopup) {
|
|
||||||
this.app = app;
|
|
||||||
this.map = map;
|
|
||||||
this.ui = ui;
|
|
||||||
this.mapChangePopup = mapChangePopup;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
|
||||||
@Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.dialog_new_style, container, false);
|
|
||||||
|
|
||||||
Button builtInBtn = view.findViewById(R.id.buttonFromBuiltInStyle);
|
|
||||||
Button fileBtn = view.findViewById(R.id.buttonFromFile);
|
|
||||||
Button emptyBtn = view.findViewById(R.id.buttonCreateEmpty);
|
|
||||||
|
|
||||||
builtInBtn.setOnClickListener(v -> {
|
|
||||||
app.getUi().alert(AlertDialogFactory.copyBuiltInStyle(app, map, ui, mapChangePopup));
|
|
||||||
});
|
|
||||||
|
|
||||||
fileBtn.setOnClickListener(v -> {
|
|
||||||
showImportDialog();
|
|
||||||
});
|
|
||||||
|
|
||||||
emptyBtn.setOnClickListener(v -> {
|
|
||||||
app.getUi().alert(AlertDialogFactory.createStyle(app, styleBase, mapChangePopup));
|
|
||||||
});
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-156
@@ -1,156 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.ui.fragment.dialog;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
|
||||||
import com.google.android.material.button.MaterialButton;
|
|
||||||
import eu.konggdev.strikemaps.R;
|
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
|
||||||
import eu.konggdev.strikemaps.data.helper.FileHelper;
|
|
||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
|
||||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
|
||||||
import eu.konggdev.strikemaps.ui.UIComponent;
|
|
||||||
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
|
|
||||||
import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static android.media.MediaExtractor.MetricsConstants.MIME_TYPE;
|
|
||||||
|
|
||||||
public class StyleDetailsBottomSheet extends BottomSheetDialogFragment {
|
|
||||||
@NonNull
|
|
||||||
AppController app;
|
|
||||||
@NonNull
|
|
||||||
MapComponent map;
|
|
||||||
@NonNull
|
|
||||||
UIComponent ui;
|
|
||||||
@NonNull
|
|
||||||
FragmentMapChangePopup mapChangePopup;
|
|
||||||
|
|
||||||
private final MapStyle style;
|
|
||||||
private final String stylePath;
|
|
||||||
|
|
||||||
private final ActivityResultLauncher<Intent> exportLauncher =
|
|
||||||
registerForActivityResult(
|
|
||||||
new ActivityResultContracts.StartActivityForResult(),
|
|
||||||
result -> {
|
|
||||||
|
|
||||||
if (result.getResultCode() == android.app.Activity.RESULT_OK
|
|
||||||
&& result.getData() != null) {
|
|
||||||
|
|
||||||
Uri uri = result.getData().getData();
|
|
||||||
|
|
||||||
try (OutputStream out =
|
|
||||||
requireContext()
|
|
||||||
.getContentResolver()
|
|
||||||
.openOutputStream(uri)) {
|
|
||||||
|
|
||||||
out.write(getContents().getBytes());
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
//Action definitions
|
|
||||||
//*//
|
|
||||||
void deleteStyle() {
|
|
||||||
boolean deleted = FileHelper.deleteFile(stylePath);
|
|
||||||
if (!deleted) {
|
|
||||||
Toast.makeText(requireContext(), "Failed deleting style", Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mapChangePopup.reloadStyles();
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void showExportDialog(String fileName) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
|
||||||
intent.setType("application/json");
|
|
||||||
intent.putExtra(Intent.EXTRA_TITLE, fileName);
|
|
||||||
|
|
||||||
exportLauncher.launch(intent);
|
|
||||||
}
|
|
||||||
//*//
|
|
||||||
|
|
||||||
String getContents() {
|
|
||||||
if (stylePath.startsWith("/storage")) return FileHelper.loadStringFromUserFile(stylePath);
|
|
||||||
else return FileHelper.loadStringFromAssetFile(stylePath, app);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StyleDetailsBottomSheet(AppController app, MapComponent map, UIComponent ui, FragmentMapChangePopup mapChangePopup, MapStyle style, String stylePath) {
|
|
||||||
this.app = app;
|
|
||||||
this.map = map;
|
|
||||||
this.ui = ui;
|
|
||||||
this.mapChangePopup = mapChangePopup;
|
|
||||||
this.style = style;
|
|
||||||
this.stylePath = stylePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
|
||||||
@Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.dialog_style_details, container, false);
|
|
||||||
|
|
||||||
TextView styleNameView = view.findViewById(R.id.styleName);
|
|
||||||
TextView fileNameView = view.findViewById(R.id.fileName);
|
|
||||||
TextView styleTypeView = view.findViewById(R.id.styleType);
|
|
||||||
|
|
||||||
TextView builtInStyleAlert = view.findViewById(R.id.builtInStyleAlert);
|
|
||||||
ConstraintLayout editButtonLayout = view.findViewById(R.id.editButton);
|
|
||||||
ConstraintLayout copyButtonLayout = view.findViewById(R.id.copyButton);
|
|
||||||
ConstraintLayout exportButtonLayout = view.findViewById(R.id.exportButton);
|
|
||||||
ConstraintLayout deleteButtonLayout = view.findViewById(R.id.deleteButton);
|
|
||||||
ConstraintLayout closeButtonLayout = view.findViewById(R.id.closeButton);
|
|
||||||
|
|
||||||
|
|
||||||
styleNameView.setText(style.name);
|
|
||||||
|
|
||||||
String[] pathSplit = stylePath.split("/");
|
|
||||||
String fileName = pathSplit[pathSplit.length - 1];
|
|
||||||
|
|
||||||
fileNameView.setText(fileName);
|
|
||||||
|
|
||||||
if (Objects.equals(pathSplit[0], "bundled") && pathSplit.length > 1) {
|
|
||||||
styleTypeView.setText("Built-In Style");
|
|
||||||
fileNameView.setVisibility(View.GONE);
|
|
||||||
editButtonLayout.setVisibility(View.GONE);
|
|
||||||
builtInStyleAlert.setVisibility(View.VISIBLE);
|
|
||||||
deleteButtonLayout.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
styleTypeView.setText("User Style");
|
|
||||||
}
|
|
||||||
|
|
||||||
editButtonLayout.setOnClickListener(v -> Toast.makeText(requireContext(), "Editor not implemented yet\nWait for release", Toast.LENGTH_SHORT).show());
|
|
||||||
copyButtonLayout.setOnClickListener(v -> ui.alert(AlertDialogFactory.createStyle(app, getContents(), mapChangePopup)));
|
|
||||||
exportButtonLayout.setOnClickListener(v -> showExportDialog(fileName));
|
|
||||||
deleteButtonLayout.setOnClickListener(v -> deleteStyle());
|
|
||||||
closeButtonLayout.setOnClickListener(v -> dismiss());
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -52,7 +52,7 @@ public class FragmentLayoutControls extends Fragment implements Layout {
|
|||||||
.setTitle(app.getActivity().getString(R.string.attribution_title))
|
.setTitle(app.getActivity().getString(R.string.attribution_title))
|
||||||
.setMessage(app.getActivity().getString(R.string.shipped_attribution))
|
.setMessage(app.getActivity().getString(R.string.shipped_attribution))
|
||||||
.setPositiveButton("OK", null).show();
|
.setPositiveButton("OK", null).show();
|
||||||
}
|
}
|
||||||
//*//
|
//*//
|
||||||
|
|
||||||
public FragmentLayoutControls(AppController app, Integer region) {
|
public FragmentLayoutControls(AppController app, Integer region) {
|
||||||
|
|||||||
-125
@@ -1,125 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.ui.fragment.layout;
|
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.drawable.ColorDrawable;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.PopupWindow;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
import eu.konggdev.strikemaps.R;
|
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
|
||||||
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
|
|
||||||
import eu.konggdev.strikemaps.ui.screen.definition.DefinedScreen;
|
|
||||||
|
|
||||||
public class FragmentLayoutSearch extends Fragment implements Layout {
|
|
||||||
AppController app;
|
|
||||||
private final Integer region;
|
|
||||||
|
|
||||||
public FragmentLayoutSearch(AppController app, Integer region) {
|
|
||||||
super(R.layout.fragment_search);
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setupButton(view, R.id.hamburgerButton, click(() -> {
|
|
||||||
|
|
||||||
View menuView = getLayoutInflater().inflate(R.layout.dropdown_main, null);
|
|
||||||
|
|
||||||
PopupWindow popupWindow = new PopupWindow(
|
|
||||||
menuView,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
popupWindow.setOutsideTouchable(true);
|
|
||||||
popupWindow.setFocusable(true);
|
|
||||||
popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
|
||||||
|
|
||||||
setupButton(menuView, R.id.menuSearchSettings, click(() -> {
|
|
||||||
app.getUi().alert(AlertDialogFactory.searchSettings(app));
|
|
||||||
}));
|
|
||||||
|
|
||||||
setupButton(menuView, R.id.menuSettings, click(() -> {
|
|
||||||
popupWindow.dismiss();
|
|
||||||
app.getUi().swapScreen(DefinedScreen.SETTINGS);
|
|
||||||
}));
|
|
||||||
|
|
||||||
menuView.findViewById(R.id.menuSearchSettings).setOnClickListener(v -> popupWindow.dismiss());
|
|
||||||
menuView.findViewById(R.id.menuAbout).setOnClickListener(v -> popupWindow.dismiss());
|
|
||||||
|
|
||||||
View anchor = view.findViewById(R.id.searchContainer);
|
|
||||||
|
|
||||||
anchor.post(() -> {
|
|
||||||
|
|
||||||
menuView.measure(
|
|
||||||
View.MeasureSpec.UNSPECIFIED,
|
|
||||||
View.MeasureSpec.UNSPECIFIED
|
|
||||||
);
|
|
||||||
|
|
||||||
int popupWidth = menuView.getMeasuredWidth();
|
|
||||||
int containerWidth = anchor.getWidth();
|
|
||||||
|
|
||||||
int xOffset = containerWidth - popupWidth;
|
|
||||||
popupWindow.showAsDropDown(anchor, xOffset, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
setupButton(view, R.id.offlineMapsButton, click(() -> {
|
|
||||||
View offlineMapsPopupView = getLayoutInflater().inflate(R.layout.dropdown_offline, null);
|
|
||||||
|
|
||||||
PopupWindow popupWindow = new PopupWindow(
|
|
||||||
offlineMapsPopupView,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
popupWindow.setOutsideTouchable(true);
|
|
||||||
popupWindow.setFocusable(true);
|
|
||||||
popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
|
||||||
|
|
||||||
View anchor = view.findViewById(R.id.searchContainer);
|
|
||||||
|
|
||||||
setupButton(offlineMapsPopupView, R.id.offlineMaps, click(() -> {
|
|
||||||
popupWindow.dismiss();
|
|
||||||
app.getUi().swapScreen(DefinedScreen.OFFLINE);
|
|
||||||
}));
|
|
||||||
|
|
||||||
anchor.post(() -> {
|
|
||||||
|
|
||||||
offlineMapsPopupView.measure(
|
|
||||||
View.MeasureSpec.UNSPECIFIED,
|
|
||||||
View.MeasureSpec.UNSPECIFIED
|
|
||||||
);
|
|
||||||
|
|
||||||
int popupWidth = offlineMapsPopupView.getMeasuredWidth();
|
|
||||||
int containerWidth = anchor.getWidth();
|
|
||||||
|
|
||||||
int xOffset = containerWidth - popupWidth;
|
|
||||||
popupWindow.showAsDropDown(anchor, xOffset, 1);
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+3
-2
@@ -2,11 +2,13 @@ package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.ui.element.UIRegion;
|
||||||
|
|
||||||
import eu.konggdev.strikemaps.R;
|
import eu.konggdev.strikemaps.R;
|
||||||
|
|
||||||
public class FragmentLayoutContentMap extends Fragment implements MainContentLayout {
|
public class FragmentLayoutContentMap extends Fragment implements MainContentLayout {
|
||||||
@@ -26,7 +28,6 @@ public class FragmentLayoutContentMap extends Fragment implements MainContentLay
|
|||||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
LinearLayout layout = (LinearLayout) view;
|
LinearLayout layout = (LinearLayout) view;
|
||||||
if(mapView.getParent() != null) ((ViewGroup) mapView.getParent()).removeView(mapView);
|
|
||||||
layout.addView(mapView);
|
layout.addView(mapView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-60
@@ -1,60 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import eu.konggdev.strikemaps.R;
|
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
|
||||||
import eu.konggdev.strikemaps.data.helper.FileHelper;
|
|
||||||
import eu.konggdev.strikemaps.map.source.MapSource;
|
|
||||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
|
||||||
import eu.konggdev.strikemaps.ui.element.item.GenericItem;
|
|
||||||
import eu.konggdev.strikemaps.ui.element.item.InlineItem;
|
|
||||||
import eu.konggdev.strikemaps.ui.element.item.PreviewItem;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class FragmentLayoutContentOfflineMaps extends Fragment implements MainContentLayout {
|
|
||||||
@NonNull AppController app;
|
|
||||||
|
|
||||||
public FragmentLayoutContentOfflineMaps(AppController app) {
|
|
||||||
super(R.layout.fragment_offline_maps);
|
|
||||||
this.app = app;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Fragment toFragment() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
|
||||||
super.onViewCreated(view, savedInstanceState);
|
|
||||||
|
|
||||||
List<MapSource> sources = new ArrayList<>();
|
|
||||||
|
|
||||||
List<String> stylePaths = new ArrayList<>();
|
|
||||||
stylePaths.addAll(Arrays.asList(FileHelper.getAssetFiles("bundled/style", ".style.json", app)));
|
|
||||||
stylePaths.addAll(Arrays.asList(FileHelper.getUserFiles("style", ".style.json", app)));
|
|
||||||
/* Parsing an entire MapStyle is absolutely unnecessary and resource wasteful
|
|
||||||
TODO: A method should be implemented to parse a List<MapSource> directly from the JSON */
|
|
||||||
for (String stylePath : stylePaths) {
|
|
||||||
MapStyle parsedStyle = MapStyle.fromFile(stylePath, app);
|
|
||||||
sources.addAll(parsedStyle.sources.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
LinearLayout sourcesLayout = view.findViewById(R.id.llDownloadContainer);
|
|
||||||
for (MapSource source : sources) {
|
|
||||||
if (!Objects.equals(source.type, "raster"))
|
|
||||||
sourcesLayout.addView(new InlineItem(source.url, () -> Toast.makeText(app.getActivity(), "Work in progress", Toast.LENGTH_SHORT).show()).makeView(app.getUi()));
|
|
||||||
else
|
|
||||||
sourcesLayout.addView(new InlineItem(source.tiles.toString(), () -> Toast.makeText(app.getActivity(), "Work in progress", Toast.LENGTH_SHORT).show()).makeView(app.getUi()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-58
@@ -1,66 +1,10 @@
|
|||||||
package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
|
package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
|
||||||
|
|
||||||
import android.app.ActionBar;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import com.google.android.material.appbar.MaterialToolbar;
|
|
||||||
import eu.konggdev.strikemaps.R;
|
|
||||||
import eu.konggdev.strikemaps.data.helper.UserPrefsHelper;
|
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
|
||||||
import eu.konggdev.strikemaps.map.MapComponent;
|
|
||||||
import eu.konggdev.strikemaps.ui.factory.AlertDialogFactory;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
|
|
||||||
public class FragmentLayoutContentSettings extends Fragment implements MainContentLayout {
|
|
||||||
@NonNull AppController app;
|
|
||||||
|
|
||||||
public FragmentLayoutContentSettings(AppController app) {
|
|
||||||
super(R.layout.fragment_settings);
|
|
||||||
this.app = app;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public class FragmentLayoutContentSettings implements MainContentLayout {
|
||||||
@Override
|
@Override
|
||||||
public Fragment toFragment() {
|
public Fragment toFragment() {
|
||||||
return this;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
|
||||||
Spinner mapRendererSelector = view.findViewById(R.id.mapRendererSelector);
|
|
||||||
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
|
|
||||||
view.getContext(),
|
|
||||||
R.array.map_renderers,
|
|
||||||
android.R.layout.simple_spinner_item
|
|
||||||
);
|
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
mapRendererSelector.setAdapter(adapter);
|
|
||||||
mapRendererSelector.setSelection(UserPrefsHelper.mapRenderer(app.getPrefs()));
|
|
||||||
final boolean[] ignoreFirst = {true};
|
|
||||||
mapRendererSelector.setOnItemSelectedListener(
|
|
||||||
new AdapterView.OnItemSelectedListener() {
|
|
||||||
@Override
|
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
if (ignoreFirst[0]) {
|
|
||||||
ignoreFirst[0] = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserPrefsHelper.mapRenderer(app.getPrefs(), position);
|
|
||||||
app.getUi().alert(AlertDialogFactory.restartDialog(app));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> parent) {}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-37
@@ -1,7 +1,5 @@
|
|||||||
package eu.konggdev.strikemaps.ui.fragment.popup;
|
package eu.konggdev.strikemaps.ui.fragment.popup;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
@@ -16,8 +14,6 @@ import eu.konggdev.strikemaps.map.MapComponent;
|
|||||||
|
|
||||||
import eu.konggdev.strikemaps.map.style.MapStyle;
|
import eu.konggdev.strikemaps.map.style.MapStyle;
|
||||||
import eu.konggdev.strikemaps.ui.UIComponent;
|
import eu.konggdev.strikemaps.ui.UIComponent;
|
||||||
import eu.konggdev.strikemaps.ui.fragment.dialog.NewStyleBottomSheet;
|
|
||||||
import eu.konggdev.strikemaps.ui.fragment.dialog.StyleDetailsBottomSheet;
|
|
||||||
import eu.konggdev.strikemaps.ui.element.item.GenericItem;
|
import eu.konggdev.strikemaps.ui.element.item.GenericItem;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -32,19 +28,6 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
|
|||||||
|
|
||||||
private final Integer region;
|
private final Integer region;
|
||||||
|
|
||||||
private View view;
|
|
||||||
|
|
||||||
// Action definitions
|
|
||||||
//*//
|
|
||||||
void newStyleFlow() {
|
|
||||||
new NewStyleBottomSheet(app, map, ui, this).show(app.getActivity().getSupportFragmentManager(), "NewStyleBottomSheet");
|
|
||||||
}
|
|
||||||
|
|
||||||
void styleDetails(MapStyle style, String stylePath) {
|
|
||||||
new StyleDetailsBottomSheet(app, map, ui, this, style, stylePath).show(app.getActivity().getSupportFragmentManager(), "StyleDetailsBottomSheet");
|
|
||||||
}
|
|
||||||
//*//
|
|
||||||
|
|
||||||
public FragmentMapChangePopup(AppController app, Integer region) {
|
public FragmentMapChangePopup(AppController app, Integer region) {
|
||||||
super(R.layout.popup_map_change);
|
super(R.layout.popup_map_change);
|
||||||
this.app = app;
|
this.app = app;
|
||||||
@@ -63,30 +46,16 @@ public class FragmentMapChangePopup extends Fragment implements Popup {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reloadStyles() {
|
|
||||||
List<String> stylePaths = new ArrayList<>();
|
|
||||||
stylePaths.addAll(Arrays.asList(FileHelper.getAssetFiles("bundled/style", ".style.json", app)));
|
|
||||||
stylePaths.addAll(Arrays.asList(FileHelper.getUserFiles("style", ".style.json", app)));
|
|
||||||
LinearLayout stylesLayout = view.findViewById(R.id.stylesLayout);
|
|
||||||
stylesLayout.removeAllViews();
|
|
||||||
for (String stylePath : stylePaths) {
|
|
||||||
MapStyle parsedStyle = MapStyle.fromFile(stylePath, app);
|
|
||||||
stylesLayout.addView(GenericItem.fromStyle(parsedStyle, map,
|
|
||||||
() -> map.setStyle(parsedStyle),
|
|
||||||
() -> this.styleDetails(parsedStyle, stylePath)).makeView(ui));
|
|
||||||
}
|
|
||||||
Bitmap addNewIcon = BitmapFactory.decodeResource(app.getActivity().getResources(), android.R.drawable.ic_menu_add);
|
|
||||||
stylesLayout.addView(new GenericItem("",
|
|
||||||
addNewIcon,
|
|
||||||
this::newStyleFlow).makeView(ui));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||||
//FIXME
|
//FIXME
|
||||||
setupButton(view, R.id.closeButton, click(() -> ui.getCurrentScreen().closePopup()));
|
setupButton(view, R.id.closeButton, click(() -> ui.getCurrentScreen().closePopup()));
|
||||||
setupDragHandle(view, view, () -> ui.getCurrentScreen().closePopup());
|
setupDragHandle(view, view, () -> ui.getCurrentScreen().closePopup());
|
||||||
this.view = view;
|
List<String> stylePaths = new ArrayList<>();
|
||||||
reloadStyles();
|
stylePaths.addAll(Arrays.asList(FileHelper.getAssetFiles("bundled/style", ".style.json", app)));
|
||||||
|
stylePaths.addAll(Arrays.asList(FileHelper.getUserFiles("style", ".style.json", app)));
|
||||||
|
LinearLayout stylesLayout = view.findViewById(R.id.stylesLayout);
|
||||||
|
for (String style : stylePaths)
|
||||||
|
stylesLayout.addView(GenericItem.fromStyle(MapStyle.fromMapLibreJsonFile(style, app), map).makeView(ui));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,31 @@
|
|||||||
package eu.konggdev.strikemaps.ui.screen;
|
package eu.konggdev.strikemaps.ui.screen;
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import eu.konggdev.strikemaps.R;
|
||||||
import eu.konggdev.strikemaps.app.AppController;
|
import eu.konggdev.strikemaps.app.AppController;
|
||||||
import eu.konggdev.strikemaps.ui.fragment.ContainerFragment;
|
import eu.konggdev.strikemaps.ui.fragment.ContainerFragment;
|
||||||
import eu.konggdev.strikemaps.ui.fragment.FragmentEmptyPlaceholder;
|
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.MainContentLayout;
|
||||||
import eu.konggdev.strikemaps.ui.fragment.popup.Popup;
|
import eu.konggdev.strikemaps.ui.fragment.popup.Popup;
|
||||||
import eu.konggdev.strikemaps.ui.element.region.UIRegion;
|
import eu.konggdev.strikemaps.ui.element.UIRegion;
|
||||||
|
|
||||||
public class Screen {
|
public class Screen {
|
||||||
@NonNull AppController app;
|
@NonNull AppController app;
|
||||||
Toolbar toolbar;
|
public Screen(AppController app, MainContentLayout mainContent, Map<Integer, UIRegion> regions, Integer layout) {
|
||||||
public Screen(AppController app, Map<Integer, UIRegion> regions) {
|
|
||||||
this.app = app;
|
this.app = app;
|
||||||
|
this.layout = layout;
|
||||||
|
this.mainContent = mainContent;
|
||||||
this.uiRegions = regions;
|
this.uiRegions = regions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Integer layout;
|
||||||
|
|
||||||
|
private MainContentLayout mainContent;
|
||||||
|
|
||||||
Map<Integer, UIRegion> uiRegions;
|
Map<Integer, UIRegion> uiRegions;
|
||||||
public Integer popup;
|
public Integer popup;
|
||||||
|
|
||||||
@@ -62,10 +68,10 @@ public class Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void attachAll() {
|
public void attachAll() {
|
||||||
for (UIRegion region : uiRegions.values()) setFragment(region, region.getFragment());
|
app.getActivity().setContentView(layout);
|
||||||
}
|
fragmentTransaction(R.id.mainContentView, mainContent.toFragment());
|
||||||
|
for (UIRegion region : uiRegions.values()) {
|
||||||
public void detachAll() {
|
setFragment(region, region.getFragment());
|
||||||
for (UIRegion region : uiRegions.values()) fragmentTransaction(region.layoutId, new FragmentEmptyPlaceholder());
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package eu.konggdev.strikemaps.ui.screen.definition;
|
|
||||||
public enum DefinedScreen {
|
|
||||||
MAIN,
|
|
||||||
SETTINGS,
|
|
||||||
OFFLINE
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="rectangle">
|
|
||||||
<solid android:color="#2A2100" />
|
|
||||||
<corners android:radius="10dp" />
|
|
||||||
<stroke
|
|
||||||
android:width="1dp"
|
|
||||||
android:color="#4D3D00" />
|
|
||||||
</shape>
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24"
|
|
||||||
android:tint="?attr/colorControlNormal">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z" />
|
|
||||||
</vector>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 177 B After Width: | Height: | Size: 214 B |
@@ -1,5 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
|
||||||
|
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.49,2 2,6.49 2,12s4.49,10 10,10s10,-4.49 10,-10S17.51,2 12,2zM11,10V6h2v4h3l-4,4l-4,-4H11zM17,17H7v-2h10V17z"/>
|
|
||||||
|
|
||||||
</vector>
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
<LinearLayout
|
|
||||||
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:orientation="vertical"
|
|
||||||
android:background="#000000"
|
|
||||||
android:padding="24dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="New style"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="22sp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<Space
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="6dp" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/buttonFromBuiltInStyle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:text="From built-in style"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
app:backgroundTint="#1A1A1A"
|
|
||||||
app:cornerRadius="24dp" />
|
|
||||||
|
|
||||||
<Space
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="4dp" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/buttonFromFile"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:text="From file"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
app:backgroundTint="#1A1A1A"
|
|
||||||
app:cornerRadius="24dp" />
|
|
||||||
|
|
||||||
<Space
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="4dp" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/buttonCreateEmpty"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:text="Create empty"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
app:backgroundTint="#1A1A1A"
|
|
||||||
app:cornerRadius="24dp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -1,250 +0,0 @@
|
|||||||
<?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="wrap_content"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:background="#000000"
|
|
||||||
android:padding="12dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/styleName"
|
|
||||||
android:layout_width="164dp"
|
|
||||||
android:layout_height="34dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Style Name"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="24sp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/fileName"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="27dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="\?.style.json"
|
|
||||||
android:textColor="#BDBDBD"
|
|
||||||
android:textSize="18sp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/styleName" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/styleType"
|
|
||||||
android:layout_width="112dp"
|
|
||||||
android:layout_height="27dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="Style Type?"
|
|
||||||
android:textColor="#FDFDFD"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:gravity="center"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/fileName" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/builtInStyleAlert"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:paddingHorizontal="14dp"
|
|
||||||
android:paddingVertical="12dp"
|
|
||||||
android:background="@drawable/bg_alert_warning"
|
|
||||||
android:text="Built-in styles can't be edited directly\nMake a copy to customize it"
|
|
||||||
android:textColor="#FFD54F"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:lineSpacingExtra="2dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:drawablePadding="8dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/styleType"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/editButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="38dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginBottom="2dp"
|
|
||||||
android:background="#1B1A1A"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/builtInStyleAlert"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/hideIcon"
|
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:src="@android:drawable/ic_menu_edit"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/hideBtnText"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Edit style"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/copyButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="38dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:layout_marginBottom="2dp"
|
|
||||||
android:background="#1B1A1A"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/editButton"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/copyIcon"
|
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:src="@drawable/ic_copy"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/copyBtnText"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Copy style"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/exportButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="38dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:layout_marginBottom="2dp"
|
|
||||||
android:background="#1B1A1A"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/copyButton">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/exportIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:src="@android:drawable/ic_menu_save"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/exportBtnText"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Export style"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/deleteButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="38dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:layout_marginBottom="5dp"
|
|
||||||
android:background="#1B1A1A"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/exportButton"
|
|
||||||
app:layout_constraintVertical_bias="0.081">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/deleteIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:src="@android:drawable/ic_menu_delete"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/deleteText"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Delete style"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/closeButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="38dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:background="#1B1A1A"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/deleteButton"
|
|
||||||
tools:layout_editor_absoluteY="251dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/closeIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:src="@android:drawable/ic_menu_more"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/closeText"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Close"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="20sp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<?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">
|
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="200dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:cardCornerRadius="12dp"
|
|
||||||
app:cardElevation="12dp"
|
|
||||||
app:cardBackgroundColor="#000000">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="8dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/menuSearchSettings"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="12dp"
|
|
||||||
android:text="Configure Search"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:background="?android:attr/selectableItemBackground"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/menuSettings"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="12dp"
|
|
||||||
android:text="Settings"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:background="?android:attr/selectableItemBackground"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/menuAbout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="12dp"
|
|
||||||
android:text="About"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:background="?android:attr/selectableItemBackground"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
<?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">
|
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="200dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:cardCornerRadius="12dp"
|
|
||||||
app:cardElevation="12dp"
|
|
||||||
app:cardBackgroundColor="#000000">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="8dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/offlineMaps"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="12dp"
|
|
||||||
android:text="Offline Maps"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:background="?android:attr/selectableItemBackground"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -2,4 +2,5 @@
|
|||||||
<android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
</android.widget.LinearLayout>
|
</android.widget.LinearLayout>
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
<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="match_parent"
|
|
||||||
android:background="#000000">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvDownloadLabel"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Download for source:"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:includeFontPadding="true"
|
|
||||||
android:paddingBottom="4dp"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginStart="16dp" />
|
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
|
||||||
android:id="@+id/scrollDownloadContainer"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/tvDownloadLabel"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:fillViewport="true">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/llDownloadContainer"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical" />
|
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
<?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="match_parent"
|
|
||||||
android:padding="12dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/searchContainer"
|
|
||||||
android:layout_width="320dp"
|
|
||||||
android:layout_height="35dp"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
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/offlineMapsButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:contentDescription="Offline Maps"
|
|
||||||
android:src="@drawable/ic_offline"
|
|
||||||
android:padding="6dp"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
app:tint="#B0B0B0" />
|
|
||||||
|
|
||||||
<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>
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
<?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="match_parent"
|
|
||||||
android:padding="24dp"
|
|
||||||
android:background="@android:color/background_dark">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/mapRendererLabel"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Map Renderer:"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textSize="16sp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/mapRendererSelector"/>
|
|
||||||
|
|
||||||
<Spinner
|
|
||||||
android:id="@+id/mapRendererSelector"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/mapRendererLabel"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"/>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
<?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:foregroundTint="#FFFFFF">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/inline"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="24dp"
|
|
||||||
android:paddingVertical="12dp"
|
|
||||||
android:text=""
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:drawableEnd="@drawable/ic_arrow_forward"
|
|
||||||
android:drawablePadding="8dp"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"/>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="#000000"
|
android:background="#0E0000"
|
||||||
android:foregroundTint="#FFFFFF">
|
android:foregroundTint="#FFFFFF">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -15,7 +16,7 @@
|
|||||||
android:layout_marginEnd="12dp"
|
android:layout_marginEnd="12dp"
|
||||||
android:text="Choice Item"
|
android:text="Choice Item"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="#FFFFFF"
|
||||||
android:textSize="20sp"
|
android:textSize="24sp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:scrollHorizontally="false"
|
android:scrollHorizontally="false"
|
||||||
@@ -23,12 +24,12 @@
|
|||||||
android:autoSizeMinTextSize="12sp"
|
android:autoSizeMinTextSize="12sp"
|
||||||
android:autoSizeMaxTextSize="24sp"
|
android:autoSizeMaxTextSize="24sp"
|
||||||
android:autoSizeStepGranularity="1sp"
|
android:autoSizeStepGranularity="1sp"
|
||||||
app:layout_constraintStart_toEndOf="@+id/icon"
|
app:layout_constraintStart_toEndOf="@+id/poiIcon"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/icon"
|
android:id="@+id/poiIcon"
|
||||||
android:layout_width="55dp"
|
android:layout_width="55dp"
|
||||||
android:layout_height="55dp"
|
android:layout_height="55dp"
|
||||||
android:layout_marginStart="7dp"
|
android:layout_marginStart="7dp"
|
||||||
@@ -38,20 +39,20 @@
|
|||||||
app:srcCompat="@drawable/maplibre_info_bg_selector" />
|
app:srcCompat="@drawable/maplibre_info_bg_selector" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/details"
|
android:id="@+id/type"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="7dp"
|
android:layout_marginStart="7dp"
|
||||||
android:layout_marginEnd="12dp"
|
android:layout_marginEnd="12dp"
|
||||||
android:layout_marginBottom="12dp"
|
android:layout_marginBottom="12dp"
|
||||||
|
android:text="Type"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="#FFFFFF"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
app:layout_constraintStart_toEndOf="@id/icon"
|
app:layout_constraintStart_toEndOf="@id/poiIcon"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/choiceName"
|
app:layout_constraintTop_toBottomOf="@id/choiceName"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Executable
+80
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
<?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/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" />
|
|
||||||
|
|
||||||
<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_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="0.0" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/topUi"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="0.0" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="Theme.StrikeMaps" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
<style name="Theme.StrikeMaps" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
<!-- Primary brand color. -->
|
<!-- Primary brand color. -->
|
||||||
<item name="colorPrimary">@color/purple_200</item>
|
<item name="colorPrimary">@color/purple_200</item>
|
||||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||||
@@ -11,5 +11,6 @@
|
|||||||
<item name="colorOnSecondary">@color/black</item>
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,11 +1,5 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Strike Maps</string>
|
<string name="app_name">Strike Maps</string>
|
||||||
<string name="settings_title">Settings</string>
|
|
||||||
<string name="attribution_title"> Attribution </string>
|
<string name="attribution_title"> Attribution </string>
|
||||||
<string name="shipped_attribution">Map Rendering libraries Included;\n - MapLibre developed by MapLibre Organization\n - Vtm developed by Mapsforge\nStrike Maps made with <3 by konggdev</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>
|
||||||
<string-array name="map_renderers">
|
|
||||||
<item>MapLibre GL JS</item>
|
|
||||||
<item>MapLibre Native</item>
|
|
||||||
<item>VTM</item>
|
|
||||||
</string-array>
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="Theme.StrikeMaps" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
<style name="Theme.StrikeMaps" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
<!-- Primary brand color. -->
|
<!-- Primary brand color. -->
|
||||||
<item name="colorPrimary">@color/black</item>
|
<item name="colorPrimary">@color/black</item>
|
||||||
<item name="colorPrimaryVariant">@color/black</item>
|
<item name="colorPrimaryVariant">@color/black</item>
|
||||||
@@ -11,5 +11,6 @@
|
|||||||
<item name="colorOnSecondary">@color/black</item>
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -10,6 +10,7 @@ constraintlayout = "2.1.4"
|
|||||||
playServicesMaps = "19.0.0"
|
playServicesMaps = "19.0.0"
|
||||||
viewpager2 = "1.1.0"
|
viewpager2 = "1.1.0"
|
||||||
kotlin = "2.3.10"
|
kotlin = "2.3.10"
|
||||||
|
coreKtx = "1.18.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
@@ -19,7 +20,9 @@ appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "a
|
|||||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
||||||
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
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" }
|
viewpager2 = { group = "androidx.viewpager2", name = "viewpager2", version.ref = "viewpager2" }
|
||||||
|
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|||||||
Reference in New Issue
Block a user