Merge branch 'master' of https://github.com/osmandapp/Osmand
|
@ -69,4 +69,5 @@ public class IndexConstants {
|
|||
public static final String ROUTING_XML_FILE= "routing.xml";
|
||||
public static final String SETTINGS_DIR = "settings/"; //$NON-NLS-1$
|
||||
public static final String TEMP_DIR = "temp/";
|
||||
public static final String ROUTING_PROFILES_DIR = "routing/";
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ public class GeneralRouter implements VehicleRouter {
|
|||
private boolean shortestRoute;
|
||||
private boolean heightObstacles;
|
||||
private boolean allowPrivate;
|
||||
private String filename = null;
|
||||
private String profileName = "";
|
||||
|
||||
private Map<RouteRegion, Map<Integer, Integer>> regionConvert = new LinkedHashMap<RouteRegion, Map<Integer,Integer>>();
|
||||
|
||||
|
@ -119,7 +121,23 @@ public class GeneralRouter implements VehicleRouter {
|
|||
ruleToValue = new ArrayList<Object>();
|
||||
parameters = new LinkedHashMap<String, GeneralRouter.RoutingParameter>();
|
||||
}
|
||||
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public String getProfileName() {
|
||||
return profileName;
|
||||
}
|
||||
|
||||
public void setProfileName(String profileName) {
|
||||
this.profileName = profileName;
|
||||
}
|
||||
|
||||
public GeneralRouter(GeneralRouter parent, Map<String, String> params) {
|
||||
this.profile = parent.profile;
|
||||
this.attributes = new LinkedHashMap<String, String>();
|
||||
|
|
|
@ -19,7 +19,7 @@ import java.util.Map;
|
|||
import java.util.Stack;
|
||||
|
||||
public class RoutingConfiguration {
|
||||
|
||||
|
||||
public static final int DEFAULT_MEMORY_LIMIT = 30;
|
||||
public final float DEVIATION_RADIUS = 3000;
|
||||
public Map<String, String> attributes = new LinkedHashMap<String, String>();
|
||||
|
@ -46,14 +46,13 @@ public class RoutingConfiguration {
|
|||
|
||||
// 1.5 Recalculate distance help
|
||||
public float recalculateDistance = 20000f;
|
||||
|
||||
|
||||
public static class Builder {
|
||||
// Design time storage
|
||||
private String defaultRouter = "";
|
||||
private Map<String, GeneralRouter> routers = new LinkedHashMap<String, GeneralRouter>();
|
||||
private Map<String, String> attributes = new LinkedHashMap<String, String>();
|
||||
private HashMap<Long, Location> impassableRoadLocations = new HashMap<Long, Location>();
|
||||
private Map<String, GeneralRouter> routers = new LinkedHashMap<>();
|
||||
private Map<String, String> attributes = new LinkedHashMap<>();
|
||||
private HashMap<Long, Location> impassableRoadLocations = new HashMap<>();
|
||||
|
||||
// Example
|
||||
// {
|
||||
|
@ -125,12 +124,16 @@ public class RoutingConfiguration {
|
|||
public String getDefaultRouter() {
|
||||
return defaultRouter;
|
||||
}
|
||||
|
||||
public GeneralRouter getRouter(String applicationMode) {
|
||||
return routers.get(applicationMode);
|
||||
|
||||
public GeneralRouter getRouter(String routingProfileName) {
|
||||
return routers.get(routingProfileName);
|
||||
|
||||
}
|
||||
|
||||
public Map<String, GeneralRouter> getAllRouters() {
|
||||
return routers;
|
||||
}
|
||||
|
||||
public void removeImpassableRoad(RouteDataObject obj) {
|
||||
impassableRoadLocations.remove(obj.id);
|
||||
}
|
||||
|
@ -164,10 +167,13 @@ public class RoutingConfiguration {
|
|||
}
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
public static RoutingConfiguration.Builder parseFromInputStream(InputStream is) throws IOException, XmlPullParserException {
|
||||
return parseFromInputStream(is, null, new RoutingConfiguration.Builder());
|
||||
}
|
||||
|
||||
public static RoutingConfiguration.Builder parseFromInputStream(InputStream is, String filename, RoutingConfiguration.Builder config) throws IOException, XmlPullParserException {
|
||||
XmlPullParser parser = PlatformUtil.newXMLPullParser();
|
||||
final RoutingConfiguration.Builder config = new RoutingConfiguration.Builder();
|
||||
GeneralRouter currentRouter = null;
|
||||
RouteDataObjectAttribute currentAttribute = null;
|
||||
String preType = null;
|
||||
|
@ -180,7 +186,7 @@ public class RoutingConfiguration {
|
|||
if ("osmand_routing_config".equals(name)) {
|
||||
config.defaultRouter = parser.getAttributeValue("", "defaultProfile");
|
||||
} else if ("routingProfile".equals(name)) {
|
||||
currentRouter = parseRoutingProfile(parser, config);
|
||||
currentRouter = parseRoutingProfile(parser, config, filename);
|
||||
} else if ("attribute".equals(name)) {
|
||||
parseAttribute(parser, config, currentRouter);
|
||||
} else if ("parameter".equals(name)) {
|
||||
|
@ -295,10 +301,8 @@ public class RoutingConfiguration {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static GeneralRouter parseRoutingProfile(XmlPullParser parser, final RoutingConfiguration.Builder config) {
|
||||
String currentSelectedRouter = parser.getAttributeValue("", "name");
|
||||
private static GeneralRouter parseRoutingProfile(XmlPullParser parser, final RoutingConfiguration.Builder config, String filename) {
|
||||
String currentSelectedRouterName = parser.getAttributeValue("", "name");
|
||||
Map<String, String> attrs = new LinkedHashMap<String, String>();
|
||||
for(int i=0; i< parser.getAttributeCount(); i++) {
|
||||
attrs.put(parser.getAttributeName(i), parser.getAttributeValue(i));
|
||||
|
@ -306,7 +310,13 @@ public class RoutingConfiguration {
|
|||
GeneralRouterProfile c = Algorithms.parseEnumValue(GeneralRouterProfile.values(),
|
||||
parser.getAttributeValue("", "baseProfile"), GeneralRouterProfile.CAR);
|
||||
GeneralRouter currentRouter = new GeneralRouter(c, attrs);
|
||||
config.routers.put(currentSelectedRouter, currentRouter);
|
||||
currentRouter.setProfileName(currentSelectedRouterName);
|
||||
if (filename != null) {
|
||||
currentRouter.setFilename(filename);
|
||||
currentSelectedRouterName = filename + "/" + currentSelectedRouterName;
|
||||
}
|
||||
|
||||
config.routers.put(currentSelectedRouterName, currentRouter);
|
||||
return currentRouter;
|
||||
}
|
||||
|
||||
|
@ -315,7 +325,7 @@ public class RoutingConfiguration {
|
|||
currentRouter.addAttribute(parser.getAttributeValue("", "name"),
|
||||
parser.getAttributeValue("", "value"));
|
||||
} else {
|
||||
config.attributes.put(parser.getAttributeValue("", "name"),
|
||||
config.attributes.put(parser.getAttributeValue("", "name"),
|
||||
parser.getAttributeValue("", "value"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,6 +131,35 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/list_item_divider" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/card_bg_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/list_header_height"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard"
|
||||
android:text="@string/gpx_settings"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/list_item_title_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/gpx_settings_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/list_item_divider"/>
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="shared_string_select">Select</string>
|
||||
<string name="min_logging_distance">Minimum logging distance</string>
|
||||
<string name="min_logging_distance_descr">Filter: minimum distance to log a new point</string>
|
||||
<string name="min_logging_accuracy">Minimum logging accuracy</string>
|
||||
<string name="min_logging_accuracy_descr">Filter: no logging unless the accuracy is reached</string>
|
||||
<string name="min_logging_speed">Minimum logging speed</string>
|
||||
<string name="min_logging_speed_descr">Filter: no logging below selected speed</string>
|
||||
<string name="gpx_settings">GPX settings</string>
|
||||
<string name="proxy_key">Key</string>
|
||||
<string name="proxy_password">Password</string>
|
||||
<string name="proxy_username">Username</string>
|
||||
|
|
|
@ -15,6 +15,7 @@ public class AMapPoint implements Parcelable {
|
|||
public static final String POINT_SPEED_PARAM = "point_speed_param";
|
||||
public static final String POINT_TYPE_ICON_NAME_PARAM = "point_type_icon_name_param";
|
||||
public static final String POINT_STALE_LOC_PARAM = "point_stale_loc_param";
|
||||
public static final String POINT_BEARING_PARAM = "point_bearing_param";
|
||||
|
||||
private String id;
|
||||
private String shortName;
|
||||
|
|
|
@ -43,6 +43,9 @@ private val LOC_HISTORY_VALUES_SEC = listOf(
|
|||
12 * 60 * 60L,
|
||||
24 * 60 * 60L
|
||||
)
|
||||
private val MIN_LOCATION_DISTANCE = listOf(0f, 2.0f, 5.0f, 10.0f, 20.0f, 30.0f, 50.0f)
|
||||
private val MIN_LOCATION_ACCURACY = listOf(0f, 1.0f, 2.0f, 5.0f, 10.0f, 15.0f, 20.0f, 50.0f, 100.0f)
|
||||
private val MIN_LOCATION_SPEED = listOf(0f, 0.000001f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f)
|
||||
|
||||
const val SHARE_TYPE_MAP = "Map"
|
||||
const val SHARE_TYPE_TEXT = "Text"
|
||||
|
@ -53,6 +56,9 @@ private const val SEND_MY_LOC_DEFAULT_INDEX = 6
|
|||
private const val STALE_LOC_DEFAULT_INDEX = 0
|
||||
private const val LOC_HISTORY_DEFAULT_INDEX = 7
|
||||
private const val SHARE_TYPE_DEFAULT_INDEX = 2
|
||||
private const val MIN_LOCATION_DISTANCE_INDEX = 0
|
||||
private const val MIN_LOCATION_ACCURACY_INDEX = 0
|
||||
private const val MIN_LOCATION_SPEED_INDEX = 0
|
||||
|
||||
private const val SETTINGS_NAME = "osmand_telegram_settings"
|
||||
|
||||
|
@ -69,6 +75,10 @@ private const val STALE_LOC_TIME_KEY = "stale_loc_time"
|
|||
private const val LOC_HISTORY_TIME_KEY = "loc_history_time"
|
||||
private const val SHARE_TYPE_KEY = "share_type"
|
||||
|
||||
private const val MIN_LOCATION_DISTANCE_KEY = "min_location_distance"
|
||||
private const val MIN_LOCATION_ACCURACY_KEY = "min_location_accuracy"
|
||||
private const val MIN_LOCATION_SPEED_KEY = "min_location_speed"
|
||||
|
||||
private const val APP_TO_CONNECT_PACKAGE_KEY = "app_to_connect_package"
|
||||
|
||||
private const val DEFAULT_VISIBLE_TIME_SECONDS = 60 * 60L // 1 hour
|
||||
|
@ -117,12 +127,17 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
var locHistoryTime = LOC_HISTORY_VALUES_SEC[LOC_HISTORY_DEFAULT_INDEX]
|
||||
var shareTypeValue = SHARE_TYPE_VALUES[SHARE_TYPE_DEFAULT_INDEX]
|
||||
|
||||
var minLocationDistance = MIN_LOCATION_DISTANCE[MIN_LOCATION_DISTANCE_INDEX]
|
||||
var minLocationAccuracy = MIN_LOCATION_ACCURACY[MIN_LOCATION_ACCURACY_INDEX]
|
||||
var minLocationSpeed = MIN_LOCATION_SPEED[MIN_LOCATION_SPEED_INDEX]
|
||||
|
||||
var appToConnectPackage = ""
|
||||
private set
|
||||
|
||||
var liveNowSortType = LiveNowSortType.SORT_BY_DISTANCE
|
||||
|
||||
val gpsAndLocPrefs = listOf(SendMyLocPref(), StaleLocPref(), LocHistoryPref(), ShareTypePref())
|
||||
val gpxLoggingPrefs = listOf(MinLocationDistance(), MinLocationAccuracy(), MinLocationSpeed())
|
||||
|
||||
var batteryOptimisationAsked = false
|
||||
|
||||
|
@ -460,13 +475,18 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
if (shareInfo.lastTextSuccessfulSendTime == -1L && shareInfo.lastMapSuccessfulSendTime == -1L
|
||||
&& ((statusChangeTime / 1000 - shareInfo.start) < SHARING_INITIALIZATION_TIME)) {
|
||||
initializing = true
|
||||
} else if (shareInfo.hasSharingError
|
||||
|| (shareInfo.lastSendTextMessageTime - shareInfo.lastTextSuccessfulSendTime > WAITING_TDLIB_TIME)
|
||||
|| (shareInfo.lastSendMapMessageTime - shareInfo.lastMapSuccessfulSendTime > WAITING_TDLIB_TIME)
|
||||
) {
|
||||
sendChatsErrors = true
|
||||
locationTime = Math.max(shareInfo.lastTextSuccessfulSendTime, shareInfo.lastMapSuccessfulSendTime)
|
||||
chatsIds.add(shareInfo.chatId)
|
||||
} else {
|
||||
val textSharingError = shareInfo.lastSendTextMessageTime - shareInfo.lastTextSuccessfulSendTime > WAITING_TDLIB_TIME
|
||||
val mapSharingError = shareInfo.lastSendMapMessageTime - shareInfo.lastMapSuccessfulSendTime > WAITING_TDLIB_TIME
|
||||
if (shareInfo.hasSharingError
|
||||
|| (shareTypeValue == SHARE_TYPE_MAP_AND_TEXT && (textSharingError || mapSharingError))
|
||||
|| textSharingError && (shareTypeValue == SHARE_TYPE_TEXT)
|
||||
|| mapSharingError && (shareTypeValue == SHARE_TYPE_MAP)
|
||||
) {
|
||||
sendChatsErrors = true
|
||||
locationTime = Math.max(shareInfo.lastTextSuccessfulSendTime, shareInfo.lastMapSuccessfulSendTime)
|
||||
chatsIds.add(shareInfo.chatId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,7 +497,7 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
} else if (!initializing) {
|
||||
when {
|
||||
!gpsEnabled -> {
|
||||
locationTime = app.shareLocationHelper.lastLocationUpdateTime
|
||||
locationTime = app.shareLocationHelper.lastLocationUpdateTime / 1000
|
||||
if (locationTime <= 0) {
|
||||
locationTime = getLastSuccessfulSendTime()
|
||||
}
|
||||
|
@ -557,6 +577,10 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
edit.putLong(STALE_LOC_TIME_KEY, staleLocTime)
|
||||
edit.putLong(LOC_HISTORY_TIME_KEY, locHistoryTime)
|
||||
|
||||
edit.putFloat(MIN_LOCATION_DISTANCE_KEY, minLocationDistance)
|
||||
edit.putFloat(MIN_LOCATION_ACCURACY_KEY, minLocationAccuracy)
|
||||
edit.putFloat(MIN_LOCATION_SPEED_KEY, minLocationSpeed)
|
||||
|
||||
edit.putString(SHARE_TYPE_KEY, shareTypeValue)
|
||||
|
||||
edit.putString(APP_TO_CONNECT_PACKAGE_KEY, appToConnectPackage)
|
||||
|
@ -623,6 +647,13 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
val shareTypeDef = SHARE_TYPE_VALUES[SHARE_TYPE_DEFAULT_INDEX]
|
||||
shareTypeValue = prefs.getString(SHARE_TYPE_KEY, shareTypeDef)
|
||||
|
||||
val minLocationDistanceDef = MIN_LOCATION_DISTANCE[MIN_LOCATION_DISTANCE_INDEX]
|
||||
minLocationDistance = prefs.getFloat(MIN_LOCATION_DISTANCE_KEY, minLocationDistanceDef)
|
||||
val minLocationPrecisionDef = MIN_LOCATION_ACCURACY[MIN_LOCATION_ACCURACY_INDEX]
|
||||
minLocationAccuracy = prefs.getFloat(MIN_LOCATION_ACCURACY_KEY, minLocationPrecisionDef)
|
||||
val minLocationSpeedDef = MIN_LOCATION_SPEED[MIN_LOCATION_SPEED_INDEX]
|
||||
minLocationSpeed = prefs.getFloat(MIN_LOCATION_SPEED_KEY, minLocationSpeedDef)
|
||||
|
||||
val currentUserId = app.telegramHelper.getCurrentUserId()
|
||||
currentSharingMode = prefs.getString(SHARING_MODE_KEY, if (currentUserId != -1) currentUserId.toString() else "")
|
||||
|
||||
|
@ -787,7 +818,7 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
}
|
||||
}
|
||||
|
||||
inner class SendMyLocPref : DurationPref(
|
||||
inner class SendMyLocPref : NumericPref(
|
||||
R.drawable.ic_action_share_location,
|
||||
R.string.send_my_location,
|
||||
R.string.send_my_location_desc,
|
||||
|
@ -798,12 +829,15 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
OsmandFormatter.getFormattedDuration(app, sendMyLocInterval)
|
||||
|
||||
override fun setCurrentValue(index: Int) {
|
||||
sendMyLocInterval = values[index]
|
||||
sendMyLocInterval = values[index].toLong()
|
||||
app.updateSendLocationInterval()
|
||||
}
|
||||
|
||||
override fun getMenuItems() =
|
||||
values.map { OsmandFormatter.getFormattedDuration(app, it.toLong()) }
|
||||
}
|
||||
|
||||
inner class StaleLocPref : DurationPref(
|
||||
inner class StaleLocPref : NumericPref(
|
||||
R.drawable.ic_action_time_span,
|
||||
R.string.stale_location,
|
||||
R.string.stale_location_desc,
|
||||
|
@ -814,11 +848,14 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
OsmandFormatter.getFormattedDuration(app, staleLocTime)
|
||||
|
||||
override fun setCurrentValue(index: Int) {
|
||||
staleLocTime = values[index]
|
||||
staleLocTime = values[index].toLong()
|
||||
}
|
||||
|
||||
override fun getMenuItems() =
|
||||
values.map { OsmandFormatter.getFormattedDuration(app, it.toLong()) }
|
||||
}
|
||||
|
||||
inner class LocHistoryPref : DurationPref(
|
||||
inner class LocHistoryPref : NumericPref(
|
||||
R.drawable.ic_action_location_history,
|
||||
R.string.location_history,
|
||||
R.string.location_history_desc,
|
||||
|
@ -830,12 +867,15 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
|
||||
override fun setCurrentValue(index: Int) {
|
||||
val value = values[index]
|
||||
locHistoryTime = value
|
||||
app.telegramHelper.messageActiveTimeSec = value
|
||||
locHistoryTime = value.toLong()
|
||||
app.telegramHelper.messageActiveTimeSec = value.toLong()
|
||||
}
|
||||
|
||||
override fun getMenuItems() =
|
||||
values.map { OsmandFormatter.getFormattedDuration(app, it.toLong()) }
|
||||
}
|
||||
|
||||
inner class ShareTypePref : DurationPref(
|
||||
inner class ShareTypePref : NumericPref(
|
||||
R.drawable.ic_action_location_history,
|
||||
R.string.send_location_as,
|
||||
R.string.send_location_as_descr,
|
||||
|
@ -871,18 +911,87 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
}
|
||||
}
|
||||
|
||||
abstract inner class DurationPref(
|
||||
inner class MinLocationDistance : NumericPref(
|
||||
R.drawable.ic_action_location_history,
|
||||
R.string.min_logging_distance,
|
||||
R.string.min_logging_distance_descr,
|
||||
MIN_LOCATION_DISTANCE
|
||||
) {
|
||||
|
||||
override fun getCurrentValue() = getFormattedValue(minLocationDistance)
|
||||
|
||||
override fun setCurrentValue(index: Int) {
|
||||
val value = values[index]
|
||||
minLocationDistance = value.toFloat()
|
||||
}
|
||||
|
||||
override fun getMenuItems() = values.map { getFormattedValue(it.toFloat()) }
|
||||
|
||||
private fun getFormattedValue(value: Float): String {
|
||||
return if (value == 0f) app.getString(R.string.shared_string_select)
|
||||
else OsmandFormatter.getFormattedDistance(value, app)
|
||||
}
|
||||
}
|
||||
|
||||
inner class MinLocationAccuracy : NumericPref(
|
||||
R.drawable.ic_action_location_history,
|
||||
R.string.min_logging_accuracy,
|
||||
R.string.min_logging_accuracy_descr,
|
||||
MIN_LOCATION_ACCURACY
|
||||
) {
|
||||
|
||||
override fun getCurrentValue() = getFormattedValue(minLocationAccuracy)
|
||||
|
||||
override fun setCurrentValue(index: Int) {
|
||||
val value = values[index]
|
||||
minLocationAccuracy = value.toFloat()
|
||||
}
|
||||
|
||||
override fun getMenuItems() = values.map { getFormattedValue(it.toFloat()) }
|
||||
|
||||
private fun getFormattedValue(value: Float): String {
|
||||
return if (value == 0f) app.getString(R.string.shared_string_select)
|
||||
else OsmandFormatter.getFormattedDistance(value, app)
|
||||
}
|
||||
}
|
||||
|
||||
inner class MinLocationSpeed : NumericPref(
|
||||
R.drawable.ic_action_location_history,
|
||||
R.string.min_logging_speed,
|
||||
R.string.min_logging_speed_descr,
|
||||
MIN_LOCATION_SPEED
|
||||
) {
|
||||
|
||||
override fun getCurrentValue() = getFormattedValue(minLocationSpeed)
|
||||
|
||||
override fun setCurrentValue(index: Int) {
|
||||
val value = values[index]
|
||||
minLocationSpeed = value.toFloat()
|
||||
}
|
||||
|
||||
override fun getMenuItems() = values.map { getFormattedValue(it.toFloat()) }
|
||||
|
||||
private fun getFormattedValue(value: Float): String {
|
||||
return when (value) {
|
||||
MIN_LOCATION_SPEED[0] -> app.getString(R.string.shared_string_select)
|
||||
MIN_LOCATION_SPEED[1] -> "> 0"
|
||||
else -> OsmandFormatter.getFormattedSpeed(value, app)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract inner class NumericPref(
|
||||
@DrawableRes val iconId: Int,
|
||||
@StringRes val titleId: Int,
|
||||
@StringRes val descriptionId: Int,
|
||||
val values: List<Long>
|
||||
val values: List<Number>
|
||||
) {
|
||||
|
||||
abstract fun getCurrentValue(): String
|
||||
|
||||
abstract fun setCurrentValue(index: Int)
|
||||
|
||||
open fun getMenuItems() = values.map { OsmandFormatter.getFormattedDuration(app, it) }
|
||||
abstract fun getMenuItems(): List<String>
|
||||
}
|
||||
|
||||
enum class AppConnect(
|
||||
|
|
|
@ -7,6 +7,7 @@ import net.osmand.telegram.helpers.LocationMessages.BufferMessage
|
|||
import net.osmand.telegram.notifications.TelegramNotification.NotificationType
|
||||
import net.osmand.telegram.utils.AndroidNetworkUtils
|
||||
import net.osmand.telegram.utils.BASE_URL
|
||||
import net.osmand.util.MapUtils
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
@ -15,6 +16,8 @@ private const val USER_SET_LIVE_PERIOD_DELAY_MS = 5000 // 5 sec
|
|||
|
||||
private const val UPDATE_LOCATION_ACCURACY = 150 // 150 meters
|
||||
|
||||
private const val SENT_LOCATIONS_INTERVAL_TIME_MS = 4000 // 4 sec
|
||||
|
||||
class ShareLocationHelper(private val app: TelegramApplication) {
|
||||
|
||||
private val log = PlatformUtil.getLog(ShareLocationHelper::class.java)
|
||||
|
@ -30,6 +33,8 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
|
||||
var lastLocationUpdateTime: Long = 0
|
||||
|
||||
var lastLocationSentTime: Long = 0
|
||||
|
||||
var lastLocation: Location? = null
|
||||
set(value) {
|
||||
if (lastTimeInMillis == 0L) {
|
||||
|
@ -48,12 +53,31 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
private var lastTimeInMillis: Long = 0L
|
||||
|
||||
fun updateLocation(location: Location?) {
|
||||
lastLocation = location
|
||||
val lastPoint = lastLocation
|
||||
var record = true
|
||||
if (location != null) {
|
||||
val minDistance = app.settings.minLocationDistance
|
||||
if (minDistance > 0 && lastPoint != null) {
|
||||
val calculatedDistance = MapUtils.getDistance(lastPoint.latitude, lastPoint.longitude, location.latitude, location.longitude)
|
||||
if (calculatedDistance < minDistance) {
|
||||
record = false
|
||||
}
|
||||
}
|
||||
val accuracy = app.settings.minLocationAccuracy
|
||||
if (accuracy > 0 && (!location.hasAccuracy() || location.accuracy > accuracy)) {
|
||||
record = false
|
||||
}
|
||||
val minSpeed = app.settings.minLocationSpeed
|
||||
if (minSpeed > 0 && (!location.hasSpeed() || location.speed < minSpeed)) {
|
||||
record = false
|
||||
}
|
||||
|
||||
if (location != null && location.accuracy < UPDATE_LOCATION_ACCURACY) {
|
||||
lastLocationUpdateTime = System.currentTimeMillis()
|
||||
if (app.settings.getChatsShareInfo().isNotEmpty()) {
|
||||
shareLocationMessages(location, app.telegramHelper.getCurrentUserId())
|
||||
if (record) {
|
||||
lastLocationUpdateTime = System.currentTimeMillis()
|
||||
lastLocation = location
|
||||
if (app.settings.getChatsShareInfo().isNotEmpty()) {
|
||||
shareLocationMessages(location, app.telegramHelper.getCurrentUserId())
|
||||
}
|
||||
}
|
||||
}
|
||||
app.settings.updateSharingStatusHistory()
|
||||
|
@ -108,12 +132,16 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
|
||||
fun checkAndSendBufferMessagesToChat(chatId: Long) {
|
||||
val shareInfo = app.settings.getChatsShareInfo()[chatId]
|
||||
if (shareInfo != null) {
|
||||
val shareChatsInfo = app.settings.getChatsShareInfo()
|
||||
val shareInfo = shareChatsInfo[chatId]
|
||||
val chatsCounts = shareChatsInfo.size
|
||||
val currentTime = System.currentTimeMillis()
|
||||
if (shareInfo != null && currentTime - lastLocationSentTime > chatsCounts * SENT_LOCATIONS_INTERVAL_TIME_MS) {
|
||||
app.locationMessages.getBufferedTextMessagesForChat(chatId).take(MAX_MESSAGES_IN_TDLIB_PER_CHAT).forEach {
|
||||
if (shareInfo.pendingTdLibText < MAX_MESSAGES_IN_TDLIB_PER_CHAT) {
|
||||
if (it.deviceName.isEmpty()) {
|
||||
if (!shareInfo.pendingTextMessage && shareInfo.currentTextMessageId != -1L) {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.editTextLocation(shareInfo, it)
|
||||
app.locationMessages.removeBufferedMessage(it)
|
||||
}
|
||||
|
@ -126,6 +154,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
if (shareInfo.pendingTdLibMap < MAX_MESSAGES_IN_TDLIB_PER_CHAT) {
|
||||
if (it.deviceName.isEmpty()) {
|
||||
if (!shareInfo.pendingMapMessage && shareInfo.currentMapMessageId != -1L) {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.editMapLocation(shareInfo, it)
|
||||
app.locationMessages.removeBufferedMessage(it)
|
||||
}
|
||||
|
@ -188,6 +217,14 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
val isBot = app.settings.currentSharingMode != userId.toString()
|
||||
val deviceName = if (isBot) app.settings.currentSharingMode else ""
|
||||
var bufferedMessagesFull = false
|
||||
val chatsCounts = chatsShareInfo.size
|
||||
val currentTime = System.currentTimeMillis()
|
||||
|
||||
app.locationMessages.addMyLocationMessage(location)
|
||||
|
||||
if (currentTime - lastLocationSentTime <= chatsCounts * SENT_LOCATIONS_INTERVAL_TIME_MS) {
|
||||
return
|
||||
}
|
||||
|
||||
chatsShareInfo.values.forEach { shareInfo ->
|
||||
if (shareInfo.pendingTdLibText >= MAX_MESSAGES_IN_TDLIB_PER_CHAT || shareInfo.pendingTdLibMap >= MAX_MESSAGES_IN_TDLIB_PER_CHAT) {
|
||||
|
@ -209,8 +246,8 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
prepareTextMessage(shareInfo, messageText, isBot)
|
||||
}
|
||||
}
|
||||
checkAndSendBufferMessagesToChat(shareInfo.chatId)
|
||||
}
|
||||
app.locationMessages.addMyLocationMessage(location)
|
||||
if (bufferedMessagesFull) {
|
||||
checkNetworkType()
|
||||
}
|
||||
|
@ -225,6 +262,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
if (isBot) {
|
||||
sendLocationToBot(message, shareInfo, SHARE_TYPE_TEXT)
|
||||
} else {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.sendNewTextLocation(shareInfo, message)
|
||||
}
|
||||
}
|
||||
|
@ -237,6 +275,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
} else {
|
||||
if (shareInfo.pendingTdLibText < MAX_MESSAGES_IN_TDLIB_PER_CHAT) {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.editTextLocation(shareInfo, message)
|
||||
} else {
|
||||
app.locationMessages.addBufferedMessage(message)
|
||||
|
@ -258,6 +297,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
app.locationMessages.addBufferedMessage(message)
|
||||
}
|
||||
} else {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.sendNewMapLocation(shareInfo, message)
|
||||
}
|
||||
}
|
||||
|
@ -270,6 +310,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
} else {
|
||||
if (shareInfo.pendingTdLibMap < MAX_MESSAGES_IN_TDLIB_PER_CHAT) {
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
app.telegramHelper.editMapLocation(shareInfo, message)
|
||||
} else {
|
||||
app.locationMessages.addBufferedMessage(message)
|
||||
|
@ -298,6 +339,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
} else if (shareType == SHARE_TYPE_MAP) {
|
||||
shareInfo.lastSendMapMessageTime = (System.currentTimeMillis() / 1000).toInt()
|
||||
}
|
||||
lastLocationSentTime = System.currentTimeMillis()
|
||||
AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false,
|
||||
object : AndroidNetworkUtils.OnRequestResultListener {
|
||||
override fun onResult(result: String?) {
|
||||
|
|
|
@ -90,6 +90,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
if (item.latLon == null) {
|
||||
return
|
||||
}
|
||||
setupMapLayer()
|
||||
osmandAidlHelper.execOsmandApi {
|
||||
osmandAidlHelper.showMapPoint(
|
||||
MAP_LAYER_ID,
|
||||
|
@ -100,7 +101,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
Color.WHITE,
|
||||
ALatLon(item.latLon!!.latitude, item.latLon!!.longitude),
|
||||
generatePointDetails(item.bearing?.toFloat(), item.altitude?.toFloat(), item.precision?.toFloat()),
|
||||
generatePointParams(if (stale) item.grayscalePhotoPath else item.photoPath, stale, item.speed?.toFloat())
|
||||
generatePointParams(if (stale) item.grayscalePhotoPath else item.photoPath, stale, item.speed?.toFloat(), item.bearing?.toFloat())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -147,8 +148,13 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
}
|
||||
setupMapLayer()
|
||||
val params = generatePointParams(photoPath, stale, if (content is MessageUserLocation) content.speed.toFloat() else null)
|
||||
|
||||
var speed = 0f
|
||||
var bearing = 0f
|
||||
if (content is MessageUserLocation) {
|
||||
speed = content.speed.toFloat()
|
||||
bearing = content.bearing.toFloat()
|
||||
}
|
||||
val params = generatePointParams(photoPath, stale, speed, bearing)
|
||||
val typeName = if (isGroup) chatTitle else OsmandFormatter.getListItemLiveTimeDescr(app, date, app.getString(R.string.last_response) + ": ")
|
||||
if (update) {
|
||||
osmandAidlHelper.updateMapPoint(MAP_LAYER_ID, pointId, name, name, typeName, Color.WHITE, aLatLon, details, params)
|
||||
|
@ -158,7 +164,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
points[pointId] = message
|
||||
} else if (content is MessageOsmAndBotLocation && content.isValid()) {
|
||||
setupMapLayer()
|
||||
val params = generatePointParams(null, stale, content.speed.toFloat())
|
||||
val params = generatePointParams(null, stale, content.speed.toFloat(), content.bearing.toFloat())
|
||||
if (update) {
|
||||
osmandAidlHelper.updateMapPoint(MAP_LAYER_ID, pointId, name, name, chatTitle, Color.WHITE, aLatLon, details, params)
|
||||
} else {
|
||||
|
@ -340,7 +346,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
private fun generatePointDetails(bearing: Float?, altitude: Float?, precision: Float?): List<String> {
|
||||
val details = mutableListOf<String>()
|
||||
if (bearing != null && bearing != 0.0f) {
|
||||
details.add(String.format(Locale.US, "${OsmandLocationUtils.BEARING_PREFIX}%.1f \n", bearing))
|
||||
details.add(String.format(Locale.US, "${OsmandLocationUtils.BEARING_PREFIX}%.1f${OsmandLocationUtils.BEARING_SUFFIX} \n", bearing))
|
||||
}
|
||||
if (altitude != null && altitude != 0.0f) {
|
||||
details.add(String.format(Locale.US, "${OsmandLocationUtils.ALTITUDE_PREFIX}%.1f m\n", altitude))
|
||||
|
@ -352,7 +358,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
return details
|
||||
}
|
||||
|
||||
private fun generatePointParams(photoPath: String?, stale: Boolean, speed: Float?): Map<String, String> {
|
||||
private fun generatePointParams(photoPath: String?, stale: Boolean, speed: Float?, bearing: Float?): Map<String, String> {
|
||||
val photoUri = generatePhotoUri(photoPath, stale)
|
||||
app.grantUriPermission(
|
||||
app.settings.appToConnectPackage,
|
||||
|
@ -366,6 +372,9 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
if (speed != 0.0f) {
|
||||
params[AMapPoint.POINT_SPEED_PARAM] = speed.toString()
|
||||
}
|
||||
if (bearing != 0.0f) {
|
||||
params[AMapPoint.POINT_BEARING_PARAM] = bearing.toString()
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import android.view.ViewGroup
|
|||
import android.widget.*
|
||||
import net.osmand.telegram.R
|
||||
import net.osmand.telegram.TelegramSettings
|
||||
import net.osmand.telegram.TelegramSettings.DurationPref
|
||||
import net.osmand.telegram.TelegramSettings.NumericPref
|
||||
import net.osmand.telegram.helpers.TelegramHelper.Companion.OSMAND_BOT_USERNAME
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||
import net.osmand.telegram.utils.AndroidUtils
|
||||
|
@ -49,18 +49,8 @@ class SettingsDialogFragment : BaseDialogFragment() {
|
|||
window.statusBarColor = ContextCompat.getColor(app, R.color.card_bg_light)
|
||||
}
|
||||
var container = mainView.findViewById<ViewGroup>(R.id.gps_and_loc_container)
|
||||
for (pref in settings.gpsAndLocPrefs) {
|
||||
inflater.inflate(R.layout.item_with_desc_and_right_value, container, false).apply {
|
||||
findViewById<ImageView>(R.id.icon).setImageDrawable(uiUtils.getThemedIcon(pref.iconId))
|
||||
findViewById<TextView>(R.id.title).setText(pref.titleId)
|
||||
findViewById<TextView>(R.id.description).setText(pref.descriptionId)
|
||||
val valueView = findViewById<TextView>(R.id.value)
|
||||
valueView.text = pref.getCurrentValue()
|
||||
setOnClickListener {
|
||||
showPopupMenu(pref, valueView)
|
||||
}
|
||||
container.addView(this)
|
||||
}
|
||||
settings.gpsAndLocPrefs.forEach {
|
||||
createNumericPref(inflater, container, it)
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
|
@ -148,6 +138,11 @@ class SettingsDialogFragment : BaseDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
container = mainView.findViewById<ViewGroup>(R.id.gpx_settings_container)
|
||||
settings.gpxLoggingPrefs.forEach {
|
||||
createNumericPref(inflater, container, it)
|
||||
}
|
||||
|
||||
container = mainView.findViewById(R.id.osmand_connect_container)
|
||||
for (appConn in TelegramSettings.AppConnect.values()) {
|
||||
val pack = appConn.appPackage
|
||||
|
@ -249,6 +244,20 @@ class SettingsDialogFragment : BaseDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun createNumericPref(inflater: LayoutInflater, container: ViewGroup, pref: NumericPref) {
|
||||
inflater.inflate(R.layout.item_with_desc_and_right_value, container, false).apply {
|
||||
findViewById<ImageView>(R.id.icon).setImageDrawable(uiUtils.getThemedIcon(pref.iconId))
|
||||
findViewById<TextView>(R.id.title).setText(pref.titleId)
|
||||
findViewById<TextView>(R.id.description).setText(pref.descriptionId)
|
||||
val valueView = findViewById<TextView>(R.id.value)
|
||||
valueView.text = pref.getCurrentValue()
|
||||
setOnClickListener {
|
||||
showPopupMenu(pref, valueView)
|
||||
}
|
||||
container.addView(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addItemToContainer(inflater: LayoutInflater, container: ViewGroup, tag: String, title: String) {
|
||||
inflater.inflate(R.layout.item_with_rb_and_btn, container, false).apply {
|
||||
val checked = tag == settings.currentSharingMode
|
||||
|
@ -270,7 +279,7 @@ class SettingsDialogFragment : BaseDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun showPopupMenu(pref: DurationPref, valueView: TextView) {
|
||||
private fun showPopupMenu(pref: NumericPref, valueView: TextView) {
|
||||
val menuList = pref.getMenuItems()
|
||||
val ctx = valueView.context
|
||||
ListPopupWindow(ctx).apply {
|
||||
|
|
|
@ -32,6 +32,7 @@ object OsmandLocationUtils {
|
|||
const val BEARING_PREFIX = "Bearing: "
|
||||
const val SPEED_PREFIX = "Speed: "
|
||||
const val HDOP_PREFIX = "Horizontal precision: "
|
||||
const val BEARING_SUFFIX = "°"
|
||||
|
||||
const val NOW = "now"
|
||||
const val FEW_SECONDS_AGO = "few seconds ago"
|
||||
|
@ -241,19 +242,28 @@ object OsmandLocationUtils {
|
|||
}
|
||||
}
|
||||
s.startsWith(SPEED_PREFIX) -> {
|
||||
val altStr = s.removePrefix(SPEED_PREFIX)
|
||||
val speedStr = s.removePrefix(SPEED_PREFIX)
|
||||
try {
|
||||
val alt = altStr.split(" ").first()
|
||||
res.speed = alt.toDouble()
|
||||
val speed = speedStr.split(" ").first()
|
||||
res.speed = speed.toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
s.startsWith(BEARING_PREFIX) -> {
|
||||
val bearingStr = s.removePrefix(BEARING_PREFIX)
|
||||
try {
|
||||
val bearing = bearingStr.removeSuffix(BEARING_SUFFIX)
|
||||
res.bearing = bearing.toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
s.startsWith(HDOP_PREFIX) -> {
|
||||
val altStr = s.removePrefix(HDOP_PREFIX)
|
||||
val hdopStr = s.removePrefix(HDOP_PREFIX)
|
||||
try {
|
||||
val alt = altStr.split(" ").first()
|
||||
res.hdop = alt.toDouble()
|
||||
val hdop = hdopStr.split(" ").first()
|
||||
res.hdop = hdop.toDouble()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
@ -336,6 +346,10 @@ object OsmandLocationUtils {
|
|||
entities.add(TdApi.TextEntity(builder.lastIndex, SPEED_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$SPEED_PREFIX%.1f m/s\n", location.speed))
|
||||
}
|
||||
if (location.bearing > 0) {
|
||||
entities.add(TdApi.TextEntity(builder.lastIndex, BEARING_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$BEARING_PREFIX%.1f$BEARING_SUFFIX\n", location.bearing))
|
||||
}
|
||||
if (location.hdop != 0.0 && location.speed == 0.0) {
|
||||
entities.add(TdApi.TextEntity(builder.lastIndex, HDOP_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$HDOP_PREFIX%d m\n", location.hdop.toInt()))
|
||||
|
@ -375,6 +389,10 @@ object OsmandLocationUtils {
|
|||
entities.add(TdApi.TextEntity(builder.lastIndex, SPEED_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$SPEED_PREFIX%.1f m/s\n", location.speed))
|
||||
}
|
||||
if (location.bearing > 0) {
|
||||
entities.add(TdApi.TextEntity(builder.lastIndex, BEARING_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$BEARING_PREFIX%.1f$BEARING_SUFFIX\n", location.bearing))
|
||||
}
|
||||
if (location.hdop != 0.0 && location.speed == 0.0) {
|
||||
entities.add(TdApi.TextEntity(builder.lastIndex, HDOP_PREFIX.length, TdApi.TextEntityTypeBold()))
|
||||
builder.append(String.format(Locale.US, "$HDOP_PREFIX%d m\n", location.hdop.toInt()))
|
||||
|
|
|
@ -891,5 +891,15 @@
|
|||
</activity>
|
||||
|
||||
<receiver android:name="net.osmand.plus.liveupdates.LiveUpdatesAlarmReceiver"/>
|
||||
|
||||
<activity
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:label="Application profiles"
|
||||
android:name=".profiles.SettingsProfileActivity"/>
|
||||
|
||||
<activity
|
||||
android:name=".profiles.EditProfileActivity"
|
||||
android:label="Application profiles"/>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
BIN
OsmAnd/res/drawable-hdpi/ic_action_compass_widget.png
Normal file
After Width: | Height: | Size: 643 B |
BIN
OsmAnd/res/drawable-hdpi/ic_action_compass_widget_hide.png
Normal file
After Width: | Height: | Size: 623 B |
BIN
OsmAnd/res/drawable-hdpi/ic_action_location_color_lost.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
OsmAnd/res/drawable-mdpi/ic_action_compass_widget.png
Normal file
After Width: | Height: | Size: 421 B |
BIN
OsmAnd/res/drawable-mdpi/ic_action_compass_widget_hide.png
Normal file
After Width: | Height: | Size: 437 B |
BIN
OsmAnd/res/drawable-mdpi/ic_action_location_color_lost.png
Normal file
After Width: | Height: | Size: 934 B |
BIN
OsmAnd/res/drawable-xhdpi/ic_action_compass_widget.png
Normal file
After Width: | Height: | Size: 802 B |
BIN
OsmAnd/res/drawable-xhdpi/ic_action_compass_widget_hide.png
Normal file
After Width: | Height: | Size: 834 B |
BIN
OsmAnd/res/drawable-xhdpi/ic_action_location_color_lost.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
OsmAnd/res/drawable-xxhdpi/ic_action_compass_widget.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
OsmAnd/res/drawable-xxhdpi/ic_action_compass_widget_hide.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
OsmAnd/res/drawable-xxhdpi/ic_action_location_color_lost.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
OsmAnd/res/drawable-xxxhdpi/ic_action_compass_widget.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
OsmAnd/res/drawable-xxxhdpi/ic_action_compass_widget_hide.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
OsmAnd/res/drawable-xxxhdpi/ic_action_location_color_lost.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
|
@ -10,7 +10,7 @@
|
|||
<solid android:color="@color/map_widget_light" />
|
||||
<corners
|
||||
android:topRightRadius="@dimen/map_button_rect_rad"
|
||||
android:bottomRightRadius="@dimen/map_button_rect_rad"
|
||||
android:bottomRightRadius="@dimen/map_button_rect_rad"
|
||||
/>
|
||||
<stroke android:color="@color/map_widget_stroke" android:width="@dimen/map_button_stroke"/>
|
||||
</shape></item>
|
||||
|
|
17
OsmAnd/res/drawable/btn_round_profile_blue.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_pressed="true"><shape android:shape="rectangle">
|
||||
<solid android:color="@color/map_widget_blue_pressed" />
|
||||
<corners android:radius="@dimen/map_button_rect_rad" />
|
||||
</shape></item>
|
||||
<item android:state_enabled="false"><shape android:shape="rectangle">
|
||||
<solid android:color="@color/searchbar_tab_inactive_light" />
|
||||
<corners android:radius="@dimen/map_button_rect_rad" />
|
||||
</shape></item>
|
||||
<item><shape android:shape="rectangle">
|
||||
<solid android:color="@color/active_buttons_and_links_light" />
|
||||
<corners android:radius="@dimen/map_button_rect_rad" />
|
||||
</shape></item>
|
||||
|
||||
</selector>
|
16
OsmAnd/res/drawable/btn_round_profile_gray.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true"><shape android:shape="rectangle">
|
||||
<solid android:color="@color/profile_button_gray_pressed" />
|
||||
<corners android:radius="@dimen/map_button_rect_rad" />
|
||||
</shape></item>
|
||||
<item android:state_enabled="false"><shape android:shape="rectangle">
|
||||
<solid android:color="@color/searchbar_tab_inactive_light" />
|
||||
<corners android:radius="@dimen/map_button_rect_rad" />
|
||||
</shape></item>
|
||||
<item><shape android:shape="rectangle">
|
||||
<solid android:color="@color/profile_button_gray" />
|
||||
<corners android:radius="@dimen/map_button_rect_rad" />
|
||||
</shape></item>
|
||||
|
||||
</selector>
|
5
OsmAnd/res/drawable/fab_extended_drawable.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/bg_shadow_fab_normal" android:state_pressed="true"/>
|
||||
<item android:drawable="@drawable/bg_shadow_fab_normal"/>
|
||||
</selector>
|
|
@ -0,0 +1,80 @@
|
|||
<?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="@dimen/bottom_sheet_large_list_item_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="63dp"
|
||||
android:paddingStart="@dimen/list_content_padding"
|
||||
android:paddingEnd="@dimen/list_content_padding"
|
||||
android:paddingLeft="@dimen/list_content_padding"
|
||||
android:paddingRight="@dimen/list_content_padding"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/bottom_sheet_icon_margin"
|
||||
android:layout_marginRight="@dimen/bottom_sheet_icon_margin"
|
||||
tools:tint="?attr/primary_icon_color"
|
||||
tools:src="@drawable/ic_action_coordinates_latitude"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.ListItemTitle"
|
||||
android:textColor="?attr/main_font_color_basic"
|
||||
tools:text="Item Title"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
tools:text="Item additional desription"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/compound_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:saveEnabled="false"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="64dp"
|
||||
android:layout_marginLeft="64dp"
|
||||
android:background="@color/divider_light"/>
|
||||
|
||||
</LinearLayout>
|
75
OsmAnd/res/layout/bottom_sheet_select_type_fragment.xml
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="?attr/bg_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dialog_title"
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/list_content_padding"
|
||||
android:layout_marginBottom="@dimen/list_content_padding"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
tools:text="Select navigation type"
|
||||
android:textColor="?attr/main_font_color_basic"
|
||||
android:textSize="@dimen/default_list_text_size"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dialog_description_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/list_content_padding"
|
||||
android:paddingStart="@dimen/list_content_padding"
|
||||
android:paddingEnd="@dimen/list_content_padding"
|
||||
android:paddingLeft="@dimen/list_content_padding"
|
||||
android:paddingRight="@dimen/list_content_padding"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/menu_list_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
</android.support.v7.widget.RecyclerView>
|
||||
|
||||
|
||||
<View
|
||||
android:id="@+id/bottom_row_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/dashboard_divider"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttons_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel_selection"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/bottom_sheet_cancel_button_height"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="@dimen/list_content_padding"
|
||||
android:layout_marginBottom="@dimen/list_content_padding"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:background="@drawable/btn_right_round"
|
||||
android:text="@string/shared_string_cancel"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/map_widget_blue"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
550
OsmAnd/res/layout/fragment_selected_profile.xml
Normal file
|
@ -0,0 +1,550 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout
|
||||
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:background="?attr/ctx_menu_info_view_bg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
>
|
||||
<ScrollView
|
||||
android:id="@+id/scroll_view_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:layout_marginBottom="@dimen/setting_profile_item_height">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/type_selection_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="?attr/bg_color"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:clickable="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding_small"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding_small"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/mode_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/bottom_sheet_icon_margin"
|
||||
android:layout_marginRight="@dimen/bottom_sheet_icon_margin"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:tint="?attr/primary_icon_color"
|
||||
tools:src="@drawable/ic_action_coordinates_latitude"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="Base Profile"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mode_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textSize="18sp"
|
||||
android:textColor="?attr/main_font_color_basic"
|
||||
tools:text="Item additional description"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/type_down_arrow2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:tint="@color/settings_divider"
|
||||
android:src="@drawable/ic_action_arrow_drop_down"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/ctx_menu_info_view_bg"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/bg_shadow_list_bottom"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/bg_shadow_list_top"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/bg_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
|
||||
<net.osmand.plus.widgets.OsmandTextFieldBoxes
|
||||
android:id="@+id/profile_name_otfb"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="@dimen/list_content_padding"
|
||||
android:layout_marginBottom="@dimen/list_content_padding"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
app:labelText="Profile Name">
|
||||
|
||||
<studio.carbonylgroup.textfieldboxes.ExtendedEditText
|
||||
android:id="@+id/profile_name_et"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
|
||||
tools:text="@string/lorem_ipsum"/>
|
||||
|
||||
</net.osmand.plus.widgets.OsmandTextFieldBoxes>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/profile_icon_layout"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/select_icon_btn_txt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="12sp"
|
||||
android:paddingBottom="2dp"
|
||||
android:text="Icon"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/select_icon_btn_img"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
tools:src="@drawable/ic_action_car_dark"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/click_block_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="false"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:layout_marginRight="@dimen/list_content_padding">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/type_down_arrow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|right"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:tint="@color/settings_divider"
|
||||
android:src="@drawable/ic_action_arrow_drop_down"/>
|
||||
|
||||
<net.osmand.plus.widgets.OsmandTextFieldBoxes
|
||||
android:id="@+id/navigation_type_otfb"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
|
||||
app:labelText="Navigation Type">
|
||||
|
||||
<studio.carbonylgroup.textfieldboxes.ExtendedEditText
|
||||
android:id="@+id/navigation_type_et"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableEnd="@drawable/ic_action_arrow_drop_down"
|
||||
android:drawableRight="@drawable/ic_action_arrow_drop_down"
|
||||
android:focusable="false"
|
||||
android:maxLines="1"
|
||||
|
||||
tools:text="Car"/>
|
||||
|
||||
</net.osmand.plus.widgets.OsmandTextFieldBoxes>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/select_nav_type_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:focusable="true"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:text="You can add own modified version of routing.xml to ..osmand/files/routing/"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/ctx_menu_info_view_bg"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/bg_shadow_list_bottom"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="10dp"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/bg_shadow_list_top"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/bg_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:textStyle="bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/list_content_padding"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:text="Setup Profile"
|
||||
android:textColor="?attr/main_font_color_basic"
|
||||
android:textSize="@dimen/default_list_text_size"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/list_content_padding"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:text="Profile keeps its own settings"
|
||||
android:textColor="@color/description_font_and_bottom_sheet_icons"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/map_config_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="65dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/map_config_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:src="@drawable/ic_action_layers_dark"
|
||||
android:tint="?attr/primary_icon_color"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Configure map"
|
||||
android:textColor="?attr/main_font_color_basic"
|
||||
android:textSize="@dimen/default_list_text_size"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Select default map options for profile"
|
||||
android:textColor="@color/description_font_and_bottom_sheet_icons"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="64dp"
|
||||
android:layout_marginLeft="64dp"
|
||||
android:background="@color/divider_light"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/screen_config_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/screen_config_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:src="@drawable/ic_configure_screen_dark"
|
||||
android:tint="?attr/primary_icon_color"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Configure screen"
|
||||
android:textColor="?attr/main_font_color_basic"
|
||||
android:textSize="@dimen/default_list_text_size"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Select default screen options for profile"
|
||||
android:textColor="@color/description_font_and_bottom_sheet_icons"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="64dp"
|
||||
android:layout_marginLeft="64dp"
|
||||
android:background="@color/divider_light"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/nav_settings_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:gravity="center_vertical"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/nav_settings_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:src="@drawable/ic_action_gdirections_dark"
|
||||
android:tint="?attr/primary_icon_color"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Navigation settings"
|
||||
android:textColor="?attr/main_font_color_basic"
|
||||
android:textSize="@dimen/default_list_text_size"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Select default navigation settings for profile"
|
||||
android:textColor="@color/description_font_and_bottom_sheet_icons"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
<include layout="@layout/list_shadow_footer"/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttons_layout_sv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?attr/bg_color"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel_button_sv"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="42dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="@dimen/list_content_padding"
|
||||
android:layout_marginBottom="@dimen/list_content_padding"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="@drawable/btn_round_profile_gray"
|
||||
android:text="@string/shared_string_cancel"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/map_widget_blue"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/save_profile_btn_sv"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="42dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="@dimen/list_content_padding"
|
||||
android:layout_marginBottom="@dimen/list_content_padding"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:background="@drawable/btn_round_profile_blue"
|
||||
android:text="@string/shared_string_save"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/color_white"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttons_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?attr/bg_color"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel_button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="42dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="@dimen/list_content_padding"
|
||||
android:layout_marginBottom="@dimen/list_content_padding"
|
||||
android:layout_marginStart="@dimen/list_content_padding"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginLeft="@dimen/list_content_padding"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="@drawable/btn_round_profile_gray"
|
||||
android:text="@string/shared_string_cancel"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/map_widget_blue"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/save_profile_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="42dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginTop="@dimen/list_content_padding"
|
||||
android:layout_marginBottom="@dimen/list_content_padding"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
android:background="@drawable/btn_round_profile_blue"
|
||||
android:text="@string/shared_string_save"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/color_white"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -35,6 +35,80 @@
|
|||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/type_selection_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding_small"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding_small"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/mode_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/bottom_sheet_icon_margin"
|
||||
android:layout_marginRight="@dimen/bottom_sheet_icon_margin"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:tint="?attr/primary_icon_color"
|
||||
tools:src="@drawable/ic_action_coordinates_latitude"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mode_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.ListItemTitle"
|
||||
android:textColor="?attr/main_font_color_basic"
|
||||
tools:text="Item Title"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mode_subtitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
tools:text="Item additional desription"/>
|
||||
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/type_down_arrow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@drawable/ic_action_arrow_drop_down"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bottom_shadow2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="5dp"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/bg_shadow_list_bottom"/>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
|
98
OsmAnd/res/layout/profile_list_item.xml
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?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:id="@+id/profile_settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/setting_profile_item_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/profile_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_marginLeft="@dimen/setting_profile_image_margin"
|
||||
android:layout_marginRight="@dimen/setting_profile_image_margin"
|
||||
tools:src="@drawable/ic_action_bicycle_dark"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/settings_divider"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:layout_weight="5">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profile_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/main_font_dark"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
tools:text="Bicycle"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profile_descr"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
tools:text="Type: Bicycle"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_action_additional_option"
|
||||
android:tint="?attr/primary_icon_color"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/setting_profile_item_switch_margin"
|
||||
android:paddingRight="10dp"
|
||||
android:paddingBottom="@dimen/setting_profile_item_switch_margin"
|
||||
android:paddingTop="@dimen/setting_profile_item_switch_margin"
|
||||
android:paddingStart="@dimen/setting_profile_item_switch_margin"
|
||||
android:paddingEnd="10dp"/>
|
||||
|
||||
<android.support.v7.widget.SwitchCompat
|
||||
android:id="@+id/profile_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="@dimen/setting_profile_item_switch_margin"
|
||||
android:paddingBottom="@dimen/setting_profile_item_switch_margin"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
50
OsmAnd/res/layout/profiles_list_fragment.xml
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/ctx_menu_info_view_bg"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/profiles_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="72dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/add_profile_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:background="@drawable/fab_extended_drawable"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginLeft="14dp"
|
||||
android:layout_marginStart="14dp"
|
||||
android:src="@drawable/ic_action_plus"/>
|
||||
|
||||
<android.support.v7.widget.AppCompatTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/shared_string_add"
|
||||
android:textColor="@color/color_white"
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
|
@ -258,6 +258,8 @@
|
|||
|
||||
<color name="shadow_color">#33888888</color>
|
||||
|
||||
<color name="compass_control_active">#EE5622</color>
|
||||
|
||||
<color name="sherpafy_selection">#ff33b5e5</color>
|
||||
<color name="sherpafy_add_text">#b9b9b9</color>
|
||||
|
||||
|
@ -455,6 +457,9 @@
|
|||
<color name="wiki_webview_background_light">#ffffff</color>
|
||||
<color name="wiki_webview_background_dark">#17191a</color>
|
||||
|
||||
<color name="text_field_box_dark">#3F474B</color>
|
||||
<color name="text_field_box_light">#eeeeee</color>
|
||||
|
||||
<!-- Basic colors -->
|
||||
<color name="app_bar_main_dark">#101112</color>
|
||||
<color name="app_bar_main_light">#ff8800</color>
|
||||
|
@ -477,5 +482,8 @@
|
|||
<color name="inactive_buttons_and_links_dark">#505050</color>
|
||||
<color name="active_buttons_and_links_trans_light">#66237bff</color>
|
||||
<color name="active_buttons_and_links_trans_dark">#66d28521</color>
|
||||
<color name="settings_divider">#dcdcdc</color>
|
||||
<color name="profile_button_gray">#EFEFEF</color>
|
||||
<color name="profile_button_gray_pressed">#ababab</color>
|
||||
|
||||
</resources>
|
|
@ -8,5 +8,8 @@
|
|||
<!-- Time control widget ids-->
|
||||
<item name="time_control_widget_state_arrival_time" type="id"/>
|
||||
<item name="time_control_widget_state_time_to_go" type="id"/>
|
||||
<!-- Compass control widget ids-->
|
||||
<item name="compass_ruler_control_widget_state_show" type="id"/>
|
||||
<item name="compass_ruler_control_widget_state_hide" type="id"/>
|
||||
|
||||
</resources>
|
|
@ -244,6 +244,7 @@
|
|||
<dimen name="bottom_sheet_title_height">52dp</dimen>
|
||||
<dimen name="bottom_sheet_descr_height">44dp</dimen>
|
||||
<dimen name="bottom_sheet_list_item_height">48dp</dimen>
|
||||
<dimen name="bottom_sheet_large_list_item_height">64dp</dimen>
|
||||
<dimen name="bottom_sheet_icon_margin">24dp</dimen>
|
||||
<dimen name="bottom_sheet_divider_margin_top">7dp</dimen>
|
||||
<dimen name="bottom_sheet_divider_margin_bottom">8dp</dimen>
|
||||
|
@ -340,4 +341,9 @@
|
|||
<dimen name="pages_item_padding">3dp</dimen>
|
||||
<dimen name="pages_item_margin">4dp</dimen>
|
||||
|
||||
|
||||
<dimen name="setting_profile_item_height">64dp</dimen>
|
||||
<dimen name="setting_profile_image_margin">24dp</dimen>
|
||||
<dimen name="setting_profile_item_switch_margin">18dp</dimen>
|
||||
|
||||
</resources>
|
|
@ -11,6 +11,44 @@
|
|||
Thx - Hardy
|
||||
|
||||
-->
|
||||
|
||||
<string name="show_compass_ruler">Show compass ruler</string>
|
||||
<string name="hide_compass_ruler">Hide compass ruler</string>
|
||||
<string name="select_icon_profile_dialog_title">Select icon</string>
|
||||
<string name="settings_routing_mode_string">Mode: %s</string>
|
||||
<string name="settings_derived_routing_mode_string">User Mode, derived from: %s</string>
|
||||
<string name="routing_profile_ski">Ski</string>
|
||||
<string name="profile_type_descr_string">Type: %s</string>
|
||||
<string name="profile_type_base_string">Base Profile</string>
|
||||
<string name="profile_alert_need_routing_type_title">Select navigation type</string>
|
||||
<string name="profile_alert_need_routing_type_msg">You need to select Navigation type to create New Application Profile</string>
|
||||
<string name="profile_alert_need_profile_name_title">Enter Profile Name</string>
|
||||
<string name="profile_alert_need_profile_name_msg">Profile name shouldn\'t be empty!</string>
|
||||
<string name="profile_alert_duplicate_name_title">Duplicate Name</string>
|
||||
<string name="profile_alert_duplicate_name_msg">There is already profile with such name</string>
|
||||
<string name="profile_alert_cant_delete_base">You cannot delete OsmAnd base profiles</string>
|
||||
<string name="profile_alert_need_save_title">Save Changes</string>
|
||||
<string name="profile_alert_need_save_msg">You need to save changes to Profile before proceed</string>
|
||||
<string name="profile_alert_delete_title">Delete Profile</string>
|
||||
<string name="profile_alert_delete_msg">Are you sure you want to delete %s profile</string>
|
||||
<string name="select_base_profile_dialog_title">Select base profile</string>
|
||||
<string name="select_base_profile_dialog_message">Custom Application Profile should be based on one of the default App Profiles. Selected Profile defines basic settings: setup of Widgets, units of speed and distance. In string below Profile\'s name, you could learn which Navigation Profiles are suitable for each Application Profile.</string>
|
||||
<string name="select_nav_profile_dialog_title">Select navigation type</string>
|
||||
<string name="base_profile_descr_car">Car, Truck, Motorcycle</string>
|
||||
<string name="base_profile_descr_bicycle">MBT, Moped, Skiing, Horse</string>
|
||||
<string name="base_profile_descr_pedestrian">Walking, Hiking, Running</string>
|
||||
<string name="base_profile_descr_public_transport">All PT types</string>
|
||||
<string name="base_profile_descr_boat">Ship, Rowing, Sailing</string>
|
||||
<string name="base_profile_descr_aircraft">Airplane, Gliding</string>
|
||||
<string name="routing_profile_geocoding">Geocoding</string>
|
||||
<string name="routing_profile_straightline">Straight Line</string>
|
||||
<string name="routing_profile_broutrer">BRouter (Offline)</string>
|
||||
<string name="osmand_default_routing">OsmAnd routing</string>
|
||||
<string name="custom_routing">Custom routing profile</string>
|
||||
<string name="special_routing_type">Special routing</string>
|
||||
<string name="third_party_routing_type">3rd-party routing</string>
|
||||
<string name="application_profiles_descr">Select the profiles to be visible in the app.</string>
|
||||
<string name="application_profiles">Application profiles</string>
|
||||
<string name="searching_gps">Searching GPS</string>
|
||||
<string name="coordinates_widget">Coordinates widget</string>
|
||||
<string name="files_moved">Moved %1$d files (%2$s).</string>
|
||||
|
@ -26,6 +64,7 @@
|
|||
<string name="public_transport_calc_pedestrian">Calculate pedestrian route</string>
|
||||
<string name="public_transport_type">Transport type</string>
|
||||
<string name="send_log">Send log</string>
|
||||
|
||||
<string name="routing_attr_avoid_tram_name">Avoid trams</string>
|
||||
<string name="routing_attr_avoid_tram_description">Avoid trams</string>
|
||||
<string name="routing_attr_avoid_bus_name">Avoid buses</string>
|
||||
|
@ -3119,4 +3158,5 @@
|
|||
<string name="routing_attr_avoid_sett_name">Avoid cobblestone and sett</string>
|
||||
<string name="routing_attr_avoid_sett_description">Avoid cobblestone and sett</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<Preference android:key="general_settings" android:title="@string/general_settings_2" android:summary="@string/general_settings_descr"/>
|
||||
<Preference android:key="application_profiles" android:title="@string/application_profiles" android:summary="@string/application_profiles_descr"/>
|
||||
<Preference android:key="routing_settings" android:title="@string/routing_settings_2" android:summary="@string/routing_settings_descr"/>
|
||||
<Preference android:key="subscription_settings" android:title="@string/osm_live_subscription" android:summary="@string/osm_live_subscription_desc"/>
|
||||
<PreferenceCategory android:key="plugin_settings" android:title="@string/plugin_settings" />
|
||||
|
|
|
@ -15,6 +15,7 @@ public class AMapPoint implements Parcelable {
|
|||
public static final String POINT_SPEED_PARAM = "point_speed_param";
|
||||
public static final String POINT_TYPE_ICON_NAME_PARAM = "point_type_icon_name_param";
|
||||
public static final String POINT_STALE_LOC_PARAM = "point_stale_loc_param";
|
||||
public static final String POINT_BEARING_PARAM = "point_bearing_param";
|
||||
|
||||
private String id;
|
||||
private String shortName;
|
||||
|
|
|
@ -11,6 +11,7 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
||||
|
@ -56,6 +57,7 @@ import net.osmand.plus.voice.TTSCommandPlayerImpl;
|
|||
import net.osmand.plus.wikivoyage.data.TravelDbHelper;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
import net.osmand.router.RoutingConfiguration;
|
||||
import net.osmand.router.RoutingConfiguration.Builder;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.OpeningHoursParser;
|
||||
|
||||
|
@ -190,7 +192,9 @@ public class AppInitializer implements IProgress {
|
|||
}
|
||||
app.getSettings().SHOW_TRAVEL_UPDATE_CARD.set(true);
|
||||
app.getSettings().SHOW_TRAVEL_NEEDED_MAPS_CARD.set(true);
|
||||
ApplicationMode.initCustomModes(app.getSettings());
|
||||
initSettings = true;
|
||||
|
||||
}
|
||||
|
||||
public int getNumberOfStarts() {
|
||||
|
@ -456,6 +460,7 @@ public class AppInitializer implements IProgress {
|
|||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
getLazyRoutingConfig();
|
||||
app.applyTheme(app);
|
||||
app.inAppPurchaseHelper = startupInit(new InAppPurchaseHelper(app), InAppPurchaseHelper.class);
|
||||
app.poiTypes = startupInit(MapPoiTypes.getDefaultNoInit(), MapPoiTypes.class);
|
||||
|
@ -492,7 +497,7 @@ public class AppInitializer implements IProgress {
|
|||
app.travelDbHelper.initTravelBooks();
|
||||
}
|
||||
app.travelDbHelper = startupInit(app.travelDbHelper, TravelDbHelper.class);
|
||||
|
||||
|
||||
|
||||
initOpeningHoursParser();
|
||||
}
|
||||
|
@ -547,31 +552,37 @@ public class AppInitializer implements IProgress {
|
|||
return object;
|
||||
}
|
||||
|
||||
|
||||
public net.osmand.router.RoutingConfiguration.Builder getLazyDefaultRoutingConfig() {
|
||||
long tm = System.currentTimeMillis();
|
||||
try {
|
||||
File routingXml = app.getAppPath(IndexConstants.ROUTING_XML_FILE);
|
||||
if (routingXml.exists() && routingXml.canRead()) {
|
||||
try {
|
||||
return RoutingConfiguration.parseFromInputStream(new FileInputStream(routingXml));
|
||||
} catch (XmlPullParserException | IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private void getLazyRoutingConfig() {
|
||||
new AsyncTask<Void, Void, RoutingConfiguration.Builder>() {
|
||||
@Override
|
||||
protected Builder doInBackground(Void... voids) {
|
||||
File routingFolder = app.getAppPath(IndexConstants.ROUTING_PROFILES_DIR);
|
||||
RoutingConfiguration.Builder builder = RoutingConfiguration.getDefault();
|
||||
if (routingFolder.isDirectory() && routingFolder.listFiles().length > 0) {
|
||||
File[] fl = routingFolder.listFiles();
|
||||
for (File f : fl) {
|
||||
if (f.isFile() && f.getName().endsWith(".xml") && f.canRead()) {
|
||||
try {
|
||||
RoutingConfiguration.parseFromInputStream(new FileInputStream(f), f.getName(), builder);
|
||||
} catch (XmlPullParserException | IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return RoutingConfiguration.getDefault();
|
||||
return builder;
|
||||
}
|
||||
} finally {
|
||||
long te = System.currentTimeMillis();
|
||||
if(te - tm > 30) {
|
||||
System.err.println("Defalt routing config init took " + (te - tm) + " ms");
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Builder builder) {
|
||||
super.onPostExecute(builder);
|
||||
app.updateRoutingConfig(builder);
|
||||
}
|
||||
}
|
||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public synchronized void initVoiceDataInDifferentThread(final Activity uiContext,
|
||||
final ApplicationMode applicationMode,
|
||||
final String voiceProvider,
|
||||
|
|
|
@ -2,6 +2,14 @@ package net.osmand.plus;
|
|||
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.StateChangedListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -12,53 +20,46 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.osmand.plus.routing.RouteProvider.RouteService;
|
||||
import net.osmand.util.Algorithms;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
|
||||
public class ApplicationMode {
|
||||
|
||||
private static final Log LOG = PlatformUtil.getLog(ApplicationMode.class);
|
||||
private static Map<String, Set<ApplicationMode>> widgetsVisibilityMap = new LinkedHashMap<>();
|
||||
private static Map<String, Set<ApplicationMode>> widgetsAvailabilityMap = new LinkedHashMap<>();
|
||||
private static List<ApplicationMode> defaultValues = new ArrayList<>();
|
||||
private static List<ApplicationMode> values = new ArrayList<>();
|
||||
private static List<ApplicationMode> cachedFilteredValues = new ArrayList<>();
|
||||
/*
|
||||
* DEFAULT("Browse map"), CAR("Car"), BICYCLE("Bicycle"), PEDESTRIAN("Pedestrian"); NAUTICAL("boat")
|
||||
* DEFAULT("Browse map"), CAR("Car"), BICYCLE("Bicycle"), PEDESTRIAN("Pedestrian"); NAUTICAL("boat"); PUBLIC_TRANSPORT("Public transport"); AIRCRAFT("Aircraft")
|
||||
*/
|
||||
public static final ApplicationMode DEFAULT = create(R.string.app_mode_default, "default").speed(1.5f, 5).arrivalDistance(90).defLocation().
|
||||
icon(R.drawable.map_world_globe_dark, R.drawable.ic_world_globe_dark).reg();
|
||||
|
||||
public static final ApplicationMode CAR = create(R.string.app_mode_car, "car").speed(15.3f, 35).carLocation().
|
||||
icon(R.drawable.map_action_car_dark, R.drawable.ic_action_car_dark).reg();
|
||||
icon(R.drawable.map_action_car_dark, R.drawable.ic_action_car_dark).setRoutingProfile("car").reg();
|
||||
|
||||
public static final ApplicationMode BICYCLE = create(R.string.app_mode_bicycle, "bicycle").speed(5.5f, 15).arrivalDistance(60).offRouteDistance(50).bicycleLocation().
|
||||
icon(R.drawable.map_action_bicycle_dark, R.drawable.ic_action_bicycle_dark).reg();
|
||||
icon(R.drawable.map_action_bicycle_dark, R.drawable.ic_action_bicycle_dark).setRoutingProfile("bicycle").reg();
|
||||
|
||||
public static final ApplicationMode PEDESTRIAN = create(R.string.app_mode_pedestrian, "pedestrian").speed(1.5f, 5).arrivalDistance(45).offRouteDistance(20).
|
||||
icon(R.drawable.map_action_pedestrian_dark, R.drawable.ic_action_pedestrian_dark).reg();
|
||||
icon(R.drawable.map_action_pedestrian_dark, R.drawable.ic_action_pedestrian_dark).setRoutingProfile("pedestrian").reg();
|
||||
|
||||
public static final ApplicationMode PUBLIC_TRANSPORT = create(R.string.app_mode_public_transport, "public_transport").
|
||||
icon(R.drawable.map_action_bus_dark, R.drawable.ic_action_bus_dark).reg();
|
||||
icon(R.drawable.map_action_bus_dark, R.drawable.ic_action_bus_dark).setRoutingProfile("public_transport").reg();
|
||||
|
||||
public static final ApplicationMode BOAT = create(R.string.app_mode_boat, "boat").speed(5.5f, 20).carLocation().nauticalLocation().
|
||||
icon(R.drawable.map_action_sail_boat_dark, R.drawable.ic_action_sail_boat_dark).reg();
|
||||
public static final ApplicationMode BOAT = create(R.string.app_mode_boat, "boat").speed(5.5f, 20).nauticalLocation().
|
||||
icon(R.drawable.map_action_sail_boat_dark, R.drawable.ic_action_sail_boat_dark).setRoutingProfile("boat").reg();
|
||||
|
||||
public static final ApplicationMode AIRCRAFT = create(R.string.app_mode_aircraft, "aircraft").speed(40f, 100).carLocation().
|
||||
icon(R.drawable.map_action_aircraft, R.drawable.ic_action_aircraft).reg();
|
||||
|
||||
public static final ApplicationMode HIKING = create(R.string.app_mode_hiking, "hiking").speed(1.5f, 5).parent(PEDESTRIAN).
|
||||
icon(R.drawable.map_action_trekking_dark, R.drawable.ic_action_trekking_dark).reg();
|
||||
|
||||
public static final ApplicationMode MOTORCYCLE = create(R.string.app_mode_motorcycle, "motorcycle").speed(15.3f, 40).
|
||||
carLocation().parent(CAR).
|
||||
icon(R.drawable.map_action_motorcycle_dark, R.drawable.ic_action_motorcycle_dark).reg();
|
||||
|
||||
public static final ApplicationMode TRUCK = create(R.string.app_mode_truck, "truck").speed(15.3f, 40).
|
||||
carLocation().parent(CAR).
|
||||
icon(R.drawable.map_action_truck_dark, R.drawable.ic_action_truck_dark).reg();
|
||||
|
||||
public static final ApplicationMode TRAIN = create(R.string.app_mode_train, "train").speed(25f, 40).
|
||||
carLocation().icon(R.drawable.map_action_train, R.drawable.ic_action_train).reg();
|
||||
icon(R.drawable.map_action_aircraft, R.drawable.ic_action_aircraft).setRouteService(RouteService.STRAIGHT).setRoutingProfile("STRAIGHT_LINE_MODE").reg();
|
||||
|
||||
static {
|
||||
ApplicationMode[] exceptDefault = new ApplicationMode[]{CAR, PEDESTRIAN, BICYCLE, BOAT, AIRCRAFT, PUBLIC_TRANSPORT, TRAIN};
|
||||
ApplicationMode[] exceptPedestrianAndDefault = new ApplicationMode[]{CAR, BICYCLE, BOAT, AIRCRAFT, PUBLIC_TRANSPORT, TRAIN};
|
||||
ApplicationMode[] exceptDefault = new ApplicationMode[]{CAR, PEDESTRIAN, BICYCLE, BOAT, AIRCRAFT, PUBLIC_TRANSPORT};
|
||||
ApplicationMode[] exceptPedestrianAndDefault = new ApplicationMode[]{CAR, BICYCLE, BOAT, AIRCRAFT, PUBLIC_TRANSPORT};
|
||||
ApplicationMode[] exceptAirBoatDefault = new ApplicationMode[]{CAR, BICYCLE, PEDESTRIAN};
|
||||
ApplicationMode[] pedestrian = new ApplicationMode[]{PEDESTRIAN};
|
||||
ApplicationMode[] pedestrianBicycle = new ApplicationMode[]{PEDESTRIAN, BICYCLE};
|
||||
|
@ -100,13 +101,16 @@ public class ApplicationMode {
|
|||
regWidgetVisibility("bgService", none);
|
||||
}
|
||||
|
||||
|
||||
private static class ApplicationModeBuilder {
|
||||
|
||||
|
||||
public static class ApplicationModeBuilder {
|
||||
private ApplicationMode applicationMode;
|
||||
|
||||
public ApplicationMode reg() {
|
||||
values.add(applicationMode);
|
||||
defaultValues.add(applicationMode);
|
||||
return applicationMode;
|
||||
}
|
||||
|
||||
public ApplicationMode customReg() {
|
||||
values.add(applicationMode);
|
||||
return applicationMode;
|
||||
}
|
||||
|
@ -117,6 +121,22 @@ public class ApplicationMode {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ApplicationModeBuilder parent(ApplicationMode parent) {
|
||||
applicationMode.parent = parent;
|
||||
String parentTypeName = parent.getStringKey();
|
||||
if (parentTypeName.equals("car") || parentTypeName.equals("aircraft")) {
|
||||
this.carLocation();
|
||||
} else if (parentTypeName.equals("bicycle")) {
|
||||
this.bicycleLocation();
|
||||
} else if (parentTypeName.equals("boat")) {
|
||||
this.nauticalLocation();
|
||||
} else {
|
||||
this.defLocation();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ApplicationModeBuilder carLocation() {
|
||||
applicationMode.bearingIconDay = R.drawable.map_car_bearing;
|
||||
applicationMode.bearingIconNight = R.drawable.map_car_bearing_night;
|
||||
|
@ -129,11 +149,6 @@ public class ApplicationMode {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ApplicationModeBuilder parent(ApplicationMode parent) {
|
||||
applicationMode.parent = parent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ApplicationModeBuilder bicycleLocation() {
|
||||
applicationMode.bearingIconDay = R.drawable.map_bicycle_bearing;
|
||||
applicationMode.bearingIconNight = R.drawable.map_bicycle_bearing_night;
|
||||
|
@ -183,6 +198,21 @@ public class ApplicationMode {
|
|||
applicationMode.offRouteDistance = offRouteDistance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ApplicationModeBuilder userProfileTitle(String userProfileTitle) {
|
||||
applicationMode.userProfileName = userProfileTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ApplicationModeBuilder setRoutingProfile(String routingProfileName) {
|
||||
applicationMode.routingProfile = routingProfileName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ApplicationModeBuilder setRouteService(RouteService service) {
|
||||
applicationMode.routeService = service;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static ApplicationModeBuilder create(int key, String stringKey) {
|
||||
|
@ -191,6 +221,10 @@ public class ApplicationMode {
|
|||
return builder;
|
||||
}
|
||||
|
||||
public static ApplicationModeBuilder createCustomMode(String userProfileTitle, String stringKey) {
|
||||
return create(-1, stringKey).userProfileTitle(userProfileTitle);
|
||||
}
|
||||
|
||||
private ApplicationMode(int key, String stringKey) {
|
||||
this.key = key;
|
||||
this.stringKey = stringKey;
|
||||
|
@ -229,9 +263,12 @@ public class ApplicationMode {
|
|||
}
|
||||
|
||||
public static List<ApplicationMode> allPossibleValues() {
|
||||
return new ArrayList<ApplicationMode>(values);
|
||||
return new ArrayList<>(values);
|
||||
}
|
||||
|
||||
public static List<ApplicationMode> getDefaultValues() {
|
||||
return new ArrayList<>(defaultValues);
|
||||
}
|
||||
|
||||
// returns modifiable ! Set<ApplicationMode> to exclude non-wanted derived
|
||||
public static Set<ApplicationMode> regWidgetVisibility(String widgetId, ApplicationMode... am) {
|
||||
|
@ -363,11 +400,24 @@ public class ApplicationMode {
|
|||
}
|
||||
|
||||
public String toHumanString(Context ctx) {
|
||||
return ctx.getString(key);
|
||||
if (Algorithms.isEmpty(userProfileName) && key != -1) {
|
||||
return ctx.getString(key);
|
||||
} else {
|
||||
return userProfileName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String toHumanStringCtx(Context ctx) {
|
||||
return ctx.getString(key);
|
||||
if (Algorithms.isEmpty(userProfileName)) {
|
||||
return ctx.getString(key);
|
||||
} else {
|
||||
return userProfileName;
|
||||
}
|
||||
}
|
||||
|
||||
public RouteService getRouteService() {
|
||||
return routeService;
|
||||
}
|
||||
|
||||
public static ApplicationMode valueOfStringKey(String key, ApplicationMode def) {
|
||||
|
@ -399,24 +449,92 @@ public class ApplicationMode {
|
|||
return this == mode || getParent() == mode;
|
||||
}
|
||||
|
||||
private final int key;
|
||||
private final String stringKey;
|
||||
public String getRoutingProfile() {
|
||||
return routingProfile;
|
||||
}
|
||||
|
||||
private ApplicationMode parent;
|
||||
private int mapIconId = R.drawable.map_world_globe_dark;
|
||||
private int smallIconDark = R.drawable.ic_world_globe_dark;
|
||||
private float defaultSpeed = 10f;
|
||||
private int minDistanceForTurn = 50;
|
||||
private int arrivalDistance = 90;
|
||||
private int offRouteDistance = 350;
|
||||
private int bearingIconDay = R.drawable.map_pedestrian_bearing;
|
||||
private int bearingIconNight = R.drawable.map_pedestrian_bearing_night;
|
||||
private int headingIconDay = R.drawable.map_pedestrian_location_view_angle;
|
||||
private int headingIconNight = R.drawable.map_pedestrian_location_view_angle_night;
|
||||
private int locationIconDay = R.drawable.map_pedestrian_location;
|
||||
private int locationIconNight = R.drawable.map_pedestrian_location_night;
|
||||
private int locationIconDayLost = R.drawable.map_pedestrian_location_lost;
|
||||
private int locationIconNightLost = R.drawable.map_pedestrian_location_lost_night;
|
||||
public String getUserProfileName() {
|
||||
return userProfileName;
|
||||
}
|
||||
|
||||
@Expose private final int key;
|
||||
@Expose private final String stringKey;
|
||||
@Expose private String userProfileName;
|
||||
@Expose private ApplicationMode parent;
|
||||
@Expose private int mapIconId = R.drawable.map_world_globe_dark;
|
||||
@Expose private int smallIconDark = R.drawable.ic_world_globe_dark;
|
||||
@Expose private float defaultSpeed = 10f;
|
||||
@Expose private int minDistanceForTurn = 50;
|
||||
@Expose private int arrivalDistance = 90;
|
||||
@Expose private int offRouteDistance = 350;
|
||||
@Expose private int bearingIconDay = R.drawable.map_pedestrian_bearing;
|
||||
@Expose private int bearingIconNight = R.drawable.map_pedestrian_bearing_night;
|
||||
@Expose private int headingIconDay = R.drawable.map_pedestrian_location_view_angle;
|
||||
@Expose private int headingIconNight = R.drawable.map_pedestrian_location_view_angle_night;
|
||||
@Expose private int locationIconDay = R.drawable.map_pedestrian_location;
|
||||
@Expose private int locationIconNight = R.drawable.map_pedestrian_location_night;
|
||||
@Expose private int locationIconDayLost = R.drawable.map_pedestrian_location_lost;
|
||||
@Expose private int locationIconNightLost = R.drawable.map_pedestrian_location_lost_night;
|
||||
@Expose private String routingProfile = null;
|
||||
@Expose private RouteService routeService = RouteService.OSMAND;
|
||||
private static StateChangedListener<String> listener;
|
||||
private static OsmAndAppCustomization.OsmAndAppCustomizationListener customizationListener;
|
||||
|
||||
public static void saveCustomModeToSettings(OsmandSettings settings){
|
||||
List<ApplicationMode> customModes = new ArrayList<>();
|
||||
for (ApplicationMode mode : values) {
|
||||
if (mode.parent != null) {
|
||||
customModes.add(mode);
|
||||
}
|
||||
}
|
||||
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
|
||||
String profiles = gson.toJson(customModes);
|
||||
settings.CUSTOM_APP_PROFILES.set(profiles);
|
||||
}
|
||||
|
||||
public static void initCustomModes(OsmandSettings settings){
|
||||
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
|
||||
Type t = new TypeToken<ArrayList<ApplicationMode>>() {}.getType();
|
||||
List<ApplicationMode> customProfiles = gson.fromJson(settings.CUSTOM_APP_PROFILES.get(), t);
|
||||
|
||||
if (!Algorithms.isEmpty(customProfiles)) {
|
||||
for (ApplicationMode m : customProfiles) {
|
||||
if (!values.contains(m)) {
|
||||
values.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteCustomMode(String userModeTitle, OsmandApplication app) {
|
||||
Iterator<ApplicationMode> it = values.iterator();
|
||||
while (it.hasNext()) {
|
||||
ApplicationMode m = it.next();
|
||||
if (m.userProfileName != null && m.userProfileName.equals(userModeTitle)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
ApplicationMode.saveCustomModeToSettings(app.getSettings());
|
||||
}
|
||||
|
||||
public static boolean changeProfileStatus(ApplicationMode mode, boolean isSelected, OsmandApplication app) {
|
||||
Set<ApplicationMode> selectedModes = new LinkedHashSet<>(ApplicationMode.values(app));
|
||||
StringBuilder vls = new StringBuilder(ApplicationMode.DEFAULT.getStringKey() + ",");
|
||||
if (allPossibleValues().contains(mode)) {
|
||||
if (isSelected) {
|
||||
selectedModes.add(mode);
|
||||
} else {
|
||||
selectedModes.remove(mode);
|
||||
if (app.getSettings().APPLICATION_MODE.get() == mode) {
|
||||
app.getSettings().APPLICATION_MODE.set(ApplicationMode.DEFAULT);
|
||||
}
|
||||
}
|
||||
for (ApplicationMode m : selectedModes) {
|
||||
vls.append(m.getStringKey()).append(",");
|
||||
}
|
||||
app.getSettings().AVAILABLE_APP_MODES.set(vls.toString());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -137,10 +137,10 @@ public class CurrentPositionHelper {
|
|||
for (BinaryMapReaderResource rep : checkReaders) {
|
||||
rs[i++] = rep.getReader(BinaryMapReaderResourceType.STREET_LOOKUP);
|
||||
}
|
||||
RoutingConfiguration cfg = app.getDefaultRoutingConfig().build(p, 10,
|
||||
RoutingConfiguration cfg = app.getRoutingConfig().build(p, 10,
|
||||
new HashMap<String, String>());
|
||||
ctx = new RoutePlannerFrontEnd().buildRoutingContext(cfg, null, rs);
|
||||
RoutingConfiguration defCfg = app.getDefaultRoutingConfig().build("geocoding", 10,
|
||||
RoutingConfiguration defCfg = app.getRoutingConfig().build("geocoding", 10,
|
||||
new HashMap<String, String>());
|
||||
defCtx = new RoutePlannerFrontEnd().buildRoutingContext(defCfg, null, rs);
|
||||
} else {
|
||||
|
|
|
@ -64,6 +64,7 @@ import net.osmand.plus.search.QuickSearchHelper;
|
|||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.plus.wikivoyage.data.TravelDbHelper;
|
||||
import net.osmand.router.RoutingConfiguration;
|
||||
import net.osmand.router.RoutingConfiguration.Builder;
|
||||
import net.osmand.search.SearchUICore;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
|
@ -127,7 +128,7 @@ public class OsmandApplication extends MultiDexApplication {
|
|||
InAppPurchaseHelper inAppPurchaseHelper;
|
||||
MapViewTrackingUtilities mapViewTrackingUtilities;
|
||||
|
||||
RoutingConfiguration.Builder defaultRoutingConfig;
|
||||
private RoutingConfiguration.Builder routingConfig;
|
||||
private Locale preferredLocale = null;
|
||||
private Locale defaultLocale;
|
||||
private File externalStorageDirectory;
|
||||
|
@ -797,13 +798,20 @@ public class OsmandApplication extends MultiDexApplication {
|
|||
return lang;
|
||||
}
|
||||
|
||||
public synchronized RoutingConfiguration.Builder getDefaultRoutingConfig() {
|
||||
if(defaultRoutingConfig == null) {
|
||||
defaultRoutingConfig = appInitializer.getLazyDefaultRoutingConfig();
|
||||
public synchronized RoutingConfiguration.Builder getRoutingConfig() {
|
||||
RoutingConfiguration.Builder rc;
|
||||
if(routingConfig == null) {
|
||||
rc = new RoutingConfiguration.Builder();
|
||||
} else {
|
||||
rc = routingConfig;
|
||||
}
|
||||
return defaultRoutingConfig;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
public void updateRoutingConfig(Builder update) {
|
||||
routingConfig = update;
|
||||
}
|
||||
|
||||
public OsmandRegions getRegions() {
|
||||
return regions;
|
||||
}
|
||||
|
|
|
@ -803,6 +803,8 @@ public class OsmandSettings {
|
|||
|
||||
public final CommonPreference<RulerMode> RULER_MODE = new EnumIntPreference<>("ruler_mode", RulerMode.FIRST, RulerMode.values()).makeGlobal();
|
||||
|
||||
public final OsmandPreference<Boolean> SHOW_COMPASS_CONTROL_RULER = new BooleanPreference("show_compass_ruler", true).makeGlobal();
|
||||
|
||||
public final CommonPreference<Boolean> SHOW_LINES_TO_FIRST_MARKERS = new BooleanPreference("show_lines_to_first_markers", false).makeProfile();
|
||||
public final CommonPreference<Boolean> SHOW_ARROWS_TO_FIRST_MARKERS = new BooleanPreference("show_arrows_to_first_markers", false).makeProfile();
|
||||
|
||||
|
@ -2745,6 +2747,9 @@ public class OsmandSettings {
|
|||
RateUsBottomSheetDialog.RateUsState.INITIAL_STATE, RateUsBottomSheetDialog.RateUsState.values())
|
||||
.makeGlobal();
|
||||
|
||||
public final CommonPreference<String> CUSTOM_APP_PROFILES =
|
||||
new StringPreference("custom_profiles", "").makeGlobal().cache();
|
||||
|
||||
|
||||
public enum DayNightMode {
|
||||
AUTO(R.string.daynight_mode_auto, R.drawable.ic_action_map_sunst),
|
||||
|
|
|
@ -9,8 +9,11 @@ import android.support.v7.widget.Toolbar;
|
|||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import android.widget.TextView;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
|
@ -56,6 +59,7 @@ public abstract class ActionBarPreferenceActivity extends AppCompatPreferenceAct
|
|||
});
|
||||
|
||||
getSpinner().setVisibility(View.GONE);
|
||||
getTypeButton().setVisibility(View.GONE);
|
||||
setProgressVisibility(false);
|
||||
}
|
||||
|
||||
|
@ -81,6 +85,25 @@ public abstract class ActionBarPreferenceActivity extends AppCompatPreferenceAct
|
|||
return (Spinner) findViewById(R.id.spinner_nav);
|
||||
}
|
||||
|
||||
protected LinearLayout getTypeButton() {
|
||||
return (LinearLayout) findViewById(R.id.type_selection_button);
|
||||
}
|
||||
|
||||
protected TextView getModeTitleTV() {
|
||||
return (TextView) findViewById(R.id.mode_title);
|
||||
}
|
||||
|
||||
protected TextView getModeSubTitleTV() {
|
||||
return (TextView) findViewById(R.id.mode_subtitle);
|
||||
}
|
||||
|
||||
protected ImageView getModeIconIV() {
|
||||
return (ImageView) findViewById(R.id.mode_icon);
|
||||
}
|
||||
protected ImageView getDropDownArrow() {
|
||||
return (ImageView) findViewById(R.id.type_down_arrow);
|
||||
}
|
||||
|
||||
protected void setProgressVisibility(boolean visibility) {
|
||||
if (visibility) {
|
||||
findViewById(R.id.ProgressBar).setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
package net.osmand.plus.activities;
|
||||
import android.app.FragmentManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
|
|
@ -82,6 +82,7 @@ import net.osmand.plus.base.FailSafeFuntions;
|
|||
import net.osmand.plus.base.MapViewTrackingUtilities;
|
||||
import net.osmand.plus.chooseplan.OsmLiveCancelledDialog;
|
||||
import net.osmand.plus.dashboard.DashboardOnMap;
|
||||
import net.osmand.plus.dashboard.DashboardOnMap.DashboardType;
|
||||
import net.osmand.plus.dialogs.ErrorBottomSheetDialog;
|
||||
import net.osmand.plus.dialogs.RateUsBottomSheetDialog;
|
||||
import net.osmand.plus.dialogs.WhatsNewDialogFragment;
|
||||
|
@ -107,6 +108,7 @@ import net.osmand.plus.mapmarkers.PlanRouteFragment;
|
|||
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
||||
import net.osmand.plus.measurementtool.MeasurementToolFragment;
|
||||
import net.osmand.plus.measurementtool.NewGpxData;
|
||||
import net.osmand.plus.profiles.EditProfileFragment;
|
||||
import net.osmand.plus.render.RendererRegistry;
|
||||
import net.osmand.plus.resources.ResourceManager;
|
||||
import net.osmand.plus.routepreparationmenu.ChooseRouteFragment;
|
||||
|
@ -782,6 +784,19 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
|
|||
}
|
||||
setIntent(null);
|
||||
}
|
||||
if (intent.hasExtra(EditProfileFragment.OPEN_CONFIG_ON_MAP)) {
|
||||
switch (intent.getStringExtra(EditProfileFragment.OPEN_CONFIG_ON_MAP)) {
|
||||
case EditProfileFragment.MAP_CONFIG:
|
||||
this.getDashboard().setDashboardVisibility(true, DashboardType.CONFIGURE_MAP, null);
|
||||
break;
|
||||
|
||||
case EditProfileFragment.SCREEN_CONFIG:
|
||||
this.getDashboard().setDashboardVisibility(true, DashboardType.CONFIGURE_SCREEN, null);
|
||||
break;
|
||||
}
|
||||
setIntent(null);
|
||||
}
|
||||
|
||||
}
|
||||
mapView.refreshMap(true);
|
||||
if (atlasMapRendererView != null) {
|
||||
|
|
|
@ -14,6 +14,7 @@ import net.osmand.plus.OsmandPlugin;
|
|||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.liveupdates.OsmLiveActivity;
|
||||
import net.osmand.plus.profiles.SettingsProfileActivity;
|
||||
|
||||
public class SettingsActivity extends SettingsBaseActivity {
|
||||
|
||||
|
@ -28,6 +29,7 @@ public class SettingsActivity extends SettingsBaseActivity {
|
|||
private Preference general;
|
||||
private Preference routing;
|
||||
private Preference subscription;
|
||||
private Preference profiles;
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -40,6 +42,8 @@ public class SettingsActivity extends SettingsBaseActivity {
|
|||
general.setOnPreferenceClickListener(this);
|
||||
routing = (Preference) screen.findPreference("routing_settings");
|
||||
routing.setOnPreferenceClickListener(this);
|
||||
profiles = (Preference) screen.findPreference("application_profiles");
|
||||
profiles.setOnPreferenceClickListener(this);
|
||||
subscription = (Preference) screen.findPreference("subscription_settings");
|
||||
subscription.setOnPreferenceClickListener(this);
|
||||
|
||||
|
@ -88,6 +92,9 @@ public class SettingsActivity extends SettingsBaseActivity {
|
|||
if (preference == general) {
|
||||
startActivity(new Intent(this, SettingsGeneralActivity.class));
|
||||
return true;
|
||||
} else if (preference == profiles){
|
||||
startActivity(new Intent(this, SettingsProfileActivity.class));
|
||||
return true;
|
||||
} else if (preference == routing) {
|
||||
startActivity(new Intent(this, SettingsNavigationActivity.class));
|
||||
return true;
|
||||
|
|
|
@ -2,6 +2,8 @@ package net.osmand.plus.activities;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.DialogInterface.OnDismissListener;
|
||||
import android.content.DialogInterface.OnMultiChoiceClickListener;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
|
@ -13,12 +15,12 @@ import android.preference.Preference.OnPreferenceClickListener;
|
|||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AlertDialog.Builder;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
|
@ -38,6 +40,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
|
||||
public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
|
||||
|
@ -48,7 +51,7 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
|
|||
protected OsmandSettings settings;
|
||||
protected final boolean profileSettings;
|
||||
protected List<ApplicationMode> modes = new ArrayList<ApplicationMode>();
|
||||
private ApplicationMode previousAppMode;
|
||||
private ApplicationMode previousAppMode;
|
||||
|
||||
private Map<String, Preference> screenPreferences = new LinkedHashMap<String, Preference>();
|
||||
private Map<String, OsmandPreference<Boolean>> booleanPreferences = new LinkedHashMap<String, OsmandPreference<Boolean>>();
|
||||
|
@ -328,7 +331,6 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
|
|||
settings = app.getSettings();
|
||||
getToolbar().setTitle(R.string.shared_string_settings);
|
||||
|
||||
|
||||
if (profileSettings) {
|
||||
modes.clear();
|
||||
for (ApplicationMode a : ApplicationMode.values(app)) {
|
||||
|
@ -336,52 +338,63 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
|
|||
modes.add(a);
|
||||
}
|
||||
}
|
||||
List<String> s = new ArrayList<String>();
|
||||
for (ApplicationMode a : modes) {
|
||||
s.add(a.toHumanString(app));
|
||||
}
|
||||
SpinnerAdapter spinnerAdapter = new SpinnerAdapter(this,
|
||||
R.layout.spinner_item, s);
|
||||
// android.R.layout.simple_spinner_dropdown_item
|
||||
spinnerAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
|
||||
getSpinner().setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
settings.APPLICATION_MODE.set(modes.get(position));
|
||||
updateAllSettings();
|
||||
}
|
||||
|
||||
getTypeButton().setVisibility(View.VISIBLE);
|
||||
getTypeButton().setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
|
||||
public void onClick(View v) {
|
||||
AlertDialog.Builder singleSelectDialogBuilder = new Builder(SettingsBaseActivity.this);
|
||||
singleSelectDialogBuilder.setTitle("Select App Profile");
|
||||
final ArrayAdapter<String> modeNames = new ArrayAdapter<>(
|
||||
SettingsBaseActivity.this, android.R.layout.select_dialog_singlechoice);
|
||||
for (ApplicationMode am : modes) {
|
||||
modeNames.add(am.toHumanString(SettingsBaseActivity.this));
|
||||
}
|
||||
singleSelectDialogBuilder.setNegativeButton(R.string.shared_string_cancel,
|
||||
new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
singleSelectDialogBuilder.setAdapter(modeNames, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
settings.APPLICATION_MODE.set(modes.get(which));
|
||||
updateModeButton(modes.get(which));
|
||||
updateAllSettings();
|
||||
}
|
||||
});
|
||||
singleSelectDialogBuilder.show();
|
||||
}
|
||||
});
|
||||
getSpinner().setAdapter(spinnerAdapter);
|
||||
getSpinner().setVisibility(View.VISIBLE);
|
||||
|
||||
}
|
||||
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(this));
|
||||
}
|
||||
|
||||
|
||||
class SpinnerAdapter extends ArrayAdapter<String>{
|
||||
|
||||
|
||||
public SpinnerAdapter(Context context, int resource, List<String> objects) {
|
||||
super(context, resource, objects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getDropDownView(int position, View convertView, ViewGroup parent) {
|
||||
View view = super.getDropDownView(position, convertView, parent);
|
||||
if (!settings.isLightActionBar()){
|
||||
TextView textView = (TextView) view.findViewById(android.R.id.text1);
|
||||
textView.setBackgroundColor(getResources().getColor(R.color.actionbar_dark_color));
|
||||
}
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void updateModeButton(ApplicationMode mode) {
|
||||
String title = Algorithms.isEmpty(mode.getUserProfileName())
|
||||
? mode.toHumanString(SettingsBaseActivity.this)
|
||||
: mode.getUserProfileName();
|
||||
String subtitle = mode.getParent() == null
|
||||
? String.format(getString(R.string.settings_routing_mode_string), Algorithms
|
||||
.capitalizeFirstLetterAndLowercase(mode.getStringKey().replace("_", "")))
|
||||
: String.format(getString(R.string.settings_derived_routing_mode_string), Algorithms
|
||||
.capitalizeFirstLetterAndLowercase(mode.getParent().getStringKey()));
|
||||
getModeTitleTV().setText(title);
|
||||
getModeSubTitleTV().setText(subtitle);
|
||||
getModeIconIV().setImageDrawable(getMyApplication().getUIUtilities().getIcon(mode.getSmallIconDark(),
|
||||
getMyApplication().getSettings().isLightContent()
|
||||
? R.color.active_buttons_and_links_light
|
||||
: R.color.active_buttons_and_links_dark));
|
||||
getDropDownArrow().setImageDrawable(getMyApplication().getUIUtilities().getIcon(R.drawable.ic_action_arrow_drop_down,
|
||||
getMyApplication().getSettings().isLightContent()
|
||||
? R.color.active_buttons_and_links_light
|
||||
: R.color.active_buttons_and_links_dark));
|
||||
settings.APPLICATION_MODE.set(mode);
|
||||
updateAllSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
|
@ -421,6 +434,14 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
|
|||
profileDialog = null;
|
||||
}
|
||||
});
|
||||
b.setOnDismissListener(new OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
if (selected.size() == 0) {
|
||||
setSelectedAppMode(ApplicationMode.CAR);
|
||||
}
|
||||
}
|
||||
});
|
||||
b.setTitle(R.string.profile_settings);
|
||||
b.setView(v);
|
||||
profileDialog = b.show();
|
||||
|
@ -431,7 +452,7 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
|
|||
boolean found = false;
|
||||
for (ApplicationMode a : modes) {
|
||||
if (am == a) {
|
||||
getSpinner().setSelection(ind);
|
||||
updateModeButton(a);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -541,7 +562,7 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void showBooleanSettings(String[] vals, final OsmandPreference<Boolean>[] prefs) {
|
||||
AlertDialog.Builder bld = new AlertDialog.Builder(this);
|
||||
|
|
|
@ -503,6 +503,7 @@ public class SettingsGeneralActivity extends SettingsBaseActivity implements OnR
|
|||
misc.addPreference(createCheckBoxPreference(settings.DO_NOT_USE_ANIMATIONS, R.string.do_not_use_animations, R.string.do_not_use_animations_descr));
|
||||
misc.addPreference(createCheckBoxPreference(settings.MAP_EMPTY_STATE_ALLOWED, R.string.tap_on_map_to_hide_interface, R.string.tap_on_map_to_hide_interface_descr));
|
||||
misc.addPreference(createCheckBoxPreference(settings.DO_NOT_SHOW_STARTUP_MESSAGES, R.string.do_not_show_startup_messages, R.string.do_not_show_startup_messages_desc));
|
||||
misc.addPreference(createCheckBoxPreference(settings.ANIMATE_MY_LOCATION,R.string.animate_my_location, R.string.animate_my_location_desc));
|
||||
OsmandApplication app = getMyApplication();
|
||||
if (Version.isGooglePlayEnabled(getMyApplication()) && !Version.isPaidVersion(app)) {
|
||||
misc.addPreference(createCheckBoxPreference(settings.DO_NOT_SEND_ANONYMOUS_APP_USAGE, R.string.do_not_send_anonymous_app_usage, R.string.do_not_send_anonymous_app_usage_desc));
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.view.ViewGroup;
|
|||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
import net.osmand.plus.ContextMenuAdapter;
|
||||
import net.osmand.plus.ContextMenuItem;
|
||||
|
@ -46,10 +47,10 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
|
||||
public class SettingsNavigationActivity extends SettingsBaseActivity {
|
||||
|
||||
public static final String MORE_VALUE = "MORE_VALUE";
|
||||
|
||||
private Preference avoidRouting;
|
||||
|
@ -75,7 +76,6 @@ public class SettingsNavigationActivity extends SettingsBaseActivity {
|
|||
((OsmandApplication) getApplication()).applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
getToolbar().setTitle(R.string.routing_settings);
|
||||
|
||||
createUI();
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,6 @@ public class SettingsNavigationActivity extends SettingsBaseActivity {
|
|||
PreferenceScreen screen = getPreferenceScreen();
|
||||
settings = getMyApplication().getSettings();
|
||||
routerServicePreference = (ListPreference) screen.findPreference(settings.ROUTER_SERVICE.getId());
|
||||
|
||||
RouteService[] vls = RouteService.getAvailableRouters(getMyApplication());
|
||||
String[] entries = new String[vls.length];
|
||||
for(int i=0; i<entries.length; i++){
|
||||
|
@ -245,7 +244,7 @@ public class SettingsNavigationActivity extends SettingsBaseActivity {
|
|||
cat.addPreference(fastRoute);
|
||||
} else {
|
||||
ApplicationMode am = settings.getApplicationMode();
|
||||
GeneralRouter router = getRouter(getMyApplication().getDefaultRoutingConfig(), am);
|
||||
GeneralRouter router = getRouter(getMyApplication().getRoutingConfig(), am);
|
||||
clearParameters();
|
||||
if (router != null) {
|
||||
Map<String, RoutingParameter> parameters = router.getParameters();
|
||||
|
@ -355,7 +354,7 @@ public class SettingsNavigationActivity extends SettingsBaseActivity {
|
|||
|
||||
|
||||
public static GeneralRouter getRouter(net.osmand.router.RoutingConfiguration.Builder builder, ApplicationMode am) {
|
||||
GeneralRouter router = builder.getRouter(am.getStringKey());
|
||||
GeneralRouter router = builder.getRouter(am.getRoutingProfile());
|
||||
if(router == null && am.getParent() != null) {
|
||||
router = builder.getRouter(am.getParent().getStringKey());
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import android.preference.PreferenceScreen;
|
|||
import android.support.v7.app.AlertDialog;
|
||||
import android.view.View;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.StateChangedListener;
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
import net.osmand.plus.OsmAndLocationSimulation;
|
||||
|
@ -22,6 +23,7 @@ import net.osmand.plus.OsmandSettings;
|
|||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.SettingsBaseActivity;
|
||||
import net.osmand.plus.activities.actions.AppModeDialog;
|
||||
import net.osmand.plus.profiles.SettingsProfileFragment;
|
||||
import net.osmand.util.SunriseSunset;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
@ -42,26 +44,9 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
|
|||
PreferenceScreen cat = getPreferenceScreen();
|
||||
Preference pref;
|
||||
|
||||
// 2 should be in main settings
|
||||
cat.addPreference(createCheckBoxPreference(settings.USE_OPENGL_RENDER,
|
||||
R.string.use_opengl_render,R.string.use_opengl_render_descr));
|
||||
|
||||
cat.addPreference(createCheckBoxPreference(settings.ANIMATE_MY_LOCATION,
|
||||
R.string.animate_my_location, R.string.animate_my_location_desc));
|
||||
|
||||
pref = new Preference(this);
|
||||
pref.setTitle(R.string.app_modes_choose);
|
||||
pref.setSummary(R.string.app_modes_choose_descr);
|
||||
pref.setKey("available_application_modes");
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
availableProfileDialog();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
cat.addPreference(pref);
|
||||
|
||||
PreferenceCategory navigation = new PreferenceCategory(this);
|
||||
navigation.setTitle(R.string.routing_settings);
|
||||
cat.addPreference(navigation);
|
||||
|
@ -225,30 +210,4 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
|
|||
//pref.setEnabled(false);
|
||||
info.addPreference(pref);
|
||||
}
|
||||
|
||||
protected void availableProfileDialog() {
|
||||
AlertDialog.Builder b = new AlertDialog.Builder(this);
|
||||
final List<ApplicationMode> modes = ApplicationMode.allPossibleValues();
|
||||
modes.remove(ApplicationMode.DEFAULT);
|
||||
final Set<ApplicationMode> selected = new LinkedHashSet<ApplicationMode>(ApplicationMode.values(getMyApplication()));
|
||||
selected.remove(ApplicationMode.DEFAULT);
|
||||
View v = AppModeDialog.prepareAppModeView(this, modes, selected, null, false, true, false,
|
||||
new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
StringBuilder vls = new StringBuilder(ApplicationMode.DEFAULT.getStringKey()+",");
|
||||
for(ApplicationMode mode : modes) {
|
||||
if(selected.contains(mode)) {
|
||||
vls.append(mode.getStringKey()).append(",");
|
||||
}
|
||||
}
|
||||
settings.AVAILABLE_APP_MODES.set(vls.toString());
|
||||
}
|
||||
});
|
||||
b.setTitle(R.string.profile_settings);
|
||||
b.setPositiveButton(R.string.shared_string_ok, null);
|
||||
b.setView(v);
|
||||
b.show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ public class AvoidSpecificRoads {
|
|||
app.getSettings().removeImpassableRoad(latLon);
|
||||
RouteDataObject obj = impassableRoads.remove(latLon);
|
||||
if (obj != null) {
|
||||
app.getDefaultRoutingConfig().removeImpassableRoad(obj);
|
||||
app.getRoutingConfig().removeImpassableRoad(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,7 +254,7 @@ public class AvoidSpecificRoads {
|
|||
final LatLon oldLoc = getLocation(currentObject);
|
||||
app.getSettings().moveImpassableRoad(oldLoc, newLoc);
|
||||
impassableRoads.remove(oldLoc);
|
||||
app.getDefaultRoutingConfig().removeImpassableRoad(currentObject);
|
||||
app.getRoutingConfig().removeImpassableRoad(currentObject);
|
||||
addImpassableRoadInternal(object, ll, showDialog, activity, newLoc);
|
||||
|
||||
if (callback != null) {
|
||||
|
@ -276,7 +276,7 @@ public class AvoidSpecificRoads {
|
|||
boolean showDialog,
|
||||
@Nullable MapActivity activity,
|
||||
@NonNull LatLon loc) {
|
||||
if (app.getDefaultRoutingConfig().addImpassableRoad(object, ll)) {
|
||||
if (app.getRoutingConfig().addImpassableRoad(object, ll)) {
|
||||
impassableRoads.put(loc, object);
|
||||
} else {
|
||||
LatLon location = getLocation(object);
|
||||
|
@ -305,7 +305,7 @@ public class AvoidSpecificRoads {
|
|||
}
|
||||
|
||||
public LatLon getLocation(RouteDataObject object) {
|
||||
Location location = app.getDefaultRoutingConfig().getImpassableRoadLocations().get(object.getId());
|
||||
Location location = app.getRoutingConfig().getImpassableRoadLocations().get(object.getId());
|
||||
return location == null ? null : new LatLon(location.getLatitude(), location.getLongitude());
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.Map;
|
|||
|
||||
public class AMapPointMenuController extends MenuController {
|
||||
|
||||
private static final float NO_SPEED = -1;
|
||||
private static final float NO_VALUE = -1;
|
||||
private static final int NO_ICON = 0;
|
||||
|
||||
private AMapPoint point;
|
||||
|
@ -136,19 +136,40 @@ public class AMapPointMenuController extends MenuController {
|
|||
public CharSequence getAdditionalInfoStr() {
|
||||
MapActivity activity = getMapActivity();
|
||||
if (activity != null) {
|
||||
float speed = getPointSpeed();
|
||||
if (speed != NO_SPEED) {
|
||||
String formatted = OsmAndFormatter.getFormattedSpeed(speed, activity.getMyApplication());
|
||||
return activity.getString(R.string.map_widget_speed) + ": " + formatted;
|
||||
float bearing = getPointBearing();
|
||||
if (bearing != NO_VALUE) {
|
||||
return OsmAndFormatter.getFormattedAzimuth(bearing, activity.getMyApplication());
|
||||
}
|
||||
}
|
||||
return super.getAdditionalInfoStr();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getSubtypeStr() {
|
||||
MapActivity activity = getMapActivity();
|
||||
if (activity != null) {
|
||||
float speed = getPointSpeed();
|
||||
if (speed != NO_VALUE) {
|
||||
return OsmAndFormatter.getFormattedSpeed(speed, activity.getMyApplication());
|
||||
}
|
||||
}
|
||||
return super.getSubtypeStr();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Drawable getSubtypeIcon() {
|
||||
if (getPointSpeed() != NO_VALUE) {
|
||||
return getIcon(R.drawable.ic_action_speed_16);
|
||||
}
|
||||
return super.getSubtypeIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAdditionalInfoIconRes() {
|
||||
if (getPointSpeed() != NO_SPEED) {
|
||||
return R.drawable.ic_action_speed_16;
|
||||
if (getPointBearing() != NO_VALUE) {
|
||||
return R.drawable.ic_action_bearing;
|
||||
}
|
||||
return super.getAdditionalInfoIconRes();
|
||||
}
|
||||
|
@ -214,10 +235,22 @@ public class AMapPointMenuController extends MenuController {
|
|||
try {
|
||||
return Float.parseFloat(speed);
|
||||
} catch (NumberFormatException e) {
|
||||
return NO_SPEED;
|
||||
return NO_VALUE;
|
||||
}
|
||||
}
|
||||
return NO_SPEED;
|
||||
return NO_VALUE;
|
||||
}
|
||||
|
||||
private float getPointBearing() {
|
||||
String bearing = point.getParams().get(AMapPoint.POINT_BEARING_PARAM);
|
||||
if (!TextUtils.isEmpty(bearing)) {
|
||||
try {
|
||||
return Float.parseFloat(bearing);
|
||||
} catch (NumberFormatException e) {
|
||||
return NO_VALUE;
|
||||
}
|
||||
}
|
||||
return NO_VALUE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
70
OsmAnd/src/net/osmand/plus/profiles/EditProfileActivity.java
Normal file
|
@ -0,0 +1,70 @@
|
|||
package net.osmand.plus.profiles;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.OsmandActionBarActivity;
|
||||
|
||||
public class EditProfileActivity extends OsmandActionBarActivity {
|
||||
|
||||
public static final int DELETE_ID = 1010;
|
||||
public static final String EDIT_PROFILE_FRAGMENT_TAG = "editProfileFragment";
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
getMyApplication().applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.single_fragment_layout);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
EditProfileFragment editProfileFragment = new EditProfileFragment();
|
||||
editProfileFragment.setArguments(getIntent().getExtras());
|
||||
getSupportFragmentManager().beginTransaction().add(android.R.id.content,
|
||||
editProfileFragment, EDIT_PROFILE_FRAGMENT_TAG).commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuItem m = menu.add(0, DELETE_ID, 0, R.string.action_delete)
|
||||
.setIcon(R.drawable.ic_action_delete_dark);
|
||||
MenuItemCompat.setShowAsAction(m, MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
super.onCreateOptionsMenu(menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
int itemId = item.getItemId();
|
||||
switch (itemId) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
case DELETE_ID:
|
||||
((EditProfileFragment) getSupportFragmentManager().findFragmentByTag(
|
||||
EDIT_PROFILE_FRAGMENT_TAG)).onDeleteProfileClick();
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
final EditProfileFragment epf = (EditProfileFragment) getSupportFragmentManager()
|
||||
.findFragmentByTag(EDIT_PROFILE_FRAGMENT_TAG);
|
||||
if (epf.onBackPressedAllowed()) {
|
||||
super.onBackPressed();
|
||||
} else {
|
||||
epf.confirmCancelDialog(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
790
OsmAnd/src/net/osmand/plus/profiles/EditProfileFragment.java
Normal file
|
@ -0,0 +1,790 @@
|
|||
package net.osmand.plus.profiles;
|
||||
|
||||
import static net.osmand.plus.activities.SettingsNavigationActivity.INTENT_SKIP_DIALOG;
|
||||
import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.DIALOG_TYPE;
|
||||
import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.SELECTED_KEY;
|
||||
import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.TYPE_APP_PROFILE;
|
||||
import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.TYPE_ICON;
|
||||
import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.TYPE_NAV_PROFILE;
|
||||
import static net.osmand.plus.profiles.SettingsProfileFragment.IS_NEW_PROFILE;
|
||||
import static net.osmand.plus.profiles.SettingsProfileFragment.IS_USER_PROFILE;
|
||||
import static net.osmand.plus.profiles.SettingsProfileFragment.PROFILE_STRING_KEY;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnDismissListener;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AlertDialog.Builder;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.OsmandActionBarActivity;
|
||||
import net.osmand.plus.activities.SettingsNavigationActivity;
|
||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||
import net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.SelectProfileListener;
|
||||
import net.osmand.plus.routing.RouteProvider.RouteService;
|
||||
import net.osmand.plus.widgets.OsmandTextFieldBoxes;
|
||||
import net.osmand.router.GeneralRouter;
|
||||
import net.osmand.util.Algorithms;
|
||||
import org.apache.commons.logging.Log;
|
||||
import studio.carbonylgroup.textfieldboxes.ExtendedEditText;
|
||||
|
||||
public class EditProfileFragment extends BaseOsmAndFragment {
|
||||
|
||||
private static final Log LOG = PlatformUtil.getLog(EditProfileFragment.class);
|
||||
|
||||
public static final String OPEN_CONFIG_ON_MAP = "openConfigOnMap";
|
||||
public static final String MAP_CONFIG = "openMapConfigMenu";
|
||||
public static final String NAV_CONFIG = "openNavConfigMenu";
|
||||
public static final String SCREEN_CONFIG = "openScreenConfigMenu";
|
||||
public static final String SELECTED_ITEM = "editedProfile";
|
||||
public static final String SELECTED_ICON = "selectedIcon";
|
||||
|
||||
OsmandApplication app;
|
||||
|
||||
ApplicationMode mode = null;
|
||||
ApplicationProfileObject profile = null;
|
||||
List<RoutingProfileDataObject> routingProfileDataObjects;
|
||||
RoutingProfileDataObject selectedRoutingProfileDataObject = null;
|
||||
|
||||
private boolean isNew = false;
|
||||
private boolean isUserProfile = false;
|
||||
private boolean isDataChanged = false;
|
||||
private boolean isCancelAllowed = true;
|
||||
private boolean isNightMode;
|
||||
|
||||
private SelectProfileListener navTypeListener = null;
|
||||
private SelectProfileListener iconIdListener = null;
|
||||
private SelectProfileListener baseTypeListener = null;
|
||||
|
||||
private ImageView profileIcon;
|
||||
private LinearLayout profileIconBtn;
|
||||
private ExtendedEditText profileNameEt;
|
||||
private OsmandTextFieldBoxes profileNameTextBox;
|
||||
private ExtendedEditText navTypeEt;
|
||||
private OsmandTextFieldBoxes navTypeTextBox;
|
||||
private FrameLayout selectNavTypeBtn;
|
||||
private Button cancelBtn;
|
||||
private Button saveButton;
|
||||
private View mapConfigBtn;
|
||||
private View screenConfigBtn;
|
||||
private View navConfigBtn;
|
||||
private LinearLayout buttonsLayout;
|
||||
private FrameLayout clickBlockLayout;
|
||||
private LinearLayout typeSelectionBtn;
|
||||
private ImageView baseModeIcon;
|
||||
private TextView baseModeTitle;
|
||||
private ScrollView scrollContainer;
|
||||
private LinearLayout buttonsLayoutSV;
|
||||
private Button cancelBtnSV;
|
||||
private Button saveButtonSV;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
app = getMyApplication();
|
||||
if (getArguments() != null) {
|
||||
String modeName = getArguments().getString(PROFILE_STRING_KEY, "car");
|
||||
isNew = getArguments().getBoolean(IS_NEW_PROFILE, false);
|
||||
isUserProfile = getArguments().getBoolean(IS_USER_PROFILE, false);
|
||||
mode = ApplicationMode.valueOfStringKey(modeName, ApplicationMode.DEFAULT);
|
||||
profile = new ApplicationProfileObject(mode, isNew, isUserProfile);
|
||||
}
|
||||
isNightMode = !app.getSettings().isLightContent();
|
||||
routingProfileDataObjects = getRoutingProfiles(app);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
final View view = inflater.inflate(R.layout.fragment_selected_profile, container, false);
|
||||
|
||||
profileIcon = view.findViewById(R.id.select_icon_btn_img);
|
||||
profileIconBtn = view.findViewById(R.id.profile_icon_layout);
|
||||
profileNameEt = view.findViewById(R.id.profile_name_et);
|
||||
profileNameTextBox = view.findViewById(R.id.profile_name_otfb);
|
||||
navTypeEt = view.findViewById(R.id.navigation_type_et);
|
||||
navTypeTextBox = view.findViewById(R.id.navigation_type_otfb);
|
||||
selectNavTypeBtn = view.findViewById(R.id.select_nav_type_btn);
|
||||
cancelBtn = view.findViewById(R.id.cancel_button);
|
||||
saveButton = view.findViewById(R.id.save_profile_btn);
|
||||
mapConfigBtn = view.findViewById(R.id.map_config_btn);
|
||||
screenConfigBtn = view.findViewById(R.id.screen_config_btn);
|
||||
navConfigBtn = view.findViewById(R.id.nav_settings_btn);
|
||||
buttonsLayout = view.findViewById(R.id.buttons_layout);
|
||||
clickBlockLayout = view.findViewById(R.id.click_block_layout);
|
||||
typeSelectionBtn = view.findViewById(R.id.type_selection_button);
|
||||
baseModeIcon = view.findViewById(R.id.mode_icon);
|
||||
baseModeTitle = view.findViewById(R.id.mode_title);
|
||||
scrollContainer = view.findViewById(R.id.scroll_view_container);
|
||||
buttonsLayoutSV = view.findViewById(R.id.buttons_layout_sv);
|
||||
cancelBtnSV = view.findViewById(R.id.cancel_button_sv);
|
||||
saveButtonSV = view.findViewById(R.id.save_profile_btn_sv);
|
||||
|
||||
profileNameEt.setFocusable(true);
|
||||
profileNameEt.setSelectAllOnFocus(true);
|
||||
profileIconBtn.setBackgroundResource(R.drawable.rounded_background_3dp);
|
||||
GradientDrawable selectIconBtnBackground = (GradientDrawable) profileIconBtn
|
||||
.getBackground();
|
||||
|
||||
if (isNightMode) {
|
||||
profileNameTextBox
|
||||
.setPrimaryColor(ContextCompat.getColor(app, R.color.color_dialog_buttons_dark));
|
||||
navTypeTextBox
|
||||
.setPrimaryColor(ContextCompat.getColor(app, R.color.color_dialog_buttons_dark));
|
||||
selectIconBtnBackground
|
||||
.setColor(app.getResources().getColor(R.color.text_field_box_dark));
|
||||
} else {
|
||||
selectIconBtnBackground
|
||||
.setColor(app.getResources().getColor(R.color.text_field_box_light));
|
||||
}
|
||||
|
||||
String title = "New Profile";
|
||||
|
||||
int startIconId = R.drawable.map_world_globe_dark;
|
||||
|
||||
if (isNew) {
|
||||
isDataChanged = true;
|
||||
startIconId = profile.parent.getSmallIconDark();
|
||||
profile.iconId = startIconId;
|
||||
} else if (isUserProfile) {
|
||||
title = profile.userProfileTitle;
|
||||
profileNameEt.setText(title);
|
||||
startIconId = profile.iconId;
|
||||
isDataChanged = false;
|
||||
} else if (profile.key != -1) {
|
||||
title = getResources().getString(profile.key);
|
||||
profileNameEt.setText(profile.key);
|
||||
startIconId = profile.iconId;
|
||||
clickBlockLayout.setClickable(true);
|
||||
}
|
||||
profile.userProfileTitle = title;
|
||||
|
||||
if (profile.parent != null) {
|
||||
setupBaseProfileView(profile.parent.getStringKey());
|
||||
} else if (profile.key != -1) {
|
||||
baseModeTitle.setText(profile.key);
|
||||
baseModeIcon.setImageDrawable(
|
||||
app.getUIUtilities().getIcon(profile.iconId, R.color.icon_color));
|
||||
}
|
||||
typeSelectionBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isUserProfile || isNew) {
|
||||
final SelectProfileBottomSheetDialogFragment dialog = new SelectProfileBottomSheetDialogFragment();
|
||||
Bundle bundle = new Bundle();
|
||||
if (profile.parent != null) {
|
||||
bundle.putString(SELECTED_KEY, profile.parent.getStringKey());
|
||||
}
|
||||
bundle.putString(DIALOG_TYPE, TYPE_APP_PROFILE);
|
||||
dialog.setArguments(bundle);
|
||||
if (getActivity() != null) {
|
||||
getActivity().getSupportFragmentManager().beginTransaction()
|
||||
.add(dialog, "select_base_type").commitAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!Algorithms.isEmpty(mode.getRoutingProfile())) {
|
||||
for (RoutingProfileDataObject r : routingProfileDataObjects) {
|
||||
if (mode.getRoutingProfile().equals(r.getStringKey())) {
|
||||
profile.routingProfileDataObject = r;
|
||||
r.setSelected(true);
|
||||
navTypeEt.setText(r.getName());
|
||||
navTypeEt.clearFocus();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (RoutingProfileDataObject rp : routingProfileDataObjects) {
|
||||
if (profile.stringKey.equals(rp.getStringKey())) {
|
||||
navTypeEt.setText(
|
||||
RoutingProfilesResources.valueOf(rp.getStringKey().toUpperCase())
|
||||
.getStringRes());
|
||||
}
|
||||
}
|
||||
navTypeEt.clearFocus();
|
||||
}
|
||||
profileNameEt.clearFocus();
|
||||
|
||||
if (getActivity() != null
|
||||
&& ((EditProfileActivity) getActivity()).getSupportActionBar() != null) {
|
||||
((EditProfileActivity) getActivity()).getSupportActionBar().setTitle(title);
|
||||
((EditProfileActivity) getActivity()).getSupportActionBar().setElevation(5.0f);
|
||||
}
|
||||
|
||||
int iconColor;
|
||||
if (!isUserProfile) {
|
||||
iconColor = R.color.icon_color;
|
||||
} else {
|
||||
iconColor = isNightMode
|
||||
? R.color.active_buttons_and_links_dark
|
||||
: R.color.active_buttons_and_links_light;
|
||||
}
|
||||
|
||||
profileIcon.setImageDrawable(app.getUIUtilities().getIcon(startIconId, iconColor));
|
||||
|
||||
profileNameEt.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) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (getActivity() instanceof OsmandActionBarActivity) {
|
||||
ActionBar actionBar = ((OsmandActionBarActivity) getActivity())
|
||||
.getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(s.toString());
|
||||
profile.userProfileTitle = s.toString();
|
||||
isCancelAllowed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
selectNavTypeBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isNew || isUserProfile) {
|
||||
final SelectProfileBottomSheetDialogFragment fragment = new SelectProfileBottomSheetDialogFragment();
|
||||
Bundle bundle = new Bundle();
|
||||
if (profile.routingProfileDataObject != null) {
|
||||
bundle.putString(SELECTED_KEY,
|
||||
profile.routingProfileDataObject.getStringKey());
|
||||
}
|
||||
bundle.putString(DIALOG_TYPE, TYPE_NAV_PROFILE);
|
||||
fragment.setArguments(bundle);
|
||||
if (getActivity() != null) {
|
||||
getActivity().getSupportFragmentManager().beginTransaction()
|
||||
.add(fragment, "select_nav_type").commitAllowingStateLoss();
|
||||
}
|
||||
navTypeEt.setCursorVisible(false);
|
||||
navTypeEt.setTextIsSelectable(false);
|
||||
navTypeEt.clearFocus();
|
||||
navTypeEt.requestFocus(ExtendedEditText.FOCUS_UP);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
profileIconBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final SelectProfileBottomSheetDialogFragment iconSelectDialog = new SelectProfileBottomSheetDialogFragment();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(DIALOG_TYPE, TYPE_ICON);
|
||||
bundle.putInt(SELECTED_ICON, profile.iconId);
|
||||
iconSelectDialog.setArguments(bundle);
|
||||
if (getActivity() != null) {
|
||||
getActivity().getSupportFragmentManager().beginTransaction()
|
||||
.add(iconSelectDialog, "select_icon")
|
||||
.commitAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mapConfigBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isDataChanged) {
|
||||
needSaveDialog();
|
||||
} else if (getSettings() != null) {
|
||||
activateMode(mode);
|
||||
getSettings().APPLICATION_MODE.set(mode);
|
||||
Intent i = new Intent(getActivity(), MapActivity.class);
|
||||
i.putExtra(OPEN_CONFIG_ON_MAP, MAP_CONFIG);
|
||||
i.putExtra(SELECTED_ITEM, profile.stringKey);
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
screenConfigBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isDataChanged) {
|
||||
needSaveDialog();
|
||||
} else if (getSettings() != null) {
|
||||
activateMode(mode);
|
||||
getSettings().APPLICATION_MODE.set(mode);
|
||||
Intent i = new Intent(getActivity(), MapActivity.class);
|
||||
i.putExtra(OPEN_CONFIG_ON_MAP, SCREEN_CONFIG);
|
||||
i.putExtra(SELECTED_ITEM, profile.stringKey);
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
navConfigBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isDataChanged) {
|
||||
needSaveDialog();
|
||||
} else if (getSettings() != null) {
|
||||
activateMode(mode);
|
||||
getSettings().APPLICATION_MODE.set(mode);
|
||||
Intent i = new Intent(getActivity(), SettingsNavigationActivity.class);
|
||||
i.putExtra(INTENT_SKIP_DIALOG, true);
|
||||
i.putExtra(OPEN_CONFIG_ON_MAP, NAV_CONFIG);
|
||||
i.putExtra(SELECTED_ITEM, profile.stringKey);
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cancelBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (getActivity() != null) {
|
||||
getActivity().onBackPressed();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cancelBtnSV.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (getActivity() != null) {
|
||||
getActivity().onBackPressed();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
saveButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (saveNewProfile()) {
|
||||
activateMode(mode);
|
||||
getActivity().onBackPressed();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
saveButtonSV.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (saveNewProfile()) {
|
||||
activateMode(mode);
|
||||
getActivity().onBackPressed();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
int marginShow = 66;
|
||||
int marginHide = 0;
|
||||
|
||||
float d = getResources().getDisplayMetrics().density;
|
||||
Rect r = new Rect();
|
||||
view.getWindowVisibleDisplayFrame(r);
|
||||
int screenHeight = view.getRootView().getHeight();
|
||||
int keypadHeight = screenHeight - r.bottom;
|
||||
if (keypadHeight > screenHeight * 0.15) {
|
||||
buttonsLayout.setVisibility(View.GONE);
|
||||
buttonsLayoutSV.setVisibility(View.VISIBLE);
|
||||
setMargins(scrollContainer, 0, 0, 0, (int) (marginHide * d));
|
||||
} else {
|
||||
buttonsLayoutSV.setVisibility(View.GONE);
|
||||
buttonsLayout.setVisibility(View.VISIBLE);
|
||||
setMargins(scrollContainer, 0, 0, 0, (int) (marginShow * d));
|
||||
}
|
||||
}
|
||||
});
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
getBaseProfileListener();
|
||||
getNavProfileListener();
|
||||
getIconListener();
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
boolean onBackPressedAllowed() {
|
||||
return isCancelAllowed;
|
||||
}
|
||||
|
||||
SelectProfileListener getIconListener() {
|
||||
if (iconIdListener == null) {
|
||||
iconIdListener = new SelectProfileListener() {
|
||||
@Override
|
||||
public void onSelectedType(int pos) {
|
||||
isDataChanged = true;
|
||||
profile.iconId = pos;
|
||||
profileIcon.setImageDrawable(app.getUIUtilities().getIcon(pos,
|
||||
isNightMode ? R.color.active_buttons_and_links_dark
|
||||
: R.color.active_buttons_and_links_light));
|
||||
}
|
||||
};
|
||||
}
|
||||
return iconIdListener;
|
||||
}
|
||||
|
||||
SelectProfileListener getBaseProfileListener() {
|
||||
if (baseTypeListener == null) {
|
||||
baseTypeListener = new SelectProfileListener() {
|
||||
@Override
|
||||
public void onSelectedType(int pos) {
|
||||
String key = SettingsProfileFragment.getBaseProfiles(getMyApplication())
|
||||
.get(pos).getStringKey();
|
||||
setupBaseProfileView(key);
|
||||
profile.parent = ApplicationMode.valueOfStringKey(key, ApplicationMode.DEFAULT);
|
||||
}
|
||||
};
|
||||
}
|
||||
return baseTypeListener;
|
||||
}
|
||||
|
||||
SelectProfileListener getNavProfileListener() {
|
||||
if (navTypeListener == null) {
|
||||
navTypeListener = new SelectProfileListener() {
|
||||
@Override
|
||||
public void onSelectedType(int pos) {
|
||||
updateRoutingProfile(pos);
|
||||
}
|
||||
};
|
||||
}
|
||||
return navTypeListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
if (!isUserProfile && !isNew) {
|
||||
profileNameEt.setFocusable(false);
|
||||
navTypeEt.setFocusable(false);
|
||||
}
|
||||
|
||||
if (isNew) {
|
||||
profileNameEt.requestFocus();
|
||||
} else {
|
||||
scrollContainer.requestFocus();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void updateRoutingProfile(int pos) {
|
||||
isDataChanged = true;
|
||||
for (int i = 0; i < routingProfileDataObjects.size(); i++) {
|
||||
if (i == pos) {
|
||||
routingProfileDataObjects.get(i).setSelected(true);
|
||||
} else {
|
||||
routingProfileDataObjects.get(i).setSelected(false);
|
||||
}
|
||||
}
|
||||
selectedRoutingProfileDataObject = routingProfileDataObjects.get(pos);
|
||||
navTypeEt.setText(selectedRoutingProfileDataObject.getName());
|
||||
profile.routingProfileDataObject = selectedRoutingProfileDataObject;
|
||||
}
|
||||
|
||||
void activateMode(ApplicationMode mode) {
|
||||
if (!ApplicationMode.values(app).contains(mode)) {
|
||||
ApplicationMode.changeProfileStatus(mode, true, getMyApplication());
|
||||
}
|
||||
}
|
||||
|
||||
private void setupBaseProfileView(String stringKey) {
|
||||
for (ApplicationMode am : ApplicationMode.getDefaultValues()) {
|
||||
if (am.getStringKey().equals(stringKey)) {
|
||||
baseModeIcon.setImageDrawable(
|
||||
app.getUIUtilities().getIcon(am.getSmallIconDark(), R.color.icon_color));
|
||||
baseModeTitle.setText(Algorithms.capitalizeFirstLetter(am.toHumanString(app)));
|
||||
isDataChanged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setMargins(View v, int l, int t, int r, int b) {
|
||||
if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
|
||||
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
|
||||
p.setMargins(l, t, r, b);
|
||||
v.requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean saveNewProfile() {
|
||||
if (profile.routingProfileDataObject == null) {
|
||||
showSaveWarningDialog(
|
||||
getString(R.string.profile_alert_need_routing_type_title),
|
||||
getString(R.string.profile_alert_need_routing_type_msg),
|
||||
getActivity());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (profile.userProfileTitle.isEmpty()
|
||||
|| profile.userProfileTitle.replace(" ", "").length() < 1) {
|
||||
showSaveWarningDialog(
|
||||
getString(R.string.profile_alert_need_profile_name_title),
|
||||
getString(R.string.profile_alert_need_profile_name_msg),
|
||||
getActivity()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ApplicationMode m : ApplicationMode.allPossibleValues()) {
|
||||
if (m.getUserProfileName() != null && getActivity() != null) {
|
||||
if (m.getUserProfileName().equals(profile.userProfileTitle)) {
|
||||
if (isNew || !Algorithms.isEmpty(mode.getUserProfileName())
|
||||
&& !mode.getUserProfileName().equals(profile.userProfileTitle)) {
|
||||
AlertDialog.Builder bld = new AlertDialog.Builder(getActivity());
|
||||
bld.setTitle(R.string.profile_alert_duplicate_name_title);
|
||||
bld.setMessage(R.string.profile_alert_duplicate_name_msg);
|
||||
bld.setNegativeButton(R.string.shared_string_dismiss, null);
|
||||
bld.show();
|
||||
bld.setOnDismissListener(new OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
profileNameEt.requestFocus();
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isUserProfile && !isNew) {
|
||||
ApplicationMode.deleteCustomMode(mode.getUserProfileName(), getMyApplication());
|
||||
}
|
||||
|
||||
String customStringKey = profile.stringKey;
|
||||
if (isNew && profile.parent != null) {
|
||||
customStringKey =
|
||||
profile.parent.getStringKey() + "_" + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
ApplicationMode.ApplicationModeBuilder builder = ApplicationMode
|
||||
.createCustomMode(profile.userProfileTitle.trim(), customStringKey)
|
||||
.parent(profile.parent)
|
||||
.icon(profile.iconId, profile.iconId);
|
||||
|
||||
if (profile.routingProfileDataObject != null) {
|
||||
builder.setRoutingProfile(profile.routingProfileDataObject.getStringKey());
|
||||
}
|
||||
|
||||
ApplicationMode mode = builder.customReg();
|
||||
ApplicationMode.saveCustomModeToSettings(getSettings());
|
||||
|
||||
if (!ApplicationMode.values(app).contains(mode)) {
|
||||
boolean save = ApplicationMode.changeProfileStatus(mode, true, getMyApplication());
|
||||
|
||||
if (save && getSettings() != null) {
|
||||
if (profile.routingProfileDataObject.getStringKey()
|
||||
.equals(RoutingProfilesResources.STRAIGHT_LINE_MODE.toString())) {
|
||||
getSettings().ROUTER_SERVICE.setModeValue(mode, RouteService.STRAIGHT);
|
||||
} else if (profile.routingProfileDataObject.getStringKey()
|
||||
.equals(RoutingProfilesResources.BROUTER_MODE.toString())) {
|
||||
getSettings().ROUTER_SERVICE.setModeValue(mode, RouteService.BROUTER);
|
||||
} else {
|
||||
getSettings().ROUTER_SERVICE.setModeValue(mode, RouteService.OSMAND);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
isDataChanged = false;
|
||||
isCancelAllowed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void needSaveDialog() {
|
||||
if (getActivity() != null) {
|
||||
AlertDialog.Builder bld = new AlertDialog.Builder(getActivity());
|
||||
bld.setTitle(R.string.profile_alert_need_save_title);
|
||||
bld.setMessage(R.string.profile_alert_need_save_msg);
|
||||
bld.setNegativeButton(R.string.shared_string_ok, null);
|
||||
bld.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void showSaveWarningDialog(String title, String message, Activity activity) {
|
||||
AlertDialog.Builder bld = new AlertDialog.Builder(activity);
|
||||
bld.setTitle(title);
|
||||
bld.setMessage(message);
|
||||
bld.setNegativeButton(R.string.shared_string_dismiss, null);
|
||||
bld.show();
|
||||
}
|
||||
|
||||
void confirmCancelDialog(final Activity activity) {
|
||||
AlertDialog.Builder bld = new Builder(activity);
|
||||
bld.setTitle(R.string.shared_string_dismiss);
|
||||
bld.setMessage(R.string.exit_without_saving);
|
||||
bld.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
isCancelAllowed = true;
|
||||
activity.onBackPressed();
|
||||
}
|
||||
});
|
||||
bld.setNegativeButton(R.string.shared_string_cancel, null);
|
||||
bld.show();
|
||||
|
||||
}
|
||||
|
||||
void onDeleteProfileClick() {
|
||||
if (getActivity() != null) {
|
||||
if (isUserProfile) {
|
||||
AlertDialog.Builder bld = new AlertDialog.Builder(getActivity());
|
||||
bld.setTitle(R.string.profile_alert_delete_title);
|
||||
bld.setMessage(String
|
||||
.format(getString(R.string.profile_alert_delete_msg),
|
||||
profile.userProfileTitle));
|
||||
bld.setPositiveButton(R.string.shared_string_delete,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
ApplicationMode
|
||||
.deleteCustomMode(profile.userProfileTitle, getMyApplication());
|
||||
if (getActivity() != null) {
|
||||
getActivity().onBackPressed();
|
||||
}
|
||||
getSettings().APPLICATION_MODE.set(ApplicationMode.DEFAULT);
|
||||
}
|
||||
});
|
||||
bld.setNegativeButton(R.string.shared_string_dismiss, null);
|
||||
bld.show();
|
||||
} else {
|
||||
Toast.makeText(getActivity(), R.string.profile_alert_cant_delete_base,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static List<RoutingProfileDataObject> getRoutingProfiles(OsmandApplication context) {
|
||||
List<RoutingProfileDataObject> profilesObjects = new ArrayList<>();
|
||||
profilesObjects.add(new RoutingProfileDataObject(
|
||||
RoutingProfilesResources.STRAIGHT_LINE_MODE.toString(),
|
||||
context.getString(RoutingProfilesResources.STRAIGHT_LINE_MODE.getStringRes()),
|
||||
context.getString(R.string.special_routing_type),
|
||||
RoutingProfilesResources.STRAIGHT_LINE_MODE.getIconRes(),
|
||||
false, null));
|
||||
if (context.getBRouterService() != null) {
|
||||
profilesObjects.add(new RoutingProfileDataObject(
|
||||
RoutingProfilesResources.BROUTER_MODE.toString(),
|
||||
context.getString(RoutingProfilesResources.BROUTER_MODE.getStringRes()),
|
||||
context.getString(R.string.third_party_routing_type),
|
||||
RoutingProfilesResources.BROUTER_MODE.getIconRes(),
|
||||
false, null));
|
||||
}
|
||||
|
||||
Map<String, GeneralRouter> inputProfiles = context.getRoutingConfig().getAllRouters();
|
||||
for (Entry<String, GeneralRouter> e : inputProfiles.entrySet()) {
|
||||
int iconRes = R.drawable.ic_action_gdirections_dark;
|
||||
String name = e.getValue().getProfileName();
|
||||
String description = context.getString(R.string.osmand_default_routing);
|
||||
if (!Algorithms.isEmpty(e.getValue().getFilename())) {
|
||||
description = e.getValue().getFilename();
|
||||
} else if (RoutingProfilesResources.isRpValue(name.toUpperCase())){
|
||||
iconRes = RoutingProfilesResources.valueOf(name.toUpperCase()).getIconRes();
|
||||
name = context
|
||||
.getString(RoutingProfilesResources.valueOf(name.toUpperCase()).getStringRes());
|
||||
}
|
||||
profilesObjects.add(new RoutingProfileDataObject(e.getKey(), name, description,
|
||||
iconRes, false, e.getValue().getFilename()));
|
||||
}
|
||||
return profilesObjects;
|
||||
}
|
||||
|
||||
public enum RoutingProfilesResources {
|
||||
STRAIGHT_LINE_MODE(R.string.routing_profile_straightline,R.drawable.ic_action_split_interval),
|
||||
BROUTER_MODE(R.string.routing_profile_broutrer, R.drawable.ic_action_split_interval),
|
||||
CAR(R.string.rendering_value_car_name, R.drawable.ic_action_car_dark),
|
||||
PEDESTRIAN(R.string.rendering_value_pedestrian_name, R.drawable.map_action_pedestrian_dark),
|
||||
BICYCLE(R.string.rendering_value_bicycle_name, R.drawable.map_action_bicycle_dark),
|
||||
SKI(R.string.routing_profile_ski, R.drawable.ic_plugin_skimaps),
|
||||
PUBLIC_TRANSPORT(R.string.app_mode_public_transport, R.drawable.map_action_bus_dark),
|
||||
BOAT(R.string.app_mode_boat, R.drawable.map_action_sail_boat_dark),
|
||||
GEOCODING(R.string.routing_profile_geocoding, R.drawable.ic_action_world_globe);
|
||||
|
||||
int stringRes;
|
||||
int iconRes;
|
||||
|
||||
RoutingProfilesResources(int stringRes, int iconRes) {
|
||||
this.stringRes = stringRes;
|
||||
this.iconRes = iconRes;
|
||||
}
|
||||
|
||||
public int getStringRes() {
|
||||
return stringRes;
|
||||
}
|
||||
|
||||
public int getIconRes() {
|
||||
return iconRes;
|
||||
}
|
||||
|
||||
private static final List<String> rpValues = new ArrayList<>();
|
||||
|
||||
static {
|
||||
for (RoutingProfilesResources rpr : RoutingProfilesResources.values()) {
|
||||
rpValues.add(rpr.name());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isRpValue(String value) {
|
||||
return rpValues.contains(value);
|
||||
}
|
||||
}
|
||||
|
||||
private class ApplicationProfileObject {
|
||||
|
||||
int key = -1;
|
||||
String stringKey;
|
||||
String userProfileTitle = "";
|
||||
ApplicationMode parent = null;
|
||||
int iconId = R.drawable.map_world_globe_dark;
|
||||
RoutingProfileDataObject routingProfileDataObject = null;
|
||||
|
||||
ApplicationProfileObject(ApplicationMode mode, boolean isNew, boolean isUserProfile) {
|
||||
if (isNew) {
|
||||
stringKey = mode.getStringKey() + System.currentTimeMillis();
|
||||
parent = mode;
|
||||
} else if (isUserProfile) {
|
||||
stringKey = mode.getStringKey();
|
||||
parent = mode.getParent();
|
||||
iconId = mode.getSmallIconDark();
|
||||
userProfileTitle = mode.getUserProfileName();
|
||||
} else {
|
||||
key = mode.getStringResource();
|
||||
stringKey = mode.getStringKey();
|
||||
iconId = mode.getSmallIconDark();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
42
OsmAnd/src/net/osmand/plus/profiles/ProfileDataObject.java
Normal file
|
@ -0,0 +1,42 @@
|
|||
package net.osmand.plus.profiles;
|
||||
|
||||
public class ProfileDataObject {
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
private int iconRes;
|
||||
private String stringKey;
|
||||
private boolean isSelected;
|
||||
|
||||
public ProfileDataObject(String name, String description, String stringKey, int iconRes, boolean isSelected) {
|
||||
this.name = name;
|
||||
this.iconRes = iconRes;
|
||||
this.description = description;
|
||||
this.isSelected = isSelected;
|
||||
this.stringKey = stringKey;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getIconRes() {
|
||||
return iconRes;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public boolean isSelected() {
|
||||
return isSelected;
|
||||
}
|
||||
|
||||
public void setSelected(boolean selected) {
|
||||
isSelected = selected;
|
||||
}
|
||||
|
||||
public String getStringKey() {
|
||||
return stringKey;
|
||||
}
|
||||
}
|
138
OsmAnd/src/net/osmand/plus/profiles/ProfileMenuAdapter.java
Normal file
|
@ -0,0 +1,138 @@
|
|||
package net.osmand.plus.profiles;
|
||||
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.profiles.ProfileMenuAdapter.ProfileViewHolder;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
|
||||
public class ProfileMenuAdapter extends RecyclerView.Adapter<ProfileViewHolder> {
|
||||
|
||||
private List<ApplicationMode> items;
|
||||
private Set<ApplicationMode> selectedItems;
|
||||
private ProfileListener listener;
|
||||
private final OsmandApplication app;
|
||||
@ColorRes private int selectedIconColorRes;
|
||||
|
||||
public ProfileMenuAdapter(List<ApplicationMode> items, Set<ApplicationMode> selectedItems, OsmandApplication app, ProfileListener listener) {
|
||||
this.items = items;
|
||||
this.listener = listener;
|
||||
this.app = app;
|
||||
this.selectedItems = selectedItems;
|
||||
selectedIconColorRes = isNightMode(app)
|
||||
? R.color.active_buttons_and_links_dark
|
||||
: R.color.active_buttons_and_links_light;
|
||||
}
|
||||
|
||||
public List<ApplicationMode> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void addItem(ApplicationMode profileItem) {
|
||||
items.add(profileItem);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void updateItemsList(List<ApplicationMode> newList, Set<ApplicationMode> selectedItems) {
|
||||
items.clear();
|
||||
this.selectedItems.clear();
|
||||
items.addAll(newList);
|
||||
this.selectedItems.addAll(selectedItems);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ProfileViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View itemView = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.profile_list_item, parent, false);
|
||||
return new ProfileViewHolder(itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final ProfileViewHolder holder, int position) {
|
||||
final ApplicationMode item = items.get(position);
|
||||
if (item.getParent() != null) {
|
||||
holder.title.setText(item.getUserProfileName());
|
||||
holder.descr.setText(String.format(app.getString(R.string.profile_type_descr_string),
|
||||
Algorithms.capitalizeFirstLetterAndLowercase(item.getParent().getStringKey().replace("_", " "))));
|
||||
} else {
|
||||
holder.title.setText(app.getResources().getString(item.getStringResource()));
|
||||
holder.descr.setText(R.string.profile_type_base_string);
|
||||
}
|
||||
|
||||
holder.title.setTextColor(app.getResources().getColor(isNightMode(app)
|
||||
? R.color.main_font_dark
|
||||
: R.color.main_font_light));
|
||||
if (selectedItems.contains(item)) {
|
||||
holder.aSwitch.setChecked(true);
|
||||
holder.icon.setImageDrawable(app.getUIUtilities().getIcon(item.getSmallIconDark(), selectedIconColorRes));
|
||||
} else {
|
||||
holder.aSwitch.setChecked(false);
|
||||
holder.icon.setImageDrawable(app.getUIUtilities().getIcon(item.getSmallIconDark(), R.color.icon_color));
|
||||
}
|
||||
|
||||
holder.aSwitch.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.changeProfileStatus(item, holder.aSwitch.isChecked());
|
||||
if (selectedItems.contains(item)) {
|
||||
holder.icon.setImageDrawable(app.getUIUtilities().getIcon(item.getSmallIconDark(), selectedIconColorRes));
|
||||
} else {
|
||||
holder.icon.setImageDrawable(app.getUIUtilities().getIcon(item.getSmallIconDark(), R.color.icon_color));
|
||||
}
|
||||
}
|
||||
});
|
||||
holder.profileOptions.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.editProfile(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
private static boolean isNightMode(OsmandApplication ctx) {
|
||||
return !ctx.getSettings().isLightContent();
|
||||
}
|
||||
|
||||
class ProfileViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView title, descr;
|
||||
SwitchCompat aSwitch;
|
||||
ImageView icon;
|
||||
LinearLayout profileOptions;
|
||||
|
||||
ProfileViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
title = itemView.findViewById(R.id.profile_title);
|
||||
descr = itemView.findViewById(R.id.profile_descr);
|
||||
aSwitch = itemView.findViewById(R.id.profile_switch);
|
||||
icon = itemView.findViewById(R.id.profile_icon);
|
||||
profileOptions = itemView.findViewById(R.id.profile_settings);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ProfileListener {
|
||||
void changeProfileStatus(ApplicationMode item, boolean isSelected);
|
||||
void editProfile(ApplicationMode item);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package net.osmand.plus.profiles;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
|
||||
public class RoutingProfileDataObject extends ProfileDataObject {
|
||||
|
||||
private String fileName;
|
||||
|
||||
public RoutingProfileDataObject(String stringKey, String name, String descr, int iconRes, boolean isSelected, String fileName) {
|
||||
super(name, descr, stringKey, iconRes, isSelected);
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
package net.osmand.plus.profiles;
|
||||
|
||||
import static net.osmand.plus.profiles.EditProfileFragment.SELECTED_ICON;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
public class SelectProfileBottomSheetDialogFragment extends MenuBottomSheetDialogFragment {
|
||||
|
||||
private static final Log LOG = PlatformUtil
|
||||
.getLog(SelectProfileBottomSheetDialogFragment.class);
|
||||
public static final String TAG = "SelectProfileBottomSheetDialogFragment";
|
||||
|
||||
public final static String DIALOG_TYPE = "dialog_type";
|
||||
public final static String TYPE_APP_PROFILE = "base_profiles";
|
||||
public final static String TYPE_NAV_PROFILE = "routing_profiles";
|
||||
public final static String TYPE_ICON = "icon_type";
|
||||
public final static String SELECTED_KEY = "selected_base";
|
||||
|
||||
String type;
|
||||
|
||||
private SelectProfileListener listener;
|
||||
|
||||
private List<ProfileDataObject> profiles = new ArrayList<>();
|
||||
private List<IconResWithDescr> icons;
|
||||
private String selectedItemKey;
|
||||
private int selectedIconRes;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
OsmandApplication app = getMyApplication();
|
||||
Bundle args = getArguments();
|
||||
if (args != null && args.get(DIALOG_TYPE) != null) {
|
||||
type = args.getString(DIALOG_TYPE);
|
||||
selectedItemKey = args.getString(SELECTED_KEY, null);
|
||||
|
||||
if (type.equals(TYPE_NAV_PROFILE)) {
|
||||
profiles.addAll(EditProfileFragment.getRoutingProfiles(app));
|
||||
} else if (type.equals(TYPE_APP_PROFILE)) {
|
||||
profiles.addAll(SettingsProfileFragment.getBaseProfiles(app));
|
||||
} else if (type.equals(TYPE_ICON)) {
|
||||
selectedIconRes = args.getInt(SELECTED_ICON, -1);
|
||||
icons = getProfileIcons();
|
||||
} else {
|
||||
LOG.error("Check intent data!");
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMenuItems(Bundle savedInstanceState) {
|
||||
|
||||
if (type.equals(TYPE_APP_PROFILE)) {
|
||||
items.add(new TitleItem(getString(R.string.select_base_profile_dialog_title)));
|
||||
items.add(new LongDescriptionItem(getString(R.string.select_base_profile_dialog_message)));
|
||||
for (int i = 0; i < profiles.size(); i++) {
|
||||
final int pos = i;
|
||||
final ProfileDataObject profile = profiles.get(i);
|
||||
final boolean isSelected = profile.getStringKey().equals(selectedItemKey);
|
||||
final Drawable drawableIcon;
|
||||
if (isSelected) {
|
||||
drawableIcon = getMyApplication().getUIUtilities()
|
||||
.getIcon(profile.getIconRes(), nightMode
|
||||
? R.color.active_buttons_and_links_dark
|
||||
: R.color.active_buttons_and_links_light);
|
||||
} else {
|
||||
drawableIcon = getMyApplication().getUIUtilities()
|
||||
.getIcon(profile.getIconRes(), R.color.icon_color);
|
||||
}
|
||||
|
||||
items.add(new BottomSheetItemWithCompoundButton.Builder()
|
||||
.setChecked(isSelected)
|
||||
.setButtonTintList(isSelected
|
||||
? ColorStateList.valueOf(getResolvedColor(getActiveColorId()))
|
||||
: null)
|
||||
.setDescription(profile.getDescription())
|
||||
.setTitle(profile.getName())
|
||||
.setIcon(drawableIcon)
|
||||
.setLayoutId(R.layout.bottom_sheet_item_with_descr_and_radio_btn)
|
||||
.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener == null) {
|
||||
getListener();
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onSelectedType(pos);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
})
|
||||
.create());
|
||||
}
|
||||
|
||||
} else if (type.equals(TYPE_NAV_PROFILE)){
|
||||
items.add(new TitleItem(getString(R.string.select_nav_profile_dialog_title)));
|
||||
for (int i = 0; i < profiles.size(); i++) {
|
||||
final int pos = i;
|
||||
final ProfileDataObject profile = profiles.get(i);
|
||||
final boolean isSelected = profile.getStringKey().equals(selectedItemKey);
|
||||
final Drawable drawableIcon;
|
||||
if (isSelected) {
|
||||
drawableIcon = getMyApplication().getUIUtilities()
|
||||
.getIcon(profile.getIconRes(), nightMode
|
||||
? R.color.active_buttons_and_links_dark
|
||||
: R.color.active_buttons_and_links_light);
|
||||
} else {
|
||||
drawableIcon = getMyApplication().getUIUtilities()
|
||||
.getIcon(profile.getIconRes(), R.color.icon_color);
|
||||
}
|
||||
|
||||
items.add(new BottomSheetItemWithCompoundButton.Builder()
|
||||
.setChecked(isSelected)
|
||||
.setButtonTintList(isSelected
|
||||
? ColorStateList.valueOf(getResolvedColor(getActiveColorId()))
|
||||
: null)
|
||||
.setDescription(profile.getDescription())
|
||||
.setTitle(profile.getName())
|
||||
.setIcon(drawableIcon)
|
||||
.setLayoutId(R.layout.bottom_sheet_item_with_descr_and_radio_btn)
|
||||
.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener == null) {
|
||||
getListener();
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onSelectedType(pos);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
})
|
||||
.create());
|
||||
}
|
||||
} else if (type.equals(TYPE_ICON)) {
|
||||
items.add(new TitleItem(getString(R.string.select_icon_profile_dialog_title)));
|
||||
for (final IconResWithDescr icon : icons) {
|
||||
Drawable drawableIcon;
|
||||
boolean isSelected = icon.resId == selectedIconRes;
|
||||
if (isSelected) {
|
||||
drawableIcon = getMyApplication().getUIUtilities()
|
||||
.getIcon(icon.resId, nightMode
|
||||
? R.color.active_buttons_and_links_dark
|
||||
: R.color.active_buttons_and_links_light);
|
||||
} else {
|
||||
drawableIcon = getMyApplication().getUIUtilities()
|
||||
.getIcon(icon.resId, R.color.icon_color);
|
||||
}
|
||||
|
||||
items.add(new BottomSheetItemWithCompoundButton.Builder()
|
||||
.setChecked(icon.resId == selectedIconRes)
|
||||
.setButtonTintList(isSelected
|
||||
? ColorStateList.valueOf(getResolvedColor(getActiveColorId()))
|
||||
: null)
|
||||
.setTitle(getMyApplication().getString(icon.titleId))
|
||||
.setIcon(drawableIcon)
|
||||
.setLayoutId(R.layout.bottom_sheet_item_with_radio_btn)
|
||||
.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(listener == null) {
|
||||
getListener();
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onSelectedType(icon.resId);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
})
|
||||
.create()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void getListener() {
|
||||
if (getActivity() != null && getActivity() instanceof EditProfileActivity) {
|
||||
EditProfileFragment f = (EditProfileFragment) getActivity().getSupportFragmentManager()
|
||||
.findFragmentByTag(EditProfileActivity.EDIT_PROFILE_FRAGMENT_TAG);
|
||||
if (type.equals(TYPE_APP_PROFILE)) {
|
||||
listener = f.getBaseProfileListener();
|
||||
} else if (type.equals(TYPE_NAV_PROFILE)) {
|
||||
listener = f.getNavProfileListener();
|
||||
} else if (type.equals(TYPE_ICON)) {
|
||||
listener = f.getIconListener();
|
||||
}
|
||||
} else if (getActivity() != null && getActivity() instanceof SettingsProfileActivity) {
|
||||
SettingsProfileFragment f = (SettingsProfileFragment) getActivity().getSupportFragmentManager()
|
||||
.findFragmentByTag(SettingsProfileActivity.SETTINGS_PROFILE_FRAGMENT_TAG);
|
||||
listener = f.getBaseProfileListener();
|
||||
}
|
||||
}
|
||||
|
||||
private List<IconResWithDescr> getProfileIcons() {
|
||||
List<IconResWithDescr> icons = new ArrayList<>();
|
||||
icons.add(new IconResWithDescr(R.drawable.ic_action_car_dark, R.string.rendering_value_car_name,false));
|
||||
icons.add(new IconResWithDescr(R.drawable.ic_action_bicycle_dark, R.string.rendering_value_bicycle_name,false));
|
||||
icons.add(new IconResWithDescr(R.drawable.ic_action_pedestrian_dark, R.string.rendering_value_pedestrian_name,false));
|
||||
icons.add(new IconResWithDescr(R.drawable.ic_action_bus_dark, R.string.app_mode_bus,false));
|
||||
icons.add(new IconResWithDescr(R.drawable.ic_action_sail_boat_dark, R.string.app_mode_boat,false));
|
||||
icons.add(new IconResWithDescr(R.drawable.ic_action_aircraft, R.string.app_mode_aircraft,false));
|
||||
icons.add(new IconResWithDescr(R.drawable.ic_action_truck_dark, R.string.app_mode_truck,false));
|
||||
icons.add(new IconResWithDescr(R.drawable.ic_action_motorcycle_dark, R.string.app_mode_motorcycle,false));
|
||||
icons.add(new IconResWithDescr(R.drawable.ic_action_trekking_dark, R.string.app_mode_hiking,false));
|
||||
icons.add(new IconResWithDescr(R.drawable.ic_plugin_skimaps, R.string.routing_profile_ski, false));
|
||||
return icons;
|
||||
}
|
||||
|
||||
interface SelectProfileListener {
|
||||
void onSelectedType(int pos);
|
||||
}
|
||||
|
||||
private class IconResWithDescr {
|
||||
private int resId;
|
||||
private int titleId;
|
||||
private boolean isSelected;
|
||||
|
||||
public IconResWithDescr(int resId, int titleId, boolean isSelected) {
|
||||
this.resId = resId;
|
||||
this.titleId = titleId;
|
||||
this.isSelected = isSelected;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package net.osmand.plus.profiles;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.OsmandActionBarActivity;
|
||||
|
||||
public class SettingsProfileActivity extends OsmandActionBarActivity {
|
||||
|
||||
public static final String SETTINGS_PROFILE_FRAGMENT_TAG = "settingsProfileFragment";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
getMyApplication().applyTheme(this);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.single_fragment_layout);
|
||||
getSupportActionBar().setElevation(5.0f);
|
||||
if (savedInstanceState == null) {
|
||||
SettingsProfileFragment profileFragment = new SettingsProfileFragment();
|
||||
profileFragment.setArguments(getIntent().getExtras());
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.add(android.R.id.content, profileFragment, SETTINGS_PROFILE_FRAGMENT_TAG).commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int itemId = item.getItemId();
|
||||
switch (itemId) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
|
||||
}
|
176
OsmAnd/src/net/osmand/plus/profiles/SettingsProfileFragment.java
Normal file
|
@ -0,0 +1,176 @@
|
|||
package net.osmand.plus.profiles;
|
||||
|
||||
|
||||
|
||||
import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.DIALOG_TYPE;
|
||||
import static net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.TYPE_APP_PROFILE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||
import net.osmand.plus.profiles.ProfileMenuAdapter.ProfileListener;
|
||||
import net.osmand.plus.profiles.SelectProfileBottomSheetDialogFragment.SelectProfileListener;
|
||||
import net.osmand.util.Algorithms;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
public class SettingsProfileFragment extends BaseOsmAndFragment {
|
||||
|
||||
private static final Log LOG = PlatformUtil.getLog(SettingsProfileFragment.class);
|
||||
|
||||
public static final String PROFILE_STRING_KEY = "string_key";
|
||||
public static final String IS_NEW_PROFILE = "new_profile";
|
||||
public static final String IS_USER_PROFILE = "user_profile";
|
||||
|
||||
|
||||
private ProfileMenuAdapter adapter;
|
||||
private RecyclerView recyclerView;
|
||||
private LinearLayout addNewProfileBtn;
|
||||
|
||||
ProfileListener listener = null;
|
||||
SelectProfileListener typeListener = null;
|
||||
|
||||
private List<ApplicationMode> allAppModes;
|
||||
private Set<ApplicationMode> availableAppModes;
|
||||
private List<ProfileDataObject> baseProfiles;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
allAppModes = ApplicationMode.allPossibleValues();
|
||||
allAppModes.remove(ApplicationMode.DEFAULT);
|
||||
availableAppModes = new LinkedHashSet<>(ApplicationMode.values(getMyApplication()));
|
||||
availableAppModes.remove(ApplicationMode.DEFAULT);
|
||||
baseProfiles = getBaseProfiles(getMyActivity());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
listener = new ProfileListener() {
|
||||
@Override
|
||||
public void changeProfileStatus(ApplicationMode am, boolean isSelected) {
|
||||
if(isSelected) {
|
||||
availableAppModes.add(am);
|
||||
} else {
|
||||
availableAppModes.remove(am);
|
||||
}
|
||||
ApplicationMode.changeProfileStatus(am, isSelected, getMyApplication());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editProfile(ApplicationMode item) {
|
||||
Intent intent = new Intent(getActivity(), EditProfileActivity.class);
|
||||
intent.putExtra(PROFILE_STRING_KEY, item.getStringKey());
|
||||
if (!Algorithms.isEmpty(item.getUserProfileName())) {
|
||||
intent.putExtra(IS_USER_PROFILE, true);
|
||||
}
|
||||
startActivity(intent);
|
||||
}
|
||||
};
|
||||
|
||||
View view = inflater.inflate(R.layout.profiles_list_fragment, container, false);
|
||||
recyclerView = view.findViewById(R.id.profiles_list);
|
||||
addNewProfileBtn = view.findViewById(R.id.add_profile_btn);
|
||||
|
||||
addNewProfileBtn.setOnClickListener(new OnClickListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final SelectProfileBottomSheetDialogFragment dialog = new SelectProfileBottomSheetDialogFragment();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(DIALOG_TYPE, TYPE_APP_PROFILE);
|
||||
dialog.setArguments(bundle);
|
||||
if (getActivity() != null) {
|
||||
getActivity().getSupportFragmentManager().beginTransaction()
|
||||
.add(dialog, "select_base_type").commitAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
adapter = new ProfileMenuAdapter(allAppModes, availableAppModes, getMyApplication(), listener);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
recyclerView.setAdapter(adapter);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
getBaseProfileListener();
|
||||
|
||||
allAppModes = ApplicationMode.allPossibleValues();
|
||||
allAppModes.remove(ApplicationMode.DEFAULT);
|
||||
adapter.updateItemsList(allAppModes, new LinkedHashSet<>(ApplicationMode.values(getMyApplication())));
|
||||
}
|
||||
|
||||
SelectProfileListener getBaseProfileListener() {
|
||||
if (typeListener == null) {
|
||||
typeListener = new SelectProfileListener() {
|
||||
@Override
|
||||
public void onSelectedType(int pos) {
|
||||
Intent intent = new Intent(getActivity(), EditProfileActivity.class);
|
||||
intent.putExtra(IS_NEW_PROFILE, true);
|
||||
intent.putExtra(IS_USER_PROFILE, true);
|
||||
intent.putExtra(PROFILE_STRING_KEY, baseProfiles.get(pos).getStringKey());
|
||||
startActivity(intent);
|
||||
}
|
||||
};
|
||||
}
|
||||
return typeListener;
|
||||
}
|
||||
|
||||
static List<ProfileDataObject> getBaseProfiles(Context ctx) {
|
||||
List<ProfileDataObject> profiles = new ArrayList<>();
|
||||
for (ApplicationMode mode : ApplicationMode.getDefaultValues()) {
|
||||
if (mode != ApplicationMode.DEFAULT) {
|
||||
profiles.add(new ProfileDataObject( mode.toHumanString(ctx),
|
||||
ctx.getString(BaseProfilesDescr.valueOf(mode.getStringKey().toUpperCase()).getDescrRes()),
|
||||
mode.getStringKey(), mode.getSmallIconDark(), false));
|
||||
}
|
||||
}
|
||||
return profiles;
|
||||
}
|
||||
|
||||
public enum BaseProfilesDescr {
|
||||
CAR(R.string.base_profile_descr_car),
|
||||
BICYCLE(R.string.base_profile_descr_bicycle),
|
||||
PEDESTRIAN(R.string.base_profile_descr_pedestrian),
|
||||
PUBLIC_TRANSPORT(R.string.base_profile_descr_public_transport),
|
||||
BOAT(R.string.base_profile_descr_boat),
|
||||
AIRCRAFT(R.string.base_profile_descr_aircraft);
|
||||
|
||||
private int descrRes;
|
||||
|
||||
BaseProfilesDescr(int descrRes) {
|
||||
this.descrRes = descrRes;
|
||||
}
|
||||
|
||||
public int getDescrRes() {
|
||||
return descrRes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -245,6 +245,11 @@ public class ResourceManager {
|
|||
float tiles = (dm.widthPixels / 256 + 2) * (dm.heightPixels / 256 + 2) * 3;
|
||||
log.info("Bitmap tiles to load in memory : " + tiles);
|
||||
bitmapTilesCache.setMaxCacheSize((int) (tiles));
|
||||
|
||||
File path = context.getAppPath(IndexConstants.ROUTING_PROFILES_DIR);
|
||||
if (!path.exists()) {
|
||||
path.mkdir();
|
||||
}
|
||||
}
|
||||
|
||||
public BitmapTilesCache getBitmapTilesCache() {
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package net.osmand.plus.routepreparationmenu;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
@ -27,6 +30,7 @@ import net.osmand.data.PointDescription;
|
|||
import net.osmand.plus.FavouritesDbHelper;
|
||||
import net.osmand.plus.MapMarkersHelper;
|
||||
import net.osmand.plus.MapMarkersHelper.MapMarker;
|
||||
import net.osmand.plus.OsmAndLocationProvider;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.TargetPointsHelper;
|
||||
|
@ -213,42 +217,50 @@ public class AddPointBottomSheetDialog extends MenuBottomSheetDialogFragment {
|
|||
|
||||
private void createMyLocItem() {
|
||||
BaseBottomSheetItem myLocationItem = new SimpleBottomSheetItem.Builder()
|
||||
.setIcon(getIcon(R.drawable.ic_action_location_color, 0))
|
||||
.setIcon(getIcon(OsmAndLocationProvider.isLocationPermissionAvailable(getActivity())
|
||||
? R.drawable.ic_action_location_color : R.drawable.ic_action_location_color_lost, 0))
|
||||
.setTitle(getString(R.string.shared_string_my_location))
|
||||
.setLayoutId(R.layout.bottom_sheet_item_simple_56dp)
|
||||
.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
OsmandApplication app = getMyApplication();
|
||||
Activity activity = getActivity();
|
||||
if (app != null) {
|
||||
TargetPointsHelper targetPointsHelper = app.getTargetPointsHelper();
|
||||
Location myLocation = app.getLocationProvider().getLastKnownLocation();
|
||||
if (myLocation != null) {
|
||||
LatLon ll = new LatLon(myLocation.getLatitude(), myLocation.getLongitude());
|
||||
switch (pointType) {
|
||||
case START:
|
||||
if (targetPointsHelper.getPointToStart() != null) {
|
||||
targetPointsHelper.clearStartPoint(true);
|
||||
app.getSettings().backupPointToStart();
|
||||
}
|
||||
break;
|
||||
case TARGET:
|
||||
app.showShortToastMessage(R.string.add_destination_point);
|
||||
targetPointsHelper.navigateToPoint(ll, true, -1);
|
||||
break;
|
||||
case INTERMEDIATE:
|
||||
app.showShortToastMessage(R.string.add_intermediate_point);
|
||||
targetPointsHelper.navigateToPoint(ll, true, targetPointsHelper.getIntermediatePoints().size());
|
||||
break;
|
||||
case HOME:
|
||||
app.showShortToastMessage(R.string.add_intermediate_point);
|
||||
targetPointsHelper.setHomePoint(ll, null);
|
||||
break;
|
||||
case WORK:
|
||||
app.showShortToastMessage(R.string.add_intermediate_point);
|
||||
targetPointsHelper.setWorkPoint(ll, null);
|
||||
break;
|
||||
if (OsmAndLocationProvider.isLocationPermissionAvailable(app)) {
|
||||
TargetPointsHelper targetPointsHelper = app.getTargetPointsHelper();
|
||||
Location myLocation = app.getLocationProvider().getLastKnownLocation();
|
||||
if (myLocation != null) {
|
||||
LatLon ll = new LatLon(myLocation.getLatitude(), myLocation.getLongitude());
|
||||
switch (pointType) {
|
||||
case START:
|
||||
if (targetPointsHelper.getPointToStart() != null) {
|
||||
targetPointsHelper.clearStartPoint(true);
|
||||
app.getSettings().backupPointToStart();
|
||||
}
|
||||
break;
|
||||
case TARGET:
|
||||
app.showShortToastMessage(R.string.add_destination_point);
|
||||
targetPointsHelper.navigateToPoint(ll, true, -1);
|
||||
break;
|
||||
case INTERMEDIATE:
|
||||
app.showShortToastMessage(R.string.add_intermediate_point);
|
||||
targetPointsHelper.navigateToPoint(ll, true, targetPointsHelper.getIntermediatePoints().size());
|
||||
break;
|
||||
case HOME:
|
||||
app.showShortToastMessage(R.string.add_intermediate_point);
|
||||
targetPointsHelper.setHomePoint(ll, null);
|
||||
break;
|
||||
case WORK:
|
||||
app.showShortToastMessage(R.string.add_intermediate_point);
|
||||
targetPointsHelper.setWorkPoint(ll, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (activity != null) {
|
||||
ActivityCompat.requestPermissions(activity,
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
|
||||
OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION);
|
||||
}
|
||||
}
|
||||
dismiss();
|
||||
|
|
|
@ -1640,9 +1640,14 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener
|
|||
|
||||
public void updateFromIcon(View parentView) {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
|
||||
int locationIconResByStatus = OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)
|
||||
? R.drawable.ic_action_location_color : R.drawable.ic_action_location_color_lost;
|
||||
|
||||
if (mapActivity != null) {
|
||||
((ImageView) parentView.findViewById(R.id.fromIcon)).setImageDrawable(ContextCompat.getDrawable(mapActivity,
|
||||
mapActivity.getMyApplication().getTargetPointsHelper().getPointToStart() == null ? R.drawable.ic_action_location_color : R.drawable.list_startpoint));
|
||||
mapActivity.getMyApplication().getTargetPointsHelper().getPointToStart() == null
|
||||
? locationIconResByStatus : R.drawable.list_startpoint));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,11 +72,7 @@ public class RoutingOptionsHelper {
|
|||
addRouteMenuAppModes(ApplicationMode.PEDESTRIAN, PermanentAppModeOptions.PEDESTRIAN.routingParameters);
|
||||
addRouteMenuAppModes(ApplicationMode.PUBLIC_TRANSPORT, PermanentAppModeOptions.PUBLIC_TRANSPORT.routingParameters);
|
||||
addRouteMenuAppModes(ApplicationMode.BOAT, PermanentAppModeOptions.BOAT.routingParameters);
|
||||
addRouteMenuAppModes(ApplicationMode.AIRCRAFT, PermanentAppModeOptions.AIRCAFT.routingParameters);
|
||||
addRouteMenuAppModes(ApplicationMode.HIKING, PermanentAppModeOptions.HIKING.routingParameters);
|
||||
addRouteMenuAppModes(ApplicationMode.MOTORCYCLE, PermanentAppModeOptions.MOTORCYCLE.routingParameters);
|
||||
addRouteMenuAppModes(ApplicationMode.TRUCK, PermanentAppModeOptions.TRUCK.routingParameters);
|
||||
addRouteMenuAppModes(ApplicationMode.TRAIN, PermanentAppModeOptions.TRAIN.routingParameters);
|
||||
addRouteMenuAppModes(ApplicationMode.AIRCRAFT, PermanentAppModeOptions.AIRCRAFT.routingParameters);
|
||||
}
|
||||
|
||||
private void addRouteMenuAppModes(ApplicationMode am, List<String> routingParameters) {
|
||||
|
@ -382,7 +378,7 @@ public class RoutingOptionsHelper {
|
|||
|
||||
public LocalRoutingParameter getRoutingParameterInnerById(ApplicationMode am, String parameterId) {
|
||||
RouteProvider.GPXRouteParamsBuilder rparams = app.getRoutingHelper().getCurrentGPXRoute();
|
||||
GeneralRouter rm = getRouter(app.getDefaultRoutingConfig(), am);
|
||||
GeneralRouter rm = getRouter(app.getRoutingConfig(), am);
|
||||
if (rm == null || (rparams != null && !rparams.isCalculateOsmAndRoute()) && !rparams.getFile().hasRtePt()) {
|
||||
return null;
|
||||
}
|
||||
|
@ -407,7 +403,6 @@ public class RoutingOptionsHelper {
|
|||
}
|
||||
return rpg;
|
||||
}
|
||||
|
||||
return rp;
|
||||
}
|
||||
|
||||
|
@ -457,7 +452,7 @@ public class RoutingOptionsHelper {
|
|||
public List<LocalRoutingParameter> getRoutingParametersInner(ApplicationMode am) {
|
||||
RouteProvider.GPXRouteParamsBuilder rparams = app.getRoutingHelper().getCurrentGPXRoute();
|
||||
List<LocalRoutingParameter> list = new ArrayList<LocalRoutingParameter>(getGpxAndOsmandRouterParameters(am));
|
||||
GeneralRouter rm = SettingsNavigationActivity.getRouter(app.getDefaultRoutingConfig(), am);
|
||||
GeneralRouter rm = SettingsNavigationActivity.getRouter(app.getRoutingConfig(), am);
|
||||
if (rm == null || (rparams != null && !rparams.isCalculateOsmAndRoute()) && !rparams.getFile().hasRtePt()) {
|
||||
return list;
|
||||
}
|
||||
|
@ -547,7 +542,7 @@ public class RoutingOptionsHelper {
|
|||
|
||||
public List<GeneralRouter.RoutingParameter> getAvoidRoutingPrefsForAppMode(ApplicationMode applicationMode) {
|
||||
List<GeneralRouter.RoutingParameter> avoidParameters = new ArrayList<GeneralRouter.RoutingParameter>();
|
||||
GeneralRouter router = getRouter(app.getDefaultRoutingConfig(), applicationMode);
|
||||
GeneralRouter router = getRouter(app.getRoutingConfig(), applicationMode);
|
||||
if (router != null) {
|
||||
for (Map.Entry<String, GeneralRouter.RoutingParameter> e : router.getParameters().entrySet()) {
|
||||
String param = e.getKey();
|
||||
|
@ -561,7 +556,7 @@ public class RoutingOptionsHelper {
|
|||
}
|
||||
|
||||
public GeneralRouter.RoutingParameter getRoutingPrefsForAppModeById(ApplicationMode applicationMode, String parameterId) {
|
||||
GeneralRouter router = getRouter(app.getDefaultRoutingConfig(), applicationMode);
|
||||
GeneralRouter router = getRouter(app.getRoutingConfig(), applicationMode);
|
||||
GeneralRouter.RoutingParameter parameter = null;
|
||||
|
||||
if (router != null) {
|
||||
|
@ -971,11 +966,7 @@ public class RoutingOptionsHelper {
|
|||
PEDESTRIAN(MuteSoundRoutingParameter.KEY, GeneralRouter.USE_HEIGHT_OBSTACLES),
|
||||
PUBLIC_TRANSPORT(MuteSoundRoutingParameter.KEY, AvoidPTTypesRoutingParameter.KEY),
|
||||
BOAT(MuteSoundRoutingParameter.KEY),
|
||||
AIRCAFT(MuteSoundRoutingParameter.KEY),
|
||||
HIKING(MuteSoundRoutingParameter.KEY),
|
||||
MOTORCYCLE(MuteSoundRoutingParameter.KEY),
|
||||
TRUCK(MuteSoundRoutingParameter.KEY),
|
||||
TRAIN(MuteSoundRoutingParameter.KEY);
|
||||
AIRCRAFT(MuteSoundRoutingParameter.KEY);
|
||||
|
||||
List<String> routingParameters;
|
||||
|
||||
|
|
|
@ -595,7 +595,7 @@ public class RouteProvider {
|
|||
OsmandSettings settings = params.ctx.getSettings();
|
||||
router.setUseFastRecalculation(settings.USE_FAST_RECALCULATION.get());
|
||||
|
||||
RoutingConfiguration.Builder config = params.ctx.getDefaultRoutingConfig();
|
||||
RoutingConfiguration.Builder config = params.ctx.getRoutingConfig();
|
||||
GeneralRouter generalRouter = SettingsNavigationActivity.getRouter(config, params.mode);
|
||||
if(generalRouter == null) {
|
||||
return applicationModeNotSupported(params);
|
||||
|
@ -680,19 +680,6 @@ public class RouteProvider {
|
|||
|
||||
private RoutingConfiguration initOsmAndRoutingConfig(Builder config, final RouteCalculationParams params, OsmandSettings settings,
|
||||
GeneralRouter generalRouter) throws IOException, FileNotFoundException {
|
||||
GeneralRouterProfile p ;
|
||||
if (params.mode.isDerivedRoutingFrom(ApplicationMode.BICYCLE)) {
|
||||
p = GeneralRouterProfile.BICYCLE;
|
||||
} else if (params.mode.isDerivedRoutingFrom(ApplicationMode.PEDESTRIAN)) {
|
||||
p = GeneralRouterProfile.PEDESTRIAN;
|
||||
} else if(params.mode.isDerivedRoutingFrom(ApplicationMode.CAR)){
|
||||
p = GeneralRouterProfile.CAR;
|
||||
} else if (params.mode.isDerivedRoutingFrom(ApplicationMode.BOAT)) {
|
||||
p = GeneralRouterProfile.BOAT;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, String> paramsR = new LinkedHashMap<String, String>();
|
||||
for(Map.Entry<String, RoutingParameter> e : generalRouter.getParameters().entrySet()){
|
||||
String key = e.getKey();
|
||||
|
@ -720,8 +707,7 @@ public class RouteProvider {
|
|||
// make visible
|
||||
int memoryLimit = (int) (0.95 * ((rt.maxMemory() - rt.totalMemory()) + rt.freeMemory()) / mb);
|
||||
log.warn("Use " + memoryLimit + " MB Free " + rt.freeMemory() / mb + " of " + rt.totalMemory() / mb + " max " + rt.maxMemory() / mb);
|
||||
|
||||
RoutingConfiguration cf = config.build(p.name().toLowerCase(), params.start.hasBearing() ?
|
||||
RoutingConfiguration cf = config.build( params.mode.getRoutingProfile(), params.start.hasBearing() ?
|
||||
params.start.getBearing() / 180d * Math.PI : null,
|
||||
memoryLimit, paramsR);
|
||||
return cf;
|
||||
|
|
|
@ -443,11 +443,11 @@ public class TransportRoutingHelper {
|
|||
}
|
||||
|
||||
private List<TransportRouteResult> calculateRouteImpl(TransportRouteCalculationParams params) throws IOException, InterruptedException {
|
||||
RoutingConfiguration.Builder config = params.ctx.getDefaultRoutingConfig();
|
||||
RoutingConfiguration.Builder config = params.ctx.getRoutingConfig();
|
||||
BinaryMapIndexReader[] files = params.ctx.getResourceManager().getTransportRoutingMapFiles();
|
||||
params.params.clear();
|
||||
OsmandSettings settings = params.ctx.getSettings();
|
||||
for(Map.Entry<String, GeneralRouter.RoutingParameter> e : config.getRouter(params.mode.getStringKey()).getParameters().entrySet()){
|
||||
for(Map.Entry<String, GeneralRouter.RoutingParameter> e : config.getRouter(params.mode.getRoutingProfile()).getParameters().entrySet()){
|
||||
String key = e.getKey();
|
||||
GeneralRouter.RoutingParameter pr = e.getValue();
|
||||
String vl;
|
||||
|
|
|
@ -18,6 +18,7 @@ import net.osmand.plus.activities.MapActivity;
|
|||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu.TrackChartPoints;
|
||||
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory;
|
||||
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.CompassRulerControlWidgetState;
|
||||
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopCoordinatesView;
|
||||
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopTextView;
|
||||
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
|
||||
|
@ -200,7 +201,7 @@ public class MapInfoLayer extends OsmandMapLayer {
|
|||
TextInfoWidget battery = ric.createBatteryControl(map);
|
||||
registerSideWidget(battery, R.drawable.ic_action_battery, R.string.map_widget_battery, "battery", false, 42);
|
||||
TextInfoWidget ruler = mic.createRulerControl(map);
|
||||
registerSideWidget(ruler, R.drawable.ic_action_ruler_circle, R.string.map_widget_ruler_control, "ruler", false, 43);
|
||||
registerSideWidget(ruler, new CompassRulerControlWidgetState(app), "ruler", false, 43);
|
||||
}
|
||||
|
||||
public void recreateControls() {
|
||||
|
|
|
@ -3,17 +3,23 @@ package net.osmand.plus.views;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PathMeasure;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.Location;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.QuadPoint;
|
||||
|
@ -36,6 +42,7 @@ public class RulerControlLayer extends OsmandMapLayer {
|
|||
private static final long DELAY_BEFORE_DRAW = 500;
|
||||
private static final int TEXT_SIZE = 14;
|
||||
private static final int DISTANCE_TEXT_SIZE = 16;
|
||||
private static final int COMPASS_CIRCLE_ID = 2;
|
||||
|
||||
private final MapActivity mapActivity;
|
||||
private OsmandApplication app;
|
||||
|
@ -74,11 +81,26 @@ public class RulerControlLayer extends OsmandMapLayer {
|
|||
private Bitmap centerIconDay;
|
||||
private Bitmap centerIconNight;
|
||||
private Paint bitmapPaint;
|
||||
private Paint triangleHeadingPaint;
|
||||
private Paint triangleNorthPaint;
|
||||
private Paint redLinesPaint;
|
||||
private Paint blueLinesPaint;
|
||||
|
||||
private RenderingLineAttributes lineAttrs;
|
||||
private RenderingLineAttributes lineFontAttrs;
|
||||
private RenderingLineAttributes circleAttrs;
|
||||
private RenderingLineAttributes circleAttrsAlt;
|
||||
|
||||
private Path compass = new Path();
|
||||
private Path arrow = new Path();
|
||||
private Path arrowArc = new Path();
|
||||
private Path redCompassLines = new Path();
|
||||
|
||||
private double[] degrees = new double[72];
|
||||
private int[] arcColors = {Color.parseColor("#00237BFF"), Color.parseColor("#237BFF"), Color.parseColor("#00237BFF")};
|
||||
|
||||
private float cachedHeading = 0;
|
||||
|
||||
private Handler handler;
|
||||
|
||||
public RulerControlLayer(MapActivity mapActivity) {
|
||||
|
@ -118,6 +140,14 @@ public class RulerControlLayer extends OsmandMapLayer {
|
|||
bitmapPaint.setDither(true);
|
||||
bitmapPaint.setFilterBitmap(true);
|
||||
|
||||
int colorNorthArrow = ContextCompat.getColor(app, R.color.compass_control_active);
|
||||
int colorHeadingArrow = ContextCompat.getColor(app, R.color.active_buttons_and_links_light);
|
||||
|
||||
triangleNorthPaint = initPaintWithStyle(Style.FILL, colorNorthArrow);
|
||||
triangleHeadingPaint = initPaintWithStyle(Style.FILL, colorHeadingArrow);
|
||||
redLinesPaint = initPaintWithStyle(Style.STROKE, colorNorthArrow);
|
||||
blueLinesPaint = initPaintWithStyle(Style.STROKE, colorHeadingArrow);
|
||||
|
||||
lineAttrs = new RenderingLineAttributes("rulerLine");
|
||||
|
||||
float circleTextSize = TEXT_SIZE * mapActivity.getResources().getDisplayMetrics().density;
|
||||
|
@ -141,6 +171,18 @@ public class RulerControlLayer extends OsmandMapLayer {
|
|||
view.refreshMap();
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < 72; i++) {
|
||||
degrees[i] = Math.toRadians(i * 5);
|
||||
}
|
||||
}
|
||||
|
||||
private Paint initPaintWithStyle(Paint.Style style, int color) {
|
||||
Paint paint = new Paint();
|
||||
paint.setStyle(style);
|
||||
paint.setColor(color);
|
||||
paint.setAntiAlias(true);
|
||||
return paint;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -190,6 +232,7 @@ public class RulerControlLayer extends OsmandMapLayer {
|
|||
circleAttrsAlt.paint2.setStyle(Style.FILL);
|
||||
final QuadPoint center = tb.getCenterPixelPoint();
|
||||
final RulerMode mode = app.getSettings().RULER_MODE.get();
|
||||
boolean showCompass = app.getSettings().SHOW_COMPASS_CONTROL_RULER.get();
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
|
||||
if (cacheMultiTouchEndTime != view.getMultiTouchEndTime()) {
|
||||
|
@ -226,9 +269,17 @@ public class RulerControlLayer extends OsmandMapLayer {
|
|||
}
|
||||
if (mode == RulerMode.FIRST || mode == RulerMode.SECOND) {
|
||||
updateData(tb, center);
|
||||
if (showCompass) {
|
||||
updateHeading();
|
||||
resetDrawingPaths();
|
||||
}
|
||||
RenderingLineAttributes attrs = mode == RulerMode.FIRST ? circleAttrs : circleAttrsAlt;
|
||||
for (int i = 1; i <= cacheDistances.size(); i++) {
|
||||
drawCircle(canvas, tb, i, center, attrs);
|
||||
if (showCompass && i == COMPASS_CIRCLE_ID) {
|
||||
drawCompassCircle(canvas, tb, center, attrs);
|
||||
} else {
|
||||
drawCircle(canvas, tb, i, center, attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +290,20 @@ public class RulerControlLayer extends OsmandMapLayer {
|
|||
rightWidgetsPanel.getVisibility() == View.VISIBLE;
|
||||
}
|
||||
|
||||
private void updateHeading() {
|
||||
Float heading = mapActivity.getMapViewTrackingUtilities().getHeading();
|
||||
if (heading != null && heading != cachedHeading) {
|
||||
cachedHeading = heading;
|
||||
}
|
||||
}
|
||||
|
||||
private void resetDrawingPaths() {
|
||||
redCompassLines.reset();
|
||||
arrowArc.reset();
|
||||
compass.reset();
|
||||
arrow.reset();
|
||||
}
|
||||
|
||||
private void refreshMapDelayed() {
|
||||
handler.sendEmptyMessageDelayed(0, DRAW_TIME + 50);
|
||||
}
|
||||
|
@ -293,7 +358,7 @@ public class RulerControlLayer extends OsmandMapLayer {
|
|||
}
|
||||
|
||||
private void drawCenterIcon(Canvas canvas, RotatedTileBox tb, QuadPoint center, boolean nightMode,
|
||||
RulerMode mode) {
|
||||
RulerMode mode) {
|
||||
canvas.rotate(-tb.getRotate(), center.x, center.y);
|
||||
if (nightMode || mode == RulerMode.SECOND) {
|
||||
canvas.drawBitmap(centerIconNight, center.x - centerIconNight.getWidth() / 2,
|
||||
|
@ -391,42 +456,200 @@ public class RulerControlLayer extends OsmandMapLayer {
|
|||
}
|
||||
|
||||
private void drawCircle(Canvas canvas, RotatedTileBox tb, int circleNumber, QuadPoint center,
|
||||
RenderingLineAttributes attrs) {
|
||||
RenderingLineAttributes attrs) {
|
||||
if (!tb.isZoomAnimated()) {
|
||||
Rect bounds = new Rect();
|
||||
float circleRadius = radius * circleNumber;
|
||||
String text = cacheDistances.get(circleNumber - 1);
|
||||
attrs.paint2.getTextBounds(text, 0, text.length(), bounds);
|
||||
|
||||
// coords of left or top text
|
||||
float x1 = 0;
|
||||
float y1 = 0;
|
||||
// coords of right or bottom text
|
||||
float x2 = 0;
|
||||
float y2 = 0;
|
||||
|
||||
if (textSide == TextSide.VERTICAL) {
|
||||
x1 = center.x - bounds.width() / 2;
|
||||
y1 = center.y - radius * circleNumber + bounds.height() / 2;
|
||||
x2 = center.x - bounds.width() / 2;
|
||||
y2 = center.y + radius * circleNumber + bounds.height() / 2;
|
||||
} else if (textSide == TextSide.HORIZONTAL) {
|
||||
x1 = center.x - radius * circleNumber - bounds.width() / 2;
|
||||
y1 = center.y + bounds.height() / 2;
|
||||
x2 = center.x + radius * circleNumber - bounds.width() / 2;
|
||||
y2 = center.y + bounds.height() / 2;
|
||||
}
|
||||
float[] textCoords = calculateDistanceTextCoords(text, circleRadius, center, attrs);
|
||||
|
||||
canvas.rotate(-tb.getRotate(), center.x, center.y);
|
||||
canvas.drawCircle(center.x, center.y, radius * circleNumber, attrs.shadowPaint);
|
||||
canvas.drawCircle(center.x, center.y, radius * circleNumber, attrs.paint);
|
||||
canvas.drawText(text, x1, y1, attrs.paint3);
|
||||
canvas.drawText(text, x1, y1, attrs.paint2);
|
||||
canvas.drawText(text, x2, y2, attrs.paint3);
|
||||
canvas.drawText(text, x2, y2, attrs.paint2);
|
||||
drawTextCoords(canvas, text, textCoords, attrs);
|
||||
canvas.rotate(tb.getRotate(), center.x, center.y);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawTextCoords(Canvas canvas, String text, float[] textCoords, RenderingLineAttributes attrs) {
|
||||
canvas.drawText(text, textCoords[0], textCoords[1], attrs.paint3);
|
||||
canvas.drawText(text, textCoords[0], textCoords[1], attrs.paint2);
|
||||
canvas.drawText(text, textCoords[2], textCoords[3], attrs.paint3);
|
||||
canvas.drawText(text, textCoords[2], textCoords[3], attrs.paint2);
|
||||
}
|
||||
|
||||
private float[] calculateDistanceTextCoords(String text, float drawingTextRadius, QuadPoint center, RenderingLineAttributes attrs) {
|
||||
Rect bounds = new Rect();
|
||||
attrs.paint2.getTextBounds(text, 0, text.length(), bounds);
|
||||
|
||||
// coords of left or top text
|
||||
float x1 = 0;
|
||||
float y1 = 0;
|
||||
// coords of right or bottom text
|
||||
float x2 = 0;
|
||||
float y2 = 0;
|
||||
|
||||
if (textSide == TextSide.VERTICAL) {
|
||||
x1 = center.x - bounds.width() / 2;
|
||||
y1 = center.y - drawingTextRadius + bounds.height() / 2;
|
||||
x2 = center.x - bounds.width() / 2;
|
||||
y2 = center.y + drawingTextRadius + bounds.height() / 2;
|
||||
} else if (textSide == TextSide.HORIZONTAL) {
|
||||
x1 = center.x - drawingTextRadius - bounds.width() / 2;
|
||||
y1 = center.y + bounds.height() / 2;
|
||||
x2 = center.x + drawingTextRadius - bounds.width() / 2;
|
||||
y2 = center.y + bounds.height() / 2;
|
||||
}
|
||||
return new float[]{x1, y1, x2, y2};
|
||||
}
|
||||
|
||||
private void drawCompassCircle(Canvas canvas, RotatedTileBox tileBox, QuadPoint center,
|
||||
RenderingLineAttributes attrs) {
|
||||
if (!tileBox.isZoomAnimated()) {
|
||||
float radiusLength = radius * COMPASS_CIRCLE_ID;
|
||||
float innerRadiusLength = radiusLength - attrs.paint.getStrokeWidth() / 2;
|
||||
|
||||
updateArcShader(radiusLength, center);
|
||||
updateCompassPaths(center, innerRadiusLength, radiusLength);
|
||||
drawCardinalDirections(canvas, center, radiusLength, tileBox, attrs);
|
||||
|
||||
redLinesPaint.setStrokeWidth(attrs.paint.getStrokeWidth());
|
||||
blueLinesPaint.setStrokeWidth(attrs.paint.getStrokeWidth());
|
||||
|
||||
canvas.drawPath(compass, attrs.shadowPaint);
|
||||
canvas.drawPath(compass, attrs.paint);
|
||||
canvas.drawPath(redCompassLines, redLinesPaint);
|
||||
|
||||
canvas.rotate(cachedHeading, center.x, center.y);
|
||||
canvas.drawPath(arrowArc, blueLinesPaint);
|
||||
canvas.rotate(-cachedHeading, center.x, center.y);
|
||||
|
||||
canvas.drawPath(arrow, attrs.shadowPaint);
|
||||
canvas.drawPath(arrow, triangleNorthPaint);
|
||||
|
||||
canvas.rotate(cachedHeading, center.x, center.y);
|
||||
canvas.drawPath(arrow, attrs.shadowPaint);
|
||||
canvas.drawPath(arrow, triangleHeadingPaint);
|
||||
canvas.rotate(-cachedHeading, center.x, center.y);
|
||||
|
||||
String text = cacheDistances.get(COMPASS_CIRCLE_ID - 1);
|
||||
float[] textCoords = calculateDistanceTextCoords(text, radiusLength + AndroidUtils.dpToPx(app, 16), center, attrs);
|
||||
canvas.rotate(-tileBox.getRotate(), center.x, center.y);
|
||||
drawTextCoords(canvas, text, textCoords, attrs);
|
||||
canvas.rotate(tileBox.getRotate(), center.x, center.y);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCompassPaths(QuadPoint center, float innerRadiusLength, float radiusLength) {
|
||||
compass.addCircle(center.x, center.y, radiusLength, Path.Direction.CCW);
|
||||
|
||||
arrowArc.addArc(new RectF(center.x - radiusLength, center.y - radiusLength, center.x + radiusLength, center.y + radiusLength), -45, -90);
|
||||
|
||||
for (int i = 0; i < degrees.length; i++) {
|
||||
double degree = degrees[i];
|
||||
float x = (float) Math.cos(degree);
|
||||
float y = -(float) Math.sin(degree);
|
||||
|
||||
float lineStartX = center.x + x * innerRadiusLength;
|
||||
float lineStartY = center.y + y * innerRadiusLength;
|
||||
|
||||
float lineLength = getCompassLineHeight(i);
|
||||
|
||||
float lineStopX = center.x + x * (innerRadiusLength - lineLength);
|
||||
float lineStopY = center.y + y * (innerRadiusLength - lineLength);
|
||||
|
||||
if (i == 18) {
|
||||
float shortLineMargin = AndroidUtils.dpToPx(app, 5.66f);
|
||||
float shortLineHeight = AndroidUtils.dpToPx(app, 2.94f);
|
||||
float startY = center.y + y * (radiusLength - shortLineMargin);
|
||||
float stopY = center.y + y * (radiusLength - shortLineMargin - shortLineHeight);
|
||||
|
||||
compass.moveTo(center.x, startY);
|
||||
compass.lineTo(center.x, stopY);
|
||||
|
||||
float firstPointY = center.y + y * (radiusLength + AndroidUtils.dpToPx(app, 5));
|
||||
|
||||
float secondPointX = center.x - AndroidUtils.dpToPx(app, 4);
|
||||
float secondPointY = center.y + y * (radiusLength - AndroidUtils.dpToPx(app, 2));
|
||||
|
||||
float thirdPointX = center.x + AndroidUtils.dpToPx(app, 4);
|
||||
float thirdPointY = center.y + y * (radiusLength - AndroidUtils.dpToPx(app, 2));
|
||||
|
||||
arrow.moveTo(center.x, firstPointY);
|
||||
arrow.lineTo(secondPointX, secondPointY);
|
||||
arrow.lineTo(thirdPointX, thirdPointY);
|
||||
arrow.lineTo(center.x, firstPointY);
|
||||
arrow.close();
|
||||
} else {
|
||||
compass.moveTo(lineStartX, lineStartY);
|
||||
compass.lineTo(lineStopX, lineStopY);
|
||||
}
|
||||
if (i % 9 == 0 && i % 6 != 0) {
|
||||
redCompassLines.moveTo(lineStartX, lineStartY);
|
||||
redCompassLines.lineTo(lineStopX, lineStopY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float getCompassLineHeight(int index) {
|
||||
if (index % 6 == 0) {
|
||||
return AndroidUtils.dpToPx(app, 8);
|
||||
} else if (index % 9 == 0 || index % 2 != 0) {
|
||||
return AndroidUtils.dpToPx(app, 3);
|
||||
} else {
|
||||
return AndroidUtils.dpToPx(app, 6);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawCardinalDirections(Canvas canvas, QuadPoint center, float radiusLength, RotatedTileBox tileBox, RenderingLineAttributes attrs) {
|
||||
float textMargin = AndroidUtils.dpToPx(app, 14);
|
||||
attrs.paint2.setTextAlign(Paint.Align.CENTER);
|
||||
attrs.paint3.setTextAlign(Paint.Align.CENTER);
|
||||
|
||||
for (int i = 0; i < degrees.length; i += 9) {
|
||||
String cardinalDirection = getCardinalDirection(i);
|
||||
if (cardinalDirection != null) {
|
||||
float textWidth = AndroidUtils.getTextWidth(attrs.paint2.getTextSize(), cardinalDirection);
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(center.x, center.y);
|
||||
canvas.rotate(i * 5 + 90);
|
||||
canvas.translate(0, radiusLength - textMargin - textWidth / 2);
|
||||
canvas.rotate(-i * 5 - tileBox.getRotate() - 90);
|
||||
|
||||
canvas.drawText(cardinalDirection, 0, 0, attrs.paint3);
|
||||
canvas.drawText(cardinalDirection, 0, 0, attrs.paint2);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateArcShader(float radiusLength, QuadPoint center) {
|
||||
float arcLength = (float) (2 * Math.PI * radiusLength * (90f / 360));
|
||||
LinearGradient shader = new LinearGradient((float) (center.x - arcLength * 0.25), center.y, (float) (center.x + arcLength * 0.25), center.y, arcColors, null, Shader.TileMode.CLAMP);
|
||||
blueLinesPaint.setShader(shader);
|
||||
}
|
||||
|
||||
private String getCardinalDirection(int i) {
|
||||
if (i == 0) {
|
||||
return "E";
|
||||
} else if (i == 9) {
|
||||
return "NE";
|
||||
} else if (i == 18) {
|
||||
return "N";
|
||||
} else if (i == 27) {
|
||||
return "NW";
|
||||
} else if (i == 36) {
|
||||
return "W";
|
||||
} else if (i == 45) {
|
||||
return "SW";
|
||||
} else if (i == 54) {
|
||||
return "S";
|
||||
} else if (i == 63) {
|
||||
return "SE";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private enum TextSide {
|
||||
VERTICAL,
|
||||
HORIZONTAL
|
||||
|
@ -441,4 +664,4 @@ public class RulerControlLayer extends OsmandMapLayer {
|
|||
public boolean drawInScreenPixels() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@ import net.osmand.plus.routing.RoutingHelper;
|
|||
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.plus.views.RulerControlLayer;
|
||||
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WidgetState;
|
||||
import net.osmand.plus.views.mapwidgets.NextTurnInfoWidget.TurnDrawable;
|
||||
import net.osmand.router.TurnType;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
@ -138,6 +139,54 @@ public class MapInfoWidgetsFactory {
|
|||
return gpsInfoControl;
|
||||
}
|
||||
|
||||
public static class CompassRulerControlWidgetState extends WidgetState {
|
||||
|
||||
public static final int COMPASS_CONTROL_WIDGET_STATE_SHOW = R.id.compass_ruler_control_widget_state_show;
|
||||
public static final int COMPASS_CONTROL_WIDGET_STATE_HIDE = R.id.compass_ruler_control_widget_state_hide;
|
||||
|
||||
private final OsmandSettings.OsmandPreference<Boolean> showCompass;
|
||||
|
||||
public CompassRulerControlWidgetState(OsmandApplication ctx) {
|
||||
super(ctx);
|
||||
showCompass = ctx.getSettings().SHOW_COMPASS_CONTROL_RULER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMenuTitleId() {
|
||||
return R.string.map_widget_ruler_control;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMenuIconId() {
|
||||
return R.drawable.ic_action_ruler_circle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMenuItemId() {
|
||||
return showCompass.get() ? COMPASS_CONTROL_WIDGET_STATE_SHOW : COMPASS_CONTROL_WIDGET_STATE_HIDE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getMenuTitleIds() {
|
||||
return new int[]{R.string.show_compass_ruler, R.string.hide_compass_ruler};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getMenuIconIds() {
|
||||
return new int[]{R.drawable.ic_action_compass_widget, R.drawable.ic_action_compass_widget_hide};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getMenuItemIds() {
|
||||
return new int[]{COMPASS_CONTROL_WIDGET_STATE_SHOW, COMPASS_CONTROL_WIDGET_STATE_HIDE};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeState(int stateId) {
|
||||
showCompass.set(stateId == COMPASS_CONTROL_WIDGET_STATE_SHOW);
|
||||
}
|
||||
}
|
||||
|
||||
public TextInfoWidget createRulerControl(final MapActivity map) {
|
||||
final String title = "—";
|
||||
final TextInfoWidget rulerControl = new TextInfoWidget(map) {
|
||||
|
|
|
@ -66,7 +66,7 @@ Functionality
|
|||
* Add POIs and directly upload them to OSM (or later if offline)
|
||||
* Optional trip recording also in background mode (while device is in sleep mode)
|
||||
|
||||
OsmAnd is open source and actively being developed. Everyone can contribute to the application by reporting bugs, [improving translations](https://hosted.weblate.org/projects/osmand/), or coding new features. The project is in a lively state of continuous improvement by all these forms of developer and user interaction. The project progress also relies on financial contributions to fund the development, coding, and testing of new functionality. By buying OsmAnd+ and subscribing to OsmAnd Live you help the application to be even more awesome! It is also possible to make a general donation, see http://osmand.net/help-online#buy_app.
|
||||
OsmAnd is open source and actively being developed. Everyone can contribute to the application by reporting bugs, [improving translations](https://hosted.weblate.org/projects/osmand/), or coding new features. The project is in a lively selected of continuous improvement by all these forms of developer and user interaction. The project progress also relies on financial contributions to fund the development, coding, and testing of new functionality. By buying OsmAnd+ and subscribing to OsmAnd Live you help the application to be even more awesome! It is also possible to make a general donation, see http://osmand.net/help-online#buy_app.
|
||||
|
||||
|
||||
#### Approximate map coverage and quality:
|
||||
|
|