diff --git a/android/app/src/main/cpp/app/organicmaps/Framework.cpp b/android/app/src/main/cpp/app/organicmaps/Framework.cpp index 97538f58f7..fe5897546f 100644 --- a/android/app/src/main/cpp/app/organicmaps/Framework.cpp +++ b/android/app/src/main/cpp/app/organicmaps/Framework.cpp @@ -1670,6 +1670,18 @@ Java_app_organicmaps_Framework_nativeIsIsolinesLayerEnabled(JNIEnv * env, jclass return static_cast(frm()->LoadIsolinesEnabled()); } +JNIEXPORT void JNICALL +Java_app_organicmaps_Framework_nativeSetOutdoorsLayerEnabled(JNIEnv * env, jclass, jboolean enabled) +{ + frm()->SaveOutdoorsEnabled(enabled); +} + +JNIEXPORT jboolean JNICALL +Java_app_organicmaps_Framework_nativeIsOutdoorsLayerEnabled(JNIEnv * env, jclass) +{ + return static_cast(frm()->LoadOutdoorsEnabled()); +} + JNIEXPORT void JNICALL Java_app_organicmaps_Framework_nativeSaveSettingSchemeEnabled(JNIEnv * env, jclass, jboolean enabled) { diff --git a/android/app/src/main/java/app/organicmaps/Framework.java b/android/app/src/main/java/app/organicmaps/Framework.java index 0be82101d7..c846ddfd7d 100644 --- a/android/app/src/main/java/app/organicmaps/Framework.java +++ b/android/app/src/main/java/app/organicmaps/Framework.java @@ -38,7 +38,7 @@ import java.util.Locale; public class Framework { @Retention(RetentionPolicy.SOURCE) - @IntDef({MAP_STYLE_CLEAR, MAP_STYLE_DARK, MAP_STYLE_VEHICLE_CLEAR, MAP_STYLE_VEHICLE_DARK}) + @IntDef({MAP_STYLE_CLEAR, MAP_STYLE_DARK, MAP_STYLE_VEHICLE_CLEAR, MAP_STYLE_VEHICLE_DARK, MAP_STYLE_OUTDOORS_CLEAR, MAP_STYLE_OUTDOORS_DARK}) public @interface MapStyle {} @@ -46,6 +46,8 @@ public class Framework public static final int MAP_STYLE_DARK = 1; public static final int MAP_STYLE_VEHICLE_CLEAR = 3; public static final int MAP_STYLE_VEHICLE_DARK = 4; + public static final int MAP_STYLE_OUTDOORS_CLEAR = 5; + public static final int MAP_STYLE_OUTDOORS_DARK = 6; @Retention(RetentionPolicy.SOURCE) @IntDef({ ROUTER_TYPE_VEHICLE, ROUTER_TYPE_PEDESTRIAN, ROUTER_TYPE_BICYCLE, ROUTER_TYPE_TRANSIT, ROUTER_TYPE_RULER }) @@ -365,6 +367,10 @@ public class Framework public static native boolean nativeIsIsolinesLayerEnabled(); + public static native void nativeSetOutdoorsLayerEnabled(boolean enabled); + + public static native boolean nativeIsOutdoorsLayerEnabled(); + @NonNull public static native MapObject nativeDeleteBookmarkFromMapObject(); diff --git a/android/app/src/main/java/app/organicmaps/MwmActivity.java b/android/app/src/main/java/app/organicmaps/MwmActivity.java index 2a15fda177..8e8e6d5bcf 100644 --- a/android/app/src/main/java/app/organicmaps/MwmActivity.java +++ b/android/app/src/main/java/app/organicmaps/MwmActivity.java @@ -187,7 +187,6 @@ public class MwmActivity extends BaseMwmFragmentActivity private PlacePageViewModel mPlacePageViewModel; private MapButtonsViewModel mMapButtonsViewModel; private MapButtonsController.LayoutMode mPreviousMapLayoutMode; - private Mode mPreviousLayerMode; @Nullable private WindowInsetsCompat mCurrentWindowInsets; @@ -475,8 +474,6 @@ public class MwmActivity extends BaseMwmFragmentActivity // We don't need to manually handle removing the observers it follows the activity lifecycle mMapButtonsViewModel.getBottomButtonsHeight().observe(this, this::onMapBottomButtonsHeightChange); mMapButtonsViewModel.getLayoutMode().observe(this, this::initNavigationButtons); - mPreviousLayerMode = mMapButtonsViewModel.getMapLayerMode().getValue(); - mMapButtonsViewModel.getMapLayerMode().observe(this, this::onLayerChange); mSearchController = new FloatingSearchToolbarController(this, this); mSearchController.getToolbar() @@ -2133,13 +2130,6 @@ public class MwmActivity extends BaseMwmFragmentActivity shareMyLocation(); } - public void onLayerChange(Mode mode) - { - if (mPreviousLayerMode != mode) - closeFloatingPanels(); - mPreviousLayerMode = mode; - } - @Override @Nullable public ArrayList getMenuBottomSheetItems(String id) diff --git a/android/app/src/main/java/app/organicmaps/maplayer/LayerBottomSheetItem.java b/android/app/src/main/java/app/organicmaps/maplayer/LayerBottomSheetItem.java index 8c6c6248a3..11c0c48f0c 100644 --- a/android/app/src/main/java/app/organicmaps/maplayer/LayerBottomSheetItem.java +++ b/android/app/src/main/java/app/organicmaps/maplayer/LayerBottomSheetItem.java @@ -44,6 +44,11 @@ public class LayerBottomSheetItem int buttonTextResource = R.string.layers_title; switch (mode) { + case OUTDOORS: + disabledResource = R.attr.outdoorsMenuDisabled; + enabledResource = R.attr.outdoorsMenuEnabled; + buttonTextResource = R.string.button_layer_outdoor; + break; case SUBWAY: disabledResource = R.attr.subwayMenuDisabled; enabledResource = R.attr.subwayMenuEnabled; diff --git a/android/app/src/main/java/app/organicmaps/maplayer/LayersUtils.java b/android/app/src/main/java/app/organicmaps/maplayer/LayersUtils.java index 5e08fa02e6..ad022fd865 100644 --- a/android/app/src/main/java/app/organicmaps/maplayer/LayersUtils.java +++ b/android/app/src/main/java/app/organicmaps/maplayer/LayersUtils.java @@ -8,6 +8,7 @@ public class LayersUtils public static List getAvailableLayers() { List availableLayers = new ArrayList<>(); + availableLayers.add(Mode.OUTDOORS); availableLayers.add(Mode.ISOLINES); availableLayers.add(Mode.SUBWAY); return availableLayers; diff --git a/android/app/src/main/java/app/organicmaps/maplayer/MapButtonsController.java b/android/app/src/main/java/app/organicmaps/maplayer/MapButtonsController.java index 4750faa6d1..94cbbc6f9c 100644 --- a/android/app/src/main/java/app/organicmaps/maplayer/MapButtonsController.java +++ b/android/app/src/main/java/app/organicmaps/maplayer/MapButtonsController.java @@ -25,7 +25,6 @@ import app.organicmaps.routing.RoutingController; import app.organicmaps.util.Config; import app.organicmaps.util.ThemeUtils; import app.organicmaps.util.UiUtils; -import app.organicmaps.util.Utils; import app.organicmaps.widget.menu.MyPositionButton; import app.organicmaps.widget.placepage.PlacePageViewModel; import com.google.android.material.badge.BadgeDrawable; @@ -44,7 +43,7 @@ public class MapButtonsController extends Fragment @Nullable private View mBottomButtonsFrame; @Nullable - private MapLayersController mToggleMapLayerController; + private FloatingActionButton mToggleMapLayerButton; @Nullable private MyPositionButton mNavMyPosition; @@ -60,7 +59,6 @@ public class MapButtonsController extends Fragment private final Observer mPlacePageDistanceToTopObserver = this::move; private final Observer mButtonHiddenObserver = this::setButtonsHidden; private final Observer mMyPositionModeObserver = this::updateNavMyPositionButton; - private final Observer mMapLayerModeObserver = this::toggleMapLayer; private final Observer mSearchOptionObserver = this::onSearchOptionChange; @@ -107,14 +105,11 @@ public class MapButtonsController extends Fragment mNavMyPosition = new MyPositionButton(myPosition, (v) -> mMapButtonClickListener.onMapButtonClick(MapButtons.myPosition)); // Some buttons do not exist in navigation mode - final FloatingActionButton layersButton = mFrame.findViewById(R.id.layers_button); - if (layersButton != null) + mToggleMapLayerButton = mFrame.findViewById(R.id.layers_button); + if (mToggleMapLayerButton != null) { - mToggleMapLayerController = new MapLayersController( - layersButton, - () -> mMapButtonClickListener.onMapButtonClick(MapButtons.toggleMapLayer), - requireActivity(), - mMapButtonsViewModel); + mToggleMapLayerButton.setOnClickListener(view -> mMapButtonClickListener.onMapButtonClick(MapButtons.toggleMapLayer)); + mToggleMapLayerButton.setVisibility(View.VISIBLE); } final View menuButton = mFrame.findViewById(R.id.menu_button); if (menuButton != null) @@ -148,8 +143,8 @@ public class MapButtonsController extends Fragment mButtonsMap.put(MapButtons.bookmarks, bookmarksButton); mButtonsMap.put(MapButtons.search, searchButton); - if (layersButton != null) - mButtonsMap.put(MapButtons.toggleMapLayer, layersButton); + if (mToggleMapLayerButton != null) + mButtonsMap.put(MapButtons.toggleMapLayer, mToggleMapLayerButton); if (menuButton != null) mButtonsMap.put(MapButtons.menu, menuButton); if (helpButton != null) @@ -174,8 +169,8 @@ public class MapButtonsController extends Fragment UiUtils.showIf(show && Config.showZoomButtons(), buttonView); break; case toggleMapLayer: - if (mToggleMapLayerController != null) - mToggleMapLayerController.showButton(show && !isInNavigationMode()); + if (mToggleMapLayerButton != null) + UiUtils.showIf(show && !isInNavigationMode(), mToggleMapLayerButton); break; case myPosition: if (mNavMyPosition != null) @@ -293,17 +288,6 @@ public class MapButtonsController extends Fragment return RoutingController.get().isPlanning() || RoutingController.get().isNavigating(); } - public void toggleMapLayer(@Nullable Mode mode) - { - if (mToggleMapLayerController != null) - { - if (mode == null) - mToggleMapLayerController.disableModes(); - else - mToggleMapLayerController.enableMode(mode); - } - } - public void updateNavMyPositionButton(int newMode) { if (mNavMyPosition != null) @@ -323,7 +307,6 @@ public class MapButtonsController extends Fragment mPlacePageViewModel.getPlacePageDistanceToTop().observe(activity, mPlacePageDistanceToTopObserver); mMapButtonsViewModel.getButtonsHidden().observe(activity, mButtonHiddenObserver); mMapButtonsViewModel.getMyPositionMode().observe(activity, mMyPositionModeObserver); - mMapButtonsViewModel.getMapLayerMode().observe(activity, mMapLayerModeObserver); mMapButtonsViewModel.getSearchOption().observe(activity, mSearchOptionObserver); } @@ -341,7 +324,6 @@ public class MapButtonsController extends Fragment mPlacePageViewModel.getPlacePageDistanceToTop().removeObserver(mPlacePageDistanceToTopObserver); mMapButtonsViewModel.getButtonsHidden().removeObserver(mButtonHiddenObserver); mMapButtonsViewModel.getMyPositionMode().removeObserver(mMyPositionModeObserver); - mMapButtonsViewModel.getMapLayerMode().removeObserver(mMapLayerModeObserver); mMapButtonsViewModel.getSearchOption().removeObserver(mSearchOptionObserver); } diff --git a/android/app/src/main/java/app/organicmaps/maplayer/MapButtonsViewModel.java b/android/app/src/main/java/app/organicmaps/maplayer/MapButtonsViewModel.java index eb50db7202..051166bfb2 100644 --- a/android/app/src/main/java/app/organicmaps/maplayer/MapButtonsViewModel.java +++ b/android/app/src/main/java/app/organicmaps/maplayer/MapButtonsViewModel.java @@ -10,7 +10,6 @@ public class MapButtonsViewModel extends ViewModel private final MutableLiveData mBottomButtonsHeight = new MutableLiveData<>(0f); private final MutableLiveData mLayoutMode = new MutableLiveData<>(MapButtonsController.LayoutMode.regular); private final MutableLiveData mMyPositionMode = new MutableLiveData<>(); - private final MutableLiveData mMapLayerMode = new MutableLiveData<>(); private final MutableLiveData mSearchOption = new MutableLiveData<>(); public MutableLiveData getButtonsHidden() @@ -53,16 +52,6 @@ public class MapButtonsViewModel extends ViewModel mMyPositionMode.setValue(mode); } - public MutableLiveData getMapLayerMode() - { - return mMapLayerMode; - } - - public void setMapLayerMode(Mode mode) - { - mMapLayerMode.setValue(mode); - } - public MutableLiveData getSearchOption() { return mSearchOption; diff --git a/android/app/src/main/java/app/organicmaps/maplayer/MapLayersController.java b/android/app/src/main/java/app/organicmaps/maplayer/MapLayersController.java deleted file mode 100644 index ab39c9b8c2..0000000000 --- a/android/app/src/main/java/app/organicmaps/maplayer/MapLayersController.java +++ /dev/null @@ -1,102 +0,0 @@ -package app.organicmaps.maplayer; - -import android.app.Activity; -import android.widget.ImageButton; - -import androidx.annotation.NonNull; -import app.organicmaps.R; -import app.organicmaps.util.Graphics; -import app.organicmaps.util.UiUtils; - -import java.util.List; - -public class MapLayersController -{ - @NonNull - private final Activity mActivity; - @NonNull - private final List mLayers; - @NonNull - private final ImageButton mLayersButton; - @NonNull - OnShowMenuListener mOnShowMenuListener; - @NonNull - private Mode mCurrentLayer; - private final MapButtonsViewModel mMapButtonsViewModel; - - public MapLayersController(@NonNull ImageButton layersButton, @NonNull OnShowMenuListener onShowMenuListener, @NonNull Activity activity, MapButtonsViewModel mapButtonsViewModel) - { - mActivity = activity; - mMapButtonsViewModel = mapButtonsViewModel; - mLayersButton = layersButton; - mLayersButton.setOnClickListener(view -> onLayersButtonClick()); - mOnShowMenuListener = onShowMenuListener; - mLayers = LayersUtils.getAvailableLayers(); - mCurrentLayer = getCurrentLayer(); - // View model only expects a layer if it is active - mMapButtonsViewModel.setMapLayerMode(mCurrentLayer.isEnabled(activity) ? mCurrentLayer : null); - showButton(true); - } - - @NonNull - private Mode getCurrentLayer() - { - for (Mode each : mLayers) - { - if (each.isEnabled(mActivity)) - return each; - } - return mLayers.iterator().next(); - } - - private void setCurrentLayer(@NonNull Mode mode) - { - for (Mode each : mLayers) - { - if (each == mode) - mCurrentLayer = each; - else - each.setEnabled(mActivity, false); - } - } - - private void setEnabled(boolean enabled) - { - mLayersButton.setSelected(enabled); - mCurrentLayer.setEnabled(mActivity, enabled); - int drawable = R.drawable.ic_layers; - if (enabled) - drawable = R.drawable.ic_layers_clear; - mLayersButton.setImageDrawable(Graphics.tint(mLayersButton.getContext(), drawable)); - } - - private void onLayersButtonClick() - { - if (mCurrentLayer.isEnabled(mActivity)) - mMapButtonsViewModel.setMapLayerMode(null); - else - mOnShowMenuListener.onShow(); - } - - public void disableModes() - { - setEnabled(false); - } - - public void enableMode(@NonNull Mode mode) - { - setCurrentLayer(mode); - showButton(true); - setEnabled(true); - } - - public void showButton(boolean show) - { - UiUtils.showIf(show, mLayersButton); - } - - public interface OnShowMenuListener - { - void onShow(); - } -} diff --git a/android/app/src/main/java/app/organicmaps/maplayer/Mode.java b/android/app/src/main/java/app/organicmaps/maplayer/Mode.java index 34c3e192d4..2c5204f73f 100644 --- a/android/app/src/main/java/app/organicmaps/maplayer/Mode.java +++ b/android/app/src/main/java/app/organicmaps/maplayer/Mode.java @@ -4,9 +4,11 @@ import android.content.Context; import androidx.annotation.NonNull; +import app.organicmaps.Framework; import app.organicmaps.maplayer.isolines.IsolinesManager; import app.organicmaps.maplayer.subway.SubwayManager; import app.organicmaps.maplayer.traffic.TrafficManager; +import app.organicmaps.util.ThemeSwitcher; public enum Mode { @@ -53,6 +55,21 @@ public enum Mode { IsolinesManager.from(context).setEnabled(isEnabled); } + }, + OUTDOORS + { + @Override + public boolean isEnabled(@NonNull Context context) + { + return Framework.nativeIsOutdoorsLayerEnabled(); + } + + @Override + public void setEnabled(@NonNull Context context, boolean isEnabled) + { + Framework.nativeSetOutdoorsLayerEnabled(isEnabled); + ThemeSwitcher.INSTANCE.restart(true); + } }; public abstract boolean isEnabled(@NonNull Context context); diff --git a/android/app/src/main/java/app/organicmaps/maplayer/ToggleMapLayerFragment.java b/android/app/src/main/java/app/organicmaps/maplayer/ToggleMapLayerFragment.java index 82181db600..39de202685 100644 --- a/android/app/src/main/java/app/organicmaps/maplayer/ToggleMapLayerFragment.java +++ b/android/app/src/main/java/app/organicmaps/maplayer/ToggleMapLayerFragment.java @@ -67,9 +67,9 @@ public class ToggleMapLayerFragment extends Fragment Mode mode = item.getMode(); Context context = v.getContext(); SharedPropertiesUtils.setLayerMarkerShownForLayerMode(context, mode); + mode.setEnabled(context, !mode.isEnabled(context)); mAdapter.notifyDataSetChanged(); if (IsolinesManager.from(context).shouldShowNotification()) Utils.showSnackbar(context, v.getRootView(), R.string.isolines_toast_zooms_1_10); - mMapButtonsViewModel.setMapLayerMode(mode); } } diff --git a/android/app/src/main/java/app/organicmaps/maplayer/isolines/IsolinesManager.java b/android/app/src/main/java/app/organicmaps/maplayer/isolines/IsolinesManager.java index 06f3651e47..250b95d347 100644 --- a/android/app/src/main/java/app/organicmaps/maplayer/isolines/IsolinesManager.java +++ b/android/app/src/main/java/app/organicmaps/maplayer/isolines/IsolinesManager.java @@ -36,11 +36,6 @@ public class IsolinesManager Framework.nativeSetIsolinesLayerEnabled(isEnabled); } - public void toggle() - { - setEnabled(!isEnabled()); - } - public void initialize() { registerListener(); diff --git a/android/app/src/main/java/app/organicmaps/util/ThemeSwitcher.java b/android/app/src/main/java/app/organicmaps/util/ThemeSwitcher.java index c0f7e5f76e..8d66c2d631 100644 --- a/android/app/src/main/java/app/organicmaps/util/ThemeSwitcher.java +++ b/android/app/src/main/java/app/organicmaps/util/ThemeSwitcher.java @@ -90,24 +90,33 @@ public enum ThemeSwitcher private void setThemeAndMapStyle(@NonNull String theme) { String oldTheme = Config.getCurrentUiTheme(mContext); - Config.setCurrentUiTheme(mContext, theme); - changeMapStyle(theme, oldTheme); - } - - @androidx.annotation.UiThread - private void changeMapStyle(@NonNull String newTheme, @NonNull String oldTheme) - { @Framework.MapStyle - int style = RoutingController.get().isVehicleNavigation() - ? Framework.MAP_STYLE_VEHICLE_CLEAR : Framework.MAP_STYLE_CLEAR; - if (ThemeUtils.isNightTheme(mContext, newTheme)) - style = RoutingController.get().isVehicleNavigation() - ? Framework.MAP_STYLE_VEHICLE_DARK : Framework.MAP_STYLE_DARK; + int oldStyle = Framework.nativeGetMapStyle(); - if (!newTheme.equals(oldTheme)) + @Framework.MapStyle + int style; + if (ThemeUtils.isNightTheme(mContext, theme)) { - SetMapStyle(style); + if (RoutingController.get().isVehicleNavigation()) + style = Framework.MAP_STYLE_VEHICLE_DARK; + else if (Framework.nativeIsOutdoorsLayerEnabled()) + style = Framework.MAP_STYLE_OUTDOORS_DARK; + else + style = Framework.MAP_STYLE_DARK; + } + else + { + if (RoutingController.get().isVehicleNavigation()) + style = Framework.MAP_STYLE_VEHICLE_CLEAR; + else if (Framework.nativeIsOutdoorsLayerEnabled()) + style = Framework.MAP_STYLE_OUTDOORS_CLEAR; + else + style = Framework.MAP_STYLE_CLEAR; + } + if (!theme.equals(oldTheme)) + { + Config.setCurrentUiTheme(mContext, theme); DownloaderStatusIcon.clearCache(); final Activity a = MwmApplication.from(mContext).getTopActivity(); diff --git a/android/app/src/main/res/values/attrs.xml b/android/app/src/main/res/values/attrs.xml index 6bb6a116fe..f28accc2f5 100644 --- a/android/app/src/main/res/values/attrs.xml +++ b/android/app/src/main/res/values/attrs.xml @@ -45,9 +45,11 @@ + + diff --git a/android/app/src/main/res/values/themes-base.xml b/android/app/src/main/res/values/themes-base.xml index 95d057cc82..ee0c93c0e0 100644 --- a/android/app/src/main/res/values/themes-base.xml +++ b/android/app/src/main/res/values/themes-base.xml @@ -89,9 +89,11 @@ @color/black_4 @color/black_4 @drawable/dot_divider + @drawable/ic_layers_outdoors_active @drawable/ic_layers_traffic_active @drawable/ic_layers_subway_active @drawable/ic_layers_isoline_active + @drawable/ic_layers_outdoors_inactive @drawable/ic_layers_traffic_inactive @drawable/ic_layers_subway_inactive @drawable/ic_layers_isoline_inactive diff --git a/map/framework.cpp b/map/framework.cpp index b7d2c31c66..14926fed62 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -101,6 +101,7 @@ char const kAllowAutoZoom[] = "AutoZoom"; char const kTrafficEnabledKey[] = "TrafficEnabled"; char const kTransitSchemeEnabledKey[] = "TransitSchemeEnabled"; char const kIsolinesEnabledKey[] = "IsolinesEnabled"; +char const kOutdoorsEnabledKey[] = "OutdoorsEnabled"; char const kTrafficSimplifiedColorsKey[] = "TrafficSimplifiedColors"; char const kLargeFontsSize[] = "LargeFontsSize"; char const kTranslitMode[] = "TransliterationMode"; @@ -2496,6 +2497,19 @@ void Framework::SaveIsolinesEnabled(bool enabled) settings::Set(kIsolinesEnabledKey, enabled); } +bool Framework::LoadOutdoorsEnabled() +{ + bool enabled; + if (!settings::Get(kOutdoorsEnabledKey, enabled)) + enabled = false; + return enabled; +} + +void Framework::SaveOutdoorsEnabled(bool enabled) +{ + settings::Set(kOutdoorsEnabledKey, enabled); +} + void Framework::EnableChoosePositionMode(bool enable, bool enableBounds, bool applyPosition, m2::PointD const & position) { diff --git a/map/framework.hpp b/map/framework.hpp index e411e7d9a8..507a07f8b6 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -700,6 +700,9 @@ public: bool LoadIsolinesEnabled(); void SaveIsolinesEnabled(bool enabled); + bool LoadOutdoorsEnabled(); + void SaveOutdoorsEnabled(bool enabled); + dp::ApiVersion LoadPreferredGraphicsAPI(); void SavePreferredGraphicsAPI(dp::ApiVersion apiVersion);