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 SETTINGS_DIR = "settings/"; //$NON-NLS-1$
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 heightObstacles;
private boolean allowPrivate;
private String filename = null;
private String profileName = "";
private Map<RouteRegion, Map<Integer, Integer>> regionConvert = new LinkedHashMap<RouteRegion, Map<Integer,Integer>>();
@ -119,7 +121,23 @@ public class GeneralRouter implements VehicleRouter {
ruleToValue = new ArrayList<Object>();
parameters = new LinkedHashMap<String, GeneralRouter.RoutingParameter>();
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getProfileName() {
return profileName;
}
public void setProfileName(String profileName) {
this.profileName = profileName;
}
public GeneralRouter(GeneralRouter parent, Map<String, String> params) {
this.profile = parent.profile;
this.attributes = new LinkedHashMap<String, String>();

View file

@ -19,7 +19,7 @@ import java.util.Map;
import java.util.Stack;
public class RoutingConfiguration {
public static final int DEFAULT_MEMORY_LIMIT = 30;
public final float DEVIATION_RADIUS = 3000;
public Map<String, String> attributes = new LinkedHashMap<String, String>();
@ -46,14 +46,13 @@ public class RoutingConfiguration {
// 1.5 Recalculate distance help
public float recalculateDistance = 20000f;
public static class Builder {
// Design time storage
private String defaultRouter = "";
private Map<String, GeneralRouter> routers = new LinkedHashMap<String, GeneralRouter>();
private Map<String, String> attributes = new LinkedHashMap<String, String>();
private HashMap<Long, Location> impassableRoadLocations = new HashMap<Long, Location>();
private Map<String, GeneralRouter> routers = new LinkedHashMap<>();
private Map<String, String> attributes = new LinkedHashMap<>();
private HashMap<Long, Location> impassableRoadLocations = new HashMap<>();
// Example
// {
@ -125,12 +124,16 @@ public class RoutingConfiguration {
public String getDefaultRouter() {
return defaultRouter;
}
public GeneralRouter getRouter(String applicationMode) {
return routers.get(applicationMode);
public GeneralRouter getRouter(String routingProfileName) {
return routers.get(routingProfileName);
}
public Map<String, GeneralRouter> getAllRoutes() {
return routers;
}
public void removeImpassableRoad(RouteDataObject obj) {
impassableRoadLocations.remove(obj.id);
}
@ -164,10 +167,13 @@ public class RoutingConfiguration {
}
return DEFAULT;
}
public static RoutingConfiguration.Builder parseFromInputStream(InputStream is) throws IOException, XmlPullParserException {
static RoutingConfiguration.Builder parseFromInputStream(InputStream is) throws IOException, XmlPullParserException {
return parseFromInputStream(is, null, new RoutingConfiguration.Builder());
}
public static RoutingConfiguration.Builder parseFromInputStream(InputStream is, String filename, RoutingConfiguration.Builder config) throws IOException, XmlPullParserException {
XmlPullParser parser = PlatformUtil.newXMLPullParser();
final RoutingConfiguration.Builder config = new RoutingConfiguration.Builder();
GeneralRouter currentRouter = null;
RouteDataObjectAttribute currentAttribute = null;
String preType = null;
@ -180,7 +186,7 @@ public class RoutingConfiguration {
if ("osmand_routing_config".equals(name)) {
config.defaultRouter = parser.getAttributeValue("", "defaultProfile");
} else if ("routingProfile".equals(name)) {
currentRouter = parseRoutingProfile(parser, config);
currentRouter = parseRoutingProfile(parser, config, filename);
} else if ("attribute".equals(name)) {
parseAttribute(parser, config, currentRouter);
} else if ("parameter".equals(name)) {
@ -295,10 +301,8 @@ public class RoutingConfiguration {
}
}
private static GeneralRouter parseRoutingProfile(XmlPullParser parser, final RoutingConfiguration.Builder config) {
String currentSelectedRouter = parser.getAttributeValue("", "name");
private static GeneralRouter parseRoutingProfile(XmlPullParser parser, final RoutingConfiguration.Builder config, String filename) {
String currentSelectedRouterName = parser.getAttributeValue("", "name");
Map<String, String> attrs = new LinkedHashMap<String, String>();
for(int i=0; i< parser.getAttributeCount(); i++) {
attrs.put(parser.getAttributeName(i), parser.getAttributeValue(i));
@ -306,7 +310,13 @@ public class RoutingConfiguration {
GeneralRouterProfile c = Algorithms.parseEnumValue(GeneralRouterProfile.values(),
parser.getAttributeValue("", "baseProfile"), GeneralRouterProfile.CAR);
GeneralRouter currentRouter = new GeneralRouter(c, attrs);
config.routers.put(currentSelectedRouter, currentRouter);
currentRouter.setProfileName(currentSelectedRouterName);
if (filename != null) {
currentRouter.setFilename(filename);
currentSelectedRouterName = filename + "/" + currentSelectedRouterName;
}
config.routers.put(currentSelectedRouterName, currentRouter);
return currentRouter;
}
@ -315,7 +325,7 @@ public class RoutingConfiguration {
currentRouter.addAttribute(parser.getAttributeValue("", "name"),
parser.getAttributeValue("", "value"));
} else {
config.attributes.put(parser.getAttributeValue("", "name"),
config.attributes.put(parser.getAttributeValue("", "name"),
parser.getAttributeValue("", "value"));
}
}

View file

@ -891,5 +891,15 @@
</activity>
<receiver android:name="net.osmand.plus.liveupdates.LiveUpdatesAlarmReceiver"/>
<activity
android:configChanges="keyboardHidden|orientation"
android:label="Application profiles"
android:name=".profiles.SettingsProfileActivity"/>
<activity
android:name=".profiles.EditProfileActivity"
android:label="Application profiles"/>
</application>
</manifest>

View file

@ -10,7 +10,7 @@
<solid android:color="@color/map_widget_light" />
<corners
android:topRightRadius="@dimen/map_button_rect_rad"
android:bottomRightRadius="@dimen/map_button_rect_rad"
android:bottomRightRadius="@dimen/map_button_rect_rad"
/>
<stroke android:color="@color/map_widget_stroke" android:width="@dimen/map_button_stroke"/>
</shape></item>

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>
<LinearLayout
android:id="@+id/type_selection_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="?attr/selectableItemBackground"
android:clickable="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="64dp"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding_small"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding_small"
android:orientation="horizontal">
<ImageView
android:id="@+id/mode_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/bottom_sheet_icon_margin"
android:layout_marginRight="@dimen/bottom_sheet_icon_margin"
android:layout_gravity="center_vertical"
android:tint="?attr/primary_icon_color"
tools:src="@drawable/ic_action_coordinates_latitude"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/mode_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.ListItemTitle"
android:textColor="?attr/main_font_color_basic"
tools:text="Item Title"/>
<TextView
android:id="@+id/mode_subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
tools:text="Item additional desription"/>
</LinearLayout>
<ImageView
android:id="@+id/type_down_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_action_arrow_drop_down"/>
</LinearLayout>
<ImageView
android:id="@+id/bottom_shadow2"
android:layout_width="match_parent"
android:layout_height="5dp"
android:scaleType="fitXY"
android:src="@drawable/bg_shadow_list_bottom"/>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >

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_dark">#17191a</color>
<color name="text_field_box_dark">#3F474B</color>
<color name="text_field_box_light">#eeeeee</color>
<!-- Basic colors -->
<color name="app_bar_main_dark">#101112</color>
<color name="app_bar_main_light">#ff8800</color>
@ -477,5 +480,8 @@
<color name="inactive_buttons_and_links_dark">#505050</color>
<color name="active_buttons_and_links_trans_light">#66237bff</color>
<color name="active_buttons_and_links_trans_dark">#66d28521</color>
<color name="settings_divider">#dcdcdc</color>
<color name="profile_button_gray">#EFEFEF</color>
<color name="profile_button_gray_pressed">#ababab</color>
</resources>

View file

@ -244,6 +244,7 @@
<dimen name="bottom_sheet_title_height">52dp</dimen>
<dimen name="bottom_sheet_descr_height">44dp</dimen>
<dimen name="bottom_sheet_list_item_height">48dp</dimen>
<dimen name="bottom_sheet_large_list_item_height">64dp</dimen>
<dimen name="bottom_sheet_icon_margin">24dp</dimen>
<dimen name="bottom_sheet_divider_margin_top">7dp</dimen>
<dimen name="bottom_sheet_divider_margin_bottom">8dp</dimen>
@ -340,4 +341,9 @@
<dimen name="pages_item_padding">3dp</dimen>
<dimen name="pages_item_margin">4dp</dimen>
<dimen name="setting_profile_item_height">64dp</dimen>
<dimen name="setting_profile_image_margin">20dp</dimen>
<dimen name="setting_profile_item_switch_margin">18dp</dimen>
</resources>

View file

@ -11,6 +11,37 @@
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="coordinates_widget">Coordinates widget</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_type">Transport type</string>
<string name="send_log">Send log</string>
<string name="routing_attr_avoid_tram_name">Avoid trams</string>
<string name="routing_attr_avoid_tram_description">Avoid trams</string>
<string name="routing_attr_avoid_bus_name">Avoid buses</string>
@ -3118,5 +3150,6 @@
<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_description">Avoid cobblestone and sett</string>
<string name="select_icon_profile_dialog_title">Select icon</string>
</resources>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference android:key="general_settings" android:title="@string/general_settings_2" android:summary="@string/general_settings_descr"/>
<Preference android:key="application_profiles" android:title="@string/application_profiles" android:summary="@string/application_profiles_descr"/>
<Preference android:key="routing_settings" android:title="@string/routing_settings_2" android:summary="@string/routing_settings_descr"/>
<Preference android:key="subscription_settings" android:title="@string/osm_live_subscription" android:summary="@string/osm_live_subscription_desc"/>
<PreferenceCategory android:key="plugin_settings" android:title="@string/plugin_settings" />

View file

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

View file

@ -2,6 +2,14 @@ package net.osmand.plus;
import android.content.Context;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.LinkedHashSet;
import net.osmand.PlatformUtil;
import net.osmand.StateChangedListener;
import java.util.ArrayList;
@ -12,53 +20,46 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import net.osmand.plus.routing.RouteProvider.RouteService;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
public class ApplicationMode {
private static final Log LOG = PlatformUtil.getLog(ApplicationMode.class);
private static Map<String, Set<ApplicationMode>> widgetsVisibilityMap = new LinkedHashMap<>();
private static Map<String, Set<ApplicationMode>> widgetsAvailabilityMap = new LinkedHashMap<>();
private static List<ApplicationMode> defaultValues = new ArrayList<>();
private static List<ApplicationMode> values = new ArrayList<>();
private static List<ApplicationMode> cachedFilteredValues = new ArrayList<>();
/*
* DEFAULT("Browse map"), CAR("Car"), BICYCLE("Bicycle"), PEDESTRIAN("Pedestrian"); NAUTICAL("boat")
* DEFAULT("Browse map"), CAR("Car"), BICYCLE("Bicycle"), PEDESTRIAN("Pedestrian"); NAUTICAL("boat"); PUBLIC_TRANSPORT("Public transport"); AIRCRAFT("Aircraft")
*/
public static final ApplicationMode DEFAULT = create(R.string.app_mode_default, "default").speed(1.5f, 5).arrivalDistance(90).defLocation().
icon(R.drawable.map_world_globe_dark, R.drawable.ic_world_globe_dark).reg();
public static final ApplicationMode CAR = create(R.string.app_mode_car, "car").speed(15.3f, 35).carLocation().
icon(R.drawable.map_action_car_dark, R.drawable.ic_action_car_dark).reg();
icon(R.drawable.map_action_car_dark, R.drawable.ic_action_car_dark).setRoutingProfile("car").reg();
public static final ApplicationMode BICYCLE = create(R.string.app_mode_bicycle, "bicycle").speed(5.5f, 15).arrivalDistance(60).offRouteDistance(50).bicycleLocation().
icon(R.drawable.map_action_bicycle_dark, R.drawable.ic_action_bicycle_dark).reg();
icon(R.drawable.map_action_bicycle_dark, R.drawable.ic_action_bicycle_dark).setRoutingProfile("bicycle").reg();
public static final ApplicationMode PEDESTRIAN = create(R.string.app_mode_pedestrian, "pedestrian").speed(1.5f, 5).arrivalDistance(45).offRouteDistance(20).
icon(R.drawable.map_action_pedestrian_dark, R.drawable.ic_action_pedestrian_dark).reg();
icon(R.drawable.map_action_pedestrian_dark, R.drawable.ic_action_pedestrian_dark).setRoutingProfile("pedestrian").reg();
public static final ApplicationMode PUBLIC_TRANSPORT = create(R.string.app_mode_public_transport, "public_transport").
icon(R.drawable.map_action_bus_dark, R.drawable.ic_action_bus_dark).reg();
icon(R.drawable.map_action_bus_dark, R.drawable.ic_action_bus_dark).setRoutingProfile("public_transport").reg();
public static final ApplicationMode BOAT = create(R.string.app_mode_boat, "boat").speed(5.5f, 20).carLocation().nauticalLocation().
icon(R.drawable.map_action_sail_boat_dark, R.drawable.ic_action_sail_boat_dark).reg();
public static final ApplicationMode BOAT = create(R.string.app_mode_boat, "boat").speed(5.5f, 20).nauticalLocation().
icon(R.drawable.map_action_sail_boat_dark, R.drawable.ic_action_sail_boat_dark).setRoutingProfile("boat").reg();
public static final ApplicationMode AIRCRAFT = create(R.string.app_mode_aircraft, "aircraft").speed(40f, 100).carLocation().
icon(R.drawable.map_action_aircraft, R.drawable.ic_action_aircraft).reg();
public static final ApplicationMode HIKING = create(R.string.app_mode_hiking, "hiking").speed(1.5f, 5).parent(PEDESTRIAN).
icon(R.drawable.map_action_trekking_dark, R.drawable.ic_action_trekking_dark).reg();
public static final ApplicationMode MOTORCYCLE = create(R.string.app_mode_motorcycle, "motorcycle").speed(15.3f, 40).
carLocation().parent(CAR).
icon(R.drawable.map_action_motorcycle_dark, R.drawable.ic_action_motorcycle_dark).reg();
public static final ApplicationMode TRUCK = create(R.string.app_mode_truck, "truck").speed(15.3f, 40).
carLocation().parent(CAR).
icon(R.drawable.map_action_truck_dark, R.drawable.ic_action_truck_dark).reg();
public static final ApplicationMode TRAIN = create(R.string.app_mode_train, "train").speed(25f, 40).
carLocation().icon(R.drawable.map_action_train, R.drawable.ic_action_train).reg();
icon(R.drawable.map_action_aircraft, R.drawable.ic_action_aircraft).setRouteService(RouteService.STRAIGHT).setRoutingProfile("STRAIGHT_LINE_MODE").reg();
static {
ApplicationMode[] exceptDefault = new ApplicationMode[]{CAR, PEDESTRIAN, BICYCLE, BOAT, AIRCRAFT, PUBLIC_TRANSPORT, TRAIN};
ApplicationMode[] exceptPedestrianAndDefault = new ApplicationMode[]{CAR, BICYCLE, BOAT, AIRCRAFT, PUBLIC_TRANSPORT, TRAIN};
ApplicationMode[] exceptDefault = new ApplicationMode[]{CAR, PEDESTRIAN, BICYCLE, BOAT, AIRCRAFT, PUBLIC_TRANSPORT, };
ApplicationMode[] exceptPedestrianAndDefault = new ApplicationMode[]{CAR, BICYCLE, BOAT, AIRCRAFT, PUBLIC_TRANSPORT};
ApplicationMode[] exceptAirBoatDefault = new ApplicationMode[]{CAR, BICYCLE, PEDESTRIAN};
ApplicationMode[] pedestrian = new ApplicationMode[]{PEDESTRIAN};
ApplicationMode[] pedestrianBicycle = new ApplicationMode[]{PEDESTRIAN, BICYCLE};
@ -100,13 +101,16 @@ public class ApplicationMode {
regWidgetVisibility("bgService", none);
}
private static class ApplicationModeBuilder {
public static class ApplicationModeBuilder {
private ApplicationMode applicationMode;
public ApplicationMode reg() {
values.add(applicationMode);
defaultValues.add(applicationMode);
return applicationMode;
}
public ApplicationMode customReg() {
values.add(applicationMode);
return applicationMode;
}
@ -117,6 +121,22 @@ public class ApplicationMode {
return this;
}
public ApplicationModeBuilder parent(ApplicationMode parent) {
applicationMode.parent = parent;
String parentTypeName = parent.getStringKey();
if (parentTypeName.equals("car") || parentTypeName.equals("aircraft")) {
this.carLocation();
} else if (parentTypeName.equals("bicycle")) {
this.bicycleLocation();
} else if (parentTypeName.equals("boat")) {
this.nauticalLocation();
} else {
this.defLocation();
}
return this;
}
public ApplicationModeBuilder carLocation() {
applicationMode.bearingIconDay = R.drawable.map_car_bearing;
applicationMode.bearingIconNight = R.drawable.map_car_bearing_night;
@ -129,11 +149,6 @@ public class ApplicationMode {
return this;
}
public ApplicationModeBuilder parent(ApplicationMode parent) {
applicationMode.parent = parent;
return this;
}
public ApplicationModeBuilder bicycleLocation() {
applicationMode.bearingIconDay = R.drawable.map_bicycle_bearing;
applicationMode.bearingIconNight = R.drawable.map_bicycle_bearing_night;
@ -183,6 +198,21 @@ public class ApplicationMode {
applicationMode.offRouteDistance = offRouteDistance;
return this;
}
public ApplicationModeBuilder userProfileTitle(String userProfileTitle) {
applicationMode.userProfileName = userProfileTitle;
return this;
}
public ApplicationModeBuilder setRoutingProfile(String routingProfileName) {
applicationMode.routingProfile = routingProfileName;
return this;
}
public ApplicationModeBuilder setRouteService(RouteService service) {
applicationMode.routeService = service;
return this;
}
}
private static ApplicationModeBuilder create(int key, String stringKey) {
@ -191,6 +221,10 @@ public class ApplicationMode {
return builder;
}
public static ApplicationModeBuilder createCustomMode(String userProfileTitle, String stringKey) {
return create(-1, stringKey).userProfileTitle(userProfileTitle);
}
private ApplicationMode(int key, String stringKey) {
this.key = key;
this.stringKey = stringKey;
@ -229,9 +263,12 @@ public class ApplicationMode {
}
public static List<ApplicationMode> allPossibleValues() {
return new ArrayList<ApplicationMode>(values);
return new ArrayList<>(values);
}
public static List<ApplicationMode> getDefaultValues() {
return new ArrayList<>(defaultValues);
}
// returns modifiable ! Set<ApplicationMode> to exclude non-wanted derived
public static Set<ApplicationMode> regWidgetVisibility(String widgetId, ApplicationMode... am) {
@ -363,11 +400,24 @@ public class ApplicationMode {
}
public String toHumanString(Context ctx) {
return ctx.getString(key);
if (Algorithms.isEmpty(userProfileName) && key != -1) {
return ctx.getString(key);
} else {
return userProfileName;
}
}
public String toHumanStringCtx(Context ctx) {
return ctx.getString(key);
if (Algorithms.isEmpty(userProfileName)) {
return ctx.getString(key);
} else {
return userProfileName;
}
}
public RouteService getRouteService() {
return routeService;
}
public static ApplicationMode valueOfStringKey(String key, ApplicationMode def) {
@ -399,24 +449,92 @@ public class ApplicationMode {
return this == mode || getParent() == mode;
}
private final int key;
private final String stringKey;
public String getRoutingProfile() {
return routingProfile;
}
private ApplicationMode parent;
private int mapIconId = R.drawable.map_world_globe_dark;
private int smallIconDark = R.drawable.ic_world_globe_dark;
private float defaultSpeed = 10f;
private int minDistanceForTurn = 50;
private int arrivalDistance = 90;
private int offRouteDistance = 350;
private int bearingIconDay = R.drawable.map_pedestrian_bearing;
private int bearingIconNight = R.drawable.map_pedestrian_bearing_night;
private int headingIconDay = R.drawable.map_pedestrian_location_view_angle;
private int headingIconNight = R.drawable.map_pedestrian_location_view_angle_night;
private int locationIconDay = R.drawable.map_pedestrian_location;
private int locationIconNight = R.drawable.map_pedestrian_location_night;
private int locationIconDayLost = R.drawable.map_pedestrian_location_lost;
private int locationIconNightLost = R.drawable.map_pedestrian_location_lost_night;
public String getUserProfileName() {
return userProfileName;
}
@Expose private final int key;
@Expose private final String stringKey;
@Expose private String userProfileName;
@Expose private ApplicationMode parent;
@Expose private int mapIconId = R.drawable.map_world_globe_dark;
@Expose private int smallIconDark = R.drawable.ic_world_globe_dark;
@Expose private float defaultSpeed = 10f;
@Expose private int minDistanceForTurn = 50;
@Expose private int arrivalDistance = 90;
@Expose private int offRouteDistance = 350;
@Expose private int bearingIconDay = R.drawable.map_pedestrian_bearing;
@Expose private int bearingIconNight = R.drawable.map_pedestrian_bearing_night;
@Expose private int headingIconDay = R.drawable.map_pedestrian_location_view_angle;
@Expose private int headingIconNight = R.drawable.map_pedestrian_location_view_angle_night;
@Expose private int locationIconDay = R.drawable.map_pedestrian_location;
@Expose private int locationIconNight = R.drawable.map_pedestrian_location_night;
@Expose private int locationIconDayLost = R.drawable.map_pedestrian_location_lost;
@Expose private int locationIconNightLost = R.drawable.map_pedestrian_location_lost_night;
@Expose private String routingProfile = null;
@Expose private RouteService routeService = RouteService.OSMAND;
private static StateChangedListener<String> listener;
private static OsmAndAppCustomization.OsmAndAppCustomizationListener customizationListener;
public static void saveCustomModeToSettings(OsmandSettings settings){
List<ApplicationMode> customModes = new ArrayList<>();
for (ApplicationMode mode : values) {
if (mode.parent != null) {
customModes.add(mode);
}
}
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String profiles = gson.toJson(customModes);
settings.CUSTOM_APP_PROFILES.set(profiles);
}
public static void initCustomModes(OsmandSettings settings){
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Type t = new TypeToken<ArrayList<ApplicationMode>>() {}.getType();
List<ApplicationMode> customProfiles = gson.fromJson(settings.CUSTOM_APP_PROFILES.get(), t);
if (!Algorithms.isEmpty(customProfiles)) {
for (ApplicationMode m : customProfiles) {
if (!values.contains(m)) {
values.add(m);
}
}
}
}
public static void deleteCustomMode(String userModeTitle, OsmandApplication app) {
Iterator<ApplicationMode> it = values.iterator();
while (it.hasNext()) {
ApplicationMode m = it.next();
if (m.userProfileName != null && m.userProfileName.equals(userModeTitle)) {
it.remove();
}
}
ApplicationMode.saveCustomModeToSettings(app.getSettings());
}
public static boolean changeProfileStatus(ApplicationMode mode, boolean isSelected, OsmandApplication app) {
Set<ApplicationMode> selectedModes = new LinkedHashSet<>(ApplicationMode.values(app));
StringBuilder vls = new StringBuilder(ApplicationMode.DEFAULT.getStringKey() + ",");
if (allPossibleValues().contains(mode)) {
if (isSelected) {
selectedModes.add(mode);
} else {
selectedModes.remove(mode);
if (app.getSettings().APPLICATION_MODE.get() == mode) {
app.getSettings().APPLICATION_MODE.set(ApplicationMode.DEFAULT);
}
}
for (ApplicationMode m : selectedModes) {
vls.append(m.getStringKey()).append(",");
}
app.getSettings().AVAILABLE_APP_MODES.set(vls.toString());
return true;
}
return false;
}
}

View file

@ -137,10 +137,10 @@ public class CurrentPositionHelper {
for (BinaryMapReaderResource rep : checkReaders) {
rs[i++] = rep.getReader(BinaryMapReaderResourceType.STREET_LOOKUP);
}
RoutingConfiguration cfg = app.getDefaultRoutingConfig().build(p, 10,
RoutingConfiguration cfg = app.getRoutingConfig().build(p, 10,
new HashMap<String, String>());
ctx = new RoutePlannerFrontEnd().buildRoutingContext(cfg, null, rs);
RoutingConfiguration defCfg = app.getDefaultRoutingConfig().build("geocoding", 10,
RoutingConfiguration defCfg = app.getRoutingConfig().build("geocoding", 10,
new HashMap<String, String>());
defCtx = new RoutePlannerFrontEnd().buildRoutingContext(defCfg, null, rs);
} else {

View file

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

View file

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

View file

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

View file

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

View file

@ -82,6 +82,7 @@ import net.osmand.plus.base.FailSafeFuntions;
import net.osmand.plus.base.MapViewTrackingUtilities;
import net.osmand.plus.chooseplan.OsmLiveCancelledDialog;
import net.osmand.plus.dashboard.DashboardOnMap;
import net.osmand.plus.dashboard.DashboardOnMap.DashboardType;
import net.osmand.plus.dialogs.ErrorBottomSheetDialog;
import net.osmand.plus.dialogs.RateUsBottomSheetDialog;
import net.osmand.plus.dialogs.WhatsNewDialogFragment;
@ -107,6 +108,7 @@ import net.osmand.plus.mapmarkers.PlanRouteFragment;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementToolFragment;
import net.osmand.plus.measurementtool.NewGpxData;
import net.osmand.plus.profiles.EditProfileFragment;
import net.osmand.plus.render.RendererRegistry;
import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.routepreparationmenu.ChooseRouteFragment;
@ -782,6 +784,19 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
}
setIntent(null);
}
if (intent.hasExtra(EditProfileFragment.OPEN_CONFIG_ON_MAP)) {
switch (intent.getStringExtra(EditProfileFragment.OPEN_CONFIG_ON_MAP)) {
case EditProfileFragment.MAP_CONFIG:
this.getDashboard().setDashboardVisibility(true, DashboardType.CONFIGURE_MAP, null);
break;
case EditProfileFragment.SCREEN_CONFIG:
this.getDashboard().setDashboardVisibility(true, DashboardType.CONFIGURE_SCREEN, null);
break;
}
setIntent(null);
}
}
mapView.refreshMap(true);
if (atlasMapRendererView != null) {

View file

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

View file

@ -2,6 +2,7 @@ package net.osmand.plus.activities;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
@ -13,12 +14,12 @@ import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AlertDialog.Builder;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;
import net.osmand.plus.ApplicationMode;
@ -38,6 +39,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.osmand.util.Algorithms;
public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
@ -48,7 +50,7 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
protected OsmandSettings settings;
protected final boolean profileSettings;
protected List<ApplicationMode> modes = new ArrayList<ApplicationMode>();
private ApplicationMode previousAppMode;
private ApplicationMode previousAppMode;
private Map<String, Preference> screenPreferences = new LinkedHashMap<String, Preference>();
private Map<String, OsmandPreference<Boolean>> booleanPreferences = new LinkedHashMap<String, OsmandPreference<Boolean>>();
@ -328,7 +330,6 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
settings = app.getSettings();
getToolbar().setTitle(R.string.shared_string_settings);
if (profileSettings) {
modes.clear();
for (ApplicationMode a : ApplicationMode.values(app)) {
@ -336,52 +337,62 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
modes.add(a);
}
}
List<String> s = new ArrayList<String>();
for (ApplicationMode a : modes) {
s.add(a.toHumanString(app));
}
SpinnerAdapter spinnerAdapter = new SpinnerAdapter(this,
R.layout.spinner_item, s);
// android.R.layout.simple_spinner_dropdown_item
spinnerAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
getSpinner().setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
settings.APPLICATION_MODE.set(modes.get(position));
updateAllSettings();
}
getTypeButton().setVisibility(View.VISIBLE);
getTypeButton().setOnClickListener(new View.OnClickListener() {
@Override
public void onNothingSelected(AdapterView<?> parent) {
public void onClick(View v) {
AlertDialog.Builder singleSelectDialogBuilder = new Builder(SettingsBaseActivity.this);
singleSelectDialogBuilder.setTitle("Select App Profile");
final ArrayAdapter<String> modeNames = new ArrayAdapter<>(
SettingsBaseActivity.this, android.R.layout.select_dialog_singlechoice);
for (ApplicationMode am : modes) {
modeNames.add(am.toHumanString(SettingsBaseActivity.this));
}
singleSelectDialogBuilder.setNegativeButton(R.string.shared_string_cancel,
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
singleSelectDialogBuilder.setAdapter(modeNames, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
settings.APPLICATION_MODE.set(modes.get(which));
updateModeButton(modes.get(which));
updateAllSettings();
}
});
singleSelectDialogBuilder.show();
}
});
getSpinner().setAdapter(spinnerAdapter);
getSpinner().setVisibility(View.VISIBLE);
}
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(this));
}
class SpinnerAdapter extends ArrayAdapter<String>{
public SpinnerAdapter(Context context, int resource, List<String> objects) {
super(context, resource, objects);
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
View view = super.getDropDownView(position, convertView, parent);
if (!settings.isLightActionBar()){
TextView textView = (TextView) view.findViewById(android.R.id.text1);
textView.setBackgroundColor(getResources().getColor(R.color.actionbar_dark_color));
}
return view;
}
}
void updateModeButton(ApplicationMode mode) {
String title = Algorithms.isEmpty(mode.getUserProfileName())
? mode.toHumanString(SettingsBaseActivity.this)
: mode.getUserProfileName();
String subtitle = mode.getParent() == null
? "Mode: " + Algorithms.capitalizeFirstLetterAndLowercase(mode.getStringKey().replace("_", ""))
: "User Mode, derived from: " + Algorithms
.capitalizeFirstLetterAndLowercase(mode.getParent().getStringKey());
getModeTitleTV().setText(title);
getModeSubTitleTV().setText(subtitle);
getModeIconIV().setImageDrawable(getMyApplication().getUIUtilities().getIcon(mode.getSmallIconDark(),
getMyApplication().getSettings().isLightContent()
? R.color.active_buttons_and_links_light
: R.color.active_buttons_and_links_dark));
getDropDownArrow().setImageDrawable(getMyApplication().getUIUtilities().getIcon(R.drawable.ic_action_arrow_drop_down,
getMyApplication().getSettings().isLightContent()
? R.color.active_buttons_and_links_light
: R.color.active_buttons_and_links_dark));
settings.APPLICATION_MODE.set(mode);
updateAllSettings();
}
@Override
protected void onResume() {
@ -431,7 +442,7 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
boolean found = false;
for (ApplicationMode a : modes) {
if (am == a) {
getSpinner().setSelection(ind);
updateModeButton(a);
found = true;
break;
}
@ -541,7 +552,7 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity
}
public void showBooleanSettings(String[] vals, final OsmandPreference<Boolean>[] prefs) {
AlertDialog.Builder bld = new AlertDialog.Builder(this);

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.MAP_EMPTY_STATE_ALLOWED, R.string.tap_on_map_to_hide_interface, R.string.tap_on_map_to_hide_interface_descr));
misc.addPreference(createCheckBoxPreference(settings.DO_NOT_SHOW_STARTUP_MESSAGES, R.string.do_not_show_startup_messages, R.string.do_not_show_startup_messages_desc));
misc.addPreference(createCheckBoxPreference(settings.ANIMATE_MY_LOCATION,R.string.animate_my_location, R.string.animate_my_location_desc));
OsmandApplication app = getMyApplication();
if (Version.isGooglePlayEnabled(getMyApplication()) && !Version.isPaidVersion(app)) {
misc.addPreference(createCheckBoxPreference(settings.DO_NOT_SEND_ANONYMOUS_APP_USAGE, R.string.do_not_send_anonymous_app_usage, R.string.do_not_send_anonymous_app_usage_desc));

View file

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

View file

@ -14,6 +14,7 @@ import android.preference.PreferenceScreen;
import android.support.v7.app.AlertDialog;
import android.view.View;
import net.osmand.PlatformUtil;
import net.osmand.StateChangedListener;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmAndLocationSimulation;
@ -22,6 +23,7 @@ import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.SettingsBaseActivity;
import net.osmand.plus.activities.actions.AppModeDialog;
import net.osmand.plus.profiles.SettingsProfileFragment;
import net.osmand.util.SunriseSunset;
import java.text.SimpleDateFormat;
@ -42,26 +44,9 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
PreferenceScreen cat = getPreferenceScreen();
Preference pref;
// 2 should be in main settings
cat.addPreference(createCheckBoxPreference(settings.USE_OPENGL_RENDER,
R.string.use_opengl_render,R.string.use_opengl_render_descr));
cat.addPreference(createCheckBoxPreference(settings.ANIMATE_MY_LOCATION,
R.string.animate_my_location, R.string.animate_my_location_desc));
pref = new Preference(this);
pref.setTitle(R.string.app_modes_choose);
pref.setSummary(R.string.app_modes_choose_descr);
pref.setKey("available_application_modes");
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
availableProfileDialog();
return true;
}
});
cat.addPreference(pref);
PreferenceCategory navigation = new PreferenceCategory(this);
navigation.setTitle(R.string.routing_settings);
cat.addPreference(navigation);
@ -225,30 +210,4 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
//pref.setEnabled(false);
info.addPreference(pref);
}
protected void availableProfileDialog() {
AlertDialog.Builder b = new AlertDialog.Builder(this);
final List<ApplicationMode> modes = ApplicationMode.allPossibleValues();
modes.remove(ApplicationMode.DEFAULT);
final Set<ApplicationMode> selected = new LinkedHashSet<ApplicationMode>(ApplicationMode.values(getMyApplication()));
selected.remove(ApplicationMode.DEFAULT);
View v = AppModeDialog.prepareAppModeView(this, modes, selected, null, false, true, false,
new View.OnClickListener() {
@Override
public void onClick(View v) {
StringBuilder vls = new StringBuilder(ApplicationMode.DEFAULT.getStringKey()+",");
for(ApplicationMode mode : modes) {
if(selected.contains(mode)) {
vls.append(mode.getStringKey()).append(",");
}
}
settings.AVAILABLE_APP_MODES.set(vls.toString());
}
});
b.setTitle(R.string.profile_settings);
b.setPositiveButton(R.string.shared_string_ok, null);
b.setView(v);
b.show();
}
}

View file

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

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;
log.info("Bitmap tiles to load in memory : " + tiles);
bitmapTilesCache.setMaxCacheSize((int) (tiles));
File path = context.getAppPath(IndexConstants.ROUTING_PROFILES_DIR);
if (!path.exists()) {
path.mkdir();
}
}
public BitmapTilesCache getBitmapTilesCache() {

View file

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

View file

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

View file

@ -443,11 +443,11 @@ public class TransportRoutingHelper {
}
private List<TransportRouteResult> calculateRouteImpl(TransportRouteCalculationParams params) throws IOException, InterruptedException {
RoutingConfiguration.Builder config = params.ctx.getDefaultRoutingConfig();
RoutingConfiguration.Builder config = params.ctx.getRoutingConfig();
BinaryMapIndexReader[] files = params.ctx.getResourceManager().getTransportRoutingMapFiles();
params.params.clear();
OsmandSettings settings = params.ctx.getSettings();
for(Map.Entry<String, GeneralRouter.RoutingParameter> e : config.getRouter(params.mode.getStringKey()).getParameters().entrySet()){
for(Map.Entry<String, GeneralRouter.RoutingParameter> e : config.getRouter(params.mode.getRoutingProfile()).getParameters().entrySet()){
String key = e.getKey();
GeneralRouter.RoutingParameter pr = e.getValue();
String vl;

View file

@ -66,7 +66,7 @@ Functionality
* Add POIs and directly upload them to OSM (or later if offline)
* Optional trip recording also in background mode (while device is in sleep mode)
OsmAnd is open source and actively being developed. Everyone can contribute to the application by reporting bugs, [improving translations](https://hosted.weblate.org/projects/osmand/), or coding new features. The project is in a lively state of continuous improvement by all these forms of developer and user interaction. The project progress also relies on financial contributions to fund the development, coding, and testing of new functionality. By buying OsmAnd+ and subscribing to OsmAnd Live you help the application to be even more awesome! It is also possible to make a general donation, see http://osmand.net/help-online#buy_app.
OsmAnd is open source and actively being developed. Everyone can contribute to the application by reporting bugs, [improving translations](https://hosted.weblate.org/projects/osmand/), or coding new features. The project is in a lively selected of continuous improvement by all these forms of developer and user interaction. The project progress also relies on financial contributions to fund the development, coding, and testing of new functionality. By buying OsmAnd+ and subscribing to OsmAnd Live you help the application to be even more awesome! It is also possible to make a general donation, see http://osmand.net/help-online#buy_app.
#### Approximate map coverage and quality: