package net.osmand.plus.views; import android.Manifest; import android.annotation.SuppressLint; import android.content.DialogInterface; import android.content.pm.PackageManager; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.PointF; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPropertyAnimatorCompat; import android.support.v4.view.ViewPropertyAnimatorListener; import android.support.v7.app.AlertDialog; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.SeekBar; import android.widget.TextView; import net.osmand.AndroidUtils; import net.osmand.core.android.MapRendererContext; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.data.RotatedTileBox; import net.osmand.plus.OsmAndLocationProvider; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.OsmandSettings; import net.osmand.plus.OsmandSettings.CommonPreference; import net.osmand.plus.OsmandSettings.LayerTransparencySeekbarMode; import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity.ShowQuickSearchMode; import net.osmand.plus.dashboard.DashboardOnMap.DashboardType; import net.osmand.plus.dialogs.DirectionsDialogs; import net.osmand.plus.mapcontextmenu.MapContextMenu; import net.osmand.plus.mapcontextmenu.other.MapRouteInfoMenu; import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.views.corenative.NativeCoreContext; import java.util.ArrayList; import java.util.List; import gnu.trove.list.array.TIntArrayList; public class MapControlsLayer extends OsmandMapLayer { private static final int TIMEOUT_TO_SHOW_BUTTONS = 7000; private static final int REQUEST_LOCATION_FOR_NAVIGATION_PERMISSION = 200; private static final int REQUEST_LOCATION_FOR_NAVIGATION_FAB_PERMISSION = 201; private static final int REQUEST_LOCATION_FOR_ADD_DESTINATION_PERMISSION = 202; public MapHudButton createHudButton(View iv, int resId) { MapHudButton mc = new MapHudButton(); mc.iv = iv; mc.resId = resId; return mc; } private List<MapHudButton> controls = new ArrayList<>(); private final MapActivity mapActivity; private int shadowColor = -1; // private RulerControl rulerControl; // private List<MapControls> allControls = new ArrayList<MapControls>(); private SeekBar transparencyBar; private LinearLayout transparencyBarLayout; private static CommonPreference<Integer> transparencySetting; private boolean isTransparencyBarEnabled = true; private OsmandSettings settings; private MapRouteInfoMenu mapRouteInfoMenu; private TrackDetailsMenu trackDetailsMenu; private MapHudButton backToLocationControl; private MapHudButton menuControl; private MapHudButton compassHud; private MapHudButton quickSearchHud; private float cachedRotate = 0; private TextView zoomText; private OsmandMapTileView mapView; private OsmandApplication app; private MapHudButton routePlanningBtn; private long touchEvent; private MapHudButton mapZoomOut; private MapHudButton mapZoomIn; private MapHudButton layersHud; private long lastZoom; private boolean hasTargets; private ContextMenuLayer contextMenuLayer; private MapQuickActionLayer mapQuickActionLayer; private boolean forceShowCompass; private LatLon requestedLatLon; public MapControlsLayer(MapActivity activity) { this.mapActivity = activity; app = activity.getMyApplication(); settings = activity.getMyApplication().getSettings(); mapView = mapActivity.getMapView(); contextMenuLayer = mapActivity.getMapLayers().getContextMenuLayer(); } public MapRouteInfoMenu getMapRouteInfoMenu() { return mapRouteInfoMenu; } public TrackDetailsMenu getTrackDetailsMenu() { return trackDetailsMenu; } @Override public boolean drawInScreenPixels() { return true; } @Override public void initLayer(final OsmandMapTileView view) { initTopControls(); initTransparencyBar(); initZooms(); initDasboardRelatedControls(); updateControls(view.getCurrentRotatedTileBox(), null); } public void initDasboardRelatedControls() { initControls(); initRouteControls(); } public View moveCompassButton(ViewGroup destLayout, ViewGroup.LayoutParams layoutParams, boolean night) { View compassView = compassHud.iv; ViewGroup parent = (ViewGroup) compassView.getParent(); if (parent != null) { compassHud.cancelHideAnimation(); compassHud.compassOutside = true; forceShowCompass = true; parent.removeView(compassView); compassView.setLayoutParams(layoutParams); destLayout.addView(compassView); updateCompass(night); return compassView; } return null; } public void restoreCompassButton(boolean night) { View compassView = compassHud.iv; ViewGroup parent = (ViewGroup) compassView.getParent(); if (parent != null) { compassHud.compassOutside = false; forceShowCompass = false; parent.removeView(compassView); LinearLayout mapCompassContainer = (LinearLayout) mapActivity.findViewById(R.id.layers_compass_layout); if (mapCompassContainer != null) { int buttonSizePx = mapActivity.getResources().getDimensionPixelSize(R.dimen.map_small_button_size); int topMarginPx = mapActivity.getResources().getDimensionPixelSize(R.dimen.map_small_button_margin); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(buttonSizePx, buttonSizePx); params.topMargin = topMarginPx; compassView.setLayoutParams(params); mapCompassContainer.addView(compassView); updateCompass(night); } } } private class CompassDrawable extends Drawable { private Drawable original; public CompassDrawable(Drawable original) { this.original = original; } @Override public void draw(Canvas canvas) { canvas.save(); canvas.rotate(cachedRotate, getIntrinsicWidth() / 2, getIntrinsicHeight() / 2); original.draw(canvas); canvas.restore(); } @Override public int getMinimumHeight() { return original.getMinimumHeight(); } @Override public int getMinimumWidth() { return original.getMinimumWidth(); } @Override public int getIntrinsicHeight() { return original.getIntrinsicHeight(); } @Override public int getIntrinsicWidth() { return original.getIntrinsicWidth(); } @Override public void setChangingConfigurations(int configs) { super.setChangingConfigurations(configs); original.setChangingConfigurations(configs); } @Override public void setBounds(int left, int top, int right, int bottom) { super.setBounds(left, top, right, bottom); original.setBounds(left, top, right, bottom); } @Override public void setAlpha(int alpha) { original.setAlpha(alpha); } @Override public void setColorFilter(ColorFilter cf) { original.setColorFilter(cf); } @Override public int getOpacity() { return original.getOpacity(); } } private void initTopControls() { View configureMap = mapActivity.findViewById(R.id.map_layers_button); layersHud = createHudButton(configureMap, R.drawable.map_world_globe_dark) .setIconColorId(R.color.on_map_icon_color, 0) .setBg(R.drawable.btn_inset_circle_trans, R.drawable.btn_inset_circle_night); controls.add(layersHud); configureMap.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MapActivity.clearPrevActivityIntent(); mapActivity.getDashboard().setDashboardVisibility(true, DashboardType.CONFIGURE_MAP); } }); View compass = mapActivity.findViewById(R.id.map_compass_button); compassHud = createHudButton(compass, R.drawable.map_compass).setIconColorId(0). setBg(R.drawable.btn_inset_circle_trans, R.drawable.btn_inset_circle_night); compassHud.compass = true; controls.add(compassHud); compass.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mapActivity.getMapViewTrackingUtilities().switchRotateMapMode(); } }); View search = mapActivity.findViewById(R.id.map_search_button); quickSearchHud = createHudButton(search, R.drawable.map_search_dark) .setIconsId(R.drawable.map_search_dark, R.drawable.map_search_night) .setIconColorId(0) .setBg(R.drawable.btn_inset_circle_trans, R.drawable.btn_inset_circle_night); controls.add(quickSearchHud); search.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mapActivity.showQuickSearch(ShowQuickSearchMode.NEW_IF_EXPIRED, false); } }); } private void initRouteControls() { mapRouteInfoMenu = new MapRouteInfoMenu(mapActivity, this); trackDetailsMenu = new TrackDetailsMenu(mapActivity); } public void updateRouteButtons(View main, boolean routeInfo) { boolean nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls(); ImageView cancelRouteButton = (ImageView) main.findViewById(R.id.map_cancel_route_button); cancelRouteButton.setImageDrawable(app.getIconsCache().getIcon(R.drawable.map_action_cancel, !nightMode)); AndroidUtils.setBackground(mapActivity, cancelRouteButton, nightMode, R.drawable.dashboard_button_light, R.drawable.dashboard_button_dark); cancelRouteButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickRouteCancel(); } }); ImageView waypointsButton = (ImageView) main.findViewById(R.id.map_waypoints_route_button); waypointsButton.setImageDrawable(app.getIconsCache().getIcon(R.drawable.map_action_waypoint, !nightMode)); AndroidUtils.setBackground(mapActivity, waypointsButton, nightMode, R.drawable.dashboard_button_light, R.drawable.dashboard_button_dark); waypointsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickRouteWaypoints(); } }); ImageView options = (ImageView) main.findViewById(R.id.map_options_route_button); options.setImageDrawable(!routeInfo ? app.getIconsCache().getIcon(R.drawable.map_action_settings, R.color.osmand_orange) : app.getIconsCache().getIcon(R.drawable.map_action_settings, !nightMode)); AndroidUtils.setBackground(mapActivity, options, nightMode, R.drawable.dashboard_button_light, R.drawable.dashboard_button_dark); options.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickRouteParams(); } }); TextView routeGoButton = (TextView) main.findViewById(R.id.map_go_route_button); routeGoButton.setCompoundDrawablesWithIntrinsicBounds(app.getIconsCache().getIcon(R.drawable.map_start_navigation, R.color.color_myloc_distance), null, null, null); routeGoButton.setText(mapActivity.getString(R.string.shared_string_go)); AndroidUtils.setTextSecondaryColor(mapActivity, routeGoButton, nightMode); AndroidUtils.setBackground(mapActivity, routeGoButton, nightMode, R.drawable.dashboard_button_light, R.drawable.dashboard_button_dark); routeGoButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickRouteGo(); } }); } public void setControlsClickable(boolean clickable) { for (MapHudButton mb : controls) { mb.iv.setClickable(clickable); } } private TargetPointsHelper getTargets() { return mapActivity.getMyApplication().getTargetPointsHelper(); } protected void clickRouteParams() { mapActivity.getMapActions().openRoutePreferencesDialog(); } protected void clickRouteWaypoints() { if (getTargets().checkPointToNavigateShort()) { mapActivity.getMapActions().openIntermediatePointsDialog(); } } protected void clickRouteCancel() { mapRouteInfoMenu.hide(); if (mapActivity.getRoutingHelper().isFollowingMode()) { mapActivity.getMapActions().stopNavigationActionConfirm(); } else { mapActivity.getMapActions().stopNavigationWithoutConfirm(); } } protected void clickRouteGo() { if (app.getTargetPointsHelper().getPointToNavigate() != null) { mapRouteInfoMenu.hide(); } startNavigation(); } public void showRouteInfoControlDialog() { mapRouteInfoMenu.showHideMenu(); } public void showDialog() { mapRouteInfoMenu.setShowMenu(); } private void initControls() { View backToLocation = mapActivity.findViewById(R.id.map_my_location_button); backToLocationControl = createHudButton(backToLocation, R.drawable.map_my_location) .setBg(R.drawable.btn_circle_blue); controls.add(backToLocationControl); backToLocation.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) { mapActivity.getMapViewTrackingUtilities().backToLocationImpl(); } else { ActivityCompat.requestPermissions(mapActivity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION); } } }); View backToMenuButton = mapActivity.findViewById(R.id.map_menu_button); final boolean dash = settings.SHOW_DASHBOARD_ON_MAP_SCREEN.get(); menuControl = createHudButton(backToMenuButton, !dash ? R.drawable.map_drawer : R.drawable.map_dashboard).setBg( R.drawable.btn_round, R.drawable.btn_round_night); controls.add(menuControl); backToMenuButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MapActivity.clearPrevActivityIntent(); if (dash) { mapActivity.getDashboard().setDashboardVisibility(true, DashboardType.DASHBOARD); } else { mapActivity.openDrawer(); } } }); zoomText = (TextView) mapActivity.findViewById(R.id.map_app_mode_text); View routePlanButton = mapActivity.findViewById(R.id.map_route_info_button); routePlanningBtn = createHudButton(routePlanButton, R.drawable.map_directions).setBg( R.drawable.btn_round, R.drawable.btn_round_night); controls.add(routePlanningBtn); routePlanButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doRoute(false); } }); } public void doRoute(boolean hasTargets) { this.hasTargets = hasTargets; if (OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) { onNavigationClick(); } else { ActivityCompat.requestPermissions(mapActivity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_FOR_NAVIGATION_PERMISSION); } } public void doNavigate() { mapRouteInfoMenu.hide(); startNavigation(); } private void onNavigationClick() { MapActivity.clearPrevActivityIntent(); RoutingHelper routingHelper = mapActivity.getRoutingHelper(); if (!routingHelper.isFollowingMode() && !routingHelper.isRoutePlanningMode()) { if (settings.USE_MAP_MARKERS.get() && !hasTargets) { getTargets().restoreTargetPoints(false); if (getTargets().getPointToNavigate() == null) { mapActivity.getMapActions().setFirstMapMarkerAsTarget(); } } TargetPoint start = getTargets().getPointToStart(); if (start != null) { mapActivity.getMapActions().enterRoutePlanningMode( new LatLon(start.getLatitude(), start.getLongitude()), start.getOriginalPointDescription()); } else { mapActivity.getMapActions().enterRoutePlanningMode(null, null); } } else { showRouteInfoControlDialog(); } hasTargets = false; } public void navigateFab() { if (!OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) { ActivityCompat.requestPermissions(mapActivity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_FOR_NAVIGATION_FAB_PERMISSION); } else { final MapContextMenu menu = mapActivity.getContextMenu(); final LatLon latLon = menu.getLatLon(); final PointDescription pointDescription = menu.getPointDescriptionForTarget(); menu.hide(); final TargetPointsHelper targets = mapActivity.getMyApplication().getTargetPointsHelper(); RoutingHelper routingHelper = mapActivity.getMyApplication().getRoutingHelper(); if (routingHelper.isFollowingMode() || routingHelper.isRoutePlanningMode()) { DirectionsDialogs.addWaypointDialogAndLaunchMap(mapActivity, latLon.getLatitude(), latLon.getLongitude(), pointDescription); } else if (targets.getIntermediatePoints().isEmpty()) { startRoutePlanningWithDestination(latLon, pointDescription, targets); menu.close(); } else { AlertDialog.Builder bld = new AlertDialog.Builder(mapActivity); bld.setTitle(R.string.new_directions_point_dialog); final int[] defaultVls = new int[]{0}; bld.setSingleChoiceItems(new String[]{ mapActivity.getString(R.string.clear_intermediate_points), mapActivity.getString(R.string.keep_intermediate_points) }, 0, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { defaultVls[0] = which; } }); bld.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (defaultVls[0] == 0) { targets.removeAllWayPoints(false, true); targets.navigateToPoint(latLon, true, -1, pointDescription); mapActivity.getMapActions().enterRoutePlanningModeGivenGpx(null, null, null, true, true); menu.close(); } else { targets.navigateToPoint(latLon, true, -1, pointDescription); mapActivity.getMapActions().enterRoutePlanningModeGivenGpx(null, null, null, true, true); menu.close(); } } }); bld.setNegativeButton(R.string.shared_string_cancel, null); bld.show(); } } } private void startRoutePlanningWithDestination(LatLon latLon, PointDescription pointDescription, TargetPointsHelper targets) { boolean hasPointToStart = settings.restorePointToStart(); targets.navigateToPoint(latLon, true, -1, pointDescription); if (!hasPointToStart) { mapActivity.getMapActions().enterRoutePlanningModeGivenGpx(null, null, null, true, true); } else { TargetPoint start = targets.getPointToStart(); if (start != null) { mapActivity.getMapActions().enterRoutePlanningModeGivenGpx(null, start.point, start.getOriginalPointDescription(), true, true); } else { mapActivity.getMapActions().enterRoutePlanningModeGivenGpx(null, null, null, true, true); } } } private PointDescription getPointDescriptionForTarget(LatLon latLon) { final MapContextMenu menu = mapActivity.getContextMenu(); PointDescription pointDescription; if (menu.isActive() && latLon.equals(menu.getLatLon())) { pointDescription = menu.getPointDescriptionForTarget(); } else { pointDescription = new PointDescription(PointDescription.POINT_TYPE_LOCATION, ""); } return pointDescription; } public void addDestination(LatLon latLon) { if (latLon != null) { if (!OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) { requestedLatLon = latLon; ActivityCompat.requestPermissions(mapActivity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_FOR_ADD_DESTINATION_PERMISSION); } else { PointDescription pointDescription = getPointDescriptionForTarget(latLon); mapActivity.getContextMenu().close(); final TargetPointsHelper targets = mapActivity.getMyApplication().getTargetPointsHelper(); RoutingHelper routingHelper = mapActivity.getMyApplication().getRoutingHelper(); if (routingHelper.isFollowingMode() || routingHelper.isRoutePlanningMode()) { targets.navigateToPoint(latLon, true, targets.getIntermediatePoints().size() + 1, pointDescription); } else if (targets.getIntermediatePoints().isEmpty()) { startRoutePlanningWithDestination(latLon, pointDescription, targets); } } } } public void addFirstIntermediate(LatLon latLon) { if (latLon != null) { RoutingHelper routingHelper = mapActivity.getMyApplication().getRoutingHelper(); if (routingHelper.isFollowingMode() || routingHelper.isRoutePlanningMode()) { PointDescription pointDescription = getPointDescriptionForTarget(latLon); mapActivity.getContextMenu().close(); final TargetPointsHelper targets = mapActivity.getMyApplication().getTargetPointsHelper(); if (routingHelper.isFollowingMode() || routingHelper.isRoutePlanningMode()) { targets.navigateToPoint(latLon, true, 0, pointDescription); } else if (targets.getIntermediatePoints().isEmpty()) { startRoutePlanningWithDestination(latLon, pointDescription, targets); } } else { addDestination(latLon); } } } public void replaceDestination(LatLon latLon) { RoutingHelper routingHelper = mapActivity.getMyApplication().getRoutingHelper(); if (latLon != null) { if (routingHelper.isFollowingMode() || routingHelper.isRoutePlanningMode()) { PointDescription pointDescription = getPointDescriptionForTarget(latLon); mapActivity.getContextMenu().close(); final TargetPointsHelper targets = mapActivity.getMyApplication().getTargetPointsHelper(); targets.navigateToPoint(latLon, true, -1, pointDescription); } else { addDestination(latLon); } } } public void switchToRouteFollowingLayout() { touchEvent = 0; mapActivity.getMyApplication().getRoutingHelper().setRoutePlanningMode(false); mapActivity.getMapViewTrackingUtilities().switchToRoutePlanningMode(); mapActivity.refreshMap(); } public boolean switchToRoutePlanningLayout() { if (!mapActivity.getRoutingHelper().isRoutePlanningMode() && mapActivity.getRoutingHelper().isFollowingMode()) { mapActivity.getRoutingHelper().setRoutePlanningMode(true); mapActivity.getMapViewTrackingUtilities().switchToRoutePlanningMode(); mapActivity.refreshMap(); return true; } return false; } private void initZooms() { final OsmandMapTileView view = mapActivity.getMapView(); View zoomInButton = mapActivity.findViewById(R.id.map_zoom_in_button); mapZoomIn = createHudButton(zoomInButton, R.drawable.map_zoom_in). setIconsId(R.drawable.map_zoom_in, R.drawable.map_zoom_in_night).setRoundTransparent(); controls.add(mapZoomIn); zoomInButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (view.isZooming()) { mapActivity.changeZoom(2, System.currentTimeMillis()); } else { mapActivity.changeZoom(1, System.currentTimeMillis()); } } }); final View.OnLongClickListener listener = MapControlsLayer.getOnClickMagnifierListener(view); zoomInButton.setOnLongClickListener(listener); View zoomOutButton = mapActivity.findViewById(R.id.map_zoom_out_button); mapZoomOut = createHudButton(zoomOutButton, R.drawable.map_zoom_out). setIconsId(R.drawable.map_zoom_out, R.drawable.map_zoom_out_night).setRoundTransparent(); controls.add(mapZoomOut); zoomOutButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mapActivity.changeZoom(-1, System.currentTimeMillis()); } }); zoomOutButton.setOnLongClickListener(listener); } public void startNavigation() { OsmandApplication app = mapActivity.getMyApplication(); RoutingHelper routingHelper = app.getRoutingHelper(); if (routingHelper.isFollowingMode()) { switchToRouteFollowingLayout(); if (app.getSettings().APPLICATION_MODE.get() != routingHelper.getAppMode()) { app.getSettings().APPLICATION_MODE.set(routingHelper.getAppMode()); } } else { if (!app.getTargetPointsHelper().checkPointToNavigateShort()) { mapRouteInfoMenu.show(); } else { touchEvent = 0; app.logEvent(mapActivity, "start_navigation"); app.getSettings().APPLICATION_MODE.set(routingHelper.getAppMode()); mapActivity.getMapViewTrackingUtilities().backToLocationImpl(); app.getSettings().FOLLOW_THE_ROUTE.set(true); routingHelper.setFollowingMode(true); routingHelper.setRoutePlanningMode(false); mapActivity.getMapViewTrackingUtilities().switchToRoutePlanningMode(); app.getRoutingHelper().notifyIfRouteIsCalculated(); routingHelper.setCurrentLocation(app.getLocationProvider().getLastKnownLocation(), false); } } } @Override public void destroyLayer() { controls.clear(); } @Override public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings nightMode) { updateControls(tileBox, nightMode); } @SuppressWarnings("deprecation") private void updateControls(@NonNull RotatedTileBox tileBox, DrawSettings drawSettings) { boolean isNight = drawSettings != null && drawSettings.isNightMode(); int shadw = isNight ? Color.TRANSPARENT : Color.WHITE; int textColor = isNight ? mapActivity.getResources().getColor(R.color.widgettext_night) : Color.BLACK; if (shadowColor != shadw) { shadowColor = shadw; // TODOnightMode // updatextColor(textColor, shadw, rulerControl, zoomControls, mapMenuControls); } // default buttons boolean routePlanningMode = false; RoutingHelper rh = mapActivity.getRoutingHelper(); if (rh.isRoutePlanningMode()) { routePlanningMode = true; } else if ((rh.isRouteCalculated() || rh.isRouteBeingCalculated()) && !rh.isFollowingMode()) { routePlanningMode = true; } boolean routeFollowingMode = !routePlanningMode && rh.isFollowingMode(); boolean routeDialogOpened = MapRouteInfoMenu.isVisible(); boolean trackDialogOpened = TrackDetailsMenu.isVisible(); boolean showRouteCalculationControls = routePlanningMode || ((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode); updateMyLocation(rh, routeDialogOpened || trackDialogOpened); boolean showButtons = (showRouteCalculationControls || !routeFollowingMode) && !isInChangeMarkerPositionMode() && !isInGpxDetailsMode(); //routePlanningBtn.setIconResId(routeFollowingMode ? R.drawable.ic_action_gabout_dark : R.drawable.map_directions); if (rh.isFollowingMode()) { routePlanningBtn.setIconResId(R.drawable.map_start_navigation); routePlanningBtn.setIconColorId(R.color.color_myloc_distance); } else if (routePlanningMode) { routePlanningBtn.setIconResId(R.drawable.map_directions); routePlanningBtn.setIconColorId(R.color.color_myloc_distance); } else { routePlanningBtn.setIconResId(R.drawable.map_directions); routePlanningBtn.resetIconColors(); } routePlanningBtn.updateVisibility(showButtons); menuControl.updateVisibility(showButtons); mapZoomIn.updateVisibility(!routeDialogOpened); mapZoomOut.updateVisibility(!routeDialogOpened); compassHud.updateVisibility(!routeDialogOpened && !trackDialogOpened && shouldShowCompass()); if (layersHud.setIconResId(settings.getApplicationMode().getMapIconId())) { layersHud.update(app, isNight); } layersHud.updateVisibility(!routeDialogOpened && !trackDialogOpened); quickSearchHud.updateVisibility(!routeDialogOpened && !trackDialogOpened); if (!routePlanningMode && !routeFollowingMode) { if (mapView.isZooming()) { lastZoom = System.currentTimeMillis(); } //if (!mapView.isZooming() || !OsmandPlugin.isDevelopment()) { if ((System.currentTimeMillis() - lastZoom > 1000) || !OsmandPlugin.isDevelopment()) { zoomText.setVisibility(View.GONE); } else { zoomText.setVisibility(View.VISIBLE); zoomText.setTextColor(textColor); zoomText.setText(getZoomLevel(tileBox)); } } mapRouteInfoMenu.setVisible(showRouteCalculationControls); updateCompass(isNight); for (MapHudButton mc : controls) { mc.update(mapActivity.getMyApplication(), isNight); } } public void updateCompass(boolean isNight) { float mapRotate = mapActivity.getMapView().getRotate(); boolean showCompass = shouldShowCompass(); if (mapRotate != cachedRotate) { cachedRotate = mapRotate; // Apply animation to image view compassHud.iv.invalidate(); compassHud.updateVisibility(showCompass); } if (settings.ROTATE_MAP.get() == OsmandSettings.ROTATE_MAP_NONE) { compassHud.setIconResId(isNight ? R.drawable.map_compass_niu_white : R.drawable.map_compass_niu); compassHud.iv.setContentDescription(mapActivity.getString(R.string.rotate_map_none_opt)); compassHud.updateVisibility(showCompass); } else if (settings.ROTATE_MAP.get() == OsmandSettings.ROTATE_MAP_BEARING) { compassHud.setIconResId(isNight ? R.drawable.map_compass_bearing_white : R.drawable.map_compass_bearing); compassHud.iv.setContentDescription(mapActivity.getString(R.string.rotate_map_bearing_opt)); compassHud.updateVisibility(true); } else { compassHud.setIconResId(isNight ? R.drawable.map_compass_white : R.drawable.map_compass); compassHud.iv.setContentDescription(mapActivity.getString(R.string.rotate_map_compass_opt)); compassHud.updateVisibility(true); } } private boolean shouldShowCompass() { float mapRotate = mapActivity.getMapView().getRotate(); return forceShowCompass || mapRotate != 0 || settings.ROTATE_MAP.get() != OsmandSettings.ROTATE_MAP_NONE || mapActivity.getMapLayers().getMapInfoLayer().getMapInfoControls().isVisible("compass"); } public CompassDrawable getCompassDrawable(Drawable originalDrawable) { return new CompassDrawable(originalDrawable); } private void updateMyLocation(RoutingHelper rh, boolean dialogOpened) { boolean enabled = mapActivity.getMyApplication().getLocationProvider().getLastKnownLocation() != null; boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation(); if (!enabled) { backToLocationControl.setBg(R.drawable.btn_circle, R.drawable.btn_circle_night); backToLocationControl.setIconColorId(R.color.icon_color, 0); backToLocationControl.iv.setContentDescription(mapActivity.getString(R.string.unknown_location)); } else if (tracked) { backToLocationControl.setBg(R.drawable.btn_circle, R.drawable.btn_circle_night); backToLocationControl.setIconColorId(R.color.color_myloc_distance); backToLocationControl.iv.setContentDescription(mapActivity.getString(R.string.access_map_linked_to_location)); } else { backToLocationControl.setIconColorId(0); backToLocationControl.setBg(R.drawable.btn_circle_blue); backToLocationControl.iv.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc)); } boolean visible = !(tracked && rh.isFollowingMode()); backToLocationControl.updateVisibility(visible && !dialogOpened); if (app.accessibilityEnabled()) { backToLocationControl.iv.setClickable(enabled && visible); } } public boolean onSingleTap(PointF point, RotatedTileBox tileBox) { return mapRouteInfoMenu.onSingleTap(point, tileBox); } @Override public boolean onTouchEvent(MotionEvent event, RotatedTileBox tileBox) { touchEvent = System.currentTimeMillis(); RoutingHelper rh = mapActivity.getRoutingHelper(); if (rh.isFollowingMode()) { mapActivity.refreshMap(); } return false; } // /////////////// Transparency bar ///////////////////////// private void initTransparencyBar() { transparencyBarLayout = (LinearLayout) mapActivity.findViewById(R.id.map_transparency_layout); transparencyBar = (SeekBar) mapActivity.findViewById(R.id.map_transparency_seekbar); transparencyBar.setMax(255); if (transparencySetting != null) { transparencyBar.setProgress(transparencySetting.get()); transparencyBarLayout.setVisibility(View.VISIBLE); } else { transparencyBarLayout.setVisibility(View.GONE); } transparencyBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (transparencySetting != null) { transparencySetting.set(progress); mapActivity.getMapView().refreshMap(); } } }); ImageButton imageButton = (ImageButton) mapActivity.findViewById(R.id.map_transparency_hide); imageButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { transparencyBarLayout.setVisibility(View.GONE); settings.LAYER_TRANSPARENCY_SEEKBAR_MODE.set(LayerTransparencySeekbarMode.OFF); hideTransparencyBar(transparencySetting); } }); LayerTransparencySeekbarMode seekbarMode = settings.LAYER_TRANSPARENCY_SEEKBAR_MODE.get(); if (seekbarMode == LayerTransparencySeekbarMode.OVERLAY && settings.MAP_OVERLAY.get() != null) { showTransparencyBar(settings.MAP_OVERLAY_TRANSPARENCY); setTransparencyBarEnabled(true); } else if (seekbarMode == LayerTransparencySeekbarMode.UNDERLAY && settings.MAP_UNDERLAY.get() != null) { showTransparencyBar(settings.MAP_TRANSPARENCY); setTransparencyBarEnabled(true); } } public void showTransparencyBar(CommonPreference<Integer> transparenPreference) { if (MapControlsLayer.transparencySetting != transparenPreference) { MapControlsLayer.transparencySetting = transparenPreference; if (isTransparencyBarEnabled) { transparencyBarLayout.setVisibility(View.VISIBLE); } transparencyBar.setProgress(transparenPreference.get()); } } public void hideTransparencyBar(CommonPreference<Integer> transparentPreference) { if (transparencySetting == transparentPreference) { transparencyBarLayout.setVisibility(View.GONE); transparencySetting = null; } } public void setTransparencyBarEnabled(boolean isTransparencyBarEnabled) { this.isTransparencyBarEnabled = isTransparencyBarEnabled; if (transparencySetting != null) { if (isTransparencyBarEnabled) { transparencyBarLayout.setVisibility(View.VISIBLE); } else { transparencyBarLayout.setVisibility(View.GONE); } } } private class MapHudButton { View iv; int bgDark; int bgLight; int resId; int resLightId; int resDarkId; int resClrLight = R.color.icon_color; int resClrDark = 0; boolean nightMode = false; boolean f = true; boolean compass; boolean compassOutside; ViewPropertyAnimatorCompat hideAnimator; public MapHudButton setRoundTransparent() { setBg(R.drawable.btn_circle_trans, R.drawable.btn_circle_night); return this; } public MapHudButton setBg(int dayBg, int nightBg) { if (bgDark == nightBg && dayBg == bgLight) { return this; } bgDark = nightBg; bgLight = dayBg; f = true; return this; } public void hideDelayed(long msec) { if (!compassOutside && (iv.getVisibility() == View.VISIBLE)) { if (hideAnimator != null) { hideAnimator.cancel(); } hideAnimator = ViewCompat.animate(iv).alpha(0f).setDuration(250).setStartDelay(msec).setListener(new ViewPropertyAnimatorListener() { @Override public void onAnimationStart(View view) { } @Override public void onAnimationEnd(View view) { iv.setVisibility(View.GONE); ViewCompat.setAlpha(iv, 1f); hideAnimator = null; } @Override public void onAnimationCancel(View view) { iv.setVisibility(View.GONE); ViewCompat.setAlpha(iv, 1f); hideAnimator = null; } }); hideAnimator.start(); } } public void cancelHideAnimation() { if (hideAnimator != null) { hideAnimator.cancel(); } } public boolean updateVisibility(boolean visible) { if (!compassOutside && visible != (iv.getVisibility() == View.VISIBLE)) { if (visible) { if (hideAnimator != null) { hideAnimator.cancel(); } iv.setVisibility(View.VISIBLE); iv.invalidate(); } else if (hideAnimator == null) { if (compass) { hideDelayed(5000); } else { iv.setVisibility(View.GONE); iv.invalidate(); } } return true; } else if (visible && hideAnimator != null) { hideAnimator.cancel(); iv.setVisibility(View.VISIBLE); iv.invalidate(); } return false; } public MapHudButton setBg(int bg) { if (bgDark == bg && bg == bgLight) { return this; } bgDark = bg; bgLight = bg; f = true; return this; } public boolean setIconResId(int resId) { if (this.resId == resId) { return false; } this.resId = resId; f = true; return true; } public boolean resetIconColors() { if (resClrLight == R.color.icon_color && resClrDark == 0) { return false; } resClrLight = R.color.icon_color; resClrDark = 0; f = true; return true; } public MapHudButton setIconColorId(int clr) { if (resClrLight == clr && resClrDark == clr) { return this; } resClrLight = clr; resClrDark = clr; f = true; return this; } public MapHudButton setIconsId(int icnLight, int icnDark) { if (resLightId == icnLight && resDarkId == icnDark) { return this; } resLightId = icnLight; resDarkId = icnDark; f = true; return this; } public MapHudButton setIconColorId(int clrLight, int clrDark) { if (resClrLight == clrLight && resClrDark == clrDark) { return this; } resClrLight = clrLight; resClrDark = clrDark; f = true; return this; } @SuppressLint("NewApi") @SuppressWarnings("deprecation") public void update(OsmandApplication ctx, boolean night) { if (nightMode == night && !f) { return; } f = false; nightMode = night; if (bgDark != 0 && bgLight != 0) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { iv.setBackground(ctx.getResources().getDrawable(night ? bgDark : bgLight, mapActivity.getTheme())); } else { iv.setBackgroundDrawable(ctx.getResources().getDrawable(night ? bgDark : bgLight)); } } Drawable d = null; if (resDarkId != 0 && nightMode) { d = ctx.getIconsCache().getIcon(resDarkId); } else if (resLightId != 0 && !nightMode) { d = ctx.getIconsCache().getIcon(resLightId); } else if (resId != 0) { d = ctx.getIconsCache().getIcon(resId, nightMode ? resClrDark : resClrLight); } if (iv instanceof ImageView) { if (compass) { ((ImageView) iv).setImageDrawable(new CompassDrawable(d)); } else { ((ImageView) iv).setImageDrawable(d); } } else if (iv instanceof TextView) { ((TextView) iv).setCompoundDrawablesWithIntrinsicBounds( d, null, null, null); } } } private String getZoomLevel(@NonNull RotatedTileBox tb) { String zoomText = tb.getZoom() + ""; double frac = tb.getMapDensity(); if (frac != 0) { int ifrac = (int) (frac * 10); zoomText += " "; zoomText += Math.abs(ifrac) / 10; if (ifrac % 10 != 0) { zoomText += "." + Math.abs(ifrac) % 10; } } return zoomText; } public void setMapQuickActionLayer(MapQuickActionLayer mapQuickActionLayer) { this.mapQuickActionLayer = mapQuickActionLayer; } private boolean isInChangeMarkerPositionMode(){ return mapQuickActionLayer == null ? contextMenuLayer.isInChangeMarkerPositionMode() : mapQuickActionLayer.isInChangeMarkerPositionMode() || contextMenuLayer.isInChangeMarkerPositionMode(); } private boolean isInGpxDetailsMode() { return contextMenuLayer.isInGpxDetailsMode(); } public static View.OnLongClickListener getOnClickMagnifierListener(final OsmandMapTileView view) { return new View.OnLongClickListener() { @Override public boolean onLongClick(View notUseCouldBeNull) { final OsmandSettings.OsmandPreference<Float> mapDensity = view.getSettings().MAP_DENSITY; final AlertDialog.Builder bld = new AlertDialog.Builder(view.getContext()); int p = (int) (mapDensity.get() * 100); final TIntArrayList tlist = new TIntArrayList(new int[]{20, 25, 33, 50, 75, 100, 150, 200, 300, 400}); final List<String> values = new ArrayList<>(); int i = -1; for (int k = 0; k <= tlist.size(); k++) { final boolean end = k == tlist.size(); if (i == -1) { if ((end || p < tlist.get(k))) { values.add(p + " %"); i = k; } else if (p == tlist.get(k)) { i = k; } } if (k < tlist.size()) { values.add(tlist.get(k) + " %"); } } if (values.size() != tlist.size()) { tlist.insert(i, p); } bld.setTitle(R.string.map_magnifier); bld.setSingleChoiceItems(values.toArray(new String[values.size()]), i, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { int p = tlist.get(which); mapDensity.set(p / 100.0f); view.setComplexZoom(view.getZoom(), view.getSettingsMapDensity()); MapRendererContext mapContext = NativeCoreContext.getMapRendererContext(); if (mapContext != null) { mapContext.updateMapSettings(); } dialog.dismiss(); } }); bld.show(); return true; } }; } public void selectAddress(String name, double latitude, double longitude, boolean target) { if (name != null) { mapRouteInfoMenu.selectAddress(name, new LatLon(latitude, longitude), target); } else { mapRouteInfoMenu.selectAddress("", new LatLon(latitude, longitude), target); } } public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == REQUEST_LOCATION_FOR_NAVIGATION_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) { onNavigationClick(); } else if (requestCode == REQUEST_LOCATION_FOR_NAVIGATION_FAB_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) { navigateFab(); } else if (requestCode == REQUEST_LOCATION_FOR_ADD_DESTINATION_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) { addDestination(requestedLatLon); } } }