Add TrackMenuFragment and refactor GPXItemPagerAdapter
This commit is contained in:
parent
57a68d223f
commit
9ef0d4ae7e
18 changed files with 2188 additions and 1282 deletions
127
OsmAnd/res/layout/track_menu.xml
Normal file
127
OsmAnd/res/layout/track_menu.xml
Normal file
|
@ -0,0 +1,127 @@
|
|||
<?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"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/color_transparent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/main_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/context_menu_top_shadow" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/route_menu_top_shadow_all"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/list_background_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="@dimen/content_padding"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="@dimen/context_menu_padding_margin_tiny"
|
||||
android:layout_marginBottom="@dimen/list_item_button_padding"
|
||||
android:background="?attr/bg_dash_line" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/context_menu_top_shadow_all"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/context_menu_top_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/context_menu_padding_margin_default"
|
||||
android:paddingLeft="@dimen/context_menu_padding_margin_default"
|
||||
android:paddingEnd="@dimen/context_menu_padding_margin_default"
|
||||
android:paddingRight="@dimen/context_menu_padding_margin_default">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/context_menu_first_line_top_margin"
|
||||
android:layout_marginEnd="@dimen/context_menu_padding_margin_default"
|
||||
android:layout_marginRight="@dimen/context_menu_padding_margin_default"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.ContextMenuTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="@string/search_address_building" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
style="@style/TextAppearance.ContextMenuSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:text="@string/amenity_type_finance" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/context_menu_icon_view"
|
||||
android:layout_width="@dimen/map_widget_icon"
|
||||
android:layout_height="@dimen/map_widget_icon"
|
||||
android:layout_marginTop="@dimen/context_menu_padding_margin_default"
|
||||
android:tint="?attr/default_icon_color"
|
||||
osmand:srcCompat="@drawable/ic_action_polygom_dark" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/bottom_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/activity_background_basic"
|
||||
android:foreground="@drawable/bg_contextmenu_shadow"
|
||||
android:foregroundGravity="top|fill_horizontal">
|
||||
|
||||
<net.osmand.plus.LockableScrollView
|
||||
android:id="@+id/route_menu_bottom_scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/route_menu_cards_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/context_menu_action_buttons_height" />
|
||||
|
||||
</net.osmand.plus.LockableScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/bottom_navigation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/context_menu_action_buttons_height"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?attr/wikivoyage_card_bg_color"
|
||||
osmand:itemBackground="?attr/wikivoyage_card_bg_color"
|
||||
osmand:itemIconTint="@color/bottom_navigation_color_selector_light"
|
||||
osmand:itemTextColor="@color/bottom_navigation_color_selector_light"
|
||||
osmand:labelVisibilityMode="labeled"
|
||||
osmand:menu="@menu/track_menu_bottom_navigation" />
|
||||
|
||||
</FrameLayout>
|
6
OsmAnd/res/layout/track_segments_container.xml
Normal file
6
OsmAnd/res/layout/track_segments_container.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</LinearLayout>
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/action_overview"
|
||||
android:icon="@drawable/ic_action_trail_overview"
|
||||
android:title="@string/shared_string_overview" />
|
||||
<!-- <item-->
|
||||
<!-- android:id="@+id/action_overview"-->
|
||||
<!-- android:icon="@drawable/ic_action_trail_overview"-->
|
||||
<!-- android:title="@string/shared_string_overview" />-->
|
||||
|
||||
<item
|
||||
android:id="@+id/action_track"
|
||||
|
@ -14,8 +14,8 @@
|
|||
android:icon="@drawable/ic_action_waypoint"
|
||||
android:title="@string/shared_string_gpx_points" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_options"
|
||||
android:icon="@drawable/ic_overflow_menu_white"
|
||||
android:title="@string/shared_string_options" />
|
||||
<!-- <item-->
|
||||
<!-- android:id="@+id/action_options"-->
|
||||
<!-- android:icon="@drawable/ic_overflow_menu_white"-->
|
||||
<!-- android:title="@string/shared_string_options" />-->
|
||||
</menu>
|
|
@ -43,6 +43,7 @@ import net.osmand.plus.myplaces.TrackPointFragment;
|
|||
import net.osmand.plus.myplaces.TrackSegmentFragment;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -57,18 +58,14 @@ public class TrackActivity extends TabActivity {
|
|||
public static final String OPEN_TRACKS_LIST = "OPEN_TRACKS_LIST";
|
||||
public static final String CURRENT_RECORDING = "CURRENT_RECORDING";
|
||||
public static final String SHOW_TEMPORARILY = "SHOW_TEMPORARILY";
|
||||
protected List<WeakReference<Fragment>> fragList = new ArrayList<>();
|
||||
|
||||
private OsmandApplication app;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
private TrackBitmapDrawer trackBitmapDrawer;
|
||||
|
||||
private File file = null;
|
||||
private GPXFile gpxFile;
|
||||
private GpxDataItem gpxDataItem;
|
||||
private LockableViewPager viewPager;
|
||||
private long modifiedTime = -1;
|
||||
private final List<WeakReference<Fragment>> fragList = new ArrayList<>();
|
||||
|
||||
private List<GpxDisplayGroup> displayGroups;
|
||||
private List<GpxDisplayGroup> originalGroups = new ArrayList<>();
|
||||
private boolean stopped = false;
|
||||
private boolean openPointsTab = false;
|
||||
private boolean openTracksList = false;
|
||||
|
@ -85,14 +82,15 @@ public class TrackActivity extends TabActivity {
|
|||
finish();
|
||||
return;
|
||||
}
|
||||
displayHelper = new TrackDisplayHelper(app);
|
||||
if (intent.hasExtra(TRACK_FILE_NAME)) {
|
||||
file = new File(intent.getStringExtra(TRACK_FILE_NAME));
|
||||
displayHelper.setFile(new File(intent.getStringExtra(TRACK_FILE_NAME)));
|
||||
}
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
if (file != null) {
|
||||
String fn = file.getName().replace(IndexConstants.GPX_FILE_EXT, "").replace("/", " ").replace("_", " ");
|
||||
if (getFile() != null) {
|
||||
String fn = getFile().getName().replace(IndexConstants.GPX_FILE_EXT, "").replace("/", " ").replace("_", " ");
|
||||
actionBar.setTitle(fn);
|
||||
} else {
|
||||
actionBar.setTitle(getString(R.string.shared_string_currently_recording_track));
|
||||
|
@ -109,11 +107,19 @@ public class TrackActivity extends TabActivity {
|
|||
setContentView(R.layout.track_content);
|
||||
}
|
||||
|
||||
public TrackDisplayHelper getDisplayHelper() {
|
||||
return displayHelper;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TrackBitmapDrawer getTrackBitmapDrawer() {
|
||||
return trackBitmapDrawer;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return displayHelper.getFile();
|
||||
}
|
||||
|
||||
public void addPoint(PointDescription pointDescription) {
|
||||
Intent currentIntent = getIntent();
|
||||
if (currentIntent != null) {
|
||||
|
@ -122,7 +128,7 @@ public class TrackActivity extends TabActivity {
|
|||
final OsmandSettings settings = app.getSettings();
|
||||
GPXFile gpx = getGpx();
|
||||
LatLon location = settings.getLastKnownMapLocation();
|
||||
QuadRect rect = getRect();
|
||||
QuadRect rect = displayHelper.getRect();
|
||||
NewGpxPoint newGpxPoint = new NewGpxPoint(gpx, pointDescription, rect);
|
||||
if (gpx != null && location != null) {
|
||||
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
|
||||
|
@ -152,53 +158,20 @@ public class TrackActivity extends TabActivity {
|
|||
}
|
||||
}
|
||||
|
||||
public QuadRect getRect() {
|
||||
if (getGpx() != null) {
|
||||
return getGpx().getRect();
|
||||
} else {
|
||||
return new QuadRect(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setGpxDataItem(GpxDataItem gpxDataItem) {
|
||||
this.gpxDataItem = gpxDataItem;
|
||||
displayHelper.setGpxDataItem(gpxDataItem);
|
||||
}
|
||||
|
||||
protected void setGpx(GPXFile result) {
|
||||
this.gpxFile = result;
|
||||
if (file == null) {
|
||||
this.gpxFile = getMyApplication().getSavingTrackHelper().getCurrentGpx();
|
||||
}
|
||||
displayHelper.setGpx(result);
|
||||
}
|
||||
|
||||
public List<GpxDisplayGroup> getGpxFile(boolean useDisplayGroups) {
|
||||
if (gpxFile == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
if (gpxFile.modifiedTime != modifiedTime) {
|
||||
modifiedTime = gpxFile.modifiedTime;
|
||||
GpxSelectionHelper selectedGpxHelper = ((OsmandApplication) getApplication()).getSelectedGpxHelper();
|
||||
displayGroups = selectedGpxHelper.collectDisplayGroups(gpxFile);
|
||||
originalGroups.clear();
|
||||
for (GpxDisplayGroup g : displayGroups) {
|
||||
originalGroups.add(g.cloneInstance());
|
||||
}
|
||||
if (file != null) {
|
||||
SelectedGpxFile sf = selectedGpxHelper.getSelectedFileByPath(gpxFile.path);
|
||||
if (sf != null && file != null && sf.getDisplayGroups(app) != null) {
|
||||
displayGroups = sf.getDisplayGroups(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (useDisplayGroups) {
|
||||
return displayGroups;
|
||||
} else {
|
||||
return originalGroups;
|
||||
}
|
||||
return displayHelper.getGpxFile(useDisplayGroups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachFragment(Fragment fragment) {
|
||||
public void onAttachFragment(@NonNull Fragment fragment) {
|
||||
fragList.add(new WeakReference<>(fragment));
|
||||
if (trackBitmapDrawer != null && fragment instanceof TrackBitmapDrawerListener) {
|
||||
trackBitmapDrawer.addListener((TrackBitmapDrawerListener) fragment);
|
||||
|
@ -218,7 +191,7 @@ public class TrackActivity extends TabActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (viewPager.getCurrentItem() == 1) {
|
||||
outState.putBoolean(OPEN_POINTS_TAB, true);
|
||||
|
@ -314,23 +287,23 @@ public class TrackActivity extends TabActivity {
|
|||
|
||||
@Nullable
|
||||
public GPXFile getGpx() {
|
||||
return gpxFile;
|
||||
return displayHelper.getGpx();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GpxDataItem getGpxDataItem() {
|
||||
return gpxDataItem;
|
||||
return displayHelper.getGpxDataItem();
|
||||
}
|
||||
|
||||
private void onGPXFileReady(@Nullable GPXFile gpxFile) {
|
||||
public void onGPXFileReady(@Nullable GPXFile gpxFile) {
|
||||
setGpx(gpxFile);
|
||||
setGpxDataItem(file != null ? app.getGpxDbHelper().getItem(file) : null);
|
||||
setGpxDataItem(getFile() != null ? app.getGpxDbHelper().getItem(getFile()) : null);
|
||||
|
||||
WindowManager mgr = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
|
||||
if (gpxFile != null && mgr != null) {
|
||||
DisplayMetrics dm = new DisplayMetrics();
|
||||
mgr.getDefaultDisplay().getMetrics(dm);
|
||||
trackBitmapDrawer = new TrackBitmapDrawer(app, gpxFile, getGpxDataItem(), getRect(), dm.density, dm.widthPixels, AndroidUtils.dpToPx(app, 152f));
|
||||
trackBitmapDrawer = new TrackBitmapDrawer(app, gpxFile, getGpxDataItem(), displayHelper.getRect(), dm.density, dm.widthPixels, AndroidUtils.dpToPx(app, 152f));
|
||||
}
|
||||
|
||||
for (WeakReference<Fragment> f : fragList) {
|
||||
|
@ -397,23 +370,6 @@ public class TrackActivity extends TabActivity {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean setJoinSegments(boolean joinSegments) {
|
||||
if (gpxDataItem != null) {
|
||||
boolean updated = app.getGpxDbHelper().updateJoinSegments(gpxDataItem, joinSegments);
|
||||
|
||||
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFile.path);
|
||||
if (updated && selectedGpxFile != null) {
|
||||
selectedGpxFile.setJoinSegments(joinSegments);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isJoinSegments() {
|
||||
return gpxDataItem != null && gpxDataItem.isJoinSegments();
|
||||
}
|
||||
|
||||
private static class GPXFileLoaderTask extends AsyncTask<Void, Void, GPXFile> {
|
||||
|
||||
private OsmandApplication app;
|
||||
|
@ -428,7 +384,7 @@ public class TrackActivity extends TabActivity {
|
|||
GPXFileLoaderTask(@NonNull TrackActivity activity) {
|
||||
this.activityRef = new WeakReference<>(activity);
|
||||
app = activity.getMyApplication();
|
||||
file = activity.file;
|
||||
file = activity.getDisplayHelper().getFile();
|
||||
}
|
||||
|
||||
protected void onPreExecute() {
|
||||
|
@ -477,11 +433,11 @@ public class TrackActivity extends TabActivity {
|
|||
if (activity != null) {
|
||||
activity.setSupportProgressBarIndeterminateVisibility(false);
|
||||
if (result != null) {
|
||||
final GpxSelectionHelper helper = app.getSelectedGpxHelper();
|
||||
GpxSelectionHelper helper = app.getSelectedGpxHelper();
|
||||
if (showTemporarily) {
|
||||
helper.selectGpxFile(result, false, false);
|
||||
} else {
|
||||
final SelectedGpxFile selectedGpx = helper.getSelectedFileByPath(result.path);
|
||||
SelectedGpxFile selectedGpx = helper.getSelectedFileByPath(result.path);
|
||||
if (selectedGpx != null && result.error == null) {
|
||||
selectedGpx.setGpxFile(result, app);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
|
|||
private OnLayoutChangeListener containerLayoutListener;
|
||||
private View topShadow;
|
||||
private ViewGroup topView;
|
||||
private View bottomScrollView;
|
||||
private ViewGroup bottomScrollView;
|
||||
private LinearLayout cardsContainer;
|
||||
private FrameLayout bottomContainer;
|
||||
|
||||
|
@ -259,7 +259,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
|
|||
return bottomContainer;
|
||||
}
|
||||
|
||||
public View getBottomScrollView() {
|
||||
public ViewGroup getBottomScrollView() {
|
||||
return bottomScrollView;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import net.osmand.GPXUtilities.Route;
|
|||
import net.osmand.GPXUtilities.Track;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.GPXUtilities.Metadata;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.Version;
|
||||
|
@ -91,6 +92,10 @@ class SaveGpxRouteAsyncTask extends AsyncTask<Void, Void, Exception> {
|
|||
backupFile = FileUtils.backupFile(app, outFile);
|
||||
String trackName = Algorithms.getFileNameWithoutExtension(outFile);
|
||||
GPXFile gpx = generateGpxFile(measurementLayer, editingCtx, trackName, gpxFile);
|
||||
if (gpxFile.metadata != null) {
|
||||
gpx.metadata = new Metadata();
|
||||
gpx.metadata.getExtensionsToWrite().putAll(gpxFile.metadata.getExtensionsToRead());
|
||||
}
|
||||
if (!gpx.showCurrentTrack) {
|
||||
res = GPXUtilities.writeGpxFile(outFile, gpx);
|
||||
}
|
||||
|
|
88
OsmAnd/src/net/osmand/plus/myplaces/DeletePointsTask.java
Normal file
88
OsmAnd/src/net/osmand/plus/myplaces/DeletePointsTask.java
Normal file
|
@ -0,0 +1,88 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.activities.SavingTrackHelper;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Set;
|
||||
|
||||
class DeletePointsTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private OsmandApplication app;
|
||||
private GPXFile gpx;
|
||||
private Set<GpxDisplayItem> selectedItems;
|
||||
private WeakReference<OnPointsDeleteListener> listenerRef;
|
||||
|
||||
DeletePointsTask(OsmandApplication app, GPXFile gpxFile, Set<GpxDisplayItem> selectedItems, OnPointsDeleteListener listener) {
|
||||
this.app = app;
|
||||
this.gpx = gpxFile;
|
||||
this.selectedItems = selectedItems;
|
||||
this.listenerRef = new WeakReference<>(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
OnPointsDeleteListener listener = listenerRef.get();
|
||||
if (listener != null) {
|
||||
listener.onPointsDeletionStarted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
SavingTrackHelper savingTrackHelper = app.getSavingTrackHelper();
|
||||
if (gpx != null) {
|
||||
for (GpxDisplayItem item : selectedItems) {
|
||||
if (gpx.showCurrentTrack) {
|
||||
savingTrackHelper.deletePointData(item.locationStart);
|
||||
} else {
|
||||
if (item.group.getType() == GpxDisplayItemType.TRACK_POINTS) {
|
||||
gpx.deleteWptPt(item.locationStart);
|
||||
} else if (item.group.getType() == GpxDisplayItemType.TRACK_ROUTE_POINTS) {
|
||||
gpx.deleteRtePt(item.locationStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gpx.showCurrentTrack) {
|
||||
GPXUtilities.writeGpxFile(new File(gpx.path), gpx);
|
||||
boolean selected = app.getSelectedGpxHelper().getSelectedFileByPath(gpx.path) != null;
|
||||
if (selected) {
|
||||
app.getSelectedGpxHelper().setGpxFileToDisplay(gpx);
|
||||
}
|
||||
}
|
||||
syncGpx(gpx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void syncGpx(GPXFile gpxFile) {
|
||||
MapMarkersHelper helper = app.getMapMarkersHelper();
|
||||
MapMarkersGroup group = helper.getMarkersGroup(gpxFile);
|
||||
if (group != null) {
|
||||
helper.runSynchronization(group);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
OnPointsDeleteListener listener = listenerRef.get();
|
||||
if (listener != null) {
|
||||
listener.onPointsDeleted();
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnPointsDeleteListener {
|
||||
void onPointsDeletionStarted();
|
||||
|
||||
void onPointsDeleted();
|
||||
}
|
||||
}
|
695
OsmAnd/src/net/osmand/plus/myplaces/GPXItemPagerAdapter.java
Normal file
695
OsmAnd/src/net/osmand/plus/myplaces/GPXItemPagerAdapter.java
Normal file
|
@ -0,0 +1,695 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Matrix;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
|
||||
import com.github.mikephil.charting.charts.LineChart;
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.data.LineData;
|
||||
import com.github.mikephil.charting.highlight.Highlight;
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
import com.github.mikephil.charting.listener.ChartTouchListener.ChartGesture;
|
||||
import com.github.mikephil.charting.listener.OnChartGestureListener;
|
||||
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
|
||||
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||
import net.osmand.GPXUtilities.Track;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.plus.GPXDatabase.GpxDataItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.LineGraphType;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
|
||||
import net.osmand.plus.views.controls.PagerSlidingTabStrip.CustomTabProvider;
|
||||
import net.osmand.plus.views.controls.WrapContentHeightViewPager.ViewAtPositionInterface;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.ALTITUDE;
|
||||
import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.SLOPE;
|
||||
import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.SPEED;
|
||||
|
||||
public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvider, ViewAtPositionInterface {
|
||||
|
||||
private OsmandApplication app;
|
||||
private UiUtilities iconsCache;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
private Map<GPXTabItemType, List<ILineDataSet>> dataSetsMap = new HashMap<>();
|
||||
|
||||
private WptPt selectedWpt;
|
||||
private TrkSegment segment;
|
||||
private GpxDisplayItem gpxItem;
|
||||
private GPXTabItemType[] tabTypes;
|
||||
|
||||
private PagerSlidingTabStrip tabs;
|
||||
private SparseArray<View> views = new SparseArray<>();
|
||||
private SegmentActionsListener actionsListener;
|
||||
|
||||
private boolean chartClicked;
|
||||
|
||||
|
||||
public GPXItemPagerAdapter(@NonNull PagerSlidingTabStrip tabs,
|
||||
@NonNull GpxDisplayItem gpxItem,
|
||||
@NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull SegmentActionsListener actionsListener) {
|
||||
super();
|
||||
this.tabs = tabs;
|
||||
this.gpxItem = gpxItem;
|
||||
this.displayHelper = displayHelper;
|
||||
this.actionsListener = actionsListener;
|
||||
app = (OsmandApplication) tabs.getContext().getApplicationContext();
|
||||
iconsCache = app.getUIUtilities();
|
||||
fetchTabTypes();
|
||||
}
|
||||
|
||||
private void fetchTabTypes() {
|
||||
List<GPXTabItemType> tabTypeList = new ArrayList<>();
|
||||
tabTypeList.add(GPXTabItemType.GPX_TAB_ITEM_GENERAL);
|
||||
if (gpxItem != null && gpxItem.analysis != null) {
|
||||
if (gpxItem.analysis.hasElevationData) {
|
||||
tabTypeList.add(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE);
|
||||
}
|
||||
if (gpxItem.analysis.isSpeedSpecified()) {
|
||||
tabTypeList.add(GPXTabItemType.GPX_TAB_ITEM_SPEED);
|
||||
}
|
||||
}
|
||||
tabTypes = tabTypeList.toArray(new GPXTabItemType[0]);
|
||||
}
|
||||
|
||||
private List<ILineDataSet> getDataSets(LineChart chart, GPXTabItemType tabType,
|
||||
LineGraphType firstType, LineGraphType secondType) {
|
||||
List<ILineDataSet> dataSets = dataSetsMap.get(tabType);
|
||||
if (dataSets == null && chart != null) {
|
||||
GPXTrackAnalysis analysis = gpxItem.analysis;
|
||||
GpxDataItem gpxDataItem = displayHelper.getGpxDataItem();
|
||||
boolean calcWithoutGaps = gpxItem.isGeneralTrack() && gpxDataItem != null && !gpxDataItem.isJoinSegments();
|
||||
dataSets = GpxUiHelper.getDataSets(chart, app, analysis, firstType, secondType, calcWithoutGaps);
|
||||
dataSetsMap.put(tabType, dataSets);
|
||||
}
|
||||
return dataSets;
|
||||
}
|
||||
|
||||
private TrkSegment getTrackSegment(LineChart chart) {
|
||||
if (segment == null) {
|
||||
LineData lineData = chart.getLineData();
|
||||
List<ILineDataSet> ds = lineData != null ? lineData.getDataSets() : null;
|
||||
if (ds != null && ds.size() > 0) {
|
||||
for (GPXUtilities.Track t : gpxItem.group.getGpx().tracks) {
|
||||
for (TrkSegment s : t.segments) {
|
||||
if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
|
||||
segment = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (segment != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return segment;
|
||||
}
|
||||
|
||||
private WptPt getPoint(LineChart chart, float pos) {
|
||||
WptPt wpt = null;
|
||||
LineData lineData = chart.getLineData();
|
||||
List<ILineDataSet> ds = lineData != null ? lineData.getDataSets() : null;
|
||||
if (ds != null && ds.size() > 0) {
|
||||
TrkSegment segment = getTrackSegment(chart);
|
||||
OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0);
|
||||
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) {
|
||||
float time = pos * 1000;
|
||||
for (WptPt p : segment.points) {
|
||||
if (p.time - gpxItem.analysis.startTime >= time) {
|
||||
wpt = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
float distance = pos * dataSet.getDivX();
|
||||
double totalDistance = 0;
|
||||
for (int i = 0; i < segment.points.size(); i++) {
|
||||
WptPt currentPoint = segment.points.get(i);
|
||||
if (i != 0) {
|
||||
WptPt previousPoint = segment.points.get(i - 1);
|
||||
totalDistance += MapUtils.getDistance(previousPoint.lat, previousPoint.lon, currentPoint.lat, currentPoint.lon);
|
||||
}
|
||||
if (currentPoint.distance >= distance || Math.abs(totalDistance - distance) < 0.1) {
|
||||
wpt = currentPoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return wpt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return tabTypes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return tabTypes[position].toHumanString(app);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
GPXTabItemType tabType = tabTypes[position];
|
||||
View view = getViewForTab(container, tabType);
|
||||
GPXFile gpxFile = displayHelper.getGpx();
|
||||
if (gpxFile != null && gpxItem != null) {
|
||||
GPXTrackAnalysis analysis = gpxItem.analysis;
|
||||
LineChart chart = view.findViewById(R.id.chart);
|
||||
setupChart(view, chart);
|
||||
|
||||
switch (tabType) {
|
||||
case GPX_TAB_ITEM_GENERAL:
|
||||
setupGeneralTab(view, chart, analysis, gpxFile, position);
|
||||
break;
|
||||
case GPX_TAB_ITEM_ALTITUDE:
|
||||
setupAltitudeTab(view, chart, analysis, gpxFile, position);
|
||||
break;
|
||||
case GPX_TAB_ITEM_SPEED:
|
||||
setupSpeedTab(view, chart, analysis, gpxFile, position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
container.addView(view, 0);
|
||||
views.put(position, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
private View getViewForTab(@NonNull ViewGroup container, @NonNull GPXTabItemType tabType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(container.getContext());
|
||||
switch (tabType) {
|
||||
case GPX_TAB_ITEM_ALTITUDE:
|
||||
return inflater.inflate(R.layout.gpx_item_altitude, container, false);
|
||||
case GPX_TAB_ITEM_SPEED:
|
||||
return inflater.inflate(R.layout.gpx_item_speed, container, false);
|
||||
case GPX_TAB_ITEM_GENERAL:
|
||||
default:
|
||||
return inflater.inflate(R.layout.gpx_item_general, container, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupSpeedTab(View view, LineChart chart, GPXTrackAnalysis analysis, GPXFile gpxFile, int position) {
|
||||
if (analysis != null && analysis.isSpeedSpecified()) {
|
||||
if (analysis.hasSpeedData) {
|
||||
GpxUiHelper.setupGPXChart(app, chart, 4);
|
||||
chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_SPEED, SPEED, null)));
|
||||
updateChart(chart);
|
||||
chart.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
}
|
||||
((ImageView) view.findViewById(R.id.average_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_speed));
|
||||
((ImageView) view.findViewById(R.id.max_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_max_speed));
|
||||
((ImageView) view.findViewById(R.id.time_moving_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_span));
|
||||
((ImageView) view.findViewById(R.id.distance_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_polygom_dark));
|
||||
|
||||
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
|
||||
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
|
||||
|
||||
((TextView) view.findViewById(R.id.average_text)).setText(avg);
|
||||
((TextView) view.findViewById(R.id.max_text)).setText(max);
|
||||
|
||||
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
View view = getViewAtPosition(i);
|
||||
updateJoinGapsInfo(view, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
view.findViewById(R.id.average_max).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.time_distance).setVisibility(View.GONE);
|
||||
}
|
||||
updateJoinGapsInfo(view, position);
|
||||
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_SPEED);
|
||||
}
|
||||
});
|
||||
if (gpxFile.showCurrentTrack) {
|
||||
view.findViewById(R.id.split_interval).setVisibility(View.GONE);
|
||||
} else {
|
||||
view.findViewById(R.id.split_interval).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openSplitIntervalScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
ImageView overflowMenu = view.findViewById(R.id.overflow_menu);
|
||||
if (!gpxItem.group.getTrack().generalTrack) {
|
||||
setupOptionsPopupMenu(overflowMenu, false);
|
||||
} else {
|
||||
overflowMenu.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupOptionsPopupMenu(ImageView overflowMenu, final boolean confirmDeletion) {
|
||||
overflowMenu.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_overflow_menu_white));
|
||||
overflowMenu.setVisibility(View.VISIBLE);
|
||||
overflowMenu.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
actionsListener.showOptionsPopupMenu(view, getTrkSegment(), confirmDeletion);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupAltitudeTab(View view, LineChart chart, GPXTrackAnalysis analysis, GPXFile gpxFile, int position) {
|
||||
if (analysis != null) {
|
||||
if (analysis.hasElevationData) {
|
||||
GpxUiHelper.setupGPXChart(app, chart, 4);
|
||||
chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_ALTITUDE, ALTITUDE, SLOPE)));
|
||||
updateChart(chart);
|
||||
chart.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
}
|
||||
((ImageView) view.findViewById(R.id.average_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_average));
|
||||
((ImageView) view.findViewById(R.id.range_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_average));
|
||||
((ImageView) view.findViewById(R.id.ascent_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_ascent));
|
||||
((ImageView) view.findViewById(R.id.descent_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_descent));
|
||||
|
||||
String min = OsmAndFormatter.getFormattedAlt(analysis.minElevation, app);
|
||||
String max = OsmAndFormatter.getFormattedAlt(analysis.maxElevation, app);
|
||||
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
|
||||
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
|
||||
|
||||
((TextView) view.findViewById(R.id.average_text))
|
||||
.setText(OsmAndFormatter.getFormattedAlt(analysis.avgElevation, app));
|
||||
((TextView) view.findViewById(R.id.range_text)).setText(String.format("%s - %s", min, max));
|
||||
((TextView) view.findViewById(R.id.ascent_text)).setText(asc);
|
||||
((TextView) view.findViewById(R.id.descent_text)).setText(desc);
|
||||
|
||||
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
View view = getViewAtPosition(i);
|
||||
updateJoinGapsInfo(view, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
view.findViewById(R.id.average_range).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.ascent_descent).setVisibility(View.GONE);
|
||||
}
|
||||
updateJoinGapsInfo(view, position);
|
||||
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE);
|
||||
}
|
||||
});
|
||||
if (gpxFile.showCurrentTrack) {
|
||||
view.findViewById(R.id.split_interval).setVisibility(View.GONE);
|
||||
} else {
|
||||
view.findViewById(R.id.split_interval).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openSplitIntervalScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
ImageView overflowMenu = view.findViewById(R.id.overflow_menu);
|
||||
if (!gpxItem.group.getTrack().generalTrack) {
|
||||
setupOptionsPopupMenu(overflowMenu, false);
|
||||
} else {
|
||||
overflowMenu.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupGeneralTab(View view, LineChart chart, GPXTrackAnalysis analysis, GPXFile gpxFile, int position) {
|
||||
if (analysis != null) {
|
||||
if (analysis.hasElevationData || analysis.hasSpeedData) {
|
||||
GpxUiHelper.setupGPXChart(app, chart, 4);
|
||||
chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_GENERAL, ALTITUDE, SPEED)));
|
||||
updateChart(chart);
|
||||
chart.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
((ImageView) view.findViewById(R.id.distance_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_polygom_dark));
|
||||
((ImageView) view.findViewById(R.id.duration_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_span));
|
||||
((ImageView) view.findViewById(R.id.start_time_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_start));
|
||||
((ImageView) view.findViewById(R.id.end_time_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_end));
|
||||
|
||||
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
|
||||
actionsListener.updateContent();
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
View view = getViewAtPosition(i);
|
||||
updateJoinGapsInfo(view, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (analysis.timeSpan > 0) {
|
||||
DateFormat tf = SimpleDateFormat.getTimeInstance(DateFormat.SHORT);
|
||||
DateFormat df = SimpleDateFormat.getDateInstance(DateFormat.MEDIUM);
|
||||
|
||||
Date start = new Date(analysis.startTime);
|
||||
((TextView) view.findViewById(R.id.start_time_text)).setText(tf.format(start));
|
||||
((TextView) view.findViewById(R.id.start_date_text)).setText(df.format(start));
|
||||
Date end = new Date(analysis.endTime);
|
||||
((TextView) view.findViewById(R.id.end_time_text)).setText(tf.format(end));
|
||||
((TextView) view.findViewById(R.id.end_date_text)).setText(df.format(end));
|
||||
} else {
|
||||
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.start_end_time).setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
view.findViewById(R.id.distance_time_span).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.start_end_time).setVisibility(View.GONE);
|
||||
}
|
||||
updateJoinGapsInfo(view, position);
|
||||
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_GENERAL);
|
||||
}
|
||||
});
|
||||
if (gpxFile.showCurrentTrack) {
|
||||
view.findViewById(R.id.split_interval).setVisibility(View.GONE);
|
||||
} else {
|
||||
view.findViewById(R.id.split_interval).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openSplitIntervalScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
ImageView overflowMenu = view.findViewById(R.id.overflow_menu);
|
||||
if (!gpxItem.group.getTrack().generalTrack) {
|
||||
setupOptionsPopupMenu(overflowMenu, true);
|
||||
} else {
|
||||
overflowMenu.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupChart(final View view, final LineChart chart) {
|
||||
chart.setHighlightPerDragEnabled(chartClicked);
|
||||
chart.setOnClickListener(new View.OnClickListener() {
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (!chartClicked) {
|
||||
chartClicked = true;
|
||||
if (selectedWpt != null) {
|
||||
actionsListener.onPointSelected(selectedWpt.lat, selectedWpt.lon);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
chart.setOnTouchListener(new View.OnTouchListener() {
|
||||
|
||||
private float listViewYPos;
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (chartClicked) {
|
||||
actionsListener.onChartTouch();
|
||||
if (!chart.isHighlightPerDragEnabled()) {
|
||||
chart.setHighlightPerDragEnabled(true);
|
||||
}
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
listViewYPos = event.getRawY();
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
actionsListener.scrollBy(Math.round(listViewYPos - event.getRawY()));
|
||||
listViewYPos = event.getRawY();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
|
||||
@Override
|
||||
public void onValueSelected(Entry e, Highlight h) {
|
||||
WptPt wpt = getPoint(chart, h.getX());
|
||||
selectedWpt = wpt;
|
||||
if (chartClicked && wpt != null) {
|
||||
actionsListener.onPointSelected(wpt.lat, wpt.lon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected() {
|
||||
|
||||
}
|
||||
});
|
||||
chart.setOnChartGestureListener(new OnChartGestureListener() {
|
||||
|
||||
float highlightDrawX = -1;
|
||||
|
||||
@Override
|
||||
public void onChartGestureStart(MotionEvent me, ChartGesture lastPerformedGesture) {
|
||||
if (chart.getHighlighted() != null && chart.getHighlighted().length > 0) {
|
||||
highlightDrawX = chart.getHighlighted()[0].getDrawX();
|
||||
} else {
|
||||
highlightDrawX = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartGestureEnd(MotionEvent me, ChartGesture lastPerformedGesture) {
|
||||
gpxItem.chartMatrix = new Matrix(chart.getViewPortHandler().getMatrixTouch());
|
||||
Highlight[] highlights = chart.getHighlighted();
|
||||
if (highlights != null && highlights.length > 0) {
|
||||
gpxItem.chartHighlightPos = highlights[0].getX();
|
||||
} else {
|
||||
gpxItem.chartHighlightPos = -1;
|
||||
}
|
||||
if (chartClicked) {
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
View v = getViewAtPosition(i);
|
||||
if (v != view) {
|
||||
updateChart(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartLongPressed(MotionEvent me) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartDoubleTapped(MotionEvent me) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartSingleTapped(MotionEvent me) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartTranslate(MotionEvent me, float dX, float dY) {
|
||||
if (chartClicked && highlightDrawX != -1) {
|
||||
Highlight h = chart.getHighlightByTouchPoint(highlightDrawX, 0f);
|
||||
if (h != null) {
|
||||
chart.highlightValue(h);
|
||||
WptPt wpt = getPoint(chart, h.getX());
|
||||
if (wpt != null) {
|
||||
actionsListener.onPointSelected(wpt.lat, wpt.lon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(@NonNull ViewGroup collection, int position, @NonNull Object view) {
|
||||
views.remove(position);
|
||||
collection.removeView((View) view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
|
||||
return view == object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getCustomTabView(@NonNull ViewGroup parent, int position) {
|
||||
View tab = LayoutInflater.from(parent.getContext()).inflate(R.layout.gpx_tab, parent, false);
|
||||
tab.setTag(tabTypes[position].name());
|
||||
deselect(tab);
|
||||
return tab;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void select(View tab) {
|
||||
GPXTabItemType tabType = GPXTabItemType.valueOf((String) tab.getTag());
|
||||
ImageView img = tab.findViewById(R.id.tab_image);
|
||||
switch (tabs.getTabSelectionType()) {
|
||||
case ALPHA:
|
||||
img.setAlpha(tabs.getTabTextSelectedAlpha());
|
||||
break;
|
||||
case SOLID_COLOR:
|
||||
img.setImageDrawable(iconsCache.getPaintedIcon(tabType.getIconId(), tabs.getTextColor()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deselect(View tab) {
|
||||
GPXTabItemType tabType = GPXTabItemType.valueOf((String) tab.getTag());
|
||||
ImageView img = tab.findViewById(R.id.tab_image);
|
||||
switch (tabs.getTabSelectionType()) {
|
||||
case ALPHA:
|
||||
img.setAlpha(tabs.getTabTextAlpha());
|
||||
break;
|
||||
case SOLID_COLOR:
|
||||
img.setImageDrawable(iconsCache.getPaintedIcon(tabType.getIconId(), tabs.getTabInactiveTextColor()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getViewAtPosition(int position) {
|
||||
return views.get(position);
|
||||
}
|
||||
|
||||
void updateChart(int position) {
|
||||
View view = getViewAtPosition(position);
|
||||
if (view != null) {
|
||||
updateChart((LineChart) view.findViewById(R.id.chart));
|
||||
}
|
||||
}
|
||||
|
||||
void updateJoinGapsInfo(View view, int position) {
|
||||
if (view != null) {
|
||||
GPXTrackAnalysis analysis = gpxItem.analysis;
|
||||
GPXTabItemType tabType = tabTypes[position];
|
||||
boolean visible = gpxItem.isGeneralTrack() && analysis != null && tabType.equals(GPXTabItemType.GPX_TAB_ITEM_GENERAL);
|
||||
AndroidUiHelper.updateVisibility(view.findViewById(R.id.gpx_join_gaps_container), visible);
|
||||
boolean joinSegments = displayHelper.isJoinSegments();
|
||||
((SwitchCompat) view.findViewById(R.id.gpx_join_gaps_switch)).setChecked(joinSegments);
|
||||
if (analysis != null) {
|
||||
if (tabType.equals(GPXTabItemType.GPX_TAB_ITEM_GENERAL)) {
|
||||
float totalDistance = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
|
||||
float timeSpan = !joinSegments && gpxItem.isGeneralTrack() ? analysis.timeSpanWithoutGaps : analysis.timeSpan;
|
||||
|
||||
((TextView) view.findViewById(R.id.distance_text)).setText(OsmAndFormatter.getFormattedDistance(totalDistance, app));
|
||||
((TextView) view.findViewById(R.id.duration_text)).setText(Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()));
|
||||
} else if (tabType.equals(GPXTabItemType.GPX_TAB_ITEM_SPEED)) {
|
||||
long timeMoving = !joinSegments && gpxItem.isGeneralTrack() ? analysis.timeMovingWithoutGaps : analysis.timeMoving;
|
||||
float totalDistanceMoving = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceMovingWithoutGaps : analysis.totalDistanceMoving;
|
||||
|
||||
((TextView) view.findViewById(R.id.time_moving_text)).setText(Algorithms.formatDuration((int) (timeMoving / 1000), app.accessibilityEnabled()));
|
||||
((TextView) view.findViewById(R.id.distance_text)).setText(OsmAndFormatter.getFormattedDistance(totalDistanceMoving, app));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateChart(LineChart chart) {
|
||||
if (chart != null && !chart.isEmpty()) {
|
||||
if (gpxItem.chartMatrix != null) {
|
||||
chart.getViewPortHandler().refresh(new Matrix(gpxItem.chartMatrix), chart, true);
|
||||
}
|
||||
if (gpxItem.chartHighlightPos != -1) {
|
||||
chart.highlightValue(gpxItem.chartHighlightPos, 0);
|
||||
} else {
|
||||
chart.highlightValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TrkSegment getTrkSegment() {
|
||||
for (Track track : gpxItem.group.getGpx().tracks) {
|
||||
if (!track.generalTrack && !gpxItem.isGeneralTrack() || track.generalTrack && gpxItem.isGeneralTrack()) {
|
||||
for (TrkSegment segment : track.segments) {
|
||||
if (segment.points.size() > 0 && segment.points.get(0).equals(gpxItem.analysis.locationStart)) {
|
||||
return segment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void openAnalyzeOnMap(GPXTabItemType tabType) {
|
||||
List<ILineDataSet> ds = getDataSets(null, tabType, null, null);
|
||||
actionsListener.openAnalyzeOnMap(gpxItem, ds, tabType);
|
||||
}
|
||||
|
||||
private void openSplitIntervalScreen() {
|
||||
actionsListener.openSplitInterval(gpxItem, getTrkSegment());
|
||||
}
|
||||
}
|
32
OsmAnd/src/net/osmand/plus/myplaces/GPXTabItemType.java
Normal file
32
OsmAnd/src/net/osmand/plus/myplaces/GPXTabItemType.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
|
||||
public enum GPXTabItemType {
|
||||
|
||||
GPX_TAB_ITEM_GENERAL(R.string.shared_string_overview, R.drawable.ic_action_polygom_dark),
|
||||
GPX_TAB_ITEM_ALTITUDE(R.string.altitude, R.drawable.ic_action_altitude_average),
|
||||
GPX_TAB_ITEM_SPEED(R.string.map_widget_speed, R.drawable.ic_action_speed);
|
||||
|
||||
private final int iconId;
|
||||
private final int titleId;
|
||||
|
||||
GPXTabItemType(@StringRes int titleId, @DrawableRes int iconId) {
|
||||
this.iconId = iconId;
|
||||
this.titleId = titleId;
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public int getIconId() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
public String toHumanString(Context ctx) {
|
||||
return ctx.getString(titleId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SegmentActionsListener {
|
||||
|
||||
void updateContent();
|
||||
|
||||
void onChartTouch();
|
||||
|
||||
void scrollBy(int px);
|
||||
|
||||
void onPointSelected(double lat, double lon);
|
||||
|
||||
void openSplitInterval(GpxDisplayItem gpxItem, TrkSegment trkSegment);
|
||||
|
||||
void showOptionsPopupMenu(View view, TrkSegment trkSegment, boolean confirmDeletion);
|
||||
|
||||
void openAnalyzeOnMap(GpxDisplayItem gpxItem, List<ILineDataSet> dataSets, GPXTabItemType tabType);
|
||||
}
|
91
OsmAnd/src/net/osmand/plus/myplaces/SegmentGPXAdapter.java
Normal file
91
OsmAnd/src/net/osmand/plus/myplaces/SegmentGPXAdapter.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
|
||||
import net.osmand.plus.views.controls.WrapContentHeightViewPager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SegmentGPXAdapter extends ArrayAdapter<GpxDisplayItem> {
|
||||
|
||||
private OsmandApplication app;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
private SegmentActionsListener listener;
|
||||
private boolean nightMode;
|
||||
|
||||
public SegmentGPXAdapter(@NonNull Context context, @NonNull List<GpxDisplayItem> items,
|
||||
@NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull SegmentActionsListener listener,
|
||||
boolean nightMode) {
|
||||
super(context, R.layout.gpx_list_item_tab_content, items);
|
||||
this.app = (OsmandApplication) context.getApplicationContext();
|
||||
this.displayHelper = displayHelper;
|
||||
this.listener = listener;
|
||||
this.nightMode = nightMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
|
||||
View row = convertView;
|
||||
boolean create = false;
|
||||
if (row == null) {
|
||||
create = true;
|
||||
row = createGpxTabsView(displayHelper, parent, listener, nightMode);
|
||||
}
|
||||
GpxDisplayItem item = getItem(position);
|
||||
if (item != null) {
|
||||
WrapContentHeightViewPager pager = row.findViewById(R.id.pager);
|
||||
PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs);
|
||||
|
||||
pager.setAdapter(new GPXItemPagerAdapter(tabLayout, item, displayHelper, listener));
|
||||
if (create) {
|
||||
tabLayout.setViewPager(pager);
|
||||
} else {
|
||||
tabLayout.notifyDataSetChanged(true);
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
public static View createGpxTabsView(TrackDisplayHelper displayHelper, ViewGroup root,
|
||||
SegmentActionsListener listener, boolean nightMode) {
|
||||
Context context = root.getContext();
|
||||
View row = UiUtilities.getInflater(context, nightMode).inflate(R.layout.gpx_list_item_tab_content, root, false);
|
||||
|
||||
PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs);
|
||||
tabLayout.setTabBackground(R.color.color_transparent);
|
||||
tabLayout.setIndicatorColorResource(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
|
||||
tabLayout.setIndicatorBgColorResource(nightMode ? R.color.divider_color_dark : R.color.divider_color_light);
|
||||
tabLayout.setIndicatorHeight(AndroidUtils.dpToPx(context, 1f));
|
||||
if (!nightMode) {
|
||||
tabLayout.setTextColor(tabLayout.getIndicatorColor());
|
||||
tabLayout.setTabInactiveTextColor(ContextCompat.getColor(row.getContext(), R.color.text_color_secondary_light));
|
||||
}
|
||||
tabLayout.setTextSize(AndroidUtils.spToPx(context, 12f));
|
||||
tabLayout.setShouldExpand(true);
|
||||
WrapContentHeightViewPager pager = row.findViewById(R.id.pager);
|
||||
pager.setSwipeable(false);
|
||||
pager.setOffscreenPageLimit(2);
|
||||
|
||||
return row;
|
||||
}
|
||||
}
|
|
@ -23,14 +23,18 @@ import android.widget.TextView;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.ListPopupWindow;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
|
@ -39,8 +43,8 @@ import net.osmand.plus.OsmAndFormatter;
|
|||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.TrackActivity;
|
||||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
@ -54,7 +58,9 @@ import gnu.trove.list.array.TIntArrayList;
|
|||
public class SplitSegmentDialogFragment extends DialogFragment {
|
||||
|
||||
public final static String TAG = "SPLIT_SEGMENT_DIALOG_FRAGMENT";
|
||||
|
||||
private OsmandApplication app;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
|
||||
private SplitSegmentsAdapter adapter;
|
||||
private View headerView;
|
||||
|
@ -78,8 +84,8 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
TrackActivity trackActivity = requireTrackActivity();
|
||||
app = trackActivity.getMyApplication();
|
||||
FragmentActivity activity = requireActivity();
|
||||
app = (OsmandApplication) activity.getApplication();
|
||||
ic = app.getUIUtilities();
|
||||
boolean isLightTheme = app.getSettings().isLightContent();
|
||||
int themeId = isLightTheme ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme;
|
||||
|
@ -89,9 +95,8 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
TrackActivity trackActivity = requireTrackActivity();
|
||||
listView.setBackgroundColor(getResources().getColor(
|
||||
trackActivity.getMyApplication().getSettings().isLightContent() ? R.color.activity_background_color_light
|
||||
app.getSettings().isLightContent() ? R.color.activity_background_color_light
|
||||
: R.color.activity_background_color_dark));
|
||||
}
|
||||
|
||||
|
@ -103,7 +108,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
minMaxSpeedPaint.setStyle(Paint.Style.FILL);
|
||||
minMaxSpeedTextBounds = new Rect();
|
||||
|
||||
TrackActivity trackActivity = requireTrackActivity();
|
||||
AppCompatActivity trackActivity = (AppCompatActivity) getActivity();
|
||||
final View view = trackActivity.getLayoutInflater().inflate(R.layout.split_segments_layout, container, false);
|
||||
|
||||
Toolbar toolbar = (Toolbar) view.findViewById(R.id.split_interval_toolbar);
|
||||
|
@ -250,7 +255,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
}
|
||||
|
||||
public void updateContent() {
|
||||
if (getTrackActivity() != null) {
|
||||
if (getActivity() != null) {
|
||||
adapter.clear();
|
||||
adapter.setNotifyOnChange(false);
|
||||
adapter.add(gpxItem);
|
||||
|
@ -297,18 +302,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
|
||||
@Nullable
|
||||
private GPXFile getGpx() {
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
return trackActivity != null ? trackActivity.getGpx() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TrackActivity getTrackActivity() {
|
||||
return (TrackActivity) getActivity();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TrackActivity requireTrackActivity() {
|
||||
return (TrackActivity) requireActivity();
|
||||
return displayHelper.getGpx();
|
||||
}
|
||||
|
||||
private void prepareSplitIntervalAdapterData() {
|
||||
|
@ -346,7 +340,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
|
||||
@NonNull
|
||||
private List<GpxDisplayGroup> getDisplayGroups() {
|
||||
return filterGroups(true);
|
||||
return displayHelper.getDisplayGroups(filterTypes);
|
||||
}
|
||||
|
||||
private void addOptionSplit(int value, boolean distance, List<GpxDisplayGroup> model) {
|
||||
|
@ -374,34 +368,15 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<GpxDisplayGroup> filterGroups(boolean useDisplayGroups) {
|
||||
List<GpxDisplayGroup> groups = new ArrayList<>();
|
||||
if (getTrackActivity() != null) {
|
||||
List<GpxDisplayGroup> result = getTrackActivity().getGpxFile(useDisplayGroups);
|
||||
for (GpxDisplayGroup group : result) {
|
||||
boolean add = hasFilterType(group.getType());
|
||||
if (add) {
|
||||
groups.add(group);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<GpxDisplayItem> getSplitSegments() {
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
List<GpxDisplayItem> splitSegments = new ArrayList<>();
|
||||
if (trackActivity != null) {
|
||||
List<GpxDisplayGroup> result = trackActivity.getGpxFile(true);
|
||||
List<GpxDisplayGroup> result = displayHelper.getGpxFile(true);
|
||||
if (result != null && result.size() > 0 && trkSegment.points.size() > 0) {
|
||||
for (GpxDisplayGroup group : result) {
|
||||
splitSegments.addAll(collectDisplayItemsFromGroup(group));
|
||||
}
|
||||
}
|
||||
}
|
||||
return splitSegments;
|
||||
}
|
||||
|
||||
|
@ -445,7 +420,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
@Override
|
||||
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||
GpxDisplayItem currentGpxDisplayItem = getItem(position);
|
||||
TrackActivity trackActivity = requireTrackActivity();
|
||||
FragmentActivity trackActivity = requireActivity();
|
||||
if (convertView == null) {
|
||||
convertView = trackActivity.getLayoutInflater().inflate(R.layout.gpx_split_segment_fragment, parent, false);
|
||||
}
|
||||
|
@ -731,14 +706,15 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean showInstance(@NonNull TrackActivity trackActivity, @NonNull GpxDisplayItem gpxItem, GPXUtilities.TrkSegment trkSegment) {
|
||||
public static boolean showInstance(@NonNull FragmentManager fragmentManager, @NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull GpxDisplayItem gpxItem, @NonNull TrkSegment trkSegment) {
|
||||
try {
|
||||
SplitSegmentDialogFragment fragment = new SplitSegmentDialogFragment();
|
||||
fragment.setGpxItem(gpxItem);
|
||||
fragment.setTrkSegment(trkSegment);
|
||||
fragment.setRetainInstance(true);
|
||||
fragment.setJoinSegments(trackActivity.isJoinSegments());
|
||||
fragment.show(trackActivity.getSupportFragmentManager(), TAG);
|
||||
fragment.displayHelper = displayHelper;
|
||||
fragment.show(fragmentManager, TAG);
|
||||
return true;
|
||||
} catch (RuntimeException e) {
|
||||
return false;
|
||||
|
|
|
@ -39,10 +39,7 @@ import net.osmand.GPXUtilities.GPXFile;
|
|||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.PicassoUtils;
|
||||
import net.osmand.data.PointDescription;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.plus.GPXDatabase.GpxDataItem;
|
||||
import net.osmand.plus.GpxSelectionHelper;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
|
@ -52,6 +49,7 @@ import net.osmand.plus.dialogs.GpxAppearanceAdapter;
|
|||
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.plus.widgets.tools.CropCircleTransformation;
|
||||
import net.osmand.plus.wikipedia.WikiArticleHelper;
|
||||
import net.osmand.plus.wikivoyage.WikivoyageUtils;
|
||||
|
@ -59,8 +57,6 @@ import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment;
|
|||
import net.osmand.plus.wikivoyage.data.TravelArticle;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR;
|
||||
|
@ -71,6 +67,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
private Fragment fragment;
|
||||
private ListView listView;
|
||||
private GpxDisplayItemType[] filterTypes;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
|
||||
private boolean updateEnable;
|
||||
private View headerView;
|
||||
|
@ -99,11 +96,13 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
TrackActivityFragmentAdapter(@NonNull OsmandApplication app,
|
||||
@NonNull Fragment fragment,
|
||||
@NonNull ListView listView,
|
||||
@NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull GpxDisplayItemType... filterTypes) {
|
||||
this.app = app;
|
||||
this.fragment = fragment;
|
||||
this.listView = listView;
|
||||
this.filterTypes = filterTypes;
|
||||
this.displayHelper = displayHelper;
|
||||
}
|
||||
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
|
@ -191,14 +190,12 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
|
||||
private GPXFile getGpx() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
return activity != null ? activity.getGpx() : null;
|
||||
return displayHelper.getGpx();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GpxDataItem getGpxDataItem() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
return activity != null ? activity.getGpxDataItem() : null;
|
||||
return displayHelper.getGpxDataItem();
|
||||
}
|
||||
|
||||
private void showTrackBitmapProgress() {
|
||||
|
@ -250,7 +247,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
showTemporaryObjectOnMap(getRect());
|
||||
showTemporaryObjectOnMap(displayHelper.getRect());
|
||||
}
|
||||
});
|
||||
final View appearanceView = headerView.findViewById(R.id.appearance_view);
|
||||
|
@ -258,7 +255,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
vis = (SwitchCompat) headerView.findViewById(R.id.showOnMapToggle);
|
||||
final View bottomDivider = headerView.findViewById(R.id.bottom_divider);
|
||||
GPXFile gpxFile = getGpx();
|
||||
boolean gpxFileSelected = isGpxFileSelected(gpxFile);
|
||||
boolean gpxFileSelected = isGpxFileSelected(app, gpxFile);
|
||||
|
||||
boolean hasPath = gpxFile != null && (gpxFile.tracks.size() > 0 || gpxFile.routes.size() > 0);
|
||||
TrackActivity activity = getTrackActivity();
|
||||
|
@ -318,7 +315,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
GPXFile gpx = getGpx();
|
||||
WptPt pointToShow = gpx != null ? gpx.findPointToShow() : null;
|
||||
if (activity != null && pointToShow != null) {
|
||||
boolean gpxFileSelected = isGpxFileSelected(gpx);
|
||||
boolean gpxFileSelected = isGpxFileSelected(app, gpx);
|
||||
if (!gpxFileSelected) {
|
||||
Intent intent = activity.getIntent();
|
||||
if (intent != null) {
|
||||
|
@ -530,7 +527,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isGpxFileSelected(GPXFile gpxFile) {
|
||||
public static boolean isGpxFileSelected(OsmandApplication app, GPXFile gpxFile) {
|
||||
return gpxFile != null &&
|
||||
((gpxFile.showCurrentTrack && app.getSelectedGpxHelper().getSelectedCurrentRecordingTrack() != null) ||
|
||||
(gpxFile.path != null && app.getSelectedGpxHelper().getSelectedFileByPath(gpxFile.path) != null));
|
||||
|
@ -543,12 +540,6 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private QuadRect getRect() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
return activity != null ? activity.getRect() : null;
|
||||
}
|
||||
|
||||
public boolean isShowOnMap() {
|
||||
return vis != null && vis.isChecked();
|
||||
}
|
||||
|
@ -564,42 +555,6 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
menuFab.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<GpxDisplayGroup> getOriginalGroups() {
|
||||
return filterGroups(false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<GpxDisplayGroup> getDisplayGroups() {
|
||||
return filterGroups(true);
|
||||
}
|
||||
|
||||
private boolean hasFilterType(GpxDisplayItemType filterType) {
|
||||
for (GpxDisplayItemType type : filterTypes) {
|
||||
if (type == filterType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<GpxDisplayGroup> filterGroups(boolean useDisplayGroups) {
|
||||
List<GpxDisplayGroup> groups = new ArrayList<>();
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
List<GpxDisplayGroup> result = activity.getGpxFile(useDisplayGroups);
|
||||
for (GpxDisplayGroup group : result) {
|
||||
boolean add = hasFilterType(group.getType());
|
||||
if (add) {
|
||||
groups.add(group);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
private void updateTrackColor() {
|
||||
int color = getGpxDataItem() != null ? getGpxDataItem().getColor() : 0;
|
||||
GPXFile gpxFile = getGpx();
|
||||
|
@ -621,14 +576,6 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
}
|
||||
|
||||
public List<GpxSelectionHelper.GpxDisplayItem> flatten(List<GpxDisplayGroup> groups) {
|
||||
ArrayList<GpxSelectionHelper.GpxDisplayItem> list = new ArrayList<>();
|
||||
for (GpxDisplayGroup g : groups) {
|
||||
list.addAll(g.getModifiableList());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void hideTransparentOverlay() {
|
||||
overlayView.setVisibility(View.GONE);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ import com.google.android.material.snackbar.Snackbar;
|
|||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.Collator;
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.OsmAndCollator;
|
||||
|
@ -59,7 +58,6 @@ import net.osmand.plus.UiUtilities;
|
|||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.OsmandActionBarActivity;
|
||||
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
|
||||
import net.osmand.plus.activities.SavingTrackHelper;
|
||||
import net.osmand.plus.activities.TrackActivity;
|
||||
import net.osmand.plus.base.OsmandExpandableListFragment;
|
||||
import net.osmand.plus.base.PointImageDrawable;
|
||||
|
@ -67,14 +65,16 @@ import net.osmand.plus.helpers.GpxUiHelper;
|
|||
import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersHelper;
|
||||
import net.osmand.plus.myplaces.DeletePointsTask.OnPointsDeleteListener;
|
||||
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.plus.track.TrackMenuFragment;
|
||||
import net.osmand.plus.widgets.TextViewEx;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -88,7 +88,7 @@ import java.util.Map.Entry;
|
|||
import java.util.Set;
|
||||
|
||||
|
||||
public class TrackPointFragment extends OsmandExpandableListFragment implements TrackBitmapDrawerListener {
|
||||
public class TrackPointFragment extends OsmandExpandableListFragment implements TrackBitmapDrawerListener, OnPointsDeleteListener {
|
||||
|
||||
public static final int SEARCH_ID = -1;
|
||||
public static final int DELETE_ID = 2;
|
||||
|
@ -105,6 +105,8 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
private OsmandApplication app;
|
||||
private TrackActivityFragmentAdapter fragmentAdapter;
|
||||
final private PointGPXAdapter adapter = new PointGPXAdapter();
|
||||
private GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_POINTS, GpxDisplayItemType.TRACK_ROUTE_POINTS};
|
||||
private TrackDisplayHelper displayHelper;
|
||||
|
||||
private boolean selectionMode;
|
||||
private LinkedHashMap<GpxDisplayItemType, Set<GpxDisplayItem>> selectedItems = new LinkedHashMap<>();
|
||||
|
@ -120,6 +122,13 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
this.app = getMyApplication();
|
||||
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof TrackActivity) {
|
||||
displayHelper = ((TrackActivity) activity).getDisplayHelper();
|
||||
} else if (getTargetFragment() instanceof TrackMenuFragment) {
|
||||
displayHelper = ((TrackMenuFragment) getTargetFragment()).getDisplayHelper();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -135,8 +144,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
mainView = inflater.inflate(R.layout.track_points_tree, container, false);
|
||||
ExpandableListView listView = (ExpandableListView) mainView.findViewById(android.R.id.list);
|
||||
|
||||
fragmentAdapter = new TrackActivityFragmentAdapter(app, this, listView,
|
||||
GpxDisplayItemType.TRACK_POINTS, GpxDisplayItemType.TRACK_ROUTE_POINTS);
|
||||
fragmentAdapter = new TrackActivityFragmentAdapter(app, this, listView, displayHelper, filterTypes);
|
||||
fragmentAdapter.setShowMapOnly(true);
|
||||
fragmentAdapter.setTrackBitmapSelectionSupported(false);
|
||||
fragmentAdapter.setShowDescriptionCard(true);
|
||||
|
@ -165,15 +173,10 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
if (optionsMenu != null) {
|
||||
optionsMenu.close();
|
||||
}
|
||||
if (fragmentAdapter != null) {
|
||||
if (fragmentAdapter.splitListPopupWindow != null) {
|
||||
fragmentAdapter.splitListPopupWindow.dismiss();
|
||||
}
|
||||
if (fragmentAdapter.colorListPopupWindow != null) {
|
||||
if (fragmentAdapter != null && fragmentAdapter.colorListPopupWindow != null) {
|
||||
fragmentAdapter.colorListPopupWindow.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
|
@ -192,7 +195,6 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private int getSelectedItemsCount() {
|
||||
int count = 0;
|
||||
for (Set<GpxDisplayItem> set : selectedItems.values()) {
|
||||
|
@ -213,21 +215,14 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TrackActivity getTrackActivity() {
|
||||
return (TrackActivity) getActivity();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GPXFile getGpx() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
return activity != null ? activity.getGpx() : null;
|
||||
return displayHelper.getGpx();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GpxDataItem getGpxDataItem() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
return activity != null ? activity.getGpxDataItem() : null;
|
||||
return displayHelper.getGpxDataItem();
|
||||
}
|
||||
|
||||
private void expandAllGroups() {
|
||||
|
@ -250,7 +245,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
|
||||
@Nullable
|
||||
private List<GpxDisplayGroup> getOriginalGroups() {
|
||||
return fragmentAdapter != null ? fragmentAdapter.getOriginalGroups() : null;
|
||||
return displayHelper.getOriginalGroups(filterTypes);
|
||||
}
|
||||
|
||||
public void setContent() {
|
||||
|
@ -495,13 +490,13 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
}
|
||||
|
||||
private void deleteItems() {
|
||||
new DeletePointsTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
new DeletePointsTask(app, getGpx(), getSelectedItems(), this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void addOrRemoveMapMarkersSyncGroup() {
|
||||
final MapMarkersHelper markersHelper = app.getMapMarkersHelper();
|
||||
|
||||
TrackActivity activity = getTrackActivity();
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -536,7 +531,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
.setAction(R.string.shared_string_undo, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
FragmentActivity trackActivity = getActivity();
|
||||
if (trackActivity != null) {
|
||||
if (markersRemoved) {
|
||||
if (gpxFile != null) {
|
||||
|
@ -606,7 +601,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
}
|
||||
|
||||
private void selectFavoritesImpl() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null && getSelectedItemsCount() > 0) {
|
||||
AlertDialog.Builder b = new AlertDialog.Builder(activity);
|
||||
final EditText editText = new EditText(activity);
|
||||
|
@ -684,16 +679,13 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
} else {
|
||||
GPXFile gpx = item.group.getGpx();
|
||||
if (gpx != null) {
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
if (trackActivity != null && fragmentAdapter != null) {
|
||||
boolean gpxFileSelected = fragmentAdapter.isGpxFileSelected(gpx);
|
||||
if (!gpxFileSelected) {
|
||||
Intent intent = trackActivity.getIntent();
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null && !TrackActivityFragmentAdapter.isGpxFileSelected(app, gpx)) {
|
||||
Intent intent = activity.getIntent();
|
||||
if (intent != null) {
|
||||
intent.putExtra(TrackActivity.SHOW_TEMPORARILY, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
app.getSelectedGpxHelper().setGpxFileToDisplay(gpx);
|
||||
}
|
||||
final OsmandSettings settings = app.getSettings();
|
||||
|
@ -741,6 +733,23 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointsDeletionStarted() {
|
||||
showProgressBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointsDeleted() {
|
||||
selectedItems.clear();
|
||||
selectedGroups.clear();
|
||||
|
||||
hideProgressBar();
|
||||
List<GpxDisplayGroup> groups = getOriginalGroups();
|
||||
if (groups != null) {
|
||||
adapter.synchronizeGroups(groups);
|
||||
}
|
||||
}
|
||||
|
||||
class PointGPXAdapter extends OsmandBaseExpandableListAdapter implements Filterable {
|
||||
|
||||
Map<GpxDisplayGroup, List<GpxDisplayItem>> itemGroups = new LinkedHashMap<>();
|
||||
|
@ -1199,9 +1208,6 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
|
||||
public class PointsFilter extends Filter {
|
||||
|
||||
PointsFilter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence constraint) {
|
||||
FilterResults results = new FilterResults();
|
||||
|
@ -1243,77 +1249,4 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
expandAllGroups();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DeletePointsTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private OsmandApplication app;
|
||||
private WeakReference<TrackPointFragment> fragmentRef;
|
||||
private GPXFile gpx;
|
||||
private Set<GpxDisplayItem> selectedItems;
|
||||
|
||||
DeletePointsTask(TrackPointFragment fragment) {
|
||||
this.app = fragment.getMyApplication();
|
||||
this.fragmentRef = new WeakReference<>(fragment);
|
||||
this.gpx = fragment.getGpx();
|
||||
this.selectedItems = fragment.getSelectedItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
TrackPointFragment fragment = fragmentRef.get();
|
||||
if (fragment != null) {
|
||||
fragment.showProgressBar();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
SavingTrackHelper savingTrackHelper = app.getSavingTrackHelper();
|
||||
if (gpx != null) {
|
||||
for (GpxDisplayItem item : selectedItems) {
|
||||
if (gpx.showCurrentTrack) {
|
||||
savingTrackHelper.deletePointData(item.locationStart);
|
||||
} else {
|
||||
if (item.group.getType() == GpxDisplayItemType.TRACK_POINTS) {
|
||||
gpx.deleteWptPt(item.locationStart);
|
||||
} else if (item.group.getType() == GpxDisplayItemType.TRACK_ROUTE_POINTS) {
|
||||
gpx.deleteRtePt(item.locationStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gpx.showCurrentTrack) {
|
||||
GPXUtilities.writeGpxFile(new File(gpx.path), gpx);
|
||||
boolean selected = app.getSelectedGpxHelper().getSelectedFileByPath(gpx.path) != null;
|
||||
if (selected) {
|
||||
app.getSelectedGpxHelper().setGpxFileToDisplay(gpx);
|
||||
}
|
||||
}
|
||||
syncGpx(gpx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
TrackPointFragment fragment = fragmentRef.get();
|
||||
if (fragment != null) {
|
||||
fragment.selectedItems.clear();
|
||||
fragment.selectedGroups.clear();
|
||||
|
||||
fragment.hideProgressBar();
|
||||
List<GpxDisplayGroup> groups = fragment.getOriginalGroups();
|
||||
if (groups != null) {
|
||||
fragment.adapter.synchronizeGroups(groups);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void syncGpx(GPXFile gpxFile) {
|
||||
MapMarkersHelper helper = app.getMapMarkersHelper();
|
||||
MapMarkersGroup group = helper.getMarkersGroup(gpxFile);
|
||||
if (group != null) {
|
||||
helper.runSynchronization(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
57
OsmAnd/src/net/osmand/plus/track/SegmentsCard.java
Normal file
57
OsmAnd/src/net/osmand/plus/track/SegmentsCard.java
Normal file
|
@ -0,0 +1,57 @@
|
|||
package net.osmand.plus.track;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.myplaces.GPXItemPagerAdapter;
|
||||
import net.osmand.plus.myplaces.SegmentActionsListener;
|
||||
import net.osmand.plus.myplaces.SegmentGPXAdapter;
|
||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
|
||||
import net.osmand.plus.views.controls.WrapContentHeightViewPager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SegmentsCard extends BaseCard {
|
||||
|
||||
private TrackDisplayHelper displayHelper;
|
||||
private GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT};
|
||||
private SegmentGPXAdapter adapter;
|
||||
private SegmentActionsListener listener;
|
||||
|
||||
public SegmentsCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull SegmentActionsListener listener) {
|
||||
super(mapActivity);
|
||||
this.displayHelper = displayHelper;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCardLayoutId() {
|
||||
return R.layout.track_segments_container;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateContent() {
|
||||
ViewGroup container = (ViewGroup) view;
|
||||
container.removeAllViews();
|
||||
List<GpxDisplayItem> items = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes));
|
||||
for (GpxDisplayItem displayItem : items) {
|
||||
View segmentView = SegmentGPXAdapter.createGpxTabsView(displayHelper, container, listener, nightMode);
|
||||
|
||||
WrapContentHeightViewPager pager = segmentView.findViewById(R.id.pager);
|
||||
PagerSlidingTabStrip tabLayout = segmentView.findViewById(R.id.sliding_tabs);
|
||||
|
||||
pager.setAdapter(new GPXItemPagerAdapter(tabLayout, displayItem, displayHelper, listener));
|
||||
tabLayout.setViewPager(pager);
|
||||
|
||||
container.addView(segmentView);
|
||||
}
|
||||
}
|
||||
}
|
179
OsmAnd/src/net/osmand/plus/track/TrackDisplayHelper.java
Normal file
179
OsmAnd/src/net/osmand/plus/track/TrackDisplayHelper.java
Normal file
|
@ -0,0 +1,179 @@
|
|||
package net.osmand.plus.track;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.PointDescription;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.plus.GPXDatabase.GpxDataItem;
|
||||
import net.osmand.plus.GpxSelectionHelper;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.measurementtool.GpxData;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TrackDisplayHelper {
|
||||
|
||||
private final OsmandApplication app;
|
||||
|
||||
private File file;
|
||||
private GPXFile gpxFile;
|
||||
private GpxDataItem gpxDataItem;
|
||||
|
||||
private long modifiedTime = -1;
|
||||
private List<GpxDisplayGroup> displayGroups;
|
||||
private List<GpxDisplayGroup> originalGroups = new ArrayList<>();
|
||||
|
||||
public TrackDisplayHelper(OsmandApplication app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GPXFile getGpx() {
|
||||
return gpxFile;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GpxDataItem getGpxDataItem() {
|
||||
return gpxDataItem;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public void setFile(@Nullable File file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public void setGpx(@NonNull GPXFile result) {
|
||||
this.gpxFile = result;
|
||||
if (file == null) {
|
||||
this.gpxFile = app.getSavingTrackHelper().getCurrentGpx();
|
||||
}
|
||||
}
|
||||
|
||||
public void setGpxDataItem(GpxDataItem gpxDataItem) {
|
||||
this.gpxDataItem = gpxDataItem;
|
||||
}
|
||||
|
||||
public QuadRect getRect() {
|
||||
if (getGpx() != null) {
|
||||
return getGpx().getRect();
|
||||
} else {
|
||||
return new QuadRect(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setJoinSegments(boolean joinSegments) {
|
||||
if (gpxDataItem != null) {
|
||||
boolean updated = app.getGpxDbHelper().updateJoinSegments(gpxDataItem, joinSegments);
|
||||
|
||||
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFile.path);
|
||||
if (updated && selectedGpxFile != null) {
|
||||
selectedGpxFile.setJoinSegments(joinSegments);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isJoinSegments() {
|
||||
return gpxDataItem != null && gpxDataItem.isJoinSegments();
|
||||
}
|
||||
|
||||
public List<GpxDisplayGroup> getGpxFile(boolean useDisplayGroups) {
|
||||
if (gpxFile == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
if (gpxFile.modifiedTime != modifiedTime) {
|
||||
modifiedTime = gpxFile.modifiedTime;
|
||||
GpxSelectionHelper selectedGpxHelper = app.getSelectedGpxHelper();
|
||||
displayGroups = selectedGpxHelper.collectDisplayGroups(gpxFile);
|
||||
originalGroups.clear();
|
||||
for (GpxSelectionHelper.GpxDisplayGroup g : displayGroups) {
|
||||
originalGroups.add(g.cloneInstance());
|
||||
}
|
||||
if (file != null) {
|
||||
SelectedGpxFile sf = selectedGpxHelper.getSelectedFileByPath(gpxFile.path);
|
||||
if (sf != null && file != null && sf.getDisplayGroups(app) != null) {
|
||||
displayGroups = sf.getDisplayGroups(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (useDisplayGroups) {
|
||||
return displayGroups;
|
||||
} else {
|
||||
return originalGroups;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<GpxDisplayGroup> getOriginalGroups(GpxDisplayItemType[] filterTypes) {
|
||||
return filterGroups(false, filterTypes);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<GpxDisplayGroup> getDisplayGroups(GpxDisplayItemType[] filterTypes) {
|
||||
return filterGroups(true, filterTypes);
|
||||
}
|
||||
|
||||
private boolean hasFilterType(GpxDisplayItemType filterType, GpxDisplayItemType[] filterTypes) {
|
||||
for (GpxDisplayItemType type : filterTypes) {
|
||||
if (type == filterType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<GpxDisplayGroup> filterGroups(boolean useDisplayGroups, GpxDisplayItemType[] filterTypes) {
|
||||
List<GpxDisplayGroup> groups = new ArrayList<>();
|
||||
for (GpxDisplayGroup group : getGpxFile(useDisplayGroups)) {
|
||||
if (hasFilterType(group.getType(), filterTypes)) {
|
||||
groups.add(group);
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
public static List<GpxDisplayItem> flatten(List<GpxDisplayGroup> groups) {
|
||||
ArrayList<GpxDisplayItem> list = new ArrayList<>();
|
||||
for (GpxDisplayGroup g : groups) {
|
||||
list.addAll(g.getModifiableList());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void addNewGpxData(Activity activity) {
|
||||
GPXFile gpxFile = getGpx();
|
||||
GpxData gpxData = new GpxData(gpxFile);
|
||||
WptPt pointToShow = gpxFile != null ? gpxFile.findPointToShow() : null;
|
||||
if (pointToShow != null) {
|
||||
LatLon location = new LatLon(pointToShow.getLatitude(), pointToShow.getLongitude());
|
||||
final OsmandSettings settings = app.getSettings();
|
||||
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
|
||||
settings.getLastKnownMapZoom(),
|
||||
new PointDescription(PointDescription.POINT_TYPE_WPT, activity.getString(R.string.add_line)),
|
||||
false,
|
||||
gpxData
|
||||
);
|
||||
MapActivity.launchMapActivityMoveToTop(activity);
|
||||
}
|
||||
}
|
||||
}
|
596
OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java
Normal file
596
OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java
Normal file
|
@ -0,0 +1,596 @@
|
|||
package net.osmand.plus.track;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.Track;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.data.RotatedTileBox;
|
||||
import net.osmand.plus.GPXDatabase.GpxDataItem;
|
||||
import net.osmand.plus.GpxDbHelper;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.base.ContextMenuFragment;
|
||||
import net.osmand.plus.base.ContextMenuScrollFragment;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
|
||||
import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenu;
|
||||
import net.osmand.plus.measurementtool.GpxData;
|
||||
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
||||
import net.osmand.plus.measurementtool.MeasurementToolFragment;
|
||||
import net.osmand.plus.myplaces.GPXTabItemType;
|
||||
import net.osmand.plus.myplaces.SegmentActionsListener;
|
||||
import net.osmand.plus.myplaces.SplitSegmentDialogFragment;
|
||||
import net.osmand.plus.myplaces.TrackActivityFragmentAdapter;
|
||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
|
||||
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
|
||||
import net.osmand.plus.widgets.IconPopupMenu;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING;
|
||||
import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME;
|
||||
|
||||
public class TrackMenuFragment extends ContextMenuScrollFragment implements CardListener, SegmentActionsListener {
|
||||
|
||||
public static final String TAG = TrackMenuFragment.class.getName();
|
||||
private static final Log log = PlatformUtil.getLog(TrackMenuFragment.class);
|
||||
|
||||
private OsmandApplication app;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
|
||||
private GpxDataItem gpxDataItem;
|
||||
private SelectedGpxFile selectedGpxFile;
|
||||
|
||||
private View routeMenuTopShadowAll;
|
||||
private BottomNavigationView bottomNav;
|
||||
private TrackMenuType menuType = TrackMenuType.TRACK;
|
||||
private SegmentsCard segmentsCard;
|
||||
|
||||
private int menuTitleHeight;
|
||||
|
||||
public enum TrackMenuType {
|
||||
TRACK(R.id.action_track, R.string.shared_string_gpx_tracks),
|
||||
POINTS(R.id.action_points, R.string.shared_string_gpx_points);
|
||||
|
||||
TrackMenuType(@DrawableRes int iconId, @StringRes int titleId) {
|
||||
this.iconId = iconId;
|
||||
this.titleId = titleId;
|
||||
}
|
||||
|
||||
public final int iconId;
|
||||
public final int titleId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMainLayoutId() {
|
||||
return R.layout.track_menu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeaderViewHeight() {
|
||||
return menuTitleHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHeaderViewDetached() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getToolbarHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public float getMiddleStateKoef() {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSupportedMenuStatesPortrait() {
|
||||
return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN | MenuState.FULL_SCREEN;
|
||||
}
|
||||
|
||||
public TrackDisplayHelper getDisplayHelper() {
|
||||
return displayHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
app = requireMyApplication();
|
||||
GpxDbHelper gpxDbHelper = app.getGpxDbHelper();
|
||||
displayHelper = new TrackDisplayHelper(app);
|
||||
|
||||
String gpxFilePath = "";
|
||||
boolean currentRecording = false;
|
||||
Bundle arguments = getArguments();
|
||||
if (savedInstanceState != null) {
|
||||
gpxFilePath = savedInstanceState.getString(TRACK_FILE_NAME);
|
||||
currentRecording = savedInstanceState.getBoolean(CURRENT_RECORDING, false);
|
||||
} else if (arguments != null) {
|
||||
gpxFilePath = arguments.getString(TRACK_FILE_NAME);
|
||||
currentRecording = arguments.getBoolean(CURRENT_RECORDING, false);
|
||||
}
|
||||
if (currentRecording) {
|
||||
selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack();
|
||||
} else {
|
||||
File file = new File(gpxFilePath);
|
||||
displayHelper.setFile(file);
|
||||
gpxDataItem = gpxDbHelper.getItem(file);
|
||||
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
|
||||
}
|
||||
displayHelper.setGpxDataItem(gpxDataItem);
|
||||
displayHelper.setGpx(selectedGpxFile.getGpxFile());
|
||||
}
|
||||
|
||||
public GPXFile getGpx() {
|
||||
return displayHelper.getGpx();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||
if (view != null) {
|
||||
bottomNav = view.findViewById(R.id.bottom_navigation);
|
||||
routeMenuTopShadowAll = view.findViewById(R.id.route_menu_top_shadow_all);
|
||||
TextView title = view.findViewById(R.id.title);
|
||||
String fileName = Algorithms.getFileWithoutDirs(getGpx().path);
|
||||
title.setText(GpxUiHelper.getGpxTitle(fileName));
|
||||
|
||||
if (isPortrait()) {
|
||||
updateCardsLayout();
|
||||
}
|
||||
setupCards();
|
||||
setupButtons(view);
|
||||
enterTrackAppearanceMode();
|
||||
runLayoutListener();
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
private void setupCards() {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
ViewGroup cardsContainer = getCardsContainer();
|
||||
cardsContainer.removeAllViews();
|
||||
if (menuType == TrackMenuType.TRACK) {
|
||||
if (segmentsCard != null) {
|
||||
cardsContainer.addView(segmentsCard.getView());
|
||||
} else {
|
||||
segmentsCard = new SegmentsCard(mapActivity, displayHelper, this);
|
||||
cardsContainer.addView(segmentsCard.build(mapActivity));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void calculateLayout(View view, boolean initLayout) {
|
||||
menuTitleHeight = routeMenuTopShadowAll.getHeight()
|
||||
+ bottomNav.getHeight();
|
||||
super.calculateLayout(view, initLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setViewY(int y, boolean animated, boolean adjustMapPos) {
|
||||
super.setViewY(y, animated, adjustMapPos);
|
||||
updateStatusBarColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateMainViewLayout(int posY) {
|
||||
super.updateMainViewLayout(posY);
|
||||
updateStatusBarColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShowMapControls(int menuState) {
|
||||
return menuState == MenuState.HEADER_ONLY || menuState == MenuState.HALF_SCREEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
adjustMapPosition(getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
exitTrackAppearanceMode();
|
||||
}
|
||||
|
||||
private void enterTrackAppearanceMode() {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
boolean portrait = AndroidUiHelper.isOrientationPortrait(mapActivity);
|
||||
AndroidUiHelper.setVisibility(mapActivity, portrait ? View.INVISIBLE : View.GONE,
|
||||
R.id.map_left_widgets_panel,
|
||||
R.id.map_right_widgets_panel,
|
||||
R.id.map_center_info);
|
||||
}
|
||||
}
|
||||
|
||||
private void exitTrackAppearanceMode() {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
AndroidUiHelper.setVisibility(mapActivity, View.VISIBLE,
|
||||
R.id.map_left_widgets_panel,
|
||||
R.id.map_right_widgets_panel,
|
||||
R.id.map_center_info,
|
||||
R.id.map_search_button);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
outState.putString(TRACK_FILE_NAME, getGpx().path);
|
||||
outState.putBoolean(CURRENT_RECORDING, selectedGpxFile.isShowCurrentTrack());
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatusBarColorId() {
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
boolean nightMode = isNightMode();
|
||||
if (getViewY() <= getFullScreenTopPosY() || !isPortrait()) {
|
||||
if (Build.VERSION.SDK_INT >= 23 && !nightMode) {
|
||||
view.setSystemUiVisibility(view.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
}
|
||||
return nightMode ? R.color.divider_color_dark : R.color.divider_color_light;
|
||||
} else {
|
||||
if (Build.VERSION.SDK_INT >= 23 && !nightMode) {
|
||||
view.setSystemUiVisibility(view.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void updateStatusBarColor() {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
mapActivity.updateStatusBarColor();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getThemeInfoProviderTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCardLayoutNeeded(@NonNull BaseCard card) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCardPressed(@NonNull BaseCard card) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCardButtonPressed(@NonNull BaseCard card, int buttonIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int applyPosY(int currentY, boolean needCloseMenu, boolean needMapAdjust, int previousMenuState, int newMenuState, int dZoom, boolean animated) {
|
||||
int y = super.applyPosY(currentY, needCloseMenu, needMapAdjust, previousMenuState, newMenuState, dZoom, animated);
|
||||
if (needMapAdjust) {
|
||||
adjustMapPosition(y);
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHeaderClick() {
|
||||
adjustMapPosition(getViewY());
|
||||
}
|
||||
|
||||
private void adjustMapPosition(int y) {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null && mapActivity.getMapView() != null) {
|
||||
GPXFile gpxFile = getGpx();
|
||||
QuadRect r = gpxFile.getRect();
|
||||
|
||||
RotatedTileBox tb = mapActivity.getMapView().getCurrentRotatedTileBox().copy();
|
||||
int tileBoxWidthPx = 0;
|
||||
int tileBoxHeightPx = 0;
|
||||
|
||||
if (!isPortrait()) {
|
||||
tileBoxWidthPx = tb.getPixWidth() - getWidth();
|
||||
} else {
|
||||
int fHeight = getViewHeight() - y - AndroidUtils.getStatusBarHeight(mapActivity);
|
||||
tileBoxHeightPx = tb.getPixHeight() - fHeight;
|
||||
}
|
||||
if (r.left != 0 && r.right != 0) {
|
||||
mapActivity.getMapView().fitRectToMap(r.left, r.right, r.top, r.bottom, tileBoxWidthPx, tileBoxHeightPx, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCardsLayout() {
|
||||
View mainView = getMainView();
|
||||
if (mainView != null) {
|
||||
View topShadow = getTopShadow();
|
||||
FrameLayout bottomContainer = getBottomContainer();
|
||||
if (getCurrentMenuState() == MenuState.HEADER_ONLY) {
|
||||
topShadow.setVisibility(View.INVISIBLE);
|
||||
bottomContainer.setBackgroundDrawable(null);
|
||||
} else {
|
||||
topShadow.setVisibility(View.VISIBLE);
|
||||
AndroidUtils.setBackground(mainView.getContext(), bottomContainer, isNightMode(), R.color.list_background_color_light, R.color.list_background_color_dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setupButtons(View view) {
|
||||
ColorStateList navColorStateList = AndroidUtils.createBottomNavColorStateList(getContext(), isNightMode());
|
||||
BottomNavigationView bottomNav = view.findViewById(R.id.bottom_navigation);
|
||||
bottomNav.setItemIconTintList(navColorStateList);
|
||||
bottomNav.setItemTextColor(navColorStateList);
|
||||
bottomNav.setSelectedItemId(R.id.action_track);
|
||||
bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||
for (TrackMenuType type : TrackMenuType.values()) {
|
||||
if (type.iconId == item.getItemId()) {
|
||||
menuType = type;
|
||||
setupCards();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateContent() {
|
||||
if (segmentsCard != null) {
|
||||
segmentsCard.updateContent();
|
||||
}
|
||||
setupCards();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartTouch() {
|
||||
getBottomScrollView().requestDisallowInterceptTouchEvent(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollBy(int px) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointSelected(double lat, double lon) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openSplitInterval(GpxDisplayItem gpxItem, TrkSegment trkSegment) {
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
if (fragmentManager != null) {
|
||||
SplitSegmentDialogFragment.showInstance(fragmentManager, displayHelper, gpxItem, trkSegment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openAnalyzeOnMap(GpxDisplayItem gpxItem, List<ILineDataSet> dataSets, GPXTabItemType tabType) {
|
||||
WptPt wpt = null;
|
||||
gpxItem.chartTypes = null;
|
||||
if (dataSets != null && dataSets.size() > 0) {
|
||||
gpxItem.chartTypes = new GPXDataSetType[dataSets.size()];
|
||||
for (int i = 0; i < dataSets.size(); i++) {
|
||||
OrderedLineDataSet orderedDataSet = (OrderedLineDataSet) dataSets.get(i);
|
||||
gpxItem.chartTypes[i] = orderedDataSet.getDataSetType();
|
||||
}
|
||||
if (gpxItem.chartHighlightPos != -1) {
|
||||
TrkSegment segment = null;
|
||||
for (Track t : gpxItem.group.getGpx().tracks) {
|
||||
for (TrkSegment s : t.segments) {
|
||||
if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
|
||||
segment = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (segment != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (segment != null) {
|
||||
OrderedLineDataSet dataSet = (OrderedLineDataSet) dataSets.get(0);
|
||||
float distance = gpxItem.chartHighlightPos * dataSet.getDivX();
|
||||
for (WptPt p : segment.points) {
|
||||
if (p.distance >= distance) {
|
||||
wpt = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wpt != null) {
|
||||
gpxItem.locationOnMap = wpt;
|
||||
} else {
|
||||
gpxItem.locationOnMap = gpxItem.locationStart;
|
||||
}
|
||||
|
||||
TrackDetailsMenu trackDetailsMenu = getMapActivity().getTrackDetailsMenu();
|
||||
trackDetailsMenu.setGpxItem(gpxItem);
|
||||
trackDetailsMenu.show();
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showOptionsPopupMenu(View view, final TrkSegment segment, final boolean confirmDeletion) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
IconPopupMenu optionsPopupMenu = new IconPopupMenu(activity, view.findViewById(R.id.overflow_menu));
|
||||
Menu menu = optionsPopupMenu.getMenu();
|
||||
optionsPopupMenu.getMenuInflater().inflate(R.menu.track_segment_menu, menu);
|
||||
menu.findItem(R.id.action_edit).setIcon(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_edit_dark));
|
||||
menu.findItem(R.id.action_delete).setIcon(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_remove_dark));
|
||||
optionsPopupMenu.setOnMenuItemClickListener(new IconPopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
int i = item.getItemId();
|
||||
if (i == R.id.action_edit) {
|
||||
editSegment(segment);
|
||||
return true;
|
||||
} else if (i == R.id.action_delete) {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (!confirmDeletion) {
|
||||
deleteAndSaveSegment(segment);
|
||||
} else if (activity != null) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setMessage(R.string.recording_delete_confirm);
|
||||
builder.setPositiveButton(R.string.shared_string_yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
deleteAndSaveSegment(segment);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.shared_string_cancel, null);
|
||||
builder.show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
optionsPopupMenu.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void editSegment(TrkSegment segment) {
|
||||
GPXFile gpxFile = getGpx();
|
||||
openPlanRoute(new GpxData(gpxFile));
|
||||
close();
|
||||
}
|
||||
|
||||
public void openPlanRoute(GpxData gpxData) {
|
||||
QuadRect qr = gpxData.getRect();
|
||||
getMapActivity().getMapView().fitRectToMap(qr.left, qr.right, qr.top, qr.bottom, (int) qr.width(), (int) qr.height(), 0);
|
||||
MeasurementEditingContext editingContext = new MeasurementEditingContext();
|
||||
editingContext.setGpxData(gpxData);
|
||||
MeasurementToolFragment.showInstance(getFragmentManager(), editingContext);
|
||||
}
|
||||
|
||||
private void deleteAndSaveSegment(TrkSegment segment) {
|
||||
if (deleteSegment(segment)) {
|
||||
GPXFile gpx = displayHelper.getGpx();
|
||||
if (gpx != null) {
|
||||
boolean showOnMap = TrackActivityFragmentAdapter.isGpxFileSelected(app, gpx);
|
||||
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().selectGpxFile(gpx, showOnMap, false);
|
||||
saveGpx(showOnMap ? selectedGpxFile : null, gpx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean deleteSegment(TrkSegment segment) {
|
||||
if (segment != null) {
|
||||
GPXFile gpx = displayHelper.getGpx();
|
||||
if (gpx != null) {
|
||||
return gpx.removeTrkSegment(segment);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void saveGpx(final SelectedGpxFile selectedGpxFile, GPXFile gpxFile) {
|
||||
new SaveGpxAsyncTask(new File(gpxFile.path), gpxFile, new SaveGpxListener() {
|
||||
@Override
|
||||
public void gpxSavingStarted() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gpxSavingFinished(Exception errorMessage) {
|
||||
if (selectedGpxFile != null) {
|
||||
List<GpxDisplayGroup> groups = displayHelper.getDisplayGroups(new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT});
|
||||
if (groups != null) {
|
||||
selectedGpxFile.setDisplayGroups(groups, app);
|
||||
selectedGpxFile.processPoints(app);
|
||||
}
|
||||
}
|
||||
updateContent();
|
||||
}
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void close() {
|
||||
try {
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
FragmentManager fragmentManager = mapActivity.getSupportFragmentManager();
|
||||
fragmentManager.beginTransaction().remove(this).commitAllowingStateLoss();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean showInstance(@NonNull MapActivity mapActivity, String path, boolean showCurrentTrack) {
|
||||
try {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(TRACK_FILE_NAME, path);
|
||||
args.putBoolean(CURRENT_RECORDING, showCurrentTrack);
|
||||
args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuState.HALF_SCREEN);
|
||||
|
||||
TrackMenuFragment fragment = new TrackMenuFragment();
|
||||
fragment.setArguments(args);
|
||||
|
||||
mapActivity.getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.replace(R.id.fragmentContainer, fragment, fragment.getFragmentTag())
|
||||
.addToBackStack(fragment.getFragmentTag())
|
||||
.commitAllowingStateLoss();
|
||||
return true;
|
||||
} catch (RuntimeException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue