From 1786bd235f04d949bd92d32723321819173c0abf Mon Sep 17 00:00:00 2001 From: Chumva Date: Thu, 28 Mar 2019 16:44:01 +0200 Subject: [PATCH 1/3] Fix start of route recalculation after settings change and refactor updateOptionsButtons --- .../MapRouteInfoMenu.java | 672 ++++++++++-------- .../ShowAlongTheRouteBottomSheet.java | 12 + .../cards/RouteStatisticCard.java | 5 +- .../cards/WarningCard.java | 2 +- 4 files changed, 383 insertions(+), 308 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java index 7cfe5031f1..f464006ca9 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java @@ -1,5 +1,6 @@ package net.osmand.plus.routepreparationmenu; +import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; import android.graphics.PointF; @@ -59,9 +60,12 @@ import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.WaypointHelper; import net.osmand.plus.mapmarkers.MapMarkerSelectionFragment; import net.osmand.plus.poi.PoiUIFilter; +import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidPTTypesRoutingParameter; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidRoadsRoutingParameter; +import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.LocalRoutingParameter; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.LocalRoutingParameterGroup; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.MuteSoundRoutingParameter; +import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.RouteMenuAppModes; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.ShowAlongTheRouteItem; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener; @@ -803,57 +807,10 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener } final OsmandApplication app = mapActivity.getMyApplication(); RoutingHelper routingHelper = app.getRoutingHelper(); - final boolean nightMode = app.getDaynightHelper().isNightModeForMapControls(); - final OsmandSettings settings = app.getSettings(); - final int colorActive = ContextCompat.getColor(app, nightMode ? R.color.active_buttons_and_links_dark : R.color.active_buttons_and_links_light); - final int colorDisabled = ContextCompat.getColor(app, R.color.description_font_and_bottom_sheet_icons); final ApplicationMode applicationMode = routingHelper.getAppMode(); - final RoutingOptionsHelper.RouteMenuAppModes mode = app.getRoutingOptionsHelper().modes.get(applicationMode); - int margin = AndroidUtils.dpToPx(app, 3); - - View startButton = mainView.findViewById(R.id.start_button); - TextViewExProgress startButtonText = (TextViewExProgress) mainView.findViewById(R.id.start_button_descr); - boolean publicTransportMode = routingHelper.getAppMode() == ApplicationMode.PUBLIC_TRANSPORT; - int iconId = publicTransportMode ? R.drawable.ic_map : R.drawable.ic_action_start_navigation; - int color; - if (isRouteCalculated()) { - AndroidUtils.setBackground(app, startButton, nightMode, R.color.active_buttons_and_links_light, R.color.active_buttons_and_links_dark); - color = nightMode ? R.color.main_font_dark : R.color.card_and_list_background_light; - } else { - AndroidUtils.setBackground(app, startButton, nightMode, R.color.activity_background_light, R.color.activity_background_dark); - color = R.color.description_font_and_bottom_sheet_icons; - } - startButtonText.color2 = ContextCompat.getColor(app, color); - startButtonText.setCompoundDrawablesWithIntrinsicBounds(app.getUIUtilities().getIcon(iconId, color), null, null, null); - if (publicTransportMode) { - startButtonText.setText(R.string.shared_string_show_on_map); - } else if (routingHelper.isFollowingMode() || routingHelper.isPauseNavigation()) { - startButtonText.setText(R.string.shared_string_continue); - } else { - startButtonText.setText(R.string.shared_string_control_start); - } - startButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - clickRouteGo(); - } - }); - - View cancelButton = mainView.findViewById(R.id.cancel_button); - TextView cancelButtonText = (TextView) mainView.findViewById(R.id.cancel_button_descr); - if (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated() || isTransportRouteCalculated()) { - cancelButtonText.setText(R.string.shared_string_dismiss); - } else { - cancelButtonText.setText(R.string.shared_string_cancel); - } - AndroidUtils.setBackground(app, cancelButton, nightMode, R.color.card_and_list_background_light, R.color.card_and_list_background_dark); - cancelButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - clickRouteCancel(); - } - }); + final RouteMenuAppModes mode = app.getRoutingOptionsHelper().modes.get(applicationMode); + updateControlButtons(mapActivity, mainView); LinearLayout optionsButton = (LinearLayout) mainView.findViewById(R.id.map_options_route_button); TextView optionsTitle = (TextView) mainView.findViewById(R.id.map_options_route_button_title); ImageView optionsIcon = (ImageView) mainView.findViewById(R.id.map_options_route_button_icon); @@ -880,271 +837,378 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener if (mode == null) { return; } - - LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); - LinearLayout.LayoutParams newLp = new LinearLayout.LayoutParams(AndroidUtils.dpToPx(app, 100), ViewGroup.LayoutParams.MATCH_PARENT); - - lp.setMargins(margin, 0, margin, 0); - + createRoutingParametersButtons(mapActivity, mode, optionsContainer); + int rightPadding = AndroidUtils.dpToPx(app, 70); if (mode.parameters.size() > 2) { optionsTitle.setVisibility(View.GONE); } else { optionsTitle.setVisibility(View.VISIBLE); - } - - for (final RoutingOptionsHelper.LocalRoutingParameter parameter : mode.parameters) { - if (parameter instanceof MuteSoundRoutingParameter) { - String text = null; - final boolean active = !app.getRoutingHelper().getVoiceRouter().isMute(); - if (mode.parameters.size() <= 2) { - text = app.getString(active ? R.string.shared_string_on : R.string.shared_string_off); - } - View item = createToolbarOptionView(active, text, parameter.getActiveIconId(), parameter.getDisabledIconId(), new OnClickListener() { - @Override - public void onClick(View v) { - OsmandApplication app = getApp(); - if (app != null) { - app.getRoutingOptionsHelper().switchSound(); - boolean active = !app.getRoutingHelper().getVoiceRouter().isMute(); - String text = app.getString(active ? R.string.shared_string_on : R.string.shared_string_off); - - Drawable itemDrawable = app.getUIUtilities().getIcon(active ? parameter.getActiveIconId() : parameter.getDisabledIconId(), nightMode ? R.color.route_info_control_icon_color_dark : R.color.route_info_control_icon_color_light); - Drawable activeItemDrawable = app.getUIUtilities().getIcon(active ? parameter.getActiveIconId() : parameter.getDisabledIconId(), nightMode ? R.color.active_buttons_and_links_dark : R.color.active_buttons_and_links_light); - - if (Build.VERSION.SDK_INT >= 21) { - itemDrawable = AndroidUtils.createPressedStateListDrawable(itemDrawable, activeItemDrawable); - } - - ((ImageView) v.findViewById(R.id.route_option_image_view)).setImageDrawable(active ? activeItemDrawable : itemDrawable); - ((TextView) v.findViewById(R.id.route_option_title)).setText(text); - ((TextView) v.findViewById(R.id.route_option_title)).setTextColor(active ? colorActive : colorDisabled); - } - } - }); - if (item != null) { - optionsContainer.addView(item, lp); - } - } else if (parameter instanceof ShowAlongTheRouteItem) { - final Set poiFilters = app.getPoiFilters().getSelectedPoiFilters(); - final boolean traffic = app.getSettings().SHOW_TRAFFIC_WARNINGS.getModeValue(applicationMode); - final boolean fav = app.getSettings().SHOW_NEARBY_FAVORITES.getModeValue(applicationMode); - if (!poiFilters.isEmpty()) { - LinearLayout item = createToolbarOptionView(false, null, -1, -1, null); - if (item != null) { - item.findViewById(R.id.route_option_container).setVisibility(View.GONE); - Iterator it = poiFilters.iterator(); - while (it.hasNext()) { - final PoiUIFilter poiUIFilter = it.next(); - final View container = createToolbarSubOptionView(true, poiUIFilter.getName(), R.drawable.ic_action_remove_dark, !it.hasNext(), new OnClickListener() { - @Override - public void onClick(View v) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - mapActivity.getMyApplication().getPoiFilters().removeSelectedPoiFilter(poiUIFilter); - mapActivity.getMapView().refreshMap(); - updateOptionsButtons(); - } - } - }); - if (container != null) { - item.addView(container, newLp); - } - } - optionsContainer.addView(item, lp); - } - } - if (traffic) { - LinearLayout item = createToolbarOptionView(false, null, -1, -1, null); - if (item != null) { - item.findViewById(R.id.route_option_container).setVisibility(View.GONE); - final View container = createToolbarSubOptionView(true, app.getString(R.string.way_alarms), R.drawable.ic_action_remove_dark, true, new OnClickListener() { - @Override - public void onClick(View v) { - OsmandApplication app = getApp(); - if (app != null) { - app.getWaypointHelper().enableWaypointType(WaypointHelper.ALARMS, false); - updateOptionsButtons(); - } - } - }); - if (container != null) { - AndroidUtils.setBackground(app, container, nightMode, R.drawable.btn_border_light, R.drawable.btn_border_dark); - item.addView(container, newLp); - optionsContainer.addView(item, lp); - } - } - } - if (fav) { - LinearLayout item = createToolbarOptionView(false, null, -1, -1, null); - if (item != null) { - item.findViewById(R.id.route_option_container).setVisibility(View.GONE); - final View container = createToolbarSubOptionView(true, app.getString(R.string.favourites), R.drawable.ic_action_remove_dark, true, new OnClickListener() { - @Override - public void onClick(View v) { - OsmandApplication app = getApp(); - if (app != null) { - app.getWaypointHelper().enableWaypointType(WaypointHelper.FAVORITES, false); - updateOptionsButtons(); - } - } - }); - if (container != null) { - AndroidUtils.setBackground(app, container, nightMode, R.drawable.btn_border_light, R.drawable.btn_border_dark); - item.addView(container, newLp); - optionsContainer.addView(item, lp); - } - } - } - - } else if (parameter instanceof AvoidRoadsRoutingParameter || parameter instanceof RoutingOptionsHelper.AvoidPTTypesRoutingParameter) { - final LinearLayout item = createToolbarOptionView(false, null, -1, -1, null); - if (item != null) { - - item.findViewById(R.id.route_option_container).setVisibility(View.GONE); - Map impassableRoads = new TreeMap<>(); - if (parameter instanceof AvoidRoadsRoutingParameter) { - impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads(); - } - Iterator it = impassableRoads.values().iterator(); - while (it.hasNext()) { - final RouteDataObject routeDataObject = it.next(); - final View container = createToolbarSubOptionView(false, app.getAvoidSpecificRoads().getText(routeDataObject), R.drawable.ic_action_remove_dark, !it.hasNext(), new OnClickListener() { - @Override - public void onClick(View v) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - OsmandApplication app = mapActivity.getMyApplication(); - RoutingHelper routingHelper = app.getRoutingHelper(); - if (routeDataObject != null) { - app.getAvoidSpecificRoads().removeImpassableRoad(routeDataObject); - } - if (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated()) { - routingHelper.recalculateRouteDueToSettingsChange(); - } - if (app.getAvoidSpecificRoads().getImpassableRoads().isEmpty()) { - mode.parameters.remove(parameter); - } - mapActivity.getMapView().refreshMap(); - if (mode.parameters.size() > 2) { - item.removeView(v); - } else { - updateOptionsButtons(); - } - } - } - }); - if (container != null) { - item.addView(container, newLp); - } - } - - List avoidParameters = app.getRoutingOptionsHelper().getAvoidRoutingPrefsForAppMode(applicationMode); - final List avoidedParameters = new ArrayList<>(); - for (int i = 0; i < avoidParameters.size(); i++) { - RoutingParameter p = avoidParameters.get(i); - CommonPreference preference = settings.getCustomRoutingBooleanProperty(p.getId(), p.getDefaultBoolean()); - if (preference != null && preference.getModeValue(app.getRoutingHelper().getAppMode())) { - avoidedParameters.add(p); - } - } - for (int i = 0; i < avoidedParameters.size(); i++) { - final RoutingParameter routingParameter = avoidedParameters.get(i); - final View container = createToolbarSubOptionView(false, SettingsBaseActivity.getRoutingStringPropertyName(app, routingParameter.getId(), routingParameter.getName()), R.drawable.ic_action_remove_dark, i == avoidedParameters.size() - 1, new OnClickListener() { - @Override - public void onClick(View v) { - CommonPreference preference = settings.getCustomRoutingBooleanProperty(routingParameter.getId(), routingParameter.getDefaultBoolean()); - preference.setModeValue(app.getRoutingHelper().getAppMode(), false); - avoidedParameters.remove(routingParameter); - if (avoidedParameters.isEmpty()) { - mode.parameters.remove(parameter); - } - if (mode.parameters.size() > 2) { - item.removeView(v); - } else { - updateOptionsButtons(); - } - } - }); - if (container != null) { - item.addView(container, newLp); - } - } - if(avoidedParameters.size() > 0 || impassableRoads.size() > 0) { - optionsContainer.addView(item, lp); - } - } - } else if (parameter instanceof LocalRoutingParameterGroup) { - final LocalRoutingParameterGroup group = (LocalRoutingParameterGroup) parameter; - String text = null; - RoutingOptionsHelper.LocalRoutingParameter selected = group.getSelected(settings); - if (selected != null) { - text = group.getText(mapActivity); - } - View item = createToolbarOptionView(false, text, parameter.getActiveIconId(), parameter.getDisabledIconId(), new OnClickListener() { - @Override - public void onClick(View v) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - mapActivity.getMyApplication().getRoutingOptionsHelper().showLocalRoutingParameterGroupDialog(group, mapActivity, new RoutingOptionsHelper.OnClickListener() { - @Override - public void onClick() { - updateOptionsButtons(); - } - }); - } - } - }); - if (item != null) { - optionsContainer.addView(item, lp); - } - } else { - String text; - boolean active; - if (parameter.routingParameter != null) { - if (parameter.routingParameter.getId().equals(GeneralRouter.USE_SHORTEST_WAY)) { - // if short route settings - it should be inverse of fast_route_mode - active = !settings.FAST_ROUTE_MODE.getModeValue(routingHelper.getAppMode()); - } else { - active = parameter.isSelected(settings); - } - text = parameter.getText(mapActivity); - View item = createToolbarOptionView(active, text, parameter.getActiveIconId(), parameter.getDisabledIconId(), new OnClickListener() { - @Override - public void onClick(View v) { - OsmandApplication app = getApp(); - if (parameter.routingParameter != null && app != null) { - boolean selected = !parameter.isSelected(settings); - app.getRoutingOptionsHelper().applyRoutingParameter(parameter, selected); - - Drawable itemDrawable = app.getUIUtilities().getIcon(selected ? parameter.getActiveIconId() : parameter.getDisabledIconId(), nightMode ? R.color.route_info_control_icon_color_dark : R.color.route_info_control_icon_color_light); - Drawable activeItemDrawable = app.getUIUtilities().getIcon(selected ? parameter.getActiveIconId() : parameter.getDisabledIconId(), nightMode ? R.color.active_buttons_and_links_dark : R.color.active_buttons_and_links_light); - - if (Build.VERSION.SDK_INT >= 21) { - itemDrawable = AndroidUtils.createPressedStateListDrawable(itemDrawable, activeItemDrawable); - } - ((ImageView) v.findViewById(R.id.route_option_image_view)).setImageDrawable(selected ? activeItemDrawable : itemDrawable); - ((TextView) v.findViewById(R.id.route_option_title)).setTextColor(selected ? colorActive : colorDisabled); - } - } - }); - if (item != null) { - LinearLayout.LayoutParams newLp2 = new LinearLayout.LayoutParams(AndroidUtils.dpToPx(app, 100), ViewGroup.LayoutParams.MATCH_PARENT); - newLp2.setMargins(margin, 0, margin, 0); - optionsContainer.addView(item, newLp2); - } - } - } - } - int rightPadding = AndroidUtils.dpToPx(app, 70); - if (optionsTitle.getVisibility() == View.VISIBLE) { rightPadding += AndroidUtils.getTextWidth(app.getResources().getDimensionPixelSize(R.dimen.text_button_text_size), app.getString(R.string.shared_string_options)); } optionsContainer.setPadding(optionsContainer.getPaddingLeft(), optionsContainer.getPaddingTop(), rightPadding, optionsContainer.getPaddingBottom()); } + private void updateControlButtons(MapActivity mapActivity, View mainView) { + if (mapActivity == null || mainView == null) { + return; + } + final OsmandApplication app = mapActivity.getMyApplication(); + final RoutingHelper helper = app.getRoutingHelper(); + View startButton = mainView.findViewById(R.id.start_button); + TextViewExProgress startButtonText = (TextViewExProgress) mainView.findViewById(R.id.start_button_descr); + boolean publicTransportMode = helper.getAppMode() == ApplicationMode.PUBLIC_TRANSPORT; + int iconId = publicTransportMode ? R.drawable.ic_map : R.drawable.ic_action_start_navigation; + int color; + if (isRouteCalculated()) { + AndroidUtils.setBackground(app, startButton, nightMode, R.color.active_buttons_and_links_light, R.color.active_buttons_and_links_dark); + color = nightMode ? R.color.main_font_dark : R.color.card_and_list_background_light; + } else { + AndroidUtils.setBackground(app, startButton, nightMode, R.color.activity_background_light, R.color.activity_background_dark); + color = R.color.description_font_and_bottom_sheet_icons; + } + startButtonText.color2 = ContextCompat.getColor(app, color); + startButtonText.setCompoundDrawablesWithIntrinsicBounds(app.getUIUtilities().getIcon(iconId, color), null, null, null); + if (publicTransportMode) { + startButtonText.setText(R.string.shared_string_show_on_map); + } else if (helper.isFollowingMode() || helper.isPauseNavigation()) { + startButtonText.setText(R.string.shared_string_continue); + } else { + startButtonText.setText(R.string.shared_string_control_start); + } + startButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + clickRouteGo(); + } + }); + View cancelButton = mainView.findViewById(R.id.cancel_button); + TextView cancelButtonText = (TextView) mainView.findViewById(R.id.cancel_button_descr); + if (helper.isRouteCalculated() || helper.isRouteBeingCalculated() || isTransportRouteCalculated()) { + cancelButtonText.setText(R.string.shared_string_dismiss); + } else { + cancelButtonText.setText(R.string.shared_string_cancel); + } + AndroidUtils.setBackground(app, cancelButton, nightMode, R.color.card_and_list_background_light, R.color.card_and_list_background_dark); + cancelButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + clickRouteCancel(); + } + }); + } + + private void createRoutingParametersButtons(MapActivity mapActivity, final RouteMenuAppModes mode, LinearLayout optionsContainer) { + if (mapActivity == null || optionsContainer == null) { + return; + } + for (final LocalRoutingParameter parameter : mode.parameters) { + if (parameter instanceof MuteSoundRoutingParameter) { + createMuteSoundRoutingParameterButton(mapActivity, (MuteSoundRoutingParameter) parameter, mode, optionsContainer); + } else if (parameter instanceof ShowAlongTheRouteItem) { + createShowAlongTheRouteItems(mapActivity, optionsContainer); + } else if (parameter instanceof AvoidRoadsRoutingParameter || parameter instanceof AvoidPTTypesRoutingParameter) { + createAvoidRoadsRoutingParameterButton(mapActivity, parameter, mode, optionsContainer); + } else if (parameter instanceof LocalRoutingParameterGroup) { + createLocalRoutingParameterGroupButton(mapActivity, parameter, optionsContainer); + } else { + createSimpleRoutingParameterButton(mapActivity, parameter, optionsContainer); + } + } + } + + private void createMuteSoundRoutingParameterButton(MapActivity mapActivity, final MuteSoundRoutingParameter parameter, final RouteMenuAppModes mode, LinearLayout optionsContainer) { + final int colorActive = ContextCompat.getColor(mapActivity, nightMode ? R.color.active_buttons_and_links_dark : R.color.active_buttons_and_links_light); + final int colorDisabled = ContextCompat.getColor(mapActivity, R.color.description_font_and_bottom_sheet_icons); + String text = null; + final boolean active = !mapActivity.getRoutingHelper().getVoiceRouter().isMute(); + if (mode.parameters.size() <= 2) { + text = mapActivity.getString(active ? R.string.shared_string_on : R.string.shared_string_off); + } + View item = createToolbarOptionView(active, text, parameter.getActiveIconId(), parameter.getDisabledIconId(), new OnClickListener() { + @Override + public void onClick(View v) { + OsmandApplication app = getApp(); + if (app != null) { + app.getRoutingOptionsHelper().switchSound(); + boolean active = !app.getRoutingHelper().getVoiceRouter().isMute(); + String text = app.getString(active ? R.string.shared_string_on : R.string.shared_string_off); + + Drawable itemDrawable = app.getUIUtilities().getIcon(active ? parameter.getActiveIconId() : parameter.getDisabledIconId(), nightMode ? R.color.route_info_control_icon_color_dark : R.color.route_info_control_icon_color_light); + Drawable activeItemDrawable = app.getUIUtilities().getIcon(active ? parameter.getActiveIconId() : parameter.getDisabledIconId(), nightMode ? R.color.active_buttons_and_links_dark : R.color.active_buttons_and_links_light); + + if (Build.VERSION.SDK_INT >= 21) { + itemDrawable = AndroidUtils.createPressedStateListDrawable(itemDrawable, activeItemDrawable); + } + ((ImageView) v.findViewById(R.id.route_option_image_view)).setImageDrawable(active ? activeItemDrawable : itemDrawable); + ((TextView) v.findViewById(R.id.route_option_title)).setText(text); + ((TextView) v.findViewById(R.id.route_option_title)).setTextColor(active ? colorActive : colorDisabled); + } + } + }); + if (item != null) { + optionsContainer.addView(item, getContainerButtonLayoutParams(mapActivity, true)); + } + } + + private void createShowAlongTheRouteItems(MapActivity mapActivity, LinearLayout optionsContainer) { + OsmandApplication app = mapActivity.getMyApplication(); + final ApplicationMode applicationMode = app.getRoutingHelper().getAppMode(); + final Set poiFilters = app.getPoiFilters().getSelectedPoiFilters(); + final boolean traffic = app.getSettings().SHOW_TRAFFIC_WARNINGS.getModeValue(applicationMode); + final boolean fav = app.getSettings().SHOW_NEARBY_FAVORITES.getModeValue(applicationMode); + if (!poiFilters.isEmpty()) { + createPoiFiltersItems(mapActivity, poiFilters, optionsContainer); + } + if (traffic) { + createWaypointItem(mapActivity, optionsContainer, WaypointHelper.ALARMS); + } + if (fav) { + createWaypointItem(mapActivity, optionsContainer, WaypointHelper.FAVORITES); + } + } + + private void createPoiFiltersItems(MapActivity mapActivity, Set poiFilters, LinearLayout optionsContainer) { + LinearLayout item = createToolbarOptionView(false, null, -1, -1, null); + if (item != null) { + item.findViewById(R.id.route_option_container).setVisibility(View.GONE); + Iterator it = poiFilters.iterator(); + while (it.hasNext()) { + final PoiUIFilter poiUIFilter = it.next(); + final View container = createToolbarSubOptionView(true, poiUIFilter.getName(), R.drawable.ic_action_remove_dark, !it.hasNext(), new OnClickListener() { + @Override + public void onClick(View v) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.getMyApplication().getPoiFilters().removeSelectedPoiFilter(poiUIFilter); + mapActivity.getMapView().refreshMap(); + updateOptionsButtons(); + } + } + }); + if (container != null) { + item.addView(container, getContainerButtonLayoutParams(mapActivity, false)); + } + } + optionsContainer.addView(item, getContainerButtonLayoutParams(mapActivity, true)); + } + } + + private void createWaypointItem(MapActivity mapActivity, LinearLayout optionsContainer, final int waypointType) { + LinearLayout item = createToolbarOptionView(false, null, -1, -1, null); + if (item != null) { + item.findViewById(R.id.route_option_container).setVisibility(View.GONE); + String title = ""; + if (waypointType == WaypointHelper.ALARMS) { + title = mapActivity.getString(R.string.way_alarms); + } else if (waypointType == WaypointHelper.FAVORITES) { + title = mapActivity.getString(R.string.favourites); + } + final View container = createToolbarSubOptionView(true, title, R.drawable.ic_action_remove_dark, true, new OnClickListener() { + @Override + public void onClick(View v) { + OsmandApplication app = getApp(); + if (app != null) { + app.getWaypointHelper().enableWaypointType(waypointType, false); + updateOptionsButtons(); + } + } + }); + if (container != null) { + AndroidUtils.setBackground(app, container, nightMode, R.drawable.btn_border_light, R.drawable.btn_border_dark); + item.addView(container, getContainerButtonLayoutParams(mapActivity, false)); + optionsContainer.addView(item, getContainerButtonLayoutParams(mapActivity, true)); + } + } + } + + private void createAvoidRoadsRoutingParameterButton(MapActivity mapActivity, final LocalRoutingParameter parameter, final RouteMenuAppModes mode, LinearLayout optionsContainer) { + OsmandApplication app = mapActivity.getMyApplication(); + final LinearLayout item = createToolbarOptionView(false, null, -1, -1, null); + if (item != null) { + item.findViewById(R.id.route_option_container).setVisibility(View.GONE); + Map impassableRoads = new TreeMap<>(); + if (parameter instanceof AvoidRoadsRoutingParameter) { + impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads(); + } + + final List avoidedParameters = getAvoidedParameters(app); + createImpassableRoadsItems(mapActivity, impassableRoads, parameter, mode, item); + createAvoidParametersItems(mapActivity, avoidedParameters, parameter, mode, item); + if (avoidedParameters.size() > 0 || impassableRoads.size() > 0) { + optionsContainer.addView(item, getContainerButtonLayoutParams(mapActivity, true)); + } + } + } + + private List getAvoidedParameters(OsmandApplication app) { + final ApplicationMode applicationMode = app.getRoutingHelper().getAppMode(); + List avoidParameters = app.getRoutingOptionsHelper().getAvoidRoutingPrefsForAppMode(applicationMode); + final List avoidedParameters = new ArrayList<>(); + for (int i = 0; i < avoidParameters.size(); i++) { + RoutingParameter p = avoidParameters.get(i); + CommonPreference preference = app.getSettings().getCustomRoutingBooleanProperty(p.getId(), p.getDefaultBoolean()); + if (preference != null && preference.getModeValue(app.getRoutingHelper().getAppMode())) { + avoidedParameters.add(p); + } + } + return avoidedParameters; + } + + private void createImpassableRoadsItems(MapActivity mapActivity, Map impassableRoads, final LocalRoutingParameter parameter, final RouteMenuAppModes mode, final LinearLayout item) { + OsmandApplication app = mapActivity.getMyApplication(); + Iterator it = impassableRoads.values().iterator(); + while (it.hasNext()) { + final RouteDataObject routeDataObject = it.next(); + final View container = createToolbarSubOptionView(false, app.getAvoidSpecificRoads().getText(routeDataObject), R.drawable.ic_action_remove_dark, !it.hasNext(), new OnClickListener() { + @Override + public void onClick(View v) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + OsmandApplication app = mapActivity.getMyApplication(); + RoutingHelper routingHelper = app.getRoutingHelper(); + if (routeDataObject != null) { + app.getAvoidSpecificRoads().removeImpassableRoad(routeDataObject); + } + if (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated()) { + routingHelper.recalculateRouteDueToSettingsChange(); + } + if (app.getAvoidSpecificRoads().getImpassableRoads().isEmpty() && getAvoidedParameters(app).isEmpty()) { + mode.parameters.remove(parameter); + } + mapActivity.getMapView().refreshMap(); + if (mode.parameters.size() > 2) { + item.removeView(v); + } else { + updateOptionsButtons(); + } + } + } + }); + if (container != null) { + item.addView(container, getContainerButtonLayoutParams(mapActivity, false)); + } + } + } + + private void createAvoidParametersItems(MapActivity mapActivity, final List avoidedParameters, final LocalRoutingParameter parameter, final RouteMenuAppModes mode, final LinearLayout item) { + final OsmandSettings settings = mapActivity.getMyApplication().getSettings(); + for (int i = 0; i < avoidedParameters.size(); i++) { + final RoutingParameter routingParameter = avoidedParameters.get(i); + final View container = createToolbarSubOptionView(false, SettingsBaseActivity.getRoutingStringPropertyName(app, routingParameter.getId(), routingParameter.getName()), R.drawable.ic_action_remove_dark, i == avoidedParameters.size() - 1, new OnClickListener() { + @Override + public void onClick(View v) { + OsmandApplication app = getApp(); + if (app == null) { + return; + } + CommonPreference preference = settings.getCustomRoutingBooleanProperty(routingParameter.getId(), routingParameter.getDefaultBoolean()); + preference.setModeValue(app.getRoutingHelper().getAppMode(), false); + avoidedParameters.remove(routingParameter); + RoutingHelper routingHelper = app.getRoutingHelper(); + if (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated()) { + routingHelper.recalculateRouteDueToSettingsChange(); + } + if (app.getAvoidSpecificRoads().getImpassableRoads().isEmpty() && avoidedParameters.isEmpty()) { + mode.parameters.remove(parameter); + } + if (mode.parameters.size() > 2) { + item.removeView(v); + } else { + updateOptionsButtons(); + } + } + }); + if (container != null) { + item.addView(container, getContainerButtonLayoutParams(mapActivity, false)); + } + } + } + + private void createLocalRoutingParameterGroupButton(MapActivity mapActivity, final LocalRoutingParameter parameter, LinearLayout optionsContainer) { + final OsmandSettings settings = mapActivity.getMyApplication().getSettings(); + final LocalRoutingParameterGroup group = (LocalRoutingParameterGroup) parameter; + String text = null; + LocalRoutingParameter selected = group.getSelected(settings); + if (selected != null) { + text = group.getText(mapActivity); + } + View item = createToolbarOptionView(false, text, parameter.getActiveIconId(), parameter.getDisabledIconId(), new OnClickListener() { + @Override + public void onClick(View v) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.getMyApplication().getRoutingOptionsHelper().showLocalRoutingParameterGroupDialog(group, mapActivity, new RoutingOptionsHelper.OnClickListener() { + @Override + public void onClick() { + updateOptionsButtons(); + } + }); + } + } + }); + if (item != null) { + optionsContainer.addView(item, getContainerButtonLayoutParams(mapActivity, true)); + } + } + + private void createSimpleRoutingParameterButton(MapActivity mapActivity, final LocalRoutingParameter parameter, LinearLayout optionsContainer) { + OsmandApplication app = mapActivity.getMyApplication(); + RoutingHelper routingHelper = app.getRoutingHelper(); + final int colorActive = ContextCompat.getColor(app, nightMode ? R.color.active_buttons_and_links_dark : R.color.active_buttons_and_links_light); + final int colorDisabled = ContextCompat.getColor(app, R.color.description_font_and_bottom_sheet_icons); + int margin = AndroidUtils.dpToPx(app, 3); + final OsmandSettings settings = app.getSettings(); + String text; + boolean active; + if (parameter.routingParameter != null) { + if (parameter.routingParameter.getId().equals(GeneralRouter.USE_SHORTEST_WAY)) { + // if short route settings - it should be inverse of fast_route_mode + active = !settings.FAST_ROUTE_MODE.getModeValue(routingHelper.getAppMode()); + } else { + active = parameter.isSelected(settings); + } + text = parameter.getText(mapActivity); + View item = createToolbarOptionView(active, text, parameter.getActiveIconId(), parameter.getDisabledIconId(), new OnClickListener() { + @Override + public void onClick(View v) { + OsmandApplication app = getApp(); + if (parameter.routingParameter != null && app != null) { + boolean selected = !parameter.isSelected(settings); + app.getRoutingOptionsHelper().applyRoutingParameter(parameter, selected); + + Drawable itemDrawable = app.getUIUtilities().getIcon(selected ? parameter.getActiveIconId() : parameter.getDisabledIconId(), nightMode ? R.color.route_info_control_icon_color_dark : R.color.route_info_control_icon_color_light); + Drawable activeItemDrawable = app.getUIUtilities().getIcon(selected ? parameter.getActiveIconId() : parameter.getDisabledIconId(), nightMode ? R.color.active_buttons_and_links_dark : R.color.active_buttons_and_links_light); + + if (Build.VERSION.SDK_INT >= 21) { + itemDrawable = AndroidUtils.createPressedStateListDrawable(itemDrawable, activeItemDrawable); + } + ((ImageView) v.findViewById(R.id.route_option_image_view)).setImageDrawable(selected ? activeItemDrawable : itemDrawable); + ((TextView) v.findViewById(R.id.route_option_title)).setTextColor(selected ? colorActive : colorDisabled); + } + } + }); + if (item != null) { + LinearLayout.LayoutParams layoutParams = getContainerButtonLayoutParams(mapActivity, false); + layoutParams.setMargins(margin, 0, margin, 0); + optionsContainer.addView(item, layoutParams); + } + } + } + + private LinearLayout.LayoutParams getContainerButtonLayoutParams(Context context, boolean containerParams) { + if (containerParams) { + int margin = AndroidUtils.dpToPx(context, 3); + LinearLayout.LayoutParams containerBtnLp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); + containerBtnLp.setMargins(margin, 0, margin, 0); + return containerBtnLp; + } else { + return new LinearLayout.LayoutParams(AndroidUtils.dpToPx(context, 100), ViewGroup.LayoutParams.MATCH_PARENT); + } + } + @Nullable private LinearLayout createToolbarOptionView(boolean active, String title, @DrawableRes int activeIconId, - @DrawableRes int disabledIconId, OnClickListener listener) { + @DrawableRes int disabledIconId, OnClickListener listener) { MapActivity mapActivity = getMapActivity(); if (mapActivity == null) { return null; @@ -1196,7 +1260,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener @Nullable private View createToolbarSubOptionView(boolean hideTextLine, String title, @DrawableRes int iconId, - boolean lastItem, OnClickListener listener) { + boolean lastItem, OnClickListener listener) { MapActivity mapActivity = getMapActivity(); if (mapActivity == null) { return null; diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowAlongTheRouteBottomSheet.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowAlongTheRouteBottomSheet.java index 3aef796c58..39d98c23e3 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowAlongTheRouteBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowAlongTheRouteBottomSheet.java @@ -460,6 +460,17 @@ public class ShowAlongTheRouteBottomSheet extends MenuBottomSheetDialogFragment } } + private MapActivity getMapActivity() { + return (MapActivity) getActivity(); + } + + private void updateMenu() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.getMapRouteInfoMenu().updateMenu(); + } + } + protected void selectDifferentRadius(final int type) { int length = WaypointHelper.SEARCH_RADIUS_VALUES.length; String[] names = new String[length]; @@ -548,6 +559,7 @@ public class ShowAlongTheRouteBottomSheet extends MenuBottomSheetDialogFragment ShowAlongTheRouteBottomSheet fragment = fragmentRef.get(); if (fragment != null && fragment.isAdded()) { fragment.updateAdapter(); + fragment.updateMenu(); } } } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java index e50b27a7fd..f2663aa870 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java @@ -2,7 +2,6 @@ package net.osmand.plus.routepreparationmenu.cards; import android.graphics.Matrix; import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; import android.view.MotionEvent; @@ -72,7 +71,7 @@ public class RouteStatisticCard extends BaseCard { SpannableStringBuilder distanceStr = new SpannableStringBuilder(text); int spaceIndex = text.indexOf(" "); if (spaceIndex != -1) { - distanceStr.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, nightMode ? R.color.primary_text_dark : R.color.primary_text_light)), 0, spaceIndex, 0); + distanceStr.setSpan(new ForegroundColorSpan(getMainFontColor()), 0, spaceIndex, 0); } distanceTv.setText(distanceStr); SpannableStringBuilder timeStr = new SpannableStringBuilder(); @@ -84,7 +83,7 @@ public class RouteStatisticCard extends BaseCard { } spaceIndex = timeStr.toString().lastIndexOf(" "); if (spaceIndex != -1) { - timeStr.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, nightMode ? R.color.primary_text_dark : R.color.primary_text_light)), 0, spaceIndex, 0); + timeStr.setSpan(new ForegroundColorSpan(getMainFontColor()), 0, spaceIndex, 0); } TextView timeTv = (TextView) view.findViewById(R.id.time); timeTv.setText(timeStr); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/WarningCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/WarningCard.java index 9f4bff7845..f02032e257 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/WarningCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/WarningCard.java @@ -53,7 +53,7 @@ public class WarningCard extends BaseCard { @Override public void onClick(@NonNull View widget) { - WikipediaDialogFragment.showFullArticle(app, Uri.parse(OSMAND_BLOG_LINK), nightMode); + WikipediaDialogFragment.showFullArticle(mapActivity, Uri.parse(OSMAND_BLOG_LINK), nightMode); } }; int startIndex = text.lastIndexOf(" "); From 992c675806b9d1b024cbb310bcb3f2ecf9fd101d Mon Sep 17 00:00:00 2001 From: Chumva Date: Thu, 28 Mar 2019 17:23:00 +0200 Subject: [PATCH 2/3] Fix route recalculation for public transport --- .../AvoidRoadsBottomSheetDialogFragment.java | 6 +----- .../plus/routepreparationmenu/MapRouteInfoMenu.java | 9 ++------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/AvoidRoadsBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/AvoidRoadsBottomSheetDialogFragment.java index 2a1102d289..26e3664bcd 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/AvoidRoadsBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/AvoidRoadsBottomSheetDialogFragment.java @@ -302,11 +302,7 @@ public class AvoidRoadsBottomSheetDialogFragment extends MenuBottomSheetDialogFr avoidSpecificRoads.removeImpassableRoad(routeLocation); } - RoutingHelper routingHelper = app.getRoutingHelper(); - if (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated()) { - routingHelper.recalculateRouteDueToSettingsChange(); - } - + app.getRoutingHelper().recalculateRouteDueToSettingsChange(); MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { final MapRouteInfoMenu mapRouteInfoMenu = mapActivity.getMapRouteInfoMenu(); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java index f464006ca9..6d2c09300b 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java @@ -1069,9 +1069,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener if (routeDataObject != null) { app.getAvoidSpecificRoads().removeImpassableRoad(routeDataObject); } - if (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated()) { - routingHelper.recalculateRouteDueToSettingsChange(); - } + routingHelper.recalculateRouteDueToSettingsChange(); if (app.getAvoidSpecificRoads().getImpassableRoads().isEmpty() && getAvoidedParameters(app).isEmpty()) { mode.parameters.remove(parameter); } @@ -1104,10 +1102,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener CommonPreference preference = settings.getCustomRoutingBooleanProperty(routingParameter.getId(), routingParameter.getDefaultBoolean()); preference.setModeValue(app.getRoutingHelper().getAppMode(), false); avoidedParameters.remove(routingParameter); - RoutingHelper routingHelper = app.getRoutingHelper(); - if (routingHelper.isRouteCalculated() || routingHelper.isRouteBeingCalculated()) { - routingHelper.recalculateRouteDueToSettingsChange(); - } + app.getRoutingHelper().recalculateRouteDueToSettingsChange(); if (app.getAvoidSpecificRoads().getImpassableRoads().isEmpty() && avoidedParameters.isEmpty()) { mode.parameters.remove(parameter); } From 41996fb33b8f735045fedf0642bb16b5961d5af2 Mon Sep 17 00:00:00 2001 From: Dmitriy Prodchenko Date: Fri, 29 Mar 2019 11:35:17 +0200 Subject: [PATCH 3/3] Modify Save, pedestrian acons add no route icon --- .../res/drawable-hdpi/ic_action_gsave_dark.png | Bin 1259 -> 334 bytes .../res/drawable-hdpi/ic_action_no_route.png | Bin 0 -> 660 bytes .../ic_action_pedestrian_dark.png | Bin 1513 -> 503 bytes .../res/drawable-mdpi/ic_action_gsave_dark.png | Bin 1188 -> 258 bytes .../res/drawable-mdpi/ic_action_no_route.png | Bin 0 -> 422 bytes .../ic_action_pedestrian_dark.png | Bin 1338 -> 334 bytes .../drawable-xhdpi/ic_action_gsave_dark.png | Bin 1385 -> 408 bytes .../res/drawable-xhdpi/ic_action_no_route.png | Bin 0 -> 796 bytes .../ic_action_pedestrian_dark.png | Bin 1629 -> 568 bytes .../drawable-xxhdpi/ic_action_gsave_dark.png | Bin 1587 -> 593 bytes .../res/drawable-xxhdpi/ic_action_no_route.png | Bin 0 -> 1150 bytes .../ic_action_pedestrian_dark.png | Bin 1988 -> 857 bytes .../drawable-xxxhdpi/ic_action_gsave_dark.png | Bin 0 -> 752 bytes .../drawable-xxxhdpi/ic_action_no_route.png | Bin 0 -> 1527 bytes .../ic_action_pedestrian_dark.png | Bin 0 -> 1114 bytes 15 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 OsmAnd/res/drawable-hdpi/ic_action_no_route.png create mode 100644 OsmAnd/res/drawable-mdpi/ic_action_no_route.png create mode 100644 OsmAnd/res/drawable-xhdpi/ic_action_no_route.png create mode 100644 OsmAnd/res/drawable-xxhdpi/ic_action_no_route.png create mode 100644 OsmAnd/res/drawable-xxxhdpi/ic_action_gsave_dark.png create mode 100644 OsmAnd/res/drawable-xxxhdpi/ic_action_no_route.png create mode 100644 OsmAnd/res/drawable-xxxhdpi/ic_action_pedestrian_dark.png diff --git a/OsmAnd/res/drawable-hdpi/ic_action_gsave_dark.png b/OsmAnd/res/drawable-hdpi/ic_action_gsave_dark.png index c65b341faa3659473c20632e0abfcf2ac0e7e186..83b5e2dc934cfe1e9a88067502c7f5fc0da1307e 100644 GIT binary patch delta 307 zcmV-30nGmE3C;qLB!3BTNLh0L01FcU01FcV0GgZ_00001b5ch_0Itp)=>Px#1ZP1_ zK>z@;j|==^1poj5<4Ht8RCodHmcb3eFbn`)!~l%Y5g3V4*Z`OSF%ctl1iC>nD2+@M z#}26xs(g|kjU4xyI%xqMXJvG-022}mBGAAF{tOqAa3Kj7l7Da^iE1G{ly?}tHWw@j zGIxxDN=*bZ)`z?+SP^7qqEsqGWM)oa0TwTWB0r7#=DqO-VtjwMO$WOd_U|xnFi?%(m|C>?YefaoOFPR0w1)XR~8=E}faU zo0Y1qi6Z(U77|L;25m`2q7_;UT9rnGJ`^QHv4T}WX{|y)t@@zBGn?JmhtPqUbN+Mw z@BhF5HZNoc`nGMoXDfmr+cN!f4z69{yJa){{(#KPz@&xB=tYp*Ce6Z7Fr+*z>5fIHp$<{CT!==H-aS=U)yF`9YGBl~W7x_EA7iL# z#IQkLp%ga>N@jn}1NquOL9dPJqJiz%jrLY0Xutx2idL<%?Mu}dR<|p`eRxb_Xk8^3 zi(zY|hLkLtbUc9agn;W5&7l#Ipm`x8MtV>N$|Myf849OFiDxB>K^qSSy?I7a%E{@5 zFDS*ZQV_TjNmeQqqQVl6H%ii?D3TOIG7JtiaDT!M)GBWKolOfe@O9601Jkk5(4wk2 z<3S9AOxHrNTt!(oZ2OHw!IY6z)g@_yA}uS7tFG+_Iq*M?4YmEkgbT=_tkWxFPByP8T@=*9;)w5ti3!p5h`pqhSraaZ~=*`V^kPINT;3No7Qx6<7mT zqXLW5G=M2BssLAcpwl8>W$e&+Dhpz}L+@SWo{bpjz*}YTSm-Zf1ewo|3@KdYsbLKel*?jwh$7mz?-$(ned@)LV~# zMK7ElUpT_Q|Mc?J@7o?d^xg7-XWQ~;dp>R3zweJPUQ#~!edWo^=RkRoGY@Rv|KjlH*&F{Hs9qs9^(dp)zFu671ryV$6Uc?deE*!&H@uq9`}fVh cv!m8ZAuY#t?HK%!2!CQoCN&_>Cq|C^2Sqck-2eap diff --git a/OsmAnd/res/drawable-hdpi/ic_action_no_route.png b/OsmAnd/res/drawable-hdpi/ic_action_no_route.png new file mode 100644 index 0000000000000000000000000000000000000000..b4bb2b9a61d525677b8256e28cf32197b8d72edb GIT binary patch literal 660 zcmV;F0&D$=P)h*f3GVj((2t+1mt{|3DA0c}XdoN<6HbNj{ zqp>rlcp&8wRUjlzrjSvV!4xvSyr;2)jXjkm1P5&B&ERAUS-_~T=5npvE9ZM5e-b;k zd=!K0X`NM9{S^HRnZrL5q8gSW&FX{1FEkXYv!uK!T8jf2LF$$g6s`Wln^# z>ZcX%QT0cZfq_A1tNsRGxS)_IH+Q1v6nIn|g_pi5Wq!)sK=m`fvIP_L(^%^@#Qs@luyq5}S;7SN}EhP((>f~1_&e~9TFZczdoYKxFKeUe9BARp3yAo&yUzYe6<)CQp# zm;l!z|IDwIKCuZmMu^ja2w3PYMPg}sCjqhvkXVaf&pGFd_48#=xUQX zEz;$FqmL**H6y2oWtzj>TL%pAwdN+KHXYy-mw>blQ1ppCs1PABU{eiOoFXWEF9RvA u6^@p!r2~bRz}kMir7wzAuE`xbw1IB{_r59o3oq6H0000Px#1ZP1_ zK>z@;j|==^1poj6j7da6RCodHmyJ!sFc5`b5Cdcb!Uo-djKBzG12!N`&~DH$0V5Pl$R(EVMwS^limy;)qfsD89xb zVsxg7z8yptWPdAeKK1toeKFW>X&Ut8u>Q?cfrWrfB6d!|vB=1#q) z;S*U42X4=t_o_YH`pl>LK%#2;sbvlEe+qq05QM#;({yQrps8-1_NFKcR^?++Q55V^ z3(f*7gQ!_ean3GN3%Zj#s=~PNb0iYj%SMqC+?CEOT1R_;UFH)mP1R T^z?C500000NkvXXu0mjfh`-O3 literal 1513 zcmaJ>eQXnD96r|AeXxy+$d{13+(1X*dcE7-b$6_8qt|sE>lobv^$%tD@ou|p?Un0o zEAwL;NbC@u%Y=+%C?7@$5n}KQ13@E;hy(>8NQi@2#6$=mGYBfv`F2~8KM0rHz4yNN zd!FC(`?~JxDsN8K>?{n!a(v}t0Ilv#AgZrG@mw;Qmgy{cAeZ&G*_FMbvj#RNnUf~Evwq2_Q@h`I1FUID!)k4YSi znV3y3d|Xt}Uk%*40Re002*p7$z{%SwmUHsX#ehb8(osm#4#L3;Y=PjQ!Ni3lZ-!bg z1jMolUufsT8%;AJkYrn1o4u{Tt{V*`#q&Jrph=o0kOdK48#bjF5sv1i7(^IV3@u`6 zdKe@bC0TDVT{u!Y9zrPM_unTDM<)`6Qbxw42uax;WGIx3Ys@-o2H^iP9%>z}T^oU9 z07mr|LqYYZ&r5+(?jG$ZX^7Ma%MA?`MQRpxr6mNzrcZR?=!;#|RDoetRhBu9pgE2q zcn8B1Jg?FO2Pw!ZG6U;nHO2EVyn`=rud{6$0^IJgs)PJhT3FTFq6?E{8jo6p zhSmzzGD8o6u{;afLo}$0%qvccCS;1MC!93nAb163g5y}0lQ@-E83~`js}JOFyid^y ziX)PeBS?zEO0*&oGIUA=ML~v;X)Z|)Rfpaj(sUy^%$=CaXfj0L? z3x?4=8E9~@1UnhSCf)OirM0mO^2q3D@zJ`p%Ix*o)n`h7FF8CTUThf-gO%XKwCcB4 zWZoR<$-2|0-?1Xb6qjP zwxnjxck}=LG9!Mi>(9lu(R)3aJM(iidFm%im}wrq@I=Ue9*b^M`>YG z;G57ZZ|yvoc``umDa_x!-_!S^cS`zP&w*RK?IUn}jb(U2phB%!wCV-Gxf7&kZ@J{} z!`fS?T|Zs%hbMUUr(L_(51iWDz05MSxy;@%{f7hk^2+C*&Ke|lz{&YT<(A<^_=QWG zKF*rgF#qUhm)B$u?acnXPx#1ZP1_ zK>z@;j|==^1poj5mq|oHRCodHlu-(RAPhi9bO4Xw6+1#F>Ifd8BiIqTflXL2mm$vl z$_Il?x7WZ0F!+){)Z|RinIZVQ0B@wl*f30H&(NL)Etu@+>R<0v@W#-)h^r}>3=(zV znIwp3&pRj%V(x&DaFXI`!HeWkyh$J=+2YLtCb8Ol)!(v|-+j<#u|6?OOBcw&7qWvz g9;hUK;0l8pF4^D~l%eAKm;e9(07*qoM6N<$g7X7kMF0Q* literal 1188 zcmaJ>TWB0r7@j4zHBF-nf~3CmFcobfXKp()yJy%*y1TR6F1Rsl7rGR@%*;8H9g?|Z zX5vnQXw*uLMXl5e)fb_HeX59{MIWRP(L5D|_QAd=f<9L4OCKun%qAQA5IQh(&VSDT z{r~shW^H!n`1t-O_A?AK-aKKn={k|U5AUVl-}?Gpx*SaE-Q;B8Bz-d?Oa%uP0Zq@G zBW+^h<;4wBW|)yPZl{}cThC~A;BjWA!=+wG(F{|bPD9h4Cke2~oa^iC?eBkJfs1wa zl+qGfVU6_M6DtupxiZtSSLSVm+36`zPBm)4BZ&!8Z^4hXRA&cvHM-A^c@_**l6jro zBGqlpf?5y}pl~X*1yKe?#EFVpM8!!UQJEJ?yd*#YX-Yv8B(VLk)LVodt!*^6eNjng zdr1;%Jm2s4xqg8QqB&kf2=Ri%OA@3SFkbc(GlhP9cxb^Ou^qW#;s!p*ESgrZl;|vF zx)p*Kwpu%e{dhZ3G-Z5hhP=oLyyswjkA(-aw z!HzOT%0_!Oa%oY_1tYMRJmM!!Lucs?hh4163dWYDs!&o@86rVO5Fso0WRY0OF53x-@PE6k>L*MSe_W&zB5UbT9VkSY< z34(=T7tHp8B#3)K2x_%K)xnWdu8)I$d^9W5R@4TG+?NP$M1cnedDh%rI5@}=OF}_` z7}*Glj;ulp6BQNodXn$tgoxz~O&S(*z&QnAO=dTMWr9<~k)2MXPU#)wa zo6{pO_s98fS4ZEuJ-U8<_3rfA)jeN~gG1o=xy_Azu;;uce#aaT@@u1~tKOI}S$Pjn zoPGc2()x$hiN(5fBR96jT`FDtrF`hX3uCY37N_!KBVXk|`1jn^q)~eAjbl?Em1o~Q zu3vk3^^s%Tt7o6u`_IO$-1U9yr}O9PlW%^q`1fOP-C6DC-@fyi_2f^v%iQ_Th0gQf v(`#pbyu}|8?j6lP{pgq4#Xlcs9-3e-9K8AU$9uYL_TOmMXN)V=7hnGmlUIKy diff --git a/OsmAnd/res/drawable-mdpi/ic_action_no_route.png b/OsmAnd/res/drawable-mdpi/ic_action_no_route.png new file mode 100644 index 0000000000000000000000000000000000000000..91162d59faad69197ee9082b312a0f71cc8abec0 GIT binary patch literal 422 zcmV;X0a^ZuP)cVD*mM|101(UlMVTe-ls&M;WtzeFDy5PQMmd$xCl7u0-TBa1~suBYtP=(kT@*G z{rFN|Yu$^D*b%)_Fg4=ObsALSn87ZzGzQ9si3b~KWAIVjlV@BHtPx#1ZP1_ zK>z@;j|==^1poj5<4Ht8RCoc+lz|PxAP_}=oxl+o!42#PjNk}vAWong=q7aob%J&S zM>vnTgf7tV*%ax_XHg&XQ)MO(~4ii~l?9K1qD&f$;bgj`$&8JnPR>z^d6;entD1bRS9 za|B^Ol&mYxo%2iz@i0f`M^Q~cY+tz$`>Q4mIqoLWt{*3002ovPDHLk FV1gW*eIWn< literal 1338 zcmaJ>ZA{!`9Pe>M-m>g)FEEX+7B!o$*B9CzZ8*4B#wCgr(g5~Oj+DaG-?);DG7v36BCW>+eJ&^6YXR>lSuUd38l(B`}V39`VE(0q1Cw}pHV+u#-8yL(Jv=!S_i z7{oS3^@vF{YFGee{T!~46oUqMKgDtZK5!JJ;hrFy2%5x6USJyql18^K40^NFejycW z+wui>K`i4qra%z6T+W|s^c&UyLGe6KkTgNlIJCg+QQeX9xNbL;7-GOyEX{N@Lq}ak zNj8R^AO@9ghLANyahq7Tw-NBn=V{o2ic%0`| z8s`87SVd+)zpR#ccEVFl3`d3o;b@GFP*j|0qIfnQjqzcYCL{5twh}g>+m56wpyXSF zzPGUa1F=HX0+M4`X~P&QbwM&?IEI}uOf(wZs5*MMThmn|XCHCPv>9~_SlS3s+bkoC zZsb|ecF>?IGOq+E8kZ@q9}mzBiSr7~1jn%~CvhsTG7`3hSMST;W}m_n7>8MsBS?zE zO0**3G6+aGMF9qvY0f1FD#fS@rAQJ+K#7FgI`_3w=?M0x`?@_CaI-yHK!@{W!NK{h zYiU1%csdfXa6139{P+5Ls~4yCdPgso7nZ%Jo_*rAH_+#ABFhu+>@AFkvd0_ ze1mVM>)~7ELX8+EOhi*3$+PxkMCG$rZV|&$A@RiudcOLEOt*8NndyL z#-~@b>yam^559Wut@4Xy;$wwz@4f1~t24a^7W(GBg_E-X|E#7pGqM=F+btpG;Suz@}?Ix~onjp$QKXIQs4PzsyE5?%ymC?~HvMdGYjr_8`I@ diff --git a/OsmAnd/res/drawable-xhdpi/ic_action_gsave_dark.png b/OsmAnd/res/drawable-xhdpi/ic_action_gsave_dark.png index 5f6d863e2584c1a091e42ce748c4c108d5e6c279..e7ea375f45174e072a38dcfd5e9607c3a091cbb2 100644 GIT binary patch delta 381 zcmV-@0fPSN3YY_sB!3BTNLh0L01FcU01FcV0GgZ_00001b5ch_0Itp)=>Px#1ZP1_ zK>z@;j|==^1poj6ElET{RCodHn1Kz#AP@jw;{cA}2<>E!;E$ve)D3h5H>exn6EUf@ zQ0Nz4lfQ&$r2PL;g0ujNq9~GVpb&=mN<=^bw(#eufHW!~jeiPAqXN>XfHW!~4O@T? zokwa7WMaoqJAov&0Q08zC5(sH*SIl8Okz;HnUV+zc*Ps81ZN5P4=8(Torx?b*Vnmg zW3l*zX3)C^&6wWJvd`4aTX1Q9w!n-;%5TWc&lZSC%z>~{{#62GN?<~~x&j#zm>8?R zK!OBj#E}tzuyzDy#*hV9a bQRI06TaxsC6IQcY00000NkvXXu0mjfN&}>L literal 1385 zcmaJ>eN5bB7%#{15nve%w>e_8>Ea^JUa!5jM;i`ua4>H2H8_FH80od|aoyduU0b+= z8AZf_b6>{Hz~T~7gEM3c7&AR6jty z5upt<072?Jcm)(ANNTU_YcX4Ds(De3*o1_REf&!r8bOLnW11j_fQkA+o2P~g0kawj%OUaokG_h40_Y0 z0N>!LT=NAb7Zx;4jVFj`G-``FY^vTykQ~Pmc8Z`V9BSZ3r(y~*TrqYgEqH(->au3a zs)8mg3VyZSbYYO`Y6uanre@u+Vyqfy(7t{w;Q#FFBhL)GFR2_Y)Sym)9Y7{2Qv>LSs z=yC^;Ds?r2uH>1QH{cN90%Vch!Qc`nayS{FS==uH7I!)rk!0+&Q>6UZ8eV!Jf2(~8 zPhcEck`6CWoakU35-t?64xA(bOld#>xWE9B(m(`(i)M4~*4X+_{Grk5)Z7_R+2b{@x!m7iY5vmMq0- zcd}?}NbEbc|ItGqZ1pW!zONdsKYeRPlKaQUFHYaM_WIzjA*FBr{`}Qz(_fYKpZ)s6 z_N~(`NOo&V*T}1R1F63Z9)H`?d2E-K6Tn`)9lW``{rb(SUUGNd*zj9dKKKHUfvcz{RsP4hq!gC_Z~Oisq0P~MYdhC zbTnSta@U>x*wg#tQ`GIr@L?|ho~60<-O(G!iTC1LM%0u)XTJE(I&p!IWq8rLu+V)mbGA)}>=d6Xa)Snk+fUh-b3t{iye9;^*hBsP&vL HYwh_D^9AO} diff --git a/OsmAnd/res/drawable-xhdpi/ic_action_no_route.png b/OsmAnd/res/drawable-xhdpi/ic_action_no_route.png new file mode 100644 index 0000000000000000000000000000000000000000..7bd08439179dcdef81f1c1a319e249ec934325f0 GIT binary patch literal 796 zcmV+%1LOROP)kc1LNRz^0=Eo*?E4FmDi^fRuDLojX#di^_Cyna=E@)o@we zht5I140FGk9qYd2-Mih@=>%jlnM_IsI3b6_VMsq`B!yJnvJ3`;J&xog29V;c@SLP{ zbh#qg9%D%F29WY&`gub#40OFG`9VfpA%bV<5mLTHJ@X;uA${gDrZYhUc=<`rNj8VS z{32N*%-m8}k?csea@`suvC;{z3(0J3;P%~$WJb$gS;n&KXam?qcBw& z<@ad6`FV|qG2m8}C!W6Jz*y!x+RD$+j)^};z(I@w*Qz{`L#YQy-BeZE067cNFY0t!-U*h7nh a2mA&bu>BTT$O|L@0000Px#1ZP1_ zK>z@;j|==^1poj6%}GQ-RCodHmy2=2Fbsy3PCz%H6O;|g2y}v8H(&#@0c-#pKqoNW zfKE_0fDKgnVtTm{KZxbmUA{Z|vu$DlDY2x93-Z4#O>C$DTW~I{ zAr+dSH`vs|27lf8fE4ruGHLk)K1O^I-3U6qA+@o^nA@vP05*NVgcMgBd|R?ba4`k} z3p69txEdXBjfe9%J-7J3=b0r=Mpe;7_%c0OMl1_e5?bnAUE*7fDdH5B1B+w zY45UBKJDQSasm50@Vw=(a~DwCf^!*@47@L3p&1uM0LM1k-9mpLB3=TpIUaQHw?~MG z?+WxauoFatTfmu4nP-TIuYkAC_o(?V;a-6wL}su6O#w&Ee=qtvuw{I9eIR-INPGk& hFJMXWD;O}6nm-jD2kgqACXxUE002ovPDHLkV1l-Q+>!tQ literal 1629 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 st1aVxzmt5SK2hRycQaZBTLOUoo{NBbU z*BOL&7vnEI1$Sc_4BKex4e07UfCm@847u~O<+}K{>{`k-Sf+*myex=4%O$wQAqvXN zWnA@AUa65+7;2Ny9QOlS0gb;Q)QZ#s@fV$g+z=C#_gwKK*M)d;-DEjpcjB}fEX zvn6eU;RA<5OTKTGG~;a9XRT$iH0?~>$XjJTX`nsCA9k|v`2;P6{;?xN-Vzc-YeAAg zwIS|A$Xh^y3~DAlM6?1mLi~XtP8w@g@;GAEXvd&GVD2JEIOfpcSo7z743$tvk^*Th zsJ5gXW4Pu}S@Qjc1W^fuo@$COQ|M0<>+!>L<1Cc7tJcz6T!$*Ak1zOLvxE#3QII^0gEvG~4=AS@= zuJo*j2lZD$o=H2%0y)S6ImiMz$O1V?QXqOL$NO*Byf1g8D6`M`=Ui6xD7Lqoe_?2W zJm&Y*&3L8Ok-Wqq zlAkDgh~zB}@mglm^GJD~ki0;KNuWffnQba;ytDvQJ<5l-e-dp;!MCka94aL(n+X5jS#=d*9fezrIkXm?QGE4l6L2<6y8l` zMWF&+3GpP(SDQ$jMrWCAhc_jpGLKxjLnPHO5F`+9>oh`gf#JL904K+d!E$)hv1Mf1 z=QqxCEF#sQAowc6LSt>vfZKH$8gpFTueJ%qU6T%K(NP;32PaD>-ArXF&QE3OoWP;# zfG9+OkNs~#9Hv9sSBo+a;@dSbwwPx_+jNY2+b7VHqTSGmN%ZSbyd7PF{(LfxPiI3t z&j=gs|GL4vs|d-07*qoM6N<$fPx#1ZP1_ zK>z@;j|==^1poj7?ny*JRCodHnvHRrKoEtWQh`!I=pb?hp#-M`rvrCjrGmHv%N0l+ zKnJobkWzuv!FqRu$Bc%9JJ9`c_s#4u7Ka5-yN|sCAd|^t{C}}Ppb$~Pn|qEW$C+cd zSS*f69TA43qHbOq;nJiL=Ro}&k`<}R5FIL{Mw2}z{D1?#Asp@v$Nz={LK0|cdHg6s z66kDseB6xipaQ8u>i*}N7o-T~K4_Rmq>VzH%C$IoE|!TL&XkfaQ;a>wsZ~l3NEN>L zCC4KT-?e1FlYfRV2pVCYTA8B5{3oVO8C5i%N6ZcSDx*D3M>1|6rN$Ss;`m2qWu(Iv zF+wLA&=*?dnS+x9sG3r#d=U%2$30%ip9a)L{NN|+%T zx205`YS8#4j(rj$(X=Iwd5c81S>ia5hqpRhc~H@_?-d;lq2hm3u0?VsP}#Fj-rA7q z!z+d4kS}3-n9z`7xH4!hK~>6#gSv6KKGoYea(042s@=1TO-y|I~;Cn*yl}x<*9!$e?Hp zT05{J&|C~!u$4j4chH}>7U<38OW?P_mOv_l{*TCTok2A+nM~%357sfT4yJACy#N3J M07*qoM6N<$f{|2)hyVZp literal 1988 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