diff --git a/OsmAnd/res/layout-land/map_hud_bottom.xml b/OsmAnd/res/layout-land/map_hud_bottom.xml index e2c6d8556f..cf61fd4d76 100644 --- a/OsmAnd/res/layout-land/map_hud_bottom.xml +++ b/OsmAnd/res/layout-land/map_hud_bottom.xml @@ -133,45 +133,7 @@ - - - - - - - - - - - + diff --git a/OsmAnd/res/layout/map_hud_bottom.xml b/OsmAnd/res/layout/map_hud_bottom.xml index 1fbe5167b0..e76a504d47 100644 --- a/OsmAnd/res/layout/map_hud_bottom.xml +++ b/OsmAnd/res/layout/map_hud_bottom.xml @@ -7,34 +7,6 @@ android:layout_gravity="bottom" android:orientation="vertical"> - - - + diff --git a/OsmAnd/res/layout/map_ruler.xml b/OsmAnd/res/layout/map_ruler.xml index 62f2b1cca4..8f6a66596d 100644 --- a/OsmAnd/res/layout/map_ruler.xml +++ b/OsmAnd/res/layout/map_ruler.xml @@ -3,9 +3,7 @@ android:id="@+id/map_ruler_layout" android:layout_width="@dimen/map_ruler_width" android:layout_height="wrap_content" - android:layout_gravity="bottom" - android:layout_marginStart="@dimen/map_button_margin" - android:layout_marginLeft="@dimen/map_button_margin"> + android:layout_gravity="bottom"> - - + - + android:layout_gravity="bottom"> + + + + + + mainView.getTouchSlop()) { + if (Math.abs(event.getRawY() - mDownY) > touchSlop) { moving = true; } if (moving) { @@ -435,7 +438,9 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment { } }; - ((InterceptorLinearLayout) mainView).setListener(slideTouchListener); + if (mainView instanceof InterceptorLinearLayout) { + ((InterceptorLinearLayout) mainView).setListener(slideTouchListener); + } mainView.setOnTouchListener(slideTouchListener); containerLayoutListener = new OnLayoutChangeListener() { @@ -618,7 +623,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment { } public int getWidth() { - InterceptorLinearLayout mainView = getMainView(); + LinearLayout mainView = getMainView(); if (mainView != null) { return mainView.getWidth(); } else { diff --git a/OsmAnd/src/net/osmand/plus/base/ContextMenuScrollFragment.java b/OsmAnd/src/net/osmand/plus/base/ContextMenuScrollFragment.java new file mode 100644 index 0000000000..6393c76cf5 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/base/ContextMenuScrollFragment.java @@ -0,0 +1,156 @@ +package net.osmand.plus.base; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.activities.MapActivityLayers; +import net.osmand.plus.base.ContextMenuFragment.ContextMenuFragmentListener; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.views.MapControlsLayer; +import net.osmand.plus.views.MapInfoLayer; +import net.osmand.plus.views.OsmandMapTileView; +import net.osmand.plus.views.mapwidgets.widgets.RulerWidget; + +import java.util.Arrays; +import java.util.Collections; + +import static net.osmand.aidlapi.OsmAndCustomizationConstants.BACK_TO_LOC_HUD_ID; +import static net.osmand.aidlapi.OsmAndCustomizationConstants.ZOOM_IN_HUD_ID; +import static net.osmand.aidlapi.OsmAndCustomizationConstants.ZOOM_OUT_HUD_ID; + +public abstract class ContextMenuScrollFragment extends ContextMenuFragment implements ContextMenuFragmentListener { + + public static final String TAG = ContextMenuScrollFragment.class.getSimpleName(); + + private static final String ZOOM_IN_BUTTON_ID = ZOOM_IN_HUD_ID + TAG; + private static final String ZOOM_OUT_BUTTON_ID = ZOOM_OUT_HUD_ID + TAG; + private static final String BACK_TO_LOC_BUTTON_ID = BACK_TO_LOC_HUD_ID + TAG; + + @Nullable + private View mapBottomHudButtons; + + @Nullable + private RulerWidget rulerWidget; + + public float getMiddleStateKoef() { + return 0.5f; + } + + public boolean isShowMapBottomHudButtons() { + return true; + } + + @Override + public int getSupportedMenuStatesPortrait() { + return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN; + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = super.onCreateView(inflater, container, savedInstanceState); + if (view != null) { + setListener(this); + getBottomScrollView().setScrollingEnabled(true); + + mapBottomHudButtons = view.findViewById(R.id.map_controls_container); + if (mapBottomHudButtons != null) { + if (isShowMapBottomHudButtons()) { + setupControlButtons(mapBottomHudButtons); + } else { + AndroidUiHelper.updateVisibility(mapBottomHudButtons, false); + } + } + } + return view; + } + + @Override + public void onContextMenuYPosChanged(@NonNull ContextMenuFragment fragment, int y, boolean needMapAdjust, boolean animated) { + updateMapControlsPos(fragment, y, animated); + } + + @Override + public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState) { + updateMapControlsVisibility(menuState); + } + + @Override + public void onContextMenuDismiss(@NonNull ContextMenuFragment fragment) { + + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + MapActivityLayers mapLayers = mapActivity.getMapLayers(); + + MapControlsLayer mapControlsLayer = mapLayers.getMapControlsLayer(); + mapControlsLayer.removeHudButtons(Arrays.asList(ZOOM_IN_BUTTON_ID, ZOOM_OUT_BUTTON_ID, BACK_TO_LOC_BUTTON_ID)); + + MapInfoLayer mapInfoLayer = mapLayers.getMapInfoLayer(); + mapInfoLayer.removeRulerWidgets(Collections.singletonList(rulerWidget)); + } + } + + private void setupControlButtons(@NonNull View view) { + MapActivity mapActivity = requireMapActivity(); + View zoomInButtonView = view.findViewById(R.id.map_zoom_in_button); + View zoomOutButtonView = view.findViewById(R.id.map_zoom_out_button); + View myLocButtonView = view.findViewById(R.id.map_my_location_button); + View mapRulerView = view.findViewById(R.id.map_ruler_layout); + + MapActivityLayers mapLayers = mapActivity.getMapLayers(); + + OsmandMapTileView mapTileView = mapActivity.getMapView(); + View.OnLongClickListener longClickListener = MapControlsLayer.getOnClickMagnifierListener(mapTileView); + + MapControlsLayer mapControlsLayer = mapLayers.getMapControlsLayer(); + mapControlsLayer.setupZoomInButton(zoomInButtonView, longClickListener, ZOOM_IN_BUTTON_ID); + mapControlsLayer.setupZoomOutButton(zoomOutButtonView, longClickListener, ZOOM_OUT_BUTTON_ID); + mapControlsLayer.setupBackToLocationButton(myLocButtonView, BACK_TO_LOC_BUTTON_ID); + + MapInfoLayer mapInfoLayer = mapLayers.getMapInfoLayer(); + rulerWidget = mapInfoLayer.setupRulerWidget(mapRulerView); + } + + public void updateMapControlsPos(@NonNull ContextMenuFragment fragment, int y, boolean animated) { + View mapControlsView = this.mapBottomHudButtons; + if (mapControlsView != null) { + int zoomY = y - getMapControlsHeight(); + if (animated) { + fragment.animateView(mapControlsView, zoomY); + } else { + mapControlsView.setY(zoomY); + } + } + } + + private int getMapControlsHeight() { + View mapControlsContainer = this.mapBottomHudButtons; + return mapControlsContainer != null ? mapControlsContainer.getHeight() : 0; + } + + private void updateMapControlsVisibility(int menuState) { + if (mapBottomHudButtons != null) { + if (menuState == MenuState.HEADER_ONLY) { + if (mapBottomHudButtons.getVisibility() != View.VISIBLE) { + mapBottomHudButtons.setVisibility(View.VISIBLE); + } + } else { + if (mapBottomHudButtons.getVisibility() == View.VISIBLE) { + mapBottomHudButtons.setVisibility(View.INVISIBLE); + } + } + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java b/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java index 0edc688b29..2f0eee097e 100644 --- a/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java +++ b/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java @@ -18,7 +18,7 @@ import net.osmand.plus.settings.fragments.BaseSettingsFragment; import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapTileView; -import net.osmand.plus.views.mapwidgets.TextInfoWidget; +import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_BUILDS_ID; diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java index 7cb90af938..26e2a136c8 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java @@ -48,8 +48,13 @@ public class SelectedGpxMenuController extends MenuController { @Override public void buttonPressed() { Intent intent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity()); - intent.putExtra(TrackActivity.TRACK_FILE_NAME, selectedGpxPoint.getSelectedGpxFile().getGpxFile().path); - intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + SelectedGpxFile selectedGpxFile = selectedGpxPoint.getSelectedGpxFile(); + if (selectedGpxFile.isShowCurrentTrack()) { + intent.putExtra(TrackActivity.CURRENT_RECORDING, true); + } else { + intent.putExtra(TrackActivity.TRACK_FILE_NAME, selectedGpxFile.getGpxFile().path); + } + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); mapActivity.startActivity(intent); } }; diff --git a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryPlugin.java b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryPlugin.java index ba204f970e..879e3e0184 100644 --- a/OsmAnd/src/net/osmand/plus/mapillary/MapillaryPlugin.java +++ b/OsmAnd/src/net/osmand/plus/mapillary/MapillaryPlugin.java @@ -35,7 +35,7 @@ import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.MapTileLayer; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.MapWidgetRegInfo; -import net.osmand.plus.views.mapwidgets.TextInfoWidget; +import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; import net.osmand.util.Algorithms; import java.text.MessageFormat; diff --git a/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java b/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java index 7ad66f4c95..22e18c0262 100644 --- a/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java +++ b/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java @@ -46,7 +46,7 @@ import net.osmand.plus.settings.fragments.BaseSettingsFragment; import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapTileView; -import net.osmand.plus.views.mapwidgets.TextInfoWidget; +import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; import net.osmand.util.Algorithms; import java.lang.ref.WeakReference; diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java index 66b212960d..5aac6fc2dc 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java @@ -59,7 +59,6 @@ import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference; import net.osmand.plus.track.GpxSplitType; -import net.osmand.plus.track.SplitIntervalCard; import net.osmand.plus.track.SplitTrackAsyncTask; import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener; import net.osmand.plus.widgets.tools.CropCircleTransformation; @@ -830,14 +829,14 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { if (model.size() > 0) { if (distance) { double dvalue = OsmAndFormatter.calculateRoundedDist(value, app); - options.add(SplitIntervalCard.getFormattedDistanceInterval(app, value)); + options.add(OsmAndFormatter.getFormattedDistanceInterval(app, value)); distanceSplit.add(dvalue); timeSplit.add(-1); if (Math.abs(model.get(0).getSplitDistance() - dvalue) < 1) { selectedSplitInterval = distanceSplit.size() - 1; } } else { - options.add(SplitIntervalCard.getFormattedTimeInterval(app, value)); + options.add(OsmAndFormatter.getFormattedTimeInterval(app, value)); distanceSplit.add(-1d); timeSplit.add(value); if (model.get(0).getSplitTime() == value) { diff --git a/OsmAnd/src/net/osmand/plus/notifications/NavigationNotification.java b/OsmAnd/src/net/osmand/plus/notifications/NavigationNotification.java index 71d3cbe0f7..d0632d812a 100644 --- a/OsmAnd/src/net/osmand/plus/notifications/NavigationNotification.java +++ b/OsmAnd/src/net/osmand/plus/notifications/NavigationNotification.java @@ -28,7 +28,7 @@ import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.views.TurnPathHelper; -import net.osmand.plus.views.mapwidgets.NextTurnInfoWidget.TurnDrawable; +import net.osmand.plus.views.mapwidgets.TurnDrawable; import net.osmand.router.TurnType; import net.osmand.util.Algorithms; diff --git a/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java index a6ea74f36d..b910ca75e0 100644 --- a/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java +++ b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java @@ -40,7 +40,7 @@ import net.osmand.plus.views.AnimateDraggingMapThread; import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapTileView; -import net.osmand.plus.views.mapwidgets.TextInfoWidget; +import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; import java.text.SimpleDateFormat; import java.util.ArrayList; diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java index 205993a316..e9161ec96c 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java @@ -1,6 +1,5 @@ package net.osmand.plus.routepreparationmenu; -import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Context; @@ -28,7 +27,6 @@ import androidx.annotation.Nullable; import androidx.appcompat.view.ContextThemeWrapper; import androidx.appcompat.widget.AppCompatImageButton; import androidx.appcompat.widget.AppCompatImageView; -import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; @@ -36,15 +34,12 @@ import androidx.viewpager.widget.ViewPager; import net.osmand.AndroidUtils; import net.osmand.GPXUtilities; -import net.osmand.Location; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.LockableViewPager; import net.osmand.plus.OsmAndFormatter; -import net.osmand.plus.OsmAndLocationProvider; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivityActions; @@ -60,6 +55,8 @@ import net.osmand.plus.routepreparationmenu.cards.PublicTransportCard; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.TransportRoutingHelper; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.views.MapControlsLayer; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.router.TransportRoutePlanner.TransportRouteResult; import net.osmand.util.Algorithms; @@ -71,10 +68,15 @@ import java.io.IOException; import java.lang.ref.WeakReference; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Locale; +import static net.osmand.aidlapi.OsmAndCustomizationConstants.BACK_TO_LOC_HUD_ID; +import static net.osmand.aidlapi.OsmAndCustomizationConstants.ZOOM_IN_HUD_ID; +import static net.osmand.aidlapi.OsmAndCustomizationConstants.ZOOM_OUT_HUD_ID; + public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMenuFragmentListener, RouteDetailsFragmentListener { @@ -84,18 +86,19 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe public static final String INITIAL_MENU_STATE_KEY = "initial_menu_state_key"; public static final String ADJUST_MAP_KEY = "adjust_map_key"; + private static final String ZOOM_IN_BUTTON_ID = ZOOM_IN_HUD_ID + TAG; + private static final String ZOOM_OUT_BUTTON_ID = ZOOM_OUT_HUD_ID + TAG; + private static final String BACK_TO_LOC_BUTTON_ID = BACK_TO_LOC_HUD_ID + TAG; + @Nullable private LockableViewPager viewPager; protected List> routeDetailsFragments = new ArrayList<>(); @Nullable private View solidToolbarView; - private int solidToolbarHeight; @Nullable private View zoomButtonsView; @Nullable - private ImageButton myLocButtonView; - @Nullable private ViewGroup pagesView; private boolean portrait; @@ -139,7 +142,6 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe AndroidUtils.addStatusBarPadding21v(mapActivity, view); View solidToolbarView = view.findViewById(R.id.toolbar_layout); this.solidToolbarView = solidToolbarView; - solidToolbarHeight = getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar); LockableViewPager viewPager = view.findViewById(R.id.pager); this.viewPager = viewPager; if (!portrait) { @@ -241,6 +243,17 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe } } + @Override + public void onDestroyView() { + super.onDestroyView(); + + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + MapControlsLayer mapControlsLayer = mapActivity.getMapLayers().getMapControlsLayer(); + mapControlsLayer.removeHudButtons(Arrays.asList(ZOOM_IN_BUTTON_ID, ZOOM_OUT_BUTTON_ID, BACK_TO_LOC_BUTTON_ID)); + } + } + @Override public int getStatusBarColorId() { View view = getView(); @@ -345,98 +358,27 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe } private void buildZoomButtons(@NonNull View view) { - OsmandApplication app = requireMyApplication(); - // Zoom buttons - View zoomButtonsView = view.findViewById(R.id.map_hud_controls); - this.zoomButtonsView = zoomButtonsView; - ImageButton zoomInButtonView = (ImageButton) view.findViewById(R.id.map_zoom_in_button); - ImageButton zoomOutButtonView = (ImageButton) view.findViewById(R.id.map_zoom_out_button); - ImageButton myLocButtonView = (ImageButton) view.findViewById(R.id.map_my_location_button); - this.myLocButtonView = myLocButtonView; - AndroidUtils.updateImageButton(app, zoomInButtonView, R.drawable.ic_zoom_in, R.drawable.ic_zoom_in, - R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode); - AndroidUtils.updateImageButton(app, zoomOutButtonView, R.drawable.ic_zoom_out, R.drawable.ic_zoom_out, - R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode); - zoomInButtonView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - doZoomIn(); - } - }); - zoomOutButtonView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - doZoomOut(); - } - }); - - myLocButtonView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - if (OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) { - mapActivity.getMapViewTrackingUtilities().backToLocationImpl(); - } else { - ActivityCompat.requestPermissions(mapActivity, - new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, - OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION); - } - } - } - }); - updateMyLocation(); - - zoomButtonsView.setVisibility(View.VISIBLE); - } - - private void updateMyLocation() { MapActivity mapActivity = getMapActivity(); if (mapActivity == null) { return; } - OsmandApplication app = mapActivity.getMyApplication(); - Location lastKnownLocation = app.getLocationProvider().getLastKnownLocation(); - boolean enabled = lastKnownLocation != null; - boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation(); + // Zoom buttons + View zoomButtonsView = view.findViewById(R.id.map_hud_controls); + this.zoomButtonsView = zoomButtonsView; - ImageButton myLocButtonView = this.myLocButtonView; - if (myLocButtonView != null) { - if (!enabled) { - myLocButtonView.setImageDrawable(getIcon(R.drawable.ic_my_location, R.color.icon_color_default_light)); - AndroidUtils.setBackground(app, myLocButtonView, nightMode, R.drawable.btn_circle, R.drawable.btn_circle_night); - myLocButtonView.setContentDescription(mapActivity.getString(R.string.unknown_location)); - } else if (tracked) { - myLocButtonView.setImageDrawable(getIcon(R.drawable.ic_my_location, R.color.color_myloc_distance)); - AndroidUtils.setBackground(app, myLocButtonView, nightMode, R.drawable.btn_circle, R.drawable.btn_circle_night); - } else { - myLocButtonView.setImageResource(R.drawable.ic_my_location); - AndroidUtils.setBackground(app, myLocButtonView, nightMode, R.drawable.btn_circle_blue, R.drawable.btn_circle_blue); - myLocButtonView.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc)); - } - if (app.accessibilityEnabled()) { - myLocButtonView.setClickable(enabled && !tracked && app.getRoutingHelper().isFollowingMode()); - } - } - } + ImageButton zoomInButton = view.findViewById(R.id.map_zoom_in_button); + ImageButton zoomOutButton = view.findViewById(R.id.map_zoom_out_button); + ImageButton backToLocation = view.findViewById(R.id.map_my_location_button); - public void doZoomIn() { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - OsmandMapTileView map = mapActivity.getMapView(); - if (map.isZooming() && map.hasCustomMapRatio()) { - mapActivity.changeZoom(2, System.currentTimeMillis()); - } else { - mapActivity.changeZoom(1, System.currentTimeMillis()); - } - } - } + OsmandMapTileView mapTileView = mapActivity.getMapView(); + View.OnLongClickListener longClickListener = MapControlsLayer.getOnClickMagnifierListener(mapTileView); + MapControlsLayer mapControlsLayer = mapActivity.getMapLayers().getMapControlsLayer(); - public void doZoomOut() { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - mapActivity.changeZoom(-1, System.currentTimeMillis()); - } + mapControlsLayer.setupZoomInButton(zoomInButton, longClickListener, ZOOM_IN_BUTTON_ID); + mapControlsLayer.setupZoomOutButton(zoomOutButton, longClickListener, ZOOM_OUT_BUTTON_ID); + mapControlsLayer.setupBackToLocationButton(backToLocation, BACK_TO_LOC_BUTTON_ID); + + AndroidUiHelper.updateVisibility(zoomButtonsView, true); } private void updateZoomButtonsVisibility(int menuState) { diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java index 9bcb3fbea5..fced15daa2 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java @@ -56,7 +56,6 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.TargetPointsHelper.TargetPoint; @@ -67,7 +66,6 @@ import net.osmand.plus.helpers.FontCache; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; -import net.osmand.plus.mapcontextmenu.InterceptorLinearLayout; import net.osmand.plus.mapcontextmenu.CollapsableView; import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu; import net.osmand.plus.render.MapRenderRepositories; @@ -83,6 +81,7 @@ import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.TransportRoutingHelper; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.transport.TransportStopRoute; import net.osmand.plus.widgets.TextViewEx; import net.osmand.plus.widgets.style.CustomTypefaceSpan; @@ -315,7 +314,7 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT statisticCard = new RouteStatisticCard(mapActivity, gpx, new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent ev) { - InterceptorLinearLayout mainView = getMainView(); + LinearLayout mainView = getMainView(); if (mainView != null) { mainView.requestDisallowInterceptTouchEvent(true); } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteDirectionsCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteDirectionsCard.java index 0cfd66129e..666f6b7955 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteDirectionsCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteDirectionsCard.java @@ -18,7 +18,7 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.routepreparationmenu.RouteDetailsFragment; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.views.TurnPathHelper; -import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory; +import net.osmand.plus.views.mapwidgets.LanesDrawable; import net.osmand.util.Algorithms; import java.util.List; @@ -80,7 +80,7 @@ public class RouteDirectionsCard extends BaseCard { int[] lanes = model.getTurnType().getLanes(); if (lanes != null){ - RouteInfoWidgetsFactory.LanesDrawable lanesDrawable = new RouteInfoWidgetsFactory.LanesDrawable(mapActivity,1); + LanesDrawable lanesDrawable = new LanesDrawable(mapActivity,1); lanesDrawable.lanes = lanes; lanesDrawable.isTurnByTurn = true; lanesDrawable.isNightMode = nightMode; diff --git a/OsmAnd/src/net/osmand/plus/track/SplitIntervalBottomSheet.java b/OsmAnd/src/net/osmand/plus/track/SplitIntervalBottomSheet.java index e8728d6003..e102dfffa9 100644 --- a/OsmAnd/src/net/osmand/plus/track/SplitIntervalBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/track/SplitIntervalBottomSheet.java @@ -34,7 +34,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import static net.osmand.plus.track.TrackDrawInfo.TRACK_FILE_PATH; +import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME; public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment { @@ -75,7 +75,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment { } Bundle arguments = getArguments(); if (savedInstanceState != null) { - String gpxFilePath = savedInstanceState.getString(TRACK_FILE_PATH); + String gpxFilePath = savedInstanceState.getString(TRACK_FILE_NAME); selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); prepareSplitIntervalOptions(); @@ -83,7 +83,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment { selectedDistanceSplitInterval = savedInstanceState.getInt(SELECTED_DISTANCE_SPLIT_INTERVAL); selectedSplitType = GpxSplitType.valueOf(savedInstanceState.getString(SELECTED_TRACK_SPLIT_TYPE)); } else if (arguments != null) { - String gpxFilePath = arguments.getString(TRACK_FILE_PATH); + String gpxFilePath = arguments.getString(TRACK_FILE_NAME); selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); prepareSplitIntervalOptions(); updateSelectedSplitParams(); @@ -142,7 +142,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment { outState.putInt(SELECTED_TIME_SPLIT_INTERVAL, selectedTimeSplitInterval); outState.putInt(SELECTED_DISTANCE_SPLIT_INTERVAL, selectedDistanceSplitInterval); outState.putString(SELECTED_TRACK_SPLIT_TYPE, selectedSplitType.name()); - outState.putString(TRACK_FILE_PATH, selectedGpxFile.getGpxFile().path); + outState.putString(TRACK_FILE_NAME, selectedGpxFile.getGpxFile().path); } private void updateSelectedSplitParams() { @@ -188,7 +188,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment { private void addDistanceOptionSplit(int value, @NonNull List displayGroups) { if (displayGroups.size() > 0) { double dvalue = OsmAndFormatter.calculateRoundedDist(value, app); - String formattedDist = SplitIntervalCard.getFormattedDistanceInterval(app, value); + String formattedDist = OsmAndFormatter.getFormattedDistanceInterval(app, value); distanceSplitOptions.put(formattedDist, dvalue); if (Math.abs(displayGroups.get(0).getSplitDistance() - dvalue) < 1) { selectedDistanceSplitInterval = distanceSplitOptions.size() - 1; @@ -198,7 +198,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment { private void addTimeOptionSplit(int value, @NonNull List model) { if (model.size() > 0) { - String time = SplitIntervalCard.getFormattedTimeInterval(app, value); + String time = OsmAndFormatter.getFormattedTimeInterval(app, value); timeSplitOptions.put(time, value); if (model.get(0).getSplitTime() == value) { selectedTimeSplitInterval = timeSplitOptions.size() - 1; @@ -327,7 +327,7 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment { try { if (fragmentManager.findFragmentByTag(SplitIntervalBottomSheet.TAG) == null) { Bundle args = new Bundle(); - args.putString(TRACK_FILE_PATH, trackDrawInfo.getFilePath()); + args.putString(TRACK_FILE_NAME, trackDrawInfo.getFilePath()); SplitIntervalBottomSheet splitIntervalBottomSheet = new SplitIntervalBottomSheet(); splitIntervalBottomSheet.setArguments(args); diff --git a/OsmAnd/src/net/osmand/plus/track/SplitIntervalCard.java b/OsmAnd/src/net/osmand/plus/track/SplitIntervalCard.java index 377185e714..2382aad05d 100644 --- a/OsmAnd/src/net/osmand/plus/track/SplitIntervalCard.java +++ b/OsmAnd/src/net/osmand/plus/track/SplitIntervalCard.java @@ -11,7 +11,6 @@ import androidx.annotation.NonNull; import net.osmand.AndroidUtils; import net.osmand.plus.OsmAndFormatter; -import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.AndroidUiHelper; @@ -68,25 +67,10 @@ public class SplitIntervalCard extends BaseCard { if (splitInterval == 0) { intervalStr = GpxSplitType.NO_SPLIT.getHumanString(app); } else if (trackDrawInfo.getSplitType() == GpxSplitType.DISTANCE.getType()) { - intervalStr = getFormattedDistanceInterval(app, trackDrawInfo.getSplitInterval()); + intervalStr = OsmAndFormatter.getFormattedDistanceInterval(app, trackDrawInfo.getSplitInterval()); } else if (trackDrawInfo.getSplitType() == GpxSplitType.TIME.getType()) { - intervalStr = getFormattedTimeInterval(app, splitInterval); + intervalStr = OsmAndFormatter.getFormattedTimeInterval(app, splitInterval); } return intervalStr; } - - public static String getFormattedTimeInterval(OsmandApplication app, double interval) { - if (interval < 60) { - return interval + " " + app.getString(R.string.int_seconds); - } else if (interval % 60 == 0) { - return (interval / 60) + " " + app.getString(R.string.int_min); - } else { - return (interval / 60f) + " " + app.getString(R.string.int_min); - } - } - - public static String getFormattedDistanceInterval(OsmandApplication app, double interval) { - double roundedDist = OsmAndFormatter.calculateRoundedDist(interval, app); - return OsmAndFormatter.getFormattedDistance((float) roundedDist, app); - } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java index faaa96cf52..8861e3fee2 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackAppearanceFragment.java @@ -1,6 +1,5 @@ package net.osmand.plus.track; -import android.Manifest; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.AsyncTask; @@ -11,41 +10,35 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.app.ActivityCompat; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import net.osmand.AndroidUtils; import net.osmand.GPXUtilities.GPXFile; -import net.osmand.Location; import net.osmand.PlatformUtil; import net.osmand.data.QuadRect; import net.osmand.data.RotatedTileBox; import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; -import net.osmand.plus.OsmAndLocationProvider; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities.DialogButtonType; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.base.ContextMenuFragment; -import net.osmand.plus.base.ContextMenuFragment.ContextMenuFragmentListener; +import net.osmand.plus.base.ContextMenuScrollFragment; import net.osmand.plus.dialogs.GpxAppearanceAdapter; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener; -import net.osmand.plus.views.OsmandMapTileView; import net.osmand.render.RenderingRulesStorage; import net.osmand.util.Algorithms; @@ -55,19 +48,21 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING; +import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME; import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR; import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_BOLD; import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_MEDIUM; -import static net.osmand.plus.track.TrackDrawInfo.TRACK_FILE_PATH; -public class TrackAppearanceFragment extends ContextMenuFragment implements CardListener, ContextMenuFragmentListener { +public class TrackAppearanceFragment extends ContextMenuScrollFragment implements CardListener { - public static final String TAG = TrackAppearanceFragment.class.getName(); + public static final String TAG = TrackAppearanceFragment.class.getSimpleName(); private static final Log log = PlatformUtil.getLog(TrackAppearanceFragment.class); private OsmandApplication app; + @Nullable private GpxDataItem gpxDataItem; private TrackDrawInfo trackDrawInfo; private SelectedGpxFile selectedGpxFile; @@ -80,8 +75,6 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card private SplitIntervalCard splitIntervalCard; private ImageView appearanceIcon; - private View zoomButtonsView; - private ImageButton myLocButtonView; @Override public int getMainLayoutId() { @@ -118,16 +111,32 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card Bundle arguments = getArguments(); if (savedInstanceState != null) { - trackDrawInfo = new TrackDrawInfo(); - trackDrawInfo.readBundle(savedInstanceState); - gpxDataItem = app.getGpxDbHelper().getItem(new File(trackDrawInfo.getFilePath())); - selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(trackDrawInfo.getFilePath()); + trackDrawInfo = new TrackDrawInfo(savedInstanceState); + if (trackDrawInfo.isCurrentRecording()) { + selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); + } else { + selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(trackDrawInfo.getFilePath()); + } + if (!selectedGpxFile.isShowCurrentTrack()) { + gpxDataItem = app.getGpxDbHelper().getItem(new File(trackDrawInfo.getFilePath())); + } } else if (arguments != null) { - String gpxFilePath = arguments.getString(TRACK_FILE_PATH); - selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); - File file = new File(selectedGpxFile.getGpxFile().path); - gpxDataItem = app.getGpxDbHelper().getItem(file); - trackDrawInfo = new TrackDrawInfo(gpxDataItem); + String gpxFilePath = arguments.getString(TRACK_FILE_NAME); + boolean currentRecording = arguments.getBoolean(CURRENT_RECORDING, false); + + if (gpxFilePath == null && !currentRecording) { + log.error("Required extra '" + TRACK_FILE_NAME + "' is missing"); + dismiss(); + return; + } + if (currentRecording) { + trackDrawInfo = new TrackDrawInfo(true); + selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); + } else { + gpxDataItem = app.getGpxDbHelper().getItem(new File(gpxFilePath)); + trackDrawInfo = new TrackDrawInfo(gpxDataItem, false); + selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); + } updateTrackColor(); } } @@ -155,7 +164,6 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card View view = super.onCreateView(inflater, container, savedInstanceState); if (view != null) { appearanceIcon = view.findViewById(R.id.appearance_icon); - setListener(this); if (isPortrait()) { updateCardsLayout(); @@ -169,7 +177,6 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card params.gravity = Gravity.BOTTOM | Gravity.START; view.findViewById(R.id.control_buttons).setLayoutParams(params); } - buildZoomButtons(view); enterTrackAppearanceMode(); runLayoutListener(); } @@ -196,21 +203,6 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card updateStatusBarColor(); } - @Override - public void onContextMenuYPosChanged(@NonNull ContextMenuFragment fragment, int y, boolean needMapAdjust, boolean animated) { - updateZoomButtonsPos(fragment, y, animated); - } - - @Override - public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState) { - updateZoomButtonsVisibility(menuState); - } - - @Override - public void onContextMenuDismiss(@NonNull ContextMenuFragment fragment) { - - } - @Override public void onResume() { super.onResume(); @@ -333,130 +325,6 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card return y; } - private void buildZoomButtons(@NonNull View view) { - OsmandApplication app = requireMyApplication(); - this.zoomButtonsView = view.findViewById(R.id.map_hud_controls); - ImageButton zoomInButtonView = (ImageButton) view.findViewById(R.id.map_zoom_in_button); - ImageButton zoomOutButtonView = (ImageButton) view.findViewById(R.id.map_zoom_out_button); - AndroidUtils.updateImageButton(app, zoomInButtonView, R.drawable.ic_zoom_in, R.drawable.ic_zoom_in, - R.drawable.btn_circle_trans, R.drawable.btn_circle_night, isNightMode()); - AndroidUtils.updateImageButton(app, zoomOutButtonView, R.drawable.ic_zoom_out, R.drawable.ic_zoom_out, - R.drawable.btn_circle_trans, R.drawable.btn_circle_night, isNightMode()); - zoomInButtonView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - doZoomIn(); - } - }); - zoomOutButtonView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - doZoomOut(); - } - }); - - myLocButtonView = (ImageButton) view.findViewById(R.id.map_my_location_button); - myLocButtonView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - if (OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) { - mapActivity.getMapViewTrackingUtilities().backToLocationImpl(); - } else { - ActivityCompat.requestPermissions(mapActivity, - new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, - OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION); - } - } - } - }); - updateMyLocation(); - - zoomButtonsView.setVisibility(View.VISIBLE); - } - - private void updateMyLocation() { - MapActivity mapActivity = getMapActivity(); - if (mapActivity == null) { - return; - } - OsmandApplication app = mapActivity.getMyApplication(); - Location lastKnownLocation = app.getLocationProvider().getLastKnownLocation(); - boolean enabled = lastKnownLocation != null; - boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation(); - - ImageButton myLocButtonView = this.myLocButtonView; - if (myLocButtonView != null) { - if (!enabled) { - myLocButtonView.setImageDrawable(getIcon(R.drawable.ic_my_location, R.color.icon_color_default_light)); - AndroidUtils.setBackground(app, myLocButtonView, isNightMode(), R.drawable.btn_circle, R.drawable.btn_circle_night); - myLocButtonView.setContentDescription(mapActivity.getString(R.string.unknown_location)); - } else if (tracked) { - myLocButtonView.setImageDrawable(getIcon(R.drawable.ic_my_location, R.color.color_myloc_distance)); - AndroidUtils.setBackground(app, myLocButtonView, isNightMode(), R.drawable.btn_circle, R.drawable.btn_circle_night); - } else { - myLocButtonView.setImageResource(R.drawable.ic_my_location); - AndroidUtils.setBackground(app, myLocButtonView, isNightMode(), R.drawable.btn_circle_blue, R.drawable.btn_circle_blue); - myLocButtonView.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc)); - } - if (app.accessibilityEnabled()) { - myLocButtonView.setClickable(enabled && !tracked && app.getRoutingHelper().isFollowingMode()); - } - } - } - - public void updateZoomButtonsPos(@NonNull ContextMenuFragment fragment, int y, boolean animated) { - View zoomButtonsView = this.zoomButtonsView; - if (zoomButtonsView != null) { - int zoomY = y - getZoomButtonsHeight(); - if (animated) { - fragment.animateView(zoomButtonsView, zoomY); - } else { - zoomButtonsView.setY(zoomY); - } - } - } - - private int getZoomButtonsHeight() { - View zoomButtonsView = this.zoomButtonsView; - return zoomButtonsView != null ? zoomButtonsView.getHeight() : 0; - } - - public void doZoomIn() { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - OsmandMapTileView map = mapActivity.getMapView(); - if (map.isZooming() && map.hasCustomMapRatio()) { - mapActivity.changeZoom(2, System.currentTimeMillis()); - } else { - mapActivity.changeZoom(1, System.currentTimeMillis()); - } - } - } - - public void doZoomOut() { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - mapActivity.changeZoom(-1, System.currentTimeMillis()); - } - } - - private void updateZoomButtonsVisibility(int menuState) { - View zoomButtonsView = this.zoomButtonsView; - if (zoomButtonsView != null) { - if (menuState == MenuState.HEADER_ONLY) { - if (zoomButtonsView.getVisibility() != View.VISIBLE) { - zoomButtonsView.setVisibility(View.VISIBLE); - } - } else { - if (zoomButtonsView.getVisibility() == View.VISIBLE) { - zoomButtonsView.setVisibility(View.INVISIBLE); - } - } - } - } - private void updateAppearanceIcon() { Drawable icon = getTrackIcon(app, trackDrawInfo.getWidth(), trackDrawInfo.isShowArrows(), trackDrawInfo.getColor()); appearanceIcon.setImageDrawable(icon); @@ -535,7 +403,7 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card cancelButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - discardChanges(); + discardSplitChanges(); FragmentActivity activity = getActivity(); if (activity != null) { activity.onBackPressed(); @@ -570,15 +438,21 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card gpxFile.setShowArrows(trackDrawInfo.isShowArrows()); gpxFile.setShowStartFinish(trackDrawInfo.isShowStartFinish()); - app.getSelectedGpxHelper().updateSelectedGpxFile(selectedGpxFile); - - gpxDataItem = new GpxDataItem(new File(gpxFile.path), gpxFile); - app.getGpxDbHelper().add(gpxDataItem); - saveGpx(gpxFile); + if (gpxFile.showCurrentTrack) { + app.getSettings().CURRENT_TRACK_COLOR.set(trackDrawInfo.getColor()); + } else { + if (gpxDataItem != null) { + gpxDataItem = new GpxDataItem(new File(gpxFile.path), gpxFile); + app.getGpxDbHelper().add(gpxDataItem); + } + app.getSelectedGpxHelper().updateSelectedGpxFile(selectedGpxFile); + saveGpx(gpxFile); + } } - private void discardChanges() { - if (gpxDataItem.getSplitType() != trackDrawInfo.getSplitType() || gpxDataItem.getSplitInterval() != trackDrawInfo.getSplitInterval()) { + private void discardSplitChanges() { + if (gpxDataItem != null && (gpxDataItem.getSplitType() != trackDrawInfo.getSplitType() + || gpxDataItem.getSplitInterval() != trackDrawInfo.getSplitInterval())) { int timeSplit = (int) gpxDataItem.getSplitInterval(); double distanceSplit = gpxDataItem.getSplitInterval(); @@ -640,9 +514,11 @@ public class TrackAppearanceFragment extends ContextMenuFragment implements Card ViewGroup cardsContainer = getCardsContainer(); cardsContainer.removeAllViews(); - splitIntervalCard = new SplitIntervalCard(mapActivity, trackDrawInfo); - splitIntervalCard.setListener(this); - cardsContainer.addView(splitIntervalCard.build(mapActivity)); + if (!selectedGpxFile.isShowCurrentTrack()) { + splitIntervalCard = new SplitIntervalCard(mapActivity, trackDrawInfo); + splitIntervalCard.setListener(this); + cardsContainer.addView(splitIntervalCard.build(mapActivity)); + } DirectionArrowsCard directionArrowsCard = new DirectionArrowsCard(mapActivity, trackDrawInfo); directionArrowsCard.setListener(this); diff --git a/OsmAnd/src/net/osmand/plus/track/TrackDrawInfo.java b/OsmAnd/src/net/osmand/plus/track/TrackDrawInfo.java index d915e8c519..9773ddd329 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackDrawInfo.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackDrawInfo.java @@ -7,9 +7,11 @@ import androidx.annotation.NonNull; import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.util.Algorithms; +import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING; +import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME; + public class TrackDrawInfo { - public static final String TRACK_FILE_PATH = "track_file_path"; private static final String TRACK_WIDTH = "track_width"; private static final String TRACK_GRADIENT_SCALE_TYPE = "track_gradient_scale_type"; private static final String TRACK_COLOR = "track_color"; @@ -27,13 +29,18 @@ public class TrackDrawInfo { private double splitInterval; private boolean joinSegments; private boolean showArrows; - private boolean showStartFinish; - - public TrackDrawInfo() { + private boolean showStartFinish = true; + private boolean currentRecording; + public TrackDrawInfo(boolean currentRecording) { + this.currentRecording = currentRecording; } - public TrackDrawInfo(GpxDataItem gpxDataItem) { + public TrackDrawInfo(Bundle bundle) { + readBundle(bundle); + } + + public TrackDrawInfo(GpxDataItem gpxDataItem, boolean currentRecording) { filePath = gpxDataItem.getFile().getPath(); width = gpxDataItem.getWidth(); gradientScaleType = gpxDataItem.getGradientScaleType(); @@ -43,6 +50,7 @@ public class TrackDrawInfo { joinSegments = gpxDataItem.isJoinSegments(); showArrows = gpxDataItem.isShowArrows(); showStartFinish = gpxDataItem.isShowStartFinish(); + this.currentRecording = currentRecording; } public String getFilePath() { @@ -105,8 +113,12 @@ public class TrackDrawInfo { return showStartFinish; } - protected void readBundle(@NonNull Bundle bundle) { - filePath = bundle.getString(TRACK_FILE_PATH); + public boolean isCurrentRecording() { + return currentRecording; + } + + private void readBundle(@NonNull Bundle bundle) { + filePath = bundle.getString(TRACK_FILE_NAME); width = bundle.getString(TRACK_WIDTH); String gradientScaleTypeName = bundle.getString(TRACK_GRADIENT_SCALE_TYPE); if (!Algorithms.isEmpty(gradientScaleTypeName)) { @@ -118,10 +130,11 @@ public class TrackDrawInfo { joinSegments = bundle.getBoolean(TRACK_JOIN_SEGMENTS); showArrows = bundle.getBoolean(TRACK_SHOW_ARROWS); showStartFinish = bundle.getBoolean(TRACK_SHOW_START_FINISH); + currentRecording = bundle.getBoolean(CURRENT_RECORDING); } protected void saveToBundle(@NonNull Bundle bundle) { - bundle.putString(TRACK_FILE_PATH, filePath); + bundle.putString(TRACK_FILE_NAME, filePath); bundle.putString(TRACK_WIDTH, width); bundle.putString(TRACK_GRADIENT_SCALE_TYPE, gradientScaleType != null ? gradientScaleType.getTypeName() : ""); bundle.putInt(TRACK_COLOR, color); @@ -130,5 +143,6 @@ public class TrackDrawInfo { bundle.putBoolean(TRACK_JOIN_SEGMENTS, joinSegments); bundle.putBoolean(TRACK_SHOW_ARROWS, showArrows); bundle.putBoolean(TRACK_SHOW_START_FINISH, showStartFinish); + bundle.putBoolean(CURRENT_RECORDING, currentRecording); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java index 922fbba961..9e16b28060 100644 --- a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java @@ -1,11 +1,11 @@ package net.osmand.plus.views; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; +import android.graphics.Paint.Cap; import android.graphics.Paint.Style; import android.graphics.PointF; import android.graphics.PorterDuff.Mode; @@ -50,6 +50,7 @@ import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.Sele import net.osmand.plus.mapcontextmenu.other.TrackChartPoints; import net.osmand.plus.render.OsmandRenderer; import net.osmand.plus.render.OsmandRenderer.RenderingContext; +import net.osmand.plus.render.RenderingIcons; import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference; import net.osmand.plus.track.SaveGpxAsyncTask; import net.osmand.plus.track.TrackDrawInfo; @@ -78,6 +79,8 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM private static final Log log = PlatformUtil.getLog(GPXLayer.class); private static final double TOUCH_RADIUS_MULTIPLIER = 1.5; + private static final double DIRECTION_ARROW_DISTANCE_MULTIPLIER = 10.0; + private static final float DIRECTION_ARROW_CIRCLE_MULTIPLIER = 1.5f; private static final int DEFAULT_WIDTH_MULTIPLIER = 7; private static final int START_ZOOM = 7; @@ -200,7 +203,11 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM grayColor = ContextCompat.getColor(view.getApplication(), R.color.color_favorite_gray); wayContext = new GeometryWayContext(view.getContext(), view.getDensity()); - arrowBitmap = BitmapFactory.decodeResource(view.getApplication().getResources(), R.drawable.map_route_direction_arrow, null); + + Paint paint = wayContext.getPaintIcon(); + paint.setStrokeCap(Cap.ROUND); + + arrowBitmap = RenderingIcons.getBitmapFromVectorDrawable(view.getContext(), R.drawable.mm_special_arrow_up); } @Override @@ -415,15 +422,21 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } if (showArrows) { QuadRect correctedQuadRect = getCorrectedQuadRect(tileBox.getLatLonBounds()); + String width = selectedGpxFile.getGpxFile().getWidth(currentTrackWidthPref.get()); int color = selectedGpxFile.getGpxFile().getColor(cachedColor); if (selectedGpxFile.isShowCurrentTrack()) { color = currentTrackColor; } if (hasTrackDrawInfoForSelectedGpx(selectedGpxFile)) { color = trackDrawInfo.getColor(); + width = trackDrawInfo.getWidth(); + } + Float trackWidth = cachedTrackWidth.get(width); + if (trackWidth == null) { + trackWidth = defaultTrackWidth; } int contrastColor = UiUtilities.getContrastColor(view.getApplication(), color, false); - GeometryWayStyle arrowsWayStyle = new GeometryArrowsWayStyle(wayContext, contrastColor); + GeometryWayStyle arrowsWayStyle = new GeometryArrowsWayStyle(wayContext, arrowBitmap, contrastColor, color, trackWidth); for (TrkSegment segment : selectedGpxFile.getPointsToDisplay()) { List tx = new ArrayList<>(); List ty = new ArrayList<>(); @@ -465,10 +478,10 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM int bottom = pixHeight + pixHeight / 4; double zoomCoef = tb.getZoomAnimation() > 0 ? (Math.pow(2, tb.getZoomAnimation() + tb.getZoomFloatPart())) : 1f; - double pxStep = arrowBitmap.getHeight() * 4f * zoomCoef; + double pxStep = arrowBitmap.getHeight() * DIRECTION_ARROW_DISTANCE_MULTIPLIER * zoomCoef; double dist = 0; - List arrows = new ArrayList<>(); + List arrows = new ArrayList<>(); for (int i = tx.size() - 2; i >= 0; i--) { float px = tx.get(i); float py = ty.get(i); @@ -490,7 +503,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM float iconx = (float) (px + pdx); float icony = (float) (py + pdy); if (isIn(iconx, icony, left, top, right, bottom)) { - arrows.add(new PathPoint(iconx, icony, angle, wayStyle)); + arrows.add(new ArrowPathPoint(iconx, icony, angle, wayStyle)); } dist -= pxStep; percent -= pxStep / distSegment; @@ -502,13 +515,43 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } } + private static class ArrowPathPoint extends PathPoint { + + ArrowPathPoint(float x, float y, double angle, GeometryWayStyle style) { + super(x, y, angle, style); + } + + @Override + void draw(Canvas canvas, GeometryWayContext context) { + if (style instanceof GeometryArrowsWayStyle) { + GeometryArrowsWayStyle arrowsWayStyle = (GeometryArrowsWayStyle) style; + + float arrowWidth = style.getPointBitmap().getWidth(); + if (arrowWidth > arrowsWayStyle.getTrackWidth()) { + Paint paint = context.getPaintIcon(); + paint.setColor(arrowsWayStyle.getTrackColor()); + paint.setStrokeWidth(arrowWidth * DIRECTION_ARROW_CIRCLE_MULTIPLIER); + canvas.drawPoint(x, y, paint); + } + } + super.draw(canvas, context); + } + } + private static class GeometryArrowsWayStyle extends GeometryWayStyle { - protected Integer pointColor; + private Bitmap arrowBitmap; - GeometryArrowsWayStyle(GeometryWayContext context, int pointColor) { + protected int pointColor; + protected int trackColor; + protected float trackWidth; + + GeometryArrowsWayStyle(GeometryWayContext context, Bitmap arrowBitmap, int arrowColor, int trackColor, float trackWidth) { super(context); - this.pointColor = pointColor; + this.arrowBitmap = arrowBitmap; + this.pointColor = arrowColor; + this.trackColor = trackColor; + this.trackWidth = trackWidth; } @Override @@ -524,13 +567,21 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM @Override public Bitmap getPointBitmap() { - return getContext().getArrowBitmap(); + return arrowBitmap; } @Override public Integer getPointColor() { return pointColor; } + + public int getTrackColor() { + return trackColor; + } + + public float getTrackWidth() { + return trackWidth; + } } private void drawSelectedFilesStartEndPoints(Canvas canvas, RotatedTileBox tileBox, List selectedGPXFiles) { @@ -546,13 +597,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM if (segment.points.size() >= 2) { WptPt start = segment.points.get(0); WptPt end = segment.points.get(segment.points.size() - 1); - - if (start.equals(end)) { - drawPoint(canvas, tileBox, start, startAndFinishIcon); - } else { - drawPoint(canvas, tileBox, start, startPointIcon); - drawPoint(canvas, tileBox, end, finishPointIcon); - } + drawStartEndPoints(canvas, tileBox, start, end); } } } @@ -561,17 +606,29 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } private boolean hasTrackDrawInfoForSelectedGpx(SelectedGpxFile selectedGpxFile) { - return trackDrawInfo != null && trackDrawInfo.getFilePath().equals(selectedGpxFile.getGpxFile().path); + return trackDrawInfo != null && (trackDrawInfo.isCurrentRecording() && selectedGpxFile.isShowCurrentTrack() + || selectedGpxFile.getGpxFile().path.equals(trackDrawInfo.getFilePath())); } - private void drawPoint(Canvas canvas, RotatedTileBox tileBox, WptPt wptPt, Drawable icon) { - int pointX = (int) tileBox.getPixXFromLatLon(wptPt.lat, wptPt.lon); - int pointY = (int) tileBox.getPixYFromLatLon(wptPt.lat, wptPt.lon); + private void drawStartEndPoints(Canvas canvas, RotatedTileBox tileBox, WptPt start, WptPt end) { + int startX = (int) tileBox.getPixXFromLatLon(start.lat, start.lon); + int startY = (int) tileBox.getPixYFromLatLon(start.lat, start.lon); + int endX = (int) tileBox.getPixXFromLatLon(end.lat, end.lon); + int endY = (int) tileBox.getPixYFromLatLon(end.lat, end.lon); - icon.setBounds(pointX - icon.getIntrinsicWidth() / 2, - pointY - icon.getIntrinsicHeight() / 2, - pointX + icon.getIntrinsicWidth() / 2, - pointY + icon.getIntrinsicHeight() / 2); + QuadRect startRect = calculateRect(startX, startY, startPointIcon.getIntrinsicWidth(), startPointIcon.getIntrinsicHeight()); + QuadRect endRect = calculateRect(endX, endY, finishPointIcon.getIntrinsicWidth(), finishPointIcon.getIntrinsicHeight()); + + if (QuadRect.intersects(startRect, endRect)) { + drawPoint(canvas, startRect, startAndFinishIcon); + } else { + drawPoint(canvas, startRect, startPointIcon); + drawPoint(canvas, endRect, finishPointIcon); + } + } + + private void drawPoint(Canvas canvas, QuadRect rect, Drawable icon) { + icon.setBounds((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom); icon.draw(canvas); } diff --git a/OsmAnd/src/net/osmand/plus/views/MapControlsLayer.java b/OsmAnd/src/net/osmand/plus/views/MapControlsLayer.java index 7ba473c4ee..3d3cd27f2a 100644 --- a/OsmAnd/src/net/osmand/plus/views/MapControlsLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/MapControlsLayer.java @@ -68,6 +68,7 @@ import net.osmand.plus.settings.backend.OsmandSettings.LayerTransparencySeekbarM import net.osmand.plus.views.corenative.NativeCoreContext; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import gnu.trove.list.array.TIntArrayList; @@ -356,23 +357,8 @@ public class MapControlsLayer extends OsmandMapLayer { private void initControls() { View backToLocation = mapActivity.findViewById(R.id.map_my_location_button); - backToLocationControl = createHudButton(backToLocation, R.drawable.ic_my_location, BACK_TO_LOC_HUD_ID) - .setIconColorId(R.color.map_button_icon_color_light, R.color.map_button_icon_color_dark) - .setBg(R.drawable.btn_circle_blue); - controls.add(backToLocationControl); + backToLocationControl = setupBackToLocationButton(backToLocation, BACK_TO_LOC_HUD_ID); - 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(); @@ -409,6 +395,28 @@ public class MapControlsLayer extends OsmandMapLayer { }); } + public MapHudButton setupBackToLocationButton(View backToLocation, String buttonId) { + MapHudButton backToLocationButton = createHudButton(backToLocation, R.drawable.ic_my_location, buttonId) + .setIconColorId(R.color.map_button_icon_color_light, R.color.map_button_icon_color_dark) + .setBg(R.drawable.btn_circle_blue); + + 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); + } + } + }); + controls.add(backToLocationButton); + + return backToLocationButton; + } + public void doRoute(boolean hasTargets) { this.hasTargets = hasTargets; onNavigationClick(); @@ -594,29 +602,21 @@ public class MapControlsLayer extends OsmandMapLayer { } private void initZooms() { - final OsmandMapTileView view = mapActivity.getMapView(); + OsmandMapTileView view = mapActivity.getMapView(); + View.OnLongClickListener longClickListener = MapControlsLayer.getOnClickMagnifierListener(view); + View zoomInButton = mapActivity.findViewById(R.id.map_zoom_in_button); - mapZoomIn = createHudButton(zoomInButton, R.drawable.ic_zoom_in, ZOOM_IN_HUD_ID).setRoundTransparent(); - controls.add(mapZoomIn); - zoomInButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (mapActivity.getContextMenu().zoomInPressed()) { - return; - } - if (view.isZooming()) { - mapActivity.changeZoom(2, System.currentTimeMillis()); - } else { - mapActivity.changeZoom(1, System.currentTimeMillis()); - } - lastZoom = 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.ic_zoom_out, ZOOM_OUT_HUD_ID).setRoundTransparent(); - controls.add(mapZoomOut); + + mapZoomIn = setupZoomInButton(zoomInButton, longClickListener, ZOOM_IN_HUD_ID); + mapZoomOut = setupZoomOutButton(zoomOutButton, longClickListener, ZOOM_OUT_HUD_ID); + } + + public MapHudButton setupZoomOutButton(View zoomOutButton, View.OnLongClickListener longClickListener, String buttonId) { + MapHudButton mapZoomOutButton = createHudButton(zoomOutButton, R.drawable.ic_zoom_out, buttonId); + mapZoomOutButton.setRoundTransparent(); + + zoomOutButton.setOnLongClickListener(longClickListener); zoomOutButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -627,7 +627,44 @@ public class MapControlsLayer extends OsmandMapLayer { lastZoom = System.currentTimeMillis(); } }); - zoomOutButton.setOnLongClickListener(listener); + controls.add(mapZoomOutButton); + + return mapZoomOutButton; + } + + public MapHudButton setupZoomInButton(View zoomInButton, View.OnLongClickListener longClickListener, String buttonId) { + MapHudButton mapZoomInButton = createHudButton(zoomInButton, R.drawable.ic_zoom_in, buttonId); + mapZoomInButton.setRoundTransparent(); + + zoomInButton.setOnLongClickListener(longClickListener); + zoomInButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mapActivity.getContextMenu().zoomInPressed()) { + return; + } + if (mapActivity.getMapView().isZooming()) { + mapActivity.changeZoom(2, System.currentTimeMillis()); + } else { + mapActivity.changeZoom(1, System.currentTimeMillis()); + } + lastZoom = System.currentTimeMillis(); + } + }); + controls.add(mapZoomInButton); + + return mapZoomInButton; + } + + public void removeHudButtons(List buttonIds) { + List hudButtons = new ArrayList<>(controls); + for (Iterator iterator = hudButtons.iterator(); iterator.hasNext(); ) { + MapHudButton mapHudButton = iterator.next(); + if (buttonIds.contains(mapHudButton.id)) { + iterator.remove(); + } + } + controls = hudButtons; } public void showMapControlsIfHidden() { @@ -771,14 +808,12 @@ public class MapControlsLayer extends OsmandMapLayer { return AndroidUiHelper.isOrientationPortrait(mapActivity); } - @SuppressWarnings("deprecation") private void updateControls(@NonNull RotatedTileBox tileBox, DrawSettings drawSettings) { boolean isNight = drawSettings != null && drawSettings.isNightMode(); boolean portrait = isPotrait(); // int shadw = isNight ? mapActivity.getResources().getColor(R.color.widgettext_shadow_night) : // mapActivity.getResources().getColor(R.color.widgettext_shadow_day); - int textColor = isNight ? mapActivity.getResources().getColor(R.color.widgettext_night) : - mapActivity.getResources().getColor(R.color.widgettext_day); + int textColor = ContextCompat.getColor(mapActivity, isNight ? R.color.widgettext_night : R.color.widgettext_day); // TODOnightMode // updatextColor(textColor, shadw, rulerControl, zoomControls, mapMenuControls); // default buttons @@ -796,7 +831,7 @@ public class MapControlsLayer extends OsmandMapLayer { boolean showRouteCalculationControls = routePlanningMode || ((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode); boolean routeDialogOpened = mapRouteInfoMenu.isVisible() || (showRouteCalculationControls && mapRouteInfoMenu.needShowMenu()); - updateMyLocation(rh, routeDialogOpened || contextMenuOpened); + updateMyLocationVisibility(backToLocationControl, rh, routeDialogOpened || contextMenuOpened); boolean showButtons = (showRouteCalculationControls || !routeFollowingMode) && !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode() && !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode() @@ -854,6 +889,9 @@ public class MapControlsLayer extends OsmandMapLayer { } for (MapHudButton mc : controls) { + if (mc.id.startsWith(BACK_TO_LOC_HUD_ID)) { + updateMyLocation(mc); + } mc.update(mapActivity.getMyApplication(), isNight); } } @@ -893,8 +931,7 @@ public class MapControlsLayer extends OsmandMapLayer { return new CompassDrawable(originalDrawable); } - private void updateMyLocation(RoutingHelper rh, boolean dialogOpened) { - boolean portrait = isPotrait(); + private void updateMyLocation(MapHudButton backToLocationControl) { Location lastKnownLocation = mapActivity.getMyApplication().getLocationProvider().getLastKnownLocation(); boolean enabled = lastKnownLocation != null; boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation(); @@ -912,14 +949,18 @@ public class MapControlsLayer extends OsmandMapLayer { 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 && !isInPlanRouteMode() - && !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait)); if (app.accessibilityEnabled()) { + boolean visible = backToLocationControl.iv.getVisibility() == View.VISIBLE; backToLocationControl.iv.setClickable(enabled && visible); } } + public void updateMyLocationVisibility(MapHudButton backToLocationControl, RoutingHelper rh, boolean dialogOpened) { + boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation(); + boolean visible = !(tracked && rh.isFollowingMode()); + backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode() + && !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !isPotrait())); + } public boolean onSingleTap(PointF point, RotatedTileBox tileBox) { return mapRouteInfoMenu.onSingleTap(point, tileBox); @@ -991,31 +1032,31 @@ public class MapControlsLayer extends OsmandMapLayer { transparencySetting = null; } - private class MapHudButton { - View iv; - int bgDark; - int bgLight; - int resId; - int resLightId; - int resDarkId; - int resClrLight = R.color.map_button_icon_color_light; - int resClrDark = R.color.map_button_icon_color_dark; - String id; - boolean flipIconForRtl; + public class MapHudButton { - boolean nightMode = false; - boolean f = true; - boolean compass; - boolean compassOutside; - boolean forceHideCompass; - ViewPropertyAnimatorCompat hideAnimator; + private View iv; + private int bgDark; + private int bgLight; + private int resId; + private int resLightId; + private int resDarkId; + private int resClrLight = R.color.map_button_icon_color_light; + private int resClrDark = R.color.map_button_icon_color_dark; + private String id; + private boolean flipIconForRtl; + + private boolean nightMode = false; + private boolean f = true; + private boolean compass; + private boolean compassOutside; + private boolean forceHideCompass; + private 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; diff --git a/OsmAnd/src/net/osmand/plus/views/MapInfoLayer.java b/OsmAnd/src/net/osmand/plus/views/MapInfoLayer.java index 2f38894268..9a4ad3b74c 100644 --- a/OsmAnd/src/net/osmand/plus/views/MapInfoLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/MapInfoLayer.java @@ -13,13 +13,13 @@ import androidx.core.content.ContextCompat; import net.osmand.data.RotatedTileBox; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.mapcontextmenu.other.TrackChartPoints; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.views.mapwidgets.LanesControl; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory; -import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.CompassRulerControlWidgetState; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopCoordinatesView; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopTextView; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController; @@ -28,15 +28,18 @@ import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarView; import net.osmand.plus.views.mapwidgets.MapMarkersWidgetsFactory; import net.osmand.plus.views.mapwidgets.MapWidgetRegistry; import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.MapWidgetRegInfo; -import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WidgetState; -import net.osmand.plus.views.mapwidgets.NextTurnInfoWidget; import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory; -import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory.AlarmWidget; -import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory.BearingWidgetState; -import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory.LanesControl; -import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory.RulerWidget; -import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory.TimeControlWidgetState; -import net.osmand.plus.views.mapwidgets.TextInfoWidget; +import net.osmand.plus.views.mapwidgets.widgets.AlarmWidget; +import net.osmand.plus.views.mapwidgets.widgets.NextTurnWidget; +import net.osmand.plus.views.mapwidgets.widgets.RulerWidget; +import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; +import net.osmand.plus.views.mapwidgets.widgetstates.BearingWidgetState; +import net.osmand.plus.views.mapwidgets.widgetstates.CompassRulerWidgetState; +import net.osmand.plus.views.mapwidgets.widgetstates.TimeWidgetState; +import net.osmand.plus.views.mapwidgets.widgetstates.WidgetState; + +import java.util.ArrayList; +import java.util.List; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_ALTITUDE; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_BATTERY; @@ -58,18 +61,20 @@ import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_SPEED; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_TIME; public class MapInfoLayer extends OsmandMapLayer { + private final MapActivity map; private final RouteLayer routeLayer; private OsmandMapTileView view; - + // groups private LinearLayout rightStack; private LinearLayout leftStack; - private ImageButton expand; + private ImageButton expand; + private View mapRulerLayout; private static boolean expanded = false; private LanesControl lanesControl; private AlarmWidget alarmControl; - private RulerWidget rulerControl; + private List rulerWidgets; private MapWidgetRegistry mapInfoControls; private OsmandSettings settings; @@ -96,9 +101,11 @@ public class MapInfoLayer extends OsmandMapLayer { public void initLayer(final OsmandMapTileView view) { this.view = view; mapInfoControls = map.getMapLayers().getMapWidgetRegistry() ; - leftStack = (LinearLayout) map.findViewById(R.id.map_left_widgets_panel); - rightStack = (LinearLayout) map.findViewById(R.id.map_right_widgets_panel); - expand = (ImageButton) map.findViewById(R.id.map_collapse_button); + leftStack = map.findViewById(R.id.map_left_widgets_panel); + rightStack = map.findViewById(R.id.map_right_widgets_panel); + expand = map.findViewById(R.id.map_collapse_button); + mapRulerLayout = map.findViewById(R.id.map_ruler_layout); + // update and create controls registerAllControls(); map.getMyApplication().getAidlApi().registerWidgetControls(map); @@ -159,11 +166,12 @@ public class MapInfoLayer extends OsmandMapLayer { } public void registerAllControls(){ + rulerWidgets = new ArrayList<>(); RouteInfoWidgetsFactory ric = new RouteInfoWidgetsFactory(); MapInfoWidgetsFactory mic = new MapInfoWidgetsFactory(); MapMarkersWidgetsFactory mwf = map.getMapLayers().getMapMarkersLayer().getWidgetsFactory(); OsmandApplication app = view.getApplication(); - lanesControl = ric.createLanesControl(map, view); + lanesControl = RouteInfoWidgetsFactory.createLanesControl(map, view); TextState ts = calculateTextState(); streetNameView = new TopTextView(map.getMyApplication(), map); @@ -175,20 +183,19 @@ public class MapInfoLayer extends OsmandMapLayer { topToolbarView = new TopToolbarView(map); updateTopToolbar(false); - alarmControl = ric.createAlarmInfoControl(app, map); + alarmControl = RouteInfoWidgetsFactory.createAlarmInfoControl(app, map); alarmControl.setVisibility(false); - - rulerControl = ric.createRulerControl(app, map); - rulerControl.setVisibility(false); - + + setupRulerWidget(mapRulerLayout); + // register left stack registerSideWidget(null, R.drawable.ic_action_compass, R.string.map_widget_compass, WIDGET_COMPASS, true, 4); - NextTurnInfoWidget bigInfoControl = ric.createNextInfoControl(map, app, false); + NextTurnWidget bigInfoControl = ric.createNextInfoControl(map, app, false); registerSideWidget(bigInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_turn, WIDGET_NEXT_TURN, true, 5); - NextTurnInfoWidget smallInfoControl = ric.createNextInfoControl(map, app, true); + NextTurnWidget smallInfoControl = ric.createNextInfoControl(map, app, true); registerSideWidget(smallInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_turn_small, WIDGET_NEXT_TURN_SMALL, true, 6); - NextTurnInfoWidget nextNextInfoControl = ric.createNextNextInfoControl(map, app, true); + NextTurnWidget nextNextInfoControl = ric.createNextNextInfoControl(map, app, true); registerSideWidget(nextNextInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_next_turn, WIDGET_NEXT_NEXT_TURN,true, 7); // register right stack @@ -196,11 +203,11 @@ public class MapInfoLayer extends OsmandMapLayer { TextInfoWidget intermediateDist = ric.createIntermediateDistanceControl(map); registerSideWidget(intermediateDist, R.drawable.ic_action_intermediate, R.string.map_widget_intermediate_distance, WIDGET_INTERMEDIATE_DISTANCE, false, 13); TextInfoWidget intermediateTime = ric.createTimeControl(map, true); - registerSideWidget(intermediateTime, new TimeControlWidgetState(app, true), WIDGET_INTERMEDIATE_TIME, false, 14); + registerSideWidget(intermediateTime, new TimeWidgetState(app, true), WIDGET_INTERMEDIATE_TIME, false, 14); TextInfoWidget dist = ric.createDistanceControl(map); registerSideWidget(dist, R.drawable.ic_action_target, R.string.map_widget_distance, WIDGET_DISTANCE, false, 15); TextInfoWidget time = ric.createTimeControl(map, false); - registerSideWidget(time, new TimeControlWidgetState(app, false), WIDGET_TIME, false, 16); + registerSideWidget(time, new TimeWidgetState(app, false), WIDGET_TIME, false, 16); TextInfoWidget marker = mwf.createMapMarkerControl(map, true); @@ -224,7 +231,7 @@ public class MapInfoLayer extends OsmandMapLayer { TextInfoWidget battery = ric.createBatteryControl(map); registerSideWidget(battery, R.drawable.ic_action_battery, R.string.map_widget_battery, WIDGET_BATTERY, false, 42); TextInfoWidget ruler = mic.createRulerControl(map); - registerSideWidget(ruler, new CompassRulerControlWidgetState(app), WIDGET_RULER, false, 43); + registerSideWidget(ruler, new CompassRulerWidgetState(app), WIDGET_RULER, false, 43); } public void recreateControls() { @@ -236,7 +243,7 @@ public class MapInfoLayer extends OsmandMapLayer { mapInfoControls.populateStackControl(rightStack, settings.getApplicationMode(), false, expanded); rightStack.requestLayout(); - expand.setVisibility(mapInfoControls.hasCollapsibles(settings.getApplicationMode())? + expand.setVisibility(mapInfoControls.hasCollapsibles(settings.getApplicationMode())? View.VISIBLE : View.GONE); Drawable expandIcon = map.getMyApplication().getUIUtilities().getMapIcon(expanded ? R.drawable.ic_action_arrow_up : R.drawable.ic_action_arrow_down, true); @@ -252,15 +259,34 @@ public class MapInfoLayer extends OsmandMapLayer { }); } + public RulerWidget setupRulerWidget(View mapRulerView) { + RulerWidget rulerWidget = RouteInfoWidgetsFactory.createRulerControl(map, mapRulerView); + rulerWidget.setVisibility(false); + + TextState ts = calculateTextState(); + boolean nightMode = drawSettings != null && drawSettings.isNightMode(); + rulerWidget.updateTextSize(nightMode, ts.textColor, ts.textShadowColor, (int) (2 * view.getDensity())); + + rulerWidgets.add(rulerWidget); + + return rulerWidget; + } + + public void removeRulerWidgets(List rulers) { + List widgetList = new ArrayList<>(rulerWidgets); + widgetList.removeAll(rulers); + rulerWidgets = widgetList; + } + public void setTrackChartPoints(TrackChartPoints trackChartPoints) { routeLayer.setTrackChartPoints(trackChartPoints); } private static class TextState { - boolean textBold ; + boolean textBold; boolean night; - int textColor ; - int textShadowColor ; + int textColor; + int textShadowColor; int boxTop; int rightRes; int leftRes; @@ -269,7 +295,6 @@ public class MapInfoLayer extends OsmandMapLayer { int textShadowRadius; } - private int themeId = -1; public void updateColorShadowsOfText() { boolean transparent = view.getSettings().TRANSPARENT_MAP_THEME.get(); @@ -290,12 +315,15 @@ public class MapInfoLayer extends OsmandMapLayer { updateTopCoordinates(nightMode, ts); updateTopToolbar(nightMode); lanesControl.updateTextSize(nightMode, ts.textColor, ts.textShadowColor, ts.textBold, ts.textShadowRadius / 2); - rulerControl.updateTextSize(nightMode, ts.textColor, ts.textShadowColor, (int) (2 * view.getDensity())); int padding = expand.getPaddingLeft(); expand.setBackgroundResource(ts.expand); expand.setPadding(padding, padding, padding, padding); rightStack.invalidate(); leftStack.invalidate(); + + for (RulerWidget rulerWidget : rulerWidgets) { + rulerWidget.updateTextSize(nightMode, ts.textColor, ts.textShadowColor, (int) (2 * view.getDensity())); + } } } @@ -371,9 +399,11 @@ public class MapInfoLayer extends OsmandMapLayer { topToolbarView.updateInfo(); topCoordinatesView.updateInfo(); alarmControl.updateInfo(drawSettings); - rulerControl.updateInfo(tileBox, drawSettings); lanesControl.updateInfo(drawSettings); - + + for (RulerWidget rulerWidget : rulerWidgets) { + rulerWidget.updateInfo(tileBox, drawSettings); + } } @Override diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/LanesControl.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/LanesControl.java new file mode 100644 index 0000000000..05f7a7586c --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/LanesControl.java @@ -0,0 +1,139 @@ +package net.osmand.plus.views.mapwidgets; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import net.osmand.Location; +import net.osmand.binary.RouteDataObject; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmAndLocationProvider; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.base.MapViewTrackingUtilities; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu; +import net.osmand.plus.routing.RouteCalculationResult; +import net.osmand.plus.routing.RouteDirectionInfo; +import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.views.OsmandMapLayer; +import net.osmand.plus.views.OsmandMapTileView; +import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; +import net.osmand.router.RouteResultPreparation; + +import java.util.Arrays; + +public class LanesControl { + + private MapViewTrackingUtilities trackingUtilities; + private OsmAndLocationProvider locationProvider; + private MapRouteInfoMenu mapRouteInfoMenu; + private RoutingHelper rh; + private OsmandSettings settings; + private ImageView lanesView; + private TextView lanesText; + private TextView lanesShadowText; + private OsmandApplication app; + private int dist; + private LanesDrawable lanesDrawable; + private View centerInfo; + private int shadowRadius; + + public LanesControl(MapActivity mapActivity, OsmandMapTileView view) { + lanesView = mapActivity.findViewById(R.id.map_lanes); + lanesText = mapActivity.findViewById(R.id.map_lanes_dist_text); + lanesShadowText = mapActivity.findViewById(R.id.map_lanes_dist_text_shadow); + centerInfo = mapActivity.findViewById(R.id.map_center_info); + lanesDrawable = new LanesDrawable(mapActivity, mapActivity.getMapView().getScaleCoefficient()); + lanesView.setImageDrawable(lanesDrawable); + trackingUtilities = mapActivity.getMapViewTrackingUtilities(); + locationProvider = mapActivity.getMyApplication().getLocationProvider(); + settings = mapActivity.getMyApplication().getSettings(); + mapRouteInfoMenu = mapActivity.getMapRouteInfoMenu(); + rh = mapActivity.getMyApplication().getRoutingHelper(); + app = mapActivity.getMyApplication(); + } + + public void updateTextSize(boolean isNight, int textColor, int textShadowColor, boolean textBold, int shadowRadius) { + this.shadowRadius = shadowRadius; + TextInfoWidget.updateTextColor(lanesText, lanesShadowText, textColor, textShadowColor, textBold, shadowRadius); + } + + public boolean updateInfo(OsmandMapLayer.DrawSettings drawSettings) { + boolean visible = false; + int locimminent = -1; + int[] loclanes = null; + int dist = 0; + // TurnType primary = null; + if ((rh == null || !rh.isFollowingMode() || rh.isDeviatedFromRoute() || (rh.getCurrentGPXRoute() != null && !rh.isCurrentGPXRouteV2())) + && trackingUtilities.isMapLinkedToLocation() && settings.SHOW_LANES.get()) { + RouteDataObject ro = locationProvider.getLastKnownRouteSegment(); + Location lp = locationProvider.getLastKnownLocation(); + if (ro != null) { + float degree = lp == null || !lp.hasBearing() ? 0 : lp.getBearing(); + loclanes = RouteResultPreparation.parseTurnLanes(ro, degree / 180 * Math.PI); + if (loclanes == null) { + loclanes = RouteResultPreparation.parseLanes(ro, degree / 180 * Math.PI); + } + } + } else if (rh != null && rh.isRouteCalculated()) { + if (rh.isFollowingMode() && settings.SHOW_LANES.get()) { + RouteCalculationResult.NextDirectionInfo r = rh.getNextRouteDirectionInfo(new RouteCalculationResult.NextDirectionInfo(), false); + if (r != null && r.directionInfo != null && r.directionInfo.getTurnType() != null) { + loclanes = r.directionInfo.getTurnType().getLanes(); + // primary = r.directionInfo.getTurnType(); + locimminent = r.imminent; + // Do not show too far + if ((r.distanceTo > 800 && r.directionInfo.getTurnType().isSkipToSpeak()) || r.distanceTo > 1200) { + loclanes = null; + } + dist = r.distanceTo; + } + } else { + int di = MapRouteInfoMenu.getDirectionInfo(); + if (di >= 0 && mapRouteInfoMenu.isVisible() + && di < rh.getRouteDirections().size()) { + RouteDirectionInfo next = rh.getRouteDirections().get(di); + if (next != null) { + loclanes = next.getTurnType().getLanes(); + // primary = next.getTurnType(); + } + } else { + loclanes = null; + } + } + } + visible = loclanes != null && loclanes.length > 0 && !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible; + if (visible) { + if (!Arrays.equals(lanesDrawable.lanes, loclanes) || + (locimminent == 0) != lanesDrawable.imminent) { + lanesDrawable.imminent = locimminent == 0; + lanesDrawable.lanes = loclanes; + lanesDrawable.updateBounds(); + lanesView.setImageDrawable(null); + lanesView.setImageDrawable(lanesDrawable); + lanesView.requestLayout(); + lanesView.invalidate(); + } + if (RouteInfoWidgetsFactory.distChanged(dist, this.dist)) { + this.dist = dist; + if (dist == 0) { + lanesShadowText.setText(""); + lanesText.setText(""); + } else { + lanesShadowText.setText(OsmAndFormatter.getFormattedDistance(dist, app)); + lanesText.setText(OsmAndFormatter.getFormattedDistance(dist, app)); + } + lanesShadowText.invalidate(); + lanesText.invalidate(); + } + } + AndroidUiHelper.updateVisibility(lanesShadowText, visible && shadowRadius > 0); + AndroidUiHelper.updateVisibility(lanesText, visible); + AndroidUiHelper.updateVisibility(lanesView, visible); + AndroidUiHelper.updateVisibility(centerInfo, visible); + return true; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/LanesDrawable.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/LanesDrawable.java new file mode 100644 index 0000000000..7a57e05a3d --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/LanesDrawable.java @@ -0,0 +1,300 @@ +package net.osmand.plus.views.mapwidgets; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; + +import androidx.annotation.NonNull; + +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.views.TurnPathHelper; +import net.osmand.router.TurnType; + +import java.util.ArrayList; +import java.util.List; + +public class LanesDrawable extends Drawable { + + public int[] lanes = null; + boolean imminent = false; + public boolean isTurnByTurn = false; + public boolean isNightMode = false; + private Context ctx; + private Paint paintBlack; + private Paint paintRouteDirection; + private Paint paintSecondTurn; + private float scaleCoefficient; + private int height; + private int width; + private float delta; + private float laneHalfSize; + private static final float miniCoeff = 2f; + private final boolean leftSide; + private int imgMinDelta; + private int imgMargin; + + public LanesDrawable(MapActivity ctx, float scaleCoefficent) { + this.ctx = ctx; + OsmandSettings settings = ctx.getMyApplication().getSettings(); + leftSide = settings.DRIVING_REGION.get().leftHandDriving; + imgMinDelta = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_min_delta); + imgMargin = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_margin); + laneHalfSize = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_size) / 2; + + this.scaleCoefficient = scaleCoefficent; + + paintBlack = new Paint(Paint.ANTI_ALIAS_FLAG); + paintBlack.setStyle(Paint.Style.STROKE); + paintBlack.setColor(Color.BLACK); + paintBlack.setStrokeWidth(scaleCoefficent); + + paintRouteDirection = new Paint(Paint.ANTI_ALIAS_FLAG); + paintRouteDirection.setStyle(Paint.Style.FILL); + paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow)); + + paintSecondTurn = new Paint(Paint.ANTI_ALIAS_FLAG); + paintSecondTurn.setStyle(Paint.Style.FILL); + paintSecondTurn.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); + } + + public void updateBounds() { + float w = 0; + float h = 0; + float delta = imgMinDelta; + float coef = scaleCoefficient / miniCoeff; + if (lanes != null) { + List boundsList = new ArrayList<>(lanes.length); + for (int i = 0; i < lanes.length; i++) { + int turnType = TurnType.getPrimaryTurn(lanes[i]); + int secondTurnType = TurnType.getSecondaryTurn(lanes[i]); + int thirdTurnType = TurnType.getTertiaryTurn(lanes[i]); + + RectF imgBounds = new RectF(); + if (thirdTurnType > 0) { + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, + secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + } + } + } + if (secondTurnType > 0) { + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, + secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + } + } + } + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, + secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + } + } + if (imgBounds.right > 0) { + boundsList.add(imgBounds); + + float imageHeight = imgBounds.bottom; + if (imageHeight > h) + h = imageHeight; + } + } + if (boundsList.size() > 1) { + for (int i = 1; i < boundsList.size(); i++) { + RectF b1 = boundsList.get(i - 1); + RectF b2 = boundsList.get(i); + float d = b1.right + imgMargin * 2 - b2.left; + if (delta < d) + delta = d; + } + RectF b1 = boundsList.get(0); + RectF b2 = boundsList.get(boundsList.size() - 1); + w = -b1.left + (boundsList.size() - 1) * delta + b2.right; + } else if (boundsList.size() > 0) { + RectF b1 = boundsList.get(0); + w = b1.width(); + } + if (w > 0) { + w += 4; + } + if (h > 0) { + h += 4; + } + } + this.width = (int) w; + this.height = (int) h; + this.delta = delta; + } + + @Override + public int getIntrinsicHeight() { + return height; + } + + @Override + public int getIntrinsicWidth() { + return width; + } + + + @Override + public void draw(@NonNull Canvas canvas) { + // setup default color + //canvas.drawColor(0, PorterDuff.Mode.CLEAR); + + //to change color immediately when needed + if (lanes != null && lanes.length > 0) { + float coef = scaleCoefficient / miniCoeff; + canvas.save(); + // canvas.translate((int) (16 * scaleCoefficient), 0); + for (int i = 0; i < lanes.length; i++) { + if ((lanes[i] & 1) == 1) { + if (isTurnByTurn) { + paintRouteDirection.setColor(isNightMode ? ctx.getResources().getColor(R.color.active_color_primary_dark) : + ctx.getResources().getColor(R.color.active_color_primary_light)); + } else { + paintRouteDirection.setColor(imminent ? ctx.getResources().getColor(R.color.nav_arrow_imminent) : + ctx.getResources().getColor(R.color.nav_arrow)); + } + } else { + paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); + } + int turnType = TurnType.getPrimaryTurn(lanes[i]); + int secondTurnType = TurnType.getSecondaryTurn(lanes[i]); + int thirdTurnType = TurnType.getTertiaryTurn(lanes[i]); + + RectF imgBounds = new RectF(); + Path thirdTurnPath = null; + Path secondTurnPath = null; + Path firstTurnPath = null; + + if (thirdTurnType > 0) { + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, + secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + thirdTurnPath = p; + } + } + } + if (secondTurnType > 0) { + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, + secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + secondTurnPath = p; + } + } + } + Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, + secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide, true); + if (p != null) { + RectF b = new RectF(); + p.computeBounds(b, true); + if (!b.isEmpty()) { + if (imgBounds.isEmpty()) { + imgBounds.set(b); + } else { + imgBounds.union(b); + } + firstTurnPath = p; + } + } + + if (firstTurnPath != null || secondTurnPath != null || thirdTurnPath != null) { + if (i == 0) { + imgBounds.set(imgBounds.left - 2, imgBounds.top, imgBounds.right + 2, imgBounds.bottom); + canvas.translate(-imgBounds.left, 0); + } else { + canvas.translate(-laneHalfSize, 0); + } + + // 1st pass + if (thirdTurnPath != null) { + //canvas.drawPath(thirdTurnPath, paintSecondTurn); + canvas.drawPath(thirdTurnPath, paintBlack); + } + if (secondTurnPath != null) { + //canvas.drawPath(secondTurnPath, paintSecondTurn); + canvas.drawPath(secondTurnPath, paintBlack); + } + if (firstTurnPath != null) { + //canvas.drawPath(firstTurnPath, paintRouteDirection); + canvas.drawPath(firstTurnPath, paintBlack); + } + + // 2nd pass + if (thirdTurnPath != null) { + canvas.drawPath(thirdTurnPath, paintSecondTurn); + } + if (secondTurnPath != null) { + canvas.drawPath(secondTurnPath, paintSecondTurn); + } + if (firstTurnPath != null) { + canvas.drawPath(firstTurnPath, paintRouteDirection); + } + + canvas.translate(laneHalfSize + delta, 0); + } + } + canvas.restore(); + } + } + + @Override + public void setAlpha(int alpha) { + } + + @Override + public void setColorFilter(ColorFilter cf) { + } + + @Override + public int getOpacity() { + return 0; + } + +} diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java index 30b73e7299..816798ad80 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java @@ -68,8 +68,7 @@ import net.osmand.plus.settings.backend.OsmandSettings.RulerMode; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.RulerControlLayer; -import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WidgetState; -import net.osmand.plus.views.mapwidgets.NextTurnInfoWidget.TurnDrawable; +import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRulesStorage; import net.osmand.util.Algorithms; @@ -160,54 +159,6 @@ public class MapInfoWidgetsFactory { return gpsInfoControl; } - public static class CompassRulerControlWidgetState extends WidgetState { - - public static final int COMPASS_CONTROL_WIDGET_STATE_SHOW = R.id.compass_ruler_control_widget_state_show; - public static final int COMPASS_CONTROL_WIDGET_STATE_HIDE = R.id.compass_ruler_control_widget_state_hide; - - private final OsmandSettings.OsmandPreference showCompass; - - public CompassRulerControlWidgetState(OsmandApplication ctx) { - super(ctx); - showCompass = ctx.getSettings().SHOW_COMPASS_CONTROL_RULER; - } - - @Override - public int getMenuTitleId() { - return R.string.map_widget_ruler_control; - } - - @Override - public int getMenuIconId() { - return R.drawable.ic_action_ruler_circle; - } - - @Override - public int getMenuItemId() { - return showCompass.get() ? COMPASS_CONTROL_WIDGET_STATE_SHOW : COMPASS_CONTROL_WIDGET_STATE_HIDE; - } - - @Override - public int[] getMenuTitleIds() { - return new int[]{R.string.show_compass_ruler, R.string.hide_compass_ruler}; - } - - @Override - public int[] getMenuIconIds() { - return new int[]{R.drawable.ic_action_compass_widget, R.drawable.ic_action_compass_widget_hide}; - } - - @Override - public int[] getMenuItemIds() { - return new int[]{COMPASS_CONTROL_WIDGET_STATE_SHOW, COMPASS_CONTROL_WIDGET_STATE_HIDE}; - } - - @Override - public void changeState(int stateId) { - showCompass.set(stateId == COMPASS_CONTROL_WIDGET_STATE_SHOW); - } - } - public TextInfoWidget createRulerControl(final MapActivity map) { final String title = "—"; final TextInfoWidget rulerControl = new TextInfoWidget(map) { @@ -936,7 +887,7 @@ public class MapInfoWidgetsFactory { private boolean showMarker; public TopTextView(OsmandApplication app, MapActivity map) { - turnDrawable = new NextTurnInfoWidget.TurnDrawable(map, true); + turnDrawable = new TurnDrawable(map, true); topBar = map.findViewById(R.id.map_top_bar); addressText = (TextView) map.findViewById(R.id.map_address_text); addressTextShadow = (TextView) map.findViewById(R.id.map_address_text_shadow); diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java index 1ddd521fc9..799490d949 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java @@ -20,6 +20,7 @@ import net.osmand.plus.views.AnimateDraggingMapThread; import net.osmand.plus.views.DirectionDrawable; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapTileView; +import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java index b1b18862d4..d9f1b50edc 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java @@ -27,6 +27,8 @@ import net.osmand.plus.quickaction.QuickActionListFragment; import net.osmand.plus.views.MapInfoLayer; import net.osmand.plus.views.MapQuickActionLayer; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; +import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; +import net.osmand.plus.views.mapwidgets.widgetstates.WidgetState; import net.osmand.plus.widgets.IconPopupMenu; import java.util.Collections; @@ -362,7 +364,7 @@ public class MapWidgetRegistry { cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.coordinates_widget, map) .setIcon(R.drawable.ic_action_coordinates_widget) .setSelected(settings.SHOW_COORDINATES_WIDGET.get()) - .setListener(new ApearanceItemClickListener(settings.SHOW_COORDINATES_WIDGET, map)) + .setListener(new AppearanceItemClickListener(settings.SHOW_COORDINATES_WIDGET, map)) .setLayout(R.layout.list_item_icon_and_switch).createItem()); cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.map_markers, map) .setDescription(settings.MAP_MARKERS_MODE.get().toHumanString(map)) @@ -408,14 +410,13 @@ public class MapWidgetRegistry { @StringRes int stringId, OsmandPreference pref) { cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(stringId, map) .setSelected(pref.get()) - .setListener(new ApearanceItemClickListener(pref, map)).createItem()); + .setListener(new AppearanceItemClickListener(pref, map)).createItem()); } public static boolean distChanged(int oldDist, int dist) { return !(oldDist != 0 && oldDist - dist < 100 && Math.abs(((float) dist - oldDist) / oldDist) < 0.01); } - public void addControls(MapActivity map, ContextMenuAdapter cm, ApplicationMode mode) { addQuickActionControl(map, cm, mode); // Right panel @@ -819,49 +820,23 @@ public class MapWidgetRegistry { return cm; } - class ApearanceItemClickListener implements ContextMenuAdapter.ItemClickListener { - private MapActivity map; + static class AppearanceItemClickListener implements ContextMenuAdapter.ItemClickListener { + + private MapActivity mapActivity; private OsmandPreference pref; - public ApearanceItemClickListener(OsmandPreference pref, MapActivity map) { + public AppearanceItemClickListener(OsmandPreference pref, MapActivity mapActivity) { this.pref = pref; - this.map = map; + this.mapActivity = mapActivity; } @Override public boolean onContextMenuClick(ArrayAdapter a, int itemId, int pos, boolean isChecked, int[] viewCoordinates) { pref.set(!pref.get()); - map.updateApplicationModeSettings(); + mapActivity.updateApplicationModeSettings(); a.notifyDataSetChanged(); return false; } } - - public static abstract class WidgetState { - - private OsmandApplication ctx; - - public OsmandApplication getCtx() { - return ctx; - } - - public WidgetState(OsmandApplication ctx) { - this.ctx = ctx; - } - - public abstract int getMenuTitleId(); - - public abstract int getMenuIconId(); - - public abstract int getMenuItemId(); - - public abstract int[] getMenuTitleIds(); - - public abstract int[] getMenuIconIds(); - - public abstract int[] getMenuItemIds(); - - public abstract void changeState(int stateId); - } -} +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java deleted file mode 100644 index 6633b970a0..0000000000 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/NextTurnInfoWidget.java +++ /dev/null @@ -1,236 +0,0 @@ -package net.osmand.plus.views.mapwidgets; - -import android.app.Activity; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Paint.Align; -import android.graphics.Paint.Style; -import android.graphics.Path; -import android.graphics.PointF; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.text.TextPaint; - -import androidx.annotation.ColorRes; -import androidx.annotation.NonNull; - -import net.osmand.plus.OsmAndFormatter; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.R; -import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.views.OsmandMapLayer.DrawSettings; -import net.osmand.plus.views.TurnPathHelper; -import net.osmand.router.TurnType; - - - -public class NextTurnInfoWidget extends TextInfoWidget { - - protected boolean horisontalMini; - - protected int deviatedPath = 0; - protected int nextTurnDistance = 0; - - private TurnDrawable turnDrawable; - private OsmandApplication app; - - - public NextTurnInfoWidget(Activity activity, OsmandApplication app, boolean horisontalMini) { - super(activity); - this.app = app; - this.horisontalMini = horisontalMini; - turnDrawable = new TurnDrawable(activity, horisontalMini); - if(horisontalMini) { - setImageDrawable(turnDrawable, false); - setTopImageDrawable(null, null); - } else { - setImageDrawable(null, true); - setTopImageDrawable(turnDrawable, ""); - } - } - - public TurnType getTurnType() { - return turnDrawable.turnType; - } - - public void setTurnType(TurnType turnType) { - boolean vis = updateVisibility(turnType != null); - if (turnDrawable.setTurnType(turnType) || vis) { - turnDrawable.setTextPaint(topTextView.getPaint()); - if(horisontalMini) { - setImageDrawable(turnDrawable, false); - } else { - setTopImageDrawable(turnDrawable, ""); -// setTopImageDrawable(turnDrawable, turnType == null || turnType.getExitOut() == 0 ? "" : -// turnType.getExitOut() + ""); - } - } - } - - public void setTurnImminent(int turnImminent, boolean deviatedFromRoute) { - if(turnDrawable.turnImminent != turnImminent || turnDrawable.deviatedFromRoute != deviatedFromRoute) { - turnDrawable.setTurnImminent(turnImminent, deviatedFromRoute); - } - } - - public void setDeviatePath(int deviatePath) { - if (RouteInfoWidgetsFactory.distChanged(deviatePath, this.deviatedPath)) { - this.deviatedPath = deviatePath; - updateDistance(); - } - } - - public void setTurnDistance(int nextTurnDistance) { - if (RouteInfoWidgetsFactory.distChanged(nextTurnDistance, this.nextTurnDistance)) { - this.nextTurnDistance = nextTurnDistance; - updateDistance(); - } - } - - private void updateDistance() { - int deviatePath = turnDrawable.deviatedFromRoute ? deviatedPath : nextTurnDistance; - String ds = OsmAndFormatter.getFormattedDistance(deviatePath, app); - - if (ds != null) { - TurnType turnType = getTurnType(); - RoutingHelper routingHelper = app.getRoutingHelper(); - if ((turnType != null) && (routingHelper != null)) { - setContentDescription(ds + " " + routingHelper.getRoute().toString(turnType, app, false)); - } else { - setContentDescription(ds); - } - } - - int ls = ds.lastIndexOf(' '); - if (ls == -1) { - setTextNoUpdateVisibility(ds, null); - } else { - setTextNoUpdateVisibility(ds.substring(0, ls), ds.substring(ls + 1)); - } - } - - @Override - public boolean updateInfo(DrawSettings drawSettings) { - return false; - } - - public static class TurnDrawable extends Drawable { - protected Paint paintBlack; - protected Paint paintRouteDirection; - protected Path pathForTurn = new Path(); - protected Path pathForTurnOutlay = new Path(); - protected TurnType turnType = null; - protected int turnImminent; - protected boolean deviatedFromRoute; - private Context ctx; - private boolean mini; - private PointF centerText; - private TextPaint textPaint; - private int clr; - - public TurnDrawable(Context ctx, boolean mini) { - this.ctx = ctx; - this.mini = mini; - centerText = new PointF(); - paintBlack = new Paint(); - paintBlack.setStyle(Style.STROKE); - paintBlack.setColor(Color.BLACK); - paintBlack.setAntiAlias(true); - paintBlack.setStrokeWidth(2.5f); - - - paintRouteDirection = new Paint(); - paintRouteDirection.setStyle(Style.FILL); - paintRouteDirection.setAntiAlias(true); - setColor(R.color.nav_arrow); - } - - @ColorRes - public void setColor(int clr) { - if(clr != this.clr) { - this.clr = clr; - paintRouteDirection.setColor(ctx.getResources().getColor(clr)); - } - } - - @Override - protected void onBoundsChange(Rect bounds) { - Matrix m = new Matrix(); - float scaleX = bounds.width() / 72f; - float scaleY = bounds.height() / 72f; - m.setScale(scaleX, scaleY); - pathForTurn.transform(m, pathForTurn); - centerText.x = scaleX * centerText.x; - centerText.y = scaleY * centerText.y; - pathForTurnOutlay.transform(m, pathForTurnOutlay); - } - - public void setTurnImminent(int turnImminent, boolean deviatedFromRoute) { - //if user deviates from route that we should draw grey arrow - this.turnImminent = turnImminent; - this.deviatedFromRoute = deviatedFromRoute; - if (deviatedFromRoute){ - paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); - } else if (turnImminent > 0) { - paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow)); - } else if (turnImminent == 0) { - paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_imminent)); - } else { - paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); - } - invalidateSelf(); - - } - - @Override - public void draw(@NonNull Canvas canvas) { - /// small indent - // canvas.translate(0, 3 * scaleCoefficient); - canvas.drawPath(pathForTurnOutlay, paintBlack); - canvas.drawPath(pathForTurn, paintRouteDirection); - canvas.drawPath(pathForTurn, paintBlack); - if(textPaint != null ) { - if (turnType != null && !mini && turnType.getExitOut() > 0) { - canvas.drawText(turnType.getExitOut() + "", centerText.x, - centerText.y - (textPaint.descent() + textPaint.ascent()) / 2, textPaint); - } - } - } - - public void setTextPaint(TextPaint textPaint) { - this.textPaint = textPaint; - this.textPaint.setTextAlign(Align.CENTER); - } - - @Override - public void setAlpha(int alpha) { - paintRouteDirection.setAlpha(alpha); - } - - @Override - public void setColorFilter(ColorFilter cf) { - paintRouteDirection.setColorFilter(cf); - } - - @Override - public int getOpacity() { - return 0; - } - - public boolean setTurnType(TurnType turnType) { - if(turnType != this.turnType) { - this.turnType = turnType; - TurnPathHelper.calcTurnPath(pathForTurn, pathForTurnOutlay, turnType, null, - centerText, mini, false, true, false); - onBoundsChange(getBounds()); - return true; - } - return false; - } - - } -} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java index 06e5838c73..e3a16e5975 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/RouteInfoWidgetsFactory.java @@ -2,75 +2,47 @@ package net.osmand.plus.views.mapwidgets; import android.app.Activity; -import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.Path; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; import android.hardware.GeomagneticField; import android.os.BatteryManager; import android.text.format.DateFormat; import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; import net.osmand.Location; import net.osmand.binary.RouteDataObject; import net.osmand.data.LatLon; -import net.osmand.data.RotatedTileBox; -import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.MapMarkersHelper.MapMarker; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmAndLocationProvider; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference; 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.base.MapViewTrackingUtilities; -import net.osmand.plus.helpers.AndroidUiHelper; -import net.osmand.plus.helpers.WaypointHelper; -import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu; -import net.osmand.plus.routing.AlarmInfo; -import net.osmand.plus.routing.AlarmInfo.AlarmInfoType; import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; -import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.views.AnimateDraggingMapThread; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapTileView; -import net.osmand.plus.views.TurnPathHelper; -import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WidgetState; -import net.osmand.router.RouteResultPreparation; +import net.osmand.plus.views.mapwidgets.widgets.AlarmWidget; +import net.osmand.plus.views.mapwidgets.widgets.DistanceToPointWidget; +import net.osmand.plus.views.mapwidgets.widgets.NextTurnWidget; +import net.osmand.plus.views.mapwidgets.widgets.RulerWidget; +import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; import net.osmand.router.TurnType; -import net.osmand.util.Algorithms; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import static android.util.TypedValue.COMPLEX_UNIT_PX; - public class RouteInfoWidgetsFactory { - public NextTurnInfoWidget createNextInfoControl(final Activity activity, - final OsmandApplication app, boolean horisontalMini) { + public NextTurnWidget createNextInfoControl(final Activity activity, + final OsmandApplication app, boolean horisontalMini) { final OsmandSettings settings = app.getSettings(); final RoutingHelper routingHelper = app.getRoutingHelper(); - final NextTurnInfoWidget nextTurnInfo = new NextTurnInfoWidget(activity, app, horisontalMini) { + final NextTurnWidget nextTurnInfo = new NextTurnWidget(activity, app, horisontalMini) { NextDirectionInfo calc1 = new NextDirectionInfo(); @Override @@ -80,7 +52,7 @@ public class RouteInfoWidgetsFactory { boolean deviatedFromRoute = false; int turnImminent = 0; int nextTurnDistance = 0; - if (routingHelper != null && routingHelper.isRouteCalculated() && followingMode) { + if (routingHelper.isRouteCalculated() && followingMode) { deviatedFromRoute = routingHelper.isDeviatedFromRoute(); if (deviatedFromRoute) { @@ -123,7 +95,7 @@ public class RouteInfoWidgetsFactory { // nextTurnInfo.turnImminent = (nextTurnInfo.turnImminent + 1) % 3; // nextTurnInfo.nextTurnDirection = 580; // TurnPathHelper.calcTurnPath(nextTurnInfo.pathForTurn, nextTurnInfo.turnType,nextTurnInfo.pathTransform); - if(routingHelper.isRouteCalculated() && !routingHelper.isDeviatedFromRoute()) { + if (routingHelper.isRouteCalculated() && !routingHelper.isDeviatedFromRoute()) { routingHelper.getVoiceRouter().announceCurrentDirection(null); } } @@ -132,10 +104,10 @@ public class RouteInfoWidgetsFactory { return nextTurnInfo; } - public NextTurnInfoWidget createNextNextInfoControl(final Activity activity, - final OsmandApplication app, boolean horisontalMini) { + public NextTurnWidget createNextNextInfoControl(final Activity activity, + final OsmandApplication app, boolean horisontalMini) { final RoutingHelper routingHelper = app.getRoutingHelper(); - final NextTurnInfoWidget nextTurnInfo = new NextTurnInfoWidget(activity, app, horisontalMini) { + final NextTurnWidget nextTurnInfo = new NextTurnWidget(activity, app, horisontalMini) { NextDirectionInfo calc1 = new NextDirectionInfo(); @Override public boolean updateInfo(DrawSettings drawSettings) { @@ -144,8 +116,8 @@ public class RouteInfoWidgetsFactory { boolean deviatedFromRoute = false; int turnImminent = 0; int nextTurnDistance = 0; - if (routingHelper != null && routingHelper.isRouteCalculated() && followingMode) { - deviatedFromRoute = routingHelper.isDeviatedFromRoute() ; + if (routingHelper.isRouteCalculated() && followingMode) { + deviatedFromRoute = routingHelper.isDeviatedFromRoute(); NextDirectionInfo r = routingHelper.getNextRouteDirectionInfo(calc1, true); if (!deviatedFromRoute) { if (r != null) { @@ -191,75 +163,7 @@ public class RouteInfoWidgetsFactory { return nextTurnInfo; } - - - public static class TimeControlWidgetState extends WidgetState { - - public static final int TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME = R.id.time_control_widget_state_arrival_time; - public static final int TIME_CONTROL_WIDGET_STATE_TIME_TO_GO = R.id.time_control_widget_state_time_to_go; - - private final OsmandPreference showArrival; - private final boolean intermediate; - - public TimeControlWidgetState(OsmandApplication ctx, boolean intermediate) { - super(ctx); - this.intermediate = intermediate; - if (intermediate) { - showArrival = ctx.getSettings().SHOW_INTERMEDIATE_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME; - } else { - showArrival = ctx.getSettings().SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME; - } - } - - @Override - public int getMenuTitleId() { - if (intermediate) { - return showArrival.get() ? R.string.access_intermediate_arrival_time : R.string.map_widget_intermediate_time; - } - return showArrival.get() ? R.string.access_arrival_time : R.string.map_widget_time; - } - - @Override - public int getMenuIconId() { - if (intermediate) { - return R.drawable.ic_action_intermediate_destination_time; - } - return showArrival.get() ? R.drawable.ic_action_time : R.drawable.ic_action_time_to_distance; - } - - @Override - public int getMenuItemId() { - return showArrival.get() ? TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME : TIME_CONTROL_WIDGET_STATE_TIME_TO_GO; - } - - @Override - public int[] getMenuTitleIds() { - if (intermediate) { - return new int[]{R.string.access_intermediate_arrival_time, R.string.map_widget_intermediate_time}; - } - return new int[]{R.string.access_arrival_time, R.string.map_widget_time}; - } - - @Override - public int[] getMenuIconIds() { - if (intermediate) { - return new int[]{R.drawable.ic_action_intermediate_destination_time, R.drawable.ic_action_intermediate_destination_time}; - } - return new int[]{R.drawable.ic_action_time, R.drawable.ic_action_time_to_distance}; - } - - @Override - public int[] getMenuItemIds() { - return new int[]{TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME, TIME_CONTROL_WIDGET_STATE_TIME_TO_GO}; - } - - @Override - public void changeState(int stateId) { - showArrival.set(stateId == TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME); - } - } - - public TextInfoWidget createTimeControl(final MapActivity map, final boolean intermediate){ + public TextInfoWidget createTimeControl(final MapActivity map, final boolean intermediate) { final RoutingHelper routingHelper = map.getRoutingHelper(); final OsmandApplication ctx = map.getMyApplication(); final OsmandPreference showArrival = intermediate @@ -286,7 +190,7 @@ public class RouteInfoWidgetsFactory { if (DateFormat.is24HourFormat(ctx)) { setText(DateFormat.format("k:mm", toFindTime).toString(), null); //$NON-NLS-1$ } else { - setText(DateFormat.format("h:mm", toFindTime).toString(), + setText(DateFormat.format("h:mm", toFindTime).toString(), DateFormat.format("aa", toFindTime).toString()); //$NON-NLS-1$ } return true; @@ -309,7 +213,7 @@ public class RouteInfoWidgetsFactory { return true; } return false; - }; + } }; leftTimeControl.setOnClickListener(new View.OnClickListener() { @@ -335,9 +239,8 @@ public class RouteInfoWidgetsFactory { : showArrival ? R.drawable.widget_time_night : R.drawable.widget_time_to_distance_night; timeControl.setIcons(iconLight, iconDark); } - - - public TextInfoWidget createPlainTimeControl(final MapActivity map){ + + public TextInfoWidget createPlainTimeControl(final MapActivity map) { final OsmandApplication ctx = map.getMyApplication(); final TextInfoWidget plainTimeControl = new TextInfoWidget(map) { private long cachedLeftTime = 0; @@ -355,15 +258,14 @@ public class RouteInfoWidgetsFactory { } } return false; - }; + } }; plainTimeControl.setText(null, null); plainTimeControl.setIcons(R.drawable.widget_time_day, R.drawable.widget_time_night); return plainTimeControl; } - - public TextInfoWidget createBatteryControl(final MapActivity map){ + public TextInfoWidget createBatteryControl(final MapActivity map) { final int battery = R.drawable.widget_battery_day; final int batteryN = R.drawable.widget_battery_night; final int batteryCharging = R.drawable.widget_battery_charging_day; @@ -388,12 +290,12 @@ public class RouteInfoWidgetsFactory { } else { boolean charging = ((status == BatteryManager.BATTERY_STATUS_CHARGING) || (status == BatteryManager.BATTERY_STATUS_FULL)); - setText(String.format("%d%%", (level * 100) / scale), null ); + setText(String.format("%d%%", (level * 100) / scale), null); setIcons(charging ? batteryCharging : battery, charging ? batteryChargingN : batteryN); } } return false; - }; + } }; batteryControl.setText(null, null); batteryControl.setIcons(battery, batteryN); @@ -409,11 +311,11 @@ public class RouteInfoWidgetsFactory { @Override public boolean updateInfo(DrawSettings drawSettings) { - float mx = 0; + float mx = 0; if ((rh == null || !rh.isFollowingMode() || rh.isDeviatedFromRoute() || (rh.getCurrentGPXRoute() != null && !rh.isCurrentGPXRouteV2())) && trackingUtilities.isMapLinkedToLocation()) { RouteDataObject ro = locationProvider.getLastKnownRouteSegment(); - if(ro != null) { + if (ro != null) { mx = ro.getMaximumSpeed(ro.bearingVsRouteDirection(locationProvider.getLastKnownLocation())); } } else if (rh != null) { @@ -425,7 +327,7 @@ public class RouteInfoWidgetsFactory { cachedSpeed = mx; if (cachedSpeed == 0) { setText(null, null); - } else if(cachedSpeed == RouteDataObject.NONE_MAX_SPEED) { + } else if (cachedSpeed == RouteDataObject.NONE_MAX_SPEED) { setText(map.getString(R.string.max_speed_none), ""); } else { String ds = OsmAndFormatter.getFormattedSpeed(cachedSpeed, map.getMyApplication()); @@ -450,10 +352,7 @@ public class RouteInfoWidgetsFactory { speedControl.setText(null, null); return speedControl; } - - - - + public TextInfoWidget createSpeedControl(final MapActivity map) { final OsmandApplication app = map.getMyApplication(); final TextInfoWidget speedControl = new TextInfoWidget(map) { @@ -499,80 +398,9 @@ public class RouteInfoWidgetsFactory { speedControl.setText(null, null); return speedControl; } - - public abstract static class DistanceToPointInfoControl extends TextInfoWidget { - private final OsmandMapTileView view; - private float[] calculations = new float[1]; - private int cachedMeters; - - public DistanceToPointInfoControl(MapActivity ma, int res, int resNight) { - super(ma); - this.view = ma.getMapView(); - if (res != 0 && resNight != 0) { - setIcons(res, resNight); - } - setText(null, null); - setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View v) { - click(view); - } - }); - } - - protected void click(final OsmandMapTileView view) { - AnimateDraggingMapThread thread = view.getAnimatedDraggingThread(); - LatLon pointToNavigate = getPointToNavigate(); - if (pointToNavigate != null) { - int fZoom = view.getZoom() < 15 ? 15 : view.getZoom(); - thread.startMoving(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), fZoom, true); - } - } - - @Override - public boolean updateInfo(DrawSettings drawSettings) { - int d = getDistance(); - if (isUpdateNeeded() || distChanged(cachedMeters, d)) { - cachedMeters = d; - if (cachedMeters <= 20) { - cachedMeters = 0; - setText(null, null); - } else { - String ds = OsmAndFormatter.getFormattedDistance(cachedMeters, view.getApplication()); - int ls = ds.lastIndexOf(' '); - if (ls == -1) { - setText(ds, null); - } else { - setText(ds.substring(0, ls), ds.substring(ls + 1)); - } - } - return true; - } - return false; - } - - @Override - public boolean isMetricSystemDepended() { - return true; - } - - public abstract LatLon getPointToNavigate(); - - public int getDistance() { - int d = 0; - LatLon l = getPointToNavigate(); - if (l != null) { - Location.distanceBetween(view.getLatitude(), view.getLongitude(), l.getLatitude(), l.getLongitude(), calculations); - d = (int) calculations[0]; - } - return d; - } - } - public TextInfoWidget createDistanceControl(final MapActivity map) { - DistanceToPointInfoControl distanceControl = new DistanceToPointInfoControl(map,R.drawable.widget_target_day, + DistanceToPointWidget distanceControl = new DistanceToPointWidget(map, R.drawable.widget_target_day, R.drawable.widget_target_night) { @Override public LatLon getPointToNavigate() { @@ -593,12 +421,12 @@ public class RouteInfoWidgetsFactory { public TextInfoWidget createIntermediateDistanceControl(final MapActivity map) { final TargetPointsHelper targets = map.getMyApplication().getTargetPointsHelper(); - DistanceToPointInfoControl distanceControl = new DistanceToPointInfoControl(map, R.drawable.widget_intermediate_day, + DistanceToPointWidget distanceControl = new DistanceToPointWidget(map, R.drawable.widget_intermediate_day, R.drawable.widget_intermediate_night) { @Override protected void click(OsmandMapTileView view) { - if(targets.getIntermediatePoints().size() > 1) { + if (targets.getIntermediatePoints().size() > 1) { map.getMapActions().openIntermediatePointsDialog(); } else { super.click(view); @@ -622,55 +450,6 @@ public class RouteInfoWidgetsFactory { return distanceControl; } - - public static class BearingWidgetState extends WidgetState { - - public static final int BEARING_WIDGET_STATE_RELATIVE_BEARING = R.id.bearing_widget_state_relative_bearing; - public static final int BEARING_WIDGET_STATE_MAGNETIC_BEARING = R.id.bearing_widget_state_magnetic_bearing; - - private final OsmandPreference showRelativeBearing; - - public BearingWidgetState(OsmandApplication ctx) { - super(ctx); - showRelativeBearing = ctx.getSettings().SHOW_RELATIVE_BEARING_OTHERWISE_REGULAR_BEARING; - } - - @Override - public int getMenuTitleId() { - return showRelativeBearing.get() ? R.string.map_widget_bearing : R.string.map_widget_magnetic_bearing; - } - - @Override - public int getMenuIconId() { - return showRelativeBearing.get() ? R.drawable.ic_action_relative_bearing : R.drawable.ic_action_bearing; - } - - @Override - public int getMenuItemId() { - return showRelativeBearing.get() ? BEARING_WIDGET_STATE_RELATIVE_BEARING : BEARING_WIDGET_STATE_MAGNETIC_BEARING; - } - - @Override - public int[] getMenuTitleIds() { - return new int[]{R.string.map_widget_magnetic_bearing, R.string.map_widget_bearing}; - } - - @Override - public int[] getMenuIconIds() { - return new int[]{R.drawable.ic_action_bearing, R.drawable.ic_action_relative_bearing}; - } - - @Override - public int[] getMenuItemIds() { - return new int[]{BEARING_WIDGET_STATE_MAGNETIC_BEARING, BEARING_WIDGET_STATE_RELATIVE_BEARING}; - } - - @Override - public void changeState(int stateId) { - showRelativeBearing.set(stateId == BEARING_WIDGET_STATE_RELATIVE_BEARING); - } - } - public TextInfoWidget createBearingControl(final MapActivity map) { final int bearingResId = R.drawable.widget_bearing_day; final int bearingNightResId = R.drawable.widget_bearing_night; @@ -684,7 +463,7 @@ public class RouteInfoWidgetsFactory { private float MIN_SPEED_FOR_HEADING = 1f; private LatLon getNextTargetPoint() { - List points = getOsmandApplication().getTargetPointsHelper().getIntermediatePointsWithTarget(); + List points = getApplication().getTargetPointsHelper().getIntermediatePointsWithTarget(); return points.isEmpty() ? null : points.get(0).point; } @@ -697,7 +476,7 @@ public class RouteInfoWidgetsFactory { if (isUpdateNeeded() || degreesChanged(cachedDegrees, b) || modeChanged) { cachedDegrees = b; if (b != -1000) { - setText(OsmAndFormatter.getFormattedAzimuth(b, getOsmandApplication()) + (relative ? "" : " M"), null); + setText(OsmAndFormatter.getFormattedAzimuth(b, getApplication()) + (relative ? "" : " M"), null); } else { setText(null, null); } @@ -713,10 +492,10 @@ public class RouteInfoWidgetsFactory { public int getBearing(boolean relative) { int d = -1000; - Location myLocation = getOsmandApplication().getLocationProvider().getLastKnownLocation(); + Location myLocation = getApplication().getLocationProvider().getLastKnownLocation(); LatLon l = getNextTargetPoint(); if (l == null) { - List markers = getOsmandApplication().getMapMarkersHelper().getMapMarkers(); + List markers = getApplication().getMapMarkersHelper().getMapMarkers(); if (markers.size() > 0) { l = markers.get(0).point; } @@ -731,7 +510,7 @@ public class RouteInfoWidgetsFactory { float bearingToDest = dest.getBearing() - destGf.getDeclination(); if (relative) { float b = -1000; - Float heading = getOsmandApplication().getLocationProvider().getHeading(); + Float heading = getApplication().getLocationProvider().getHeading(); if ((myLocation.getSpeed() < MIN_SPEED_FOR_HEADING || !myLocation.hasBearing()) && heading != null) { b = heading; @@ -772,654 +551,23 @@ public class RouteInfoWidgetsFactory { return bearingControl; } - - public static class LanesControl { - private MapViewTrackingUtilities trackingUtilities; - private OsmAndLocationProvider locationProvider; - private MapRouteInfoMenu mapRouteInfoMenu; - private RoutingHelper rh; - private OsmandSettings settings; - private ImageView lanesView; - private TextView lanesText; - private TextView lanesShadowText; - private OsmandApplication app; - private int dist; - private LanesDrawable lanesDrawable; - private View centerInfo; - private int shadowRadius; - - public LanesControl(final MapActivity map, final OsmandMapTileView view) { - lanesView = (ImageView) map.findViewById(R.id.map_lanes); - lanesText = (TextView) map.findViewById(R.id.map_lanes_dist_text); - lanesShadowText = (TextView) map.findViewById(R.id.map_lanes_dist_text_shadow); - centerInfo = (View) map.findViewById(R.id.map_center_info); - lanesDrawable = new LanesDrawable(map, map.getMapView().getScaleCoefficient()); - lanesView.setImageDrawable(lanesDrawable); - trackingUtilities = map.getMapViewTrackingUtilities(); - locationProvider = map.getMyApplication().getLocationProvider(); - settings = map.getMyApplication().getSettings(); - mapRouteInfoMenu = map.getMapRouteInfoMenu(); - rh = map.getMyApplication().getRoutingHelper(); - app = map.getMyApplication(); - } - - public void updateTextSize(boolean isNight, int textColor, int textShadowColor, boolean textBold, int shadowRadius) { - this.shadowRadius = shadowRadius; - TextInfoWidget.updateTextColor(lanesText, lanesShadowText, textColor, textShadowColor, textBold, shadowRadius); - } - - public boolean updateInfo(DrawSettings drawSettings) { - boolean visible = false; - int locimminent = -1; - int[] loclanes = null; - int dist = 0; - // TurnType primary = null; - if ((rh == null || !rh.isFollowingMode() || rh.isDeviatedFromRoute() || (rh.getCurrentGPXRoute() != null && !rh.isCurrentGPXRouteV2())) - && trackingUtilities.isMapLinkedToLocation() && settings.SHOW_LANES.get()) { - RouteDataObject ro = locationProvider.getLastKnownRouteSegment(); - Location lp = locationProvider.getLastKnownLocation(); - if(ro != null) { - float degree = lp == null || !lp.hasBearing() ? 0 : lp.getBearing(); - loclanes = RouteResultPreparation.parseTurnLanes(ro, degree / 180 * Math.PI); - if(loclanes == null) { - loclanes = RouteResultPreparation.parseLanes(ro, degree / 180 * Math.PI); - } - } - } else if (rh != null && rh.isRouteCalculated() ) { - if (rh.isFollowingMode() && settings.SHOW_LANES.get()) { - NextDirectionInfo r = rh.getNextRouteDirectionInfo(new NextDirectionInfo(), false); - if(r != null && r.directionInfo != null && r.directionInfo.getTurnType() != null) { - loclanes = r.directionInfo.getTurnType().getLanes(); - // primary = r.directionInfo.getTurnType(); - locimminent = r.imminent; - // Do not show too far - if ((r.distanceTo > 800 && r.directionInfo.getTurnType().isSkipToSpeak()) || r.distanceTo > 1200) { - loclanes = null; - } - dist = r.distanceTo; - } - } else { - int di = MapRouteInfoMenu.getDirectionInfo(); - if (di >= 0 && mapRouteInfoMenu.isVisible() - && di < rh.getRouteDirections().size()) { - RouteDirectionInfo next = rh.getRouteDirections().get(di); - if (next != null) { - loclanes = next.getTurnType().getLanes(); - // primary = next.getTurnType(); - } - } else { - loclanes = null; - } - } - } - visible = loclanes != null && loclanes.length > 0 && !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible; - if (visible) { - if (!Arrays.equals(lanesDrawable.lanes, loclanes) || - (locimminent == 0) != lanesDrawable.imminent) { - lanesDrawable.imminent = locimminent == 0; - lanesDrawable.lanes = loclanes; - lanesDrawable.updateBounds(); - lanesView.setImageDrawable(null); - lanesView.setImageDrawable(lanesDrawable); - lanesView.requestLayout(); - lanesView.invalidate(); - } - if (distChanged(dist, this.dist)) { - this.dist = dist; - if(dist == 0) { - lanesShadowText.setText(""); - lanesText.setText(""); - } else { - lanesShadowText.setText(OsmAndFormatter.getFormattedDistance(dist, app)); - lanesText.setText(OsmAndFormatter.getFormattedDistance(dist, app)); - } - lanesShadowText.invalidate(); - lanesText.invalidate(); - } - } - AndroidUiHelper.updateVisibility(lanesShadowText, visible && shadowRadius > 0); - AndroidUiHelper.updateVisibility(lanesText, visible); - AndroidUiHelper.updateVisibility(lanesView, visible); - AndroidUiHelper.updateVisibility(centerInfo, visible); - return true; - } - } - - - public static class LanesDrawable extends Drawable { - public int[] lanes = null; - boolean imminent = false; - public boolean isTurnByTurn = false; - public boolean isNightMode = false; - private Context ctx; - private Paint paintBlack; - private Paint paintRouteDirection; - private Paint paintSecondTurn; - private float scaleCoefficient; - private int height; - private int width; - private float delta; - private float laneHalfSize; - private static final float miniCoeff = 2f; - private final boolean leftSide; - private int imgMinDelta; - private int imgMargin; - - public LanesDrawable(MapActivity ctx, float scaleCoefficent) { - this.ctx = ctx; - OsmandSettings settings = ctx.getMyApplication().getSettings(); - leftSide = settings.DRIVING_REGION.get().leftHandDriving; - imgMinDelta = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_min_delta); - imgMargin = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_margin); - laneHalfSize = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_size) / 2; - - this.scaleCoefficient = scaleCoefficent; - - paintBlack = new Paint(Paint.ANTI_ALIAS_FLAG); - paintBlack.setStyle(Style.STROKE); - paintBlack.setColor(Color.BLACK); - paintBlack.setStrokeWidth(scaleCoefficent); - - paintRouteDirection = new Paint(Paint.ANTI_ALIAS_FLAG); - paintRouteDirection.setStyle(Style.FILL); - paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow)); - - paintSecondTurn = new Paint(Paint.ANTI_ALIAS_FLAG); - paintSecondTurn.setStyle(Style.FILL); - paintSecondTurn.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); - } - - public void updateBounds() { - float w = 0; - float h = 0; - float delta = imgMinDelta; - float coef = scaleCoefficient / miniCoeff; - if (lanes != null) { - List boundsList = new ArrayList<>(lanes.length); - for (int i = 0; i < lanes.length; i++) { - int turnType = TurnType.getPrimaryTurn(lanes[i]); - int secondTurnType = TurnType.getSecondaryTurn(lanes[i]); - int thirdTurnType = TurnType.getTertiaryTurn(lanes[i]); - - RectF imgBounds = new RectF(); - if (thirdTurnType > 0) { - Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, - secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide, true); - if (p != null) { - RectF b = new RectF(); - p.computeBounds(b, true); - if (!b.isEmpty()) { - if (imgBounds.isEmpty()) { - imgBounds.set(b); - } else { - imgBounds.union(b); - } - } - } - } - if (secondTurnType > 0) { - Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, - secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide, true); - if (p != null) { - RectF b = new RectF(); - p.computeBounds(b, true); - if (!b.isEmpty()) { - if (imgBounds.isEmpty()) { - imgBounds.set(b); - } else { - imgBounds.union(b); - } - } - } - } - Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, - secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide, true); - if (p != null) { - RectF b = new RectF(); - p.computeBounds(b, true); - if (!b.isEmpty()) { - if (imgBounds.isEmpty()) { - imgBounds.set(b); - } else { - imgBounds.union(b); - } - } - } - if (imgBounds.right > 0) - { - boundsList.add(imgBounds); - - float imageHeight = imgBounds.bottom; - if (imageHeight > h) - h = imageHeight; - } - } - if (boundsList.size() > 1) { - for (int i = 1; i < boundsList.size(); i++) { - RectF b1 = boundsList.get(i - 1); - RectF b2 = boundsList.get(i); - float d = b1.right + imgMargin * 2 - b2.left; - if (delta < d) - delta = d; - } - RectF b1 = boundsList.get(0); - RectF b2 = boundsList.get(boundsList.size() - 1); - w = -b1.left + (boundsList.size() - 1) * delta + b2.right; - } else if (boundsList.size() > 0) { - RectF b1 = boundsList.get(0); - w = b1.width(); - } - if (w > 0) { - w += 4; - } - if (h > 0) { - h += 4; - } - } - this.width = (int) w; - this.height = (int) h; - this.delta = delta; - } - - @Override - public int getIntrinsicHeight() { - return height; - } - - @Override - public int getIntrinsicWidth() { - return width; - } - - - @Override - public void draw(@NonNull Canvas canvas) { - // setup default color - //canvas.drawColor(0, PorterDuff.Mode.CLEAR); - - //to change color immediately when needed - if (lanes != null && lanes.length > 0) { - float coef = scaleCoefficient / miniCoeff; - canvas.save(); - // canvas.translate((int) (16 * scaleCoefficient), 0); - for (int i = 0; i < lanes.length; i++) { - if ((lanes[i] & 1) == 1) { - if (isTurnByTurn){ - paintRouteDirection.setColor(isNightMode ? ctx.getResources().getColor(R.color.active_color_primary_dark) : - ctx.getResources().getColor(R.color.active_color_primary_light)); - } else { - paintRouteDirection.setColor(imminent ? ctx.getResources().getColor(R.color.nav_arrow_imminent) : - ctx.getResources().getColor(R.color.nav_arrow)); - } - } else { - paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); - } - int turnType = TurnType.getPrimaryTurn(lanes[i]); - int secondTurnType = TurnType.getSecondaryTurn(lanes[i]); - int thirdTurnType = TurnType.getTertiaryTurn(lanes[i]); - - RectF imgBounds = new RectF(); - Path thirdTurnPath = null; - Path secondTurnPath = null; - Path firstTurnPath = null; - - if (thirdTurnType > 0) { - Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, - secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide, true); - if (p != null) { - RectF b = new RectF(); - p.computeBounds(b, true); - if (!b.isEmpty()) { - if (imgBounds.isEmpty()) { - imgBounds.set(b); - } else { - imgBounds.union(b); - } - thirdTurnPath = p; - } - } - } - if (secondTurnType > 0) { - Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, - secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide, true); - if (p != null) { - RectF b = new RectF(); - p.computeBounds(b, true); - if (!b.isEmpty()) { - if (imgBounds.isEmpty()) { - imgBounds.set(b); - } else { - imgBounds.union(b); - } - secondTurnPath = p; - } - } - } - Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType, - secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide, true); - if (p != null) { - RectF b = new RectF(); - p.computeBounds(b, true); - if (!b.isEmpty()) { - if (imgBounds.isEmpty()) { - imgBounds.set(b); - } else { - imgBounds.union(b); - } - firstTurnPath = p; - } - } - - if (firstTurnPath != null || secondTurnPath != null || thirdTurnPath != null) { - if (i == 0) { - imgBounds.set(imgBounds.left - 2, imgBounds.top, imgBounds.right + 2, imgBounds.bottom); - canvas.translate(-imgBounds.left, 0); - } else { - canvas.translate(-laneHalfSize, 0); - } - - // 1st pass - if (thirdTurnPath != null) { - //canvas.drawPath(thirdTurnPath, paintSecondTurn); - canvas.drawPath(thirdTurnPath, paintBlack); - } - if (secondTurnPath != null) { - //canvas.drawPath(secondTurnPath, paintSecondTurn); - canvas.drawPath(secondTurnPath, paintBlack); - } - if (firstTurnPath != null) { - //canvas.drawPath(firstTurnPath, paintRouteDirection); - canvas.drawPath(firstTurnPath, paintBlack); - } - - // 2nd pass - if (thirdTurnPath != null) { - canvas.drawPath(thirdTurnPath, paintSecondTurn); - } - if (secondTurnPath != null) { - canvas.drawPath(secondTurnPath, paintSecondTurn); - } - if (firstTurnPath != null) { - canvas.drawPath(firstTurnPath, paintRouteDirection); - } - - canvas.translate(laneHalfSize + delta, 0); - } - } - canvas.restore(); - } - } - - @Override - public void setAlpha(int alpha) { - } - - @Override - public void setColorFilter(ColorFilter cf) { - } - - @Override - public int getOpacity() { - return 0; - } - - } - - - public LanesControl createLanesControl(final MapActivity map, final OsmandMapTileView view) { - return new LanesControl(map, view); + public static boolean distChanged(int oldDist, int dist) { + return oldDist == 0 || Math.abs(oldDist - dist) >= 10; } - public static class RulerWidget { - - private View layout; - private ImageView icon; - private TextView text; - private TextView textShadow; - private MapActivity ma; - private String cacheRulerText; - private int maxWidth; - private float cacheMapDensity; - private OsmandSettings.OsmandPreference mapDensity; - private int cacheRulerZoom; - private double cacheRulerTileX; - private double cacheRulerTileY; - private boolean orientationPortrait; - - public RulerWidget(final OsmandApplication app, MapActivity ma) { - this.ma = ma; - layout = ma.findViewById(R.id.map_ruler_layout); - icon = (ImageView) ma.findViewById(R.id.map_ruler_image); - text = (TextView) ma.findViewById(R.id.map_ruler_text); - textShadow = (TextView) ma.findViewById(R.id.map_ruler_text_shadow); - maxWidth = ma.getResources().getDimensionPixelSize(R.dimen.map_ruler_width); - orientationPortrait = AndroidUiHelper.isOrientationPortrait(ma); - mapDensity = ma.getMyApplication().getSettings().MAP_DENSITY; - cacheMapDensity = mapDensity.get(); - } - - public void updateTextSize(boolean isNight, int textColor, int textShadowColor, int shadowRadius) { - TextInfoWidget.updateTextColor(text, textShadow, textColor, textShadowColor, false, shadowRadius); - icon.setBackgroundResource(isNight ? R.drawable.ruler_night : R.drawable.ruler); - } - - public boolean updateInfo(RotatedTileBox tb, DrawSettings nightMode) { - boolean visible = true; - OsmandMapTileView view = ma.getMapView(); - // update cache - if (view.isZooming()) { - visible = false; - } else if (!tb.isZoomAnimated() && (tb.getZoom() != cacheRulerZoom || Math.abs(tb.getCenterTileX() - cacheRulerTileX) > 1 || Math - .abs(tb.getCenterTileY() - cacheRulerTileY) > 1 || mapDensity.get() != cacheMapDensity) && - tb.getPixWidth() > 0 && maxWidth > 0) { - cacheRulerZoom = tb.getZoom(); - cacheRulerTileX = tb.getCenterTileX(); - cacheRulerTileY = tb.getCenterTileY(); - cacheMapDensity = mapDensity.get(); - double pixDensity = tb.getPixDensity(); - double roundedDist = OsmAndFormatter.calculateRoundedDist(maxWidth / - pixDensity, view.getApplication()); - - int cacheRulerDistPix = (int) (pixDensity * roundedDist); - cacheRulerText = OsmAndFormatter.getFormattedDistance((float) roundedDist, view.getApplication(), false); - textShadow.setText(cacheRulerText); - text.setText(cacheRulerText); - ViewGroup.LayoutParams lp = layout.getLayoutParams(); - lp.width = cacheRulerDistPix; - layout.setLayoutParams(lp); - layout.requestLayout(); - } - AndroidUiHelper.updateVisibility(layout, visible); - return true; - } - - public void setVisibility(boolean visibility) { - layout.setVisibility(visibility ? View.VISIBLE : View.GONE); - } - } - - public static class AlarmWidget { - - private View layout; - private ImageView icon; - private TextView widgetText; - private TextView widgetBottomText; - private OsmandSettings settings; - private RoutingHelper rh; - private MapViewTrackingUtilities trackingUtilities; - private OsmAndLocationProvider locationProvider; - private WaypointHelper wh; - private int imgId; - private String cachedText; - private String cachedBottomText; - private OsmandSettings.DrivingRegion cachedRegion; - - public AlarmWidget(final OsmandApplication app, MapActivity ma) { - layout = ma.findViewById(R.id.map_alarm_warning); - icon = (ImageView) ma.findViewById(R.id.map_alarm_warning_icon); - widgetText = (TextView) ma.findViewById(R.id.map_alarm_warning_text); - widgetBottomText = (TextView) ma.findViewById(R.id.map_alarm_warning_text_bottom); - settings = app.getSettings(); - rh = ma.getRoutingHelper(); - trackingUtilities = ma.getMapViewTrackingUtilities(); - locationProvider = app.getLocationProvider(); - wh = app.getWaypointHelper(); - } - - public boolean updateInfo(DrawSettings drawSettings) { - boolean showRoutingAlarms = settings.SHOW_ROUTING_ALARMS.get(); - boolean trafficWarnings = settings.SHOW_TRAFFIC_WARNINGS.get(); - boolean cams = settings.SHOW_CAMERAS.get(); - boolean peds = settings.SHOW_PEDESTRIAN.get(); - boolean tunnels = settings.SHOW_TUNNELS.get(); - boolean browseMap = settings.APPLICATION_MODE.get() == ApplicationMode.DEFAULT; - boolean visible = false; - if ((rh.isFollowingMode() || trackingUtilities.isMapLinkedToLocation() && !browseMap) - && showRoutingAlarms && (trafficWarnings || cams)) { - AlarmInfo alarm; - if(rh.isFollowingMode() && !rh.isDeviatedFromRoute() && (rh.getCurrentGPXRoute() == null || rh.isCurrentGPXRouteV2())) { - alarm = wh.getMostImportantAlarm(settings.SPEED_SYSTEM.get(), cams); - } else { - RouteDataObject ro = locationProvider.getLastKnownRouteSegment(); - Location loc = locationProvider.getLastKnownLocation(); - if(ro != null && loc != null) { - alarm = wh.calculateMostImportantAlarm(ro, loc, settings.METRIC_SYSTEM.get(), - settings.SPEED_SYSTEM.get(), cams); - } else { - alarm = null; - } - } - if(alarm != null) { - int locimgId = R.drawable.warnings_limit; - String text = ""; - String bottomText = ""; - OsmandSettings.DrivingRegion region = settings.DRIVING_REGION.get(); - boolean americanType = region.isAmericanTypeSigns(); - boolean isCanadianRegion = region == OsmandSettings.DrivingRegion.CANADA; - if (alarm.getType() == AlarmInfoType.SPEED_LIMIT) { - if (isCanadianRegion) { - locimgId = R.drawable.warnings_speed_limit_ca; - bottomText = settings.SPEED_SYSTEM.get().toShortString(settings.getContext()); - } else if (americanType) { - locimgId = R.drawable.warnings_speed_limit_us; - //else case is done by drawing red ring - } - text = alarm.getIntValue() + ""; - } else if (alarm.getType() == AlarmInfoType.SPEED_CAMERA) { - locimgId = R.drawable.warnings_speed_camera; - } else if(alarm.getType() == AlarmInfoType.BORDER_CONTROL) { - locimgId = R.drawable.warnings_border_control; - } else if(alarm.getType() == AlarmInfoType.HAZARD) { - if (americanType) { - locimgId = R.drawable.warnings_hazard_us; - } else { - locimgId = R.drawable.warnings_hazard; - } - } else if(alarm.getType() == AlarmInfoType.TOLL_BOOTH) { - //image done by drawing red ring - text = "$"; - } else if(alarm.getType() == AlarmInfoType.TRAFFIC_CALMING) { - if (americanType) { - locimgId = R.drawable.warnings_traffic_calming_us; - } else { - locimgId = R.drawable.warnings_traffic_calming; - } - } else if(alarm.getType() == AlarmInfoType.STOP) { - locimgId = R.drawable.warnings_stop; - } else if(alarm.getType() == AlarmInfoType.RAILWAY) { - if (americanType) { - locimgId = R.drawable.warnings_railways_us; - } else { - locimgId = R.drawable.warnings_railways; - } - } else if(alarm.getType() == AlarmInfoType.PEDESTRIAN) { - if (americanType) { - locimgId = R.drawable.warnings_pedestrian_us; - } else { - locimgId = R.drawable.warnings_pedestrian; - } - } else if(alarm.getType() == AlarmInfoType.TUNNEL) { - if (americanType) { - locimgId = R.drawable.warnings_tunnel_us; - } else { - locimgId = R.drawable.warnings_tunnel; - } - bottomText = OsmAndFormatter.getFormattedAlarmInfoDistance(settings.getContext(), alarm.getFloatValue()); - } else { - text = null; - bottomText = null; - } - visible = (text != null && text.length() > 0) || (locimgId != 0); - if (visible) { - if (alarm.getType() == AlarmInfoType.SPEED_CAMERA) { - visible = cams; - } else if (alarm.getType() == AlarmInfoType.PEDESTRIAN) { - visible = peds; - } else if (alarm.getType() == AlarmInfoType.TUNNEL) { - visible = tunnels; - } else { - visible = trafficWarnings; - } - } - if(visible) { - if (locimgId != imgId) { - imgId = locimgId; - icon.setImageResource(locimgId); - } - Resources res = layout.getContext().getResources(); - if (!Algorithms.objectEquals(text, cachedText) || cachedRegion != region) { - cachedText = text; - widgetText.setText(cachedText); - if (alarm.getType() == AlarmInfoType.SPEED_LIMIT && americanType && !isCanadianRegion) { - int topPadding = res.getDimensionPixelSize(R.dimen.map_alarm_text_top_padding); - widgetText.setPadding(0, topPadding, 0, 0); - } else { - widgetText.setPadding(0, 0, 0, 0); - } - } - if (!Algorithms.objectEquals(bottomText, cachedBottomText) || cachedRegion != region) { - cachedBottomText = bottomText; - widgetBottomText.setText(cachedBottomText); - cachedRegion = region; - if (alarm.getType() == AlarmInfoType.SPEED_LIMIT && isCanadianRegion) { - int bottomPadding = res.getDimensionPixelSize(R.dimen.map_button_margin); - widgetBottomText.setPadding(0, 0, 0, bottomPadding); - widgetBottomText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_bottom_si_text_size)); - } else { - widgetBottomText.setPadding(0, 0, 0, 0); - widgetBottomText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_bottom_text_size)); - } - widgetBottomText.setTextColor(ContextCompat.getColor(layout.getContext(), - americanType ? R.color.color_black : R.color.color_white)); - } - } - } - } - AndroidUiHelper.updateVisibility(layout, visible); - return true; - } - - public void setVisibility(boolean visibility) { - layout.setVisibility(visibility ? View.VISIBLE : View.GONE); - } - } - - public static boolean distChanged(int oldDist, int dist){ - if (oldDist != 0 && Math.abs(oldDist - dist) < 10) { - return false; - } - return true; - } - - public static boolean degreesChanged(int oldDegrees, int degrees){ + public static boolean degreesChanged(int oldDegrees, int degrees) { return Math.abs(oldDegrees - degrees) >= 1; } - public AlarmWidget createAlarmInfoControl(OsmandApplication app, MapActivity map) { + public static LanesControl createLanesControl(final MapActivity map, final OsmandMapTileView view) { + return new LanesControl(map, view); + } + + public static AlarmWidget createAlarmInfoControl(OsmandApplication app, MapActivity map) { return new AlarmWidget(app, map); } - - public RulerWidget createRulerControl(OsmandApplication app, MapActivity map) { - return new RulerWidget(app, map); + + public static RulerWidget createRulerControl(MapActivity map, View view) { + return new RulerWidget(map, view); } -} +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/TurnDrawable.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/TurnDrawable.java new file mode 100644 index 0000000000..f6bbb95b20 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/TurnDrawable.java @@ -0,0 +1,146 @@ +package net.osmand.plus.views.mapwidgets; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PointF; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.text.TextPaint; + +import androidx.annotation.ColorRes; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + +import net.osmand.plus.R; +import net.osmand.plus.views.TurnPathHelper; +import net.osmand.router.TurnType; + +public class TurnDrawable extends Drawable { + + protected Paint paintBlack; + protected Paint paintRouteDirection; + protected Path pathForTurn = new Path(); + protected Path pathForTurnOutlay = new Path(); + protected TurnType turnType = null; + protected int turnImminent; + protected boolean deviatedFromRoute; + private Context ctx; + private boolean mini; + private PointF centerText; + private TextPaint textPaint; + private int clr; + + public TurnDrawable(Context ctx, boolean mini) { + this.ctx = ctx; + this.mini = mini; + centerText = new PointF(); + paintBlack = new Paint(); + paintBlack.setStyle(Paint.Style.STROKE); + paintBlack.setColor(Color.BLACK); + paintBlack.setAntiAlias(true); + paintBlack.setStrokeWidth(2.5f); + + paintRouteDirection = new Paint(); + paintRouteDirection.setStyle(Paint.Style.FILL); + paintRouteDirection.setAntiAlias(true); + setColor(R.color.nav_arrow); + } + + public void setColor(@ColorRes int clr) { + if (clr != this.clr) { + this.clr = clr; + paintRouteDirection.setColor(ContextCompat.getColor(ctx, clr)); + } + } + + @Override + protected void onBoundsChange(Rect bounds) { + Matrix m = new Matrix(); + float scaleX = bounds.width() / 72f; + float scaleY = bounds.height() / 72f; + m.setScale(scaleX, scaleY); + pathForTurn.transform(m, pathForTurn); + centerText.x = scaleX * centerText.x; + centerText.y = scaleY * centerText.y; + pathForTurnOutlay.transform(m, pathForTurnOutlay); + } + + public int getTurnImminent() { + return turnImminent; + } + + public boolean isDeviatedFromRoute() { + return deviatedFromRoute; + } + + public void setTurnImminent(int turnImminent, boolean deviatedFromRoute) { + //if user deviates from route that we should draw grey arrow + this.turnImminent = turnImminent; + this.deviatedFromRoute = deviatedFromRoute; + if (deviatedFromRoute) { + paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); + } else if (turnImminent > 0) { + paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow)); + } else if (turnImminent == 0) { + paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_imminent)); + } else { + paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant)); + } + invalidateSelf(); + } + + @Override + public void draw(@NonNull Canvas canvas) { + /// small indent + // canvas.translate(0, 3 * scaleCoefficient); + canvas.drawPath(pathForTurnOutlay, paintBlack); + canvas.drawPath(pathForTurn, paintRouteDirection); + canvas.drawPath(pathForTurn, paintBlack); + if (textPaint != null) { + if (turnType != null && !mini && turnType.getExitOut() > 0) { + canvas.drawText(turnType.getExitOut() + "", centerText.x, + centerText.y - (textPaint.descent() + textPaint.ascent()) / 2, textPaint); + } + } + } + + public void setTextPaint(TextPaint textPaint) { + this.textPaint = textPaint; + this.textPaint.setTextAlign(Paint.Align.CENTER); + } + + @Override + public void setAlpha(int alpha) { + paintRouteDirection.setAlpha(alpha); + } + + @Override + public void setColorFilter(ColorFilter cf) { + paintRouteDirection.setColorFilter(cf); + } + + @Override + public int getOpacity() { + return 0; + } + + public TurnType getTurnType() { + return turnType; + } + + public boolean setTurnType(TurnType turnType) { + if (turnType != this.turnType) { + this.turnType = turnType; + TurnPathHelper.calcTurnPath(pathForTurn, pathForTurnOutlay, turnType, null, + centerText, mini, false, true, false); + onBoundsChange(getBounds()); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/AlarmWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/AlarmWidget.java new file mode 100644 index 0000000000..a75422967d --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/AlarmWidget.java @@ -0,0 +1,193 @@ +package net.osmand.plus.views.mapwidgets.widgets; + +import android.content.res.Resources; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import net.osmand.Location; +import net.osmand.binary.RouteDataObject; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmAndLocationProvider; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.base.MapViewTrackingUtilities; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.helpers.WaypointHelper; +import net.osmand.plus.routing.AlarmInfo; +import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.views.OsmandMapLayer; +import net.osmand.util.Algorithms; + +import static android.util.TypedValue.COMPLEX_UNIT_PX; + +public class AlarmWidget { + + private View layout; + private ImageView icon; + private TextView widgetText; + private TextView widgetBottomText; + private OsmandSettings settings; + private RoutingHelper routingHelper; + private MapViewTrackingUtilities trackingUtilities; + private OsmAndLocationProvider locationProvider; + private WaypointHelper wh; + private int imgId; + private String cachedText; + private String cachedBottomText; + private OsmandSettings.DrivingRegion cachedRegion; + + public AlarmWidget(final OsmandApplication app, MapActivity ma) { + layout = ma.findViewById(R.id.map_alarm_warning); + icon = ma.findViewById(R.id.map_alarm_warning_icon); + widgetText = ma.findViewById(R.id.map_alarm_warning_text); + widgetBottomText = ma.findViewById(R.id.map_alarm_warning_text_bottom); + settings = app.getSettings(); + routingHelper = ma.getRoutingHelper(); + trackingUtilities = ma.getMapViewTrackingUtilities(); + locationProvider = app.getLocationProvider(); + wh = app.getWaypointHelper(); + } + + public boolean updateInfo(OsmandMapLayer.DrawSettings drawSettings) { + boolean showRoutingAlarms = settings.SHOW_ROUTING_ALARMS.get(); + boolean trafficWarnings = settings.SHOW_TRAFFIC_WARNINGS.get(); + boolean cams = settings.SHOW_CAMERAS.get(); + boolean peds = settings.SHOW_PEDESTRIAN.get(); + boolean tunnels = settings.SHOW_TUNNELS.get(); + boolean browseMap = settings.APPLICATION_MODE.get() == ApplicationMode.DEFAULT; + boolean visible = false; + if ((routingHelper.isFollowingMode() || trackingUtilities.isMapLinkedToLocation() && !browseMap) + && showRoutingAlarms && (trafficWarnings || cams)) { + AlarmInfo alarm; + if (routingHelper.isFollowingMode() && !routingHelper.isDeviatedFromRoute() && (routingHelper.getCurrentGPXRoute() == null || routingHelper.isCurrentGPXRouteV2())) { + alarm = wh.getMostImportantAlarm(settings.SPEED_SYSTEM.get(), cams); + } else { + RouteDataObject ro = locationProvider.getLastKnownRouteSegment(); + Location loc = locationProvider.getLastKnownLocation(); + if (ro != null && loc != null) { + alarm = wh.calculateMostImportantAlarm(ro, loc, settings.METRIC_SYSTEM.get(), + settings.SPEED_SYSTEM.get(), cams); + } else { + alarm = null; + } + } + if (alarm != null) { + int locimgId = R.drawable.warnings_limit; + String text = ""; + String bottomText = ""; + OsmandSettings.DrivingRegion region = settings.DRIVING_REGION.get(); + boolean americanType = region.isAmericanTypeSigns(); + boolean isCanadianRegion = region == OsmandSettings.DrivingRegion.CANADA; + if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT) { + if (isCanadianRegion) { + locimgId = R.drawable.warnings_speed_limit_ca; + bottomText = settings.SPEED_SYSTEM.get().toShortString(settings.getContext()); + } else if (americanType) { + locimgId = R.drawable.warnings_speed_limit_us; + //else case is done by drawing red ring + } + text = alarm.getIntValue() + ""; + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_CAMERA) { + locimgId = R.drawable.warnings_speed_camera; + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.BORDER_CONTROL) { + locimgId = R.drawable.warnings_border_control; + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.HAZARD) { + if (americanType) { + locimgId = R.drawable.warnings_hazard_us; + } else { + locimgId = R.drawable.warnings_hazard; + } + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.TOLL_BOOTH) { + //image done by drawing red ring + text = "$"; + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.TRAFFIC_CALMING) { + if (americanType) { + locimgId = R.drawable.warnings_traffic_calming_us; + } else { + locimgId = R.drawable.warnings_traffic_calming; + } + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.STOP) { + locimgId = R.drawable.warnings_stop; + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.RAILWAY) { + if (americanType) { + locimgId = R.drawable.warnings_railways_us; + } else { + locimgId = R.drawable.warnings_railways; + } + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.PEDESTRIAN) { + if (americanType) { + locimgId = R.drawable.warnings_pedestrian_us; + } else { + locimgId = R.drawable.warnings_pedestrian; + } + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.TUNNEL) { + if (americanType) { + locimgId = R.drawable.warnings_tunnel_us; + } else { + locimgId = R.drawable.warnings_tunnel; + } + bottomText = OsmAndFormatter.getFormattedAlarmInfoDistance(settings.getContext(), alarm.getFloatValue()); + } else { + text = null; + bottomText = null; + } + visible = (text != null && text.length() > 0) || (locimgId != 0); + if (visible) { + if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_CAMERA) { + visible = cams; + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.PEDESTRIAN) { + visible = peds; + } else if (alarm.getType() == AlarmInfo.AlarmInfoType.TUNNEL) { + visible = tunnels; + } else { + visible = trafficWarnings; + } + } + if (visible) { + if (locimgId != imgId) { + imgId = locimgId; + icon.setImageResource(locimgId); + } + Resources res = layout.getContext().getResources(); + if (!Algorithms.objectEquals(text, cachedText) || cachedRegion != region) { + cachedText = text; + widgetText.setText(cachedText); + if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT && americanType && !isCanadianRegion) { + int topPadding = res.getDimensionPixelSize(R.dimen.map_alarm_text_top_padding); + widgetText.setPadding(0, topPadding, 0, 0); + } else { + widgetText.setPadding(0, 0, 0, 0); + } + } + if (!Algorithms.objectEquals(bottomText, cachedBottomText) || cachedRegion != region) { + cachedBottomText = bottomText; + widgetBottomText.setText(cachedBottomText); + cachedRegion = region; + if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT && isCanadianRegion) { + int bottomPadding = res.getDimensionPixelSize(R.dimen.map_button_margin); + widgetBottomText.setPadding(0, 0, 0, bottomPadding); + widgetBottomText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_bottom_si_text_size)); + } else { + widgetBottomText.setPadding(0, 0, 0, 0); + widgetBottomText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_bottom_text_size)); + } + widgetBottomText.setTextColor(ContextCompat.getColor(layout.getContext(), + americanType ? R.color.color_black : R.color.color_white)); + } + } + } + } + AndroidUiHelper.updateVisibility(layout, visible); + return true; + } + + public void setVisibility(boolean visibility) { + AndroidUiHelper.updateVisibility(layout, visibility); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/DistanceToPointWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/DistanceToPointWidget.java new file mode 100644 index 0000000000..7962b5c3ee --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/DistanceToPointWidget.java @@ -0,0 +1,83 @@ +package net.osmand.plus.views.mapwidgets.widgets; + +import android.view.View; + +import net.osmand.Location; +import net.osmand.data.LatLon; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.views.AnimateDraggingMapThread; +import net.osmand.plus.views.OsmandMapLayer; +import net.osmand.plus.views.OsmandMapTileView; +import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory; + +public abstract class DistanceToPointWidget extends TextInfoWidget { + + private final OsmandMapTileView view; + private float[] calculations = new float[1]; + private int cachedMeters; + + public DistanceToPointWidget(MapActivity ma, int res, int resNight) { + super(ma); + this.view = ma.getMapView(); + if (res != 0 && resNight != 0) { + setIcons(res, resNight); + } + setText(null, null); + setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + click(view); + } + }); + } + + protected void click(final OsmandMapTileView view) { + AnimateDraggingMapThread thread = view.getAnimatedDraggingThread(); + LatLon pointToNavigate = getPointToNavigate(); + if (pointToNavigate != null) { + int fZoom = Math.max(view.getZoom(), 15); + thread.startMoving(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), fZoom, true); + } + } + + @Override + public boolean updateInfo(OsmandMapLayer.DrawSettings drawSettings) { + int d = getDistance(); + if (isUpdateNeeded() || RouteInfoWidgetsFactory.distChanged(cachedMeters, d)) { + cachedMeters = d; + if (cachedMeters <= 20) { + cachedMeters = 0; + setText(null, null); + } else { + String ds = OsmAndFormatter.getFormattedDistance(cachedMeters, view.getApplication()); + int ls = ds.lastIndexOf(' '); + if (ls == -1) { + setText(ds, null); + } else { + setText(ds.substring(0, ls), ds.substring(ls + 1)); + } + } + return true; + } + return false; + } + + @Override + public boolean isMetricSystemDepended() { + return true; + } + + public abstract LatLon getPointToNavigate(); + + public int getDistance() { + int d = 0; + LatLon l = getPointToNavigate(); + if (l != null) { + Location.distanceBetween(view.getLatitude(), view.getLongitude(), l.getLatitude(), l.getLongitude(), calculations); + d = (int) calculations[0]; + } + return d; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/NextTurnWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/NextTurnWidget.java new file mode 100644 index 0000000000..e4e71e42ae --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/NextTurnWidget.java @@ -0,0 +1,100 @@ +package net.osmand.plus.views.mapwidgets.widgets; + +import android.app.Activity; + +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.routing.RouteCalculationResult; +import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.views.OsmandMapLayer.DrawSettings; +import net.osmand.plus.views.mapwidgets.RouteInfoWidgetsFactory; +import net.osmand.plus.views.mapwidgets.TurnDrawable; +import net.osmand.router.TurnType; + +public class NextTurnWidget extends TextInfoWidget { + + protected boolean horizontalMini; + + protected int deviatedPath = 0; + protected int nextTurnDistance = 0; + + private TurnDrawable turnDrawable; + private OsmandApplication app; + + public NextTurnWidget(Activity activity, OsmandApplication app, boolean horizontalMini) { + super(activity); + this.app = app; + this.horizontalMini = horizontalMini; + turnDrawable = new TurnDrawable(activity, horizontalMini); + if (horizontalMini) { + setImageDrawable(turnDrawable, false); + setTopImageDrawable(null, null); + } else { + setImageDrawable(null, true); + setTopImageDrawable(turnDrawable, ""); + } + } + + public TurnType getTurnType() { + return turnDrawable.getTurnType(); + } + + public void setTurnType(TurnType turnType) { + boolean vis = updateVisibility(turnType != null); + if (turnDrawable.setTurnType(turnType) || vis) { + turnDrawable.setTextPaint(topTextView.getPaint()); + if (horizontalMini) { + setImageDrawable(turnDrawable, false); + } else { + setTopImageDrawable(turnDrawable, ""); +// setTopImageDrawable(turnDrawable, turnType == null || turnType.getExitOut() == 0 ? "" : +// turnType.getExitOut() + ""); + } + } + } + + public void setTurnImminent(int turnImminent, boolean deviatedFromRoute) { + if (turnDrawable.getTurnImminent() != turnImminent || turnDrawable.isDeviatedFromRoute() != deviatedFromRoute) { + turnDrawable.setTurnImminent(turnImminent, deviatedFromRoute); + } + } + + public void setDeviatePath(int deviatePath) { + if (RouteInfoWidgetsFactory.distChanged(deviatePath, this.deviatedPath)) { + this.deviatedPath = deviatePath; + updateDistance(); + } + } + + public void setTurnDistance(int nextTurnDistance) { + if (RouteInfoWidgetsFactory.distChanged(nextTurnDistance, this.nextTurnDistance)) { + this.nextTurnDistance = nextTurnDistance; + updateDistance(); + } + } + + private void updateDistance() { + int deviatePath = turnDrawable.isDeviatedFromRoute() ? deviatedPath : nextTurnDistance; + String ds = OsmAndFormatter.getFormattedDistance(deviatePath, app); + + TurnType turnType = getTurnType(); + RoutingHelper routingHelper = app.getRoutingHelper(); + if ((turnType != null) && (routingHelper != null)) { + setContentDescription(ds + " " + RouteCalculationResult.toString(turnType, app, false)); + } else { + setContentDescription(ds); + } + + int ls = ds.lastIndexOf(' '); + if (ls == -1) { + setTextNoUpdateVisibility(ds, null); + } else { + setTextNoUpdateVisibility(ds.substring(0, ls), ds.substring(ls + 1)); + } + } + + @Override + public boolean updateInfo(DrawSettings drawSettings) { + return false; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/RulerWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/RulerWidget.java new file mode 100644 index 0000000000..8d576c72cf --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/RulerWidget.java @@ -0,0 +1,83 @@ +package net.osmand.plus.views.mapwidgets.widgets; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import net.osmand.data.RotatedTileBox; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference; +import net.osmand.plus.views.OsmandMapLayer.DrawSettings; +import net.osmand.plus.views.OsmandMapTileView; + +public class RulerWidget { + + private MapActivity mapActivity; + private OsmandPreference mapDensity; + + private View layout; + private ImageView icon; + private TextView text; + private TextView textShadow; + + private String cacheRulerText; + private int maxWidth; + private int cacheRulerZoom; + private float cacheMapDensity; + private double cacheRulerTileX; + private double cacheRulerTileY; + + public RulerWidget(MapActivity mapActivity, View view) { + this.mapActivity = mapActivity; + layout = view.findViewById(R.id.map_ruler_layout); + icon = view.findViewById(R.id.map_ruler_image); + text = view.findViewById(R.id.map_ruler_text); + textShadow = view.findViewById(R.id.map_ruler_text_shadow); + maxWidth = view.getResources().getDimensionPixelSize(R.dimen.map_ruler_width); + mapDensity = mapActivity.getMyApplication().getSettings().MAP_DENSITY; + cacheMapDensity = mapDensity.get(); + } + + public void updateTextSize(boolean isNight, int textColor, int textShadowColor, int shadowRadius) { + TextInfoWidget.updateTextColor(text, textShadow, textColor, textShadowColor, false, shadowRadius); + icon.setBackgroundResource(isNight ? R.drawable.ruler_night : R.drawable.ruler); + } + + public boolean updateInfo(RotatedTileBox tb, DrawSettings nightMode) { + boolean visible = true; + OsmandMapTileView view = mapActivity.getMapView(); + // update cache + if (view.isZooming()) { + visible = false; + } else if (!tb.isZoomAnimated() && (tb.getZoom() != cacheRulerZoom || Math.abs(tb.getCenterTileX() - cacheRulerTileX) > 1 || Math + .abs(tb.getCenterTileY() - cacheRulerTileY) > 1 || mapDensity.get() != cacheMapDensity) && + tb.getPixWidth() > 0 && maxWidth > 0) { + cacheRulerZoom = tb.getZoom(); + cacheRulerTileX = tb.getCenterTileX(); + cacheRulerTileY = tb.getCenterTileY(); + cacheMapDensity = mapDensity.get(); + double pixDensity = tb.getPixDensity(); + double roundedDist = OsmAndFormatter.calculateRoundedDist(maxWidth / + pixDensity, view.getApplication()); + + int cacheRulerDistPix = (int) (pixDensity * roundedDist); + cacheRulerText = OsmAndFormatter.getFormattedDistance((float) roundedDist, view.getApplication(), false); + textShadow.setText(cacheRulerText); + text.setText(cacheRulerText); + ViewGroup.LayoutParams lp = layout.getLayoutParams(); + lp.width = cacheRulerDistPix; + layout.setLayoutParams(lp); + layout.requestLayout(); + } + AndroidUiHelper.updateVisibility(layout, visible); + return true; + } + + public void setVisibility(boolean visibility) { + AndroidUiHelper.updateVisibility(layout, visibility); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/TextInfoWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/TextInfoWidget.java similarity index 87% rename from OsmAnd/src/net/osmand/plus/views/mapwidgets/TextInfoWidget.java rename to OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/TextInfoWidget.java index ff9cb8a325..1538c66753 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/TextInfoWidget.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/TextInfoWidget.java @@ -1,4 +1,4 @@ -package net.osmand.plus.views.mapwidgets; +package net.osmand.plus.views.mapwidgets.widgets; import android.app.Activity; import android.graphics.Paint.Style; @@ -19,7 +19,9 @@ import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; -public class TextInfoWidget { +public class TextInfoWidget { + + private OsmandApplication app; private String contentTitle; private View view; @@ -31,7 +33,6 @@ public class TextInfoWidget { private ImageView topImageView; protected TextView topTextView; private boolean explicitlyVisible; - private OsmandApplication app; private int dayIcon; private int nightIcon; @@ -44,35 +45,34 @@ public class TextInfoWidget { public TextInfoWidget(Activity activity) { app = (OsmandApplication) activity.getApplication(); view = UiUtilities.getInflater(activity, isNight).inflate(R.layout.map_hud_widget, null); - bottomLayout = (ViewGroup) view.findViewById(R.id.widget_bottom_layout); - topImageView = (ImageView) view.findViewById(R.id.widget_top_icon); - topTextView = (TextView) view.findViewById(R.id.widget_top_icon_text); - imageView = (ImageView) view.findViewById(R.id.widget_icon); - textView = (TextView) view.findViewById(R.id.widget_text); - textViewShadow = (TextView) view.findViewById(R.id.widget_text_shadow); - smallTextViewShadow = (TextView) view.findViewById(R.id.widget_text_small_shadow); - smallTextView = (TextView) view.findViewById(R.id.widget_text_small); + bottomLayout = view.findViewById(R.id.widget_bottom_layout); + topImageView = view.findViewById(R.id.widget_top_icon); + topTextView = view.findViewById(R.id.widget_top_icon_text); + imageView = view.findViewById(R.id.widget_icon); + textView = view.findViewById(R.id.widget_text); + textViewShadow = view.findViewById(R.id.widget_text_shadow); + smallTextViewShadow = view.findViewById(R.id.widget_text_small_shadow); + smallTextView = view.findViewById(R.id.widget_text_small); } - public OsmandApplication getOsmandApplication() { + public OsmandApplication getApplication() { return app; } public View getView() { return view; } - + public void setImageDrawable(Drawable imageDrawable) { setImageDrawable(imageDrawable, false); } - + public void setImageDrawable(int res) { setImageDrawable(app.getUIUtilities().getIcon(res, 0), false); } - - + public void setImageDrawable(Drawable imageDrawable, boolean gone) { - if(imageDrawable != null) { + if (imageDrawable != null) { imageView.setImageDrawable(imageDrawable); Object anim = imageView.getDrawable(); if (anim instanceof AnimationDrawable) { @@ -84,9 +84,9 @@ public class TextInfoWidget { } imageView.invalidate(); } - + public void setTopImageDrawable(Drawable imageDrawable, String topText) { - if(imageDrawable != null) { + if (imageDrawable != null) { topImageView.setImageDrawable(imageDrawable); topImageView.setVisibility(View.VISIBLE); LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) bottomLayout.getLayoutParams(); @@ -96,17 +96,17 @@ public class TextInfoWidget { topTextView.setVisibility(View.VISIBLE); topTextView.setText(topText == null ? "" : topText); } else { - topImageView.setVisibility(View.GONE ); - topTextView.setVisibility(View.GONE ); + topImageView.setVisibility(View.GONE); + topTextView.setVisibility(View.GONE); LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) bottomLayout.getLayoutParams(); lp.gravity = Gravity.NO_GRAVITY; bottomLayout.setLayoutParams(lp); } - + topTextView.invalidate(); topImageView.invalidate(); } - + public boolean setIcons(int widgetDayIcon, int widgetNightIcon) { if (dayIcon != widgetDayIcon || nightIcon != widgetNightIcon) { dayIcon = widgetDayIcon; @@ -134,7 +134,7 @@ public class TextInfoWidget { public void setContentDescription(CharSequence text) { view.setContentDescription(combine(contentTitle, text)); } - + public void setContentTitle(int messageId) { setContentTitle(view.getContext().getString(messageId)); } @@ -143,7 +143,7 @@ public class TextInfoWidget { contentTitle = text; setContentDescription(combine(textView.getText(), smallTextView.getText())); } - + public void setText(String text, String subtext) { setTextNoUpdateVisibility(text, subtext); updateVisibility(text != null); @@ -154,14 +154,14 @@ public class TextInfoWidget { // if(this.text != null && this.text.length() > 7) { // this.text = this.text.substring(0, 6) +".."; // } - if(text == null) { + if (text == null) { textView.setText(""); textViewShadow.setText(""); } else { textView.setText(text); textViewShadow.setText(text); } - if(subtext == null) { + if (subtext == null) { smallTextView.setText(""); smallTextViewShadow.setText(""); } else { @@ -169,7 +169,7 @@ public class TextInfoWidget { smallTextViewShadow.setText(subtext); } } - + protected boolean updateVisibility(boolean visible) { if (visible != (view.getVisibility() == View.VISIBLE)) { if (visible) { @@ -184,7 +184,7 @@ public class TextInfoWidget { } return false; } - + public boolean isVisible() { return view.getVisibility() == View.VISIBLE && view.getParent() != null; } @@ -223,15 +223,15 @@ public class TextInfoWidget { public void setExplicitlyVisible(boolean explicitlyVisible) { this.explicitlyVisible = explicitlyVisible; } - + public boolean isExplicitlyVisible() { return explicitlyVisible; } - + public void updateIconMode(boolean night) { isNight = night; - if(dayIcon != 0) { - setImageDrawable(!night? dayIcon : nightIcon); + if (dayIcon != 0) { + setImageDrawable(!night ? dayIcon : nightIcon); } } @@ -240,10 +240,10 @@ public class TextInfoWidget { updateTextColor(textView, textViewShadow, textColor, textShadowColor, bold, rad); updateTextColor(topTextView, null, textColor, textShadowColor, bold, rad); } - + public static void updateTextColor(TextView tv, TextView shadow, int textColor, int textShadowColor, boolean textBold, int rad) { - if(shadow != null) { - if(rad > 0) { + if (shadow != null) { + if (rad > 0) { shadow.setVisibility(View.VISIBLE); shadow.setTypeface(Typeface.DEFAULT, textBold ? Typeface.BOLD : Typeface.NORMAL); shadow.getPaint().setStrokeWidth(rad); @@ -258,4 +258,4 @@ public class TextInfoWidget { tv.setTextColor(textColor); tv.setTypeface(Typeface.DEFAULT, textBold ? Typeface.BOLD : Typeface.NORMAL); } -} +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/BearingWidgetState.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/BearingWidgetState.java new file mode 100644 index 0000000000..ce4761eab1 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/BearingWidgetState.java @@ -0,0 +1,53 @@ +package net.osmand.plus.views.mapwidgets.widgetstates; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.settings.backend.OsmandSettings; + +public class BearingWidgetState extends WidgetState { + + public static final int BEARING_WIDGET_STATE_RELATIVE_BEARING = R.id.bearing_widget_state_relative_bearing; + public static final int BEARING_WIDGET_STATE_MAGNETIC_BEARING = R.id.bearing_widget_state_magnetic_bearing; + + private final OsmandSettings.OsmandPreference showRelativeBearing; + + public BearingWidgetState(OsmandApplication ctx) { + super(ctx); + showRelativeBearing = ctx.getSettings().SHOW_RELATIVE_BEARING_OTHERWISE_REGULAR_BEARING; + } + + @Override + public int getMenuTitleId() { + return showRelativeBearing.get() ? R.string.map_widget_bearing : R.string.map_widget_magnetic_bearing; + } + + @Override + public int getMenuIconId() { + return showRelativeBearing.get() ? R.drawable.ic_action_relative_bearing : R.drawable.ic_action_bearing; + } + + @Override + public int getMenuItemId() { + return showRelativeBearing.get() ? BEARING_WIDGET_STATE_RELATIVE_BEARING : BEARING_WIDGET_STATE_MAGNETIC_BEARING; + } + + @Override + public int[] getMenuTitleIds() { + return new int[] {R.string.map_widget_magnetic_bearing, R.string.map_widget_bearing}; + } + + @Override + public int[] getMenuIconIds() { + return new int[] {R.drawable.ic_action_bearing, R.drawable.ic_action_relative_bearing}; + } + + @Override + public int[] getMenuItemIds() { + return new int[] {BEARING_WIDGET_STATE_MAGNETIC_BEARING, BEARING_WIDGET_STATE_RELATIVE_BEARING}; + } + + @Override + public void changeState(int stateId) { + showRelativeBearing.set(stateId == BEARING_WIDGET_STATE_RELATIVE_BEARING); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/CompassRulerWidgetState.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/CompassRulerWidgetState.java new file mode 100644 index 0000000000..eb77043746 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/CompassRulerWidgetState.java @@ -0,0 +1,53 @@ +package net.osmand.plus.views.mapwidgets.widgetstates; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference; + +public class CompassRulerWidgetState extends WidgetState { + + public static final int COMPASS_CONTROL_WIDGET_STATE_SHOW = R.id.compass_ruler_control_widget_state_show; + public static final int COMPASS_CONTROL_WIDGET_STATE_HIDE = R.id.compass_ruler_control_widget_state_hide; + + private final OsmandPreference showCompass; + + public CompassRulerWidgetState(OsmandApplication app) { + super(app); + showCompass = app.getSettings().SHOW_COMPASS_CONTROL_RULER; + } + + @Override + public int getMenuTitleId() { + return R.string.map_widget_ruler_control; + } + + @Override + public int getMenuIconId() { + return R.drawable.ic_action_ruler_circle; + } + + @Override + public int getMenuItemId() { + return showCompass.get() ? COMPASS_CONTROL_WIDGET_STATE_SHOW : COMPASS_CONTROL_WIDGET_STATE_HIDE; + } + + @Override + public int[] getMenuTitleIds() { + return new int[] {R.string.show_compass_ruler, R.string.hide_compass_ruler}; + } + + @Override + public int[] getMenuIconIds() { + return new int[] {R.drawable.ic_action_compass_widget, R.drawable.ic_action_compass_widget_hide}; + } + + @Override + public int[] getMenuItemIds() { + return new int[] {COMPASS_CONTROL_WIDGET_STATE_SHOW, COMPASS_CONTROL_WIDGET_STATE_HIDE}; + } + + @Override + public void changeState(int stateId) { + showCompass.set(stateId == COMPASS_CONTROL_WIDGET_STATE_SHOW); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/TimeWidgetState.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/TimeWidgetState.java new file mode 100644 index 0000000000..3274245a0c --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/TimeWidgetState.java @@ -0,0 +1,71 @@ +package net.osmand.plus.views.mapwidgets.widgetstates; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference; + +public class TimeWidgetState extends WidgetState { + + public static final int TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME = R.id.time_control_widget_state_arrival_time; + public static final int TIME_CONTROL_WIDGET_STATE_TIME_TO_GO = R.id.time_control_widget_state_time_to_go; + + private final OsmandPreference showArrival; + private final boolean intermediate; + + public TimeWidgetState(OsmandApplication app, boolean intermediate) { + super(app); + this.intermediate = intermediate; + if (intermediate) { + showArrival = app.getSettings().SHOW_INTERMEDIATE_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME; + } else { + showArrival = app.getSettings().SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME; + } + } + + @Override + public int getMenuTitleId() { + if (intermediate) { + return showArrival.get() ? R.string.access_intermediate_arrival_time : R.string.map_widget_intermediate_time; + } + return showArrival.get() ? R.string.access_arrival_time : R.string.map_widget_time; + } + + @Override + public int getMenuIconId() { + if (intermediate) { + return R.drawable.ic_action_intermediate_destination_time; + } + return showArrival.get() ? R.drawable.ic_action_time : R.drawable.ic_action_time_to_distance; + } + + @Override + public int getMenuItemId() { + return showArrival.get() ? TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME : TIME_CONTROL_WIDGET_STATE_TIME_TO_GO; + } + + @Override + public int[] getMenuTitleIds() { + if (intermediate) { + return new int[] {R.string.access_intermediate_arrival_time, R.string.map_widget_intermediate_time}; + } + return new int[] {R.string.access_arrival_time, R.string.map_widget_time}; + } + + @Override + public int[] getMenuIconIds() { + if (intermediate) { + return new int[] {R.drawable.ic_action_intermediate_destination_time, R.drawable.ic_action_intermediate_destination_time}; + } + return new int[] {R.drawable.ic_action_time, R.drawable.ic_action_time_to_distance}; + } + + @Override + public int[] getMenuItemIds() { + return new int[] {TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME, TIME_CONTROL_WIDGET_STATE_TIME_TO_GO}; + } + + @Override + public void changeState(int stateId) { + showArrival.set(stateId == TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/WidgetState.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/WidgetState.java new file mode 100644 index 0000000000..7a015f0c57 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgetstates/WidgetState.java @@ -0,0 +1,30 @@ +package net.osmand.plus.views.mapwidgets.widgetstates; + +import net.osmand.plus.OsmandApplication; + +public abstract class WidgetState { + + private OsmandApplication ctx; + + public OsmandApplication getCtx() { + return ctx; + } + + public WidgetState(OsmandApplication ctx) { + this.ctx = ctx; + } + + public abstract int getMenuTitleId(); + + public abstract int getMenuIconId(); + + public abstract int getMenuItemId(); + + public abstract int[] getMenuTitleIds(); + + public abstract int[] getMenuIconIds(); + + public abstract int[] getMenuItemIds(); + + public abstract void changeState(int stateId); +} \ No newline at end of file