add/edit map source dialog redesign
This commit is contained in:
parent
b45e432eb2
commit
d254de8598
16 changed files with 1332 additions and 180 deletions
42
OsmAnd/res/layout/edit_text_with_descr.xml
Normal file
42
OsmAnd/res/layout/edit_text_with_descr.xml
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/value_input_layout"
|
||||
style="@style/InputLayoutStyle.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:minHeight="@dimen/favorites_list_item_height"
|
||||
app:endIconMode="clear_text"
|
||||
app:hintAnimationEnabled="false"
|
||||
app:hintEnabled="false">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/value_edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:hint="@string/shared_string_never"
|
||||
android:inputType="number" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/dialog_descr"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
tools:text="@string/expire_time_descr" />
|
||||
|
||||
</LinearLayout>
|
125
OsmAnd/res/layout/fragment_edit_map_source.xml
Normal file
125
OsmAnd/res/layout/fragment_edit_map_source.xml
Normal file
|
@ -0,0 +1,125 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/toolbar_height"
|
||||
android:background="?attr/actionModeBackground"
|
||||
android:theme="?attr/toolbar_theme"
|
||||
app:title="@string/edit_online_source"
|
||||
osmand:titleTextColor="?android:textColorPrimary">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/toolbar_action"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
tools:src="@drawable/ic_action_help" />
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/name_input_layout"
|
||||
style="@style/InputLayoutStyle.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/content_padding"
|
||||
android:hint="@string/shared_string_name"
|
||||
app:helperText="@string/online_map_name_helper_text">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/name_edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/url_input_layout"
|
||||
style="@style/InputLayoutStyle.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:hint="@string/edit_tilesource_url_to_load"
|
||||
app:helperText="@string/online_map_url_helper_text">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/url_edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/divider_color_basic" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/content_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/divider_color_basic" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/bg_color"
|
||||
android:minHeight="@dimen/dialog_button_ex_height"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/content_padding_small"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingBottom="@dimen/content_padding_small">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/save_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/dlg_btn_primary">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/save_button_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:text="@string/shared_string_save"
|
||||
android:textColor="?attr/dlg_btn_primary_text" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -76,7 +76,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/shared_string_name"
|
||||
app:boxBackgroundColor="#4DCCCCCC">
|
||||
app:boxBackgroundColor="@color/input_layout_bg_color">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/name_edit"
|
||||
|
@ -129,7 +129,7 @@
|
|||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/shared_string_description"
|
||||
app:boxBackgroundColor="#4DCCCCCC">
|
||||
app:boxBackgroundColor="@color/input_layout_bg_color">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/description_edit"
|
||||
|
|
102
OsmAnd/res/layout/zoom_levels_with_descr.xml
Normal file
102
OsmAnd/res/layout/zoom_levels_with_descr.xml
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/slider_descr"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
tools:text="@string/terrain_slider_description" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:text="@string/shared_string_min"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="end"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:text="@string/shared_string_max"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/zoom_value_min"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
tools:text="3" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/zoom_slider"
|
||||
style="@style/Widget.Styled.Slider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_weight="1"
|
||||
android:stepSize="1" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/zoom_value_max"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
tools:text="19" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/dialog_descr"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
tools:text="@string/terrain_slider_description" />
|
||||
|
||||
</LinearLayout>
|
|
@ -465,5 +465,6 @@
|
|||
<color name="switch_button_active_dark">#1AD28521</color>
|
||||
<color name="switch_button_active_stroke">#80237BFF</color>
|
||||
<color name="empty_hint_bg">#80000000</color>
|
||||
<color name="input_layout_bg_color">#4DCCCCCC</color>
|
||||
|
||||
</resources>
|
|
@ -11,6 +11,23 @@
|
|||
Thx - Hardy
|
||||
|
||||
-->
|
||||
<string name="tiles_storage_descr">Choose how downloaded tiles will be stored.</string>
|
||||
<string name="expire_time_descr">Expiration time in minutes. Cached tiles will be reloaded after specified time.
|
||||
Leave this field empty if you do not need to reload tiles for this source.
|
||||
\n\nOne day is 1440 minutes.\nOne week is 10 080 minutes.\nOne month is 43 829 minutes.</string>
|
||||
<string name="map_source_zoom_levels_descr">This parameters will affect the map display when used as a map type or overlay/underlay.
|
||||
\n\n%1$s: the map will be limited to the selected zooms. \n\n%2$s: Zoom levels at which
|
||||
tiles will be visible. Upscale or downscale will occur above or below the set values.</string>
|
||||
<string name="map_source_zoom_levels">Set the minimum and maximum zoom level at which the online map will be displayed or loaded.</string>
|
||||
<string name="storage_format">Storage format</string>
|
||||
<string name="mercator_projection">Mercator Projection</string>
|
||||
<string name="expire_time">Expire time</string>
|
||||
<string name="edit_online_source">Edit online source</string>
|
||||
<string name="online_map_url_helper_text">Enter or paste URL for online source.</string>
|
||||
<string name="online_map_name_helper_text">Provide name for online map source.</string>
|
||||
<string name="sqlite_db_file">SQLiteDB file</string>
|
||||
<string name="one_image_per_tile">One image file per tile</string>
|
||||
<string name="pseudo_mercator_projection">Pseudo-Mercator projection</string>
|
||||
<string name="unsupported_type_error">Unsupported type</string>
|
||||
<string name="index_item_world_basemap_detailed">World overview map (detailed)</string>
|
||||
<string name="profiles_for_action_not_found">Could not find any such profiles.</string>
|
||||
|
|
|
@ -789,4 +789,16 @@
|
|||
<style name="ThemeOverlay.AppCompat.ActionBar">
|
||||
<item name="android:padding">0dp</item>
|
||||
</style>
|
||||
|
||||
<style name="InputLayoutStyle.FilledBox" parent="Widget.MaterialComponents.TextInputLayout.FilledBox">
|
||||
<item name="android:minHeight">@dimen/favorites_list_item_height</item>
|
||||
<item name="android:textColorHint">?android:textColorSecondary</item>
|
||||
<item name="boxBackgroundColor">@color/input_layout_bg_color</item>
|
||||
<item name="errorEnabled">true</item>
|
||||
<item name="helperTextEnabled">true</item>
|
||||
<item name="helperTextTextColor">?android:textColorSecondary</item>
|
||||
<item name="hintAnimationEnabled">true</item>
|
||||
<item name="hintTextColor">?android:textColorSecondary</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -82,6 +82,8 @@ public class SQLiteTileSource implements ITileSource {
|
|||
if (is.getName().equalsIgnoreCase(sourceName)) {
|
||||
base = is;
|
||||
urlTemplate = is.getUrlTemplate();
|
||||
expirationTimeMillis = is.getExpirationTimeMillis();
|
||||
inversiveZoom = is.getInversiveZoom();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -336,6 +338,8 @@ public class SQLiteTileSource implements ITileSource {
|
|||
}
|
||||
|
||||
public void updateFromTileSourceTemplate(TileSourceTemplate r) {
|
||||
db = ctx.getSQLiteAPI().getOrCreateDatabase(
|
||||
ctx.getAppPath(TILES_INDEX_DIR).getAbsolutePath() + "/" + name + SQLITE_EXT, false);
|
||||
if (!onlyReadonlyAvailable) {
|
||||
int maxZoom = r.getMaximumZoomSupported();
|
||||
int minZoom = r.getMinimumZoomSupported();
|
||||
|
@ -347,10 +351,10 @@ public class SQLiteTileSource implements ITileSource {
|
|||
if (getUrlTemplate() != null && !getUrlTemplate().equals(r.getUrlTemplate())) {
|
||||
db.execSQL("update info set " + URL + " = '" + r.getUrlTemplate() + "'");
|
||||
}
|
||||
if (r.getMinimumZoomSupported() != minZoom) {
|
||||
if (minZoom != this.minZoom) {
|
||||
db.execSQL("update info set " + MIN_ZOOM + " = '" + minZoom + "'");
|
||||
}
|
||||
if (r.getMaximumZoomSupported() != maxZoom) {
|
||||
if (maxZoom != this.maxZoom) {
|
||||
db.execSQL("update info set " + MAX_ZOOM + " = '" + maxZoom + "'");
|
||||
}
|
||||
if (r.isEllipticYTile() != isEllipticYTile()) {
|
||||
|
|
|
@ -445,12 +445,12 @@ public class MapActivityLayers {
|
|||
|
||||
final String layerOsmVector = "LAYER_OSM_VECTOR";
|
||||
final String layerInstallMore = "LAYER_INSTALL_MORE";
|
||||
final String layerEditInstall = "LAYER_EDIT";
|
||||
final String layerAdd = "LAYER_ADD";
|
||||
|
||||
entriesMap.put(layerOsmVector, getString(R.string.vector_data));
|
||||
entriesMap.putAll(settings.getTileSourceEntries());
|
||||
entriesMap.put(layerInstallMore, getString(R.string.install_more));
|
||||
entriesMap.put(layerEditInstall, getString(R.string.maps_define_edit));
|
||||
entriesMap.put(layerAdd, getString(R.string.shared_string_add));
|
||||
|
||||
final List<Entry<String, String>> entriesMapList = new ArrayList<>(entriesMap.entrySet());
|
||||
|
||||
|
@ -499,26 +499,8 @@ public class MapActivityLayers {
|
|||
updateMapSource(mapView, null);
|
||||
updateItem(it, adapter, null);
|
||||
break;
|
||||
case layerEditInstall:
|
||||
OsmandRasterMapsPlugin.defineNewEditLayer(activity, new ResultMatcher<TileSourceTemplate>() {
|
||||
|
||||
@Override
|
||||
public boolean publish(TileSourceTemplate object) {
|
||||
settings.MAP_TILE_SOURCES.set(object.getName());
|
||||
settings.MAP_ONLINE_DATA.set(true);
|
||||
if(it != null) {
|
||||
it.setDescription(object.getName());
|
||||
}
|
||||
updateMapSource(mapView, settings.MAP_TILE_SOURCES);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}, null);
|
||||
case layerAdd:
|
||||
OsmandRasterMapsPlugin.defineNewEditLayer(activity.getSupportFragmentManager(), null, null);
|
||||
break;
|
||||
case layerInstallMore:
|
||||
OsmandRasterMapsPlugin.installMapLayers(activity, new ResultMatcher<TileSourceTemplate>() {
|
||||
|
|
|
@ -63,6 +63,7 @@ import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents;
|
|||
import net.osmand.plus.download.IndexItem;
|
||||
import net.osmand.plus.helpers.FileNameTranslationHelper;
|
||||
import net.osmand.plus.inapp.InAppPurchaseHelper;
|
||||
import net.osmand.plus.mapsource.EditMapSourceDialogFragment;
|
||||
import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin;
|
||||
import net.osmand.plus.resources.IncrementalChangesManager;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
@ -81,7 +82,7 @@ import java.util.Set;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class LocalIndexesFragment extends OsmandExpandableListFragment implements DownloadEvents {
|
||||
public class LocalIndexesFragment extends OsmandExpandableListFragment implements DownloadEvents, EditMapSourceDialogFragment.OnMapSourceUpdateListener {
|
||||
public static final Pattern ILLEGAL_FILE_NAME_CHARACTERS = Pattern.compile("[?:\"*|/<>]");
|
||||
public static final Pattern ILLEGAL_PATH_NAME_CHARACTERS = Pattern.compile("[?:\"*|<>]");
|
||||
|
||||
|
@ -242,19 +243,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
|
|||
confirm.setMessage(getString(R.string.clear_confirmation_msg, fn));
|
||||
confirm.show();
|
||||
} else if (resId == R.string.shared_string_edit) {
|
||||
OsmandRasterMapsPlugin.defineNewEditLayer(getDownloadActivity(),
|
||||
new ResultMatcher<TileSourceManager.TileSourceTemplate>() {
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean publish(TileSourceManager.TileSourceTemplate object) {
|
||||
getDownloadActivity().reloadLocalIndexes();
|
||||
return true;
|
||||
}
|
||||
}, info.getFileName());
|
||||
OsmandRasterMapsPlugin.defineNewEditLayer(getDownloadActivity().getSupportFragmentManager(), this, info.getFileName());
|
||||
} else if (resId == R.string.local_index_mi_restore) {
|
||||
new LocalIndexOperationTask(getDownloadActivity(), listAdapter, LocalIndexOperationTask.RESTORE_OPERATION).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, info);
|
||||
} else if (resId == R.string.shared_string_delete) {
|
||||
|
@ -339,7 +328,7 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
|
|||
}
|
||||
}
|
||||
|
||||
private static File renameSQLiteFile(OsmandApplication ctx, File source, String newName,
|
||||
public static File renameSQLiteFile(OsmandApplication ctx, File source, String newName,
|
||||
RenameCallback callback) {
|
||||
File dest = checkRenamePossibility(ctx, source, newName, false);
|
||||
if (dest == null) {
|
||||
|
@ -405,6 +394,10 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
|
|||
return dest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapSourceUpdated() {
|
||||
getDownloadActivity().reloadLocalIndexes();
|
||||
}
|
||||
|
||||
public class LoadLocalIndexTask extends AsyncTask<Void, LocalIndexInfo, List<LocalIndexInfo>>
|
||||
implements AbstractLoadLocalIndexTask {
|
||||
|
|
|
@ -0,0 +1,458 @@
|
|||
package net.osmand.plus.mapsource;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.map.TileSourceManager;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.SQLiteTileSource;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.base.BaseOsmAndDialogFragment;
|
||||
import net.osmand.plus.mapsource.InputZoomLevelsBottomSheet.OnZoomSetListener;
|
||||
import net.osmand.plus.mapsource.ExpireTimeBottomSheet.OnExpireValueSetListener;
|
||||
import net.osmand.plus.mapsource.MercatorProjectionBottomSheet.OnMercatorSelectedListener;
|
||||
import net.osmand.plus.mapsource.TileStorageFormatBottomSheet.OnTileStorageFormatSelectedListener;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import static net.osmand.plus.download.ui.LocalIndexesFragment.ILLEGAL_FILE_NAME_CHARACTERS;
|
||||
import static net.osmand.plus.download.ui.LocalIndexesFragment.renameSQLiteFile;
|
||||
|
||||
public class EditMapSourceDialogFragment extends BaseOsmAndDialogFragment
|
||||
implements OnZoomSetListener, OnExpireValueSetListener, OnMercatorSelectedListener,
|
||||
OnTileStorageFormatSelectedListener, View.OnClickListener {
|
||||
|
||||
public static final String TAG = EditMapSourceDialogFragment.class.getName();
|
||||
static final int EXPIRE_TIME_NEVER = -1;
|
||||
private static final Log LOG = PlatformUtil.getLog(EditMapSourceDialogFragment.class);
|
||||
private static final String MAPS_PLUGINS_URL = "https://osmand.net/features/online-maps-plugin";
|
||||
private static final String PNG_EXT = "png";
|
||||
private static final int MAX_ZOOM = 17;
|
||||
private static final int MIN_ZOOM = 5;
|
||||
private static final int TILE_SIZE = 256;
|
||||
private static final int BIT_DENSITY = 16;
|
||||
private static final int AVG_SIZE = 32000;
|
||||
private static final String EDIT_LAYER_NAME_KEY = "edit_layer_name_key";
|
||||
private static final String MIN_ZOOM_KEY = "min_zoom_key";
|
||||
private static final String MAX_ZOOM_KEY = "max_zoom_key";
|
||||
private static final String EXPIRE_TIME_KEY = "expire_time_key";
|
||||
private static final String ELLIPTIC_KEY = "elliptic_key";
|
||||
private static final String SQLITE_DB_KEY = "sqlite_db_key";
|
||||
private OsmandApplication app;
|
||||
private TextInputEditText nameEditText;
|
||||
private TextInputEditText urlEditText;
|
||||
private LinearLayout contentContainer;
|
||||
private FrameLayout saveBtn;
|
||||
private TextView saveBtnTitle;
|
||||
private TileSourceManager.TileSourceTemplate template;
|
||||
@Nullable
|
||||
private String editedLayerName;
|
||||
private String urlToLoad = "";
|
||||
private int minZoom = MIN_ZOOM;
|
||||
private int maxZoom = MAX_ZOOM;
|
||||
private int expireTimeMinutes = EXPIRE_TIME_NEVER;
|
||||
private boolean elliptic = false;
|
||||
private boolean sqliteDB = false;
|
||||
private boolean nightMode;
|
||||
|
||||
public static void showInstance(@NonNull FragmentManager fm,
|
||||
@Nullable Fragment targetFragment,
|
||||
@Nullable String editedLayerName) {
|
||||
EditMapSourceDialogFragment fragment = new EditMapSourceDialogFragment();
|
||||
fragment.setTargetFragment(targetFragment, 0);
|
||||
fragment.setEditedLayerName(editedLayerName);
|
||||
fragment.show(fm, TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
app = getMyApplication();
|
||||
nightMode = !app.getSettings().isLightContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
editedLayerName = savedInstanceState.getString(EDIT_LAYER_NAME_KEY);
|
||||
minZoom = savedInstanceState.getInt(MIN_ZOOM_KEY);
|
||||
maxZoom = savedInstanceState.getInt(MAX_ZOOM_KEY);
|
||||
expireTimeMinutes = savedInstanceState.getInt(EXPIRE_TIME_KEY);
|
||||
elliptic = savedInstanceState.getBoolean(ELLIPTIC_KEY);
|
||||
sqliteDB = savedInstanceState.getBoolean(SQLITE_DB_KEY);
|
||||
}
|
||||
View root = UiUtilities.getMaterialInflater(getContext(), nightMode).inflate(R.layout.fragment_edit_map_source, container, false);
|
||||
Toolbar toolbar = root.findViewById(R.id.toolbar);
|
||||
ImageView iconHelp = root.findViewById(R.id.toolbar_action);
|
||||
Drawable closeDrawable = app.getUIUtilities().getIcon(R.drawable.ic_arrow_back,
|
||||
nightMode ? R.color.active_buttons_and_links_text_dark : R.color.active_buttons_and_links_text_light);
|
||||
Drawable helpDrawable = app.getUIUtilities().getIcon(R.drawable.ic_action_help,
|
||||
nightMode ? R.color.active_buttons_and_links_text_dark : R.color.active_buttons_and_links_text_light);
|
||||
iconHelp.setImageDrawable(helpDrawable);
|
||||
iconHelp.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
onHelpClick();
|
||||
}
|
||||
});
|
||||
toolbar.setNavigationIcon(closeDrawable);
|
||||
toolbar.setNavigationContentDescription(R.string.shared_string_close);
|
||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showExitDialog();
|
||||
}
|
||||
});
|
||||
int boxStrokeColor = nightMode
|
||||
? getResources().getColor(R.color.app_bar_color_light)
|
||||
: getResources().getColor(R.color.active_buttons_and_links_bg_pressed_dark);
|
||||
TextInputLayout nameInputLayout = root.findViewById(R.id.name_input_layout);
|
||||
nameInputLayout.setBoxStrokeColor(boxStrokeColor);
|
||||
nameEditText = root.findViewById(R.id.name_edit_text);
|
||||
TextInputLayout urlInputLayout = root.findViewById(R.id.url_input_layout);
|
||||
urlInputLayout.setBoxStrokeColor(boxStrokeColor);
|
||||
urlEditText = root.findViewById(R.id.url_edit_text);
|
||||
nameEditText.addTextChangedListener(getTextWatcher());
|
||||
urlEditText.addTextChangedListener(getTextWatcher());
|
||||
contentContainer = root.findViewById(R.id.content_container);
|
||||
saveBtn = root.findViewById(R.id.save_button);
|
||||
saveBtnTitle = root.findViewById(R.id.save_button_title);
|
||||
saveBtn.setOnClickListener(this);
|
||||
template = new TileSourceManager.TileSourceTemplate("", "", PNG_EXT, MAX_ZOOM, MIN_ZOOM, TILE_SIZE, BIT_DENSITY, AVG_SIZE);
|
||||
if (editedLayerName != null) {
|
||||
if (!editedLayerName.endsWith(IndexConstants.SQLITE_EXT)) {
|
||||
File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + editedLayerName);
|
||||
template = TileSourceManager.createTileSourceTemplate(f);
|
||||
sqliteDB = false;
|
||||
} else {
|
||||
List<TileSourceManager.TileSourceTemplate> knownTemplates = TileSourceManager.getKnownSourceTemplates();
|
||||
File tPath = app.getAppPath(IndexConstants.TILES_INDEX_DIR);
|
||||
File dir = new File(tPath, editedLayerName);
|
||||
SQLiteTileSource sqLiteTileSource = new SQLiteTileSource(app, dir, knownTemplates);
|
||||
sqLiteTileSource.couldBeDownloadedFromInternet();
|
||||
template = new TileSourceManager.TileSourceTemplate(sqLiteTileSource.getName(),
|
||||
sqLiteTileSource.getUrlTemplate(), PNG_EXT, sqLiteTileSource.getMaximumZoomSupported(),
|
||||
sqLiteTileSource.getMinimumZoomSupported(), sqLiteTileSource.getTileSize(),
|
||||
sqLiteTileSource.getBitDensity(), AVG_SIZE);
|
||||
template.setExpirationTimeMinutes(sqLiteTileSource.getExpirationTimeMinutes());
|
||||
template.setEllipticYTile(sqLiteTileSource.isEllipticYTile());
|
||||
sqliteDB = true;
|
||||
}
|
||||
}
|
||||
if (savedInstanceState == null) {
|
||||
urlToLoad = template.getUrlTemplate();
|
||||
expireTimeMinutes = template.getExpirationTimeMinutes();
|
||||
minZoom = template.getMinimumZoomSupported();
|
||||
maxZoom = template.getMaximumZoomSupported();
|
||||
elliptic = template.isEllipticYTile();
|
||||
}
|
||||
updateUi();
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
outState.putString(EDIT_LAYER_NAME_KEY, editedLayerName);
|
||||
outState.putInt(MIN_ZOOM_KEY, minZoom);
|
||||
outState.putInt(MAX_ZOOM_KEY, maxZoom);
|
||||
outState.putInt(EXPIRE_TIME_KEY, expireTimeMinutes);
|
||||
outState.putBoolean(ELLIPTIC_KEY, elliptic);
|
||||
outState.putBoolean(SQLITE_DB_KEY, sqliteDB);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
Dialog dialog = getDialog();
|
||||
if (dialog != null) {
|
||||
dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
if (keyCode == android.view.KeyEvent.KEYCODE_BACK) {
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
return true;
|
||||
} else {
|
||||
showExitDialog();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onZoomSet(int min, int max) {
|
||||
if (isAdded()) {
|
||||
minZoom = min;
|
||||
maxZoom = max;
|
||||
updateDescription(ConfigurationItem.ZOOM_LEVELS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExpireValueSet(int expireValue) {
|
||||
if (isAdded()) {
|
||||
expireTimeMinutes = expireValue;
|
||||
updateDescription(ConfigurationItem.EXPIRE_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMercatorSelected(boolean elliptic) {
|
||||
if (isAdded()) {
|
||||
this.elliptic = elliptic;
|
||||
updateDescription(ConfigurationItem.MERCATOR_PROJECTION);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStorageFormatSelected(boolean sqliteDb) {
|
||||
if (isAdded()) {
|
||||
this.sqliteDB = sqliteDb;
|
||||
updateDescription(ConfigurationItem.STORAGE_FORMAT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (view.getId() == R.id.save_button) {
|
||||
saveTemplate();
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
private TextWatcher getTextWatcher() {
|
||||
return new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
String s = charSequence.toString();
|
||||
if (Algorithms.isEmpty(s)) {
|
||||
saveBtn.setEnabled(false);
|
||||
saveBtnTitle.setEnabled(false);
|
||||
} else {
|
||||
saveBtn.setEnabled(true);
|
||||
saveBtnTitle.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void saveTemplate() {
|
||||
try {
|
||||
String newName = nameEditText.getText().toString();
|
||||
String urlToLoad = urlEditText.getText().toString();
|
||||
template.setName(newName);
|
||||
template.setUrlToLoad(urlToLoad.isEmpty() ? null : urlToLoad.replace("{$x}", "{1}").replace("{$y}", "{2}").replace("{$z}", "{0}"));
|
||||
template.setMinZoom(minZoom);
|
||||
template.setMaxZoom(maxZoom);
|
||||
template.setEllipticYTile(elliptic);
|
||||
template.setExpirationTimeMinutes(expireTimeMinutes);
|
||||
File f = app.getAppPath(IndexConstants.TILES_INDEX_DIR + editedLayerName);
|
||||
if (f.exists()) {
|
||||
int extIndex = f.getName().lastIndexOf('.');
|
||||
String ext = extIndex == -1 ? "" : f.getName().substring(extIndex);
|
||||
String originalName = extIndex == -1 ? f.getName() : f.getName().substring(0, extIndex);
|
||||
if (!Algorithms.objectEquals(newName, originalName)) {
|
||||
if (IndexConstants.SQLITE_EXT.equals(ext) && sqliteDB) {
|
||||
renameSQLiteFile(app, f, newName, null);
|
||||
} else if (!sqliteDB) {
|
||||
f.renameTo(app.getAppPath(IndexConstants.TILES_INDEX_DIR + newName));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sqliteDB) {
|
||||
if (!f.exists() || f.isDirectory()) {
|
||||
SQLiteTileSource sqLiteTileSource =
|
||||
new SQLiteTileSource(app, newName, minZoom,
|
||||
maxZoom, urlToLoad, "0,1,2,3",
|
||||
elliptic, false, "", expireTimeMinutes > 0,
|
||||
expireTimeMinutes * 60 * 1000L, false, ""
|
||||
);
|
||||
sqLiteTileSource.createDataBase();
|
||||
} else {
|
||||
List<TileSourceManager.TileSourceTemplate> knownTemplates = TileSourceManager.getKnownSourceTemplates();
|
||||
SQLiteTileSource sqLiteTileSource = new SQLiteTileSource(app, f, knownTemplates);
|
||||
sqLiteTileSource.couldBeDownloadedFromInternet();
|
||||
sqLiteTileSource.updateFromTileSourceTemplate(template);
|
||||
}
|
||||
} else {
|
||||
getSettings().installTileSource(template);
|
||||
}
|
||||
Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof OnMapSourceUpdateListener) {
|
||||
((OnMapSourceUpdateListener) fragment).onMapSourceUpdated();
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
LOG.error("Error on saving template " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUi() {
|
||||
nameEditText.setText(editedLayerName != null ? editedLayerName.replace(IndexConstants.SQLITE_EXT, "") : "");
|
||||
urlEditText.setText(urlToLoad);
|
||||
addConfigurationItems(ConfigurationItem.values());
|
||||
}
|
||||
|
||||
private void onHelpClick() {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse(MAPS_PLUGINS_URL));
|
||||
if (AndroidUtils.isIntentSafe(app, i)) {
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
|
||||
private void showExitDialog() {
|
||||
Context themedContext = UiUtilities.getThemedContext(getActivity(), nightMode);
|
||||
AlertDialog.Builder dismissDialog = new AlertDialog.Builder(themedContext);
|
||||
dismissDialog.setTitle(getString(R.string.shared_string_dismiss));
|
||||
dismissDialog.setMessage(getString(R.string.exit_without_saving));
|
||||
dismissDialog.setNegativeButton(R.string.shared_string_cancel, null);
|
||||
dismissDialog.setPositiveButton(R.string.shared_string_exit, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
dismissDialog.show();
|
||||
}
|
||||
|
||||
private String getDescription(ConfigurationItem item) {
|
||||
switch (item) {
|
||||
case ZOOM_LEVELS:
|
||||
String min = getString(R.string.ltr_or_rtl_combine_via_space, getString(R.string.shared_string_min), String.valueOf(minZoom));
|
||||
String max = getString(R.string.ltr_or_rtl_combine_via_space, getString(R.string.shared_string_max), String.valueOf(maxZoom));
|
||||
return getString(R.string.ltr_or_rtl_combine_via_bold_point, min, max);
|
||||
case EXPIRE_TIME:
|
||||
return expireTimeMinutes == EXPIRE_TIME_NEVER
|
||||
? getString(R.string.shared_string_never)
|
||||
: getString(R.string.ltr_or_rtl_combine_via_space, String.valueOf(expireTimeMinutes), getString(R.string.osmand_parking_minute));
|
||||
case MERCATOR_PROJECTION:
|
||||
return elliptic ? getString(R.string.edit_tilesource_elliptic_tile) : getString(R.string.pseudo_mercator_projection);
|
||||
case STORAGE_FORMAT:
|
||||
return sqliteDB ? getString(R.string.sqlite_db_file) : getString(R.string.one_image_per_tile);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private View.OnClickListener getClickListener(final ConfigurationItem item) {
|
||||
return new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
FragmentManager fm = getFragmentManager();
|
||||
if (fm != null) {
|
||||
switch (item) {
|
||||
case ZOOM_LEVELS:
|
||||
InputZoomLevelsBottomSheet.showInstance(
|
||||
fm, EditMapSourceDialogFragment.this,
|
||||
R.string.map_source_zoom_levels, R.string.map_source_zoom_levels_descr,
|
||||
minZoom, maxZoom
|
||||
);
|
||||
break;
|
||||
case EXPIRE_TIME:
|
||||
ExpireTimeBottomSheet.showInstance(fm, EditMapSourceDialogFragment.this, expireTimeMinutes);
|
||||
break;
|
||||
case MERCATOR_PROJECTION:
|
||||
MercatorProjectionBottomSheet.showInstance(fm, EditMapSourceDialogFragment.this, elliptic);
|
||||
break;
|
||||
case STORAGE_FORMAT:
|
||||
TileStorageFormatBottomSheet.showInstance(fm, EditMapSourceDialogFragment.this, sqliteDB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void addConfigurationItems(ConfigurationItem... items) {
|
||||
LayoutInflater inflater = UiUtilities.getMaterialInflater(getContext(), nightMode);
|
||||
for (ConfigurationItem item : items) {
|
||||
View view = inflater.inflate(R.layout.list_item_ui_customization, null);
|
||||
((ImageView) view.findViewById(R.id.icon)).setImageDrawable(app.getUIUtilities().getIcon(item.iconRes, nightMode));
|
||||
((TextView) view.findViewById(R.id.title)).setText(item.titleRes);
|
||||
((TextView) view.findViewById(R.id.sub_title)).setText(getDescription(item));
|
||||
view.setOnClickListener(getClickListener(item));
|
||||
contentContainer.addView(view);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDescription(ConfigurationItem item) {
|
||||
View view = contentContainer.getChildAt(ArrayUtils.indexOf(ConfigurationItem.values(), item));
|
||||
((TextView) view.findViewById(R.id.sub_title)).setText(getDescription(item));
|
||||
}
|
||||
|
||||
private enum ConfigurationItem {
|
||||
ZOOM_LEVELS(R.drawable.ic_action_layers, R.string.shared_string_zoom_levels),
|
||||
EXPIRE_TIME(R.drawable.ic_action_time_span, R.string.expire_time),
|
||||
MERCATOR_PROJECTION(R.drawable.ic_world_globe_dark, R.string.mercator_projection),
|
||||
STORAGE_FORMAT(R.drawable.ic_sdcard, R.string.storage_format);
|
||||
|
||||
@DrawableRes
|
||||
public int iconRes;
|
||||
@StringRes
|
||||
public int titleRes;
|
||||
|
||||
ConfigurationItem(int iconRes, int titleRes) {
|
||||
this.titleRes = titleRes;
|
||||
this.iconRes = iconRes;
|
||||
}
|
||||
}
|
||||
|
||||
private void setEditedLayerName(@Nullable String editedLayerName) {
|
||||
this.editedLayerName = editedLayerName;
|
||||
}
|
||||
|
||||
public interface OnMapSourceUpdateListener {
|
||||
void onMapSourceUpdated();
|
||||
}
|
||||
}
|
119
OsmAnd/src/net/osmand/plus/mapsource/ExpireTimeBottomSheet.java
Normal file
119
OsmAnd/src/net/osmand/plus/mapsource/ExpireTimeBottomSheet.java
Normal file
|
@ -0,0 +1,119 @@
|
|||
package net.osmand.plus.mapsource;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import static net.osmand.plus.mapsource.EditMapSourceDialogFragment.EXPIRE_TIME_NEVER;
|
||||
|
||||
public class ExpireTimeBottomSheet extends MenuBottomSheetDialogFragment {
|
||||
|
||||
public static final String TAG = ExpireTimeBottomSheet.class.getName();
|
||||
private static final Log LOG = PlatformUtil.getLog(ExpireTimeBottomSheet.class);
|
||||
private static final String EXPIRE_VALUE_KEY = "expire_value_key";
|
||||
private int expireValue;
|
||||
private TextInputEditText editText;
|
||||
|
||||
public static void showInstance(@NonNull FragmentManager fm,
|
||||
@Nullable Fragment targetFragment,
|
||||
int expireValue) {
|
||||
ExpireTimeBottomSheet bottomSheet = new ExpireTimeBottomSheet();
|
||||
bottomSheet.setTargetFragment(targetFragment, 0);
|
||||
bottomSheet.setExpireValue(expireValue);
|
||||
bottomSheet.show(fm, TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMenuItems(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
expireValue = savedInstanceState.getInt(EXPIRE_VALUE_KEY, EXPIRE_TIME_NEVER);
|
||||
}
|
||||
LayoutInflater inflater = UiUtilities.getMaterialInflater(getContext(), nightMode);
|
||||
TitleItem titleItem = new TitleItem(getString(R.string.expire_time));
|
||||
items.add(titleItem);
|
||||
final View inputValueLayout = inflater.inflate(R.layout.edit_text_with_descr, null);
|
||||
((TextView) inputValueLayout.findViewById(R.id.dialog_descr)).setText(R.string.expire_time_descr);
|
||||
editText = inputValueLayout.findViewById(R.id.value_edit_text);
|
||||
if (expireValue > 0) {
|
||||
editText.setText(String.valueOf(expireValue));
|
||||
}
|
||||
int boxStrokeColor = nightMode
|
||||
? getResources().getColor(R.color.app_bar_color_light)
|
||||
: getResources().getColor(R.color.active_buttons_and_links_bg_pressed_dark);
|
||||
TextInputLayout textInputLayout = inputValueLayout.findViewById(R.id.value_input_layout);
|
||||
textInputLayout.setBoxStrokeColor(boxStrokeColor);
|
||||
final SimpleBottomSheetItem editTextItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder()
|
||||
.setCustomView(inputValueLayout)
|
||||
.create();
|
||||
items.add(editTextItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putLong(EXPIRE_VALUE_KEY, getExpireValue());
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRightBottomButtonClick() {
|
||||
super.onRightBottomButtonClick();
|
||||
Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof OnExpireValueSetListener) {
|
||||
((OnExpireValueSetListener) fragment).onExpireValueSet(getExpireValue());
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDismissButtonTextId() {
|
||||
return R.string.shared_string_cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRightBottomButtonTextId() {
|
||||
return R.string.shared_string_apply;
|
||||
}
|
||||
|
||||
private int getExpireValue() {
|
||||
int expireValue = EXPIRE_TIME_NEVER;
|
||||
if (editText.getText() != null) {
|
||||
String value = editText.getText().toString();
|
||||
if (!Algorithms.isEmpty(value)) {
|
||||
try {
|
||||
expireValue = Integer.parseInt(value);
|
||||
} catch (RuntimeException e) {
|
||||
LOG.error("Error parsing expire value: " + expireValue + " " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return expireValue > 0 ? expireValue : EXPIRE_TIME_NEVER;
|
||||
}
|
||||
|
||||
private void setExpireValue(int expireValue) {
|
||||
this.expireValue = expireValue;
|
||||
}
|
||||
|
||||
public interface OnExpireValueSetListener {
|
||||
void onExpireValueSet(int expireValue);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
package net.osmand.plus.mapsource;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.google.android.material.slider.Slider;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.widgets.style.CustomTypefaceSpan;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class InputZoomLevelsBottomSheet extends MenuBottomSheetDialogFragment {
|
||||
|
||||
public static final String TAG = InputZoomLevelsBottomSheet.class.getName();
|
||||
private static final Log LOG = PlatformUtil.getLog(InputZoomLevelsBottomSheet.class);
|
||||
private static final String MIN_ZOOM_KEY = "min_zoom_key";
|
||||
private static final String MAX_ZOOM_KEY = "max_zoom_key";
|
||||
private static final String SLIDER_DESCR_RES_KEY = "slider_descr_key";
|
||||
private static final String DIALOG_DESCR_RES_KEY = "dialog_descr_key";
|
||||
private static final int SLIDER_FROM = 1;
|
||||
private static final int SLIDER_TO = 20;
|
||||
@StringRes
|
||||
private int sliderDescrRes;
|
||||
@StringRes
|
||||
private int dialogDescrRes;
|
||||
private int minZoom;
|
||||
private int maxZoom;
|
||||
|
||||
public static void showInstance(@NonNull FragmentManager fm,
|
||||
@Nullable Fragment targetFragment,
|
||||
int sliderDescr,
|
||||
int dialogDescr,
|
||||
int minZoom,
|
||||
int maxZoom) {
|
||||
InputZoomLevelsBottomSheet bottomSheet = new InputZoomLevelsBottomSheet();
|
||||
bottomSheet.setTargetFragment(targetFragment, 0);
|
||||
bottomSheet.setSliderDescrRes(sliderDescr);
|
||||
bottomSheet.setDialogDescrRes(dialogDescr);
|
||||
bottomSheet.setMinZoom(Math.max(minZoom, SLIDER_FROM));
|
||||
bottomSheet.setMaxZoom(Math.min(maxZoom, SLIDER_TO));
|
||||
bottomSheet.show(fm, TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMenuItems(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
minZoom = savedInstanceState.getInt(MIN_ZOOM_KEY);
|
||||
maxZoom = savedInstanceState.getInt(MAX_ZOOM_KEY);
|
||||
dialogDescrRes = savedInstanceState.getInt(DIALOG_DESCR_RES_KEY);
|
||||
sliderDescrRes = savedInstanceState.getInt(SLIDER_DESCR_RES_KEY);
|
||||
}
|
||||
LayoutInflater inflater = UiUtilities.getInflater(requiredMyApplication(), nightMode);
|
||||
TitleItem titleItem = new TitleItem(getString(R.string.shared_string_zoom_levels));
|
||||
items.add(titleItem);
|
||||
final View sliderView = inflater.inflate(R.layout.zoom_levels_with_descr, null);
|
||||
((TextView) sliderView.findViewById(R.id.slider_descr)).setText(sliderDescrRes);
|
||||
TextView dialogDescrTv = sliderView.findViewById(R.id.dialog_descr);
|
||||
if (dialogDescrRes == R.string.map_source_zoom_levels_descr) {
|
||||
String mapSource = getString(R.string.map_source);
|
||||
String overlayUnderlay = getString(R.string.pref_overlay);
|
||||
String dialogDesr = getString(dialogDescrRes, mapSource, overlayUnderlay);
|
||||
dialogDescrTv.setText(createSpannableString(dialogDesr, mapSource, overlayUnderlay));
|
||||
} else {
|
||||
dialogDescrTv.setText(getString(dialogDescrRes));
|
||||
}
|
||||
final TextView minZoomValue = sliderView.findViewById(R.id.zoom_value_min);
|
||||
minZoomValue.setText(String.valueOf(minZoom));
|
||||
final TextView maxZoomValue = sliderView.findViewById(R.id.zoom_value_max);
|
||||
maxZoomValue.setText(String.valueOf(maxZoom));
|
||||
Slider slider = sliderView.findViewById(R.id.zoom_slider);
|
||||
int colorProfileRes = requiredMyApplication().getSettings().getApplicationMode().getIconColorInfo().getColor(nightMode);
|
||||
int colorProfile = ContextCompat.getColor(requiredMyApplication(), colorProfileRes);
|
||||
UiUtilities.setupSlider(slider, nightMode, colorProfile, true);
|
||||
slider.setValueFrom(SLIDER_FROM);
|
||||
slider.setValueTo(SLIDER_TO);
|
||||
slider.setValues((float) minZoom, (float) maxZoom);
|
||||
slider.addOnChangeListener(new Slider.OnChangeListener() {
|
||||
@Override
|
||||
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
|
||||
List<Float> values = slider.getValues();
|
||||
if (values.size() > 0) {
|
||||
minZoomValue.setText(String.valueOf(values.get(0).intValue()));
|
||||
maxZoomValue.setText(String.valueOf(values.get(1).intValue()));
|
||||
}
|
||||
}
|
||||
});
|
||||
slider.addOnSliderTouchListener(new Slider.OnSliderTouchListener() {
|
||||
@Override
|
||||
public void onStartTrackingTouch(@NonNull Slider slider) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(@NonNull Slider slider) {
|
||||
List<Float> values = slider.getValues();
|
||||
if (values.size() > 0) {
|
||||
minZoom = values.get(0).intValue();
|
||||
maxZoom = values.get(1).intValue();
|
||||
}
|
||||
}
|
||||
});
|
||||
final SimpleBottomSheetItem sliderItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder()
|
||||
.setCustomView(sliderView)
|
||||
.create();
|
||||
items.add(sliderItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putInt(MIN_ZOOM_KEY, minZoom);
|
||||
outState.putInt(MAX_ZOOM_KEY, maxZoom);
|
||||
outState.putInt(SLIDER_DESCR_RES_KEY, sliderDescrRes);
|
||||
outState.putInt(DIALOG_DESCR_RES_KEY, dialogDescrRes);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRightBottomButtonClick() {
|
||||
super.onRightBottomButtonClick();
|
||||
Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof OnZoomSetListener) {
|
||||
((OnZoomSetListener) fragment).onZoomSet(minZoom, maxZoom);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDismissButtonTextId() {
|
||||
return R.string.shared_string_cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRightBottomButtonTextId() {
|
||||
return R.string.shared_string_apply;
|
||||
}
|
||||
|
||||
private SpannableString createSpannableString(@NonNull String text, @NonNull String... textToStyle) {
|
||||
SpannableString spannable = new SpannableString(text);
|
||||
for (String t : textToStyle) {
|
||||
try {
|
||||
int startIndex = text.indexOf(t);
|
||||
spannable.setSpan(
|
||||
new CustomTypefaceSpan(FontCache.getRobotoMedium(requireContext())),
|
||||
startIndex,
|
||||
startIndex + t.length(),
|
||||
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
} catch (RuntimeException e) {
|
||||
LOG.error("Error trying to find index of " + t + " " + e);
|
||||
}
|
||||
}
|
||||
return spannable;
|
||||
}
|
||||
|
||||
private void setSliderDescrRes(int sliderDescrRes) {
|
||||
this.sliderDescrRes = sliderDescrRes;
|
||||
}
|
||||
|
||||
private void setDialogDescrRes(int dialogDescrRes) {
|
||||
this.dialogDescrRes = dialogDescrRes;
|
||||
}
|
||||
|
||||
private void setMinZoom(int minZoom) {
|
||||
this.minZoom = minZoom;
|
||||
}
|
||||
|
||||
private void setMaxZoom(int maxZoom) {
|
||||
this.maxZoom = maxZoom;
|
||||
}
|
||||
|
||||
public interface OnZoomSetListener {
|
||||
void onZoomSet(int min, int max);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package net.osmand.plus.mapsource;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.widget.NestedScrollView;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||
|
||||
public class MercatorProjectionBottomSheet extends MenuBottomSheetDialogFragment {
|
||||
|
||||
public static final String TAG = MercatorProjectionBottomSheet.class.getName();
|
||||
private static final String ELLIPTIC_KEY = "elliptic_key";
|
||||
private LinearLayout valuesContainer;
|
||||
private MercatorProjection mercatorProjection;
|
||||
|
||||
public static void showInstance(@NonNull FragmentManager fm,
|
||||
@Nullable Fragment targetFragment,
|
||||
boolean elliptic) {
|
||||
MercatorProjectionBottomSheet bottomSheet = new MercatorProjectionBottomSheet();
|
||||
bottomSheet.setTargetFragment(targetFragment, 0);
|
||||
bottomSheet.setMercatorProjection(elliptic);
|
||||
bottomSheet.show(fm, TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMenuItems(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
setMercatorProjection(savedInstanceState.getBoolean(ELLIPTIC_KEY));
|
||||
}
|
||||
Context context = requireContext();
|
||||
TitleItem titleItem = new TitleItem(getString(R.string.mercator_projection));
|
||||
items.add(titleItem);
|
||||
NestedScrollView nestedScrollView = new NestedScrollView(context);
|
||||
valuesContainer = new LinearLayout(context);
|
||||
valuesContainer.setLayoutParams((new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)));
|
||||
valuesContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
valuesContainer.setPadding(0, getResources().getDimensionPixelSize(R.dimen.bottom_sheet_content_padding_small), 0, 0);
|
||||
for (int i = 0; i < MercatorProjection.values().length; i++) {
|
||||
LayoutInflater.from(new ContextThemeWrapper(context, themeRes))
|
||||
.inflate(R.layout.bottom_sheet_item_with_radio_btn_left, valuesContainer, true);
|
||||
}
|
||||
nestedScrollView.addView(valuesContainer);
|
||||
items.add(new BaseBottomSheetItem.Builder().setCustomView(nestedScrollView).create());
|
||||
populateValuesList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putBoolean(ELLIPTIC_KEY, mercatorProjection == MercatorProjection.ELLIPTIC);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(@NonNull DialogInterface dialog) {
|
||||
Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof OnMercatorSelectedListener) {
|
||||
((OnMercatorSelectedListener) fragment).onMercatorSelected(mercatorProjection == MercatorProjection.ELLIPTIC);
|
||||
}
|
||||
super.onDismiss(dialog);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDismissButtonTextId() {
|
||||
return R.string.shared_string_close;
|
||||
}
|
||||
|
||||
private void populateValuesList() {
|
||||
for (int i = 0; i < MercatorProjection.values().length; i++) {
|
||||
final MercatorProjection m = MercatorProjection.values()[i];
|
||||
boolean selected = mercatorProjection == m;
|
||||
View view = valuesContainer.getChildAt(i);
|
||||
((CompoundButton) view.findViewById(R.id.compound_button)).setChecked(selected);
|
||||
((TextView) view.findViewById(R.id.title)).setText(m.titleRes);
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
mercatorProjection = m;
|
||||
populateValuesList();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void setMercatorProjection(boolean elliptic) {
|
||||
mercatorProjection = elliptic ? MercatorProjection.ELLIPTIC : MercatorProjection.PSEUDO;
|
||||
}
|
||||
|
||||
public enum MercatorProjection {
|
||||
ELLIPTIC(R.string.edit_tilesource_elliptic_tile),
|
||||
PSEUDO(R.string.pseudo_mercator_projection);
|
||||
|
||||
@StringRes
|
||||
public int titleRes;
|
||||
|
||||
MercatorProjection(@StringRes int titleRes) {
|
||||
this.titleRes = titleRes;
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnMercatorSelectedListener {
|
||||
void onMercatorSelected(boolean elliptic);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package net.osmand.plus.mapsource;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.widget.NestedScrollView;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||
|
||||
public class TileStorageFormatBottomSheet extends MenuBottomSheetDialogFragment {
|
||||
|
||||
public static final String TAG = TileStorageFormatBottomSheet.class.getName();
|
||||
private static final String SQLITE_DB_KEY = "sqlite_db_key";
|
||||
private LinearLayout valuesContainer;
|
||||
private TileStorageFormat tileStorageFormat;
|
||||
|
||||
public static void showInstance(@NonNull FragmentManager fm,
|
||||
@Nullable Fragment targetFragment,
|
||||
boolean sqliteDb) {
|
||||
TileStorageFormatBottomSheet bottomSheet = new TileStorageFormatBottomSheet();
|
||||
bottomSheet.setTargetFragment(targetFragment, 0);
|
||||
bottomSheet.setTileStorageFormat(sqliteDb);
|
||||
bottomSheet.show(fm, TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMenuItems(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
setTileStorageFormat(savedInstanceState.getBoolean(SQLITE_DB_KEY));
|
||||
}
|
||||
Context context = requireContext();
|
||||
TitleItem titleItem = new TitleItem(getString(R.string.mercator_projection));
|
||||
items.add(titleItem);
|
||||
NestedScrollView nestedScrollView = new NestedScrollView(context);
|
||||
valuesContainer = new LinearLayout(context);
|
||||
valuesContainer.setLayoutParams((new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)));
|
||||
valuesContainer.setOrientation(LinearLayout.VERTICAL);
|
||||
valuesContainer.setPadding(0, getResources().getDimensionPixelSize(R.dimen.bottom_sheet_content_padding_small), 0, 0);
|
||||
for (int i = 0; i < TileStorageFormat.values().length; i++) {
|
||||
LayoutInflater.from(new ContextThemeWrapper(context, themeRes))
|
||||
.inflate(R.layout.bottom_sheet_item_with_radio_btn_left, valuesContainer, true);
|
||||
}
|
||||
nestedScrollView.addView(valuesContainer);
|
||||
items.add(new BaseBottomSheetItem.Builder().setCustomView(nestedScrollView).create());
|
||||
populateValuesList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putBoolean(SQLITE_DB_KEY, tileStorageFormat == TileStorageFormat.SQLITE_DB);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(@NonNull DialogInterface dialog) {
|
||||
Fragment fragment = getTargetFragment();
|
||||
if (fragment instanceof OnTileStorageFormatSelectedListener) {
|
||||
((OnTileStorageFormatSelectedListener) fragment).onStorageFormatSelected(tileStorageFormat == TileStorageFormat.SQLITE_DB);
|
||||
}
|
||||
super.onDismiss(dialog);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDismissButtonTextId() {
|
||||
return R.string.shared_string_close;
|
||||
}
|
||||
|
||||
private void populateValuesList() {
|
||||
for (int i = 0; i < TileStorageFormat.values().length; i++) {
|
||||
final TileStorageFormat m = TileStorageFormat.values()[i];
|
||||
boolean selected = tileStorageFormat == m;
|
||||
View view = valuesContainer.getChildAt(i);
|
||||
((CompoundButton) view.findViewById(R.id.compound_button)).setChecked(selected);
|
||||
((TextView) view.findViewById(R.id.title)).setText(m.titleRes);
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
tileStorageFormat = m;
|
||||
populateValuesList();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void setTileStorageFormat(boolean sqliteDb) {
|
||||
tileStorageFormat = sqliteDb ? TileStorageFormat.SQLITE_DB : TileStorageFormat.ONE_IMAGE_PER_TILE;
|
||||
}
|
||||
|
||||
public enum TileStorageFormat {
|
||||
ONE_IMAGE_PER_TILE(R.string.one_image_per_tile),
|
||||
SQLITE_DB(R.string.sqlite_db_file);
|
||||
|
||||
@StringRes
|
||||
public int titleRes;
|
||||
|
||||
TileStorageFormat(@StringRes int titleRes) {
|
||||
this.titleRes = titleRes;
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnTileStorageFormatSelectedListener {
|
||||
void onStorageFormatSelected(boolean sqliteDb);
|
||||
}
|
||||
}
|
|
@ -6,23 +6,17 @@ import android.graphics.drawable.Drawable;
|
|||
import android.os.AsyncTask;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.AppCompatCheckBox;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.StateChangedListener;
|
||||
import net.osmand.map.ITileSource;
|
||||
|
@ -38,10 +32,9 @@ import net.osmand.plus.settings.backend.OsmandSettings;
|
|||
import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings.LayerTransparencySeekbarMode;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.SQLiteTileSource;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.activities.DownloadTilesDialog;
|
||||
import net.osmand.plus.mapsource.EditMapSourceDialogFragment;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.MapActivityLayers;
|
||||
import net.osmand.plus.dashboard.DashboardOnMap.DashboardType;
|
||||
|
@ -51,7 +44,6 @@ import net.osmand.plus.views.MapTileLayer;
|
|||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -61,7 +53,6 @@ import static net.osmand.aidlapi.OsmAndCustomizationConstants.MAP_CONTEXT_MENU_U
|
|||
import static net.osmand.aidlapi.OsmAndCustomizationConstants.OVERLAY_MAP;
|
||||
import static net.osmand.aidlapi.OsmAndCustomizationConstants.UNDERLAY_MAP;
|
||||
import static net.osmand.plus.ContextMenuAdapter.makeDeleteAction;
|
||||
import static net.osmand.plus.UiUtilities.CompoundButtonType.PROFILE_DEPENDENT;
|
||||
|
||||
public class OsmandRasterMapsPlugin extends OsmandPlugin {
|
||||
|
||||
|
@ -483,133 +474,8 @@ public class OsmandRasterMapsPlugin extends OsmandPlugin {
|
|||
t.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public static void defineNewEditLayer(final Activity activity, final ResultMatcher<TileSourceTemplate> resultMatcher, final String editedLayerName) {
|
||||
final OsmandApplication app = (OsmandApplication) activity.getApplication();
|
||||
final OsmandSettings settings = app.getSettings();
|
||||
final Map<String, String> entriesMap = settings.getTileSourceEntries(true);
|
||||
final SQLiteTileSource[] sqLiteTileSource = new SQLiteTileSource[1];
|
||||
boolean nightMode = isNightMode(activity, app);
|
||||
final int dp8 = AndroidUtils.dpToPx(app, 8f);
|
||||
int textColorPrimary = ContextCompat.getColor(app, nightMode ? R.color.text_color_primary_dark : R.color.text_color_primary_light);
|
||||
TileSourceTemplate ts = new TileSourceTemplate("NewMapnik", "http://mapnik.osmand.net/{0}/{1}/{2}.png",
|
||||
"png", 17, 5, 256, 16, 32000);
|
||||
final TileSourceTemplate[] result = new TileSourceTemplate[]{ts};
|
||||
AlertDialog.Builder bld = new AlertDialog.Builder(new ContextThemeWrapper(activity, getThemeRes(activity, app)));
|
||||
View view = UiUtilities.getInflater(activity, isNightMode(activity, app)).inflate(R.layout.editing_tile_source, null);
|
||||
final EditText name = (EditText) view.findViewById(R.id.Name);
|
||||
final Spinner existing = (Spinner) view.findViewById(R.id.TileSourceSpinner);
|
||||
final TextView existingHint = (TextView) view.findViewById(R.id.TileSourceHint);
|
||||
final EditText urlToLoad = (EditText) view.findViewById(R.id.URLToLoad);
|
||||
final EditText minZoom = (EditText) view.findViewById(R.id.MinZoom);
|
||||
final EditText maxZoom = (EditText) view.findViewById(R.id.MaxZoom);
|
||||
final EditText expire = (EditText) view.findViewById(R.id.ExpirationTime);
|
||||
final AppCompatCheckBox elliptic = (AppCompatCheckBox) view.findViewById(R.id.EllipticMercator);
|
||||
elliptic.setTextColor(textColorPrimary);
|
||||
elliptic.setPadding(dp8, 0, 0, 0);
|
||||
UiUtilities.setupCompoundButton(elliptic, nightMode, PROFILE_DEPENDENT);
|
||||
updateTileSourceEditView(ts, name, urlToLoad, minZoom, maxZoom, expire, elliptic);
|
||||
|
||||
final ArrayList<String> templates = new ArrayList<>(entriesMap.keySet());
|
||||
templates.add(0, "");
|
||||
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(view.getContext(),
|
||||
android.R.layout.simple_spinner_item,
|
||||
templates
|
||||
);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
existing.setAdapter(adapter);
|
||||
TileSourceTemplate template;
|
||||
if (editedLayerName != null) {
|
||||
name.setFocusable(false);
|
||||
name.setFocusableInTouchMode(false);
|
||||
if (!editedLayerName.endsWith(IndexConstants.SQLITE_EXT)) {
|
||||
File f = ((OsmandApplication) activity.getApplication()).getAppPath(
|
||||
IndexConstants.TILES_INDEX_DIR + editedLayerName);
|
||||
template = TileSourceManager.createTileSourceTemplate(f);
|
||||
} else {
|
||||
List<TileSourceTemplate> knownTemplates = TileSourceManager.getKnownSourceTemplates();
|
||||
File tPath = app.getAppPath(IndexConstants.TILES_INDEX_DIR);
|
||||
File dir = new File(tPath, editedLayerName);
|
||||
sqLiteTileSource[0] = new SQLiteTileSource(app, dir, knownTemplates);
|
||||
sqLiteTileSource[0].couldBeDownloadedFromInternet();
|
||||
template = new TileSourceManager.TileSourceTemplate(sqLiteTileSource[0].getName(),
|
||||
sqLiteTileSource[0].getUrlTemplate(), "png", sqLiteTileSource[0].getMaximumZoomSupported(),
|
||||
sqLiteTileSource[0].getMinimumZoomSupported(), sqLiteTileSource[0].getTileSize(),
|
||||
sqLiteTileSource[0].getBitDensity(), 32000);
|
||||
template.setExpirationTimeMinutes(sqLiteTileSource[0].getExpirationTimeMinutes());
|
||||
template.setEllipticYTile(sqLiteTileSource[0].isEllipticYTile());
|
||||
}
|
||||
if (template != null) {
|
||||
result[0] = template.copy();
|
||||
updateTileSourceEditView(result[0], name, urlToLoad, minZoom, maxZoom, expire, elliptic);
|
||||
}
|
||||
existingHint.setVisibility(View.GONE);
|
||||
existing.setVisibility(View.GONE);
|
||||
}
|
||||
existing.setSelection(0);
|
||||
existing.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (position > 0) {
|
||||
File f = ((OsmandApplication) activity.getApplication()).getAppPath(IndexConstants.TILES_INDEX_DIR + templates.get(position));
|
||||
TileSourceTemplate template = TileSourceManager.createTileSourceTemplate(f);
|
||||
if (template != null) {
|
||||
result[0] = template.copy();
|
||||
updateTileSourceEditView(result[0], name, urlToLoad, minZoom, maxZoom, expire, elliptic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
}
|
||||
});
|
||||
|
||||
bld.setView(view);
|
||||
bld.setPositiveButton(R.string.shared_string_save, new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
TileSourceTemplate r = result[0];
|
||||
try {
|
||||
r.setName(name.getText().toString());
|
||||
r.setExpirationTimeMinutes(expire.getText().length() == 0 ? -1 :
|
||||
Integer.parseInt(expire.getText().toString()));
|
||||
r.setMinZoom(Integer.parseInt(minZoom.getText().toString()));
|
||||
r.setMaxZoom(Integer.parseInt(maxZoom.getText().toString()));
|
||||
r.setEllipticYTile(elliptic.isChecked());
|
||||
r.setUrlToLoad(urlToLoad.getText().toString().equals("") ? null : urlToLoad.getText().toString().replace("{$x}", "{1}")
|
||||
.replace("{$y}", "{2}").replace("{$z}", "{0}"));
|
||||
if (sqLiteTileSource[0] != null) {
|
||||
sqLiteTileSource[0].updateFromTileSourceTemplate(r);
|
||||
} else {
|
||||
if (r.getName().length() > 0) {
|
||||
if (settings.installTileSource(r)) {
|
||||
Toast.makeText(activity, activity.getString(R.string.edit_tilesource_successfully, r.getName()),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
resultMatcher.publish(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
Toast.makeText(activity, e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
bld.setNegativeButton(R.string.shared_string_cancel, null);
|
||||
bld.show();
|
||||
}
|
||||
|
||||
private static void updateTileSourceEditView(TileSourceTemplate ts, EditText name, final EditText urlToLoad, final EditText minZoom,
|
||||
final EditText maxZoom, EditText expire, final CheckBox elliptic) {
|
||||
minZoom.setText(String.valueOf(ts.getMinimumZoomSupported()));
|
||||
maxZoom.setText(String.valueOf(ts.getMaximumZoomSupported()));
|
||||
name.setText(ts.getName());
|
||||
expire.setText(ts.getExpirationTimeMinutes() < 0 ? "" : ts.getExpirationTimeMinutes() + "");
|
||||
urlToLoad.setText(ts.getUrlTemplate() == null ? "" :
|
||||
ts.getUrlTemplate().replace("{$x}", "{1}").replace("{$y}", "{2}").replace("{$z}", "{0}"));
|
||||
elliptic.setChecked(ts.isEllipticYTile());
|
||||
public static void defineNewEditLayer(@NonNull FragmentManager fm, @Nullable Fragment targetFragment, @Nullable String editedLayerName) {
|
||||
EditMapSourceDialogFragment.showInstance(fm, targetFragment, editedLayerName);
|
||||
}
|
||||
|
||||
public MapTileLayer getUnderlayLayer() {
|
||||
|
|
Loading…
Reference in a new issue