Plan Route Add Graphs initial commit
This commit is contained in:
parent
f39e7dd753
commit
6941d45516
15 changed files with 994 additions and 182 deletions
|
@ -130,33 +130,25 @@
|
|||
tools:text="@string/add_point_after"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
<LinearLayout
|
||||
android:id="@+id/additional_info_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/dashboard_divider"/>
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone" >
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/points_list_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/measurement_tool_points_list_container_height"
|
||||
android:background="@color/activity_background_color_dark"
|
||||
android:visibility="gone">
|
||||
<include layout="@layout/custom_radio_buttons" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/measure_points_recycler_view"
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
android:layout_height="@dimen/content_padding_small" />
|
||||
|
||||
<include layout="@layout/card_bottom_divider"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
<FrameLayout
|
||||
android:id="@+id/fragmentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="5dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:alpha="0.5"
|
||||
android:scaleType="fitXY"
|
||||
osmand:srcCompat="@drawable/bg_shadow_onmap"/>
|
||||
</FrameLayout>
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/measure_mode_controls"
|
||||
|
|
111
OsmAnd/res/layout/fragment_measurement_tool_graph.xml
Normal file
111
OsmAnd/res/layout/fragment_measurement_tool_graph.xml
Normal file
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/graph_types_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/content_padding_small"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
tools:itemCount="3"
|
||||
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/point_editor_icon_category_item"
|
||||
tools:orientation="horizontal" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/common_graphs_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.github.mikephil.charting.charts.LineChart
|
||||
android:id="@+id/line_chart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/route_info_line_chart_height"
|
||||
android:layout_gravity="center_vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/custom_graphs_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.github.mikephil.charting.charts.HorizontalBarChart
|
||||
android:id="@+id/horizontal_chart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/route_info_chart_height" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/route_items"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/route_info_legend_padding"
|
||||
android:paddingBottom="@dimen/route_info_legend_padding" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/message_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginTop="@dimen/content_padding_small"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding_small"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/message_icon"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:tint="?attr/default_icon_color"
|
||||
tools:src="@drawable/ic_action_info_dark" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/message_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:lineSpacingMultiplier="@dimen/bottom_sheet_text_spacing_multiplier"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="Altitude data available only on the roads, you need to calculate a route using “Route between points” to get it." />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="5dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:alpha="0.5"
|
||||
android:scaleType="fitXY"
|
||||
osmand:srcCompat="@drawable/bg_shadow_onmap" />
|
||||
|
||||
</LinearLayout>
|
24
OsmAnd/res/layout/fragment_measurement_tool_points_list.xml
Normal file
24
OsmAnd/res/layout/fragment_measurement_tool_points_list.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/points_list_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/measurement_tool_points_list_container_height"
|
||||
android:background="?attr/activity_background_color">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/measure_points_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<include layout="@layout/card_bottom_divider" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="5dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:alpha="0.5"
|
||||
android:scaleType="fitXY"
|
||||
osmand:srcCompat="@drawable/bg_shadow_onmap" />
|
||||
|
||||
</FrameLayout>
|
|
@ -324,6 +324,7 @@
|
|||
<dimen name="route_info_legend_padding">8dp</dimen>
|
||||
<dimen name="route_info_warning_padding">18dp</dimen>
|
||||
<dimen name="route_info_chart_height">71dp</dimen>
|
||||
<dimen name="route_info_line_chart_height">120dp</dimen>
|
||||
<dimen name="route_info_toolbar_button_size">40dp</dimen>
|
||||
<dimen name="route_info_control_buttons_height">48dp</dimen>
|
||||
<dimen name="route_info_button_bg_line_radius">18dp</dimen>
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
Thx - Hardy
|
||||
|
||||
-->
|
||||
<string name="message_need_calculate_route_for_show_graph">Altitude data available only on the roads, you need to calculate a route using “Route between points” to get it.</string>
|
||||
<string name="shared_string_graph">Graph</string>
|
||||
<string name="osm_edit_logout_success">Logout successful</string>
|
||||
<string name="clear_osm_token">Clear OpenStreetMap OAuth token</string>
|
||||
<string name="perform_oauth_authorization">Log in via OAuth</string>
|
||||
|
|
|
@ -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 <T> void registerListPreference(OsmandPreference<T> b, PreferenceGroup screen, String[] names, T[] values) {
|
||||
ListPreference p = (ListPreference) screen.findPreference(b.getId());
|
||||
prepareListPreference(b, names, values, p);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<HorizontalSelectionAdapter.ItemViewHolder> {
|
||||
|
||||
private List<String> items;
|
||||
public static int INVALID_ID = -1;
|
||||
|
||||
private List<HorizontalSelectionItem> 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<String> items) {
|
||||
public void setTitledItems(List<String> titles) {
|
||||
List<HorizontalSelectionItem> items = new ArrayList<>();
|
||||
for (String title : titles) {
|
||||
items.add(new HorizontalSelectionItem(title));
|
||||
}
|
||||
setItems(items);
|
||||
}
|
||||
|
||||
public void setItems(List<HorizontalSelectionItem> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
|
@ -44,23 +54,30 @@ public class HorizontalSelectionAdapter extends RecyclerView.Adapter<HorizontalS
|
|||
@Override
|
||||
public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view;
|
||||
view = UiUtilities.getInflater(parent.getContext(), nightMode).inflate(R.layout.point_editor_icon_category_item,
|
||||
parent, false);
|
||||
view = UiUtilities.getInflater(parent.getContext(), nightMode)
|
||||
.inflate(R.layout.point_editor_icon_category_item, parent, false);
|
||||
return new ItemViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ItemViewHolder holder, final int position) {
|
||||
final String item = items.get(holder.getAdapterPosition());
|
||||
final HorizontalSelectionItem item = items.get(holder.getAdapterPosition());
|
||||
TextView textView = holder.buttonText;
|
||||
int activeColorResId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
|
||||
if (item.equals(selectedItem)) {
|
||||
if (item.equals(selectedItem) && item.isEnabled()) {
|
||||
AndroidUtils.setBackground(holder.button, app.getUIUtilities().getPaintedIcon(
|
||||
R.drawable.bg_select_icon_group_button, ContextCompat.getColor(app, activeColorResId)));
|
||||
textView.setTextColor(ContextCompat.getColor(app, R.color.color_white));
|
||||
} else {
|
||||
textView.setTextColor(ContextCompat.getColor(app,
|
||||
nightMode ? R.color.active_color_primary_dark : R.color.preference_category_title));
|
||||
if (!item.isEnabled()) {
|
||||
int inactiveColorId = nightMode ?
|
||||
R.color.icon_color_default_dark : R.color.icon_color_secondary_light;
|
||||
textView.setTextColor(ContextCompat.getColor(app, inactiveColorId));
|
||||
} else {
|
||||
int defaultTitleColorId = nightMode ? R.color.active_color_primary_dark : R.color.preference_category_title;
|
||||
textView.setTextColor(ContextCompat.getColor(app,
|
||||
item.getTitleColorId() != INVALID_ID ? item.getTitleColorId() : defaultTitleColorId));
|
||||
}
|
||||
GradientDrawable buttonBackground = (GradientDrawable) AppCompatResources.getDrawable(app,
|
||||
R.drawable.bg_select_icon_group_button).mutate();
|
||||
buttonBackground.setStroke(AndroidUtils.dpToPx(app, 1), ContextCompat.getColor(app,
|
||||
|
@ -69,8 +86,9 @@ public class HorizontalSelectionAdapter extends RecyclerView.Adapter<HorizontalS
|
|||
buttonBackground.setColor(ContextCompat.getColor(app, R.color.color_transparent));
|
||||
AndroidUtils.setBackground(holder.button, buttonBackground);
|
||||
}
|
||||
textView.setText(capitalizeFirstLetter(item));
|
||||
textView.setText(capitalizeFirstLetter(item.title));
|
||||
textView.requestLayout();
|
||||
holder.button.setEnabled(item.isEnabled());
|
||||
holder.button.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -96,18 +114,32 @@ public class HorizontalSelectionAdapter extends RecyclerView.Adapter<HorizontalS
|
|||
return items.indexOf(name);
|
||||
}
|
||||
|
||||
public void setSelectedItem(String selectedItem) {
|
||||
public void setSelectedItemByTitle(String selectedItemTitle) {
|
||||
HorizontalSelectionItem selectedItem = getItemByTitle(selectedItemTitle);
|
||||
setSelectedItem(selectedItem);
|
||||
}
|
||||
|
||||
public void setSelectedItem(HorizontalSelectionItem selectedItem) {
|
||||
this.selectedItem = selectedItem;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public HorizontalSelectionItem getItemByTitle(String title) {
|
||||
for (HorizontalSelectionItem item : items) {
|
||||
if (title.equals(item.getTitle())) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setListener(HorizontalSelectionAdapterListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public interface HorizontalSelectionAdapterListener {
|
||||
|
||||
void onItemSelected(String item);
|
||||
void onItemSelected(HorizontalSelectionItem item);
|
||||
}
|
||||
|
||||
static class ItemViewHolder extends RecyclerView.ViewHolder {
|
||||
|
@ -120,4 +152,44 @@ public class HorizontalSelectionAdapter extends RecyclerView.Adapter<HorizontalS
|
|||
button = itemView.findViewById(R.id.button);
|
||||
}
|
||||
}
|
||||
|
||||
public static class HorizontalSelectionItem {
|
||||
private String title;
|
||||
private boolean enabled = true;
|
||||
private int titleColorId = INVALID_ID;
|
||||
private Object object;
|
||||
|
||||
public HorizontalSelectionItem(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public HorizontalSelectionItem(String title, Object object) {
|
||||
this.title = title;
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public void setTitleColorId(int titleColorId) {
|
||||
this.titleColorId = titleColorId;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public int getTitleColorId() {
|
||||
return titleColorId;
|
||||
}
|
||||
|
||||
public Object getObject() {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -313,6 +313,72 @@ public class MeasurementEditingContext {
|
|||
return before.points.size();
|
||||
}
|
||||
|
||||
public List<RouteSegmentResult> getAllRouteSegments() {
|
||||
class TmpRouteSegmentData {
|
||||
private WptPt start;
|
||||
private WptPt end;
|
||||
private List<RouteSegmentResult> routeSegments;
|
||||
|
||||
public TmpRouteSegmentData(WptPt start, WptPt end,
|
||||
List<RouteSegmentResult> 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<TmpRouteSegmentData> fullList = new ArrayList<>();
|
||||
for (Map.Entry<Pair<WptPt, WptPt>, 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<WptPt> points = new ArrayList<>();
|
||||
points.addAll(before.points);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
414
OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java
Normal file
414
OsmAnd/src/net/osmand/plus/measurementtool/MtGraphFragment.java
Normal file
|
@ -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<GraphType, Object> 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<GraphType> commonTypes;
|
||||
private static List<GraphType> customTypes;
|
||||
|
||||
static List<GraphType> getCommonTypes() {
|
||||
if (commonTypes == null) {
|
||||
prepareLists();
|
||||
}
|
||||
return commonTypes;
|
||||
}
|
||||
|
||||
static List<GraphType> 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<HorizontalSelectionItem> 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<ILineDataSet> 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<RouteSegmentResult> routeSegments = editingCtx.getAllRouteSegments();
|
||||
List<RouteStatistics> 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> 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<ILineDataSet> getDataSets(GraphType graphType, LineChart chart, GPXTrackAnalysis analysis) {
|
||||
List<ILineDataSet> 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<GpxUiHelper.OrderedLineDataSet> 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<GpxUiHelper.OrderedLineDataSet>() {
|
||||
@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<RouteStatistics> calculateRouteStatistics(List<RouteSegmentResult> 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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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<GPXInfo> items = gpxInfoCategories.get(item);
|
||||
public void onItemSelected(HorizontalSelectionAdapter.HorizontalSelectionItem item) {
|
||||
selectedCategory = item.getTitle();
|
||||
List<GPXInfo> items = gpxInfoCategories.get(selectedCategory);
|
||||
tracksAdapter.setShowFolderName(showFoldersName());
|
||||
tracksAdapter.setGpxInfoList(items != null ? items : new ArrayList<GPXInfo>());
|
||||
tracksAdapter.notifyDataSetChanged();
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue