From 3975f6799aea02313d8bfa28c0a163a99d4b80ee Mon Sep 17 00:00:00 2001 From: 0xRe1nk0 <0xre1nk0@gmail.com> Date: Wed, 25 Dec 2024 18:16:25 +0200 Subject: [PATCH 01/10] add route legend card --- OsmAnd/res/layout/fragment_mtb_routes.xml | 10 ++ OsmAnd/res/layout/route_legend_card.xml | 45 +++++++++ OsmAnd/res/layout/route_legend_item.xml | 78 +++++++++++++++ .../plus/configmap/MtbRoutesFragment.java | 20 +++- .../plus/configmap/RouteLegendCard.java | 99 +++++++++++++++++++ 5 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 OsmAnd/res/layout/route_legend_card.xml create mode 100644 OsmAnd/res/layout/route_legend_item.xml create mode 100644 OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java diff --git a/OsmAnd/res/layout/fragment_mtb_routes.xml b/OsmAnd/res/layout/fragment_mtb_routes.xml index eb19e5e4622..1dddc9e261a 100644 --- a/OsmAnd/res/layout/fragment_mtb_routes.xml +++ b/OsmAnd/res/layout/fragment_mtb_routes.xml @@ -64,6 +64,16 @@ </LinearLayout> + <include layout="@layout/list_item_divider" /> + + <LinearLayout + android:id="@+id/legend_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + </LinearLayout> + <include android:id="@+id/bottom_divider" layout="@layout/card_bottom_divider" /> diff --git a/OsmAnd/res/layout/route_legend_card.xml b/OsmAnd/res/layout/route_legend_card.xml new file mode 100644 index 00000000000..56cf2023571 --- /dev/null +++ b/OsmAnd/res/layout/route_legend_card.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/route_legend_card" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout + android:id="@+id/properties_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/list_background_color" + android:orientation="vertical"> + + <net.osmand.plus.widgets.TextViewEx + android:id="@+id/card_title" + style="@style/TitleStyle.Medium" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/content_padding" + android:layout_marginVertical="@dimen/content_padding_small" + android:textColor="?android:textColorPrimary" + tools:text="Legend" /> + + <LinearLayout + android:id="@+id/classification_properties" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + </LinearLayout> + + </LinearLayout> + + <LinearLayout + android:id="@+id/main_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/list_background_color" + android:orientation="vertical"> + + </LinearLayout> + +</LinearLayout> \ No newline at end of file diff --git a/OsmAnd/res/layout/route_legend_item.xml b/OsmAnd/res/layout/route_legend_item.xml new file mode 100644 index 00000000000..0351d0d4313 --- /dev/null +++ b/OsmAnd/res/layout/route_legend_item.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/main_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/selectableItemBackground" + android:descendantFocusability="blocksDescendants" + android:gravity="center" + android:orientation="horizontal"> + + <androidx.appcompat.widget.AppCompatImageView + android:id="@+id/icon" + android:layout_width="@dimen/standard_icon_size" + android:layout_height="@dimen/standard_icon_size" + android:layout_marginStart="@dimen/content_padding" + android:layout_marginEnd="@dimen/favorites_icon_right_margin" + android:src="@drawable/ic_action_route_direction_here" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="@dimen/setting_profile_item_height" + android:orientation="horizontal"> + + <LinearLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:gravity="center" + android:orientation="vertical"> + + <TextView + android:id="@+id/title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="2" + android:textColor="?android:textColorPrimary" + android:textSize="@dimen/default_list_text_size" + tools:text="Title" /> + + <TextView + android:id="@+id/description" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="1" + android:textColor="?android:textColorSecondary" + android:textSize="@dimen/default_desc_text_size" + tools:text="Description" /> + + </LinearLayout> + + <androidx.appcompat.widget.SwitchCompat + android:id="@+id/compound_button" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center_vertical|end" + android:background="@null" + android:focusableInTouchMode="true" + android:padding="@dimen/content_padding" /> + + </LinearLayout> + + <View + android:id="@+id/divider_bottom" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?attr/list_divider" /> + + </LinearLayout> + +</LinearLayout> \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/MtbRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/MtbRoutesFragment.java index 8d168156a54..bbba0646405 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/MtbRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/MtbRoutesFragment.java @@ -15,6 +15,7 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.configmap.RouteLegendCard.DataClass; import net.osmand.plus.configmap.routes.MtbClassification; import net.osmand.plus.configmap.routes.RouteLayersHelper; import net.osmand.plus.helpers.AndroidUiHelper; @@ -25,6 +26,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.IntStream; public class MtbRoutesFragment extends BaseOsmAndFragment { @@ -55,6 +57,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, setupClassifications(view); updateClassificationPreferences(); + setupLegendCard(view); return view; } @@ -85,6 +88,22 @@ private void setupClassifications(@NonNull View view) { } } + @NonNull + private List<DataClass> getDataClasses() { + return IntStream.rangeClosed(1, 9) + .mapToObj(i -> new DataClass("Legend item " + i, "Description")) + .toList(); + } + + private void setupLegendCard(@NonNull View view) { + List<DataClass> items = getDataClasses(); + + RouteLegendCard card = new RouteLegendCard(requireActivity(), items, app.getString(R.string.shared_string_legend)); + ViewGroup group = view.findViewById(R.id.legend_container); + View cardView = card.build(); + group.addView(cardView); + } + private View createRadioButton(@NonNull MtbClassification classification, @NonNull LayoutInflater inflater, @Nullable ViewGroup container, boolean hasDivider) { View view = inflater.inflate(R.layout.item_with_radiobutton_and_descr, container, false); view.setTag(classification); @@ -142,5 +161,4 @@ public static void showInstance(@NonNull FragmentManager manager) { .commitAllowingStateLoss(); } } - } diff --git a/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java b/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java new file mode 100644 index 00000000000..be8c0127060 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java @@ -0,0 +1,99 @@ +package net.osmand.plus.configmap; + +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.FragmentActivity; + +import net.osmand.plus.R; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.utils.AndroidUtils; +import net.osmand.plus.utils.UiUtilities; + +import java.util.List; + +public class RouteLegendCard extends BaseCard { + private final LayoutInflater themedInflater; + + private final List<DataClass> items; + private final String cardTitle; + + public RouteLegendCard(@NonNull FragmentActivity activity, @NonNull List<DataClass> items, @NonNull String cardTitle) { + super(activity, true); + this.items = items; + this.cardTitle = cardTitle; + themedInflater = UiUtilities.getInflater(activity, nightMode); + } + + @Override + public int getCardLayoutId() { + return R.layout.route_legend_card; + } + + @Override + protected void updateContent() { + setupCardTitle(); + setupLegendItems(); + } + + private void setupLegendItems() { + ViewGroup mainContainer = view.findViewById(R.id.main_container); + mainContainer.removeAllViews(); + for (int i = 0; i < items.size(); i++) { + mainContainer.addView(createView(i)); + } + } + + @NonNull + private View createView(int position) { + DataClass dataClass = items.get(position); + View itemView = themedInflater.inflate(R.layout.route_legend_item, null, false); + CompoundButton compoundButton = itemView.findViewById(R.id.compound_button); + TextView title = itemView.findViewById(R.id.title); + TextView description = itemView.findViewById(R.id.description); + View divider = itemView.findViewById(R.id.divider_bottom); + + title.setText(dataClass.title()); + description.setText(dataClass.description()); + + compoundButton.setChecked(isClassEnabled(dataClass)); + + AndroidUiHelper.updateVisibility(divider, position != items.size() - 1); + itemView.setOnClickListener(view -> { + compoundButton.performClick(); + onClassSelected(dataClass, compoundButton.isChecked()); + }); + + compoundButton.setFocusable(false); + compoundButton.setClickable(false); + + OsmandSettings settings = app.getSettings(); + Drawable background = UiUtilities.getColoredSelectableDrawable(app, settings.getApplicationMode().getProfileColor(nightMode), 0.3f); + AndroidUtils.setBackground(itemView, background); + + return itemView; + } + + private void setupCardTitle() { + TextView title = view.findViewById(R.id.card_title); + title.setText(cardTitle); + } + + public boolean isClassEnabled(@NonNull DataClass dataClass) { + return false; + } + + public void onClassSelected(@NonNull DataClass dataClass, boolean checked) { + + } + + public record DataClass(String title, String description) { + } +} From a9be1650d30752b6ad1fc4018238e2437d4e7819 Mon Sep 17 00:00:00 2001 From: 0xRe1nk0 <0xre1nk0@gmail.com> Date: Wed, 8 Jan 2025 10:22:32 +0200 Subject: [PATCH 02/10] add rendering class support/link with colors attributes --- .../net/osmand/render/RenderingClass.java | 59 +++++++++++ .../osmand/render/RenderingRulesStorage.java | 25 +++++ OsmAnd/res/layout/fragment_mtb_routes.xml | 14 --- .../res/layout/map_route_types_fragment.xml | 14 +++ OsmAnd/res/layout/route_legend_item.xml | 6 +- .../plus/configmap/HikingRoutesFragment.java | 24 +++++ .../plus/configmap/MtbRoutesFragment.java | 19 ---- .../plus/configmap/RouteLegendCard.java | 10 +- .../plus/configmap/routes/RClassUtils.java | 99 +++++++++++++++++++ 9 files changed, 233 insertions(+), 37 deletions(-) create mode 100644 OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java create mode 100644 OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java new file mode 100644 index 00000000000..ca94585995e --- /dev/null +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java @@ -0,0 +1,59 @@ +package net.osmand.render; + +import java.util.List; +import java.util.ArrayList; + +public class RenderingClass { + private final String name; + private final String title; + private final boolean enable; + private String path; + private final List<RenderingClass> children = new ArrayList<>(); + + public RenderingClass(String name, String title, boolean enable) { + this.name = name; + this.title = title; + this.enable = enable; + } + + public String getName() { + return name; + } + + public String getTitle() { + return title; + } + + public boolean isEnable() { + return enable; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public List<RenderingClass> getChildren() { + return children; + } + + public void addChild(RenderingClass child) { + children.add(child); + } + + public RenderingClass findByPath(String path) { + if (this.path.equals(path)) { + return this; + } + for (RenderingClass child : children) { + RenderingClass result = child.findByPath(path); + if (result != null) { + return result; + } + } + return null; + } +} \ No newline at end of file diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java index 2b639e050c9..f56e7942272 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java @@ -55,6 +55,7 @@ public class RenderingRulesStorage { protected Map<String, RenderingRule> renderingAttributes = new LinkedHashMap<String, RenderingRule>(); protected Map<String, RenderingRule> renderingAssociations = new LinkedHashMap<String, RenderingRule>(); + protected Map<String, RenderingClass> renderingClasses = new LinkedHashMap<String, RenderingClass>(); protected Map<String, String> renderingConstants = new LinkedHashMap<String, String>(); protected String renderingName; @@ -271,6 +272,7 @@ private class RenderingRulesHandler { private final XmlPullParser parser; private int state; Stack<RenderingRule> stack = new Stack<RenderingRule>(); + private final Stack<RenderingClass> renderingClassStack = new Stack<>(); private final RenderingRulesStorageResolver resolver; private final boolean addon; private RenderingRulesStorage dependsStorage; @@ -431,6 +433,23 @@ public void startElement(Map<String, String> attrsMap, String name) throws XmlPu } } else if ("renderer".equals(name)) { //$NON-NLS-1$ throw new XmlPullParserException("Rendering style is deprecated and no longer supported."); + }else if ("renderingClass".equals(name)) { + String className = parser.getAttributeValue(null, "name"); + String title = parser.getAttributeValue(null, "title"); + boolean enable = Boolean.parseBoolean(parser.getAttributeValue(null, "enable")); + + RenderingClass newClass = new RenderingClass(className, title, enable); + + if (!renderingClassStack.isEmpty()) { + RenderingClass parent = renderingClassStack.peek(); + parent.addChild(newClass); + newClass.setPath(parent.getPath() + className); + } else { + newClass.setPath(className); + } + + renderingClasses.put(newClass.getPath(), newClass); + renderingClassStack.push(newClass); } else { log.warn("Unknown tag : " + name); //$NON-NLS-1$ } @@ -483,6 +502,8 @@ public void endElement(String name) throws XmlPullParserException { stack.pop(); } else if ("renderingAssociation".equals(name)) { //$NON-NLS-1$ stack.pop(); + } else if ("renderingClass".equals(name)) { + renderingClassStack.pop(); } } } @@ -559,6 +580,10 @@ public RenderingRule getRule(int state, int key) { public RenderingRule getRenderingAttributeRule(String attribute) { return renderingAttributes.get(attribute); } + + public RenderingClass getRenderingClass(String path) { + return renderingClasses.get(path); + } public String[] getRenderingAttributeNames() { return renderingAttributes.keySet().toArray(new String[0]); diff --git a/OsmAnd/res/layout/fragment_mtb_routes.xml b/OsmAnd/res/layout/fragment_mtb_routes.xml index 1dddc9e261a..bdf1533a17e 100644 --- a/OsmAnd/res/layout/fragment_mtb_routes.xml +++ b/OsmAnd/res/layout/fragment_mtb_routes.xml @@ -64,20 +64,6 @@ </LinearLayout> - <include layout="@layout/list_item_divider" /> - - <LinearLayout - android:id="@+id/legend_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - </LinearLayout> - - <include - android:id="@+id/bottom_divider" - layout="@layout/card_bottom_divider" /> - <View android:id="@+id/bottom_empty_space" android:layout_width="match_parent" diff --git a/OsmAnd/res/layout/map_route_types_fragment.xml b/OsmAnd/res/layout/map_route_types_fragment.xml index ec808a87e37..b9cabbf7ee6 100644 --- a/OsmAnd/res/layout/map_route_types_fragment.xml +++ b/OsmAnd/res/layout/map_route_types_fragment.xml @@ -57,6 +57,20 @@ android:id="@+id/card_bottom_divider" layout="@layout/card_bottom_divider" /> + <include layout="@layout/list_item_divider" /> + + <LinearLayout + android:id="@+id/legend_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + </LinearLayout> + + <include + android:id="@+id/bottom_divider" + layout="@layout/card_bottom_divider" /> + <View android:id="@+id/bottom_empty_space" android:layout_width="match_parent" diff --git a/OsmAnd/res/layout/route_legend_item.xml b/OsmAnd/res/layout/route_legend_item.xml index 0351d0d4313..3083179037e 100644 --- a/OsmAnd/res/layout/route_legend_item.xml +++ b/OsmAnd/res/layout/route_legend_item.xml @@ -9,13 +9,15 @@ android:gravity="center" android:orientation="horizontal"> - <androidx.appcompat.widget.AppCompatImageView + <ImageView android:id="@+id/icon" android:layout_width="@dimen/standard_icon_size" android:layout_height="@dimen/standard_icon_size" android:layout_marginStart="@dimen/content_padding" android:layout_marginEnd="@dimen/favorites_icon_right_margin" - android:src="@drawable/ic_action_route_direction_here" /> + android:layout_gravity="center_vertical" + tools:src="@drawable/ic_action_track_line_bold_color" + tools:tint="?attr/default_icon_color" /> <LinearLayout android:layout_width="match_parent" diff --git a/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java index 70d3fc61710..7ae47997832 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java @@ -1,6 +1,8 @@ package net.osmand.plus.configmap; import static net.osmand.osm.OsmRouteType.HIKING; +import static net.osmand.plus.configmap.routes.RClassUtils.RClassType.HIKING_OSMC_NODES; +import static net.osmand.plus.configmap.routes.RClassUtils.getDataClasses; import android.os.Bundle; import android.view.LayoutInflater; @@ -18,6 +20,7 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.configmap.RouteLegendCard.DataClass; import net.osmand.plus.configmap.routes.RouteLayersHelper; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.utils.AndroidUtils; @@ -61,6 +64,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, showHideTopShadow(view); setupHeader(view); + setupLegendCard(view); setupTypesCard(view); return view; @@ -144,6 +148,7 @@ private TextRadioItem createRadioButton(@NonNull String value) { if (view != null) { setupHeader(view); setupTypesCard(view); + setupLegendCard(view); } refreshMap(); return true; @@ -151,6 +156,25 @@ private TextRadioItem createRadioButton(@NonNull String value) { return item; } + private void setupLegendCard(View view) { + ViewGroup group = view.findViewById(R.id.legend_container); + String propertyValue = routeLayersHelper.getSelectedHikingRoutesValue(); + + if (HIKING_OSMC_NODES.getPropertyValue().equals(propertyValue)) { + List<DataClass> dataClasses = getDataClasses(app, HIKING_OSMC_NODES); + if (!Algorithms.isEmpty(dataClasses)) { + RouteLegendCard card = new RouteLegendCard(requireActivity(), dataClasses, app.getString(R.string.shared_string_legend)); + View cardView = card.build(); + group.addView(cardView); + AndroidUiHelper.updateVisibility(group, true); + } else { + AndroidUiHelper.updateVisibility(group, false); + } + } else { + AndroidUiHelper.updateVisibility(group, false); + } + } + private void refreshMap() { MapActivity mapActivity = (MapActivity) getMyActivity(); if (mapActivity != null) { diff --git a/OsmAnd/src/net/osmand/plus/configmap/MtbRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/MtbRoutesFragment.java index bbba0646405..fafab71d485 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/MtbRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/MtbRoutesFragment.java @@ -15,7 +15,6 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.BaseOsmAndFragment; -import net.osmand.plus.configmap.RouteLegendCard.DataClass; import net.osmand.plus.configmap.routes.MtbClassification; import net.osmand.plus.configmap.routes.RouteLayersHelper; import net.osmand.plus.helpers.AndroidUiHelper; @@ -26,7 +25,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.stream.IntStream; public class MtbRoutesFragment extends BaseOsmAndFragment { @@ -57,7 +55,6 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, setupClassifications(view); updateClassificationPreferences(); - setupLegendCard(view); return view; } @@ -88,22 +85,6 @@ private void setupClassifications(@NonNull View view) { } } - @NonNull - private List<DataClass> getDataClasses() { - return IntStream.rangeClosed(1, 9) - .mapToObj(i -> new DataClass("Legend item " + i, "Description")) - .toList(); - } - - private void setupLegendCard(@NonNull View view) { - List<DataClass> items = getDataClasses(); - - RouteLegendCard card = new RouteLegendCard(requireActivity(), items, app.getString(R.string.shared_string_legend)); - ViewGroup group = view.findViewById(R.id.legend_container); - View cardView = card.build(); - group.addView(cardView); - } - private View createRadioButton(@NonNull MtbClassification classification, @NonNull LayoutInflater inflater, @Nullable ViewGroup container, boolean hasDivider) { View view = inflater.inflate(R.layout.item_with_radiobutton_and_descr, container, false); view.setTag(classification); diff --git a/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java b/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java index be8c0127060..f2305a22679 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java +++ b/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java @@ -5,6 +5,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; +import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; @@ -14,6 +15,7 @@ import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.track.fragments.TrackAppearanceFragment; import net.osmand.plus.utils.AndroidUtils; import net.osmand.plus.utils.UiUtilities; @@ -58,10 +60,14 @@ private View createView(int position) { CompoundButton compoundButton = itemView.findViewById(R.id.compound_button); TextView title = itemView.findViewById(R.id.title); TextView description = itemView.findViewById(R.id.description); + AndroidUiHelper.updateVisibility(description, false); View divider = itemView.findViewById(R.id.divider_bottom); + ImageView icon = itemView.findViewById(R.id.icon); + + Drawable iconDrawable = TrackAppearanceFragment.getTrackIcon(app, null, false, dataClass.color); + icon.setImageDrawable(iconDrawable); title.setText(dataClass.title()); - description.setText(dataClass.description()); compoundButton.setChecked(isClassEnabled(dataClass)); @@ -94,6 +100,6 @@ public void onClassSelected(@NonNull DataClass dataClass, boolean checked) { } - public record DataClass(String title, String description) { + public record DataClass(String title, int color) { } } diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java b/OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java new file mode 100644 index 00000000000..737681c4b15 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java @@ -0,0 +1,99 @@ +package net.osmand.plus.configmap.routes; + +import static net.osmand.render.RenderingRuleStorageProperties.ATTR_COLOR_VALUE; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.configmap.RouteLegendCard; +import net.osmand.render.RenderingClass; +import net.osmand.render.RenderingRule; +import net.osmand.render.RenderingRulesStorage; + +import java.util.ArrayList; +import java.util.List; + +public class RClassUtils { + public enum RClassType { + HIKING_OSMC_NODES(".route.hiking.osmc_nodes", "walkingRoutesOSMCNodes"); + + private final String path; + private final String propertyValue; + + RClassType(@NonNull String path, @Nullable String propertyValue) { + this.path = path; + this.propertyValue = propertyValue; + } + + public String getPropertyValue() { + return propertyValue; + } + + public String getPath() { + return path; + } + } + + public enum RClassColors { + IWN(".iwn", "iwnColor"), + NWN(".nwn", "nwnColor"), + RWN(".rwn", "rwnColor"), + LWN(".lwn", "lwnColor"); + + private final String className; + private final String colorName; + + RClassColors(String className, String colorName) { + this.className = className; + this.colorName = colorName; + } + + @Nullable + public static String getColorName(String className) { + for (RClassColors RClassColors : values()) { + if (RClassColors.className.equals(className)) { + return RClassColors.colorName; + } + } + return null; + } + } + + public static List<RouteLegendCard.DataClass> getDataClasses(@NonNull OsmandApplication app, + @NonNull RClassType rClassType){ + List<RouteLegendCard.DataClass> dataClasses = new ArrayList<>(); + + RenderingRulesStorage routeRender = app.getRendererRegistry().getCurrentSelectedRenderer(); + if (routeRender != null) { + RenderingClass rClass = routeRender.getRenderingClass(rClassType.getPath()); + if (rClass != null) { + for (RenderingClass children : rClass.getChildren()) { + String colorName = RClassColors.getColorName(children.getName()); + Integer color = parseColor(routeRender, colorName); + if (color != null) { + dataClasses.add(new RouteLegendCard.DataClass(children.getTitle(), color)); + } + } + } + } + return dataClasses; + } + + public static Integer parseColor(@NonNull RenderingRulesStorage routeRender, @Nullable String colorName) { + if (colorName == null) { + return null; + } + Integer color = null; + + RenderingRule colorRule = routeRender.getRenderingAttributeRule(colorName); + List<RenderingRule> rules = colorRule.getIfElseChildren(); + for (RenderingRule rule : rules) { + int colorValue = rule.getIntPropertyValue(ATTR_COLOR_VALUE); + if (colorValue != -1) { + color = colorValue; + } + } + return color; + } +} From 5ba95d577ba78d110a6d38bc19ea1ed62509e004 Mon Sep 17 00:00:00 2001 From: 0xRe1nk0 <0xre1nk0@gmail.com> Date: Wed, 8 Jan 2025 10:33:40 +0200 Subject: [PATCH 03/10] move value check to fragment --- .../osmand/plus/configmap/HikingRoutesFragment.java | 3 ++- .../net/osmand/plus/configmap/routes/RClassUtils.java | 10 ++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java index 7ae47997832..092fb6b9474 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java @@ -36,6 +36,7 @@ public class HikingRoutesFragment extends BaseOsmAndFragment { public static final String TAG = HikingRoutesFragment.class.getSimpleName(); + public static final String NODE_NETWORKS_VALUE = "walkingRoutesOSMCNodes"; private RouteLayersHelper routeLayersHelper; @Nullable @@ -160,7 +161,7 @@ private void setupLegendCard(View view) { ViewGroup group = view.findViewById(R.id.legend_container); String propertyValue = routeLayersHelper.getSelectedHikingRoutesValue(); - if (HIKING_OSMC_NODES.getPropertyValue().equals(propertyValue)) { + if (NODE_NETWORKS_VALUE.equals(propertyValue)) { List<DataClass> dataClasses = getDataClasses(app, HIKING_OSMC_NODES); if (!Algorithms.isEmpty(dataClasses)) { RouteLegendCard card = new RouteLegendCard(requireActivity(), dataClasses, app.getString(R.string.shared_string_legend)); diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java b/OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java index 737681c4b15..76d6ec5782e 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java @@ -16,18 +16,12 @@ public class RClassUtils { public enum RClassType { - HIKING_OSMC_NODES(".route.hiking.osmc_nodes", "walkingRoutesOSMCNodes"); + HIKING_OSMC_NODES(".route.hiking.osmc_nodes"); private final String path; - private final String propertyValue; - RClassType(@NonNull String path, @Nullable String propertyValue) { + RClassType(@NonNull String path) { this.path = path; - this.propertyValue = propertyValue; - } - - public String getPropertyValue() { - return propertyValue; } public String getPath() { From 83dea3306da4fe47ef6a9e8eded4578b34f39e69 Mon Sep 17 00:00:00 2001 From: 0xRe1nk0 <0xre1nk0@gmail.com> Date: Wed, 8 Jan 2025 10:41:39 +0200 Subject: [PATCH 04/10] show/hide legend card UI fix --- .../res/layout/map_route_types_fragment.xml | 20 +++++++++++++------ .../plus/configmap/HikingRoutesFragment.java | 12 ++++++----- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/OsmAnd/res/layout/map_route_types_fragment.xml b/OsmAnd/res/layout/map_route_types_fragment.xml index b9cabbf7ee6..4c28d3d0d77 100644 --- a/OsmAnd/res/layout/map_route_types_fragment.xml +++ b/OsmAnd/res/layout/map_route_types_fragment.xml @@ -57,19 +57,27 @@ android:id="@+id/card_bottom_divider" layout="@layout/card_bottom_divider" /> - <include layout="@layout/list_item_divider" /> - <LinearLayout android:id="@+id/legend_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> - </LinearLayout> + <include layout="@layout/list_item_divider" /> - <include - android:id="@+id/bottom_divider" - layout="@layout/card_bottom_divider" /> + <LinearLayout + android:id="@+id/legend_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + </LinearLayout> + + <include + android:id="@+id/bottom_divider" + layout="@layout/card_bottom_divider" /> + + </LinearLayout> <View android:id="@+id/bottom_empty_space" diff --git a/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java index 092fb6b9474..f8483de9fe4 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java @@ -158,7 +158,9 @@ private TextRadioItem createRadioButton(@NonNull String value) { } private void setupLegendCard(View view) { - ViewGroup group = view.findViewById(R.id.legend_container); + ViewGroup container = view.findViewById(R.id.legend_container); + ViewGroup contentGroup = view.findViewById(R.id.legend_content); + contentGroup.removeAllViews(); String propertyValue = routeLayersHelper.getSelectedHikingRoutesValue(); if (NODE_NETWORKS_VALUE.equals(propertyValue)) { @@ -166,13 +168,13 @@ private void setupLegendCard(View view) { if (!Algorithms.isEmpty(dataClasses)) { RouteLegendCard card = new RouteLegendCard(requireActivity(), dataClasses, app.getString(R.string.shared_string_legend)); View cardView = card.build(); - group.addView(cardView); - AndroidUiHelper.updateVisibility(group, true); + contentGroup.addView(cardView); + AndroidUiHelper.updateVisibility(container, true); } else { - AndroidUiHelper.updateVisibility(group, false); + AndroidUiHelper.updateVisibility(container, false); } } else { - AndroidUiHelper.updateVisibility(group, false); + AndroidUiHelper.updateVisibility(container, false); } } From 9bda498855d2eb462fcb5058e4845db5331ea19e Mon Sep 17 00:00:00 2001 From: chumv <chumva.forever@gmail.com> Date: Wed, 15 Jan 2025 17:31:02 +0200 Subject: [PATCH 05/10] Add customBooleanRenderClassProps --- .../net/osmand/render/RenderingClass.java | 112 +++++++++--------- .../osmand/render/RenderingRulesStorage.java | 34 ++++-- .../core/android/MapRendererContext.java | 12 +- .../plus/configmap/HikingRoutesFragment.java | 26 +++- .../plus/configmap/RouteLegendCard.java | 56 +++++++-- .../plus/configmap/routes/RClassUtils.java | 93 --------------- .../plus/settings/backend/OsmandSettings.java | 11 ++ 7 files changed, 168 insertions(+), 176 deletions(-) delete mode 100644 OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java index ca94585995e..d5a37520724 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java @@ -1,59 +1,65 @@ package net.osmand.render; -import java.util.List; import java.util.ArrayList; +import java.util.List; public class RenderingClass { - private final String name; - private final String title; - private final boolean enable; - private String path; - private final List<RenderingClass> children = new ArrayList<>(); - - public RenderingClass(String name, String title, boolean enable) { - this.name = name; - this.title = title; - this.enable = enable; - } - - public String getName() { - return name; - } - - public String getTitle() { - return title; - } - - public boolean isEnable() { - return enable; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public List<RenderingClass> getChildren() { - return children; - } - - public void addChild(RenderingClass child) { - children.add(child); - } - - public RenderingClass findByPath(String path) { - if (this.path.equals(path)) { - return this; - } - for (RenderingClass child : children) { - RenderingClass result = child.findByPath(path); - if (result != null) { - return result; - } - } - return null; - } + + private final String name; + private final String title; + private final List<RenderingClass> children = new ArrayList<>(); + private final boolean enable; + + private String path; + + public RenderingClass(String name, String title, boolean enable) { + this.name = name; + this.title = title; + this.enable = enable; + } + + public String getName() { + return name; + } + + public String getColorName() { + return name.replace(".", "") + "Color"; + } + + public String getTitle() { + return title; + } + + public boolean isEnable() { + return enable; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public List<RenderingClass> getChildren() { + return children; + } + + public void addChild(RenderingClass child) { + children.add(child); + } + + public RenderingClass findByPath(String path) { + if (this.path.equals(path)) { + return this; + } + for (RenderingClass child : children) { + RenderingClass result = child.findByPath(path); + if (result != null) { + return result; + } + } + return null; + } } \ No newline at end of file diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java index f56e7942272..4242073f42a 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java @@ -269,14 +269,15 @@ private void process(RenderingRulesHandler handler, int el) throws XmlPullParser } private class RenderingRulesHandler { + private final XmlPullParser parser; private int state; - Stack<RenderingRule> stack = new Stack<RenderingRule>(); + private final Stack<RenderingRule> stack = new Stack<RenderingRule>(); private final Stack<RenderingClass> renderingClassStack = new Stack<>(); private final RenderingRulesStorageResolver resolver; private final boolean addon; private RenderingRulesStorage dependsStorage; - + public RenderingRulesHandler(XmlPullParser parser, RenderingRulesStorageResolver resolver, boolean addon){ this.parser = parser; @@ -433,23 +434,22 @@ public void startElement(Map<String, String> attrsMap, String name) throws XmlPu } } else if ("renderer".equals(name)) { //$NON-NLS-1$ throw new XmlPullParserException("Rendering style is deprecated and no longer supported."); - }else if ("renderingClass".equals(name)) { - String className = parser.getAttributeValue(null, "name"); - String title = parser.getAttributeValue(null, "title"); - boolean enable = Boolean.parseBoolean(parser.getAttributeValue(null, "enable")); + } else if ("renderingClass".equals(name)) { + String title = attrsMap.get("title"); + String className = attrsMap.get("name"); + boolean enable = Boolean.parseBoolean(attrsMap.get("enable")); - RenderingClass newClass = new RenderingClass(className, title, enable); + RenderingClass renderingClass = new RenderingClass(className, title, enable); if (!renderingClassStack.isEmpty()) { RenderingClass parent = renderingClassStack.peek(); - parent.addChild(newClass); - newClass.setPath(parent.getPath() + className); + parent.addChild(renderingClass); + renderingClass.setPath(parent.getPath() + className); } else { - newClass.setPath(className); + renderingClass.setPath(className); } - - renderingClasses.put(newClass.getPath(), newClass); - renderingClassStack.push(newClass); + renderingClasses.put(renderingClass.getPath(), renderingClass); + renderingClassStack.push(renderingClass); } else { log.warn("Unknown tag : " + name); //$NON-NLS-1$ } @@ -600,6 +600,14 @@ public String[] getRenderingAssociationNames() { return renderingAssociations.keySet().toArray(new String[0]); } + public Map<String, RenderingClass> getRenderingClasses() { + return renderingClasses; + } + + public Map<String, RenderingRule> getRenderingAssociations() { + return renderingAssociations; + } + public RenderingRule[] getRules(int state){ if(state >= tagValueGlobalRules.length || tagValueGlobalRules[state] == null) { return new RenderingRule[0]; diff --git a/OsmAnd/src/net/osmand/core/android/MapRendererContext.java b/OsmAnd/src/net/osmand/core/android/MapRendererContext.java index 2132c8cc953..8dac0bfbcfd 100644 --- a/OsmAnd/src/net/osmand/core/android/MapRendererContext.java +++ b/OsmAnd/src/net/osmand/core/android/MapRendererContext.java @@ -29,7 +29,10 @@ import net.osmand.plus.render.MapRenderRepositories; import net.osmand.plus.render.RendererRegistry; import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.settings.backend.preferences.CommonPreference; import net.osmand.plus.utils.NativeUtilities; +import net.osmand.render.RenderingClass; +import net.osmand.render.RenderingRule; import net.osmand.render.RenderingRuleProperty; import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRuleStorageProperties; @@ -325,9 +328,14 @@ protected QStringStringHash getMapStyleSettings() { } } } - + for (Map.Entry<String, RenderingClass> entry : storage.getRenderingClasses().entrySet()) { + RenderingClass renderingClass = entry.getValue(); + String name = renderingClass.getName(); + CommonPreference<Boolean> preference = settings.getСustomBooleanRenderClassProperty(name, renderingClass.isEnable()); + properties.put(name, String.valueOf(preference.get())); + } QStringStringHash styleSettings = new QStringStringHash(); - for (Entry<String, String> setting : properties.entrySet()) { + for (Map.Entry<String, String> setting : properties.entrySet()) { styleSettings.set(setting.getKey(), setting.getValue()); } if (nightMode) { diff --git a/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java index f8483de9fe4..deccb821cc5 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/HikingRoutesFragment.java @@ -1,8 +1,6 @@ package net.osmand.plus.configmap; import static net.osmand.osm.OsmRouteType.HIKING; -import static net.osmand.plus.configmap.routes.RClassUtils.RClassType.HIKING_OSMC_NODES; -import static net.osmand.plus.configmap.routes.RClassUtils.getDataClasses; import android.os.Bundle; import android.view.LayoutInflater; @@ -17,17 +15,19 @@ import androidx.annotation.Nullable; import androidx.fragment.app.FragmentManager; +import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.BaseOsmAndFragment; -import net.osmand.plus.configmap.RouteLegendCard.DataClass; import net.osmand.plus.configmap.routes.RouteLayersHelper; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.utils.AndroidUtils; import net.osmand.plus.utils.UiUtilities; import net.osmand.plus.widgets.multistatetoggle.TextToggleButton; import net.osmand.plus.widgets.multistatetoggle.TextToggleButton.TextRadioItem; +import net.osmand.render.RenderingClass; import net.osmand.render.RenderingRuleProperty; +import net.osmand.render.RenderingRulesStorage; import net.osmand.util.Algorithms; import java.util.ArrayList; @@ -37,6 +37,7 @@ public class HikingRoutesFragment extends BaseOsmAndFragment { public static final String TAG = HikingRoutesFragment.class.getSimpleName(); public static final String NODE_NETWORKS_VALUE = "walkingRoutesOSMCNodes"; + public static final String OSMC_NODES_KEY = ".route.hiking.osmc_nodes"; private RouteLayersHelper routeLayersHelper; @Nullable @@ -59,7 +60,8 @@ private boolean isEnabled() { } @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { updateNightMode(); View view = themedInflater.inflate(R.layout.map_route_types_fragment, container, false); @@ -164,7 +166,7 @@ private void setupLegendCard(View view) { String propertyValue = routeLayersHelper.getSelectedHikingRoutesValue(); if (NODE_NETWORKS_VALUE.equals(propertyValue)) { - List<DataClass> dataClasses = getDataClasses(app, HIKING_OSMC_NODES); + List<RenderingClass> dataClasses = getDataClasses(app); if (!Algorithms.isEmpty(dataClasses)) { RouteLegendCard card = new RouteLegendCard(requireActivity(), dataClasses, app.getString(R.string.shared_string_legend)); View cardView = card.build(); @@ -178,6 +180,20 @@ private void setupLegendCard(View view) { } } + @NonNull + public List<RenderingClass> getDataClasses(@NonNull OsmandApplication app) { + List<RenderingClass> renderingClasses = new ArrayList<>(); + + RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); + if (renderer != null) { + RenderingClass renderingClass = renderer.getRenderingClass(OSMC_NODES_KEY); + if (renderingClass != null) { + renderingClasses.addAll(renderingClass.getChildren()); + } + } + return renderingClasses; + } + private void refreshMap() { MapActivity mapActivity = (MapActivity) getMyActivity(); if (mapActivity != null) { diff --git a/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java b/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java index f2305a22679..937388759cd 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java +++ b/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java @@ -1,5 +1,7 @@ package net.osmand.plus.configmap; +import static net.osmand.render.RenderingRuleStorageProperties.ATTR_COLOR_VALUE; + import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.View; @@ -9,25 +11,33 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.track.fragments.TrackAppearanceFragment; import net.osmand.plus.utils.AndroidUtils; import net.osmand.plus.utils.UiUtilities; +import net.osmand.render.RenderingClass; +import net.osmand.render.RenderingRule; +import net.osmand.render.RenderingRulesStorage; import java.util.List; public class RouteLegendCard extends BaseCard { + + private final LayoutInflater themedInflater; - private final List<DataClass> items; + private final List<RenderingClass> items; private final String cardTitle; - public RouteLegendCard(@NonNull FragmentActivity activity, @NonNull List<DataClass> items, @NonNull String cardTitle) { + public RouteLegendCard(@NonNull FragmentActivity activity, @NonNull List<RenderingClass> items, + @NonNull String cardTitle) { super(activity, true); this.items = items; this.cardTitle = cardTitle; @@ -55,7 +65,7 @@ private void setupLegendItems() { @NonNull private View createView(int position) { - DataClass dataClass = items.get(position); + RenderingClass dataClass = items.get(position); View itemView = themedInflater.inflate(R.layout.route_legend_item, null, false); CompoundButton compoundButton = itemView.findViewById(R.id.compound_button); TextView title = itemView.findViewById(R.id.title); @@ -64,10 +74,14 @@ private View createView(int position) { View divider = itemView.findViewById(R.id.divider_bottom); ImageView icon = itemView.findViewById(R.id.icon); - Drawable iconDrawable = TrackAppearanceFragment.getTrackIcon(app, null, false, dataClass.color); - icon.setImageDrawable(iconDrawable); + String colorName = dataClass.getColorName(); + Integer color = parseColor(app.getRendererRegistry().getCurrentSelectedRenderer(), colorName); + if (color != null) { + Drawable iconDrawable = TrackAppearanceFragment.getTrackIcon(app, null, false, color); + icon.setImageDrawable(iconDrawable); + } - title.setText(dataClass.title()); + title.setText(dataClass.getTitle()); compoundButton.setChecked(isClassEnabled(dataClass)); @@ -92,14 +106,36 @@ private void setupCardTitle() { title.setText(cardTitle); } - public boolean isClassEnabled(@NonNull DataClass dataClass) { + public boolean isClassEnabled(@NonNull RenderingClass dataClass) { return false; } - public void onClassSelected(@NonNull DataClass dataClass, boolean checked) { + public void onClassSelected(@NonNull RenderingClass dataClass, boolean checked) { + settings.getСustomBooleanRenderClassProperty(dataClass.getName(), dataClass.isEnable()).set(checked); + refreshMap(); + } + private void refreshMap() { + if (activity instanceof MapActivity mapActivity) { + mapActivity.refreshMapComplete(); + mapActivity.updateLayers(); + } } - public record DataClass(String title, int color) { + public static Integer parseColor(@NonNull RenderingRulesStorage routeRender, @Nullable String colorName) { + if (colorName == null) { + return null; + } + Integer color = null; + + RenderingRule colorRule = routeRender.getRenderingAttributeRule(colorName); + List<RenderingRule> rules = colorRule.getIfElseChildren(); + for (RenderingRule rule : rules) { + int colorValue = rule.getIntPropertyValue(ATTR_COLOR_VALUE); + if (colorValue != -1) { + color = colorValue; + } + } + return color; } -} +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java b/OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java deleted file mode 100644 index 76d6ec5782e..00000000000 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/RClassUtils.java +++ /dev/null @@ -1,93 +0,0 @@ -package net.osmand.plus.configmap.routes; - -import static net.osmand.render.RenderingRuleStorageProperties.ATTR_COLOR_VALUE; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.configmap.RouteLegendCard; -import net.osmand.render.RenderingClass; -import net.osmand.render.RenderingRule; -import net.osmand.render.RenderingRulesStorage; - -import java.util.ArrayList; -import java.util.List; - -public class RClassUtils { - public enum RClassType { - HIKING_OSMC_NODES(".route.hiking.osmc_nodes"); - - private final String path; - - RClassType(@NonNull String path) { - this.path = path; - } - - public String getPath() { - return path; - } - } - - public enum RClassColors { - IWN(".iwn", "iwnColor"), - NWN(".nwn", "nwnColor"), - RWN(".rwn", "rwnColor"), - LWN(".lwn", "lwnColor"); - - private final String className; - private final String colorName; - - RClassColors(String className, String colorName) { - this.className = className; - this.colorName = colorName; - } - - @Nullable - public static String getColorName(String className) { - for (RClassColors RClassColors : values()) { - if (RClassColors.className.equals(className)) { - return RClassColors.colorName; - } - } - return null; - } - } - - public static List<RouteLegendCard.DataClass> getDataClasses(@NonNull OsmandApplication app, - @NonNull RClassType rClassType){ - List<RouteLegendCard.DataClass> dataClasses = new ArrayList<>(); - - RenderingRulesStorage routeRender = app.getRendererRegistry().getCurrentSelectedRenderer(); - if (routeRender != null) { - RenderingClass rClass = routeRender.getRenderingClass(rClassType.getPath()); - if (rClass != null) { - for (RenderingClass children : rClass.getChildren()) { - String colorName = RClassColors.getColorName(children.getName()); - Integer color = parseColor(routeRender, colorName); - if (color != null) { - dataClasses.add(new RouteLegendCard.DataClass(children.getTitle(), color)); - } - } - } - } - return dataClasses; - } - - public static Integer parseColor(@NonNull RenderingRulesStorage routeRender, @Nullable String colorName) { - if (colorName == null) { - return null; - } - Integer color = null; - - RenderingRule colorRule = routeRender.getRenderingAttributeRule(colorName); - List<RenderingRule> rules = colorRule.getIfElseChildren(); - for (RenderingRule rule : rules) { - int colorValue = rule.getIntPropertyValue(ATTR_COLOR_VALUE); - if (colorValue != -1) { - color = colorValue; - } - } - return color; - } -} diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java index 4ee64f2a873..1258b94a83f 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java @@ -143,6 +143,7 @@ public class OsmandSettings { private final Map<String, CommonPreference<String>> customRendersProps = new LinkedHashMap<>(); private final Map<String, CommonPreference<Boolean>> customBooleanRoutingProps = new LinkedHashMap<>(); private final Map<String, CommonPreference<Boolean>> customBooleanRendersProps = new LinkedHashMap<>(); + private final Map<String, CommonPreference<Boolean>> customBooleanRenderClassProps = new LinkedHashMap<>(); private final ImpassableRoadsStorage impassableRoadsStorage = new ImpassableRoadsStorage(this); private final IntermediatePointsStorage intermediatePointsStorage = new IntermediatePointsStorage(this); @@ -3118,6 +3119,16 @@ public CommonPreference<Boolean> getCustomRenderBooleanProperty(@NonNull String return customBooleanRendersProps.get(attrName); } + @NonNull + public CommonPreference<Boolean> getСustomBooleanRenderClassProperty(@NonNull String className, boolean defaultValue) { + if (!customBooleanRenderClassProps.containsKey(className)) { + CommonPreference<Boolean> preference = new BooleanPreference(this, className, defaultValue).makeProfile(); + customBooleanRenderClassProps.put(className, preference); + return preference; + } + return customBooleanRenderClassProps.get(className); + } + @NonNull public CommonPreference<Boolean> registerCustomRenderBooleanProperty(@NonNull String attrName, boolean defaultValue) { CommonPreference<Boolean> preference = new BooleanPreference(this, RENDERER_PREFERENCE_PREFIX + attrName, defaultValue).makeProfile(); From 56d1c1eeaef445cdb9087c681fbc4aedc2e1b1a3 Mon Sep 17 00:00:00 2001 From: chumv <chumva.forever@gmail.com> Date: Tue, 28 Jan 2025 16:39:53 +0200 Subject: [PATCH 06/10] Route legend [WIP] --- .../net/osmand/render/RenderingClass.java | 50 +------ .../osmand/render/RenderingRulesStorage.java | 33 +--- OsmAnd/res/layout/rendering_classes_card.xml | 28 ++++ OsmAnd/res/layout/route_legend_card.xml | 45 ------ OsmAnd/res/layout/route_legend_item.xml | 80 ---------- .../core/android/MapRendererContext.java | 6 +- .../plus/configmap/ConfigureMapMenu.java | 8 +- .../plus/configmap/ConfigureMapUtils.java | 49 +++++- .../plus/configmap/RouteLegendCard.java | 141 ------------------ .../routes/AlpineHikingScaleFragment.java | 25 +++- .../routes/CustomRoutesFragment.java | 80 ++++++++++ .../configmap/routes/CycleRoutesFragment.java | 21 ++- .../routes/HikingRoutesFragment.java | 21 ++- .../configmap/routes/MapRoutesFragment.java | 51 +++++-- .../configmap/routes/MtbRoutesFragment.java | 24 ++- .../routes/RenderingClassesCard.java | 92 ++++++++++++ .../configmap/routes/RouteLayersHelper.java | 11 ++ .../plus/settings/backend/OsmandSettings.java | 20 +-- 18 files changed, 397 insertions(+), 388 deletions(-) create mode 100644 OsmAnd/res/layout/rendering_classes_card.xml delete mode 100644 OsmAnd/res/layout/route_legend_card.xml delete mode 100644 OsmAnd/res/layout/route_legend_item.xml delete mode 100644 OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java create mode 100644 OsmAnd/src/net/osmand/plus/configmap/routes/CustomRoutesFragment.java create mode 100644 OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassesCard.java diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java index d5a37520724..ee995b45af2 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java @@ -1,65 +1,31 @@ package net.osmand.render; -import java.util.ArrayList; -import java.util.List; - public class RenderingClass { private final String name; private final String title; - private final List<RenderingClass> children = new ArrayList<>(); - private final boolean enable; - - private String path; + private final boolean enabledByDefault; - public RenderingClass(String name, String title, boolean enable) { + public RenderingClass(String name, String title, boolean enabledByDefault) { this.name = name; this.title = title; - this.enable = enable; + this.enabledByDefault = enabledByDefault; } public String getName() { return name; } - public String getColorName() { - return name.replace(".", "") + "Color"; - } - public String getTitle() { return title; } - public boolean isEnable() { - return enable; + public boolean isEnabledByDefault() { + return enabledByDefault; } - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public List<RenderingClass> getChildren() { - return children; - } - - public void addChild(RenderingClass child) { - children.add(child); - } - - public RenderingClass findByPath(String path) { - if (this.path.equals(path)) { - return this; - } - for (RenderingClass child : children) { - RenderingClass result = child.findByPath(path); - if (result != null) { - return result; - } - } - return null; + @Override + public String toString() { + return name; } } \ No newline at end of file diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java index 90ab524b8e8..dda11e451ca 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java @@ -100,6 +100,7 @@ public RenderingRulesStorage copy() { } storage.renderingAttributes.putAll(renderingAttributes); storage.renderingAssociations.putAll(renderingAssociations); + storage.renderingClasses.putAll(renderingClasses); return storage; } @@ -269,15 +270,13 @@ private void process(RenderingRulesHandler handler, int el) throws XmlPullParser } private class RenderingRulesHandler { - private final XmlPullParser parser; private int state; - private final Stack<RenderingRule> stack = new Stack<RenderingRule>(); - private final Stack<RenderingClass> renderingClassStack = new Stack<>(); + Stack<RenderingRule> stack = new Stack<RenderingRule>(); private final RenderingRulesStorageResolver resolver; private final boolean addon; private RenderingRulesStorage dependsStorage; - + public RenderingRulesHandler(XmlPullParser parser, RenderingRulesStorageResolver resolver, boolean addon){ this.parser = parser; @@ -438,18 +437,7 @@ public void startElement(Map<String, String> attrsMap, String name) throws XmlPu String title = attrsMap.get("title"); String className = attrsMap.get("name"); boolean enable = Boolean.parseBoolean(attrsMap.get("enable")); - - RenderingClass renderingClass = new RenderingClass(className, title, enable); - - if (!renderingClassStack.isEmpty()) { - RenderingClass parent = renderingClassStack.peek(); - parent.addChild(renderingClass); - renderingClass.setPath(parent.getPath() + className); - } else { - renderingClass.setPath(className); - } - renderingClasses.put(renderingClass.getPath(), renderingClass); - renderingClassStack.push(renderingClass); + renderingClasses.put(className, new RenderingClass(className, title, enable)); } else { log.warn("Unknown tag : " + name); //$NON-NLS-1$ } @@ -477,7 +465,8 @@ private Map<String, String> parseAttributes(XmlPullParser parser, Map<String, St String vl = parser.getAttributeValue(i); if (vl != null && vl.startsWith("$")) { String cv = vl.substring(1); - if (!renderingConstants.containsKey(cv) && !renderingAttributes.containsKey(cv) && !renderingAssociations.containsKey(cv)) { + if (!renderingConstants.containsKey(cv) && !renderingAttributes.containsKey(cv) + && !renderingAssociations.containsKey(cv) && !renderingClasses.containsKey(cv)) { throw new IllegalStateException("Rendering constant or attribute '" + cv + "' was not specified."); } if (renderingConstants.containsKey(cv)) { @@ -502,8 +491,6 @@ public void endElement(String name) throws XmlPullParserException { stack.pop(); } else if ("renderingAssociation".equals(name)) { //$NON-NLS-1$ stack.pop(); - } else if ("renderingClass".equals(name)) { - renderingClassStack.pop(); } } } @@ -581,8 +568,8 @@ public RenderingRule getRenderingAttributeRule(String attribute) { return renderingAttributes.get(attribute); } - public RenderingClass getRenderingClass(String path) { - return renderingClasses.get(path); + public RenderingClass getRenderingClass(String name) { + return renderingClasses.get(name); } public String[] getRenderingAttributeNames() { @@ -604,10 +591,6 @@ public Map<String, RenderingClass> getRenderingClasses() { return renderingClasses; } - public Map<String, RenderingRule> getRenderingAssociations() { - return renderingAssociations; - } - public RenderingRule[] getRules(int state){ if(state >= tagValueGlobalRules.length || tagValueGlobalRules[state] == null) { return new RenderingRule[0]; diff --git a/OsmAnd/res/layout/rendering_classes_card.xml b/OsmAnd/res/layout/rendering_classes_card.xml new file mode 100644 index 00000000000..ee033b2031f --- /dev/null +++ b/OsmAnd/res/layout/rendering_classes_card.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/rendering_classes_card" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/list_background_color" + android:orientation="vertical"> + + <net.osmand.plus.widgets.TextViewEx + android:id="@+id/header" + style="@style/TitleStyle.Medium" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/content_padding" + android:layout_marginVertical="@dimen/content_padding_small" + android:textColor="?android:textColorPrimary" + tools:text="@string/mtb_scale" /> + + <LinearLayout + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + </LinearLayout> + +</LinearLayout> \ No newline at end of file diff --git a/OsmAnd/res/layout/route_legend_card.xml b/OsmAnd/res/layout/route_legend_card.xml deleted file mode 100644 index 56cf2023571..00000000000 --- a/OsmAnd/res/layout/route_legend_card.xml +++ /dev/null @@ -1,45 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/route_legend_card" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> - - <LinearLayout - android:id="@+id/properties_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?attr/list_background_color" - android:orientation="vertical"> - - <net.osmand.plus.widgets.TextViewEx - android:id="@+id/card_title" - style="@style/TitleStyle.Medium" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginHorizontal="@dimen/content_padding" - android:layout_marginVertical="@dimen/content_padding_small" - android:textColor="?android:textColorPrimary" - tools:text="Legend" /> - - <LinearLayout - android:id="@+id/classification_properties" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - </LinearLayout> - - </LinearLayout> - - <LinearLayout - android:id="@+id/main_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?attr/list_background_color" - android:orientation="vertical"> - - </LinearLayout> - -</LinearLayout> \ No newline at end of file diff --git a/OsmAnd/res/layout/route_legend_item.xml b/OsmAnd/res/layout/route_legend_item.xml deleted file mode 100644 index 3083179037e..00000000000 --- a/OsmAnd/res/layout/route_legend_item.xml +++ /dev/null @@ -1,80 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/main_view" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?attr/selectableItemBackground" - android:descendantFocusability="blocksDescendants" - android:gravity="center" - android:orientation="horizontal"> - - <ImageView - android:id="@+id/icon" - android:layout_width="@dimen/standard_icon_size" - android:layout_height="@dimen/standard_icon_size" - android:layout_marginStart="@dimen/content_padding" - android:layout_marginEnd="@dimen/favorites_icon_right_margin" - android:layout_gravity="center_vertical" - tools:src="@drawable/ic_action_track_line_bold_color" - tools:tint="?attr/default_icon_color" /> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="@dimen/setting_profile_item_height" - android:orientation="horizontal"> - - <LinearLayout - android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_weight="1" - android:gravity="center" - android:orientation="vertical"> - - <TextView - android:id="@+id/title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:ellipsize="end" - android:maxLines="2" - android:textColor="?android:textColorPrimary" - android:textSize="@dimen/default_list_text_size" - tools:text="Title" /> - - <TextView - android:id="@+id/description" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:ellipsize="end" - android:maxLines="1" - android:textColor="?android:textColorSecondary" - android:textSize="@dimen/default_desc_text_size" - tools:text="Description" /> - - </LinearLayout> - - <androidx.appcompat.widget.SwitchCompat - android:id="@+id/compound_button" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_gravity="center_vertical|end" - android:background="@null" - android:focusableInTouchMode="true" - android:padding="@dimen/content_padding" /> - - </LinearLayout> - - <View - android:id="@+id/divider_bottom" - android:layout_width="match_parent" - android:layout_height="1dp" - android:background="?attr/list_divider" /> - - </LinearLayout> - -</LinearLayout> \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/core/android/MapRendererContext.java b/OsmAnd/src/net/osmand/core/android/MapRendererContext.java index 8dac0bfbcfd..f1b1597a47d 100644 --- a/OsmAnd/src/net/osmand/core/android/MapRendererContext.java +++ b/OsmAnd/src/net/osmand/core/android/MapRendererContext.java @@ -320,7 +320,7 @@ protected QStringStringHash getMapStyleSettings() { for (RenderingRuleProperty property : storage.PROPS.getCustomRules()) { String attrName = property.getAttrName(); if (property.isBoolean()) { - properties.put(attrName, settings.getRenderBooleanPropertyValue(attrName) + ""); + properties.put(attrName, String.valueOf(settings.getRenderBooleanPropertyValue(attrName))); } else { String value = settings.getRenderPropertyValue(attrName); if (!Algorithms.isEmpty(value)) { @@ -330,8 +330,10 @@ protected QStringStringHash getMapStyleSettings() { } for (Map.Entry<String, RenderingClass> entry : storage.getRenderingClasses().entrySet()) { RenderingClass renderingClass = entry.getValue(); + String name = renderingClass.getName(); - CommonPreference<Boolean> preference = settings.getСustomBooleanRenderClassProperty(name, renderingClass.isEnable()); + boolean enabled = renderingClass.isEnabledByDefault(); + CommonPreference<Boolean> preference = settings.getСustomBooleanRenderClassProperty(name, enabled); properties.put(name, String.valueOf(preference.get())); } QStringStringHash styleSettings = new QStringStringHash(); diff --git a/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapMenu.java b/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapMenu.java index dcdbee5108f..d1775d24994 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapMenu.java +++ b/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapMenu.java @@ -59,6 +59,7 @@ import net.osmand.plus.widgets.ctxmenu.callback.OnDataChangeUiAdapter; import net.osmand.plus.widgets.ctxmenu.callback.OnRowItemClick; import net.osmand.plus.widgets.ctxmenu.data.ContextMenuItem; +import net.osmand.render.RenderingClass; import net.osmand.render.RenderingRuleProperty; import net.osmand.util.Algorithms; import net.osmand.util.SunriseSunset; @@ -71,6 +72,7 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.Map; public class ConfigureMapMenu { @@ -104,10 +106,12 @@ public ContextMenuAdapter createListAdapter(@NonNull MapActivity mapActivity) { List<RenderingRuleProperty> customRules = ConfigureMapUtils.getCustomRules(app, UI_CATEGORY_HIDDEN, RENDERING_CATEGORY_TRANSPORT); + createLayersItems(customRules, adapter, mapActivity, nightMode); PluginsHelper.registerConfigureMapCategory(adapter, mapActivity, customRules); createRouteAttributeItems(customRules, adapter, mapActivity, nightMode); createRenderingAttributeItems(customRules, adapter, mapActivity, nightMode); + return adapter; } @@ -210,9 +214,7 @@ private void createLayersItems(@NonNull List<RenderingRuleProperty> customRules, } private void createRouteAttributeItems(@NonNull List<RenderingRuleProperty> customRules, - @NonNull ContextMenuAdapter adapter, - @NonNull MapActivity activity, - boolean nightMode) { + @NonNull ContextMenuAdapter adapter, @NonNull MapActivity activity, boolean nightMode) { adapter.addItem(new ContextMenuItem(ROUTES_CATEGORY_ID) .setCategory(true) .setTitleId(R.string.rendering_category_routes, activity) diff --git a/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java b/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java index 9ce1a6a0562..f82ac50856d 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java +++ b/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java @@ -4,6 +4,8 @@ import static net.osmand.plus.dialogs.DetailsBottomSheet.STREET_LIGHTING_NIGHT; import static net.osmand.plus.settings.backend.OsmandSettings.RENDERER_PREFERENCE_PREFIX; +import android.util.Pair; + import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -15,21 +17,19 @@ import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.preferences.CommonPreference; import net.osmand.plus.utils.AndroidUtils; +import net.osmand.render.RenderingClass; import net.osmand.render.RenderingRuleProperty; import net.osmand.render.RenderingRulesStorage; import net.osmand.util.Algorithms; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; +import java.util.*; public class ConfigureMapUtils { public static final String[] MAP_LANGUAGES_IDS = {"", "en", "af", "als", "ar", "az", "be", "ber", "bg", "bn", "bpy", "br", "bs", "ca", "ceb", "ckb", "cs", "cy", "da", "de", "el", "eo", "es", "et", "eu", "fa", "fi", "fr", "fy", "ga", "gl", "he", "hi", "hsb", "hr", "ht", "hu", "hy", "id", "is", "it", "ja", "ka", "kab", "kk", "kn", "ko", "ku", "la", "lb", "lo", "lt", "lv", "mk", "ml", "mr", "ms", "nds", "new", "nl", "nn", "no", "nv", "oc", "os", "pl", "pms", "pt", "ro", "ru", "sat", "sc", "sh", "sk", "sl", "sq", "sr", "sr-latn", "sv", "sw", "ta", "te", "th", "tl", "tr", "uk", "vi", "vo", "zh", "zh-Hans", "zh-Hant"}; + public static final String ROUTE_CLASS_PREFIX = ".route."; + @NonNull public static Map<String, String> getSorterMapLanguages(@NonNull OsmandApplication app) { Map<String, String> mapLanguages = new HashMap<>(); @@ -71,7 +71,8 @@ public static RenderingRuleProperty getPropertyForAttr(@NonNull OsmandApplicatio } @Nullable - public static RenderingRuleProperty getPropertyForAttr(@NonNull List<RenderingRuleProperty> customRules, @NonNull String attrName) { + public static RenderingRuleProperty getPropertyForAttr( + @NonNull List<RenderingRuleProperty> customRules, @NonNull String attrName) { for (RenderingRuleProperty property : customRules) { if (Algorithms.stringsEqual(property.getAttrName(), attrName)) { return property; @@ -103,7 +104,39 @@ public static List<RenderingRuleProperty> getCustomRules(@NonNull OsmandApplicat return customRules; } - protected static String[] getRenderingPropertyPossibleValues(OsmandApplication app, RenderingRuleProperty p) { + @NonNull + public static Map<String, RenderingClass> getRenderingClasses(@NonNull OsmandApplication app) { + RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); + if (renderer == null) { + return new LinkedHashMap<>(); + } + return renderer.getRenderingClasses(); + } + + @NonNull + public static Pair<RenderingClass, List<RenderingClass>> getRenderingClassesForKey( + @NonNull OsmandApplication app, @NonNull String attrName) { + RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); + if (renderer == null) { + return null; + } + String key = ROUTE_CLASS_PREFIX + attrName.replace("show", ""); + RenderingClass mainClass = renderer.getRenderingClass(key); + if (mainClass != null) { + List<RenderingClass> list = new ArrayList<>(); + for (Map.Entry<String, RenderingClass> entry : renderer.getRenderingClasses().entrySet()) { + RenderingClass renderingClass = entry.getValue(); + if (renderingClass.getName().startsWith(key + ".")) { + list.add(renderingClass); + } + } + return Pair.create(mainClass, list); + } + return null; + } + + protected static String[] getRenderingPropertyPossibleValues(OsmandApplication app, + RenderingRuleProperty p) { String[] possibleValuesString = new String[p.getPossibleValues().length + 1]; possibleValuesString[0] = AndroidUtils.getRenderingStringPropertyValue(app, p.getDefaultValueDescription()); diff --git a/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java b/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java deleted file mode 100644 index 937388759cd..00000000000 --- a/OsmAnd/src/net/osmand/plus/configmap/RouteLegendCard.java +++ /dev/null @@ -1,141 +0,0 @@ -package net.osmand.plus.configmap; - -import static net.osmand.render.RenderingRuleStorageProperties.ATTR_COLOR_VALUE; - -import android.graphics.drawable.Drawable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CompoundButton; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.FragmentActivity; - -import net.osmand.plus.R; -import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.helpers.AndroidUiHelper; -import net.osmand.plus.routepreparationmenu.cards.BaseCard; -import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.track.fragments.TrackAppearanceFragment; -import net.osmand.plus.utils.AndroidUtils; -import net.osmand.plus.utils.UiUtilities; -import net.osmand.render.RenderingClass; -import net.osmand.render.RenderingRule; -import net.osmand.render.RenderingRulesStorage; - -import java.util.List; - -public class RouteLegendCard extends BaseCard { - - - private final LayoutInflater themedInflater; - - private final List<RenderingClass> items; - private final String cardTitle; - - public RouteLegendCard(@NonNull FragmentActivity activity, @NonNull List<RenderingClass> items, - @NonNull String cardTitle) { - super(activity, true); - this.items = items; - this.cardTitle = cardTitle; - themedInflater = UiUtilities.getInflater(activity, nightMode); - } - - @Override - public int getCardLayoutId() { - return R.layout.route_legend_card; - } - - @Override - protected void updateContent() { - setupCardTitle(); - setupLegendItems(); - } - - private void setupLegendItems() { - ViewGroup mainContainer = view.findViewById(R.id.main_container); - mainContainer.removeAllViews(); - for (int i = 0; i < items.size(); i++) { - mainContainer.addView(createView(i)); - } - } - - @NonNull - private View createView(int position) { - RenderingClass dataClass = items.get(position); - View itemView = themedInflater.inflate(R.layout.route_legend_item, null, false); - CompoundButton compoundButton = itemView.findViewById(R.id.compound_button); - TextView title = itemView.findViewById(R.id.title); - TextView description = itemView.findViewById(R.id.description); - AndroidUiHelper.updateVisibility(description, false); - View divider = itemView.findViewById(R.id.divider_bottom); - ImageView icon = itemView.findViewById(R.id.icon); - - String colorName = dataClass.getColorName(); - Integer color = parseColor(app.getRendererRegistry().getCurrentSelectedRenderer(), colorName); - if (color != null) { - Drawable iconDrawable = TrackAppearanceFragment.getTrackIcon(app, null, false, color); - icon.setImageDrawable(iconDrawable); - } - - title.setText(dataClass.getTitle()); - - compoundButton.setChecked(isClassEnabled(dataClass)); - - AndroidUiHelper.updateVisibility(divider, position != items.size() - 1); - itemView.setOnClickListener(view -> { - compoundButton.performClick(); - onClassSelected(dataClass, compoundButton.isChecked()); - }); - - compoundButton.setFocusable(false); - compoundButton.setClickable(false); - - OsmandSettings settings = app.getSettings(); - Drawable background = UiUtilities.getColoredSelectableDrawable(app, settings.getApplicationMode().getProfileColor(nightMode), 0.3f); - AndroidUtils.setBackground(itemView, background); - - return itemView; - } - - private void setupCardTitle() { - TextView title = view.findViewById(R.id.card_title); - title.setText(cardTitle); - } - - public boolean isClassEnabled(@NonNull RenderingClass dataClass) { - return false; - } - - public void onClassSelected(@NonNull RenderingClass dataClass, boolean checked) { - settings.getСustomBooleanRenderClassProperty(dataClass.getName(), dataClass.isEnable()).set(checked); - refreshMap(); - } - - private void refreshMap() { - if (activity instanceof MapActivity mapActivity) { - mapActivity.refreshMapComplete(); - mapActivity.updateLayers(); - } - } - - public static Integer parseColor(@NonNull RenderingRulesStorage routeRender, @Nullable String colorName) { - if (colorName == null) { - return null; - } - Integer color = null; - - RenderingRule colorRule = routeRender.getRenderingAttributeRule(colorName); - List<RenderingRule> rules = colorRule.getIfElseChildren(); - for (RenderingRule rule : rules) { - int colorValue = rule.getIntPropertyValue(ATTR_COLOR_VALUE); - if (colorValue != -1) { - color = colorValue; - } - } - return color; - } -} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/AlpineHikingScaleFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/AlpineHikingScaleFragment.java index 3919f0d35cb..e5e61feef62 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/AlpineHikingScaleFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/AlpineHikingScaleFragment.java @@ -1,5 +1,7 @@ package net.osmand.plus.configmap.routes; +import static net.osmand.osm.OsmRouteType.ALPINE; + import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -8,6 +10,7 @@ import net.osmand.plus.R; import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.utils.AndroidUtils; public class AlpineHikingScaleFragment extends MapRoutesFragment { @@ -24,6 +27,12 @@ protected void toggleMainPreference(@NonNull View view) { routeLayersHelper.toggleAlpineHikingRoutes(); } + @NonNull + @Override + protected String getSelectedAttrName() { + return ALPINE.getRenderingPropertyAttr(); + } + protected void setupHeader(@NonNull View view) { super.setupHeader(view); @@ -34,21 +43,25 @@ protected void setupHeader(@NonNull View view) { title.setText(R.string.rendering_attr_alpineHiking_name); TextView description = container.findViewById(R.id.description); - description.setText(AlpineHikingCard.getDifficultyClassificationDescription(app)); + description.setText(routeLayersHelper.getRoutesTypeDescription(getSelectedAttrName())); AndroidUiHelper.updateVisibility(description, enabled); int selectedColor = settings.getApplicationMode().getProfileColor(nightMode); int disabledColor = AndroidUtils.getColorFromAttr(app, R.attr.default_icon_color); ImageView icon = container.findViewById(R.id.icon); - icon.setImageDrawable(getPaintedContentIcon(R.drawable.ic_action_trekking_dark, enabled ? selectedColor : disabledColor)); + icon.setImageDrawable(getPaintedContentIcon(RouteUtils.getIconIdForAttr(getSelectedAttrName()), + enabled ? selectedColor : disabledColor)); } @Override - protected void setupCards(@NonNull View view) { - super.setupCards(view); + protected void createCards(@NonNull View view) { + super.createCards(view); - cardsContainer.addView(createDivider(cardsContainer, true, true)); addCard(new AlpineHikingCard(getMapActivity())); - cardsContainer.addView(createDivider(cardsContainer, false, true)); + + BaseCard card = createRenderingClassCard(getSelectedAttrName()); + if (card != null) { + addCard(card); + } } } diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/CustomRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/CustomRoutesFragment.java new file mode 100644 index 00000000000..7650bd3b3a4 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/CustomRoutesFragment.java @@ -0,0 +1,80 @@ +package net.osmand.plus.configmap.routes; + +import android.os.Bundle; +import android.util.Pair; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import net.osmand.plus.R; +import net.osmand.plus.configmap.ConfigureMapUtils; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; +import net.osmand.plus.utils.AndroidUtils; +import net.osmand.render.RenderingClass; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class CustomRoutesFragment extends MapRoutesFragment { + + public static final String TAG = CustomRoutesFragment.class.getSimpleName(); + + private String attrName; + + @Override + protected boolean isEnabled() { + return routeLayersHelper.isRoutesTypeEnabled(attrName); + } + + @Override + protected void toggleMainPreference(@NonNull View view) { + routeLayersHelper.toggleRoutesType(attrName); + } + + @NonNull + @Override + protected @NotNull String getSelectedAttrName() { + return attrName; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + attrName = app.getRouteLayersHelper().getSelectedAttrName(); + } + + protected void setupHeader(@NonNull View view) { + super.setupHeader(view); + + boolean enabled = isEnabled(); + View container = view.findViewById(R.id.preference_container); + + TextView title = container.findViewById(R.id.title); + title.setText(routeLayersHelper.getRoutesTypeName(routeLayersHelper.getSelectedAttrName())); + + int selectedColor = settings.getApplicationMode().getProfileColor(nightMode); + int disabledColor = AndroidUtils.getColorFromAttr(app, R.attr.default_icon_color); + ImageView icon = container.findViewById(R.id.icon); + int iconId = RouteUtils.getIconIdForAttr(attrName); + if (iconId > 0) { + icon.setImageDrawable(getPaintedContentIcon(iconId, enabled ? selectedColor : disabledColor)); + } + + AndroidUiHelper.updateVisibility(container.findViewById(R.id.description), false); + } + + @Override + protected void createCards(@NonNull View view) { + super.createCards(view); + + BaseCard card = createRenderingClassCard(getSelectedAttrName()); + if (card != null) { + addCard(card); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/CycleRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/CycleRoutesFragment.java index deba0d94df5..7b5400d088a 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/CycleRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/CycleRoutesFragment.java @@ -9,9 +9,12 @@ import androidx.annotation.NonNull; import net.osmand.plus.R; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.utils.AndroidUtils; import net.osmand.plus.utils.ColorUtilities; +import org.jetbrains.annotations.NotNull; + public class CycleRoutesFragment extends MapRoutesFragment { public static final String TAG = CycleRoutesFragment.class.getSimpleName(); @@ -26,6 +29,12 @@ protected void toggleMainPreference(@NonNull View view) { routeLayersHelper.toggleCycleRoutes(); } + @NonNull + @Override + protected String getSelectedAttrName() { + return BICYCLE.getRenderingPropertyAttr(); + } + protected void setupHeader(@NonNull View view) { super.setupHeader(view); @@ -46,11 +55,13 @@ protected void setupHeader(@NonNull View view) { } @Override - protected void setupCards(@NonNull View view) { - super.setupCards(view); - - cardsContainer.addView(createDivider(cardsContainer, true, true)); + protected void createCards(@NonNull View view) { + super.createCards(view); addCard(new CycleRouteTypesCard(getMapActivity())); - cardsContainer.addView(createDivider(cardsContainer, false, true)); + + BaseCard card = createRenderingClassCard(getSelectedAttrName()); + if (card != null) { + addCard(card); + } } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/HikingRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/HikingRoutesFragment.java index 9a9a04d5f68..655c2716417 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/HikingRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/HikingRoutesFragment.java @@ -1,5 +1,7 @@ package net.osmand.plus.configmap.routes; +import static net.osmand.osm.OsmRouteType.HIKING; + import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -7,6 +9,7 @@ import androidx.annotation.NonNull; import net.osmand.plus.R; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.utils.AndroidUtils; public class HikingRoutesFragment extends MapRoutesFragment { @@ -25,6 +28,12 @@ protected void toggleMainPreference(@NonNull View view) { routeLayersHelper.toggleHikingRoutes(); } + @NonNull + @Override + protected String getSelectedAttrName() { + return HIKING.getRenderingPropertyAttr(); + } + protected void setupHeader(@NonNull View view) { super.setupHeader(view); @@ -44,11 +53,13 @@ protected void setupHeader(@NonNull View view) { } @Override - protected void setupCards(@NonNull View view) { - super.setupCards(view); - - cardsContainer.addView(createDivider(cardsContainer, true, true)); + protected void createCards(@NonNull View view) { + super.createCards(view); addCard(new HikingRoutesCard(getMapActivity())); - cardsContainer.addView(createDivider(cardsContainer, false, true)); + + BaseCard card = createRenderingClassCard(getSelectedAttrName()); + if (card != null) { + addCard(card); + } } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/MapRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/MapRoutesFragment.java index 90252960fca..ea96e000f14 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/MapRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/MapRoutesFragment.java @@ -6,6 +6,7 @@ import static net.osmand.osm.OsmRouteType.MTB; import android.os.Bundle; +import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -22,11 +23,13 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.configmap.ConfigureMapUtils; 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.utils.AndroidUtils; import net.osmand.plus.utils.UiUtilities; +import net.osmand.render.RenderingClass; import net.osmand.util.Algorithms; import net.osmand.util.CollectionUtils; @@ -56,6 +59,9 @@ protected boolean isUsedOnMap() { protected abstract void toggleMainPreference(@NonNull View view); + @NonNull + protected abstract String getSelectedAttrName(); + @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -70,8 +76,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c View view = themedInflater.inflate(R.layout.map_routes_fragment, container, false); setupHeader(view); - setupCards(view); - updateContent(); + setupContent(view); return view; } @@ -83,7 +88,7 @@ protected void setupHeader(@NonNull View view) { preferenceContainer.setOnClickListener(v -> { toggleMainPreference(view); setupHeader(view); - updateContent(); + setupContent(view); refreshMap(); }); @@ -106,19 +111,41 @@ protected void setupHeader(@NonNull View view) { protected void addCard(@NonNull BaseCard card) { cards.add(card); card.setListener(this); - cardsContainer.addView(card.build(cardsContainer.getContext())); } - protected void setupCards(@NonNull View view) { + protected void createCards(@NonNull View view) { cards.clear(); + } + + protected void inflateCards(@NonNull View view) { cardsContainer = view.findViewById(R.id.cards_container); cardsContainer.removeAllViews(); + + for (int i = 0; i < cards.size(); i++) { + BaseCard card = cards.get(i); + + if (i == 0) { + cardsContainer.addView(createDivider(cardsContainer, true, true)); + } + cardsContainer.addView(card.build(cardsContainer.getContext())); + + boolean lastItem = i == cards.size() - 1; + cardsContainer.addView(createDivider(cardsContainer, !lastItem, true)); + } } - protected void updateContent() { - for (BaseCard card : cards) { - card.update(); + @Nullable + protected BaseCard createRenderingClassCard(@NonNull String attrName) { + Pair<RenderingClass, List<RenderingClass>> pair = ConfigureMapUtils.getRenderingClassesForKey(app, attrName); + if (pair != null) { + addCard(new RenderingClassesCard(getMapActivity(), pair.first, pair.second)); } + return null; + } + + protected void setupContent(@NonNull View view) { + createCards(view); + inflateCards(view); AndroidUiHelper.updateVisibility(cardsContainer, isEnabled()); } @@ -145,6 +172,7 @@ public void onCardPressed(@NonNull BaseCard card) { View view = getView(); if (view != null) { setupHeader(view); + setupContent(view); } } @@ -167,9 +195,12 @@ protected MapActivity requireMapActivity() { } public static boolean shouldShow(@NonNull OsmandApplication app, @NonNull String attrName) { - return CollectionUtils.equalsToAny(attrName, + boolean defaultScreens = CollectionUtils.equalsToAny(attrName, BICYCLE.getRenderingPropertyAttr(), MTB.getRenderingPropertyAttr(), HIKING.getRenderingPropertyAttr(), ALPINE.getRenderingPropertyAttr()); + + Pair<RenderingClass, List<RenderingClass>> pair = ConfigureMapUtils.getRenderingClassesForKey(app, attrName); + return defaultScreens || pair != null; } @Nullable @@ -183,7 +214,7 @@ public static String getFragmentName(@Nullable String attrName) { } else if (Algorithms.stringsEqual(ALPINE.getRenderingPropertyAttr(), attrName)) { return AlpineHikingScaleFragment.class.getName(); } - return null; + return CustomRoutesFragment.class.getName(); } public static void showInstance(@NonNull FragmentActivity activity, @NonNull String attrName) { diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/MtbRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/MtbRoutesFragment.java index d8506411185..4b203d2d5f9 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/MtbRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/MtbRoutesFragment.java @@ -1,5 +1,7 @@ package net.osmand.plus.configmap.routes; +import static net.osmand.osm.OsmRouteType.MTB; + import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -8,6 +10,7 @@ import net.osmand.plus.R; import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.utils.AndroidUtils; public class MtbRoutesFragment extends MapRoutesFragment { @@ -24,6 +27,13 @@ protected void toggleMainPreference(@NonNull View view) { routeLayersHelper.toggleMtbRoutes(); } + @NonNull + @Override + protected String getSelectedAttrName() { + MtbClassification classification = routeLayersHelper.getSelectedMtbClassification(); + return classification != null ? classification.attrName : MTB.getRenderingPropertyAttr(); + } + protected void setupHeader(@NonNull View view) { super.setupHeader(view); @@ -31,7 +41,7 @@ protected void setupHeader(@NonNull View view) { View container = view.findViewById(R.id.preference_container); TextView title = container.findViewById(R.id.title); - title.setText(R.string.rendering_attr_showMtbRoutes_name); + title.setText(routeLayersHelper.getRoutesTypeName(MTB.getRenderingPropertyAttr())); int selectedColor = settings.getApplicationMode().getProfileColor(nightMode); int disabledColor = AndroidUtils.getColorFromAttr(app, R.attr.default_icon_color); @@ -42,11 +52,13 @@ protected void setupHeader(@NonNull View view) { } @Override - protected void setupCards(@NonNull View view) { - super.setupCards(view); - - cardsContainer.addView(createDivider(cardsContainer, true, true)); + protected void createCards(@NonNull View view) { + super.createCards(view); addCard(new MtbRoutesCard(getMapActivity())); - cardsContainer.addView(createDivider(cardsContainer, false, true)); + + BaseCard card = createRenderingClassCard(getSelectedAttrName()); + if (card != null) { + addCard(card); + } } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassesCard.java b/OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassesCard.java new file mode 100644 index 00000000000..c583bafac62 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassesCard.java @@ -0,0 +1,92 @@ +package net.osmand.plus.configmap.routes; + +import android.graphics.drawable.Drawable; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.routepreparationmenu.cards.MapBaseCard; +import net.osmand.plus.settings.backend.preferences.CommonPreference; +import net.osmand.plus.utils.AndroidUtils; +import net.osmand.plus.utils.ColorUtilities; +import net.osmand.plus.utils.UiUtilities; +import net.osmand.render.RenderingClass; + +import java.util.List; + +public class RenderingClassesCard extends MapBaseCard { + + private final RenderingClass mainClass; + private final List<RenderingClass> list; + + private ViewGroup container; + + @Override + public int getCardLayoutId() { + return R.layout.rendering_classes_card; + } + + public RenderingClassesCard(@NonNull MapActivity activity, @NonNull RenderingClass mainClass, + @NonNull List<RenderingClass> list) { + super(activity, true); + this.mainClass = mainClass; + this.list = list; + } + + @Override + protected void updateContent() { + setupHeader(); + setupRenderingClasses(); + } + + private void setupHeader() { + TextView header = view.findViewById(R.id.header); + header.setText(mainClass.getTitle()); + } + + private void setupRenderingClasses() { + container = view.findViewById(R.id.container); + container.removeAllViews(); + + for (int i = 0; i < list.size(); i++) { + RenderingClass renderingClass = list.get(i); + container.addView(createRadioButton(renderingClass, i == list.size() - 1)); + } + } + + @NonNull + private View createRadioButton(@NonNull RenderingClass renderingClass, boolean lastItem) { + CommonPreference<Boolean> pref = settings.getСustomBooleanRenderClassProperty(renderingClass.getName(), renderingClass.isEnabledByDefault()); + View view = themedInflater.inflate(R.layout.bottom_sheet_item_with_switch_56dp, container, false); + + ImageView icon = view.findViewById(R.id.icon); + AndroidUiHelper.updateVisibility(icon, false); + + TextView title = view.findViewById(R.id.title); + title.setText(renderingClass.getTitle()); + + CompoundButton button = view.findViewById(R.id.compound_button); + UiUtilities.setupCompoundButton(nightMode, ColorUtilities.getActiveColor(app, nightMode), button); + button.setChecked(pref.get()); + + view.setOnClickListener(v -> { + boolean checked = !pref.get(); + pref.set(checked); + button.setChecked(checked); + notifyCardPressed(); + }); + + int profileColor = settings.getApplicationMode().getProfileColor(nightMode); + Drawable background = UiUtilities.getColoredSelectableDrawable(app, profileColor, 0.3f); + AndroidUtils.setBackground(view, background); + + return view; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/RouteLayersHelper.java b/OsmAnd/src/net/osmand/plus/configmap/routes/RouteLayersHelper.java index 4870d2c7f84..40045f52109 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/RouteLayersHelper.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/RouteLayersHelper.java @@ -195,6 +195,17 @@ public String getSelectedMtbClassificationName(@NonNull Context context) { return ""; } + @NonNull + public MtbClassification getSelectedMtbClassification() { + String selectedId = getSelectedMtbClassificationId(); + for (MtbClassification classification : MtbClassification.values()) { + if (Objects.equals(classification.attrName, selectedId)) { + return classification; + } + } + return null; + } + @Nullable public String getSelectedMtbClassificationId() { return isMtbRoutesEnabled() ? mtbRoutesLastClassification.get() : null; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java index afa85d70da9..f43156d718b 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java @@ -3084,16 +3084,6 @@ public CommonPreference<Boolean> getCustomRenderBooleanProperty(@NonNull String return customBooleanRendersProps.get(attrName); } - @NonNull - public CommonPreference<Boolean> getСustomBooleanRenderClassProperty(@NonNull String className, boolean defaultValue) { - if (!customBooleanRenderClassProps.containsKey(className)) { - CommonPreference<Boolean> preference = new BooleanPreference(this, className, defaultValue).makeProfile(); - customBooleanRenderClassProps.put(className, preference); - return preference; - } - return customBooleanRenderClassProps.get(className); - } - @NonNull public CommonPreference<Boolean> registerCustomRenderBooleanProperty(@NonNull String attrName, boolean defaultValue) { String id = attrName.startsWith(RENDERER_PREFERENCE_PREFIX) ? attrName : RENDERER_PREFERENCE_PREFIX + attrName; @@ -3120,6 +3110,16 @@ public CommonPreference<Boolean> getCustomRoutingBooleanProperty(@NonNull String return customBooleanRoutingProps.get(attrName); } + @NonNull + public CommonPreference<Boolean> getСustomBooleanRenderClassProperty(@NonNull String name, boolean defaultValue) { + if (!customBooleanRenderClassProps.containsKey(name)) { + CommonPreference<Boolean> preference = new BooleanPreference(this, name, defaultValue).makeProfile(); + customBooleanRenderClassProps.put(name, preference); + return preference; + } + return customBooleanRenderClassProps.get(name); + } + public final OsmandPreference<Boolean> SHOW_TRAVEL = new BooleanPreference(this, "show_travel_routes", false).makeProfile().cache(); public final CommonPreference<Float> ROUTE_RECALCULATION_DISTANCE = new FloatPreference(this, "routing_recalc_distance", 0.f).makeProfile(); From d8b7afcaf492343466dbe1936fb5282b2484e28d Mon Sep 17 00:00:00 2001 From: chumv <chumva.forever@gmail.com> Date: Tue, 4 Feb 2025 19:23:26 +0200 Subject: [PATCH 07/10] Remove deprecated renderingAssociation --- .../java/net/osmand/render/RenderingRule.java | 3 - .../render/RenderingRuleSearchRequest.java | 10 --- .../osmand/render/RenderingRulesStorage.java | 78 ++++--------------- 3 files changed, 16 insertions(+), 75 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRule.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRule.java index adb59f9c767..2eaae8a9a96 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRule.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRule.java @@ -64,9 +64,6 @@ public void init(Map<String, String> attributes) { attributesRef = new RenderingRule[attributes.size()]; } attributesRef[i] = storage.getRenderingAttributeRule(vl.substring(1)); - if (attributesRef[i] == null) { - attributesRef[i] = storage.getRenderingAssociationRule(vl.substring(1)); - } } else if (property.isString()) { intProperties[i] = storage.getDictionaryValue(vl); } else { diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRuleSearchRequest.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRuleSearchRequest.java index c4c911cc764..3d3168fb96e 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRuleSearchRequest.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRuleSearchRequest.java @@ -161,16 +161,6 @@ public boolean searchRenderingAttribute(String attribute) { return searchResult; } - public boolean searchRenderingAssociation(String association) { - searchResult = false; - RenderingRule rule = storage.getRenderingAssociationRule(association); - if (rule == null) { - return false; - } - searchResult = visitRule(rule, true); - return searchResult; - } - public boolean search(int state) { return search(state, true); } diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java index dda11e451ca..d6881497c9a 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java @@ -12,15 +12,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Stack; import gnu.trove.map.hash.TIntObjectHashMap; @@ -54,7 +47,6 @@ public class RenderingRulesStorage { public TIntObjectHashMap<RenderingRule>[] tagValueGlobalRules = new TIntObjectHashMap[LENGTH_RULES]; protected Map<String, RenderingRule> renderingAttributes = new LinkedHashMap<String, RenderingRule>(); - protected Map<String, RenderingRule> renderingAssociations = new LinkedHashMap<String, RenderingRule>(); protected Map<String, RenderingClass> renderingClasses = new LinkedHashMap<String, RenderingClass>(); protected Map<String, String> renderingConstants = new LinkedHashMap<String, String>(); @@ -99,7 +91,6 @@ public RenderingRulesStorage copy() { } } storage.renderingAttributes.putAll(renderingAttributes); - storage.renderingAssociations.putAll(renderingAssociations); storage.renderingClasses.putAll(renderingClasses); return storage; } @@ -163,20 +154,6 @@ public void mergeDependsOrAddon(RenderingRulesStorage depends) { renderingAttributes.put(e.getKey(), e.getValue()); } } - it = depends.renderingAssociations.entrySet().iterator(); - while (it.hasNext()) { - Entry<String, RenderingRule> e = it.next(); - if (renderingAssociations.containsKey(e.getKey())) { - RenderingRule root = renderingAssociations.get(e.getKey()); - List<RenderingRule> list = e.getValue().getIfElseChildren(); - for (RenderingRule every : list) { - root.addIfElseChildren(every); - } - e.getValue().addToBeginIfElseChildren(root); - } else { - renderingAssociations.put(e.getKey(), e.getValue()); - } - } for (int i = 0; i < LENGTH_RULES; i++) { if (depends.tagValueGlobalRules[i] == null || depends.tagValueGlobalRules[i].isEmpty()) { continue; @@ -272,7 +249,7 @@ private void process(RenderingRulesHandler handler, int el) throws XmlPullParser private class RenderingRulesHandler { private final XmlPullParser parser; private int state; - Stack<RenderingRule> stack = new Stack<RenderingRule>(); + private Stack<RenderingRule> stack = new Stack<RenderingRule>(); private final RenderingRulesStorageResolver resolver; private final boolean addon; private RenderingRulesStorage dependsStorage; @@ -376,7 +353,7 @@ public void startElement(Map<String, String> attrsMap, String name) throws XmlPu state = LINE_RULES; } else if("polygon".equals(name)){ //$NON-NLS-1$ state = POLYGON_RULES; - } else if("renderingAttribute".equals(name)){ //$NON-NLS-1$ + } else if ("renderingAttribute".equals(name)) { //$NON-NLS-1$ String attr = attrsMap.get("name"); RenderingRule root = new RenderingRule(new HashMap<String, String>(), false, RenderingRulesStorage.this); if (renderingAttributes.containsKey(attr)) { @@ -385,22 +362,13 @@ public void startElement(Map<String, String> attrsMap, String name) throws XmlPu renderingAttributes.put(attr, root); } stack.push(root); - } else if("renderingAssociation".equals(name)){ //$NON-NLS-1$ - String attr = attrsMap.get("name"); - RenderingRule root = new RenderingRule(new HashMap<String, String>(), false, RenderingRulesStorage.this); - if (renderingAssociations.containsKey(attr)) { - renderingAssociations.get(attr).addIfElseChildren(root); - } else { - renderingAssociations.put(attr, root); - } - stack.push(root); - } else if("renderingProperty".equals(name)){ //$NON-NLS-1$ + } else if ("renderingProperty".equals(name)) { //$NON-NLS-1$ String attr = attrsMap.get("attr"); RenderingRuleProperty prop; String type = attrsMap.get("type"); - if("boolean".equalsIgnoreCase(type)){ + if ("boolean".equalsIgnoreCase(type)) { prop = RenderingRuleProperty.createInputBooleanProperty(attr); - } else if("string".equalsIgnoreCase(type)){ + } else if ("string".equalsIgnoreCase(type)) { prop = RenderingRuleProperty.createInputStringProperty(attr); } else { prop = RenderingRuleProperty.createInputIntProperty(attr); @@ -413,11 +381,11 @@ public void startElement(Map<String, String> attrsMap, String name) throws XmlPu prop.setPossibleValues(attrsMap.get("possibleValues").split(",")); } PROPS.registerRule(prop, !addon); - } else if("renderingConstant".equals(name)){ //$NON-NLS-1$ - if(!renderingConstants.containsKey(attrsMap.get("name"))){ + } else if ("renderingConstant".equals(name)) { + if (!renderingConstants.containsKey(attrsMap.get("name"))) { renderingConstants.put(attrsMap.get("name"), attrsMap.get("value")); } - } else if ("renderingStyle".equals(name)) { //$NON-NLS-1$ + } else if ("renderingStyle".equals(name)) { if (!addon) { String depends = attrsMap.get("depends"); if (depends != null && depends.length() > 0) { @@ -466,8 +434,8 @@ private Map<String, String> parseAttributes(XmlPullParser parser, Map<String, St if (vl != null && vl.startsWith("$")) { String cv = vl.substring(1); if (!renderingConstants.containsKey(cv) && !renderingAttributes.containsKey(cv) - && !renderingAssociations.containsKey(cv) && !renderingClasses.containsKey(cv)) { - throw new IllegalStateException("Rendering constant or attribute '" + cv + "' was not specified."); + && !renderingClasses.containsKey(cv)) { + throw new IllegalStateException("Rendering constant, attribute or class '" + cv + "' was not specified."); } if (renderingConstants.containsKey(cv)) { vl = renderingConstants.get(cv); @@ -478,7 +446,6 @@ private Map<String, String> parseAttributes(XmlPullParser parser, Map<String, St return m; } - public void endElement(String name) throws XmlPullParserException { if (isCase(name) || isSwitch(name)) { RenderingRule renderingRule = (RenderingRule) stack.pop(); @@ -487,9 +454,7 @@ public void endElement(String name) throws XmlPullParserException { } } else if (isApply(name)) { stack.pop(); - } else if ("renderingAttribute".equals(name)) { //$NON-NLS-1$ - stack.pop(); - } else if ("renderingAssociation".equals(name)) { //$NON-NLS-1$ + } else if ("renderingAttribute".equals(name)) { stack.pop(); } } @@ -539,15 +504,15 @@ public void registerTopLevel(RenderingRule renderingRule, public int getTagValueKey(String tag, String value){ int itag = getDictionaryValue(tag); int ivalue = getDictionaryValue(value); - return (itag << SHIFT_TAG_VAL) | ivalue; + return (itag << SHIFT_TAG_VAL) | ivalue; } public String getValueString(int tagValueKey){ - return getStringValue(tagValueKey & ((1 << SHIFT_TAG_VAL) - 1)); + return getStringValue(tagValueKey & ((1 << SHIFT_TAG_VAL) - 1)); } public String getTagString(int tagValueKey){ - return getStringValue(tagValueKey >> SHIFT_TAG_VAL); + return getStringValue(tagValueKey >> SHIFT_TAG_VAL); } protected RenderingRule getRule(int state, int itag, int ivalue){ @@ -567,26 +532,15 @@ public RenderingRule getRule(int state, int key) { public RenderingRule getRenderingAttributeRule(String attribute) { return renderingAttributes.get(attribute); } - - public RenderingClass getRenderingClass(String name) { - return renderingClasses.get(name); - } public String[] getRenderingAttributeNames() { return renderingAttributes.keySet().toArray(new String[0]); } + public RenderingRule[] getRenderingAttributeValues() { return renderingAttributes.values().toArray(new RenderingRule[0]); } - public RenderingRule getRenderingAssociationRule(String association) { - return renderingAssociations.get(association); - } - - public String[] getRenderingAssociationNames() { - return renderingAssociations.keySet().toArray(new String[0]); - } - public Map<String, RenderingClass> getRenderingClasses() { return renderingClasses; } From d4d9111bad154eae6d0fd37446b36f3e45fa5c9c Mon Sep 17 00:00:00 2001 From: chumv <chumva.forever@gmail.com> Date: Thu, 6 Feb 2025 16:55:11 +0200 Subject: [PATCH 08/10] Add support for inner rendering classes & update UI --- .../java/net/osmand/osm/OsmRouteType.java | 16 +-- .../net/osmand/osm/RenderingPropertyAttr.java | 15 +++ .../net/osmand/render/RenderingClass.java | 64 +++++++++- .../osmand/render/RenderingRulesStorage.java | 117 ++++++++++++++++- OsmAnd/res/layout/rendering_classes_card.xml | 14 +- .../plus/configmap/ConfigureMapUtils.java | 107 +++++++++++----- .../routes/AlpineHikingScaleFragment.java | 19 +-- .../routes/CustomRoutesFragment.java | 13 +- .../configmap/routes/CycleRoutesFragment.java | 16 +-- .../routes/HikingRoutesFragment.java | 14 +- .../configmap/routes/MapRoutesFragment.java | 50 ++++---- .../configmap/routes/MtbRoutesFragment.java | 15 +-- .../routes/RenderingClassFragment.java | 81 ++++++++++++ .../routes/RenderingClassesCard.java | 120 ++++++++++++------ .../configmap/routes/RouteLayersHelper.java | 21 ++- .../osmand/plus/dashboard/DashboardOnMap.java | 30 ++++- .../osmand/plus/dashboard/DashboardType.java | 1 + 17 files changed, 500 insertions(+), 213 deletions(-) create mode 100644 OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java create mode 100644 OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassFragment.java diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/OsmRouteType.java b/OsmAnd-java/src/main/java/net/osmand/osm/OsmRouteType.java index c22a7334777..79ce575116b 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/OsmRouteType.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/OsmRouteType.java @@ -1,6 +1,6 @@ package net.osmand.osm; -import static net.osmand.osm.OsmRouteType.RenderingPropertyAttr.*; +import static net.osmand.osm.RenderingPropertyAttr.*; import net.osmand.binary.BinaryMapDataObject; import net.osmand.binary.BinaryMapIndexReader; @@ -448,18 +448,4 @@ private OsmRouteType reg() { return osmRouteType; } } - - protected static class RenderingPropertyAttr { - static final String HIKING_ROUTES = "hikingRoutesOSMC"; - static final String CYCLE_ROUTES = "showCycleRoutes"; - static final String MTB_ROUTES = "showMtbRoutes"; - static final String ALPINE_HIKING = "alpineHiking"; - static final String HORSE_ROUTES = "horseRoutes"; - static final String PISTE_ROUTES = "pisteRoutes"; - static final String WHITE_WATER_SPORTS = "whiteWaterSports"; - static final String RUNNING_ROUTES = "showRunningRoutes"; - static final String FITNESS_TRAILS = "showFitnessTrails"; - static final String DIRTBIKE_ROUTES = "showDirtbikeTrails"; - static final String CLIMBING_ROUTES = "showClimbingRoutes"; - } } diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java b/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java new file mode 100644 index 00000000000..0ee99e1255a --- /dev/null +++ b/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java @@ -0,0 +1,15 @@ +package net.osmand.osm; + +public class RenderingPropertyAttr { + public static final String HIKING_ROUTES = "hikingRoutesOSMC"; + public static final String CYCLE_ROUTES = "showCycleRoutes"; + public static final String MTB_ROUTES = "showMtbRoutes"; + public static final String ALPINE_HIKING = "alpineHiking"; + public static final String HORSE_ROUTES = "horseRoutes"; + public static final String PISTE_ROUTES = "pisteRoutes"; + public static final String WHITE_WATER_SPORTS = "whiteWaterSports"; + public static final String RUNNING_ROUTES = "showRunningRoutes"; + public static final String FITNESS_TRAILS = "showFitnessTrails"; + public static final String DIRTBIKE_ROUTES = "showDirtbikeTrails"; + public static final String CLIMBING_ROUTES = "showClimbingRoutes"; +} diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java index ee995b45af2..13fbf03e101 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingClass.java @@ -2,28 +2,78 @@ public class RenderingClass { - private final String name; private final String title; + private final String description; + private final String category; + private final String legendObject; + private final String innerLegendObject; + private final String innerTitle; + private final String innerDescription; + private final String innerCategory; + private final String innerNames; private final boolean enabledByDefault; + private final String name; - public RenderingClass(String name, String title, boolean enabledByDefault) { - this.name = name; + public RenderingClass(String title, String description, String category, String legendObject, + String innerLegendObject, String innerTitle, String innerDescription, + String innerCategory, String innerNames, boolean enabledByDefault, String name) { this.title = title; + this.description = description; + this.category = category; + this.legendObject = legendObject; + this.innerLegendObject = innerLegendObject; + this.innerTitle = innerTitle; + this.innerDescription = innerDescription; + this.innerCategory = innerCategory; + this.innerNames = innerNames; this.enabledByDefault = enabledByDefault; - } - - public String getName() { - return name; + this.name = name; } public String getTitle() { return title; } + public String getDescription() { + return description; + } + + public String getCategory() { + return category; + } + + public String getLegendObject() { + return legendObject; + } + + public String getInnerLegendObject() { + return innerLegendObject; + } + + public String getInnerTitle() { + return innerTitle; + } + + public String getInnerDescription() { + return innerDescription; + } + + public String getInnerCategory() { + return innerCategory; + } + + public String getInnerNames() { + return innerNames; + } + public boolean isEnabledByDefault() { return enabledByDefault; } + public String getName() { + return name; + } + @Override public String toString() { return name; diff --git a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java index d6881497c9a..1c06f3828c2 100644 --- a/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java +++ b/OsmAnd-java/src/main/java/net/osmand/render/RenderingRulesStorage.java @@ -177,6 +177,34 @@ public void mergeDependsOrAddon(RenderingRulesStorage depends) { tagValueGlobalRules[i] = depends.tagValueGlobalRules[i]; } } + for (Entry<String, RenderingClass> entry : depends.renderingClasses.entrySet()) { + String className = entry.getKey(); + RenderingClass renderingClass = entry.getValue(); + + if (renderingClasses.containsKey(className)) { + RenderingClass existingClass = renderingClasses.get(className); + RenderingClass mergedClass = mergeRenderingClasses(existingClass, renderingClass); + renderingClasses.put(className, mergedClass); + } else { + renderingClasses.put(className, renderingClass); + } + } + } + + private RenderingClass mergeRenderingClasses(RenderingClass existing, RenderingClass depends) { + return new RenderingClass( + existing.getTitle() != null ? existing.getTitle() : depends.getTitle(), + existing.getDescription() != null ? existing.getDescription() : depends.getDescription(), + existing.getCategory() != null ? existing.getCategory() : depends.getCategory(), + existing.getLegendObject() != null ? existing.getLegendObject() : depends.getLegendObject(), + existing.getInnerLegendObject() != null ? existing.getInnerLegendObject() : depends.getInnerLegendObject(), + existing.getInnerTitle() != null ? existing.getInnerTitle() : depends.getInnerTitle(), + existing.getInnerDescription() != null ? existing.getInnerDescription() : depends.getInnerDescription(), + existing.getInnerCategory() != null ? existing.getInnerCategory() : depends.getInnerCategory(), + existing.getInnerNames() != null ? existing.getInnerNames() : depends.getInnerNames(), + existing.isEnabledByDefault() || depends.isEnabledByDefault(), + existing.getName() != null ? existing.getName() : depends.getName() + ); } public static String colorToString(int color) { @@ -250,6 +278,7 @@ private class RenderingRulesHandler { private final XmlPullParser parser; private int state; private Stack<RenderingRule> stack = new Stack<RenderingRule>(); + private Stack<String> nodeNamesStack = new Stack<String>(); private final RenderingRulesStorageResolver resolver; private final boolean addon; private RenderingRulesStorage dependsStorage; @@ -402,10 +431,7 @@ public void startElement(Map<String, String> attrsMap, String name) throws XmlPu } else if ("renderer".equals(name)) { //$NON-NLS-1$ throw new XmlPullParserException("Rendering style is deprecated and no longer supported."); } else if ("renderingClass".equals(name)) { - String title = attrsMap.get("title"); - String className = attrsMap.get("name"); - boolean enable = Boolean.parseBoolean(attrsMap.get("enable")); - renderingClasses.put(className, new RenderingClass(className, title, enable)); + parseRenderingClass(attrsMap); } else { log.warn("Unknown tag : " + name); //$NON-NLS-1$ } @@ -415,6 +441,83 @@ public void startElement(Map<String, String> attrsMap, String name) throws XmlPu } } + private void parseRenderingClass(Map<String, String> attrsMap) { + StringBuilder path = new StringBuilder(); + if (!nodeNamesStack.isEmpty()) { + for (String nodeName : nodeNamesStack) { + path.append(nodeName); + } + } + + String name = attrsMap.get("name"); + String title = attrsMap.get("title"); + boolean enable = Boolean.parseBoolean(attrsMap.get("enable")); + String description = attrsMap.get("description"); + String category = attrsMap.get("category"); + String legendObject = attrsMap.get("legend-object"); + String innerLegendObject = attrsMap.get("inner-legend-object"); + String innerTitle = attrsMap.get("inner-title"); + String innerDescription = attrsMap.get("inner-description"); + String innerCategory = attrsMap.get("inner-category"); + String innerNames = attrsMap.get("inner-names"); + + path.append(name); + + RenderingClass renderingClass = new RenderingClass(title, description, category, legendObject, + innerLegendObject, innerTitle, innerDescription, innerCategory, innerNames, enable, path.toString()); + + nodeNamesStack.push(name); + renderingClasses.put(renderingClass.getName(), renderingClass); + + parseInnerRenderingClasses(renderingClass); + } + + private void parseInnerRenderingClasses(RenderingClass parentClass) { + String innerNames = parentClass.getInnerNames(); + if (innerNames != null && !innerNames.isEmpty()) { + List<String> classNames = new ArrayList<>(); + String nextPart = innerNames; + int splitPosition = 1; + + while (splitPosition > 0) { + if (!nextPart.isEmpty() && !nextPart.startsWith(",")) { + splitPosition = nextPart.indexOf(','); + String symbolClassName = (splitPosition > 0) ? nextPart.substring(0, splitPosition) : nextPart; + if (!symbolClassName.isEmpty()) { + classNames.add(symbolClassName); + } + } else { + log.error(String.format("'%s' contains an empty name for inner class definition", innerNames)); + break; + } + if (splitPosition > 0) { + nextPart = nextPart.substring(splitPosition + 1); + } + } + + String temp = "$class"; + String path = parentClass.getName(); + boolean enabled = parentClass.isEnabledByDefault(); + String innerLegendObject = parentClass.getInnerLegendObject(); + String innerTitle = parentClass.getInnerTitle(); + String innerDescription = parentClass.getInnerDescription(); + String innerCategory = parentClass.getInnerCategory(); + + for (String className : classNames) { + String classTitle = innerTitle != null ? innerTitle.replace(temp, className) : null; + String classDescription = innerDescription != null ? innerDescription.replace(temp, className) : null; + String classCategory = innerCategory != null ? innerCategory.replace(temp, className) : null; + String classLegendObject = innerLegendObject != null ? innerLegendObject.replace(temp, className) : null; + + RenderingClass newClass = new RenderingClass(classTitle, classDescription, + classCategory, classLegendObject, "", "", + "", "", "", enabled, + path.toString() + "." + className); + renderingClasses.put(newClass.getName(), newClass); + } + } + } + protected boolean isCase(String name) { return "filter".equals(name) || "case".equals(name); } @@ -456,6 +559,8 @@ public void endElement(String name) throws XmlPullParserException { stack.pop(); } else if ("renderingAttribute".equals(name)) { stack.pop(); + } else if ("renderingClass".equals(name)) { + nodeNamesStack.pop(); } } } @@ -541,6 +646,10 @@ public RenderingRule[] getRenderingAttributeValues() { return renderingAttributes.values().toArray(new RenderingRule[0]); } + public RenderingClass getRenderingClass(String name) { + return renderingClasses.get(name); + } + public Map<String, RenderingClass> getRenderingClasses() { return renderingClasses; } diff --git a/OsmAnd/res/layout/rendering_classes_card.xml b/OsmAnd/res/layout/rendering_classes_card.xml index ee033b2031f..166efec3209 100644 --- a/OsmAnd/res/layout/rendering_classes_card.xml +++ b/OsmAnd/res/layout/rendering_classes_card.xml @@ -7,22 +7,10 @@ android:background="?attr/list_background_color" android:orientation="vertical"> - <net.osmand.plus.widgets.TextViewEx - android:id="@+id/header" - style="@style/TitleStyle.Medium" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginHorizontal="@dimen/content_padding" - android:layout_marginVertical="@dimen/content_padding_small" - android:textColor="?android:textColorPrimary" - tools:text="@string/mtb_scale" /> - <LinearLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="vertical"> - - </LinearLayout> + android:orientation="vertical" /> </LinearLayout> \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java b/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java index f82ac50856d..249bb7ebff4 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java +++ b/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java @@ -1,5 +1,6 @@ package net.osmand.plus.configmap; +import static net.osmand.osm.RenderingPropertyAttr.*; import static net.osmand.plus.dialogs.DetailsBottomSheet.STREET_LIGHTING; import static net.osmand.plus.dialogs.DetailsBottomSheet.STREET_LIGHTING_NIGHT; import static net.osmand.plus.settings.backend.OsmandSettings.RENDERER_PREFERENCE_PREFIX; @@ -22,14 +23,18 @@ import net.osmand.render.RenderingRulesStorage; import net.osmand.util.Algorithms; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; public class ConfigureMapUtils { public static final String[] MAP_LANGUAGES_IDS = {"", "en", "af", "als", "ar", "az", "be", "ber", "bg", "bn", "bpy", "br", "bs", "ca", "ceb", "ckb", "cs", "cy", "da", "de", "el", "eo", "es", "et", "eu", "fa", "fi", "fr", "fy", "ga", "gl", "he", "hi", "hsb", "hr", "ht", "hu", "hy", "id", "is", "it", "ja", "ka", "kab", "kk", "kn", "ko", "ku", "la", "lb", "lo", "lt", "lv", "mk", "ml", "mr", "ms", "nds", "new", "nl", "nn", "no", "nv", "oc", "os", "pl", "pms", "pt", "ro", "ru", "sat", "sc", "sh", "sk", "sl", "sq", "sr", "sr-latn", "sv", "sw", "ta", "te", "th", "tl", "tr", "uk", "vi", "vo", "zh", "zh-Hans", "zh-Hant"}; - public static final String ROUTE_CLASS_PREFIX = ".route."; - @NonNull public static Map<String, String> getSorterMapLanguages(@NonNull OsmandApplication app) { Map<String, String> mapLanguages = new HashMap<>(); @@ -51,7 +56,8 @@ public static Map<String, String> getSorterMapLanguages(@NonNull OsmandApplicati * @param unsortedLanguages map of entries like en:English. Empty key stands for device locale or default locale */ @NonNull - public static Comparator<String> getLanguagesComparator(@NonNull Map<String, String> unsortedLanguages) { + public static Comparator<String> getLanguagesComparator( + @NonNull Map<String, String> unsortedLanguages) { return (leftKey, rightKey) -> { int i1 = Algorithms.isEmpty(leftKey) ? 0 : (leftKey.equals("en") ? 1 : 2); int i2 = Algorithms.isEmpty(rightKey) ? 0 : (rightKey.equals("en") ? 1 : 2); @@ -66,7 +72,8 @@ public static Comparator<String> getLanguagesComparator(@NonNull Map<String, Str } @Nullable - public static RenderingRuleProperty getPropertyForAttr(@NonNull OsmandApplication app, @NonNull String attrName) { + public static RenderingRuleProperty getPropertyForAttr(@NonNull OsmandApplication app, + @NonNull String attrName) { return getPropertyForAttr(getCustomRules(app), attrName); } @@ -81,7 +88,8 @@ public static RenderingRuleProperty getPropertyForAttr( return null; } - public static List<RenderingRuleProperty> getCustomRules(@NonNull OsmandApplication app, String... skipCategories) { + public static List<RenderingRuleProperty> getCustomRules(@NonNull OsmandApplication app, + String... skipCategories) { RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); if (renderer == null) { return new ArrayList<>(); @@ -104,50 +112,81 @@ public static List<RenderingRuleProperty> getCustomRules(@NonNull OsmandApplicat return customRules; } - @NonNull - public static Map<String, RenderingClass> getRenderingClasses(@NonNull OsmandApplication app) { - RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); - if (renderer == null) { - return new LinkedHashMap<>(); + protected static String[] getRenderingPropertyPossibleValues(@NonNull OsmandApplication app, + @NonNull RenderingRuleProperty p) { + String[] possibleValuesString = new String[p.getPossibleValues().length + 1]; + possibleValuesString[0] = AndroidUtils.getRenderingStringPropertyValue(app, p.getDefaultValueDescription()); + + for (int j = 0; j < p.getPossibleValues().length; j++) { + possibleValuesString[j + 1] = AndroidUtils.getRenderingStringPropertyValue(app, p.getPossibleValues()[j]); } - return renderer.getRenderingClasses(); + return possibleValuesString; } @NonNull - public static Pair<RenderingClass, List<RenderingClass>> getRenderingClassesForKey( + public static Pair<RenderingClass, List<RenderingClass>> getRenderingClassWithChildren( @NonNull OsmandApplication app, @NonNull String attrName) { RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); - if (renderer == null) { - return null; - } - String key = ROUTE_CLASS_PREFIX + attrName.replace("show", ""); - RenderingClass mainClass = renderer.getRenderingClass(key); - if (mainClass != null) { - List<RenderingClass> list = new ArrayList<>(); - for (Map.Entry<String, RenderingClass> entry : renderer.getRenderingClasses().entrySet()) { - RenderingClass renderingClass = entry.getValue(); - if (renderingClass.getName().startsWith(key + ".")) { - list.add(renderingClass); - } + if (renderer != null) { + String key = getRenderingClassNameForAttr(app, attrName); + RenderingClass renderingClass = renderer.getRenderingClass(key); + if (renderingClass != null) { + List<RenderingClass> children = getChildrenRenderingClasses(app, renderingClass); + return Pair.create(renderingClass, children); } - return Pair.create(mainClass, list); } return null; } - protected static String[] getRenderingPropertyPossibleValues(OsmandApplication app, - RenderingRuleProperty p) { - String[] possibleValuesString = new String[p.getPossibleValues().length + 1]; - possibleValuesString[0] = AndroidUtils.getRenderingStringPropertyValue(app, p.getDefaultValueDescription()); + @NonNull + public static List<RenderingClass> getChildrenRenderingClasses(@NonNull OsmandApplication app, + @NonNull RenderingClass parentClass) { + RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); + if (renderer != null) { + String key = parentClass.getName(); + return renderer.getRenderingClasses().values().stream() + .filter(renderingClass -> { + String name = renderingClass.getName(); + return name.startsWith(key + ".") && name.lastIndexOf('.') == key.length(); + }) + .collect(Collectors.toList()); + } + return null; + } - for (int j = 0; j < p.getPossibleValues().length; j++) { - possibleValuesString[j + 1] = AndroidUtils.getRenderingStringPropertyValue(app, p.getPossibleValues()[j]); + @NonNull + public static String getRenderingClassNameForAttr(@NonNull OsmandApplication app, + @NonNull String attrName) { + switch (attrName) { + case HIKING_ROUTES: + return ".route.hiking"; + case CYCLE_ROUTES: + return ".route.bicycle"; + case MTB_ROUTES: + return ".route.mtb"; + case "showMtbScale": + return ".route.mtb.mtb_scale"; + case "showMtbScaleIMBATrails": + return ".route.mtb.mtb_scale_imba"; + case ALPINE_HIKING: + return ".road.alpinehiking"; + case HORSE_ROUTES: + return ".route.horse"; + case PISTE_ROUTES: + return ".route.piste"; + case RUNNING_ROUTES: + return ".route.running"; + case FITNESS_TRAILS: + return ".route.fitness_trail"; + case DIRTBIKE_ROUTES: + return ".route.dirtbike"; + default: + return attrName; } - return possibleValuesString; } protected static String getDescription(@NonNull OsmandSettings settings, - @NonNull List<CommonPreference<Boolean>> prefs) { + @NonNull List<CommonPreference<Boolean>> prefs) { int count = 0; int enabled = 0; diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/AlpineHikingScaleFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/AlpineHikingScaleFragment.java index e5e61feef62..83c23cb46df 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/AlpineHikingScaleFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/AlpineHikingScaleFragment.java @@ -10,7 +10,6 @@ import net.osmand.plus.R; import net.osmand.plus.helpers.AndroidUiHelper; -import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.utils.AndroidUtils; public class AlpineHikingScaleFragment extends MapRoutesFragment { @@ -27,12 +26,6 @@ protected void toggleMainPreference(@NonNull View view) { routeLayersHelper.toggleAlpineHikingRoutes(); } - @NonNull - @Override - protected String getSelectedAttrName() { - return ALPINE.getRenderingPropertyAttr(); - } - protected void setupHeader(@NonNull View view) { super.setupHeader(view); @@ -43,14 +36,14 @@ protected void setupHeader(@NonNull View view) { title.setText(R.string.rendering_attr_alpineHiking_name); TextView description = container.findViewById(R.id.description); - description.setText(routeLayersHelper.getRoutesTypeDescription(getSelectedAttrName())); + description.setText(routeLayersHelper.getRoutesTypeDescription(ALPINE.getRenderingPropertyAttr())); AndroidUiHelper.updateVisibility(description, enabled); int selectedColor = settings.getApplicationMode().getProfileColor(nightMode); int disabledColor = AndroidUtils.getColorFromAttr(app, R.attr.default_icon_color); ImageView icon = container.findViewById(R.id.icon); - icon.setImageDrawable(getPaintedContentIcon(RouteUtils.getIconIdForAttr(getSelectedAttrName()), - enabled ? selectedColor : disabledColor)); + icon.setImageDrawable(getPaintedContentIcon(RouteUtils.getIconIdForAttr( + ALPINE.getRenderingPropertyAttr()), enabled ? selectedColor : disabledColor)); } @Override @@ -58,10 +51,6 @@ protected void createCards(@NonNull View view) { super.createCards(view); addCard(new AlpineHikingCard(getMapActivity())); - - BaseCard card = createRenderingClassCard(getSelectedAttrName()); - if (card != null) { - addCard(card); - } + addRenderingClassCard(ALPINE.getRenderingPropertyAttr()); } } diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/CustomRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/CustomRoutesFragment.java index 7650bd3b3a4..d5fa3ba65f1 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/CustomRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/CustomRoutesFragment.java @@ -1,5 +1,7 @@ package net.osmand.plus.configmap.routes; +import static net.osmand.osm.OsmRouteType.MTB; + import android.os.Bundle; import android.util.Pair; import android.view.View; @@ -36,12 +38,6 @@ protected void toggleMainPreference(@NonNull View view) { routeLayersHelper.toggleRoutesType(attrName); } - @NonNull - @Override - protected @NotNull String getSelectedAttrName() { - return attrName; - } - @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -72,9 +68,6 @@ protected void setupHeader(@NonNull View view) { protected void createCards(@NonNull View view) { super.createCards(view); - BaseCard card = createRenderingClassCard(getSelectedAttrName()); - if (card != null) { - addCard(card); - } + addRenderingClassCard(attrName); } } diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/CycleRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/CycleRoutesFragment.java index 7b5400d088a..fcae8c180b7 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/CycleRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/CycleRoutesFragment.java @@ -9,12 +9,9 @@ import androidx.annotation.NonNull; import net.osmand.plus.R; -import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.utils.AndroidUtils; import net.osmand.plus.utils.ColorUtilities; -import org.jetbrains.annotations.NotNull; - public class CycleRoutesFragment extends MapRoutesFragment { public static final String TAG = CycleRoutesFragment.class.getSimpleName(); @@ -29,12 +26,6 @@ protected void toggleMainPreference(@NonNull View view) { routeLayersHelper.toggleCycleRoutes(); } - @NonNull - @Override - protected String getSelectedAttrName() { - return BICYCLE.getRenderingPropertyAttr(); - } - protected void setupHeader(@NonNull View view) { super.setupHeader(view); @@ -57,11 +48,8 @@ protected void setupHeader(@NonNull View view) { @Override protected void createCards(@NonNull View view) { super.createCards(view); - addCard(new CycleRouteTypesCard(getMapActivity())); - BaseCard card = createRenderingClassCard(getSelectedAttrName()); - if (card != null) { - addCard(card); - } + addCard(new CycleRouteTypesCard(getMapActivity())); + addRenderingClassCard(BICYCLE.getRenderingPropertyAttr()); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/HikingRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/HikingRoutesFragment.java index 655c2716417..46d68d6f8bf 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/HikingRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/HikingRoutesFragment.java @@ -9,7 +9,6 @@ import androidx.annotation.NonNull; import net.osmand.plus.R; -import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.utils.AndroidUtils; public class HikingRoutesFragment extends MapRoutesFragment { @@ -28,12 +27,6 @@ protected void toggleMainPreference(@NonNull View view) { routeLayersHelper.toggleHikingRoutes(); } - @NonNull - @Override - protected String getSelectedAttrName() { - return HIKING.getRenderingPropertyAttr(); - } - protected void setupHeader(@NonNull View view) { super.setupHeader(view); @@ -55,11 +48,8 @@ protected void setupHeader(@NonNull View view) { @Override protected void createCards(@NonNull View view) { super.createCards(view); - addCard(new HikingRoutesCard(getMapActivity())); - BaseCard card = createRenderingClassCard(getSelectedAttrName()); - if (card != null) { - addCard(card); - } + addCard(new HikingRoutesCard(getMapActivity())); + addRenderingClassCard(HIKING.getRenderingPropertyAttr()); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/MapRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/MapRoutesFragment.java index ea96e000f14..4517a1eee48 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/MapRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/MapRoutesFragment.java @@ -59,9 +59,6 @@ protected boolean isUsedOnMap() { protected abstract void toggleMainPreference(@NonNull View view); - @NonNull - protected abstract String getSelectedAttrName(); - @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -108,9 +105,10 @@ protected void setupHeader(@NonNull View view) { AndroidUiHelper.updateVisibility(view.findViewById(R.id.header_divider), !enabled); } - protected void addCard(@NonNull BaseCard card) { - cards.add(card); - card.setListener(this); + protected void setupContent(@NonNull View view) { + createCards(view); + inflateCards(view); + AndroidUiHelper.updateVisibility(cardsContainer, isEnabled()); } protected void createCards(@NonNull View view) { @@ -134,27 +132,25 @@ protected void inflateCards(@NonNull View view) { } } - @Nullable - protected BaseCard createRenderingClassCard(@NonNull String attrName) { - Pair<RenderingClass, List<RenderingClass>> pair = ConfigureMapUtils.getRenderingClassesForKey(app, attrName); - if (pair != null) { - addCard(new RenderingClassesCard(getMapActivity(), pair.first, pair.second)); - } - return null; + protected void addCard(@NonNull BaseCard card) { + cards.add(card); + card.setListener(this); } - protected void setupContent(@NonNull View view) { - createCards(view); - inflateCards(view); - AndroidUiHelper.updateVisibility(cardsContainer, isEnabled()); + protected void addRenderingClassCard(@NonNull String attrName) { + BaseCard card = createRenderingClassCard(attrName); + if (card != null) { + addCard(card); + } } - protected void refreshMap() { - MapActivity mapActivity = (MapActivity) getMyActivity(); - if (mapActivity != null) { - mapActivity.refreshMapComplete(); - mapActivity.updateLayers(); + @Nullable + protected BaseCard createRenderingClassCard(@NonNull String attrName) { + Pair<RenderingClass, List<RenderingClass>> pair = ConfigureMapUtils.getRenderingClassWithChildren(app, attrName); + if (pair != null) { + return new RenderingClassesCard(getMapActivity(), pair.first, pair.second); } + return null; } @NonNull @@ -176,6 +172,14 @@ public void onCardPressed(@NonNull BaseCard card) { } } + protected void refreshMap() { + MapActivity mapActivity = (MapActivity) getMyActivity(); + if (mapActivity != null) { + mapActivity.refreshMapComplete(); + mapActivity.updateLayers(); + } + } + @Nullable protected MapActivity getMapActivity() { FragmentActivity activity = getActivity(); @@ -199,7 +203,7 @@ public static boolean shouldShow(@NonNull OsmandApplication app, @NonNull String BICYCLE.getRenderingPropertyAttr(), MTB.getRenderingPropertyAttr(), HIKING.getRenderingPropertyAttr(), ALPINE.getRenderingPropertyAttr()); - Pair<RenderingClass, List<RenderingClass>> pair = ConfigureMapUtils.getRenderingClassesForKey(app, attrName); + Pair<RenderingClass, List<RenderingClass>> pair = ConfigureMapUtils.getRenderingClassWithChildren(app, attrName); return defaultScreens || pair != null; } diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/MtbRoutesFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/MtbRoutesFragment.java index 4b203d2d5f9..9b401bcf999 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/MtbRoutesFragment.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/MtbRoutesFragment.java @@ -10,7 +10,6 @@ import net.osmand.plus.R; import net.osmand.plus.helpers.AndroidUiHelper; -import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.utils.AndroidUtils; public class MtbRoutesFragment extends MapRoutesFragment { @@ -27,13 +26,6 @@ protected void toggleMainPreference(@NonNull View view) { routeLayersHelper.toggleMtbRoutes(); } - @NonNull - @Override - protected String getSelectedAttrName() { - MtbClassification classification = routeLayersHelper.getSelectedMtbClassification(); - return classification != null ? classification.attrName : MTB.getRenderingPropertyAttr(); - } - protected void setupHeader(@NonNull View view) { super.setupHeader(view); @@ -54,11 +46,8 @@ protected void setupHeader(@NonNull View view) { @Override protected void createCards(@NonNull View view) { super.createCards(view); - addCard(new MtbRoutesCard(getMapActivity())); - BaseCard card = createRenderingClassCard(getSelectedAttrName()); - if (card != null) { - addCard(card); - } + addCard(new MtbRoutesCard(getMapActivity())); + addRenderingClassCard(MTB.getRenderingPropertyAttr()); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassFragment.java b/OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassFragment.java new file mode 100644 index 00000000000..dbef2e89c8d --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassFragment.java @@ -0,0 +1,81 @@ +package net.osmand.plus.configmap.routes; + +import android.os.Bundle; +import android.util.Pair; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import net.osmand.plus.R; +import net.osmand.plus.configmap.ConfigureMapUtils; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.settings.backend.preferences.CommonPreference; +import net.osmand.plus.utils.AndroidUtils; +import net.osmand.render.RenderingClass; + +import java.util.List; + +public class RenderingClassFragment extends MapRoutesFragment { + + public static final String TAG = RenderingClassFragment.class.getSimpleName(); + + private RenderingClass renderingClass; + private CommonPreference<Boolean> preference; + + @Override + protected boolean isEnabled() { + return preference.get(); + } + + @Override + protected void toggleMainPreference(@NonNull View view) { + preference.set(!isEnabled()); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + renderingClass = app.getRouteLayersHelper().getSelectedRenderingClass(); + preference = settings.getСustomBooleanRenderClassProperty(renderingClass.getName(), renderingClass.isEnabledByDefault()); + } + + protected void setupHeader(@NonNull View view) { + super.setupHeader(view); + + boolean enabled = isEnabled(); + View container = view.findViewById(R.id.preference_container); + + TextView title = container.findViewById(R.id.title); + title.setText(renderingClass.getTitle()); + + AndroidUiHelper.updateVisibility(container.findViewById(R.id.icon), false); + AndroidUiHelper.updateVisibility(container.findViewById(R.id.description), false); + } + + @Override + protected void createCards(@NonNull View view) { + super.createCards(view); + + Pair<RenderingClass, List<RenderingClass>> pair = ConfigureMapUtils.getRenderingClassWithChildren(app, renderingClass.getName()); + if (pair != null) { + addCard(new RenderingClassesCard(getMapActivity(), null, pair.second)); + } + } + + public static void showInstance(@NonNull FragmentActivity activity, + @NonNull RenderingClass renderingClass) { + FragmentManager manager = activity.getSupportFragmentManager(); + if (AndroidUtils.isFragmentCanBeAdded(manager, TAG)) { + RenderingClassFragment fragment = new RenderingClassFragment(); + fragment.renderingClass = renderingClass; + manager.beginTransaction() + .replace(R.id.content, fragment, fragment.getTag()) + .commitAllowingStateLoss(); + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassesCard.java b/OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassesCard.java index c583bafac62..0f5216af524 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassesCard.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/RenderingClassesCard.java @@ -1,31 +1,40 @@ package net.osmand.plus.configmap.routes; -import android.graphics.drawable.Drawable; +import static net.osmand.plus.dashboard.DashboardType.RENDERING_CLASS; +import static net.osmand.plus.widgets.ctxmenu.data.ContextMenuItem.INVALID_ID; + import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.CompoundButton; -import android.widget.ImageView; +import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.configmap.ConfigureMapUtils; import net.osmand.plus.routepreparationmenu.cards.MapBaseCard; import net.osmand.plus.settings.backend.preferences.CommonPreference; import net.osmand.plus.utils.AndroidUtils; -import net.osmand.plus.utils.ColorUtilities; +import net.osmand.plus.utils.FontCache; import net.osmand.plus.utils.UiUtilities; +import net.osmand.plus.widgets.ctxmenu.ViewCreator; +import net.osmand.plus.widgets.ctxmenu.data.ContextMenuItem; import net.osmand.render.RenderingClass; +import net.osmand.util.Algorithms; import java.util.List; public class RenderingClassesCard extends MapBaseCard { - private final RenderingClass mainClass; - private final List<RenderingClass> list; + private final RouteLayersHelper routeLayersHelper; + private final RenderingClass renderingClass; + private final List<RenderingClass> subclasses; + private ViewCreator viewCreator; private ViewGroup container; @Override @@ -33,59 +42,88 @@ public int getCardLayoutId() { return R.layout.rendering_classes_card; } - public RenderingClassesCard(@NonNull MapActivity activity, @NonNull RenderingClass mainClass, - @NonNull List<RenderingClass> list) { + public RenderingClassesCard(@NonNull MapActivity activity, + @Nullable RenderingClass renderingClass, + @Nullable List<RenderingClass> subclasses) { super(activity, true); - this.mainClass = mainClass; - this.list = list; - } + this.renderingClass = renderingClass; + this.subclasses = subclasses; - @Override - protected void updateContent() { - setupHeader(); - setupRenderingClasses(); - } + routeLayersHelper = app.getRouteLayersHelper(); - private void setupHeader() { - TextView header = view.findViewById(R.id.header); - header.setText(mainClass.getTitle()); + viewCreator = new ViewCreator(activity, nightMode); + viewCreator.setDefaultLayoutId(R.layout.list_item_icon_and_menu); + viewCreator.setCustomControlsColor(settings.getApplicationMode().getProfileColor(nightMode)); } - private void setupRenderingClasses() { + @Override + protected void updateContent() { container = view.findViewById(R.id.container); container.removeAllViews(); - for (int i = 0; i < list.size(); i++) { - RenderingClass renderingClass = list.get(i); - container.addView(createRadioButton(renderingClass, i == list.size() - 1)); + if (renderingClass != null) { + container.addView(createHeaderRow(renderingClass)); + } + + if (!Algorithms.isEmpty(subclasses)) { + container.addView(themedInflater.inflate(R.layout.simple_divider_item, container, false)); + + for (int i = 0; i < subclasses.size(); i++) { + RenderingClass renderingClass = subclasses.get(i); + boolean lastItem = i == subclasses.size() - 1; + List<RenderingClass> children = ConfigureMapUtils.getChildrenRenderingClasses(app, renderingClass); + container.addView(createItemRow(renderingClass, !Algorithms.isEmpty(children), !lastItem)); + } } } @NonNull - private View createRadioButton(@NonNull RenderingClass renderingClass, boolean lastItem) { - CommonPreference<Boolean> pref = settings.getСustomBooleanRenderClassProperty(renderingClass.getName(), renderingClass.isEnabledByDefault()); - View view = themedInflater.inflate(R.layout.bottom_sheet_item_with_switch_56dp, container, false); - - ImageView icon = view.findViewById(R.id.icon); - AndroidUiHelper.updateVisibility(icon, false); + private View createHeaderRow(@NonNull RenderingClass renderingClass) { + View view = createItemRow(renderingClass, false, false); TextView title = view.findViewById(R.id.title); - title.setText(renderingClass.getTitle()); + title.setTypeface(FontCache.getMediumFont(title.getTypeface())); - CompoundButton button = view.findViewById(R.id.compound_button); - UiUtilities.setupCompoundButton(nightMode, ColorUtilities.getActiveColor(app, nightMode), button); - button.setChecked(pref.get()); + return view; + } - view.setOnClickListener(v -> { - boolean checked = !pref.get(); - pref.set(checked); - button.setChecked(checked); - notifyCardPressed(); + @NonNull + private View createItemRow(@NonNull RenderingClass renderingClass, boolean showSubscreen, boolean showDivider) { + CommonPreference<Boolean> pref = settings.getСustomBooleanRenderClassProperty( + renderingClass.getName(), renderingClass.isEnabledByDefault()); + boolean enabled = pref.get(); + + ContextMenuItem item = new ContextMenuItem(renderingClass.getName()) + .setSelected(enabled) + .setHideDivider(!showDivider) + .setTitle(renderingClass.getTitle()) + .setColor(enabled ? settings.getApplicationMode().getProfileColor(nightMode) : null) + .setSecondaryIcon(showSubscreen ? R.drawable.ic_action_additional_option : INVALID_ID); + + View view = viewCreator.getView(item, null); + + CompoundButton compoundButton = view.findViewById(R.id.toggle_item); + compoundButton.setOnCheckedChangeListener(new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + pref.set(isChecked); + notifyCardPressed(); + } + }); + view.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (showSubscreen) { + routeLayersHelper.setSelectedRenderingClass(renderingClass); + mapActivity.getDashboard().setDashboardVisibility(true, + RENDERING_CLASS, AndroidUtils.getCenterViewCoordinates(view)); + } else { + compoundButton.toggle(); + } + } }); - int profileColor = settings.getApplicationMode().getProfileColor(nightMode); - Drawable background = UiUtilities.getColoredSelectableDrawable(app, profileColor, 0.3f); - AndroidUtils.setBackground(view, background); + AndroidUtils.setBackground(view, UiUtilities.getColoredSelectableDrawable(app, profileColor, 0.3f)); return view; } diff --git a/OsmAnd/src/net/osmand/plus/configmap/routes/RouteLayersHelper.java b/OsmAnd/src/net/osmand/plus/configmap/routes/RouteLayersHelper.java index 40045f52109..e116fbd0762 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/routes/RouteLayersHelper.java +++ b/OsmAnd/src/net/osmand/plus/configmap/routes/RouteLayersHelper.java @@ -19,6 +19,7 @@ import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.preferences.CommonPreference; import net.osmand.plus.utils.AndroidUtils; +import net.osmand.render.RenderingClass; import net.osmand.render.RenderingRuleProperty; import net.osmand.util.Algorithms; @@ -46,6 +47,8 @@ public class RouteLayersHelper { @Nullable private String selectedAttrName; + @Nullable + private RenderingClass selectedRenderingClass; public RouteLayersHelper(@NonNull OsmandApplication app) { this.app = app; @@ -74,6 +77,15 @@ public void setSelectedAttrName(@Nullable String selectedAttrName) { this.selectedAttrName = selectedAttrName; } + @Nullable + public RenderingClass getSelectedRenderingClass() { + return selectedRenderingClass; + } + + public void setSelectedRenderingClass(@Nullable RenderingClass renderingClass) { + this.selectedRenderingClass = renderingClass; + } + public void toggleRoutesType(@NonNull String attrName) { if (BICYCLE.getRenderingPropertyAttr().equals(attrName)) { toggleCycleRoutes(); @@ -186,13 +198,8 @@ public void updateSelectedMtbClassification(@Nullable String classificationId) { @NonNull public String getSelectedMtbClassificationName(@NonNull Context context) { - String selectedId = getSelectedMtbClassificationId(); - for (MtbClassification classification : MtbClassification.values()) { - if (Objects.equals(classification.attrName, selectedId)) { - return context.getString(classification.nameId); - } - } - return ""; + MtbClassification classification = getSelectedMtbClassification(); + return classification != null ? context.getString(classification.nameId) : ""; } @NonNull diff --git a/OsmAnd/src/net/osmand/plus/dashboard/DashboardOnMap.java b/OsmAnd/src/net/osmand/plus/dashboard/DashboardOnMap.java index e314ab40911..59221b9cc7e 100644 --- a/OsmAnd/src/net/osmand/plus/dashboard/DashboardOnMap.java +++ b/OsmAnd/src/net/osmand/plus/dashboard/DashboardOnMap.java @@ -43,8 +43,11 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.configmap.routes.*; import net.osmand.plus.configmap.ConfigureMapFragment; +import net.osmand.plus.configmap.routes.MapRoutesFragment; +import net.osmand.plus.configmap.routes.RenderingClassFragment; +import net.osmand.plus.configmap.routes.RouteLayersHelper; +import net.osmand.plus.configmap.routes.TravelRoutesFragment; import net.osmand.plus.dashboard.tools.DashFragmentData; import net.osmand.plus.dashboard.tools.DashboardSettingsDialogFragment; import net.osmand.plus.dashboard.tools.TransactionBuilder; @@ -87,6 +90,7 @@ import net.osmand.plus.widgets.ctxmenu.callback.OnRowItemClick; import net.osmand.plus.widgets.ctxmenu.data.ContextMenuItem; import net.osmand.plus.wikipedia.WikipediaPoiMenu; +import net.osmand.render.RenderingClass; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -321,6 +325,12 @@ private void updateToolbarActions() { } else if (isCurrentType(MAP_ROUTES)) { RouteLayersHelper helper = getMyApplication().getRouteLayersHelper(); tv.setText(helper.getRoutesTypeName(helper.getSelectedAttrName())); + } else if (isCurrentType(RENDERING_CLASS)) { + RouteLayersHelper helper = getMyApplication().getRouteLayersHelper(); + RenderingClass renderingClass = helper.getSelectedRenderingClass(); + if (renderingClass != null) { + tv.setText(renderingClass.getTitle()); + } } ImageView edit = dashboardView.findViewById(R.id.toolbar_edit); edit.setVisibility(View.GONE); @@ -559,7 +569,17 @@ public void setDashboardVisibility(boolean visible, DashboardType type, boolean } else if (isCurrentType(WEATHER_CONTOURS)) { WeatherContoursFragment.showInstance(fragmentManager); } else if (isCurrentType(MAP_ROUTES)) { - MapRoutesFragment.showInstance(mapActivity, getMyApplication().getRouteLayersHelper().getSelectedAttrName()); + RouteLayersHelper helper = getMyApplication().getRouteLayersHelper(); + String attrName = helper.getSelectedAttrName(); + if (attrName != null) { + MapRoutesFragment.showInstance(mapActivity, attrName); + } + } else if (isCurrentType(RENDERING_CLASS)) { + RouteLayersHelper helper = getMyApplication().getRouteLayersHelper(); + RenderingClass renderingClass = helper.getSelectedRenderingClass(); + if (renderingClass != null) { + RenderingClassFragment.showInstance(mapActivity, renderingClass); + } } scrollView.setVisibility(View.VISIBLE); listViewLayout.setVisibility(View.GONE); @@ -624,7 +644,7 @@ private void applyDayNightMode() { } else { listView.setBackgroundColor(backgroundColor); } - if (isNoCurrentType(CONFIGURE_MAP, CONTOUR_LINES, TERRAIN, MAP_ROUTES, TRAVEL_ROUTES, + if (isNoCurrentType(CONFIGURE_MAP, CONTOUR_LINES, TERRAIN, MAP_ROUTES, RENDERING_CLASS, TRAVEL_ROUTES, OSM_NOTES, WIKIPEDIA, TRANSPORT_LINES, WEATHER, WEATHER_LAYER, WEATHER_CONTOURS, NAUTICAL_DEPTH)) { listView.setDivider(dividerDrawable); listView.setDividerHeight(AndroidUtils.dpToPx(mapActivity, 1f)); @@ -962,8 +982,8 @@ public boolean isNoCurrentType(@NonNull DashboardType... types) { public boolean isCurrentTypeHasIndividualFragment() { return isCurrentType( - CONFIGURE_MAP, MAPILLARY, TERRAIN, RELIEF_3D, MAP_ROUTES, TRAVEL_ROUTES, - TRANSPORT_LINES, WEATHER, WEATHER_LAYER, WEATHER_CONTOURS, NAUTICAL_DEPTH + CONFIGURE_MAP, MAPILLARY, TERRAIN, RELIEF_3D, MAP_ROUTES, RENDERING_CLASS, + TRAVEL_ROUTES, TRANSPORT_LINES, WEATHER, WEATHER_LAYER, WEATHER_CONTOURS, NAUTICAL_DEPTH ); } diff --git a/OsmAnd/src/net/osmand/plus/dashboard/DashboardType.java b/OsmAnd/src/net/osmand/plus/dashboard/DashboardType.java index 11a0661d87f..2a792eeb9f7 100644 --- a/OsmAnd/src/net/osmand/plus/dashboard/DashboardType.java +++ b/OsmAnd/src/net/osmand/plus/dashboard/DashboardType.java @@ -18,4 +18,5 @@ public enum DashboardType { WEATHER_CONTOURS, NAUTICAL_DEPTH, MAP_ROUTES, + RENDERING_CLASS } From 3283ef675d56de827146525e3e3b2844aafd6f2a Mon Sep 17 00:00:00 2001 From: chumv <chumva.forever@gmail.com> Date: Fri, 7 Feb 2025 10:52:50 +0200 Subject: [PATCH 09/10] Move getRenderingClassNameForAttr to RenderingPropertyAttr --- .../net/osmand/osm/RenderingPropertyAttr.java | 32 +++++++++++++++++ .../plus/configmap/ConfigureMapUtils.java | 35 ++----------------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java b/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java index 0ee99e1255a..0d5c6c92ca2 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java @@ -1,6 +1,7 @@ package net.osmand.osm; public class RenderingPropertyAttr { + public static final String HIKING_ROUTES = "hikingRoutesOSMC"; public static final String CYCLE_ROUTES = "showCycleRoutes"; public static final String MTB_ROUTES = "showMtbRoutes"; @@ -12,4 +13,35 @@ public class RenderingPropertyAttr { public static final String FITNESS_TRAILS = "showFitnessTrails"; public static final String DIRTBIKE_ROUTES = "showDirtbikeTrails"; public static final String CLIMBING_ROUTES = "showClimbingRoutes"; + public static final String SHOW_MTB_SCALE = "showMtbScale"; + public static final String SHOW_MTB_IMBA_SCALE = "showMtbScaleIMBATrails"; + + public static String getRenderingClassNameForAttr(String attrName) { + switch (attrName) { + case HIKING_ROUTES: + return ".route.hiking"; + case CYCLE_ROUTES: + return ".route.bicycle"; + case MTB_ROUTES: + return ".route.mtb"; + case SHOW_MTB_SCALE: + return ".route.mtb.mtb_scale"; + case SHOW_MTB_IMBA_SCALE: + return ".route.mtb.mtb_scale_imba"; + case ALPINE_HIKING: + return ".road.alpinehiking"; + case HORSE_ROUTES: + return ".route.horse"; + case PISTE_ROUTES: + return ".route.piste"; + case RUNNING_ROUTES: + return ".route.running"; + case FITNESS_TRAILS: + return ".route.fitness_trail"; + case DIRTBIKE_ROUTES: + return ".route.dirtbike"; + default: + return attrName; + } + } } diff --git a/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java b/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java index 249bb7ebff4..8d95910f77f 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java +++ b/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java @@ -1,6 +1,5 @@ package net.osmand.plus.configmap; -import static net.osmand.osm.RenderingPropertyAttr.*; import static net.osmand.plus.dialogs.DetailsBottomSheet.STREET_LIGHTING; import static net.osmand.plus.dialogs.DetailsBottomSheet.STREET_LIGHTING_NIGHT; import static net.osmand.plus.settings.backend.OsmandSettings.RENDERER_PREFERENCE_PREFIX; @@ -11,6 +10,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import net.osmand.osm.RenderingPropertyAttr; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; @@ -128,7 +128,7 @@ public static Pair<RenderingClass, List<RenderingClass>> getRenderingClassWithCh @NonNull OsmandApplication app, @NonNull String attrName) { RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); if (renderer != null) { - String key = getRenderingClassNameForAttr(app, attrName); + String key = RenderingPropertyAttr.getRenderingClassNameForAttr(attrName); RenderingClass renderingClass = renderer.getRenderingClass(key); if (renderingClass != null) { List<RenderingClass> children = getChildrenRenderingClasses(app, renderingClass); @@ -154,37 +154,6 @@ public static List<RenderingClass> getChildrenRenderingClasses(@NonNull OsmandAp return null; } - @NonNull - public static String getRenderingClassNameForAttr(@NonNull OsmandApplication app, - @NonNull String attrName) { - switch (attrName) { - case HIKING_ROUTES: - return ".route.hiking"; - case CYCLE_ROUTES: - return ".route.bicycle"; - case MTB_ROUTES: - return ".route.mtb"; - case "showMtbScale": - return ".route.mtb.mtb_scale"; - case "showMtbScaleIMBATrails": - return ".route.mtb.mtb_scale_imba"; - case ALPINE_HIKING: - return ".road.alpinehiking"; - case HORSE_ROUTES: - return ".route.horse"; - case PISTE_ROUTES: - return ".route.piste"; - case RUNNING_ROUTES: - return ".route.running"; - case FITNESS_TRAILS: - return ".route.fitness_trail"; - case DIRTBIKE_ROUTES: - return ".route.dirtbike"; - default: - return attrName; - } - } - protected static String getDescription(@NonNull OsmandSettings settings, @NonNull List<CommonPreference<Boolean>> prefs) { int count = 0; From e0fbf13bbcdb49a8600f470638c29a167492851d Mon Sep 17 00:00:00 2001 From: chumv <chumva.forever@gmail.com> Date: Fri, 7 Feb 2025 11:08:11 +0200 Subject: [PATCH 10/10] Convert RenderingPropertyAttr to enum --- .../java/net/osmand/osm/OsmRouteType.java | 9 +- .../net/osmand/osm/RenderingPropertyAttr.java | 87 ++++++++++--------- .../plus/configmap/ConfigureMapUtils.java | 3 +- 3 files changed, 53 insertions(+), 46 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/OsmRouteType.java b/OsmAnd-java/src/main/java/net/osmand/osm/OsmRouteType.java index 68a54007c5e..52ac3669b5c 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/OsmRouteType.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/OsmRouteType.java @@ -443,8 +443,13 @@ public RouteActivityTypeBuilder icon(String icon) { return this; } - public RouteActivityTypeBuilder renderingPropertyAttr(String renderingPropertyAttr) { - osmRouteType.renderingPropertyAttr = renderingPropertyAttr; + public RouteActivityTypeBuilder renderingPropertyAttr(String propertyAttr) { + osmRouteType.renderingPropertyAttr = propertyAttr; + return this; + } + + public RouteActivityTypeBuilder renderingPropertyAttr(RenderingPropertyAttr propertyAttr) { + renderingPropertyAttr(propertyAttr.getAttrName()); return this; } diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java b/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java index 0d5c6c92ca2..256ed321b83 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/RenderingPropertyAttr.java @@ -1,47 +1,48 @@ package net.osmand.osm; -public class RenderingPropertyAttr { - - public static final String HIKING_ROUTES = "hikingRoutesOSMC"; - public static final String CYCLE_ROUTES = "showCycleRoutes"; - public static final String MTB_ROUTES = "showMtbRoutes"; - public static final String ALPINE_HIKING = "alpineHiking"; - public static final String HORSE_ROUTES = "horseRoutes"; - public static final String PISTE_ROUTES = "pisteRoutes"; - public static final String WHITE_WATER_SPORTS = "whiteWaterSports"; - public static final String RUNNING_ROUTES = "showRunningRoutes"; - public static final String FITNESS_TRAILS = "showFitnessTrails"; - public static final String DIRTBIKE_ROUTES = "showDirtbikeTrails"; - public static final String CLIMBING_ROUTES = "showClimbingRoutes"; - public static final String SHOW_MTB_SCALE = "showMtbScale"; - public static final String SHOW_MTB_IMBA_SCALE = "showMtbScaleIMBATrails"; - - public static String getRenderingClassNameForAttr(String attrName) { - switch (attrName) { - case HIKING_ROUTES: - return ".route.hiking"; - case CYCLE_ROUTES: - return ".route.bicycle"; - case MTB_ROUTES: - return ".route.mtb"; - case SHOW_MTB_SCALE: - return ".route.mtb.mtb_scale"; - case SHOW_MTB_IMBA_SCALE: - return ".route.mtb.mtb_scale_imba"; - case ALPINE_HIKING: - return ".road.alpinehiking"; - case HORSE_ROUTES: - return ".route.horse"; - case PISTE_ROUTES: - return ".route.piste"; - case RUNNING_ROUTES: - return ".route.running"; - case FITNESS_TRAILS: - return ".route.fitness_trail"; - case DIRTBIKE_ROUTES: - return ".route.dirtbike"; - default: - return attrName; +public enum RenderingPropertyAttr { + + HIKING_ROUTES("hikingRoutesOSMC", ".route.hiking"), + CYCLE_ROUTES("showCycleRoutes", ".route.bicycle"), + MTB_ROUTES("showMtbRoutes", ".route.mtb"), + ALPINE_HIKING("alpineHiking", ".road.alpinehiking"), + HORSE_ROUTES("horseRoutes", ".route.horse"), + PISTE_ROUTES("pisteRoutes", ".route.piste"), + WHITE_WATER_SPORTS("whiteWaterSports", null), + RUNNING_ROUTES("showRunningRoutes", ".route.running"), + FITNESS_TRAILS("showFitnessTrails", ".route.fitness_trail"), + DIRTBIKE_ROUTES("showDirtbikeTrails", ".route.dirtbike"), + CLIMBING_ROUTES("showClimbingRoutes", null), + SHOW_MTB_SCALE("showMtbScale", ".route.mtb.mtb_scale"), + SHOW_MTB_IMBA_SCALE("showMtbScaleIMBATrails", ".route.mtb.mtb_scale_imba"); + + private final String attrName; + private final String renderingClassName; + + RenderingPropertyAttr(String attrName, String renderingClassName) { + this.attrName = attrName; + this.renderingClassName = renderingClassName; + } + + public String getAttrName() { + return attrName; + } + + public String getRenderingClassName() { + return renderingClassName; + } + + public static String getRenderingClassName(String attrName) { + RenderingPropertyAttr attr = fromAttrName(attrName); + return attr != null && attr.renderingClassName != null ? attr.renderingClassName : attrName; + } + + public static RenderingPropertyAttr fromAttrName(String attrName) { + for (RenderingPropertyAttr attr : values()) { + if (attr.attrName.equals(attrName)) { + return attr; + } } + return null; } -} +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java b/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java index 36ed077fbc4..c30adc629b0 100644 --- a/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java +++ b/OsmAnd/src/net/osmand/plus/configmap/ConfigureMapUtils.java @@ -130,7 +130,8 @@ public static Pair<RenderingClass, List<RenderingClass>> getRenderingClassWithCh @NonNull OsmandApplication app, @NonNull String attrName) { RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); if (renderer != null) { - String key = RenderingPropertyAttr.getRenderingClassNameForAttr(attrName); + RenderingPropertyAttr attr = RenderingPropertyAttr.fromAttrName(attrName); + String key = RenderingPropertyAttr.getRenderingClassName(attrName); RenderingClass renderingClass = renderer.getRenderingClass(key); if (renderingClass != null) { List<RenderingClass> children = getChildrenRenderingClasses(app, renderingClass);