Merge pull request #6815 from osmandapp/app_profiles

App profiles
This commit is contained in:
Alexey 2019-05-22 16:16:33 +03:00 committed by GitHub
commit 09540e4485
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 2924 additions and 230 deletions

View file

@ -69,4 +69,5 @@ public class IndexConstants {
public static final String ROUTING_XML_FILE= "routing.xml"; public static final String ROUTING_XML_FILE= "routing.xml";
public static final String SETTINGS_DIR = "settings/"; //$NON-NLS-1$ public static final String SETTINGS_DIR = "settings/"; //$NON-NLS-1$
public static final String TEMP_DIR = "temp/"; public static final String TEMP_DIR = "temp/";
public static final String ROUTING_PROFILES_DIR = "routing/";
} }

View file

@ -44,6 +44,8 @@ public class GeneralRouter implements VehicleRouter {
private boolean shortestRoute; private boolean shortestRoute;
private boolean heightObstacles; private boolean heightObstacles;
private boolean allowPrivate; private boolean allowPrivate;
private String filename = null;
private String profileName = "";
private Map<RouteRegion, Map<Integer, Integer>> regionConvert = new LinkedHashMap<RouteRegion, Map<Integer,Integer>>(); private Map<RouteRegion, Map<Integer, Integer>> regionConvert = new LinkedHashMap<RouteRegion, Map<Integer,Integer>>();
@ -120,6 +122,22 @@ public class GeneralRouter implements VehicleRouter {
parameters = new LinkedHashMap<String, GeneralRouter.RoutingParameter>(); 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) { public GeneralRouter(GeneralRouter parent, Map<String, String> params) {
this.profile = parent.profile; this.profile = parent.profile;
this.attributes = new LinkedHashMap<String, String>(); this.attributes = new LinkedHashMap<String, String>();

View file

@ -47,13 +47,12 @@ public class RoutingConfiguration {
// 1.5 Recalculate distance help // 1.5 Recalculate distance help
public float recalculateDistance = 20000f; public float recalculateDistance = 20000f;
public static class Builder { public static class Builder {
// Design time storage // Design time storage
private String defaultRouter = ""; private String defaultRouter = "";
private Map<String, GeneralRouter> routers = new LinkedHashMap<String, GeneralRouter>(); private Map<String, GeneralRouter> routers = new LinkedHashMap<>();
private Map<String, String> attributes = new LinkedHashMap<String, String>(); private Map<String, String> attributes = new LinkedHashMap<>();
private HashMap<Long, Location> impassableRoadLocations = new HashMap<Long, Location>(); private HashMap<Long, Location> impassableRoadLocations = new HashMap<>();
// Example // Example
// { // {
@ -126,11 +125,15 @@ public class RoutingConfiguration {
return defaultRouter; return defaultRouter;
} }
public GeneralRouter getRouter(String applicationMode) { public GeneralRouter getRouter(String routingProfileName) {
return routers.get(applicationMode); return routers.get(routingProfileName);
} }
public Map<String, GeneralRouter> getAllRoutes() {
return routers;
}
public void removeImpassableRoad(RouteDataObject obj) { public void removeImpassableRoad(RouteDataObject obj) {
impassableRoadLocations.remove(obj.id); impassableRoadLocations.remove(obj.id);
} }
@ -165,9 +168,12 @@ public class RoutingConfiguration {
return DEFAULT; return DEFAULT;
} }
public static RoutingConfiguration.Builder parseFromInputStream(InputStream is) throws IOException, XmlPullParserException { 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(); XmlPullParser parser = PlatformUtil.newXMLPullParser();
final RoutingConfiguration.Builder config = new RoutingConfiguration.Builder();
GeneralRouter currentRouter = null; GeneralRouter currentRouter = null;
RouteDataObjectAttribute currentAttribute = null; RouteDataObjectAttribute currentAttribute = null;
String preType = null; String preType = null;
@ -180,7 +186,7 @@ public class RoutingConfiguration {
if ("osmand_routing_config".equals(name)) { if ("osmand_routing_config".equals(name)) {
config.defaultRouter = parser.getAttributeValue("", "defaultProfile"); config.defaultRouter = parser.getAttributeValue("", "defaultProfile");
} else if ("routingProfile".equals(name)) { } else if ("routingProfile".equals(name)) {
currentRouter = parseRoutingProfile(parser, config); currentRouter = parseRoutingProfile(parser, config, filename);
} else if ("attribute".equals(name)) { } else if ("attribute".equals(name)) {
parseAttribute(parser, config, currentRouter); parseAttribute(parser, config, currentRouter);
} else if ("parameter".equals(name)) { } else if ("parameter".equals(name)) {
@ -295,10 +301,8 @@ public class RoutingConfiguration {
} }
} }
private static GeneralRouter parseRoutingProfile(XmlPullParser parser, final RoutingConfiguration.Builder config, String filename) {
String currentSelectedRouterName = parser.getAttributeValue("", "name");
private static GeneralRouter parseRoutingProfile(XmlPullParser parser, final RoutingConfiguration.Builder config) {
String currentSelectedRouter = parser.getAttributeValue("", "name");
Map<String, String> attrs = new LinkedHashMap<String, String>(); Map<String, String> attrs = new LinkedHashMap<String, String>();
for(int i=0; i< parser.getAttributeCount(); i++) { for(int i=0; i< parser.getAttributeCount(); i++) {
attrs.put(parser.getAttributeName(i), parser.getAttributeValue(i)); attrs.put(parser.getAttributeName(i), parser.getAttributeValue(i));
@ -306,7 +310,13 @@ public class RoutingConfiguration {
GeneralRouterProfile c = Algorithms.parseEnumValue(GeneralRouterProfile.values(), GeneralRouterProfile c = Algorithms.parseEnumValue(GeneralRouterProfile.values(),
parser.getAttributeValue("", "baseProfile"), GeneralRouterProfile.CAR); parser.getAttributeValue("", "baseProfile"), GeneralRouterProfile.CAR);
GeneralRouter currentRouter = new GeneralRouter(c, attrs); 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; return currentRouter;
} }

View file

@ -891,5 +891,15 @@
</activity> </activity>
<receiver android:name="net.osmand.plus.liveupdates.LiveUpdatesAlarmReceiver"/> <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> </application>
</manifest> </manifest>

View 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>

View 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>

View 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>

View file

@ -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>

View 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>

View 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>

View file

@ -35,6 +35,80 @@
</android.support.design.widget.AppBarLayout> </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 <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" > android:layout_height="match_parent" >

View 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>

View 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>

View file

@ -455,6 +455,9 @@
<color name="wiki_webview_background_light">#ffffff</color> <color name="wiki_webview_background_light">#ffffff</color>
<color name="wiki_webview_background_dark">#17191a</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 --> <!-- Basic colors -->
<color name="app_bar_main_dark">#101112</color> <color name="app_bar_main_dark">#101112</color>
<color name="app_bar_main_light">#ff8800</color> <color name="app_bar_main_light">#ff8800</color>
@ -477,5 +480,8 @@
<color name="inactive_buttons_and_links_dark">#505050</color> <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_light">#66237bff</color>
<color name="active_buttons_and_links_trans_dark">#66d28521</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> </resources>

View file

@ -244,6 +244,7 @@
<dimen name="bottom_sheet_title_height">52dp</dimen> <dimen name="bottom_sheet_title_height">52dp</dimen>
<dimen name="bottom_sheet_descr_height">44dp</dimen> <dimen name="bottom_sheet_descr_height">44dp</dimen>
<dimen name="bottom_sheet_list_item_height">48dp</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_icon_margin">24dp</dimen>
<dimen name="bottom_sheet_divider_margin_top">7dp</dimen> <dimen name="bottom_sheet_divider_margin_top">7dp</dimen>
<dimen name="bottom_sheet_divider_margin_bottom">8dp</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_padding">3dp</dimen>
<dimen name="pages_item_margin">4dp</dimen> <dimen name="pages_item_margin">4dp</dimen>
<dimen name="setting_profile_item_height">64dp</dimen>
<dimen name="setting_profile_image_margin">20dp</dimen>
<dimen name="setting_profile_item_switch_margin">18dp</dimen>
</resources> </resources>

View file

@ -11,6 +11,37 @@
Thx - Hardy Thx - Hardy
--> -->
<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="searching_gps">Searching GPS</string>
<string name="coordinates_widget">Coordinates widget</string> <string name="coordinates_widget">Coordinates widget</string>
<string name="files_moved">Moved %1$d files (%2$s).</string> <string name="files_moved">Moved %1$d files (%2$s).</string>
@ -26,6 +57,7 @@
<string name="public_transport_calc_pedestrian">Calculate pedestrian route</string> <string name="public_transport_calc_pedestrian">Calculate pedestrian route</string>
<string name="public_transport_type">Transport type</string> <string name="public_transport_type">Transport type</string>
<string name="send_log">Send log</string> <string name="send_log">Send log</string>
<string name="routing_attr_avoid_tram_name">Avoid trams</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_tram_description">Avoid trams</string>
<string name="routing_attr_avoid_bus_name">Avoid buses</string> <string name="routing_attr_avoid_bus_name">Avoid buses</string>
@ -3118,5 +3150,6 @@
<string name="run_full_osmand_header">Launch OsmAnd?</string> <string name="run_full_osmand_header">Launch OsmAnd?</string>
<string name="routing_attr_avoid_sett_name">Avoid cobblestone and sett</string> <string name="routing_attr_avoid_sett_name">Avoid cobblestone and sett</string>
<string name="routing_attr_avoid_sett_description">Avoid cobblestone and sett</string> <string name="routing_attr_avoid_sett_description">Avoid cobblestone and sett</string>
<string name="select_icon_profile_dialog_title">Select icon</string>
</resources> </resources>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <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="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="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"/> <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" /> <PreferenceCategory android:key="plugin_settings" android:title="@string/plugin_settings" />

View file

@ -11,6 +11,7 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.support.v7.app.AlertDialog; 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.plus.wikivoyage.data.TravelDbHelper;
import net.osmand.render.RenderingRulesStorage; import net.osmand.render.RenderingRulesStorage;
import net.osmand.router.RoutingConfiguration; import net.osmand.router.RoutingConfiguration;
import net.osmand.router.RoutingConfiguration.Builder;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import net.osmand.util.OpeningHoursParser; 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_UPDATE_CARD.set(true);
app.getSettings().SHOW_TRAVEL_NEEDED_MAPS_CARD.set(true); app.getSettings().SHOW_TRAVEL_NEEDED_MAPS_CARD.set(true);
ApplicationMode.initCustomModes(app.getSettings());
initSettings = true; initSettings = true;
} }
public int getNumberOfStarts() { public int getNumberOfStarts() {
@ -456,6 +460,7 @@ public class AppInitializer implements IProgress {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
getLazyRoutingConfig();
app.applyTheme(app); app.applyTheme(app);
app.inAppPurchaseHelper = startupInit(new InAppPurchaseHelper(app), InAppPurchaseHelper.class); app.inAppPurchaseHelper = startupInit(new InAppPurchaseHelper(app), InAppPurchaseHelper.class);
app.poiTypes = startupInit(MapPoiTypes.getDefaultNoInit(), MapPoiTypes.class); app.poiTypes = startupInit(MapPoiTypes.getDefaultNoInit(), MapPoiTypes.class);
@ -546,31 +551,37 @@ public class AppInitializer implements IProgress {
return object; return object;
} }
@SuppressLint("StaticFieldLeak")
public net.osmand.router.RoutingConfiguration.Builder getLazyDefaultRoutingConfig() { private void getLazyRoutingConfig() {
long tm = System.currentTimeMillis(); new AsyncTask<Void, Void, RoutingConfiguration.Builder>() {
try { @Override
File routingXml = app.getAppPath(IndexConstants.ROUTING_XML_FILE); protected Builder doInBackground(Void... voids) {
if (routingXml.exists() && routingXml.canRead()) { File routingFolder = app.getAppPath(IndexConstants.ROUTING_PROFILES_DIR);
try { RoutingConfiguration.Builder builder = RoutingConfiguration.getDefault();
return RoutingConfiguration.parseFromInputStream(new FileInputStream(routingXml)); if (routingFolder.isDirectory() && routingFolder.listFiles().length > 0) {
} catch (XmlPullParserException | IOException e) { File[] fl = routingFolder.listFiles();
throw new IllegalStateException(e); 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 builder;
return RoutingConfiguration.getDefault();
} }
} finally {
long te = System.currentTimeMillis(); @Override
if(te - tm > 30) { protected void onPostExecute(Builder builder) {
System.err.println("Defalt routing config init took " + (te - tm) + " ms"); super.onPostExecute(builder);
app.updateRoutingConfig(builder);
} }
} }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} }
public synchronized void initVoiceDataInDifferentThread(final Activity uiContext, public synchronized void initVoiceDataInDifferentThread(final Activity uiContext,
final ApplicationMode applicationMode, final ApplicationMode applicationMode,
final String voiceProvider, final String voiceProvider,

View file

@ -2,6 +2,14 @@ package net.osmand.plus;
import android.content.Context; 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 net.osmand.StateChangedListener;
import java.util.ArrayList; import java.util.ArrayList;
@ -12,53 +20,46 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; 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 { 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>> widgetsVisibilityMap = new LinkedHashMap<>();
private static Map<String, Set<ApplicationMode>> widgetsAvailabilityMap = 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> values = new ArrayList<>();
private static List<ApplicationMode> cachedFilteredValues = 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(). 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(); 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(). 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(). 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). 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"). 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(). 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).reg(); 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(). 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(); icon(R.drawable.map_action_aircraft, R.drawable.ic_action_aircraft).setRouteService(RouteService.STRAIGHT).setRoutingProfile("STRAIGHT_LINE_MODE").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();
static { static {
ApplicationMode[] exceptDefault = new ApplicationMode[]{CAR, PEDESTRIAN, 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, TRAIN}; ApplicationMode[] exceptPedestrianAndDefault = new ApplicationMode[]{CAR, BICYCLE, BOAT, AIRCRAFT, PUBLIC_TRANSPORT};
ApplicationMode[] exceptAirBoatDefault = new ApplicationMode[]{CAR, BICYCLE, PEDESTRIAN}; ApplicationMode[] exceptAirBoatDefault = new ApplicationMode[]{CAR, BICYCLE, PEDESTRIAN};
ApplicationMode[] pedestrian = new ApplicationMode[]{PEDESTRIAN}; ApplicationMode[] pedestrian = new ApplicationMode[]{PEDESTRIAN};
ApplicationMode[] pedestrianBicycle = new ApplicationMode[]{PEDESTRIAN, BICYCLE}; ApplicationMode[] pedestrianBicycle = new ApplicationMode[]{PEDESTRIAN, BICYCLE};
@ -100,13 +101,16 @@ public class ApplicationMode {
regWidgetVisibility("bgService", none); regWidgetVisibility("bgService", none);
} }
public static class ApplicationModeBuilder {
private static class ApplicationModeBuilder {
private ApplicationMode applicationMode; private ApplicationMode applicationMode;
public ApplicationMode reg() { public ApplicationMode reg() {
values.add(applicationMode);
defaultValues.add(applicationMode);
return applicationMode;
}
public ApplicationMode customReg() {
values.add(applicationMode); values.add(applicationMode);
return applicationMode; return applicationMode;
} }
@ -117,6 +121,22 @@ public class ApplicationMode {
return this; 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() { public ApplicationModeBuilder carLocation() {
applicationMode.bearingIconDay = R.drawable.map_car_bearing; applicationMode.bearingIconDay = R.drawable.map_car_bearing;
applicationMode.bearingIconNight = R.drawable.map_car_bearing_night; applicationMode.bearingIconNight = R.drawable.map_car_bearing_night;
@ -129,11 +149,6 @@ public class ApplicationMode {
return this; return this;
} }
public ApplicationModeBuilder parent(ApplicationMode parent) {
applicationMode.parent = parent;
return this;
}
public ApplicationModeBuilder bicycleLocation() { public ApplicationModeBuilder bicycleLocation() {
applicationMode.bearingIconDay = R.drawable.map_bicycle_bearing; applicationMode.bearingIconDay = R.drawable.map_bicycle_bearing;
applicationMode.bearingIconNight = R.drawable.map_bicycle_bearing_night; applicationMode.bearingIconNight = R.drawable.map_bicycle_bearing_night;
@ -183,6 +198,21 @@ public class ApplicationMode {
applicationMode.offRouteDistance = offRouteDistance; applicationMode.offRouteDistance = offRouteDistance;
return this; 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) { private static ApplicationModeBuilder create(int key, String stringKey) {
@ -191,6 +221,10 @@ public class ApplicationMode {
return builder; return builder;
} }
public static ApplicationModeBuilder createCustomMode(String userProfileTitle, String stringKey) {
return create(-1, stringKey).userProfileTitle(userProfileTitle);
}
private ApplicationMode(int key, String stringKey) { private ApplicationMode(int key, String stringKey) {
this.key = key; this.key = key;
this.stringKey = stringKey; this.stringKey = stringKey;
@ -229,9 +263,12 @@ public class ApplicationMode {
} }
public static List<ApplicationMode> allPossibleValues() { 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 // returns modifiable ! Set<ApplicationMode> to exclude non-wanted derived
public static Set<ApplicationMode> regWidgetVisibility(String widgetId, ApplicationMode... am) { public static Set<ApplicationMode> regWidgetVisibility(String widgetId, ApplicationMode... am) {
@ -363,11 +400,24 @@ public class ApplicationMode {
} }
public String toHumanString(Context ctx) { 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) { 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) { public static ApplicationMode valueOfStringKey(String key, ApplicationMode def) {
@ -399,24 +449,92 @@ public class ApplicationMode {
return this == mode || getParent() == mode; return this == mode || getParent() == mode;
} }
private final int key; public String getRoutingProfile() {
private final String stringKey; return routingProfile;
}
private ApplicationMode parent; public String getUserProfileName() {
private int mapIconId = R.drawable.map_world_globe_dark; return userProfileName;
private int smallIconDark = R.drawable.ic_world_globe_dark; }
private float defaultSpeed = 10f;
private int minDistanceForTurn = 50; @Expose private final int key;
private int arrivalDistance = 90; @Expose private final String stringKey;
private int offRouteDistance = 350; @Expose private String userProfileName;
private int bearingIconDay = R.drawable.map_pedestrian_bearing; @Expose private ApplicationMode parent;
private int bearingIconNight = R.drawable.map_pedestrian_bearing_night; @Expose private int mapIconId = R.drawable.map_world_globe_dark;
private int headingIconDay = R.drawable.map_pedestrian_location_view_angle; @Expose private int smallIconDark = R.drawable.ic_world_globe_dark;
private int headingIconNight = R.drawable.map_pedestrian_location_view_angle_night; @Expose private float defaultSpeed = 10f;
private int locationIconDay = R.drawable.map_pedestrian_location; @Expose private int minDistanceForTurn = 50;
private int locationIconNight = R.drawable.map_pedestrian_location_night; @Expose private int arrivalDistance = 90;
private int locationIconDayLost = R.drawable.map_pedestrian_location_lost; @Expose private int offRouteDistance = 350;
private int locationIconNightLost = R.drawable.map_pedestrian_location_lost_night; @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 StateChangedListener<String> listener;
private static OsmAndAppCustomization.OsmAndAppCustomizationListener customizationListener; 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;
}
} }

View file

@ -137,10 +137,10 @@ public class CurrentPositionHelper {
for (BinaryMapReaderResource rep : checkReaders) { for (BinaryMapReaderResource rep : checkReaders) {
rs[i++] = rep.getReader(BinaryMapReaderResourceType.STREET_LOOKUP); 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>()); new HashMap<String, String>());
ctx = new RoutePlannerFrontEnd().buildRoutingContext(cfg, null, rs); 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>()); new HashMap<String, String>());
defCtx = new RoutePlannerFrontEnd().buildRoutingContext(defCfg, null, rs); defCtx = new RoutePlannerFrontEnd().buildRoutingContext(defCfg, null, rs);
} else { } else {

View file

@ -64,6 +64,7 @@ import net.osmand.plus.search.QuickSearchHelper;
import net.osmand.plus.voice.CommandPlayer; import net.osmand.plus.voice.CommandPlayer;
import net.osmand.plus.wikivoyage.data.TravelDbHelper; import net.osmand.plus.wikivoyage.data.TravelDbHelper;
import net.osmand.router.RoutingConfiguration; import net.osmand.router.RoutingConfiguration;
import net.osmand.router.RoutingConfiguration.Builder;
import net.osmand.search.SearchUICore; import net.osmand.search.SearchUICore;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
@ -126,7 +127,7 @@ public class OsmandApplication extends MultiDexApplication {
InAppPurchaseHelper inAppPurchaseHelper; InAppPurchaseHelper inAppPurchaseHelper;
MapViewTrackingUtilities mapViewTrackingUtilities; MapViewTrackingUtilities mapViewTrackingUtilities;
RoutingConfiguration.Builder defaultRoutingConfig; private RoutingConfiguration.Builder routingConfig;
private Locale preferredLocale = null; private Locale preferredLocale = null;
private Locale defaultLocale; private Locale defaultLocale;
private File externalStorageDirectory; private File externalStorageDirectory;
@ -796,11 +797,18 @@ public class OsmandApplication extends MultiDexApplication {
return lang; return lang;
} }
public synchronized RoutingConfiguration.Builder getDefaultRoutingConfig() { public synchronized RoutingConfiguration.Builder getRoutingConfig() {
if(defaultRoutingConfig == null) { RoutingConfiguration.Builder rc;
defaultRoutingConfig = appInitializer.getLazyDefaultRoutingConfig(); if(routingConfig == null) {
rc = new RoutingConfiguration.Builder();
} else {
rc = routingConfig;
} }
return defaultRoutingConfig; return rc;
}
public void updateRoutingConfig(Builder update) {
routingConfig = update;
} }
public OsmandRegions getRegions() { public OsmandRegions getRegions() {

View file

@ -2745,6 +2745,9 @@ public class OsmandSettings {
RateUsBottomSheetDialog.RateUsState.INITIAL_STATE, RateUsBottomSheetDialog.RateUsState.values()) RateUsBottomSheetDialog.RateUsState.INITIAL_STATE, RateUsBottomSheetDialog.RateUsState.values())
.makeGlobal(); .makeGlobal();
public final CommonPreference<String> CUSTOM_APP_PROFILES =
new StringPreference("custom_profiles", "").makeGlobal().cache();
public enum DayNightMode { public enum DayNightMode {
AUTO(R.string.daynight_mode_auto, R.drawable.ic_action_map_sunst), AUTO(R.string.daynight_mode_auto, R.drawable.ic_action_map_sunst),

View file

@ -9,8 +9,11 @@ import android.support.v7.widget.Toolbar;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TextView;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings; import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
@ -56,6 +59,7 @@ public abstract class ActionBarPreferenceActivity extends AppCompatPreferenceAct
}); });
getSpinner().setVisibility(View.GONE); getSpinner().setVisibility(View.GONE);
getTypeButton().setVisibility(View.GONE);
setProgressVisibility(false); setProgressVisibility(false);
} }
@ -81,6 +85,25 @@ public abstract class ActionBarPreferenceActivity extends AppCompatPreferenceAct
return (Spinner) findViewById(R.id.spinner_nav); 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) { protected void setProgressVisibility(boolean visibility) {
if (visibility) { if (visibility) {
findViewById(R.id.ProgressBar).setVisibility(View.VISIBLE); findViewById(R.id.ProgressBar).setVisibility(View.VISIBLE);

View file

@ -14,6 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package net.osmand.plus.activities; package net.osmand.plus.activities;
import android.app.FragmentManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceActivity; import android.preference.PreferenceActivity;

View file

@ -82,6 +82,7 @@ import net.osmand.plus.base.FailSafeFuntions;
import net.osmand.plus.base.MapViewTrackingUtilities; import net.osmand.plus.base.MapViewTrackingUtilities;
import net.osmand.plus.chooseplan.OsmLiveCancelledDialog; import net.osmand.plus.chooseplan.OsmLiveCancelledDialog;
import net.osmand.plus.dashboard.DashboardOnMap; import net.osmand.plus.dashboard.DashboardOnMap;
import net.osmand.plus.dashboard.DashboardOnMap.DashboardType;
import net.osmand.plus.dialogs.ErrorBottomSheetDialog; import net.osmand.plus.dialogs.ErrorBottomSheetDialog;
import net.osmand.plus.dialogs.RateUsBottomSheetDialog; import net.osmand.plus.dialogs.RateUsBottomSheetDialog;
import net.osmand.plus.dialogs.WhatsNewDialogFragment; 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.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementToolFragment; import net.osmand.plus.measurementtool.MeasurementToolFragment;
import net.osmand.plus.measurementtool.NewGpxData; import net.osmand.plus.measurementtool.NewGpxData;
import net.osmand.plus.profiles.EditProfileFragment;
import net.osmand.plus.render.RendererRegistry; import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.resources.ResourceManager; import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.routepreparationmenu.ChooseRouteFragment; import net.osmand.plus.routepreparationmenu.ChooseRouteFragment;
@ -782,6 +784,19 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
} }
setIntent(null); 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); mapView.refreshMap(true);
if (atlasMapRendererView != null) { if (atlasMapRendererView != null) {

View file

@ -14,6 +14,7 @@ import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.Version; import net.osmand.plus.Version;
import net.osmand.plus.liveupdates.OsmLiveActivity; import net.osmand.plus.liveupdates.OsmLiveActivity;
import net.osmand.plus.profiles.SettingsProfileActivity;
public class SettingsActivity extends SettingsBaseActivity { public class SettingsActivity extends SettingsBaseActivity {
@ -28,6 +29,7 @@ public class SettingsActivity extends SettingsBaseActivity {
private Preference general; private Preference general;
private Preference routing; private Preference routing;
private Preference subscription; private Preference subscription;
private Preference profiles;
@Override @Override
@ -40,6 +42,8 @@ public class SettingsActivity extends SettingsBaseActivity {
general.setOnPreferenceClickListener(this); general.setOnPreferenceClickListener(this);
routing = (Preference) screen.findPreference("routing_settings"); routing = (Preference) screen.findPreference("routing_settings");
routing.setOnPreferenceClickListener(this); routing.setOnPreferenceClickListener(this);
profiles = (Preference) screen.findPreference("application_profiles");
profiles.setOnPreferenceClickListener(this);
subscription = (Preference) screen.findPreference("subscription_settings"); subscription = (Preference) screen.findPreference("subscription_settings");
subscription.setOnPreferenceClickListener(this); subscription.setOnPreferenceClickListener(this);
@ -88,6 +92,9 @@ public class SettingsActivity extends SettingsBaseActivity {
if (preference == general) { if (preference == general) {
startActivity(new Intent(this, SettingsGeneralActivity.class)); startActivity(new Intent(this, SettingsGeneralActivity.class));
return true; return true;
} else if (preference == profiles){
startActivity(new Intent(this, SettingsProfileActivity.class));
return true;
} else if (preference == routing) { } else if (preference == routing) {
startActivity(new Intent(this, SettingsNavigationActivity.class)); startActivity(new Intent(this, SettingsNavigationActivity.class));
return true; return true;

View file

@ -2,6 +2,7 @@ package net.osmand.plus.activities;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnMultiChoiceClickListener; import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
@ -13,12 +14,12 @@ import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceGroup; import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.support.v7.app.AlertDialog.Builder;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import net.osmand.plus.ApplicationMode; import net.osmand.plus.ApplicationMode;
@ -38,6 +39,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import net.osmand.util.Algorithms;
public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
@ -328,7 +330,6 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
settings = app.getSettings(); settings = app.getSettings();
getToolbar().setTitle(R.string.shared_string_settings); getToolbar().setTitle(R.string.shared_string_settings);
if (profileSettings) { if (profileSettings) {
modes.clear(); modes.clear();
for (ApplicationMode a : ApplicationMode.values(app)) { for (ApplicationMode a : ApplicationMode.values(app)) {
@ -336,52 +337,62 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
modes.add(a); 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 @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)); setPreferenceScreen(getPreferenceManager().createPreferenceScreen(this));
} }
void updateModeButton(ApplicationMode mode) {
class SpinnerAdapter extends ArrayAdapter<String>{ String title = Algorithms.isEmpty(mode.getUserProfileName())
? mode.toHumanString(SettingsBaseActivity.this)
: mode.getUserProfileName();
public SpinnerAdapter(Context context, int resource, List<String> objects) { String subtitle = mode.getParent() == null
super(context, resource, objects); ? "Mode: " + Algorithms.capitalizeFirstLetterAndLowercase(mode.getStringKey().replace("_", ""))
} : "User Mode, derived from: " + Algorithms
.capitalizeFirstLetterAndLowercase(mode.getParent().getStringKey());
@Override getModeTitleTV().setText(title);
public View getDropDownView(int position, View convertView, ViewGroup parent) { getModeSubTitleTV().setText(subtitle);
View view = super.getDropDownView(position, convertView, parent); getModeIconIV().setImageDrawable(getMyApplication().getUIUtilities().getIcon(mode.getSmallIconDark(),
if (!settings.isLightActionBar()){ getMyApplication().getSettings().isLightContent()
TextView textView = (TextView) view.findViewById(android.R.id.text1); ? R.color.active_buttons_and_links_light
textView.setBackgroundColor(getResources().getColor(R.color.actionbar_dark_color)); : R.color.active_buttons_and_links_dark));
} getDropDownArrow().setImageDrawable(getMyApplication().getUIUtilities().getIcon(R.drawable.ic_action_arrow_drop_down,
return view; getMyApplication().getSettings().isLightContent()
} ? R.color.active_buttons_and_links_light
} : R.color.active_buttons_and_links_dark));
settings.APPLICATION_MODE.set(mode);
updateAllSettings();
}
@Override @Override
protected void onResume() { protected void onResume() {
@ -431,7 +442,7 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
boolean found = false; boolean found = false;
for (ApplicationMode a : modes) { for (ApplicationMode a : modes) {
if (am == a) { if (am == a) {
getSpinner().setSelection(ind); updateModeButton(a);
found = true; found = true;
break; break;
} }

View file

@ -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.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.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.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(); OsmandApplication app = getMyApplication();
if (Version.isGooglePlayEnabled(getMyApplication()) && !Version.isPaidVersion(app)) { 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)); 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));

View file

@ -21,6 +21,7 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.TextView; import android.widget.TextView;
import net.osmand.PlatformUtil;
import net.osmand.plus.ApplicationMode; import net.osmand.plus.ApplicationMode;
import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem; import net.osmand.plus.ContextMenuItem;
@ -46,10 +47,10 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.commons.logging.Log;
public class SettingsNavigationActivity extends SettingsBaseActivity { public class SettingsNavigationActivity extends SettingsBaseActivity {
public static final String MORE_VALUE = "MORE_VALUE"; public static final String MORE_VALUE = "MORE_VALUE";
private Preference avoidRouting; private Preference avoidRouting;
@ -75,7 +76,6 @@ public class SettingsNavigationActivity extends SettingsBaseActivity {
((OsmandApplication) getApplication()).applyTheme(this); ((OsmandApplication) getApplication()).applyTheme(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
getToolbar().setTitle(R.string.routing_settings); getToolbar().setTitle(R.string.routing_settings);
createUI(); createUI();
} }
@ -84,7 +84,6 @@ public class SettingsNavigationActivity extends SettingsBaseActivity {
PreferenceScreen screen = getPreferenceScreen(); PreferenceScreen screen = getPreferenceScreen();
settings = getMyApplication().getSettings(); settings = getMyApplication().getSettings();
routerServicePreference = (ListPreference) screen.findPreference(settings.ROUTER_SERVICE.getId()); routerServicePreference = (ListPreference) screen.findPreference(settings.ROUTER_SERVICE.getId());
RouteService[] vls = RouteService.getAvailableRouters(getMyApplication()); RouteService[] vls = RouteService.getAvailableRouters(getMyApplication());
String[] entries = new String[vls.length]; String[] entries = new String[vls.length];
for(int i=0; i<entries.length; i++){ for(int i=0; i<entries.length; i++){
@ -245,7 +244,7 @@ public class SettingsNavigationActivity extends SettingsBaseActivity {
cat.addPreference(fastRoute); cat.addPreference(fastRoute);
} else { } else {
ApplicationMode am = settings.getApplicationMode(); ApplicationMode am = settings.getApplicationMode();
GeneralRouter router = getRouter(getMyApplication().getDefaultRoutingConfig(), am); GeneralRouter router = getRouter(getMyApplication().getRoutingConfig(), am);
clearParameters(); clearParameters();
if (router != null) { if (router != null) {
Map<String, RoutingParameter> parameters = router.getParameters(); 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) { 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) { if(router == null && am.getParent() != null) {
router = builder.getRouter(am.getParent().getStringKey()); router = builder.getRouter(am.getParent().getStringKey());
} }

View file

@ -14,6 +14,7 @@ import android.preference.PreferenceScreen;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.View; import android.view.View;
import net.osmand.PlatformUtil;
import net.osmand.StateChangedListener; import net.osmand.StateChangedListener;
import net.osmand.plus.ApplicationMode; import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmAndLocationSimulation; import net.osmand.plus.OsmAndLocationSimulation;
@ -22,6 +23,7 @@ import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.activities.SettingsBaseActivity; import net.osmand.plus.activities.SettingsBaseActivity;
import net.osmand.plus.activities.actions.AppModeDialog; import net.osmand.plus.activities.actions.AppModeDialog;
import net.osmand.plus.profiles.SettingsProfileFragment;
import net.osmand.util.SunriseSunset; import net.osmand.util.SunriseSunset;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -42,26 +44,9 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
PreferenceScreen cat = getPreferenceScreen(); PreferenceScreen cat = getPreferenceScreen();
Preference pref; Preference pref;
// 2 should be in main settings
cat.addPreference(createCheckBoxPreference(settings.USE_OPENGL_RENDER, cat.addPreference(createCheckBoxPreference(settings.USE_OPENGL_RENDER,
R.string.use_opengl_render,R.string.use_opengl_render_descr)); 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); PreferenceCategory navigation = new PreferenceCategory(this);
navigation.setTitle(R.string.routing_settings); navigation.setTitle(R.string.routing_settings);
cat.addPreference(navigation); cat.addPreference(navigation);
@ -225,30 +210,4 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
//pref.setEnabled(false); //pref.setEnabled(false);
info.addPreference(pref); 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();
}
} }

View file

@ -149,7 +149,7 @@ public class AvoidSpecificRoads {
app.getSettings().removeImpassableRoad(latLon); app.getSettings().removeImpassableRoad(latLon);
RouteDataObject obj = impassableRoads.remove(latLon); RouteDataObject obj = impassableRoads.remove(latLon);
if (obj != null) { if (obj != null) {
app.getDefaultRoutingConfig().removeImpassableRoad(obj); app.getRoutingConfig().removeImpassableRoad(obj);
} }
} }
@ -254,7 +254,7 @@ public class AvoidSpecificRoads {
final LatLon oldLoc = getLocation(currentObject); final LatLon oldLoc = getLocation(currentObject);
app.getSettings().moveImpassableRoad(oldLoc, newLoc); app.getSettings().moveImpassableRoad(oldLoc, newLoc);
impassableRoads.remove(oldLoc); impassableRoads.remove(oldLoc);
app.getDefaultRoutingConfig().removeImpassableRoad(currentObject); app.getRoutingConfig().removeImpassableRoad(currentObject);
addImpassableRoadInternal(object, ll, showDialog, activity, newLoc); addImpassableRoadInternal(object, ll, showDialog, activity, newLoc);
if (callback != null) { if (callback != null) {
@ -276,7 +276,7 @@ public class AvoidSpecificRoads {
boolean showDialog, boolean showDialog,
@Nullable MapActivity activity, @Nullable MapActivity activity,
@NonNull LatLon loc) { @NonNull LatLon loc) {
if (app.getDefaultRoutingConfig().addImpassableRoad(object, ll)) { if (app.getRoutingConfig().addImpassableRoad(object, ll)) {
impassableRoads.put(loc, object); impassableRoads.put(loc, object);
} else { } else {
LatLon location = getLocation(object); LatLon location = getLocation(object);
@ -305,7 +305,7 @@ public class AvoidSpecificRoads {
} }
public LatLon getLocation(RouteDataObject object) { 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()); return location == null ? null : new LatLon(location.getLatitude(), location.getLongitude());
} }

View 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);
}
}
}

View file

@ -0,0 +1,779 @@
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().getAllRoutes();
for (Entry<String, GeneralRouter> e : inputProfiles.entrySet()) {
int iconRes = R.drawable.ic_action_gdirections_dark;
String name = e.getValue().getProfileName();
String description;
if (e.getValue().getFilename() == null) {
iconRes = RoutingProfilesResources.valueOf(name.toUpperCase()).getIconRes();
name = context
.getString(RoutingProfilesResources.valueOf(name.toUpperCase()).getStringRes());
description = context.getString(R.string.osmand_default_routing);
} else {
description = e.getValue().getFilename();
}
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),
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 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();
}
}
}
}

View 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;
}
}

View 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);
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,239 @@
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));
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;
}
}
}

View file

@ -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();
}
}

View 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;
}
}
}

View file

@ -245,6 +245,11 @@ public class ResourceManager {
float tiles = (dm.widthPixels / 256 + 2) * (dm.heightPixels / 256 + 2) * 3; float tiles = (dm.widthPixels / 256 + 2) * (dm.heightPixels / 256 + 2) * 3;
log.info("Bitmap tiles to load in memory : " + tiles); log.info("Bitmap tiles to load in memory : " + tiles);
bitmapTilesCache.setMaxCacheSize((int) (tiles)); bitmapTilesCache.setMaxCacheSize((int) (tiles));
File path = context.getAppPath(IndexConstants.ROUTING_PROFILES_DIR);
if (!path.exists()) {
path.mkdir();
}
} }
public BitmapTilesCache getBitmapTilesCache() { public BitmapTilesCache getBitmapTilesCache() {

View file

@ -72,11 +72,7 @@ public class RoutingOptionsHelper {
addRouteMenuAppModes(ApplicationMode.PEDESTRIAN, PermanentAppModeOptions.PEDESTRIAN.routingParameters); addRouteMenuAppModes(ApplicationMode.PEDESTRIAN, PermanentAppModeOptions.PEDESTRIAN.routingParameters);
addRouteMenuAppModes(ApplicationMode.PUBLIC_TRANSPORT, PermanentAppModeOptions.PUBLIC_TRANSPORT.routingParameters); addRouteMenuAppModes(ApplicationMode.PUBLIC_TRANSPORT, PermanentAppModeOptions.PUBLIC_TRANSPORT.routingParameters);
addRouteMenuAppModes(ApplicationMode.BOAT, PermanentAppModeOptions.BOAT.routingParameters); addRouteMenuAppModes(ApplicationMode.BOAT, PermanentAppModeOptions.BOAT.routingParameters);
addRouteMenuAppModes(ApplicationMode.AIRCRAFT, PermanentAppModeOptions.AIRCAFT.routingParameters); addRouteMenuAppModes(ApplicationMode.AIRCRAFT, PermanentAppModeOptions.AIRCRAFT.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);
} }
private void addRouteMenuAppModes(ApplicationMode am, List<String> routingParameters) { private void addRouteMenuAppModes(ApplicationMode am, List<String> routingParameters) {
@ -382,7 +378,7 @@ public class RoutingOptionsHelper {
public LocalRoutingParameter getRoutingParameterInnerById(ApplicationMode am, String parameterId) { public LocalRoutingParameter getRoutingParameterInnerById(ApplicationMode am, String parameterId) {
RouteProvider.GPXRouteParamsBuilder rparams = app.getRoutingHelper().getCurrentGPXRoute(); 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()) { if (rm == null || (rparams != null && !rparams.isCalculateOsmAndRoute()) && !rparams.getFile().hasRtePt()) {
return null; return null;
} }
@ -407,7 +403,6 @@ public class RoutingOptionsHelper {
} }
return rpg; return rpg;
} }
return rp; return rp;
} }
@ -457,7 +452,7 @@ public class RoutingOptionsHelper {
public List<LocalRoutingParameter> getRoutingParametersInner(ApplicationMode am) { public List<LocalRoutingParameter> getRoutingParametersInner(ApplicationMode am) {
RouteProvider.GPXRouteParamsBuilder rparams = app.getRoutingHelper().getCurrentGPXRoute(); RouteProvider.GPXRouteParamsBuilder rparams = app.getRoutingHelper().getCurrentGPXRoute();
List<LocalRoutingParameter> list = new ArrayList<LocalRoutingParameter>(getGpxAndOsmandRouterParameters(am)); 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()) { if (rm == null || (rparams != null && !rparams.isCalculateOsmAndRoute()) && !rparams.getFile().hasRtePt()) {
return list; return list;
} }
@ -547,7 +542,7 @@ public class RoutingOptionsHelper {
public List<GeneralRouter.RoutingParameter> getAvoidRoutingPrefsForAppMode(ApplicationMode applicationMode) { public List<GeneralRouter.RoutingParameter> getAvoidRoutingPrefsForAppMode(ApplicationMode applicationMode) {
List<GeneralRouter.RoutingParameter> avoidParameters = new ArrayList<GeneralRouter.RoutingParameter>(); List<GeneralRouter.RoutingParameter> avoidParameters = new ArrayList<GeneralRouter.RoutingParameter>();
GeneralRouter router = getRouter(app.getDefaultRoutingConfig(), applicationMode); GeneralRouter router = getRouter(app.getRoutingConfig(), applicationMode);
if (router != null) { if (router != null) {
for (Map.Entry<String, GeneralRouter.RoutingParameter> e : router.getParameters().entrySet()) { for (Map.Entry<String, GeneralRouter.RoutingParameter> e : router.getParameters().entrySet()) {
String param = e.getKey(); String param = e.getKey();
@ -561,7 +556,7 @@ public class RoutingOptionsHelper {
} }
public GeneralRouter.RoutingParameter getRoutingPrefsForAppModeById(ApplicationMode applicationMode, String parameterId) { public GeneralRouter.RoutingParameter getRoutingPrefsForAppModeById(ApplicationMode applicationMode, String parameterId) {
GeneralRouter router = getRouter(app.getDefaultRoutingConfig(), applicationMode); GeneralRouter router = getRouter(app.getRoutingConfig(), applicationMode);
GeneralRouter.RoutingParameter parameter = null; GeneralRouter.RoutingParameter parameter = null;
if (router != null) { if (router != null) {
@ -971,11 +966,7 @@ public class RoutingOptionsHelper {
PEDESTRIAN(MuteSoundRoutingParameter.KEY, GeneralRouter.USE_HEIGHT_OBSTACLES), PEDESTRIAN(MuteSoundRoutingParameter.KEY, GeneralRouter.USE_HEIGHT_OBSTACLES),
PUBLIC_TRANSPORT(MuteSoundRoutingParameter.KEY, AvoidPTTypesRoutingParameter.KEY), PUBLIC_TRANSPORT(MuteSoundRoutingParameter.KEY, AvoidPTTypesRoutingParameter.KEY),
BOAT(MuteSoundRoutingParameter.KEY), BOAT(MuteSoundRoutingParameter.KEY),
AIRCAFT(MuteSoundRoutingParameter.KEY), AIRCRAFT(MuteSoundRoutingParameter.KEY);
HIKING(MuteSoundRoutingParameter.KEY),
MOTORCYCLE(MuteSoundRoutingParameter.KEY),
TRUCK(MuteSoundRoutingParameter.KEY),
TRAIN(MuteSoundRoutingParameter.KEY);
List<String> routingParameters; List<String> routingParameters;

View file

@ -595,7 +595,7 @@ public class RouteProvider {
OsmandSettings settings = params.ctx.getSettings(); OsmandSettings settings = params.ctx.getSettings();
router.setUseFastRecalculation(settings.USE_FAST_RECALCULATION.get()); 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); GeneralRouter generalRouter = SettingsNavigationActivity.getRouter(config, params.mode);
if(generalRouter == null) { if(generalRouter == null) {
return applicationModeNotSupported(params); return applicationModeNotSupported(params);
@ -680,19 +680,6 @@ public class RouteProvider {
private RoutingConfiguration initOsmAndRoutingConfig(Builder config, final RouteCalculationParams params, OsmandSettings settings, private RoutingConfiguration initOsmAndRoutingConfig(Builder config, final RouteCalculationParams params, OsmandSettings settings,
GeneralRouter generalRouter) throws IOException, FileNotFoundException { 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>(); Map<String, String> paramsR = new LinkedHashMap<String, String>();
for(Map.Entry<String, RoutingParameter> e : generalRouter.getParameters().entrySet()){ for(Map.Entry<String, RoutingParameter> e : generalRouter.getParameters().entrySet()){
String key = e.getKey(); String key = e.getKey();
@ -720,8 +707,7 @@ public class RouteProvider {
// make visible // make visible
int memoryLimit = (int) (0.95 * ((rt.maxMemory() - rt.totalMemory()) + rt.freeMemory()) / mb); 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); log.warn("Use " + memoryLimit + " MB Free " + rt.freeMemory() / mb + " of " + rt.totalMemory() / mb + " max " + rt.maxMemory() / mb);
RoutingConfiguration cf = config.build( params.mode.getRoutingProfile(), params.start.hasBearing() ?
RoutingConfiguration cf = config.build(p.name().toLowerCase(), params.start.hasBearing() ?
params.start.getBearing() / 180d * Math.PI : null, params.start.getBearing() / 180d * Math.PI : null,
memoryLimit, paramsR); memoryLimit, paramsR);
return cf; return cf;

View file

@ -443,11 +443,11 @@ public class TransportRoutingHelper {
} }
private List<TransportRouteResult> calculateRouteImpl(TransportRouteCalculationParams params) throws IOException, InterruptedException { 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(); BinaryMapIndexReader[] files = params.ctx.getResourceManager().getTransportRoutingMapFiles();
params.params.clear(); params.params.clear();
OsmandSettings settings = params.ctx.getSettings(); 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(); String key = e.getKey();
GeneralRouter.RoutingParameter pr = e.getValue(); GeneralRouter.RoutingParameter pr = e.getValue();
String vl; String vl;

View file

@ -66,7 +66,7 @@ Functionality
* Add POIs and directly upload them to OSM (or later if offline) * 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) * 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: #### Approximate map coverage and quality: