Add split interval card and bottom sheet
This commit is contained in:
parent
e5c61ddc8b
commit
1eb20f7dfa
9 changed files with 745 additions and 76 deletions
45
OsmAnd/res/layout/track_coloring_card.xml
Normal file
45
OsmAnd/res/layout/track_coloring_card.xml
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
android:id="@+id/header_view"
|
||||
layout="@layout/bottom_sheet_item_with_right_descr" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="@dimen/context_menu_padding_margin_tiny"
|
||||
android:paddingBottom="@dimen/content_padding">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/content_padding_half"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
tools:itemCount="3"
|
||||
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/point_editor_group_select_item"
|
||||
tools:orientation="horizontal" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<net.osmand.plus.widgets.FlowLayout
|
||||
android:id="@+id/select_color"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding_small"
|
||||
android:layout_marginLeft="@dimen/content_padding_small"
|
||||
android:layout_marginTop="@dimen/context_menu_padding_margin_tiny"
|
||||
android:layout_marginBottom="@dimen/content_padding_half" />
|
||||
|
||||
</LinearLayout>
|
169
OsmAnd/res/layout/track_split_interval.xml
Normal file
169
OsmAnd/res/layout/track_split_interval.xml
Normal file
|
@ -0,0 +1,169 @@
|
|||
<?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="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottom_btns"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginTop="@dimen/text_margin_small"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding_small"
|
||||
android:background="?attr/btn_bg_border_inactive"
|
||||
android:baselineAligned="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/left_btn_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/left_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:text="@string/shared_string_none"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/center_btn_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/center_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:text="@string/shared_string_time"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/right_btn_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/right_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:text="@string/distance"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/slider_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:text="@string/gpx_split_interval"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/split_value_tv"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="end"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
tools:text="@string/shared_string_max" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/split_slider"
|
||||
style="@style/Widget.Styled.Slider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:stepSize="1" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/split_value_min"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
tools:text="3" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/split_value_max"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="end"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
tools:text="19" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/split_interval_none_descr"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:lineSpacingExtra="@dimen/line_spacing_extra_description"
|
||||
android:text="@string/gpx_split_interval_none_descr"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size" />
|
||||
|
||||
</LinearLayout>
|
|
@ -178,7 +178,7 @@ public class TrackActivity extends TabActivity {
|
|||
}
|
||||
}
|
||||
|
||||
public List<GpxDisplayGroup> getGpxFile(boolean useDisplayGroups) {
|
||||
public List<GpxDisplayGroup> getGpxDisplayGroups(boolean useDisplayGroups) {
|
||||
if (gpxFile == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
|
|
@ -380,7 +380,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
private List<GpxDisplayGroup> filterGroups(boolean useDisplayGroups) {
|
||||
List<GpxDisplayGroup> groups = new ArrayList<>();
|
||||
if (getTrackActivity() != null) {
|
||||
List<GpxDisplayGroup> result = getTrackActivity().getGpxFile(useDisplayGroups);
|
||||
List<GpxDisplayGroup> result = getTrackActivity().getGpxDisplayGroups(useDisplayGroups);
|
||||
for (GpxDisplayGroup group : result) {
|
||||
boolean add = hasFilterType(group.getType());
|
||||
if (add) {
|
||||
|
@ -397,7 +397,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
TrackActivity trackActivity = getTrackActivity();
|
||||
List<GpxDisplayItem> splitSegments = new ArrayList<>();
|
||||
if (trackActivity != null) {
|
||||
List<GpxDisplayGroup> result = trackActivity.getGpxFile(true);
|
||||
List<GpxDisplayGroup> result = trackActivity.getGpxDisplayGroups(true);
|
||||
if (result != null && result.size() > 0 && trkSegment.points.size() > 0) {
|
||||
for (GpxDisplayGroup group : result) {
|
||||
splitSegments.addAll(collectDisplayItemsFromGroup(group));
|
||||
|
|
76
OsmAnd/src/net/osmand/plus/myplaces/SplitTrackAsyncTask.java
Normal file
76
OsmAnd/src/net/osmand/plus/myplaces/SplitTrackAsyncTask.java
Normal file
|
@ -0,0 +1,76 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.plus.GpxSelectionHelper;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.track.GpxSplitType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SplitTrackAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private OsmandApplication app;
|
||||
private GpxSplitType gpxSplitType;
|
||||
private List<GpxDisplayGroup> groups;
|
||||
private SplitTrackListener splitTrackListener;
|
||||
|
||||
private boolean joinSegments;
|
||||
private int timeSplitInterval;
|
||||
private double distanceSplitInterval;
|
||||
|
||||
public SplitTrackAsyncTask(@NonNull OsmandApplication app,
|
||||
@NonNull GpxSplitType gpxSplitType,
|
||||
@NonNull List<GpxDisplayGroup> groups,
|
||||
@Nullable SplitTrackListener splitTrackListener,
|
||||
boolean joinSegments,
|
||||
int timeSplitInterval,
|
||||
double distanceSplitInterval) {
|
||||
this.app = app;
|
||||
this.groups = groups;
|
||||
this.gpxSplitType = gpxSplitType;
|
||||
this.splitTrackListener = splitTrackListener;
|
||||
this.joinSegments = joinSegments;
|
||||
this.timeSplitInterval = timeSplitInterval;
|
||||
this.distanceSplitInterval = distanceSplitInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (splitTrackListener != null) {
|
||||
splitTrackListener.trackSplittingStarted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
for (GpxSelectionHelper.GpxDisplayGroup model : groups) {
|
||||
if (gpxSplitType == GpxSplitType.NO_SPLIT) {
|
||||
model.noSplit(app);
|
||||
} else if (gpxSplitType == GpxSplitType.DISTANCE && distanceSplitInterval > 0) {
|
||||
model.splitByDistance(app, distanceSplitInterval, joinSegments);
|
||||
} else if (gpxSplitType == GpxSplitType.TIME && timeSplitInterval > 0) {
|
||||
model.splitByTime(app, timeSplitInterval, joinSegments);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
if (splitTrackListener != null) {
|
||||
splitTrackListener.trackSplittingFinished();
|
||||
}
|
||||
}
|
||||
|
||||
public interface SplitTrackListener {
|
||||
|
||||
void trackSplittingStarted();
|
||||
|
||||
void trackSplittingFinished();
|
||||
}
|
||||
}
|
|
@ -55,6 +55,7 @@ import net.osmand.plus.R;
|
|||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.TrackActivity;
|
||||
import net.osmand.plus.measurementtool.NewGpxData;
|
||||
import net.osmand.plus.myplaces.SplitTrackAsyncTask.SplitTrackListener;
|
||||
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.track.GpxSplitType;
|
||||
|
@ -64,7 +65,6 @@ import net.osmand.plus.wikivoyage.WikivoyageUtils;
|
|||
import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment;
|
||||
import net.osmand.plus.wikivoyage.data.TravelArticle;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -639,7 +639,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
List<GpxDisplayGroup> groups = new ArrayList<>();
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
List<GpxDisplayGroup> result = activity.getGpxFile(useDisplayGroups);
|
||||
List<GpxDisplayGroup> result = activity.getGpxDisplayGroups(useDisplayGroups);
|
||||
for (GpxDisplayGroup group : result) {
|
||||
boolean add = hasFilterType(group.getType());
|
||||
if (add) {
|
||||
|
@ -738,14 +738,55 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
addOptionSplit(3600, false, groups);
|
||||
}
|
||||
|
||||
private void updateSplit(@NonNull List<GpxDisplayGroup> groups, @Nullable SelectedGpxFile sf) {
|
||||
private void updateSplit(@NonNull List<GpxDisplayGroup> groups, @Nullable final SelectedGpxFile selectedGpx) {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
new SplitTrackAsyncTask(activity, this, sf, groups)
|
||||
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
|
||||
GpxSplitType gpxSplitType = getGpxSplitType();
|
||||
if (gpxSplitType != null) {
|
||||
int timeSplit = this.timeSplit.get(selectedSplitInterval);
|
||||
double distanceSplit = this.distanceSplit.get(selectedSplitInterval);
|
||||
|
||||
SplitTrackListener splitTrackListener = new SplitTrackListener() {
|
||||
|
||||
@Override
|
||||
public void trackSplittingStarted() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
activity.setSupportProgressBarIndeterminateVisibility(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackSplittingFinished() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
if (AndroidUtils.isActivityNotDestroyed(activity)) {
|
||||
activity.setSupportProgressBarIndeterminateVisibility(false);
|
||||
}
|
||||
if (selectedGpx != null) {
|
||||
List<GpxDisplayGroup> groups = getDisplayGroups();
|
||||
selectedGpx.setDisplayGroups(groups, app);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
new SplitTrackAsyncTask(app, gpxSplitType, groups, splitTrackListener, activity.isJoinSegments(),
|
||||
timeSplit, distanceSplit).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GpxSplitType getGpxSplitType() {
|
||||
if (selectedSplitInterval == 0) {
|
||||
return GpxSplitType.NO_SPLIT;
|
||||
} else if (distanceSplit.get(selectedSplitInterval) > 0) {
|
||||
return GpxSplitType.DISTANCE;
|
||||
} else if (timeSplit.get(selectedSplitInterval) > 0) {
|
||||
return GpxSplitType.TIME;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addOptionSplit(int value, boolean distance, @NonNull List<GpxDisplayGroup> model) {
|
||||
if (model.size() > 0) {
|
||||
if (distance) {
|
||||
|
@ -905,70 +946,4 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
public void drawTrackBitmap(Bitmap bitmap) {
|
||||
imageView.setImageDrawable(new BitmapDrawable(app.getResources(), bitmap));
|
||||
}
|
||||
|
||||
private static class SplitTrackAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||
private final SelectedGpxFile selectedGpx;
|
||||
private OsmandApplication app;
|
||||
private final WeakReference<TrackActivity> activityRef;
|
||||
private final WeakReference<TrackActivityFragmentAdapter> fragmentAdapterRef;
|
||||
private final List<GpxDisplayGroup> groups;
|
||||
|
||||
private List<Double> distanceSplit;
|
||||
private TIntArrayList timeSplit;
|
||||
private int selectedSplitInterval;
|
||||
private boolean joinSegments;
|
||||
|
||||
SplitTrackAsyncTask(@NonNull TrackActivity activity,
|
||||
@NonNull TrackActivityFragmentAdapter fragmentAdapter,
|
||||
@Nullable SelectedGpxFile selectedGpx,
|
||||
@NonNull List<GpxDisplayGroup> groups) {
|
||||
activityRef = new WeakReference<>(activity);
|
||||
fragmentAdapterRef = new WeakReference<>(fragmentAdapter);
|
||||
app = activity.getMyApplication();
|
||||
this.selectedGpx = selectedGpx;
|
||||
this.groups = groups;
|
||||
|
||||
selectedSplitInterval = fragmentAdapter.selectedSplitInterval;
|
||||
distanceSplit = fragmentAdapter.distanceSplit;
|
||||
timeSplit = fragmentAdapter.timeSplit;
|
||||
joinSegments = activity.isJoinSegments();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
TrackActivity activity = activityRef.get();
|
||||
if (activity != null) {
|
||||
activity.setSupportProgressBarIndeterminateVisibility(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
TrackActivity activity = activityRef.get();
|
||||
TrackActivityFragmentAdapter fragment = fragmentAdapterRef.get();
|
||||
if (activity != null && fragment != null) {
|
||||
if (!activity.isFinishing()) {
|
||||
activity.setSupportProgressBarIndeterminateVisibility(false);
|
||||
}
|
||||
if (selectedGpx != null) {
|
||||
List<GpxDisplayGroup> groups = fragment.getDisplayGroups();
|
||||
selectedGpx.setDisplayGroups(groups, app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
for (GpxDisplayGroup model : groups) {
|
||||
if (selectedSplitInterval == 0) {
|
||||
model.noSplit(app);
|
||||
} else if (distanceSplit.get(selectedSplitInterval) > 0) {
|
||||
model.splitByDistance(app, distanceSplit.get(selectedSplitInterval), joinSegments);
|
||||
} else if (timeSplit.get(selectedSplitInterval) > 0) {
|
||||
model.splitByTime(app, timeSplit.get(selectedSplitInterval), joinSegments);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
358
OsmAnd/src/net/osmand/plus/track/SplitIntervalBottomSheet.java
Normal file
358
OsmAnd/src/net/osmand/plus/track/SplitIntervalBottomSheet.java
Normal file
|
@ -0,0 +1,358 @@
|
|||
package net.osmand.plus.track;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.google.android.material.slider.Slider;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.GPXDatabase.GpxDataItem;
|
||||
import net.osmand.plus.GpxSelectionHelper;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.myplaces.SplitTrackAsyncTask;
|
||||
import net.osmand.plus.myplaces.SplitTrackAsyncTask.SplitTrackListener;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.osmand.plus.track.TrackAppearanceFragment.SELECTED_TRACK_FILE_PATH;
|
||||
|
||||
public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
|
||||
|
||||
public static final String TAG = SplitIntervalBottomSheet.class.getSimpleName();
|
||||
|
||||
private static final Log log = PlatformUtil.getLog(SplitIntervalBottomSheet.class);
|
||||
|
||||
public static final String SELECTED_TRACK_SPLIT_TYPE = "selected_track_split_type";
|
||||
public static final String SELECTED_TIME_SPLIT_INTERVAL = "selected_time_split_interval";
|
||||
public static final String SELECTED_DISTANCE_SPLIT_INTERVAL = "selected_distance_split_interval";
|
||||
|
||||
|
||||
private OsmandApplication app;
|
||||
private SelectedGpxFile selectedGpxFile;
|
||||
|
||||
private Map<String, Integer> timeSplitOptions = new LinkedHashMap<>();
|
||||
private Map<String, Double> distanceSplitOptions = new LinkedHashMap<>();
|
||||
|
||||
private int selectedTimeSplitInterval;
|
||||
private int selectedDistanceSplitInterval;
|
||||
private GpxSplitType selectedSplitType = GpxSplitType.NO_SPLIT;
|
||||
|
||||
private Slider slider;
|
||||
private View sliderContainer;
|
||||
private TextView splitValueMin;
|
||||
private TextView splitValueMax;
|
||||
private TextView selectedSplitValue;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
app = requiredMyApplication();
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
if (savedInstanceState != null) {
|
||||
String gpxFilePath = savedInstanceState.getString(SELECTED_TRACK_FILE_PATH);
|
||||
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
|
||||
prepareSplitIntervalOptions();
|
||||
|
||||
selectedTimeSplitInterval = savedInstanceState.getInt(SELECTED_TIME_SPLIT_INTERVAL);
|
||||
selectedDistanceSplitInterval = savedInstanceState.getInt(SELECTED_DISTANCE_SPLIT_INTERVAL);
|
||||
selectedSplitType = GpxSplitType.valueOf(savedInstanceState.getString(SELECTED_TRACK_SPLIT_TYPE));
|
||||
} else if (arguments != null) {
|
||||
String gpxFilePath = arguments.getString(SELECTED_TRACK_FILE_PATH);
|
||||
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
|
||||
prepareSplitIntervalOptions();
|
||||
updateSelectedSplitParams();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMenuItems(Bundle savedInstanceState) {
|
||||
items.add(new TitleItem(getString(R.string.gpx_split_interval)));
|
||||
items.add(new LongDescriptionItem(getString(R.string.gpx_split_interval_descr)));
|
||||
|
||||
LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode);
|
||||
View view = themedInflater.inflate(R.layout.track_split_interval, null);
|
||||
|
||||
sliderContainer = view.findViewById(R.id.slider_container);
|
||||
slider = sliderContainer.findViewById(R.id.split_slider);
|
||||
|
||||
splitValueMin = (TextView) view.findViewById(R.id.split_value_min);
|
||||
splitValueMax = (TextView) view.findViewById(R.id.split_value_max);
|
||||
selectedSplitValue = (TextView) view.findViewById(R.id.split_value_tv);
|
||||
|
||||
UiUtilities.setupSlider(slider, nightMode, null);
|
||||
|
||||
view.findViewById(R.id.left_btn_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
selectedSplitType = GpxSplitType.NO_SPLIT;
|
||||
updateSlider();
|
||||
}
|
||||
});
|
||||
view.findViewById(R.id.center_btn_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
selectedSplitType = GpxSplitType.TIME;
|
||||
updateSlider();
|
||||
}
|
||||
});
|
||||
view.findViewById(R.id.right_btn_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
selectedSplitType = GpxSplitType.DISTANCE;
|
||||
updateSlider();
|
||||
}
|
||||
});
|
||||
|
||||
SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder()
|
||||
.setCustomView(view)
|
||||
.create();
|
||||
items.add(titleItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(SELECTED_TIME_SPLIT_INTERVAL, selectedTimeSplitInterval);
|
||||
outState.putInt(SELECTED_DISTANCE_SPLIT_INTERVAL, selectedDistanceSplitInterval);
|
||||
outState.putString(SELECTED_TRACK_SPLIT_TYPE, selectedSplitType.name());
|
||||
outState.putString(SELECTED_TRACK_FILE_PATH, selectedGpxFile.getGpxFile().path);
|
||||
}
|
||||
|
||||
private void updateSelectedSplitParams() {
|
||||
GpxDataItem gpxDataItem = app.getGpxDbHelper().getItem(new File(selectedGpxFile.getGpxFile().path));
|
||||
if (gpxDataItem != null) {
|
||||
if (gpxDataItem.getSplitType() == GpxSplitType.DISTANCE.getType()) {
|
||||
selectedSplitType = GpxSplitType.DISTANCE;
|
||||
List<Double> splitOptions = new ArrayList<>(distanceSplitOptions.values());
|
||||
int index = splitOptions.indexOf(gpxDataItem.getSplitInterval());
|
||||
selectedDistanceSplitInterval = Math.max(index, 0);
|
||||
} else if (gpxDataItem.getSplitType() == GpxSplitType.TIME.getType()) {
|
||||
selectedSplitType = GpxSplitType.TIME;
|
||||
List<Integer> splitOptions = new ArrayList<>(timeSplitOptions.values());
|
||||
int index = splitOptions.indexOf((int) gpxDataItem.getSplitInterval());
|
||||
selectedTimeSplitInterval = Math.max(index, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareSplitIntervalOptions() {
|
||||
List<GpxDisplayGroup> groups = getDisplayGroups();
|
||||
addDistanceOptionSplit(30, groups); // 50 feet, 20 yards, 20 m
|
||||
addDistanceOptionSplit(60, groups); // 100 feet, 50 yards, 50 m
|
||||
addDistanceOptionSplit(150, groups); // 200 feet, 100 yards, 100 m
|
||||
addDistanceOptionSplit(300, groups); // 500 feet, 200 yards, 200 m
|
||||
addDistanceOptionSplit(600, groups); // 1000 feet, 500 yards, 500 m
|
||||
addDistanceOptionSplit(1500, groups); // 2000 feet, 1000 yards, 1 km
|
||||
addDistanceOptionSplit(3000, groups); // 1 mi, 2 km
|
||||
addDistanceOptionSplit(6000, groups); // 2 mi, 5 km
|
||||
addDistanceOptionSplit(15000, groups); // 5 mi, 10 km
|
||||
|
||||
addTimeOptionSplit(15, groups);
|
||||
addTimeOptionSplit(30, groups);
|
||||
addTimeOptionSplit(60, groups);
|
||||
addTimeOptionSplit(120, groups);
|
||||
addTimeOptionSplit(150, groups);
|
||||
addTimeOptionSplit(300, groups);
|
||||
addTimeOptionSplit(600, groups);
|
||||
addTimeOptionSplit(900, groups);
|
||||
addTimeOptionSplit(1800, groups);
|
||||
addTimeOptionSplit(3600, groups);
|
||||
}
|
||||
|
||||
private void addDistanceOptionSplit(int value, @NonNull List<GpxDisplayGroup> displayGroups) {
|
||||
if (displayGroups.size() > 0) {
|
||||
double dvalue = OsmAndFormatter.calculateRoundedDist(value, app);
|
||||
String formattedDist = OsmAndFormatter.getFormattedDistance((float) dvalue, app);
|
||||
distanceSplitOptions.put(formattedDist, dvalue);
|
||||
if (Math.abs(displayGroups.get(0).getSplitDistance() - dvalue) < 1) {
|
||||
selectedDistanceSplitInterval = distanceSplitOptions.size() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addTimeOptionSplit(int value, @NonNull List<GpxDisplayGroup> model) {
|
||||
if (model.size() > 0) {
|
||||
String time;
|
||||
if (value < 60) {
|
||||
time = value + " " + getString(R.string.int_seconds);
|
||||
} else if (value % 60 == 0) {
|
||||
time = (value / 60) + " " + getString(R.string.int_min);
|
||||
} else {
|
||||
time = (value / 60f) + " " + getString(R.string.int_min);
|
||||
}
|
||||
timeSplitOptions.put(time, value);
|
||||
if (model.get(0).getSplitTime() == value) {
|
||||
selectedTimeSplitInterval = timeSplitOptions.size() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
updateSlider();
|
||||
}
|
||||
|
||||
private void updateSlider() {
|
||||
if (selectedSplitType != GpxSplitType.NO_SPLIT) {
|
||||
slider.clearOnChangeListeners();
|
||||
if (selectedSplitType == GpxSplitType.TIME) {
|
||||
updateSliderTimeInterval();
|
||||
} else {
|
||||
updateSliderDistanceInterval();
|
||||
}
|
||||
AndroidUiHelper.updateVisibility(sliderContainer, true);
|
||||
} else {
|
||||
AndroidUiHelper.updateVisibility(sliderContainer, false);
|
||||
}
|
||||
setupHeightAndBackground(getView());
|
||||
}
|
||||
|
||||
private void updateSliderTimeInterval() {
|
||||
final List<String> splitOptions = new ArrayList<>(timeSplitOptions.keySet());
|
||||
updateSliderMinMaxValues(splitOptions);
|
||||
|
||||
slider.setValue(selectedTimeSplitInterval);
|
||||
slider.addOnChangeListener(new Slider.OnChangeListener() {
|
||||
@Override
|
||||
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
|
||||
if (fromUser) {
|
||||
selectedTimeSplitInterval = (int) value;
|
||||
selectedSplitValue.setText(splitOptions.get(selectedTimeSplitInterval));
|
||||
}
|
||||
}
|
||||
});
|
||||
selectedSplitValue.setText(splitOptions.get(selectedTimeSplitInterval));
|
||||
}
|
||||
|
||||
private void updateSliderDistanceInterval() {
|
||||
final List<String> splitOptions = new ArrayList<>(distanceSplitOptions.keySet());
|
||||
updateSliderMinMaxValues(splitOptions);
|
||||
|
||||
slider.setValue(selectedDistanceSplitInterval);
|
||||
slider.addOnChangeListener(new Slider.OnChangeListener() {
|
||||
@Override
|
||||
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
|
||||
if (fromUser) {
|
||||
selectedDistanceSplitInterval = (int) value;
|
||||
selectedSplitValue.setText(splitOptions.get(selectedDistanceSplitInterval));
|
||||
}
|
||||
}
|
||||
});
|
||||
selectedSplitValue.setText(splitOptions.get(selectedDistanceSplitInterval));
|
||||
}
|
||||
|
||||
private void updateSliderMinMaxValues(List<String> splitOptions) {
|
||||
int valueFrom = 0;
|
||||
int valueTo = splitOptions.size() - 1;
|
||||
|
||||
slider.setValueTo(valueTo);
|
||||
slider.setValueFrom(valueFrom);
|
||||
splitValueMin.setText(splitOptions.get(valueFrom));
|
||||
splitValueMax.setText(splitOptions.get(valueTo));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRightBottomButtonTextId() {
|
||||
return R.string.shared_string_apply;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRightBottomButtonClick() {
|
||||
applySelectedSplit();
|
||||
updateSplitInDatabase();
|
||||
dismiss();
|
||||
}
|
||||
|
||||
private void updateSplitInDatabase() {
|
||||
double splitInterval = 0;
|
||||
if (selectedSplitType == GpxSplitType.NO_SPLIT) {
|
||||
splitInterval = 0;
|
||||
} else if (selectedSplitType == GpxSplitType.DISTANCE) {
|
||||
splitInterval = new ArrayList<>(distanceSplitOptions.values()).get(selectedDistanceSplitInterval);
|
||||
} else if (selectedSplitType == GpxSplitType.TIME) {
|
||||
splitInterval = new ArrayList<>(timeSplitOptions.values()).get(selectedTimeSplitInterval);
|
||||
}
|
||||
GpxDataItem gpxDataItem = app.getGpxDbHelper().getItem(new File(selectedGpxFile.getGpxFile().path));
|
||||
if (gpxDataItem != null) {
|
||||
app.getGpxDbHelper().updateSplit(gpxDataItem, selectedSplitType, splitInterval);
|
||||
}
|
||||
}
|
||||
|
||||
private void applySelectedSplit() {
|
||||
int timeSplit = new ArrayList<>(timeSplitOptions.values()).get(selectedTimeSplitInterval);
|
||||
double distanceSplit = new ArrayList<>(distanceSplitOptions.values()).get(selectedDistanceSplitInterval);
|
||||
|
||||
SplitTrackListener splitTrackListener = new SplitTrackListener() {
|
||||
|
||||
@Override
|
||||
public void trackSplittingStarted() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackSplittingFinished() {
|
||||
if (selectedGpxFile != null) {
|
||||
List<GpxDisplayGroup> groups = getDisplayGroups();
|
||||
selectedGpxFile.setDisplayGroups(groups, app);
|
||||
}
|
||||
}
|
||||
};
|
||||
List<GpxDisplayGroup> groups = selectedGpxFile.getDisplayGroups(app);
|
||||
GpxDataItem gpxDataItem = app.getGpxDbHelper().getItem(new File(selectedGpxFile.getGpxFile().path));
|
||||
boolean isJoinSegments = gpxDataItem != null && gpxDataItem.isJoinSegments();
|
||||
|
||||
new SplitTrackAsyncTask(app, selectedSplitType, groups, splitTrackListener, isJoinSegments,
|
||||
timeSplit, distanceSplit).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<GpxDisplayGroup> getDisplayGroups() {
|
||||
List<GpxDisplayGroup> groups = new ArrayList<>();
|
||||
for (GpxDisplayGroup group : selectedGpxFile.getDisplayGroups(app)) {
|
||||
if (GpxSelectionHelper.GpxDisplayItemType.TRACK_SEGMENT == group.getType()) {
|
||||
groups.add(group);
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
public static void showInstance(@NonNull FragmentManager fragmentManager, SelectedGpxFile selectedGpxFile) {
|
||||
try {
|
||||
if (fragmentManager.findFragmentByTag(SplitIntervalBottomSheet.TAG) == null) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(SELECTED_TRACK_FILE_PATH, selectedGpxFile.getGpxFile().path);
|
||||
|
||||
SplitIntervalBottomSheet splitIntervalBottomSheet = new SplitIntervalBottomSheet();
|
||||
splitIntervalBottomSheet.setArguments(args);
|
||||
splitIntervalBottomSheet.show(fragmentManager, SplitIntervalBottomSheet.TAG);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
log.error("showInstance", e);
|
||||
}
|
||||
}
|
||||
}
|
44
OsmAnd/src/net/osmand/plus/track/SplitIntervalCard.java
Normal file
44
OsmAnd/src/net/osmand/plus/track/SplitIntervalCard.java
Normal file
|
@ -0,0 +1,44 @@
|
|||
package net.osmand.plus.track;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||
|
||||
public class SplitIntervalCard extends BaseCard {
|
||||
|
||||
private SelectedGpxFile selectedGpxFile;
|
||||
|
||||
public SplitIntervalCard(@NonNull MapActivity mapActivity, SelectedGpxFile selectedGpxFile) {
|
||||
super(mapActivity);
|
||||
this.selectedGpxFile = selectedGpxFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCardLayoutId() {
|
||||
return R.layout.bottom_sheet_item_with_right_descr;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateContent() {
|
||||
AndroidUiHelper.updateVisibility(view.findViewById(R.id.icon), false);
|
||||
|
||||
TextView titleView = view.findViewById(R.id.title);
|
||||
titleView.setText(R.string.gpx_split_interval);
|
||||
|
||||
TextView descriptionView = view.findViewById(R.id.description);
|
||||
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
SplitIntervalBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), selectedGpxFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -27,13 +27,12 @@ public class TrackAppearanceFragment extends ContextMenuFragment {
|
|||
|
||||
public static final String SELECTED_TRACK_FILE_PATH = "selected_track_file_path";
|
||||
|
||||
private OsmandApplication app;
|
||||
private SelectedGpxFile selectedGpxFile;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
app = requireMyApplication();
|
||||
OsmandApplication app = requireMyApplication();
|
||||
|
||||
String gpxFilePath = null;
|
||||
Bundle arguments = getArguments();
|
||||
|
@ -122,6 +121,9 @@ public class TrackAppearanceFragment extends ContextMenuFragment {
|
|||
ViewGroup cardsContainer = getCardsContainer();
|
||||
cardsContainer.removeAllViews();
|
||||
|
||||
BaseCard splitIntervalCard = new SplitIntervalCard(mapActivity, selectedGpxFile);
|
||||
cardsContainer.addView(splitIntervalCard.build(mapActivity));
|
||||
|
||||
BaseCard arrowsCard = new DirectionArrowsCard(mapActivity, selectedGpxFile);
|
||||
cardsContainer.addView(arrowsCard.build(mapActivity));
|
||||
|
||||
|
|
Loading…
Reference in a new issue