From 6941d455161d57e3f23f8905aaea4da6496f788a Mon Sep 17 00:00:00 2001 From: Nazar-Kutz Date: Fri, 9 Oct 2020 17:53:57 +0300 Subject: [PATCH 1/8] Plan Route Add Graphs initial commit --- .../res/layout/fragment_measurement_tool.xml | 34 +- .../fragment_measurement_tool_graph.xml | 111 +++++ .../fragment_measurement_tool_points_list.xml | 24 + OsmAnd/res/values/sizes.xml | 1 + OsmAnd/res/values/strings.xml | 2 + .../plus/activities/SettingsBaseActivity.java | 21 +- .../editors/PointEditorFragmentNew.java | 8 +- .../other/HorizontalSelectionAdapter.java | 98 ++++- .../MeasurementEditingContext.java | 66 +++ .../MeasurementToolFragment.java | 296 +++++++------ .../plus/measurementtool/MtGraphFragment.java | 414 ++++++++++++++++++ .../measurementtool/MtPointsFragment.java | 70 +++ .../SelectFileBottomSheet.java | 11 +- .../cards/TracksToFollowCard.java | 10 +- .../VehicleParametersBottomSheet.java | 10 +- 15 files changed, 994 insertions(+), 182 deletions(-) create mode 100644 OsmAnd/res/layout/fragment_measurement_tool_graph.xml create mode 100644 OsmAnd/res/layout/fragment_measurement_tool_points_list.xml create mode 100644 OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java create mode 100644 OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java diff --git a/OsmAnd/res/layout/fragment_measurement_tool.xml b/OsmAnd/res/layout/fragment_measurement_tool.xml index fe1ba9b1d7..1ccae4f0c3 100644 --- a/OsmAnd/res/layout/fragment_measurement_tool.xml +++ b/OsmAnd/res/layout/fragment_measurement_tool.xml @@ -130,33 +130,25 @@ tools:text="@string/add_point_after"/> - + android:layout_height="wrap_content" + android:orientation="vertical" + android:visibility="gone" > - + - + android:layout_height="@dimen/content_padding_small" /> - - - - + android:layout_height="wrap_content" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/fragment_measurement_tool_points_list.xml b/OsmAnd/res/layout/fragment_measurement_tool_points_list.xml new file mode 100644 index 0000000000..a0684707ea --- /dev/null +++ b/OsmAnd/res/layout/fragment_measurement_tool_points_list.xml @@ -0,0 +1,24 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index f4eb13a389..69f711b6fb 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -324,6 +324,7 @@ 8dp 18dp 71dp + 120dp 40dp 48dp 18dp diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index d6d400bd8f..9d8aa0e70c 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,8 @@ Thx - Hardy --> + Altitude data available only on the roads, you need to calculate a route using “Route between points” to get it. + Graph Logout successful Clear OpenStreetMap OAuth token Log in via OAuth diff --git a/OsmAnd/src/net/osmand/plus/activities/SettingsBaseActivity.java b/OsmAnd/src/net/osmand/plus/activities/SettingsBaseActivity.java index 316de777b0..1750787774 100644 --- a/OsmAnd/src/net/osmand/plus/activities/SettingsBaseActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/SettingsBaseActivity.java @@ -189,11 +189,9 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity if(propertyValue == null) { return ""; } - final String propertyValueReplaced = propertyValue.replaceAll("\\s+","_"); - Field f = R.string.class.getField("routeInfo_" + propertyValueReplaced + "_name"); - if (f != null) { - Integer in = (Integer) f.get(null); - return ctx.getString(in); + int valueId = getStringRouteInfoPropertyValueId(propertyValue); + if (valueId != -1) { + return ctx.getString(valueId); } } catch (Exception e) { System.err.println(e.getMessage()); @@ -201,6 +199,19 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity return propertyValue; } + public static int getStringRouteInfoPropertyValueId(String propertyValue) { + try { + final String propertyValueReplaced = propertyValue.replaceAll("\\s+","_"); + Field f = R.string.class.getField("routeInfo_" + propertyValueReplaced + "_name"); + if (f != null) { + return (Integer) f.get(null); + } + } catch (Exception e) { + System.err.println(e.getMessage()); + } + return -1; + } + public void registerListPreference(OsmandPreference b, PreferenceGroup screen, String[] names, T[] values) { ListPreference p = (ListPreference) screen.findPreference(b.getId()); prepareListPreference(b, names, values, p); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java index 7500a17d77..0bc215c366 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java @@ -618,12 +618,12 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment { } } HorizontalSelectionAdapter horizontalSelectionAdapter = new HorizontalSelectionAdapter(app, nightMode); - horizontalSelectionAdapter.setItems(new ArrayList<>(iconCategories.keySet())); - horizontalSelectionAdapter.setSelectedItem(selectedIconCategory); + horizontalSelectionAdapter.setTitledItems(new ArrayList<>(iconCategories.keySet())); + horizontalSelectionAdapter.setSelectedItemByTitle(selectedIconCategory); horizontalSelectionAdapter.setListener(new HorizontalSelectionAdapter.HorizontalSelectionAdapterListener() { @Override - public void onItemSelected(String item) { - selectedIconCategory = item; + public void onItemSelected(HorizontalSelectionAdapter.HorizontalSelectionItem item) { + selectedIconCategory = item.getTitle(); createIconForCategory(); updateIconSelector(selectedIcon, PointEditorFragmentNew.this.view); } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/HorizontalSelectionAdapter.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/HorizontalSelectionAdapter.java index bf7844a0f4..0eb3c3b21e 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/HorizontalSelectionAdapter.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/HorizontalSelectionAdapter.java @@ -17,6 +17,7 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; +import java.util.ArrayList; import java.util.List; import static net.osmand.util.Algorithms.capitalizeFirstLetter; @@ -24,19 +25,28 @@ import static net.osmand.util.Algorithms.capitalizeFirstLetter; public class HorizontalSelectionAdapter extends RecyclerView.Adapter { - private List items; + public static int INVALID_ID = -1; + + private List items; private OsmandApplication app; private boolean nightMode; private HorizontalSelectionAdapterListener listener; - - private String selectedItem = ""; + private HorizontalSelectionItem selectedItem = null; public HorizontalSelectionAdapter(OsmandApplication app, boolean nightMode) { this.app = app; this.nightMode = nightMode; } - public void setItems(List items) { + public void setTitledItems(List titles) { + List items = new ArrayList<>(); + for (String title : titles) { + items.add(new HorizontalSelectionItem(title)); + } + setItems(items); + } + + public void setItems(List items) { this.items = items; } @@ -44,23 +54,30 @@ public class HorizontalSelectionAdapter extends RecyclerView.Adapter getAllRouteSegments() { + class TmpRouteSegmentData { + private WptPt start; + private WptPt end; + private List routeSegments; + + public TmpRouteSegmentData(WptPt start, WptPt end, + List routeSegments) { + this.start = start; + this.end = end; + this.routeSegments = new ArrayList<>(routeSegments); + } + + boolean isAfterOf(TmpRouteSegmentData other) { + return Algorithms.objectEquals(this.start, other.end); + } + + boolean isBeforeOf(TmpRouteSegmentData other) { + return Algorithms.objectEquals(this.end, other.start); + } + + void joinAfter(TmpRouteSegmentData other) { + end = other.end; + routeSegments.addAll(other.routeSegments); + } + + void joinBefore(TmpRouteSegmentData other) { + start = other.start; + routeSegments.addAll(0, other.routeSegments); + } + } + + // prepare data for sorting + List fullList = new ArrayList<>(); + for (Map.Entry, RoadSegmentData> entry : roadSegmentData.entrySet()) { + fullList.add(new TmpRouteSegmentData( + entry.getKey().first, + entry.getKey().second, + entry.getValue().getSegments())); + } + + // sorting data by connecting together + while (fullList.size() > 1) { + TmpRouteSegmentData firstInList = fullList.get(0); + for (int i = 1; i < fullList.size(); i++) { + TmpRouteSegmentData other = fullList.get(i); + boolean isMatched = false; + + if (firstInList.isAfterOf(other)) { + isMatched = true; + firstInList.joinBefore(other); + } else if (firstInList.isBeforeOf(other)) { + isMatched = true; + firstInList.joinAfter(other); + } + + if (isMatched) { + fullList.remove(other); + break; + } + } + } + + return fullList.size() > 0 ? fullList.get(0).routeSegments : null; + } + void splitSegments(int position) { List points = new ArrayList<>(); points.addAll(before.points); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index 0cb1ae2f33..d5c21d8c07 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -5,7 +5,6 @@ import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.AsyncTask; -import android.os.Build; import android.os.Bundle; import android.util.TypedValue; import android.view.LayoutInflater; @@ -14,6 +13,7 @@ import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; @@ -26,8 +26,8 @@ import androidx.core.content.ContextCompat; import androidx.core.widget.TextViewCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; import androidx.recyclerview.widget.ItemTouchHelper; -import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.snackbar.Snackbar; @@ -62,7 +62,6 @@ import net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragme import net.osmand.plus.measurementtool.RouteBetweenPointsBottomSheetDialogFragment.RouteBetweenPointsFragmentListener; import net.osmand.plus.measurementtool.SaveGpxRouteAsyncTask.SaveGpxRouteListener; import net.osmand.plus.measurementtool.SelectedPointBottomSheetDialogFragment.SelectedPointFragmentListener; -import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter; import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter.MeasurementAdapterListener; import net.osmand.plus.measurementtool.command.AddPointCommand; import net.osmand.plus.measurementtool.command.ApplyGpxApproximationCommand; @@ -75,7 +74,6 @@ import net.osmand.plus.measurementtool.command.ReorderPointCommand; import net.osmand.plus.measurementtool.command.ReversePointsCommand; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback; import net.osmand.plus.views.layers.MapControlsLayer; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType; @@ -92,6 +90,8 @@ import java.util.Locale; import static net.osmand.IndexConstants.GPX_FILE_EXT; import static net.osmand.IndexConstants.GPX_INDEX_DIR; +import static net.osmand.plus.UiUtilities.CustomRadioButtonType.END; +import static net.osmand.plus.UiUtilities.CustomRadioButtonType.START; import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode; import static net.osmand.plus.measurementtool.MeasurementEditingContext.SnapToRoadProgressListener; import static net.osmand.plus.measurementtool.SaveAsNewTrackBottomSheetDialogFragment.SaveAsNewTrackFragmentListener; @@ -109,18 +109,14 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route public static final String TAG = MeasurementToolFragment.class.getSimpleName(); public static final String TAPS_DISABLED_KEY = "taps_disabled_key"; - private RecyclerView pointsRv; private String previousToolBarTitle = ""; private MeasurementToolBarController toolBarController; - private MeasurementToolAdapter adapter; private TextView distanceTv; private TextView pointsTv; private TextView distanceToCenterTv; private String pointsSt; - private Drawable upIcon; - private Drawable downIcon; - private View pointsListContainer; - private View upDownRow; + private View additionalInfoContainer; + private LinearLayout customRadioButton; private View mainView; private ImageView upDownBtn; private ImageView undoBtn; @@ -131,7 +127,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private boolean wasCollapseButtonVisible; private boolean progressBarVisible; - private boolean pointsListOpened; + private boolean additionalInfoExpanded; private static final int PLAN_ROUTE_MODE = 0x1; private static final int DIRECTION_MODE = 0x2; @@ -143,6 +139,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private boolean portrait; private boolean nightMode; private int cachedMapPosition; + private AdditionalInfoType currentAdditionalInfoType; private MeasurementEditingContext editingCtx = new MeasurementEditingContext(); @@ -159,8 +156,15 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route SHOW_IS_SAVED_FRAGMENT } - protected MeasurementEditingContext getEditingCtx() { - return editingCtx; + private enum AdditionalInfoType { + POINTS(MtPointsFragment.TAG), + GRAPH(MtGraphFragment.TAG); + + AdditionalInfoType(String fragmentName) { + this.fragmentName = fragmentName; + } + + String fragmentName; } private void setEditingCtx(MeasurementEditingContext editingCtx) { @@ -244,17 +248,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route measurementLayer.setEditingCtx(editingCtx); - // If rotate the screen from landscape to portrait when the list of points is displayed then - // the RecyclerViewFragment will exist without view. This is necessary to remove it. - if (!portrait) { - hidePointsListFragment(); - } - nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls(); portrait = AndroidUiHelper.isOrientationPortrait(mapActivity); - upIcon = getContentIcon(R.drawable.ic_action_arrow_up); - downIcon = getContentIcon(R.drawable.ic_action_arrow_down); pointsSt = getString(R.string.shared_string_gpx_points).toLowerCase(); View view = UiUtilities.getInflater(getContext(), nightMode) @@ -262,12 +258,29 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route mainView = view.findViewById(R.id.main_view); AndroidUtils.setBackground(mapActivity, mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark); - pointsListContainer = view.findViewById(R.id.points_list_container); - if (portrait && pointsListContainer != null) { - final int backgroundColor = ContextCompat.getColor(mapActivity, nightMode - ? R.color.activity_background_color_dark - : R.color.activity_background_color_light); - pointsListContainer.setBackgroundColor(backgroundColor); + additionalInfoContainer = mainView.findViewById(R.id.additional_info_container); + if (portrait) { + customRadioButton = mainView.findViewById(R.id.custom_radio_buttons); + + View pointListBtn = customRadioButton.findViewById(R.id.left_button_container); + TextView tvPointListBtn = customRadioButton.findViewById(R.id.left_button); + tvPointListBtn.setText(R.string.shared_string_gpx_points); + pointListBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + changeAdditionalInfoType(AdditionalInfoType.POINTS); + } + }); + + View graphBtn = customRadioButton.findViewById(R.id.right_button_container); + TextView tvGraphBtn = customRadioButton.findViewById(R.id.right_button); + tvGraphBtn.setText(R.string.shared_string_graph); + graphBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + changeAdditionalInfoType(AdditionalInfoType.GRAPH); + } + }); } if (progressBarVisible) { @@ -280,7 +293,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route mainIcon = (ImageView) mainView.findViewById(R.id.main_icon); upDownBtn = (ImageView) mainView.findViewById(R.id.up_down_button); - upDownBtn.setImageDrawable(upIcon); + updateUpDownBtn(); mainView.findViewById(R.id.cancel_move_point_button).setOnClickListener(new OnClickListener() { @Override @@ -296,14 +309,14 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } }); - upDownRow = mainView.findViewById(R.id.up_down_row); + View upDownRow = mainView.findViewById(R.id.up_down_row); upDownRow.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - if (!pointsListOpened && editingCtx.getPointsCount() > 0 && editingCtx.getSelectedPointPosition() == -1) { - showPointsList(); + if (!additionalInfoExpanded && editingCtx.getPointsCount() > 0 && editingCtx.getSelectedPointPosition() == -1) { + expandAdditionalInfoView(); } else { - hidePointsList(); + collapseAdditionalInfoView(); } } }); @@ -396,8 +409,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void onSelectPoint(int selectedPointPos) { - if (pointsListOpened) { - hidePointsList(); + if (additionalInfoExpanded) { + collapseAdditionalInfoView(); } if (selectedPointPos != -1) { openSelectedPointMenu(mapActivity); @@ -420,8 +433,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route measurementLayer.setOnEnterMovePointModeListener(new MeasurementToolLayer.OnEnterMovePointModeListener() { @Override public void onEnterMovePointMode() { - if (pointsListOpened) { - hidePointsList(); + if (additionalInfoExpanded) { + collapseAdditionalInfoView(); } switchMovePointMode(true); } @@ -474,18 +487,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route updateToolbar(); final GpxData gpxData = editingCtx.getGpxData(); - adapter = new MeasurementToolAdapter(getMapActivity(), editingCtx.getPoints(), - gpxData != null ? gpxData.getActionType() : null); - if (portrait) { - pointsRv = mainView.findViewById(R.id.measure_points_recycler_view); - } else { - pointsRv = new RecyclerView(getActivity()); - } - ItemTouchHelper touchHelper = new ItemTouchHelper(new ReorderItemTouchHelperCallback(adapter)); - touchHelper.attachToRecyclerView(pointsRv); - adapter.setAdapterListener(createMeasurementAdapterListener(touchHelper)); - pointsRv.setLayoutManager(new LinearLayoutManager(getContext())); - pointsRv.setAdapter(adapter); ImageButton snapToRoadBtn = (ImageButton) mapActivity.findViewById(R.id.snap_to_road_image_button); snapToRoadBtn.setBackgroundResource(nightMode ? R.drawable.btn_circle_night : R.drawable.btn_circle); @@ -512,6 +513,30 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route return view; } + private void changeAdditionalInfoType(@NonNull AdditionalInfoType type) { + if (!additionalInfoExpanded || !isCurrentAdditionalInfoType(type)) { + currentAdditionalInfoType = type; + additionalInfoExpanded = true; + updateUpDownBtn(); + OsmandApplication app = getMyApplication(); + if (AdditionalInfoType.POINTS.equals(type)) { + UiUtilities.updateCustomRadioButtons(app, customRadioButton, nightMode, START); + } else if (AdditionalInfoType.GRAPH.equals(type)) { + UiUtilities.updateCustomRadioButtons(app, customRadioButton, nightMode, END); + } else { + return; + } + setAdditionalInfoFragment(type.fragmentName); + } + } + + private void updateAdditionalInfoView() { + Fragment fragment = getActiveAdditionalInfoFragment(); + if (fragment instanceof OnUpdateAdditionalInfoListener) { + ((OnUpdateAdditionalInfoListener) fragment).onUpdateAdditionalInfo(); + } + } + public boolean isInEditMode() { return !isPlanRouteMode() && !editingCtx.isNewData() && !isDirectionMode() && !isFollowTrackMode(); } @@ -520,12 +545,16 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route this.fileName = fileName; } + public MeasurementEditingContext getEditingCtx() { + return editingCtx; + } + private void updateUndoRedoCommonStuff() { - hidePointsListIfNoPoints(); + collapseAdditionalInfoIfNoPointsEnough(); if (editingCtx.getPointsCount() > 0) { enable(upDownBtn); } - adapter.notifyDataSetChanged(); + updateAdditionalInfoView(); updateDistancePointsText(); updateSnapToRoadControls(); } @@ -585,9 +614,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route super.onDestroyView(); cancelModes(); exitMeasurementMode(); - adapter.setAdapterListener(null); - if (pointsListOpened) { - hidePointsList(); + if (additionalInfoExpanded) { + collapseAdditionalInfoView(); } MeasurementToolLayer layer = getMeasurementLayer(); if (layer != null) { @@ -834,8 +862,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route MeasurementToolLayer measurementLayer = getMeasurementLayer(); editingCtx.getCommandManager().execute(new ClearPointsCommand(measurementLayer, ALL)); editingCtx.cancelSnapToRoad(); - if (pointsListOpened) { - hidePointsList(); + if (additionalInfoExpanded) { + collapseAdditionalInfoView(); } updateUndoRedoButton(false, redoBtn); disable(upDownBtn); @@ -850,8 +878,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (points.size() > 1) { MeasurementToolLayer measurementLayer = getMeasurementLayer(); editingCtx.getCommandManager().execute(new ReversePointsCommand(measurementLayer)); - if (pointsListOpened) { - hidePointsList(); + if (additionalInfoExpanded) { + collapseAdditionalInfoView(); } updateUndoRedoButton(false, redoBtn); updateUndoRedoButton(true, undoBtn); @@ -919,8 +947,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private void trimRoute(ClearCommandMode before) { MeasurementToolLayer measurementLayer = getMeasurementLayer(); editingCtx.getCommandManager().execute(new ClearPointsCommand(measurementLayer, before)); - if (pointsListOpened) { - hidePointsList(); + if (additionalInfoExpanded) { + collapseAdditionalInfoView(); } editingCtx.setSelectedPointPosition(-1); editingCtx.splitSegments(editingCtx.getBeforePoints().size() + editingCtx.getAfterPoints().size()); @@ -1077,11 +1105,11 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private void removePoint(MeasurementToolLayer measurementLayer, int position) { if (measurementLayer != null) { editingCtx.getCommandManager().execute(new RemovePointCommand(measurementLayer, position)); - adapter.notifyDataSetChanged(); + updateAdditionalInfoView(); updateUndoRedoButton(true, undoBtn); updateUndoRedoButton(false, redoBtn); updateDistancePointsText(); - hidePointsListIfNoPoints(); + collapseAdditionalInfoIfNoPointsEnough(); } } @@ -1104,7 +1132,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - private MeasurementAdapterListener createMeasurementAdapterListener(final ItemTouchHelper touchHelper) { + MeasurementAdapterListener createMeasurementAdapterListener(final ItemTouchHelper touchHelper) { return new MeasurementAdapterListener() { final MapActivity mapActivity = getMapActivity(); @@ -1120,8 +1148,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void onItemClick(int position) { if (mapActivity != null && measurementLayer != null) { - if (pointsListOpened) { - hidePointsList(); + if (additionalInfoExpanded) { + collapseAdditionalInfoView(); } if (portrait) { setMapPosition(OsmandSettings.MIDDLE_TOP_CONSTANT); @@ -1143,7 +1171,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route toPosition = holder.getAdapterPosition(); if (toPosition >= 0 && fromPosition >= 0 && toPosition != fromPosition) { editingCtx.getCommandManager().execute(new ReorderPointCommand(measurementLayer, fromPosition, toPosition)); - adapter.notifyDataSetChanged(); + updateAdditionalInfoView(); updateUndoRedoButton(false, redoBtn); updateDistancePointsText(); mapActivity.refreshMap(); @@ -1209,7 +1237,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (!isUndoMode()) { editingCtx.addPoints(points); } - adapter.notifyDataSetChanged(); + updateAdditionalInfoView(); updateDistancePointsText(); } } @@ -1221,7 +1249,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (!isUndoMode()) { editingCtx.addPoints(); } - adapter.notifyDataSetChanged(); + updateAdditionalInfoView(); updateDistancePointsText(); } } @@ -1417,85 +1445,91 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route updateUndoRedoButton(true, undoBtn); updateUndoRedoButton(false, redoBtn); updateDistancePointsText(); - adapter.notifyDataSetChanged(); + updateAdditionalInfoView(); } - private void showPointsList() { - pointsListOpened = true; - upDownBtn.setImageDrawable(downIcon); - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - if (portrait && pointsListContainer != null) { - pointsListContainer.setVisibility(View.VISIBLE); - } else { - showPointsListFragment(); + private void expandAdditionalInfoView() { + if (portrait) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + additionalInfoContainer.setVisibility(View.VISIBLE); + AdditionalInfoType typeToShow = currentAdditionalInfoType == null + ? AdditionalInfoType.POINTS : currentAdditionalInfoType; + changeAdditionalInfoType(typeToShow); + setMapPosition(portrait + ? OsmandSettings.MIDDLE_TOP_CONSTANT + : OsmandSettings.LANDSCAPE_MIDDLE_RIGHT_CONSTANT); } - setMapPosition(portrait - ? OsmandSettings.MIDDLE_TOP_CONSTANT - : OsmandSettings.LANDSCAPE_MIDDLE_RIGHT_CONSTANT); } } - private void hidePointsList() { - pointsListOpened = false; - upDownBtn.setImageDrawable(upIcon); - if (portrait && pointsListContainer != null) { - pointsListContainer.setVisibility(View.GONE); - } else { - hidePointsListFragment(); + private void collapseAdditionalInfoView() { + if (portrait) { + additionalInfoExpanded = false; + updateUpDownBtn(); + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + Fragment activeFragment = getActiveAdditionalInfoFragment(); + if (activeFragment != null) { + FragmentManager manager = getChildFragmentManager(); + manager.beginTransaction().remove(activeFragment).commitAllowingStateLoss(); + } + additionalInfoContainer.setVisibility(View.GONE); + setDefaultMapPosition(); + } } - setDefaultMapPosition(); } - private void hidePointsListIfNoPoints() { + private void setAdditionalInfoFragment(String fragmentName) { + Context ctx = getContext(); + if (ctx == null) return; + + Fragment fragment = Fragment.instantiate(ctx, fragmentName); + FragmentManager fm = getChildFragmentManager(); + FragmentTransaction fragmentTransaction = fm.beginTransaction(); + fragmentTransaction.replace(R.id.fragmentContainer, fragment, fragmentName); + fragmentTransaction.commit(); + fm.executePendingTransactions(); + } + + private void collapseAdditionalInfoIfNoPointsEnough() { MeasurementToolLayer measurementLayer = getMeasurementLayer(); if (measurementLayer != null) { - if (editingCtx.getPointsCount() < 1) { + int pointsCount = editingCtx.getPointsCount(); + if (isCurrentAdditionalInfoType(AdditionalInfoType.GRAPH) && pointsCount < 2) { + collapseAdditionalInfoView(); + } else if (pointsCount < 1) { disable(upDownBtn); - if (pointsListOpened) { - hidePointsList(); + if (additionalInfoExpanded) { + collapseAdditionalInfoView(); } } } } - private void showPointsListFragment() { + private Fragment getActiveAdditionalInfoFragment() { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { - boolean transparentStatusBar = Build.VERSION.SDK_INT >= 21; - int statusBarHeight = transparentStatusBar ? 0 : AndroidUtils.getStatusBarHeight(mapActivity); - int screenHeight = AndroidUtils.getScreenHeight(mapActivity) - statusBarHeight; - RecyclerViewFragment fragment = new RecyclerViewFragment(); - fragment.setRecyclerView(pointsRv); - fragment.setWidth(upDownRow.getWidth()); - fragment.setHeight(screenHeight - upDownRow.getHeight()); - fragment.setTransparentStatusBar(transparentStatusBar); - mapActivity.getSupportFragmentManager().beginTransaction() - .add(R.id.fragmentContainer, fragment, RecyclerViewFragment.TAG) - .commitAllowingStateLoss(); - } - } - - private void hidePointsListFragment() { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - try { - FragmentManager manager = mapActivity.getSupportFragmentManager(); - Fragment fragment = manager.findFragmentByTag(RecyclerViewFragment.TAG); - if (fragment != null) { - manager.beginTransaction().remove(fragment).commitAllowingStateLoss(); + for (AdditionalInfoType type : AdditionalInfoType.values()) { + try { + FragmentManager fm = getChildFragmentManager(); + Fragment fragment = fm.findFragmentByTag(type.fragmentName); + if (fragment != null) { + return fragment; + } + } catch (Exception e) { + // ignore } - } catch (Exception e) { - // ignore } } + return null; } private void setDefaultMapPosition() { setMapPosition(OsmandSettings.CENTER_CONSTANT); } - private void setMapPosition(int position) { + public void setMapPosition(int position) { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { mapActivity.getMapView().setMapPosition(position); @@ -1515,6 +1549,16 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } + private void updateUpDownBtn() { + Drawable icon = getContentIcon(additionalInfoExpanded + ? R.drawable.ic_action_arrow_down : R.drawable.ic_action_arrow_up); + upDownBtn.setImageDrawable(icon); + } + + private boolean isCurrentAdditionalInfoType(@NonNull AdditionalInfoType type) { + return type.equals(currentAdditionalInfoType); + } + private String getSuggestedFileName() { GpxData gpxData = editingCtx.getGpxData(); String displayedName; @@ -1790,8 +1834,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route final MapActivity mapActivity = getMapActivity(); MeasurementToolLayer measurementLayer = getMeasurementLayer(); if (mapActivity != null && measurementLayer != null) { - if (pointsListOpened && hidePointsListFirst) { - hidePointsList(); + if (additionalInfoExpanded && hidePointsListFirst) { + collapseAdditionalInfoView(); return; } if (!editingCtx.hasChanges()) { @@ -1811,8 +1855,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (clearContext) { editingCtx.clearSegments(); } - if (pointsListOpened) { - hidePointsList(); + if (additionalInfoExpanded) { + collapseAdditionalInfoView(); } resetAppMode(); hideSnapToRoadIcon(); @@ -1949,8 +1993,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (!editingCtx.getCommandManager().update(command)) { editingCtx.getCommandManager().execute(command); } - if (pointsListOpened) { - hidePointsList(); + if (additionalInfoExpanded) { + collapseAdditionalInfoView(); } updateSnapToRoadControls(); } @@ -2024,4 +2068,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route public boolean isNightModeForMapControls() { return nightMode; } + + public interface OnUpdateAdditionalInfoListener { + void onUpdateAdditionalInfo(); + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java new file mode 100644 index 0000000000..7b35b6dce1 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java @@ -0,0 +1,414 @@ +package net.osmand.plus.measurementtool; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.activities.SettingsBaseActivity; +import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter; +import net.osmand.plus.render.MapRenderRepositories; +import net.osmand.render.RenderingRuleSearchRequest; +import net.osmand.render.RenderingRulesStorage; +import net.osmand.router.RouteSegmentResult; +import net.osmand.router.RouteStatisticsHelper; +import net.osmand.util.Algorithms; + +import static net.osmand.router.RouteStatisticsHelper.RouteStatistics; +import static net.osmand.GPXUtilities.GPXTrackAnalysis; +import static net.osmand.GPXUtilities.GPXFile; +import static net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MtGraphFragment extends Fragment + implements MeasurementToolFragment.OnUpdateAdditionalInfoListener { + + public static final String TAG = MtGraphFragment.class.getName(); + + private static String GRAPH_DATA_GPX_FILE_NAME = "graph_data_tmp"; + + private View commonGraphContainer; + private View customGraphContainer; + private View messageContainer; + private LineChart commonGraphChart; + private HorizontalBarChart customGraphChart; + private RecyclerView rvMenu; + + private boolean nightMode; + private MeasurementEditingContext editingCtx; + private GraphType currentGraphType; + private Map graphData = new HashMap<>(); + + private enum GraphType { + OVERVIEW(R.string.shared_string_overview, false, false), + ALTITUDE(R.string.altitude, false, true), +// SLOPE(R.string.shared_string_slope, false, true), + SPEED(R.string.map_widget_speed, false, false), + + SURFACE(R.string.routeInfo_surface_name, true, false), + ROAD_TYPE(R.string.routeInfo_roadClass_name, true, false), + STEEPNESS(R.string.routeInfo_steepness_name, true, false), + SMOOTHNESS(R.string.routeInfo_smoothness_name, true, false); + + GraphType(int titleId, boolean isCustomType, boolean canBeCalculated) { + this.titleId = titleId; + this.isCustomType = isCustomType; + this.canBeCalculated = canBeCalculated; + } + + final int titleId; + final boolean isCustomType; + final boolean canBeCalculated; + + private static List commonTypes; + private static List customTypes; + + static List getCommonTypes() { + if (commonTypes == null) { + prepareLists(); + } + return commonTypes; + } + + static List getCustomTypes() { + if (customTypes == null) { + prepareLists(); + } + return customTypes; + } + + private static void prepareLists() { + commonTypes = new ArrayList<>(); + customTypes = new ArrayList<>(); + for (GraphType type : values()) { + if (type.isCustomType) { + customTypes.add(type); + } else { + commonTypes.add(type); + } + } + } + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + + final MapActivity mapActivity = (MapActivity) getActivity(); + final MeasurementToolFragment mtf = (MeasurementToolFragment) getParentFragment(); + if (mapActivity == null || mtf == null) return null; + + editingCtx = mtf.getEditingCtx(); + OsmandApplication app = mapActivity.getMyApplication(); + + nightMode = app.getDaynightHelper().isNightModeForMapControls(); + View view = UiUtilities.getInflater(app, nightMode).inflate( + R.layout.fragment_measurement_tool_graph, container, false); + commonGraphContainer = view.findViewById(R.id.common_graphs_container); + customGraphContainer = view.findViewById(R.id.custom_graphs_container); + messageContainer = view.findViewById(R.id.message_container); + commonGraphChart = (LineChart) view.findViewById(R.id.line_chart); + customGraphChart = (HorizontalBarChart) view.findViewById(R.id.horizontal_chart); + updateGraphData(); + + rvMenu = view.findViewById(R.id.graph_types_recycler_view); + rvMenu.setLayoutManager( + new LinearLayoutManager(mapActivity, RecyclerView.HORIZONTAL, false)); + + prepareGraphTypesSelectionMenu(); + setupVisibleGraphType(GraphType.OVERVIEW); + + return view; + } + + private void prepareGraphTypesSelectionMenu() { + rvMenu.removeAllViews(); + OsmandApplication app = getMyApplication(); + int activeColorId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; + final HorizontalSelectionAdapter adapter = new HorizontalSelectionAdapter(app, nightMode); + final ArrayList items = new ArrayList<>(); + for (GraphType type : GraphType.values()) { + String title = getString(type.titleId); + HorizontalSelectionItem item = new HorizontalSelectionItem(title, type); + if (type.isCustomType) { + item.setTitleColorId(activeColorId); + } + if (isDataAvailableFor(type) || type.canBeCalculated) { + items.add(item); + } + } + adapter.setItems(items); + String selectedItemKey = currentGraphType != null ? + getString(currentGraphType.titleId) : items.get(0).getTitle(); + adapter.setSelectedItemByTitle(selectedItemKey); + adapter.setListener(new HorizontalSelectionAdapter.HorizontalSelectionAdapterListener() { + @Override + public void onItemSelected(HorizontalSelectionAdapter.HorizontalSelectionItem item) { + adapter.setItems(items); + adapter.setSelectedItem(item); + GraphType chosenGraphType = (GraphType) item.getObject(); + if (chosenGraphType != null && !chosenGraphType.equals(currentGraphType)) { + setupVisibleGraphType(chosenGraphType); + } + } + }); + rvMenu.setAdapter(adapter); + adapter.notifyDataSetChanged(); + } + + @Override + public void onUpdateAdditionalInfo() { + updateGraphData(); + prepareGraphTypesSelectionMenu(); + setupVisibleGraphType(currentGraphType); + } + + private void setupVisibleGraphType(GraphType preferredType) { + currentGraphType = isDataAvailableFor(preferredType) ? + preferredType : getFirstAvailableGraphType(); + updateDataView(); + } + + private GraphType getFirstAvailableGraphType() { + for (GraphType type : GraphType.values()) { + if (isDataAvailableFor(type) || type.canBeCalculated) { + return type; + } + } + return GraphType.OVERVIEW; + } + + private void updateDataView() { + if (isDataAvailableFor(currentGraphType)) { + showGraph(); + } else if (currentGraphType.canBeCalculated) { + showMessage(); + } + } + + private void showGraph() { + if (currentGraphType.isCustomType) { + customGraphChart.clear(); + commonGraphContainer.setVisibility(View.GONE); + customGraphContainer.setVisibility(View.VISIBLE); + messageContainer.setVisibility(View.GONE); + prepareCustomGraphView(); + } else { + commonGraphChart.clear(); + commonGraphContainer.setVisibility(View.VISIBLE); + customGraphContainer.setVisibility(View.GONE); + messageContainer.setVisibility(View.GONE); + prepareCommonGraphView(); + } + } + + private void showMessage() { + commonGraphContainer.setVisibility(View.GONE); + customGraphContainer.setVisibility(View.GONE); + messageContainer.setVisibility(View.VISIBLE); + TextView tvMessage = messageContainer.findViewById(R.id.message_text); + ImageView icon = messageContainer.findViewById(R.id.message_icon); + if (GraphType.ALTITUDE.equals(currentGraphType)) { + tvMessage.setText(R.string.message_need_calculate_route_for_show_graph); + icon.setImageResource(R.drawable.ic_action_altitude_average); + } + } + + private void prepareCommonGraphView() { + LineData data = (LineData) graphData.get(currentGraphType); + if (data == null) return; + + GpxUiHelper.setupGPXChart(commonGraphChart, 4, 24f, 16f, !nightMode, true); + commonGraphChart.setData(data); + } + + private void prepareCustomGraphView() { + BarData data = (BarData) graphData.get(currentGraphType); + OsmandApplication app = getMapActivity().getMyApplication(); + if (data == null || app == null) return; + + GpxUiHelper.setupHorizontalGPXChart(app, customGraphChart, 5, 9, 24, true, nightMode); + customGraphChart.setExtraRightOffset(16); + customGraphChart.setExtraLeftOffset(16); + customGraphChart.setData(data); + } + + private void updateGraphData() { + OsmandApplication app = getMyApplication(); + GPXTrackAnalysis analysis = createGpxTrackAnalysis(); + + // update common graph data + for (GraphType type : GraphType.getCommonTypes()) { + List dataSets = getDataSets(type, commonGraphChart, analysis); + if (!Algorithms.isEmpty(dataSets)) { + graphData.put(type, new LineData(dataSets)); + } else { + graphData.put(type, null); + } + } + + // update custom graph data + List routeSegments = editingCtx.getAllRouteSegments(); + List routeStatistics = calculateRouteStatistics(routeSegments); + for (GraphType type : GraphType.getCustomTypes()) { + RouteStatistics statistic = getStatisticForGraphType(routeStatistics, type); + if (statistic != null && !Algorithms.isEmpty(statistic.elements)) { + BarData data = GpxUiHelper.buildStatisticChart( + app, customGraphChart, statistic, analysis, true, nightMode); + graphData.put(type, data); + } else { + graphData.put(type, null); + } + } + } + + private RouteStatistics getStatisticForGraphType(List routeStatistics, GraphType graphType) { + if (routeStatistics == null) return null; + for (RouteStatistics statistic : routeStatistics) { + int graphTypeId = graphType.titleId; + int statisticId = SettingsBaseActivity.getStringRouteInfoPropertyValueId(statistic.name); + if (graphTypeId == statisticId) { + return statistic; + } + } + return null; + } + + private List getDataSets(GraphType graphType, LineChart chart, GPXTrackAnalysis analysis) { + List dataSets = new ArrayList<>(); + if (chart != null && analysis != null) { + OsmandApplication app = getMyApplication(); + switch (graphType) { + case OVERVIEW: { + GpxUiHelper.OrderedLineDataSet speedDataSet = null; + GpxUiHelper.OrderedLineDataSet elevationDataSet = null; +// GpxUiHelper.OrderedLineDataSet slopeDataSet = null; + if (analysis.hasSpeedData) { + speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, + analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, true, true, false); + } + if (analysis.hasElevationData) { + elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, + analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true, false); +// slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, +// analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, null, true, true, false); + } + List dataList = new ArrayList<>(); + if (speedDataSet != null) { + dataList.add(speedDataSet); + } + if (elevationDataSet != null) { + dataList.add(elevationDataSet); + } +// if (slopeDataSet != null) { +// dataList.add(slopeDataSet); +// } + if (dataList.size() > 0) { + Collections.sort(dataList, new Comparator() { + @Override + public int compare(GpxUiHelper.OrderedLineDataSet o1, GpxUiHelper.OrderedLineDataSet o2) { + return Float.compare(o1.getPriority(), o2.getPriority()); + } + }); + } + dataSets.addAll(dataList); + break; + } + case ALTITUDE: { + if (analysis.hasElevationData) { + GpxUiHelper.OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, + analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true, false);//calcWithoutGaps); + if (elevationDataSet != null) { + dataSets.add(elevationDataSet); + } + } + break; + } +// case SLOPE: +// if (analysis.hasElevationData) { +// GpxUiHelper.OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, +// analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, null, true, true, false); +// if (slopeDataSet != null) { +// dataSets.add(slopeDataSet); +// } +// } +// break; + case SPEED: { + if (analysis.hasSpeedData) { + GpxUiHelper.OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, + analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true, false);//calcWithoutGaps); + if (speedDataSet != null) { + dataSets.add(speedDataSet); + } + } + break; + } + } + } + return dataSets; + } + + private GPXTrackAnalysis createGpxTrackAnalysis() { + GPXFile gpx; + if (editingCtx.getGpxData() != null) { + gpx = editingCtx.getGpxData().getGpxFile(); + } else { + gpx = editingCtx.exportRouteAsGpx(GRAPH_DATA_GPX_FILE_NAME); + } + return gpx != null ? gpx.getAnalysis(0) : null; + } + + private List calculateRouteStatistics(List route) { + OsmandApplication app = getMyApplication(); + if (route == null || app == null) return null; + + RenderingRulesStorage currentRenderer = app.getRendererRegistry().getCurrentSelectedRenderer(); + RenderingRulesStorage defaultRender = app.getRendererRegistry().defaultRender(); + MapRenderRepositories maps = app.getResourceManager().getRenderer(); + RenderingRuleSearchRequest currentSearchRequest = + maps.getSearchRequestWithAppliedCustomRules(currentRenderer, nightMode); + RenderingRuleSearchRequest defaultSearchRequest = + maps.getSearchRequestWithAppliedCustomRules(defaultRender, nightMode); + return RouteStatisticsHelper.calculateRouteStatistic(route, currentRenderer, + defaultRender, currentSearchRequest, defaultSearchRequest); + } + + private boolean isDataAvailableFor(GraphType graphType) { + return graphData != null && graphData.get(graphType) != null; + } + + private OsmandApplication getMyApplication() { + return getMapActivity().getMyApplication(); + } + + private MapActivity getMapActivity() { + return (MapActivity) getActivity(); + } +} diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java new file mode 100644 index 0000000000..9ee46b3648 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java @@ -0,0 +1,70 @@ +package net.osmand.plus.measurementtool; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter; +import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback; + +public class MtPointsFragment extends Fragment + implements MeasurementToolFragment.OnUpdateAdditionalInfoListener { + + public static final String TAG = MtPointsFragment.class.getName(); + + private boolean nightMode; + private MeasurementToolAdapter adapter; + private MeasurementEditingContext editingCtx; + private RecyclerView pointsRv; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + + final MapActivity mapActivity = (MapActivity) getActivity(); + final MeasurementToolFragment mtf = (MeasurementToolFragment) getParentFragment(); + if (mapActivity == null || mtf == null) { + return null; + } + nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls(); + View view = UiUtilities.getInflater(getContext(), nightMode) + .inflate(R.layout.fragment_measurement_tool_points_list, container, false); + + editingCtx = mtf.getEditingCtx(); + final GpxData gpxData = editingCtx.getGpxData(); + adapter = new MeasurementToolAdapter(mapActivity, editingCtx.getPoints(), + gpxData != null ? gpxData.getActionType() : null); + pointsRv = view.findViewById(R.id.measure_points_recycler_view); + ItemTouchHelper touchHelper = new ItemTouchHelper(new ReorderItemTouchHelperCallback(adapter)); + touchHelper.attachToRecyclerView(pointsRv); + adapter.setAdapterListener(mtf.createMeasurementAdapterListener(touchHelper)); + pointsRv.setLayoutManager(new LinearLayoutManager(getContext())); + pointsRv.setAdapter(adapter); + + return view; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + adapter.setAdapterListener(null); + } + + @Override + public void onUpdateAdditionalInfo() { + adapter.notifyDataSetChanged(); + } +} diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java b/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java index c155ec493c..b89cbda954 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java @@ -28,6 +28,7 @@ import net.osmand.plus.helpers.GpxUiHelper.GPXInfo; import net.osmand.plus.helpers.enums.TracksSortByMode; import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter; import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionAdapterListener; +import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem; import java.io.File; import java.util.ArrayList; @@ -128,7 +129,7 @@ public class SelectFileBottomSheet extends BottomSheetBehaviourDialogFragment { sortButton.setImageResource(mode.getIconId()); updateDescription(descriptionView); sortFolderList(); - folderAdapter.setItems(getFolderNames()); + folderAdapter.setTitledItems(getFolderNames()); folderAdapter.notifyDataSetChanged(); sortFileList(); adapter.notifyDataSetChanged(); @@ -191,13 +192,13 @@ public class SelectFileBottomSheet extends BottomSheetBehaviourDialogFragment { folders = new ArrayList<>(); collectDirs(gpxDir, folders); sortFolderList(); - folderAdapter.setItems(getFolderNames()); - folderAdapter.setSelectedItem(selectedFolder); + folderAdapter.setTitledItems(getFolderNames()); + folderAdapter.setSelectedItemByTitle(selectedFolder); foldersRecyclerView.setAdapter(folderAdapter); folderAdapter.setListener(new HorizontalSelectionAdapterListener() { @Override - public void onItemSelected(String item) { - selectedFolder = item; + public void onItemSelected(HorizontalSelectionItem item) { + selectedFolder = item.getTitle(); updateFileList(folderAdapter); } }); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/TracksToFollowCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/TracksToFollowCard.java index 94770e0135..c21b508116 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/TracksToFollowCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/TracksToFollowCard.java @@ -85,13 +85,13 @@ public class TracksToFollowCard extends BaseCard { private void setupCategoriesRow() { final HorizontalSelectionAdapter selectionAdapter = new HorizontalSelectionAdapter(app, nightMode); - selectionAdapter.setItems(new ArrayList<>(gpxInfoCategories.keySet())); - selectionAdapter.setSelectedItem(selectedCategory); + selectionAdapter.setTitledItems(new ArrayList<>(gpxInfoCategories.keySet())); + selectionAdapter.setSelectedItemByTitle(selectedCategory); selectionAdapter.setListener(new HorizontalSelectionAdapter.HorizontalSelectionAdapterListener() { @Override - public void onItemSelected(String item) { - selectedCategory = item; - List items = gpxInfoCategories.get(item); + public void onItemSelected(HorizontalSelectionAdapter.HorizontalSelectionItem item) { + selectedCategory = item.getTitle(); + List items = gpxInfoCategories.get(selectedCategory); tracksAdapter.setShowFolderName(showFoldersName()); tracksAdapter.setGpxInfoList(items != null ? items : new ArrayList()); tracksAdapter.notifyDataSetChanged(); diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/VehicleParametersBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/VehicleParametersBottomSheet.java index 5ac7aea8e8..9d3275e8fd 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/VehicleParametersBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/VehicleParametersBottomSheet.java @@ -121,7 +121,7 @@ public class VehicleParametersBottomSheet extends BasePreferenceBottomSheet { currentValue = 0.0f; } selectedItem = preference.getEntryFromValue(String.valueOf(currentValue)); - adapter.setSelectedItem(selectedItem); + adapter.setSelectedItemByTitle(selectedItem); int itemPosition = adapter.getItemPosition(selectedItem); if (itemPosition >= 0) { recyclerView.smoothScrollToPosition(itemPosition); @@ -129,11 +129,11 @@ public class VehicleParametersBottomSheet extends BasePreferenceBottomSheet { } }); - adapter.setItems(Arrays.asList(preference.getEntries())); + adapter.setTitledItems(Arrays.asList(preference.getEntries())); adapter.setListener(new HorizontalSelectionAdapter.HorizontalSelectionAdapterListener() { @Override - public void onItemSelected(String item) { - selectedItem = item; + public void onItemSelected(HorizontalSelectionAdapter.HorizontalSelectionItem item) { + selectedItem = item.getTitle(); currentValue = preference.getValueFromEntries(selectedItem); String currentValueStr = currentValue == 0.0f ? "" : df.format(currentValue + 0.01f); @@ -145,7 +145,7 @@ public class VehicleParametersBottomSheet extends BasePreferenceBottomSheet { } }); recyclerView.setAdapter(adapter); - adapter.setSelectedItem(selectedItem); + adapter.setSelectedItemByTitle(selectedItem); return new BaseBottomSheetItem.Builder() .setCustomView(mainView) .create(); From 3c2bda87ce9ef0ee60a4a24dadb5aec5b9830d24 Mon Sep 17 00:00:00 2001 From: Nazar-Kutz Date: Mon, 12 Oct 2020 10:33:46 +0300 Subject: [PATCH 2/8] small refactoring --- .../measurementtool/MeasurementToolFragment.java | 15 ++++++++++----- .../plus/measurementtool/MtGraphFragment.java | 2 -- .../plus/measurementtool/MtPointsFragment.java | 2 -- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index d5c21d8c07..a927ca884e 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -157,14 +157,18 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } private enum AdditionalInfoType { - POINTS(MtPointsFragment.TAG), - GRAPH(MtGraphFragment.TAG); + POINTS(MtPointsFragment.class.getName()), + GRAPH(MtGraphFragment.class.getName()); AdditionalInfoType(String fragmentName) { this.fragmentName = fragmentName; } - String fragmentName; + final String fragmentName; + + public String getFragmentName() { + return fragmentName; + } } private void setEditingCtx(MeasurementEditingContext editingCtx) { @@ -237,6 +241,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route public void hideProgressBar() { ((ProgressBar) mainView.findViewById(R.id.snap_to_road_progress_bar)).setVisibility(View.GONE); progressBarVisible = false; + updateAdditionalInfoView(); } @Override @@ -526,7 +531,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } else { return; } - setAdditionalInfoFragment(type.fragmentName); + setAdditionalInfoFragment(type.getFragmentName()); } } @@ -1513,7 +1518,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route for (AdditionalInfoType type : AdditionalInfoType.values()) { try { FragmentManager fm = getChildFragmentManager(); - Fragment fragment = fm.findFragmentByTag(type.fragmentName); + Fragment fragment = fm.findFragmentByTag(type.getFragmentName()); if (fragment != null) { return fragment; } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java index 7b35b6dce1..72cc761c84 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java @@ -48,8 +48,6 @@ import java.util.Map; public class MtGraphFragment extends Fragment implements MeasurementToolFragment.OnUpdateAdditionalInfoListener { - public static final String TAG = MtGraphFragment.class.getName(); - private static String GRAPH_DATA_GPX_FILE_NAME = "graph_data_tmp"; private View commonGraphContainer; diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java index 9ee46b3648..086ab6c322 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java @@ -21,8 +21,6 @@ import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback; public class MtPointsFragment extends Fragment implements MeasurementToolFragment.OnUpdateAdditionalInfoListener { - public static final String TAG = MtPointsFragment.class.getName(); - private boolean nightMode; private MeasurementToolAdapter adapter; private MeasurementEditingContext editingCtx; From a6d117f5a1ecc18dee7e664474f62a456c777849 Mon Sep 17 00:00:00 2001 From: Nazar-Kutz Date: Mon, 12 Oct 2020 17:18:01 +0300 Subject: [PATCH 3/8] refactor GraphType --- OsmAnd/res/values/strings.xml | 2 +- .../plus/activities/SettingsBaseActivity.java | 21 +- .../MeasurementEditingContext.java | 68 ++--- .../plus/measurementtool/MtGraphFragment.java | 254 ++++++++---------- 4 files changed, 148 insertions(+), 197 deletions(-) diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 9d8aa0e70c..da8878c111 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,7 +11,7 @@ Thx - Hardy --> - Altitude data available only on the roads, you need to calculate a route using “Route between points” to get it. + %1$s data available only on the roads, you need to calculate a route using “Route between points” to get it. Graph Logout successful Clear OpenStreetMap OAuth token diff --git a/OsmAnd/src/net/osmand/plus/activities/SettingsBaseActivity.java b/OsmAnd/src/net/osmand/plus/activities/SettingsBaseActivity.java index 1750787774..316de777b0 100644 --- a/OsmAnd/src/net/osmand/plus/activities/SettingsBaseActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/SettingsBaseActivity.java @@ -189,9 +189,11 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity if(propertyValue == null) { return ""; } - int valueId = getStringRouteInfoPropertyValueId(propertyValue); - if (valueId != -1) { - return ctx.getString(valueId); + final String propertyValueReplaced = propertyValue.replaceAll("\\s+","_"); + Field f = R.string.class.getField("routeInfo_" + propertyValueReplaced + "_name"); + if (f != null) { + Integer in = (Integer) f.get(null); + return ctx.getString(in); } } catch (Exception e) { System.err.println(e.getMessage()); @@ -199,19 +201,6 @@ public abstract class SettingsBaseActivity extends ActionBarPreferenceActivity return propertyValue; } - public static int getStringRouteInfoPropertyValueId(String propertyValue) { - try { - final String propertyValueReplaced = propertyValue.replaceAll("\\s+","_"); - Field f = R.string.class.getField("routeInfo_" + propertyValueReplaced + "_name"); - if (f != null) { - return (Integer) f.get(null); - } - } catch (Exception e) { - System.err.println(e.getMessage()); - } - return -1; - } - public void registerListPreference(OsmandPreference b, PreferenceGroup screen, String[] names, T[] values) { ListPreference p = (ListPreference) screen.findPreference(b.getId()); prepareListPreference(b, names, values, p); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java index f87c324c92..66ced9ebd1 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementEditingContext.java @@ -314,37 +314,6 @@ public class MeasurementEditingContext { } public List getAllRouteSegments() { - class TmpRouteSegmentData { - private WptPt start; - private WptPt end; - private List routeSegments; - - public TmpRouteSegmentData(WptPt start, WptPt end, - List routeSegments) { - this.start = start; - this.end = end; - this.routeSegments = new ArrayList<>(routeSegments); - } - - boolean isAfterOf(TmpRouteSegmentData other) { - return Algorithms.objectEquals(this.start, other.end); - } - - boolean isBeforeOf(TmpRouteSegmentData other) { - return Algorithms.objectEquals(this.end, other.start); - } - - void joinAfter(TmpRouteSegmentData other) { - end = other.end; - routeSegments.addAll(other.routeSegments); - } - - void joinBefore(TmpRouteSegmentData other) { - start = other.start; - routeSegments.addAll(0, other.routeSegments); - } - } - // prepare data for sorting List fullList = new ArrayList<>(); for (Map.Entry, RoadSegmentData> entry : roadSegmentData.entrySet()) { @@ -353,7 +322,6 @@ public class MeasurementEditingContext { entry.getKey().second, entry.getValue().getSegments())); } - // sorting data by connecting together while (fullList.size() > 1) { TmpRouteSegmentData firstInList = fullList.get(0); @@ -375,8 +343,42 @@ public class MeasurementEditingContext { } } } + return fullList.size() > 0 ? fullList.get(0).getRouteSegments() : null; + } - return fullList.size() > 0 ? fullList.get(0).routeSegments : null; + private static class TmpRouteSegmentData { + private WptPt start; + private WptPt end; + private List routeSegments; + + public TmpRouteSegmentData(WptPt start, WptPt end, + List routeSegments) { + this.start = start; + this.end = end; + this.routeSegments = new ArrayList<>(routeSegments); + } + + boolean isAfterOf(TmpRouteSegmentData other) { + return Algorithms.objectEquals(this.start, other.end); + } + + boolean isBeforeOf(TmpRouteSegmentData other) { + return Algorithms.objectEquals(this.end, other.start); + } + + void joinAfter(TmpRouteSegmentData other) { + end = other.end; + routeSegments.addAll(other.routeSegments); + } + + void joinBefore(TmpRouteSegmentData other) { + start = other.start; + routeSegments.addAll(0, other.routeSegments); + } + + public List getRouteSegments() { + return routeSegments; + } } void splitSegments(int position) { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java index 72cc761c84..0bda872c2d 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java @@ -41,9 +41,7 @@ import static net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.Ho import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class MtGraphFragment extends Fragment implements MeasurementToolFragment.OnUpdateAdditionalInfoListener { @@ -55,62 +53,26 @@ public class MtGraphFragment extends Fragment private View messageContainer; private LineChart commonGraphChart; private HorizontalBarChart customGraphChart; - private RecyclerView rvMenu; + private RecyclerView rvGraphTypesMenu; private boolean nightMode; private MeasurementEditingContext editingCtx; private GraphType currentGraphType; - private Map graphData = new HashMap<>(); + private List graphTypes = new ArrayList<>(); - private enum GraphType { - OVERVIEW(R.string.shared_string_overview, false, false), - ALTITUDE(R.string.altitude, false, true), -// SLOPE(R.string.shared_string_slope, false, true), - SPEED(R.string.map_widget_speed, false, false), + private enum CommonGraphType { + OVERVIEW(R.string.shared_string_overview, false), + ALTITUDE(R.string.altitude, true), + SLOPE(R.string.shared_string_slope, true), + SPEED(R.string.map_widget_speed, false); - SURFACE(R.string.routeInfo_surface_name, true, false), - ROAD_TYPE(R.string.routeInfo_roadClass_name, true, false), - STEEPNESS(R.string.routeInfo_steepness_name, true, false), - SMOOTHNESS(R.string.routeInfo_smoothness_name, true, false); - - GraphType(int titleId, boolean isCustomType, boolean canBeCalculated) { + CommonGraphType(int titleId, boolean canBeCalculated) { this.titleId = titleId; - this.isCustomType = isCustomType; this.canBeCalculated = canBeCalculated; } final int titleId; - final boolean isCustomType; final boolean canBeCalculated; - - private static List commonTypes; - private static List customTypes; - - static List getCommonTypes() { - if (commonTypes == null) { - prepareLists(); - } - return commonTypes; - } - - static List getCustomTypes() { - if (customTypes == null) { - prepareLists(); - } - return customTypes; - } - - private static void prepareLists() { - commonTypes = new ArrayList<>(); - customTypes = new ArrayList<>(); - for (GraphType type : values()) { - if (type.isCustomType) { - customTypes.add(type); - } else { - commonTypes.add(type); - } - } - } } @Nullable @@ -136,35 +98,33 @@ public class MtGraphFragment extends Fragment customGraphChart = (HorizontalBarChart) view.findViewById(R.id.horizontal_chart); updateGraphData(); - rvMenu = view.findViewById(R.id.graph_types_recycler_view); - rvMenu.setLayoutManager( + rvGraphTypesMenu = view.findViewById(R.id.graph_types_recycler_view); + rvGraphTypesMenu.setLayoutManager( new LinearLayoutManager(mapActivity, RecyclerView.HORIZONTAL, false)); - prepareGraphTypesSelectionMenu(); - setupVisibleGraphType(GraphType.OVERVIEW); + refreshGraphTypesSelectionMenu(); + setupVisibleGraphType(graphTypes.get(0)); return view; } - private void prepareGraphTypesSelectionMenu() { - rvMenu.removeAllViews(); + private void refreshGraphTypesSelectionMenu() { + rvGraphTypesMenu.removeAllViews(); OsmandApplication app = getMyApplication(); int activeColorId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; final HorizontalSelectionAdapter adapter = new HorizontalSelectionAdapter(app, nightMode); final ArrayList items = new ArrayList<>(); - for (GraphType type : GraphType.values()) { - String title = getString(type.titleId); - HorizontalSelectionItem item = new HorizontalSelectionItem(title, type); - if (type.isCustomType) { + for (GraphType type : graphTypes) { + HorizontalSelectionItem item = new HorizontalSelectionItem(type.getTitle(), type); + if (type.isCustom()) { item.setTitleColorId(activeColorId); } - if (isDataAvailableFor(type) || type.canBeCalculated) { + if (type.hasData() || type.canBeCalculated) { items.add(item); } } adapter.setItems(items); - String selectedItemKey = currentGraphType != null ? - getString(currentGraphType.titleId) : items.get(0).getTitle(); + String selectedItemKey = currentGraphType != null ? currentGraphType.getTitle() : items.get(0).getTitle(); adapter.setSelectedItemByTitle(selectedItemKey); adapter.setListener(new HorizontalSelectionAdapter.HorizontalSelectionAdapterListener() { @Override @@ -177,53 +137,52 @@ public class MtGraphFragment extends Fragment } } }); - rvMenu.setAdapter(adapter); + rvGraphTypesMenu.setAdapter(adapter); adapter.notifyDataSetChanged(); } @Override public void onUpdateAdditionalInfo() { updateGraphData(); - prepareGraphTypesSelectionMenu(); + refreshGraphTypesSelectionMenu(); setupVisibleGraphType(currentGraphType); } private void setupVisibleGraphType(GraphType preferredType) { - currentGraphType = isDataAvailableFor(preferredType) ? - preferredType : getFirstAvailableGraphType(); + currentGraphType = preferredType.hasData() ? preferredType : getFirstAvailableGraphType(); updateDataView(); } private GraphType getFirstAvailableGraphType() { - for (GraphType type : GraphType.values()) { - if (isDataAvailableFor(type) || type.canBeCalculated) { + for (GraphType type : graphTypes) { + if (type.hasData() || type.canBeCalculated()) { return type; } } - return GraphType.OVERVIEW; + return null; } private void updateDataView() { - if (isDataAvailableFor(currentGraphType)) { + if (currentGraphType.hasData()) { showGraph(); - } else if (currentGraphType.canBeCalculated) { + } else if (currentGraphType.canBeCalculated()) { showMessage(); } } private void showGraph() { - if (currentGraphType.isCustomType) { + if (currentGraphType.isCustom()) { customGraphChart.clear(); commonGraphContainer.setVisibility(View.GONE); customGraphContainer.setVisibility(View.VISIBLE); messageContainer.setVisibility(View.GONE); - prepareCustomGraphView(); + prepareCustomGraphView((BarData) currentGraphType.getData()); } else { commonGraphChart.clear(); commonGraphContainer.setVisibility(View.VISIBLE); customGraphContainer.setVisibility(View.GONE); messageContainer.setVisibility(View.GONE); - prepareCommonGraphView(); + prepareCommonGraphView((LineData) currentGraphType.getData()); } } @@ -233,24 +192,19 @@ public class MtGraphFragment extends Fragment messageContainer.setVisibility(View.VISIBLE); TextView tvMessage = messageContainer.findViewById(R.id.message_text); ImageView icon = messageContainer.findViewById(R.id.message_icon); - if (GraphType.ALTITUDE.equals(currentGraphType)) { - tvMessage.setText(R.string.message_need_calculate_route_for_show_graph); - icon.setImageResource(R.drawable.ic_action_altitude_average); - } + String message = getString(R.string.message_need_calculate_route_before_show_graph, currentGraphType.getTitle()); + tvMessage.setText(message); + icon.setImageResource(R.drawable.ic_action_altitude_average); } - private void prepareCommonGraphView() { - LineData data = (LineData) graphData.get(currentGraphType); - if (data == null) return; - + private void prepareCommonGraphView(LineData data) { GpxUiHelper.setupGPXChart(commonGraphChart, 4, 24f, 16f, !nightMode, true); commonGraphChart.setData(data); } - private void prepareCustomGraphView() { - BarData data = (BarData) graphData.get(currentGraphType); - OsmandApplication app = getMapActivity().getMyApplication(); - if (data == null || app == null) return; + private void prepareCustomGraphView(BarData data) { + OsmandApplication app = getMyApplication(); + if (app == null) return; GpxUiHelper.setupHorizontalGPXChart(app, customGraphChart, 5, 9, 24, true, nightMode); customGraphChart.setExtraRightOffset(16); @@ -259,75 +213,57 @@ public class MtGraphFragment extends Fragment } private void updateGraphData() { + graphTypes.clear(); OsmandApplication app = getMyApplication(); GPXTrackAnalysis analysis = createGpxTrackAnalysis(); // update common graph data - for (GraphType type : GraphType.getCommonTypes()) { - List dataSets = getDataSets(type, commonGraphChart, analysis); + for (CommonGraphType commonType : CommonGraphType.values()) { + List dataSets = getDataSets(commonType, commonGraphChart, analysis); + Object data = null; if (!Algorithms.isEmpty(dataSets)) { - graphData.put(type, new LineData(dataSets)); - } else { - graphData.put(type, null); + data = new LineData(dataSets); } + String title = getString(commonType.titleId); + graphTypes.add(new GraphType(title, false, commonType.canBeCalculated, data)); } // update custom graph data List routeSegments = editingCtx.getAllRouteSegments(); List routeStatistics = calculateRouteStatistics(routeSegments); - for (GraphType type : GraphType.getCustomTypes()) { - RouteStatistics statistic = getStatisticForGraphType(routeStatistics, type); - if (statistic != null && !Algorithms.isEmpty(statistic.elements)) { - BarData data = GpxUiHelper.buildStatisticChart( - app, customGraphChart, statistic, analysis, true, nightMode); - graphData.put(type, data); - } else { - graphData.put(type, null); + if (analysis != null && routeStatistics != null) { + for (RouteStatistics statistics : routeStatistics) { + String title = SettingsBaseActivity.getStringRouteInfoPropertyValue(app, statistics.name); + BarData data = null; + if (!Algorithms.isEmpty(statistics.elements)) { + data = GpxUiHelper.buildStatisticChart( + app, customGraphChart, statistics, analysis, true, nightMode); + } + graphTypes.add(new GraphType(title, true, false, data)); } } } - private RouteStatistics getStatisticForGraphType(List routeStatistics, GraphType graphType) { - if (routeStatistics == null) return null; - for (RouteStatistics statistic : routeStatistics) { - int graphTypeId = graphType.titleId; - int statisticId = SettingsBaseActivity.getStringRouteInfoPropertyValueId(statistic.name); - if (graphTypeId == statisticId) { - return statistic; - } - } - return null; - } - - private List getDataSets(GraphType graphType, LineChart chart, GPXTrackAnalysis analysis) { + private List getDataSets(CommonGraphType type, LineChart chart, GPXTrackAnalysis analysis) { List dataSets = new ArrayList<>(); if (chart != null && analysis != null) { OsmandApplication app = getMyApplication(); - switch (graphType) { + switch (type) { case OVERVIEW: { - GpxUiHelper.OrderedLineDataSet speedDataSet = null; - GpxUiHelper.OrderedLineDataSet elevationDataSet = null; -// GpxUiHelper.OrderedLineDataSet slopeDataSet = null; - if (analysis.hasSpeedData) { - speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, - analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, true, true, false); - } - if (analysis.hasElevationData) { - elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, - analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true, false); -// slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, -// analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, null, true, true, false); - } List dataList = new ArrayList<>(); - if (speedDataSet != null) { + if (analysis.hasSpeedData) { + GpxUiHelper.OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, + analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, true, true, false); dataList.add(speedDataSet); } - if (elevationDataSet != null) { + if (analysis.hasElevationData) { + GpxUiHelper.OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, + analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true, false); dataList.add(elevationDataSet); + GpxUiHelper.OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, + analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, null, true, true, false); + dataList.add(slopeDataSet); } -// if (slopeDataSet != null) { -// dataList.add(slopeDataSet); -// } if (dataList.size() > 0) { Collections.sort(dataList, new Comparator() { @Override @@ -343,28 +279,22 @@ public class MtGraphFragment extends Fragment if (analysis.hasElevationData) { GpxUiHelper.OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true, false);//calcWithoutGaps); - if (elevationDataSet != null) { - dataSets.add(elevationDataSet); - } + dataSets.add(elevationDataSet); } break; } -// case SLOPE: -// if (analysis.hasElevationData) { -// GpxUiHelper.OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, -// analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, null, true, true, false); -// if (slopeDataSet != null) { -// dataSets.add(slopeDataSet); -// } -// } -// break; + case SLOPE: + if (analysis.hasElevationData) { + GpxUiHelper.OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, + analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, null, true, true, false); + dataSets.add(slopeDataSet); + } + break; case SPEED: { if (analysis.hasSpeedData) { GpxUiHelper.OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true, false);//calcWithoutGaps); - if (speedDataSet != null) { - dataSets.add(speedDataSet); - } + dataSets.add(speedDataSet); } break; } @@ -398,10 +328,6 @@ public class MtGraphFragment extends Fragment defaultRender, currentSearchRequest, defaultSearchRequest); } - private boolean isDataAvailableFor(GraphType graphType) { - return graphData != null && graphData.get(graphType) != null; - } - private OsmandApplication getMyApplication() { return getMapActivity().getMyApplication(); } @@ -409,4 +335,38 @@ public class MtGraphFragment extends Fragment private MapActivity getMapActivity() { return (MapActivity) getActivity(); } + + private static class GraphType { + private String title; + private boolean isCustom; + private boolean canBeCalculated; + private Object data; + + public GraphType(String title, boolean isCustom, boolean canBeCalculated, Object data) { + this.title = title; + this.isCustom = isCustom; + this.canBeCalculated = canBeCalculated; + this.data = data; + } + + public String getTitle() { + return title; + } + + public boolean isCustom() { + return isCustom; + } + + public boolean canBeCalculated() { + return canBeCalculated; + } + + public boolean hasData() { + return getData() != null; + } + + public Object getData() { + return data; + } + } } From f5cacff2cda159b29b447b5a24654fdbde5d45e2 Mon Sep 17 00:00:00 2001 From: Nazar-Kutz Date: Mon, 12 Oct 2020 19:23:04 +0300 Subject: [PATCH 4/8] use cards instead of fragment --- .../res/layout/fragment_measurement_tool.xml | 2 +- .../MeasurementToolFragment.java | 82 ++++++------------ .../plus/measurementtool/MtGraphFragment.java | 83 ++++++++----------- .../measurementtool/MtPointsFragment.java | 54 ++++-------- 4 files changed, 81 insertions(+), 140 deletions(-) diff --git a/OsmAnd/res/layout/fragment_measurement_tool.xml b/OsmAnd/res/layout/fragment_measurement_tool.xml index 1ccae4f0c3..a6e1e15018 100644 --- a/OsmAnd/res/layout/fragment_measurement_tool.xml +++ b/OsmAnd/res/layout/fragment_measurement_tool.xml @@ -144,7 +144,7 @@ android:layout_height="@dimen/content_padding_small" /> diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index a927ca884e..e5737ceca1 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -26,7 +26,6 @@ import androidx.core.content.ContextCompat; import androidx.core.widget.TextViewCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; @@ -72,6 +71,7 @@ import net.osmand.plus.measurementtool.command.MovePointCommand; import net.osmand.plus.measurementtool.command.RemovePointCommand; import net.osmand.plus.measurementtool.command.ReorderPointCommand; import net.osmand.plus.measurementtool.command.ReversePointsCommand; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.views.layers.MapControlsLayer; @@ -116,6 +116,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private TextView distanceToCenterTv; private String pointsSt; private View additionalInfoContainer; + private ViewGroup additionalInfoCardsContainer; + private BaseCard visibleAdditionalInfoCard; private LinearLayout customRadioButton; private View mainView; private ImageView upDownBtn; @@ -157,18 +159,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } private enum AdditionalInfoType { - POINTS(MtPointsFragment.class.getName()), - GRAPH(MtGraphFragment.class.getName()); - - AdditionalInfoType(String fragmentName) { - this.fragmentName = fragmentName; - } - - final String fragmentName; - - public String getFragmentName() { - return fragmentName; - } + POINTS, + GRAPH } private void setEditingCtx(MeasurementEditingContext editingCtx) { @@ -264,6 +256,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route mainView = view.findViewById(R.id.main_view); AndroidUtils.setBackground(mapActivity, mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark); additionalInfoContainer = mainView.findViewById(R.id.additional_info_container); + additionalInfoCardsContainer = mainView.findViewById(R.id.cards_container); if (portrait) { customRadioButton = mainView.findViewById(R.id.custom_radio_buttons); @@ -521,7 +514,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private void changeAdditionalInfoType(@NonNull AdditionalInfoType type) { if (!additionalInfoExpanded || !isCurrentAdditionalInfoType(type)) { currentAdditionalInfoType = type; - additionalInfoExpanded = true; updateUpDownBtn(); OsmandApplication app = getMyApplication(); if (AdditionalInfoType.POINTS.equals(type)) { @@ -531,14 +523,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } else { return; } - setAdditionalInfoFragment(type.getFragmentName()); + setAdditionalInfoCard(type); } } private void updateAdditionalInfoView() { - Fragment fragment = getActiveAdditionalInfoFragment(); - if (fragment instanceof OnUpdateAdditionalInfoListener) { - ((OnUpdateAdditionalInfoListener) fragment).onUpdateAdditionalInfo(); + if (visibleAdditionalInfoCard instanceof OnUpdateAdditionalInfoListener) { + ((OnUpdateAdditionalInfoListener) visibleAdditionalInfoCard).onUpdateAdditionalInfo(); } } @@ -1472,29 +1463,28 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (portrait) { additionalInfoExpanded = false; updateUpDownBtn(); - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - Fragment activeFragment = getActiveAdditionalInfoFragment(); - if (activeFragment != null) { - FragmentManager manager = getChildFragmentManager(); - manager.beginTransaction().remove(activeFragment).commitAllowingStateLoss(); - } - additionalInfoContainer.setVisibility(View.GONE); - setDefaultMapPosition(); - } + additionalInfoContainer.setVisibility(View.GONE); + setDefaultMapPosition(); } } - private void setAdditionalInfoFragment(String fragmentName) { - Context ctx = getContext(); - if (ctx == null) return; + private void setAdditionalInfoCard(AdditionalInfoType type) { + MapActivity ma = getMapActivity(); + if (ma == null) return; - Fragment fragment = Fragment.instantiate(ctx, fragmentName); - FragmentManager fm = getChildFragmentManager(); - FragmentTransaction fragmentTransaction = fm.beginTransaction(); - fragmentTransaction.replace(R.id.fragmentContainer, fragment, fragmentName); - fragmentTransaction.commit(); - fm.executePendingTransactions(); + BaseCard additionalInfoCard = null; + if (type.equals(AdditionalInfoType.POINTS)) { + additionalInfoCard = new MtPointsFragment(ma, this); + } else if (type.equals(AdditionalInfoType.GRAPH)) { + additionalInfoCard = new MtGraphFragment(ma, this); + } + + if (additionalInfoCard != null) { + visibleAdditionalInfoCard = additionalInfoCard; + additionalInfoCardsContainer.removeAllViews(); + additionalInfoCardsContainer.addView(additionalInfoCard.build(ma)); + additionalInfoExpanded = true; + } } private void collapseAdditionalInfoIfNoPointsEnough() { @@ -1512,24 +1502,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - private Fragment getActiveAdditionalInfoFragment() { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - for (AdditionalInfoType type : AdditionalInfoType.values()) { - try { - FragmentManager fm = getChildFragmentManager(); - Fragment fragment = fm.findFragmentByTag(type.getFragmentName()); - if (fragment != null) { - return fragment; - } - } catch (Exception e) { - // ignore - } - } - } - return null; - } - private void setDefaultMapPosition() { setMapPosition(OsmandSettings.CENTER_CONSTANT); } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java index 0bda872c2d..71a7c45db2 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java @@ -1,15 +1,10 @@ package net.osmand.plus.measurementtool; -import android.os.Bundle; -import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -21,12 +16,12 @@ import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; -import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.SettingsBaseActivity; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter; import net.osmand.plus.render.MapRenderRepositories; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRulesStorage; import net.osmand.router.RouteSegmentResult; @@ -43,7 +38,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -public class MtGraphFragment extends Fragment +public class MtGraphFragment extends BaseCard implements MeasurementToolFragment.OnUpdateAdditionalInfoListener { private static String GRAPH_DATA_GPX_FILE_NAME = "graph_data_tmp"; @@ -55,10 +50,15 @@ public class MtGraphFragment extends Fragment private HorizontalBarChart customGraphChart; private RecyclerView rvGraphTypesMenu; - private boolean nightMode; private MeasurementEditingContext editingCtx; private GraphType currentGraphType; private List graphTypes = new ArrayList<>(); + private MeasurementToolFragment mtf; + + public MtGraphFragment(@NonNull MapActivity mapActivity, MeasurementToolFragment mtf) { + super(mapActivity); + this.mtf = mtf; + } private enum CommonGraphType { OVERVIEW(R.string.shared_string_overview, false), @@ -75,39 +75,6 @@ public class MtGraphFragment extends Fragment final boolean canBeCalculated; } - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, - @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - - final MapActivity mapActivity = (MapActivity) getActivity(); - final MeasurementToolFragment mtf = (MeasurementToolFragment) getParentFragment(); - if (mapActivity == null || mtf == null) return null; - - editingCtx = mtf.getEditingCtx(); - OsmandApplication app = mapActivity.getMyApplication(); - - nightMode = app.getDaynightHelper().isNightModeForMapControls(); - View view = UiUtilities.getInflater(app, nightMode).inflate( - R.layout.fragment_measurement_tool_graph, container, false); - commonGraphContainer = view.findViewById(R.id.common_graphs_container); - customGraphContainer = view.findViewById(R.id.custom_graphs_container); - messageContainer = view.findViewById(R.id.message_container); - commonGraphChart = (LineChart) view.findViewById(R.id.line_chart); - customGraphChart = (HorizontalBarChart) view.findViewById(R.id.horizontal_chart); - updateGraphData(); - - rvGraphTypesMenu = view.findViewById(R.id.graph_types_recycler_view); - rvGraphTypesMenu.setLayoutManager( - new LinearLayoutManager(mapActivity, RecyclerView.HORIZONTAL, false)); - - refreshGraphTypesSelectionMenu(); - setupVisibleGraphType(graphTypes.get(0)); - - return view; - } - private void refreshGraphTypesSelectionMenu() { rvGraphTypesMenu.removeAllViews(); OsmandApplication app = getMyApplication(); @@ -149,7 +116,8 @@ public class MtGraphFragment extends Fragment } private void setupVisibleGraphType(GraphType preferredType) { - currentGraphType = preferredType.hasData() ? preferredType : getFirstAvailableGraphType(); + currentGraphType = currentGraphType != null && preferredType.hasData() + ? preferredType : getFirstAvailableGraphType(); updateDataView(); } @@ -192,7 +160,7 @@ public class MtGraphFragment extends Fragment messageContainer.setVisibility(View.VISIBLE); TextView tvMessage = messageContainer.findViewById(R.id.message_text); ImageView icon = messageContainer.findViewById(R.id.message_icon); - String message = getString(R.string.message_need_calculate_route_before_show_graph, currentGraphType.getTitle()); + String message = app.getString(R.string.message_need_calculate_route_before_show_graph, currentGraphType.getTitle()); tvMessage.setText(message); icon.setImageResource(R.drawable.ic_action_altitude_average); } @@ -224,7 +192,7 @@ public class MtGraphFragment extends Fragment if (!Algorithms.isEmpty(dataSets)) { data = new LineData(dataSets); } - String title = getString(commonType.titleId); + String title = app.getString(commonType.titleId); graphTypes.add(new GraphType(title, false, commonType.canBeCalculated, data)); } @@ -328,12 +296,31 @@ public class MtGraphFragment extends Fragment defaultRender, currentSearchRequest, defaultSearchRequest); } - private OsmandApplication getMyApplication() { - return getMapActivity().getMyApplication(); + @Override + public int getCardLayoutId() { + return R.layout.fragment_measurement_tool_graph; } - private MapActivity getMapActivity() { - return (MapActivity) getActivity(); + @Override + protected void updateContent() { + if (mapActivity == null || mtf == null) return; + + editingCtx = mtf.getEditingCtx(); + OsmandApplication app = mapActivity.getMyApplication(); + + commonGraphContainer = view.findViewById(R.id.common_graphs_container); + customGraphContainer = view.findViewById(R.id.custom_graphs_container); + messageContainer = view.findViewById(R.id.message_container); + commonGraphChart = (LineChart) view.findViewById(R.id.line_chart); + customGraphChart = (HorizontalBarChart) view.findViewById(R.id.horizontal_chart); + updateGraphData(); + + rvGraphTypesMenu = view.findViewById(R.id.graph_types_recycler_view); + rvGraphTypesMenu.setLayoutManager( + new LinearLayoutManager(mapActivity, RecyclerView.HORIZONTAL, false)); + + refreshGraphTypesSelectionMenu(); + setupVisibleGraphType(currentGraphType); } private static class GraphType { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java index 086ab6c322..c859d9b84d 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java @@ -1,46 +1,41 @@ package net.osmand.plus.measurementtool; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import net.osmand.plus.R; -import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback; -public class MtPointsFragment extends Fragment +public class MtPointsFragment extends BaseCard implements MeasurementToolFragment.OnUpdateAdditionalInfoListener { - private boolean nightMode; private MeasurementToolAdapter adapter; private MeasurementEditingContext editingCtx; private RecyclerView pointsRv; + private MeasurementToolFragment mtf; + + public MtPointsFragment(@NonNull MapActivity mapActivity, MeasurementToolFragment mtf) { + super(mapActivity); + this.mtf = mtf; + } - @Nullable @Override - public View onCreateView(@NonNull LayoutInflater inflater, - @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public void onUpdateAdditionalInfo() { + adapter.notifyDataSetChanged(); + } - final MapActivity mapActivity = (MapActivity) getActivity(); - final MeasurementToolFragment mtf = (MeasurementToolFragment) getParentFragment(); - if (mapActivity == null || mtf == null) { - return null; - } - nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls(); - View view = UiUtilities.getInflater(getContext(), nightMode) - .inflate(R.layout.fragment_measurement_tool_points_list, container, false); + @Override + public int getCardLayoutId() { + return R.layout.fragment_measurement_tool_points_list; + } + @Override + protected void updateContent() { editingCtx = mtf.getEditingCtx(); final GpxData gpxData = editingCtx.getGpxData(); adapter = new MeasurementToolAdapter(mapActivity, editingCtx.getPoints(), @@ -49,20 +44,7 @@ public class MtPointsFragment extends Fragment ItemTouchHelper touchHelper = new ItemTouchHelper(new ReorderItemTouchHelperCallback(adapter)); touchHelper.attachToRecyclerView(pointsRv); adapter.setAdapterListener(mtf.createMeasurementAdapterListener(touchHelper)); - pointsRv.setLayoutManager(new LinearLayoutManager(getContext())); + pointsRv.setLayoutManager(new LinearLayoutManager(app)); pointsRv.setAdapter(adapter); - - return view; - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - adapter.setAdapterListener(null); - } - - @Override - public void onUpdateAdditionalInfo() { - adapter.notifyDataSetChanged(); } } From 3ef12afb08841818d4151bb53c5bcc706295e628 Mon Sep 17 00:00:00 2001 From: Nazar-Kutz Date: Tue, 13 Oct 2020 12:27:24 +0300 Subject: [PATCH 5/8] show progress bar while route is recalculating --- .../fragment_measurement_tool_graph.xml | 10 ++ OsmAnd/res/values/strings.xml | 1 + .../MeasurementToolFragment.java | 6 +- .../plus/measurementtool/MtGraphFragment.java | 102 +++++++++++------- 4 files changed, 78 insertions(+), 41 deletions(-) diff --git a/OsmAnd/res/layout/fragment_measurement_tool_graph.xml b/OsmAnd/res/layout/fragment_measurement_tool_graph.xml index dd9d3b7cae..3d14187712 100644 --- a/OsmAnd/res/layout/fragment_measurement_tool_graph.xml +++ b/OsmAnd/res/layout/fragment_measurement_tool_graph.xml @@ -85,6 +85,16 @@ android:tint="?attr/default_icon_color" tools:src="@drawable/ic_action_info_dark" /> + + + Wait for the route recalculation.\nGraph will be available after recalculation. %1$s data available only on the roads, you need to calculate a route using “Route between points” to get it. Graph Logout successful diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index e5737ceca1..671539ffb8 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -24,7 +24,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.core.widget.TextViewCompat; -import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; @@ -222,6 +221,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void showProgressBar() { MeasurementToolFragment.this.showProgressBar(); + updateAdditionalInfoView(); } @Override @@ -659,6 +659,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route progressBarVisible = true; } + public boolean isProgressBarVisible() { + return progressBarVisible; + } + private void updateMainIcon() { GpxData gpxData = editingCtx.getGpxData(); if (gpxData != null) { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java index 71a7c45db2..c8f6e3cf2d 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java @@ -2,6 +2,7 @@ package net.osmand.plus.measurementtool; import android.view.View; import android.widget.ImageView; +import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; @@ -55,11 +56,6 @@ public class MtGraphFragment extends BaseCard private List graphTypes = new ArrayList<>(); private MeasurementToolFragment mtf; - public MtGraphFragment(@NonNull MapActivity mapActivity, MeasurementToolFragment mtf) { - super(mapActivity); - this.mtf = mtf; - } - private enum CommonGraphType { OVERVIEW(R.string.shared_string_overview, false), ALTITUDE(R.string.altitude, true), @@ -75,6 +71,37 @@ public class MtGraphFragment extends BaseCard final boolean canBeCalculated; } + public MtGraphFragment(@NonNull MapActivity mapActivity, MeasurementToolFragment mtf) { + super(mapActivity); + this.mtf = mtf; + } + + @Override + protected void updateContent() { + if (mapActivity == null || mtf == null) return; + editingCtx = mtf.getEditingCtx(); + + commonGraphContainer = view.findViewById(R.id.common_graphs_container); + customGraphContainer = view.findViewById(R.id.custom_graphs_container); + messageContainer = view.findViewById(R.id.message_container); + commonGraphChart = (LineChart) view.findViewById(R.id.line_chart); + customGraphChart = (HorizontalBarChart) view.findViewById(R.id.horizontal_chart); + updateGraphData(); + + rvGraphTypesMenu = view.findViewById(R.id.graph_types_recycler_view); + rvGraphTypesMenu.setLayoutManager( + new LinearLayoutManager(mapActivity, RecyclerView.HORIZONTAL, false)); + + refreshGraphTypesSelectionMenu(); + GraphType firstAvailableGraphType = getFirstAvailableGraphType(); + setupVisibleGraphType(firstAvailableGraphType); + } + + @Override + public int getCardLayoutId() { + return R.layout.fragment_measurement_tool_graph; + } + private void refreshGraphTypesSelectionMenu() { rvGraphTypesMenu.removeAllViews(); OsmandApplication app = getMyApplication(); @@ -112,18 +139,18 @@ public class MtGraphFragment extends BaseCard public void onUpdateAdditionalInfo() { updateGraphData(); refreshGraphTypesSelectionMenu(); - setupVisibleGraphType(currentGraphType); + setupVisibleGraphType(currentGraphType.isAvailable() + ? currentGraphType : getFirstAvailableGraphType()); } - private void setupVisibleGraphType(GraphType preferredType) { - currentGraphType = currentGraphType != null && preferredType.hasData() - ? preferredType : getFirstAvailableGraphType(); + private void setupVisibleGraphType(GraphType type) { + currentGraphType = type; updateDataView(); } private GraphType getFirstAvailableGraphType() { for (GraphType type : graphTypes) { - if (type.hasData() || type.canBeCalculated()) { + if (type.isAvailable()) { return type; } } @@ -131,13 +158,27 @@ public class MtGraphFragment extends BaseCard } private void updateDataView() { - if (currentGraphType.hasData()) { + if (mtf.isProgressBarVisible()) { + showProgressMessage(); + } else if (currentGraphType.hasData()) { showGraph(); } else if (currentGraphType.canBeCalculated()) { showMessage(); } } + private void showProgressMessage() { + commonGraphContainer.setVisibility(View.GONE); + customGraphContainer.setVisibility(View.GONE); + messageContainer.setVisibility(View.VISIBLE); + TextView tvMessage = messageContainer.findViewById(R.id.message_text); + ImageView icon = messageContainer.findViewById(R.id.message_icon); + ProgressBar pb = messageContainer.findViewById(R.id.progress_bar); + pb.setVisibility(View.VISIBLE); + icon.setVisibility(View.GONE); + tvMessage.setText(R.string.message_graph_will_be_available_after_recalculation); + } + private void showGraph() { if (currentGraphType.isCustom()) { customGraphChart.clear(); @@ -160,8 +201,12 @@ public class MtGraphFragment extends BaseCard messageContainer.setVisibility(View.VISIBLE); TextView tvMessage = messageContainer.findViewById(R.id.message_text); ImageView icon = messageContainer.findViewById(R.id.message_icon); - String message = app.getString(R.string.message_need_calculate_route_before_show_graph, currentGraphType.getTitle()); - tvMessage.setText(message); + ProgressBar pb = messageContainer.findViewById(R.id.progress_bar); + pb.setVisibility(View.GONE); + icon.setVisibility(View.VISIBLE); + tvMessage.setText(app.getString( + R.string.message_need_calculate_route_before_show_graph, + currentGraphType.getTitle())); icon.setImageResource(R.drawable.ic_action_altitude_average); } @@ -296,33 +341,6 @@ public class MtGraphFragment extends BaseCard defaultRender, currentSearchRequest, defaultSearchRequest); } - @Override - public int getCardLayoutId() { - return R.layout.fragment_measurement_tool_graph; - } - - @Override - protected void updateContent() { - if (mapActivity == null || mtf == null) return; - - editingCtx = mtf.getEditingCtx(); - OsmandApplication app = mapActivity.getMyApplication(); - - commonGraphContainer = view.findViewById(R.id.common_graphs_container); - customGraphContainer = view.findViewById(R.id.custom_graphs_container); - messageContainer = view.findViewById(R.id.message_container); - commonGraphChart = (LineChart) view.findViewById(R.id.line_chart); - customGraphChart = (HorizontalBarChart) view.findViewById(R.id.horizontal_chart); - updateGraphData(); - - rvGraphTypesMenu = view.findViewById(R.id.graph_types_recycler_view); - rvGraphTypesMenu.setLayoutManager( - new LinearLayoutManager(mapActivity, RecyclerView.HORIZONTAL, false)); - - refreshGraphTypesSelectionMenu(); - setupVisibleGraphType(currentGraphType); - } - private static class GraphType { private String title; private boolean isCustom; @@ -344,6 +362,10 @@ public class MtGraphFragment extends BaseCard return isCustom; } + public boolean isAvailable() { + return hasData() || canBeCalculated(); + } + public boolean canBeCalculated() { return canBeCalculated; } From f158381f5f38e6d0fd134a8a7122e1fc3853c685 Mon Sep 17 00:00:00 2001 From: Nazar-Kutz Date: Tue, 13 Oct 2020 13:06:27 +0300 Subject: [PATCH 6/8] fix "visible graph doesn't update after data updated" --- .../plus/measurementtool/MtGraphFragment.java | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java index c8f6e3cf2d..f3b4bbcf8c 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java @@ -52,7 +52,7 @@ public class MtGraphFragment extends BaseCard private RecyclerView rvGraphTypesMenu; private MeasurementEditingContext editingCtx; - private GraphType currentGraphType; + private GraphType visibleGraphType; private List graphTypes = new ArrayList<>(); private MeasurementToolFragment mtf; @@ -93,8 +93,7 @@ public class MtGraphFragment extends BaseCard new LinearLayoutManager(mapActivity, RecyclerView.HORIZONTAL, false)); refreshGraphTypesSelectionMenu(); - GraphType firstAvailableGraphType = getFirstAvailableGraphType(); - setupVisibleGraphType(firstAvailableGraphType); + updateDataView(); } @Override @@ -118,7 +117,7 @@ public class MtGraphFragment extends BaseCard } } adapter.setItems(items); - String selectedItemKey = currentGraphType != null ? currentGraphType.getTitle() : items.get(0).getTitle(); + String selectedItemKey = visibleGraphType.getTitle(); adapter.setSelectedItemByTitle(selectedItemKey); adapter.setListener(new HorizontalSelectionAdapter.HorizontalSelectionAdapterListener() { @Override @@ -126,7 +125,7 @@ public class MtGraphFragment extends BaseCard adapter.setItems(items); adapter.setSelectedItem(item); GraphType chosenGraphType = (GraphType) item.getObject(); - if (chosenGraphType != null && !chosenGraphType.equals(currentGraphType)) { + if (!isCurrentVisibleType(chosenGraphType)) { setupVisibleGraphType(chosenGraphType); } } @@ -139,15 +138,21 @@ public class MtGraphFragment extends BaseCard public void onUpdateAdditionalInfo() { updateGraphData(); refreshGraphTypesSelectionMenu(); - setupVisibleGraphType(currentGraphType.isAvailable() - ? currentGraphType : getFirstAvailableGraphType()); + updateDataView(); } private void setupVisibleGraphType(GraphType type) { - currentGraphType = type; + visibleGraphType = type; updateDataView(); } + private boolean isCurrentVisibleType(GraphType type) { + if (visibleGraphType != null && type != null) { + return Algorithms.objectEquals(visibleGraphType.getTitle(), type.getTitle()); + } + return false; + } + private GraphType getFirstAvailableGraphType() { for (GraphType type : graphTypes) { if (type.isAvailable()) { @@ -160,9 +165,9 @@ public class MtGraphFragment extends BaseCard private void updateDataView() { if (mtf.isProgressBarVisible()) { showProgressMessage(); - } else if (currentGraphType.hasData()) { + } else if (visibleGraphType.hasData()) { showGraph(); - } else if (currentGraphType.canBeCalculated()) { + } else if (visibleGraphType.canBeCalculated()) { showMessage(); } } @@ -180,18 +185,18 @@ public class MtGraphFragment extends BaseCard } private void showGraph() { - if (currentGraphType.isCustom()) { + if (visibleGraphType.isCustom()) { customGraphChart.clear(); commonGraphContainer.setVisibility(View.GONE); customGraphContainer.setVisibility(View.VISIBLE); messageContainer.setVisibility(View.GONE); - prepareCustomGraphView((BarData) currentGraphType.getData()); + prepareCustomGraphView((BarData) visibleGraphType.getData()); } else { commonGraphChart.clear(); commonGraphContainer.setVisibility(View.VISIBLE); customGraphContainer.setVisibility(View.GONE); messageContainer.setVisibility(View.GONE); - prepareCommonGraphView((LineData) currentGraphType.getData()); + prepareCommonGraphView((LineData) visibleGraphType.getData()); } } @@ -206,7 +211,7 @@ public class MtGraphFragment extends BaseCard icon.setVisibility(View.VISIBLE); tvMessage.setText(app.getString( R.string.message_need_calculate_route_before_show_graph, - currentGraphType.getTitle())); + visibleGraphType.getTitle())); icon.setImageResource(R.drawable.ic_action_altitude_average); } @@ -255,6 +260,18 @@ public class MtGraphFragment extends BaseCard graphTypes.add(new GraphType(title, true, false, data)); } } + + // update current visible graph type + if (visibleGraphType == null) { + visibleGraphType = getFirstAvailableGraphType(); + } else { + for (GraphType type : graphTypes) { + if (isCurrentVisibleType(type)) { + visibleGraphType = type.isAvailable() ? type : getFirstAvailableGraphType(); + break; + } + } + } } private List getDataSets(CommonGraphType type, LineChart chart, GPXTrackAnalysis analysis) { From c75aa594eacc9ffd924ab94ebbbdffce0c4044ef Mon Sep 17 00:00:00 2001 From: Nazar-Kutz Date: Tue, 13 Oct 2020 13:26:02 +0300 Subject: [PATCH 7/8] fix "selected graph changed after recalculation" --- .../plus/measurementtool/MtGraphFragment.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java index f3b4bbcf8c..eadc5c6a7e 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java @@ -101,6 +101,15 @@ public class MtGraphFragment extends BaseCard return R.layout.fragment_measurement_tool_graph; } + @Override + public void onUpdateAdditionalInfo() { + if (!isRouteCalculating()) { + updateGraphData(); + refreshGraphTypesSelectionMenu(); + } + updateDataView(); + } + private void refreshGraphTypesSelectionMenu() { rvGraphTypesMenu.removeAllViews(); OsmandApplication app = getMyApplication(); @@ -112,7 +121,7 @@ public class MtGraphFragment extends BaseCard if (type.isCustom()) { item.setTitleColorId(activeColorId); } - if (type.hasData() || type.canBeCalculated) { + if (type.isAvailable()) { items.add(item); } } @@ -134,13 +143,6 @@ public class MtGraphFragment extends BaseCard adapter.notifyDataSetChanged(); } - @Override - public void onUpdateAdditionalInfo() { - updateGraphData(); - refreshGraphTypesSelectionMenu(); - updateDataView(); - } - private void setupVisibleGraphType(GraphType type) { visibleGraphType = type; updateDataView(); @@ -163,7 +165,7 @@ public class MtGraphFragment extends BaseCard } private void updateDataView() { - if (mtf.isProgressBarVisible()) { + if (isRouteCalculating()) { showProgressMessage(); } else if (visibleGraphType.hasData()) { showGraph(); @@ -358,6 +360,10 @@ public class MtGraphFragment extends BaseCard defaultRender, currentSearchRequest, defaultSearchRequest); } + private boolean isRouteCalculating() { + return mtf.isProgressBarVisible(); + } + private static class GraphType { private String title; private boolean isCustom; From 3ad7590844c09cf45993276bda40cabc76c23507 Mon Sep 17 00:00:00 2001 From: Nazar-Kutz Date: Tue, 13 Oct 2020 14:30:00 +0300 Subject: [PATCH 8/8] PR fixes --- OsmAnd/res/values/strings.xml | 3 + .../{MtGraphFragment.java => GraphsCard.java} | 102 ++++++++---------- .../MeasurementToolFragment.java | 44 +++----- ...{MtPointsFragment.java => PointsCard.java} | 18 ++-- .../RouteDetailsFragment.java | 25 +++-- 5 files changed, 90 insertions(+), 102 deletions(-) rename OsmAnd/src/net/osmand/plus/measurementtool/{MtGraphFragment.java => GraphsCard.java} (77%) rename OsmAnd/src/net/osmand/plus/measurementtool/{MtPointsFragment.java => PointsCard.java} (68%) diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 22b7b37b2f..5f63c1dc0b 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,9 @@ Thx - Hardy --> + Wait for the route recalculation.\nGraph will be available after recalculation. + %1$s data available only on the roads, you need to calculate a route using “Route between points” to get it. + Graph Use 2-phase A* routing algorithm File is already imported in OsmAnd Logout successful diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java similarity index 77% rename from OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java rename to OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java index eadc5c6a7e..9a5cbeffba 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/GraphsCard.java @@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; @@ -20,13 +21,13 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.SettingsBaseActivity; import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; +import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter; -import net.osmand.plus.render.MapRenderRepositories; +import net.osmand.plus.measurementtool.MeasurementToolFragment.OnUpdateAdditionalInfoListener; +import net.osmand.plus.routepreparationmenu.RouteDetailsFragment; import net.osmand.plus.routepreparationmenu.cards.BaseCard; -import net.osmand.render.RenderingRuleSearchRequest; -import net.osmand.render.RenderingRulesStorage; import net.osmand.router.RouteSegmentResult; -import net.osmand.router.RouteStatisticsHelper; import net.osmand.util.Algorithms; import static net.osmand.router.RouteStatisticsHelper.RouteStatistics; @@ -39,22 +40,22 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -public class MtGraphFragment extends BaseCard - implements MeasurementToolFragment.OnUpdateAdditionalInfoListener { +public class GraphsCard extends BaseCard implements OnUpdateAdditionalInfoListener { private static String GRAPH_DATA_GPX_FILE_NAME = "graph_data_tmp"; + private MeasurementEditingContext editingCtx; + private MeasurementToolFragment fragment; + + private GraphType visibleGraphType; + private List graphTypes = new ArrayList<>(); + private View commonGraphContainer; private View customGraphContainer; private View messageContainer; private LineChart commonGraphChart; private HorizontalBarChart customGraphChart; - private RecyclerView rvGraphTypesMenu; - - private MeasurementEditingContext editingCtx; - private GraphType visibleGraphType; - private List graphTypes = new ArrayList<>(); - private MeasurementToolFragment mtf; + private RecyclerView graphTypesMenu; private enum CommonGraphType { OVERVIEW(R.string.shared_string_overview, false), @@ -71,15 +72,15 @@ public class MtGraphFragment extends BaseCard final boolean canBeCalculated; } - public MtGraphFragment(@NonNull MapActivity mapActivity, MeasurementToolFragment mtf) { + public GraphsCard(@NonNull MapActivity mapActivity, MeasurementToolFragment fragment) { super(mapActivity); - this.mtf = mtf; + this.fragment = fragment; } @Override protected void updateContent() { - if (mapActivity == null || mtf == null) return; - editingCtx = mtf.getEditingCtx(); + if (mapActivity == null || fragment == null) return; + editingCtx = fragment.getEditingCtx(); commonGraphContainer = view.findViewById(R.id.common_graphs_container); customGraphContainer = view.findViewById(R.id.custom_graphs_container); @@ -88,8 +89,8 @@ public class MtGraphFragment extends BaseCard customGraphChart = (HorizontalBarChart) view.findViewById(R.id.horizontal_chart); updateGraphData(); - rvGraphTypesMenu = view.findViewById(R.id.graph_types_recycler_view); - rvGraphTypesMenu.setLayoutManager( + graphTypesMenu = view.findViewById(R.id.graph_types_recycler_view); + graphTypesMenu.setLayoutManager( new LinearLayoutManager(mapActivity, RecyclerView.HORIZONTAL, false)); refreshGraphTypesSelectionMenu(); @@ -111,7 +112,7 @@ public class MtGraphFragment extends BaseCard } private void refreshGraphTypesSelectionMenu() { - rvGraphTypesMenu.removeAllViews(); + graphTypesMenu.removeAllViews(); OsmandApplication app = getMyApplication(); int activeColorId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; final HorizontalSelectionAdapter adapter = new HorizontalSelectionAdapter(app, nightMode); @@ -139,7 +140,7 @@ public class MtGraphFragment extends BaseCard } } }); - rvGraphTypesMenu.setAdapter(adapter); + graphTypesMenu.setAdapter(adapter); adapter.notifyDataSetChanged(); } @@ -192,13 +193,13 @@ public class MtGraphFragment extends BaseCard commonGraphContainer.setVisibility(View.GONE); customGraphContainer.setVisibility(View.VISIBLE); messageContainer.setVisibility(View.GONE); - prepareCustomGraphView((BarData) visibleGraphType.getData()); + prepareCustomGraphView((BarData) visibleGraphType.getGraphData()); } else { commonGraphChart.clear(); commonGraphContainer.setVisibility(View.VISIBLE); customGraphContainer.setVisibility(View.GONE); messageContainer.setVisibility(View.GONE); - prepareCommonGraphView((LineData) visibleGraphType.getData()); + prepareCommonGraphView((LineData) visibleGraphType.getGraphData()); } } @@ -240,7 +241,7 @@ public class MtGraphFragment extends BaseCard // update common graph data for (CommonGraphType commonType : CommonGraphType.values()) { List dataSets = getDataSets(commonType, commonGraphChart, analysis); - Object data = null; + LineData data = null; if (!Algorithms.isEmpty(dataSets)) { data = new LineData(dataSets); } @@ -282,24 +283,24 @@ public class MtGraphFragment extends BaseCard OsmandApplication app = getMyApplication(); switch (type) { case OVERVIEW: { - List dataList = new ArrayList<>(); + List dataList = new ArrayList<>(); if (analysis.hasSpeedData) { - GpxUiHelper.OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, - analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, true, true, false); + OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, true, true, false); dataList.add(speedDataSet); } if (analysis.hasElevationData) { - GpxUiHelper.OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, - analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true, false); + OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, false, true, false); dataList.add(elevationDataSet); - GpxUiHelper.OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, - analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, null, true, true, false); + OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, null, true, true, false); dataList.add(slopeDataSet); } if (dataList.size() > 0) { - Collections.sort(dataList, new Comparator() { + Collections.sort(dataList, new Comparator() { @Override - public int compare(GpxUiHelper.OrderedLineDataSet o1, GpxUiHelper.OrderedLineDataSet o2) { + public int compare(OrderedLineDataSet o1, OrderedLineDataSet o2) { return Float.compare(o1.getPriority(), o2.getPriority()); } }); @@ -309,23 +310,23 @@ public class MtGraphFragment extends BaseCard } case ALTITUDE: { if (analysis.hasElevationData) { - GpxUiHelper.OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, - analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true, false);//calcWithoutGaps); + OrderedLineDataSet elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, false, true, false);//calcWithoutGaps); dataSets.add(elevationDataSet); } break; } case SLOPE: if (analysis.hasElevationData) { - GpxUiHelper.OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, - analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, null, true, true, false); + OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, null, true, true, false); dataSets.add(slopeDataSet); } break; case SPEED: { if (analysis.hasSpeedData) { - GpxUiHelper.OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, - analysis, GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true, false);//calcWithoutGaps); + OrderedLineDataSet speedDataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, + analysis, GPXDataSetAxisType.DISTANCE, false, true, false);//calcWithoutGaps); dataSets.add(speedDataSet); } break; @@ -348,33 +349,24 @@ public class MtGraphFragment extends BaseCard private List calculateRouteStatistics(List route) { OsmandApplication app = getMyApplication(); if (route == null || app == null) return null; - - RenderingRulesStorage currentRenderer = app.getRendererRegistry().getCurrentSelectedRenderer(); - RenderingRulesStorage defaultRender = app.getRendererRegistry().defaultRender(); - MapRenderRepositories maps = app.getResourceManager().getRenderer(); - RenderingRuleSearchRequest currentSearchRequest = - maps.getSearchRequestWithAppliedCustomRules(currentRenderer, nightMode); - RenderingRuleSearchRequest defaultSearchRequest = - maps.getSearchRequestWithAppliedCustomRules(defaultRender, nightMode); - return RouteStatisticsHelper.calculateRouteStatistic(route, currentRenderer, - defaultRender, currentSearchRequest, defaultSearchRequest); + return RouteDetailsFragment.calculateRouteStatistics(app, route, nightMode); } private boolean isRouteCalculating() { - return mtf.isProgressBarVisible(); + return fragment.isProgressBarVisible(); } private static class GraphType { private String title; private boolean isCustom; private boolean canBeCalculated; - private Object data; + private ChartData graphData; - public GraphType(String title, boolean isCustom, boolean canBeCalculated, Object data) { + public GraphType(String title, boolean isCustom, boolean canBeCalculated, ChartData graphData) { this.title = title; this.isCustom = isCustom; this.canBeCalculated = canBeCalculated; - this.data = data; + this.graphData = graphData; } public String getTitle() { @@ -394,11 +386,11 @@ public class MtGraphFragment extends BaseCard } public boolean hasData() { - return getData() != null; + return getGraphData() != null; } - public Object getData() { - return data; + public ChartData getGraphData() { + return graphData; } } } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index 99ee2a6ef9..c40e7b70ca 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -127,6 +127,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private Snackbar snackbar; private String fileName; + private AdditionalInfoType currentAdditionalInfoType; + private boolean wasCollapseButtonVisible; private boolean progressBarVisible; private boolean additionalInfoExpanded; @@ -141,7 +143,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private boolean portrait; private boolean nightMode; private int cachedMapPosition; - private AdditionalInfoType currentAdditionalInfoType; private MeasurementEditingContext editingCtx = new MeasurementEditingContext(); @@ -514,17 +515,25 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private void changeAdditionalInfoType(@NonNull AdditionalInfoType type) { if (!additionalInfoExpanded || !isCurrentAdditionalInfoType(type)) { + MapActivity ma = getMapActivity(); + if (ma == null) return; currentAdditionalInfoType = type; updateUpDownBtn(); - OsmandApplication app = getMyApplication(); - if (AdditionalInfoType.POINTS.equals(type)) { + OsmandApplication app = ma.getMyApplication(); + BaseCard additionalInfoCard = null; + if (AdditionalInfoType.POINTS == type) { + additionalInfoCard = new PointsCard(ma, this); UiUtilities.updateCustomRadioButtons(app, customRadioButton, nightMode, START); - } else if (AdditionalInfoType.GRAPH.equals(type)) { + } else if (AdditionalInfoType.GRAPH == type) { + additionalInfoCard = new GraphsCard(ma, this); UiUtilities.updateCustomRadioButtons(app, customRadioButton, nightMode, END); - } else { - return; } - setAdditionalInfoCard(type); + if (additionalInfoCard != null) { + visibleAdditionalInfoCard = additionalInfoCard; + additionalInfoCardsContainer.removeAllViews(); + additionalInfoCardsContainer.addView(additionalInfoCard.build(ma)); + additionalInfoExpanded = true; + } } } @@ -1477,25 +1486,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - private void setAdditionalInfoCard(AdditionalInfoType type) { - MapActivity ma = getMapActivity(); - if (ma == null) return; - - BaseCard additionalInfoCard = null; - if (type.equals(AdditionalInfoType.POINTS)) { - additionalInfoCard = new MtPointsFragment(ma, this); - } else if (type.equals(AdditionalInfoType.GRAPH)) { - additionalInfoCard = new MtGraphFragment(ma, this); - } - - if (additionalInfoCard != null) { - visibleAdditionalInfoCard = additionalInfoCard; - additionalInfoCardsContainer.removeAllViews(); - additionalInfoCardsContainer.addView(additionalInfoCard.build(ma)); - additionalInfoExpanded = true; - } - } - private void collapseAdditionalInfoIfNoPointsEnough() { MeasurementToolLayer measurementLayer = getMeasurementLayer(); if (measurementLayer != null) { @@ -1515,7 +1505,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route setMapPosition(OsmandSettings.CENTER_CONSTANT); } - public void setMapPosition(int position) { + private void setMapPosition(int position) { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { mapActivity.getMapView().setMapPosition(position); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java similarity index 68% rename from OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java rename to OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java index c859d9b84d..4b0117bd42 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MtPointsFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java @@ -7,21 +7,19 @@ import androidx.recyclerview.widget.RecyclerView; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.measurementtool.MeasurementToolFragment.OnUpdateAdditionalInfoListener; import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback; -public class MtPointsFragment extends BaseCard - implements MeasurementToolFragment.OnUpdateAdditionalInfoListener { +public class PointsCard extends BaseCard implements OnUpdateAdditionalInfoListener { private MeasurementToolAdapter adapter; - private MeasurementEditingContext editingCtx; - private RecyclerView pointsRv; - private MeasurementToolFragment mtf; + private MeasurementToolFragment fragment; - public MtPointsFragment(@NonNull MapActivity mapActivity, MeasurementToolFragment mtf) { + public PointsCard(@NonNull MapActivity mapActivity, MeasurementToolFragment fragment) { super(mapActivity); - this.mtf = mtf; + this.fragment = fragment; } @Override @@ -36,14 +34,14 @@ public class MtPointsFragment extends BaseCard @Override protected void updateContent() { - editingCtx = mtf.getEditingCtx(); + MeasurementEditingContext editingCtx = fragment.getEditingCtx(); final GpxData gpxData = editingCtx.getGpxData(); adapter = new MeasurementToolAdapter(mapActivity, editingCtx.getPoints(), gpxData != null ? gpxData.getActionType() : null); - pointsRv = view.findViewById(R.id.measure_points_recycler_view); + RecyclerView pointsRv = view.findViewById(R.id.measure_points_recycler_view); ItemTouchHelper touchHelper = new ItemTouchHelper(new ReorderItemTouchHelperCallback(adapter)); touchHelper.attachToRecyclerView(pointsRv); - adapter.setAdapterListener(mtf.createMeasurementAdapterListener(touchHelper)); + adapter.setAdapterListener(fragment.createMeasurementAdapterListener(touchHelper)); pointsRv.setLayoutManager(new LinearLayoutManager(app)); pointsRv.setAdapter(adapter); } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java index fcab4d6578..1f29dfd1b7 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteDetailsFragment.java @@ -345,18 +345,9 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT List route = app.getRoutingHelper().getRoute().getOriginalRoute(); if (route != null) { - RenderingRulesStorage currentRenderer = app.getRendererRegistry().getCurrentSelectedRenderer(); - RenderingRulesStorage defaultRender = app.getRendererRegistry().defaultRender(); - - MapRenderRepositories maps = app.getResourceManager().getRenderer(); - RenderingRuleSearchRequest currentSearchRequest = maps.getSearchRequestWithAppliedCustomRules(currentRenderer, isNightMode()); - RenderingRuleSearchRequest defaultSearchRequest = maps.getSearchRequestWithAppliedCustomRules(defaultRender, isNightMode()); - - List routeStatistics = RouteStatisticsHelper.calculateRouteStatistic(route, - currentRenderer, defaultRender, currentSearchRequest, defaultSearchRequest); + List routeStatistics = calculateRouteStatistics(app, route, isNightMode()); GPXTrackAnalysis analysis = gpx.getAnalysis(0); - for (RouteStatistics statistic : routeStatistics) { RouteInfoCard routeClassCard = new RouteInfoCard(mapActivity, statistic, analysis); addRouteCard(cardsContainer, routeClassCard); @@ -375,6 +366,20 @@ public class RouteDetailsFragment extends ContextMenuFragment implements PublicT } } + public static List calculateRouteStatistics(OsmandApplication app, + List route, + boolean nightMode) { + RenderingRulesStorage currentRenderer = app.getRendererRegistry().getCurrentSelectedRenderer(); + RenderingRulesStorage defaultRender = app.getRendererRegistry().defaultRender(); + MapRenderRepositories maps = app.getResourceManager().getRenderer(); + RenderingRuleSearchRequest currentSearchRequest = + maps.getSearchRequestWithAppliedCustomRules(currentRenderer, nightMode); + RenderingRuleSearchRequest defaultSearchRequest = + maps.getSearchRequestWithAppliedCustomRules(defaultRender, nightMode); + return RouteStatisticsHelper.calculateRouteStatistic(route, currentRenderer, + defaultRender, currentSearchRequest, defaultSearchRequest); + } + @Override protected void calculateLayout(View view, boolean initLayout) { super.calculateLayout(view, initLayout);