Merge pull request #10655 from osmandapp/points_menu_gpx
Points GPX context menu
This commit is contained in:
commit
d224fdecaa
19 changed files with 1299 additions and 122 deletions
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/search_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="56dp"
|
android:layout_height="56dp"
|
||||||
android:focusableInTouchMode="true"
|
android:focusableInTouchMode="true"
|
||||||
|
|
|
@ -43,8 +43,8 @@
|
||||||
android:paddingStart="@dimen/context_menu_padding_margin_default"
|
android:paddingStart="@dimen/context_menu_padding_margin_default"
|
||||||
android:paddingLeft="@dimen/context_menu_padding_margin_default"
|
android:paddingLeft="@dimen/context_menu_padding_margin_default"
|
||||||
android:paddingEnd="@dimen/context_menu_padding_margin_default"
|
android:paddingEnd="@dimen/context_menu_padding_margin_default"
|
||||||
android:paddingRight="@dimen/context_menu_padding_margin_default"
|
android:paddingRight="@dimen/context_menu_padding_margin_default"
|
||||||
android:paddingBottom="@dimen/context_menu_direction_margin">
|
android:paddingBottom="@dimen/context_menu_direction_margin">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:text="@string/amenity_type_finance" />
|
tools:text="@string/amenity_type_finance" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@
|
||||||
android:id="@+id/icon_view"
|
android:id="@+id/icon_view"
|
||||||
android:layout_width="@dimen/map_widget_icon"
|
android:layout_width="@dimen/map_widget_icon"
|
||||||
android:layout_height="@dimen/map_widget_icon"
|
android:layout_height="@dimen/map_widget_icon"
|
||||||
android:layout_marginTop="@dimen/context_menu_second_line_top_margin"
|
android:layout_marginTop="@dimen/context_menu_second_line_top_margin"
|
||||||
android:tint="?attr/default_icon_color"
|
android:tint="?attr/default_icon_color"
|
||||||
osmand:srcCompat="@drawable/ic_action_polygom_dark" />
|
osmand:srcCompat="@drawable/ic_action_polygom_dark" />
|
||||||
|
|
||||||
|
@ -118,6 +118,79 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/context_menu_toolbar_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:alpha="0">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/actionModeBackground"
|
||||||
|
android:minHeight="@dimen/toolbar_height"
|
||||||
|
android:padding="0dp"
|
||||||
|
osmand:contentInsetEnd="0dp"
|
||||||
|
osmand:contentInsetLeft="0dp"
|
||||||
|
osmand:contentInsetRight="0dp"
|
||||||
|
osmand:contentInsetStart="0dp"
|
||||||
|
osmand:theme="@style/ThemeOverlay.AppCompat.ActionBar">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:minHeight="@dimen/toolbar_height">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/close_button"
|
||||||
|
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
|
||||||
|
android:layout_width="@dimen/toolbar_height"
|
||||||
|
android:layout_height="@dimen/toolbar_height"
|
||||||
|
android:contentDescription="@string/access_shared_string_navigate_up"
|
||||||
|
osmand:srcCompat="@drawable/ic_arrow_back" />
|
||||||
|
|
||||||
|
<net.osmand.plus.widgets.TextViewEx
|
||||||
|
android:id="@+id/toolbar_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/content_padding"
|
||||||
|
android:layout_marginLeft="@dimen/content_padding"
|
||||||
|
android:layout_marginEnd="@dimen/content_padding"
|
||||||
|
android:layout_marginRight="@dimen/content_padding"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textColor="?attr/app_bar_primary_item_color"
|
||||||
|
android:textSize="@dimen/dialog_header_text_size"
|
||||||
|
osmand:typeface="@string/font_roboto_medium"
|
||||||
|
tools:text="@string/routing_settings_2" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/search_text_layout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/search_button"
|
||||||
|
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
|
||||||
|
android:layout_width="@dimen/toolbar_height"
|
||||||
|
android:layout_height="@dimen/toolbar_height"
|
||||||
|
android:contentDescription="@string/access_shared_string_navigate_up"
|
||||||
|
android:visibility="gone"
|
||||||
|
osmand:srcCompat="@drawable/ic_action_search_dark" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
android:id="@+id/bottom_navigation"
|
android:id="@+id/bottom_navigation"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
21
OsmAnd/res/layout/track_points_card.xml
Normal file
21
OsmAnd/res/layout/track_points_card.xml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ExpandableListView
|
||||||
|
android:id="@android:id/list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="0dp"
|
||||||
|
android:layout_marginLeft="0dp"
|
||||||
|
android:layout_marginTop="0dp"
|
||||||
|
android:layout_marginEnd="0dp"
|
||||||
|
android:layout_marginRight="0dp"
|
||||||
|
android:divider="@null"
|
||||||
|
android:dividerHeight="0dp"
|
||||||
|
android:drawSelectorOnTop="false"
|
||||||
|
android:groupIndicator="@android:color/transparent" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -12,6 +12,9 @@
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<string name="copy_to_map_favorites">Copy to favorites</string>
|
||||||
|
<string name="copy_to_map_markers">Copy to map markers</string>
|
||||||
|
<string name="delete_waypoints">Delete waypoints</string>
|
||||||
<string name="context_menu_edit_descr">Edit description</string>
|
<string name="context_menu_edit_descr">Edit description</string>
|
||||||
<string name="context_menu_read_full">Read full</string>
|
<string name="context_menu_read_full">Read full</string>
|
||||||
<string name="delete_online_routing_engine">Delete this online routing engine?</string>
|
<string name="delete_online_routing_engine">Delete this online routing engine?</string>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.osmand;
|
package net.osmand;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -8,6 +9,8 @@ import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
|
import net.osmand.GPXUtilities.GPXFile;
|
||||||
|
import net.osmand.GPXUtilities.Metadata;
|
||||||
import net.osmand.plus.GpxSelectionHelper;
|
import net.osmand.plus.GpxSelectionHelper;
|
||||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
|
@ -109,6 +112,8 @@ public class FileUtils {
|
||||||
selected.getGpxFile().path = dest.getAbsolutePath();
|
selected.getGpxFile().path = dest.getAbsolutePath();
|
||||||
helper.updateSelectedGpxFile(selected);
|
helper.updateSelectedGpxFile(selected);
|
||||||
}
|
}
|
||||||
|
RenameGpxAsyncTask renameGpxAsyncTask = new RenameGpxAsyncTask(app, dest);
|
||||||
|
renameGpxAsyncTask.execute();
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -196,4 +201,34 @@ public class FileUtils {
|
||||||
public interface RenameCallback {
|
public interface RenameCallback {
|
||||||
void renamedTo(File file);
|
void renamedTo(File file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class RenameGpxAsyncTask extends AsyncTask<Void, Void, Exception> {
|
||||||
|
|
||||||
|
private OsmandApplication app;
|
||||||
|
private File file;
|
||||||
|
|
||||||
|
private RenameGpxAsyncTask(@NonNull OsmandApplication app, @NonNull File file) {
|
||||||
|
this.app = app;
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Exception doInBackground(Void... voids) {
|
||||||
|
GpxSelectionHelper helper = app.getSelectedGpxHelper();
|
||||||
|
SelectedGpxFile selected = helper.getSelectedFileByPath(file.getAbsolutePath());
|
||||||
|
|
||||||
|
GPXFile gpxFile;
|
||||||
|
if (selected != null && selected.getGpxFile() != null) {
|
||||||
|
gpxFile = selected.getGpxFile();
|
||||||
|
} else {
|
||||||
|
gpxFile = GPXUtilities.loadGPXFile(file);
|
||||||
|
}
|
||||||
|
if (gpxFile.metadata == null) {
|
||||||
|
gpxFile.metadata = new Metadata();
|
||||||
|
}
|
||||||
|
gpxFile.metadata.name = Algorithms.getFileNameWithoutExtension(file.getName());
|
||||||
|
|
||||||
|
return GPXUtilities.writeGpxFile(file, gpxFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,10 +45,12 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
public class GpxSelectionHelper {
|
public class GpxSelectionHelper {
|
||||||
|
|
||||||
|
@ -60,6 +62,7 @@ public class GpxSelectionHelper {
|
||||||
private static final String BACKUPMODIFIEDTIME = "backupTime";
|
private static final String BACKUPMODIFIEDTIME = "backupTime";
|
||||||
private static final String COLOR = "color";
|
private static final String COLOR = "color";
|
||||||
private static final String SELECTED_BY_USER = "selected_by_user";
|
private static final String SELECTED_BY_USER = "selected_by_user";
|
||||||
|
private static final String HIDDEN_GROUPS = "hidden_groups";
|
||||||
|
|
||||||
private OsmandApplication app;
|
private OsmandApplication app;
|
||||||
private SavingTrackHelper savingTrackHelper;
|
private SavingTrackHelper savingTrackHelper;
|
||||||
|
@ -577,7 +580,10 @@ public class GpxSelectionHelper {
|
||||||
} else if (obj.has(BACKUP)) {
|
} else if (obj.has(BACKUP)) {
|
||||||
selectedGpxFilesBackUp.put(gpx, gpx.modifiedTime);
|
selectedGpxFilesBackUp.put(gpx, gpx.modifiedTime);
|
||||||
} else {
|
} else {
|
||||||
selectGpxFile(gpx, true, false, true, selectedByUser, false);
|
SelectedGpxFile file = selectGpxFile(gpx, true, false, true, selectedByUser, false);
|
||||||
|
if (obj.has(HIDDEN_GROUPS)) {
|
||||||
|
readHiddenGroups(file, obj.getString(HIDDEN_GROUPS));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gpx.addGeneralTrack();
|
gpx.addGeneralTrack();
|
||||||
} else if (obj.has(CURRENT_TRACK)) {
|
} else if (obj.has(CURRENT_TRACK)) {
|
||||||
|
@ -598,6 +604,33 @@ public class GpxSelectionHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String saveHiddenGroups(SelectedGpxFile selectedGpxFile) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
Iterator<String> it = selectedGpxFile.hiddenGroups.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
String name = it.next();
|
||||||
|
stringBuilder.append(name != null ? name : " ");
|
||||||
|
if (it.hasNext()) {
|
||||||
|
stringBuilder.append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readHiddenGroups(SelectedGpxFile selectedGpxFile, String text) {
|
||||||
|
StringTokenizer toks = new StringTokenizer(text, ",");
|
||||||
|
Set<String> res = new HashSet<>();
|
||||||
|
while (toks.hasMoreTokens()) {
|
||||||
|
String token = toks.nextToken();
|
||||||
|
if (!Algorithms.isBlank(token)) {
|
||||||
|
res.add(token);
|
||||||
|
} else {
|
||||||
|
res.add(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectedGpxFile.hiddenGroups = res;
|
||||||
|
}
|
||||||
|
|
||||||
private int parseColor(String color) {
|
private int parseColor(String color) {
|
||||||
try {
|
try {
|
||||||
return Algorithms.isEmpty(color) ? 0 : Algorithms.parseColor(color);
|
return Algorithms.isEmpty(color) ? 0 : Algorithms.parseColor(color);
|
||||||
|
@ -619,6 +652,7 @@ public class GpxSelectionHelper {
|
||||||
if (s.gpxFile.getColor(0) != 0) {
|
if (s.gpxFile.getColor(0) != 0) {
|
||||||
obj.put(COLOR, Algorithms.colorToString(s.gpxFile.getColor(0)));
|
obj.put(COLOR, Algorithms.colorToString(s.gpxFile.getColor(0)));
|
||||||
}
|
}
|
||||||
|
obj.put(HIDDEN_GROUPS, saveHiddenGroups(s));
|
||||||
}
|
}
|
||||||
obj.put(SELECTED_BY_USER, s.selectedByUser);
|
obj.put(SELECTED_BY_USER, s.selectedByUser);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
|
@ -765,6 +799,7 @@ public class GpxSelectionHelper {
|
||||||
private GPXFile gpxFile;
|
private GPXFile gpxFile;
|
||||||
private GPXTrackAnalysis trackAnalysis;
|
private GPXTrackAnalysis trackAnalysis;
|
||||||
|
|
||||||
|
private Set<String> hiddenGroups = new HashSet<>();
|
||||||
private List<TrkSegment> processedPointsToDisplay = new ArrayList<>();
|
private List<TrkSegment> processedPointsToDisplay = new ArrayList<>();
|
||||||
private List<GpxDisplayGroup> displayGroups;
|
private List<GpxDisplayGroup> displayGroups;
|
||||||
|
|
||||||
|
@ -832,6 +867,18 @@ public class GpxSelectionHelper {
|
||||||
return processedPointsToDisplay;
|
return processedPointsToDisplay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> getHiddenGroups() {
|
||||||
|
return Collections.unmodifiableSet(hiddenGroups);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addHiddenGroups(String group) {
|
||||||
|
hiddenGroups.add(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeHiddenGroups(String group) {
|
||||||
|
hiddenGroups.remove(group);
|
||||||
|
}
|
||||||
|
|
||||||
public GPXFile getGpxFile() {
|
public GPXFile getGpxFile() {
|
||||||
return gpxFile;
|
return gpxFile;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,8 @@ public class RenameFileBottomSheet extends MenuBottomSheetDialogFragment {
|
||||||
file = new File(path);
|
file = new File(path);
|
||||||
}
|
}
|
||||||
selectedFileName = savedInstanceState.getString(SELECTED_FILE_NAME_KEY);
|
selectedFileName = savedInstanceState.getString(SELECTED_FILE_NAME_KEY);
|
||||||
|
} else {
|
||||||
|
selectedFileName = Algorithms.getFileNameWithoutExtension(file);
|
||||||
}
|
}
|
||||||
items.add(new TitleItem(getString(R.string.shared_string_rename)));
|
items.add(new TitleItem(getString(R.string.shared_string_rename)));
|
||||||
|
|
||||||
|
@ -74,7 +76,7 @@ public class RenameFileBottomSheet extends MenuBottomSheetDialogFragment {
|
||||||
nameTextBox.setDefaultHintTextColor(colorStateList);
|
nameTextBox.setDefaultHintTextColor(colorStateList);
|
||||||
|
|
||||||
editText = view.findViewById(R.id.name_edit_text);
|
editText = view.findViewById(R.id.name_edit_text);
|
||||||
editText.setText(selectedFileName != null ? selectedFileName : Algorithms.getFileNameWithoutExtension(file));
|
editText.setText(selectedFileName);
|
||||||
editText.addTextChangedListener(new TextWatcher() {
|
editText.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
@ -127,12 +129,13 @@ public class RenameFileBottomSheet extends MenuBottomSheetDialogFragment {
|
||||||
File dest;
|
File dest;
|
||||||
int index = file.getName().lastIndexOf('.');
|
int index = file.getName().lastIndexOf('.');
|
||||||
String ext = index == -1 ? "" : file.getName().substring(index);
|
String ext = index == -1 ? "" : file.getName().substring(index);
|
||||||
|
String newName = Algorithms.getFileNameWithoutExtension(selectedFileName);
|
||||||
if (SQLiteTileSource.EXT.equals(ext)) {
|
if (SQLiteTileSource.EXT.equals(ext)) {
|
||||||
dest = renameSQLiteFile(app, file, selectedFileName + ext, null);
|
dest = renameSQLiteFile(app, file, newName + ext, null);
|
||||||
} else if (IndexConstants.GPX_FILE_EXT.equals(ext)) {
|
} else if (IndexConstants.GPX_FILE_EXT.equals(ext)) {
|
||||||
dest = renameGpxFile(app, file, selectedFileName + ext, false, null);
|
dest = renameGpxFile(app, file, newName + ext, false, null);
|
||||||
} else {
|
} else {
|
||||||
dest = renameFile(app, file, selectedFileName + ext, false, null);
|
dest = renameFile(app, file, newName + ext, false, null);
|
||||||
}
|
}
|
||||||
if (dest != null) {
|
if (dest != null) {
|
||||||
Fragment fragment = getTargetFragment();
|
Fragment fragment = getTargetFragment();
|
||||||
|
|
|
@ -15,14 +15,14 @@ import java.io.File;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
class DeletePointsTask extends AsyncTask<Void, Void, Void> {
|
public class DeletePointsTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
private OsmandApplication app;
|
private OsmandApplication app;
|
||||||
private GPXFile gpx;
|
private GPXFile gpx;
|
||||||
private Set<GpxDisplayItem> selectedItems;
|
private Set<GpxDisplayItem> selectedItems;
|
||||||
private WeakReference<OnPointsDeleteListener> listenerRef;
|
private WeakReference<OnPointsDeleteListener> listenerRef;
|
||||||
|
|
||||||
DeletePointsTask(OsmandApplication app, GPXFile gpxFile, Set<GpxDisplayItem> selectedItems, OnPointsDeleteListener listener) {
|
public DeletePointsTask(OsmandApplication app, GPXFile gpxFile, Set<GpxDisplayItem> selectedItems, OnPointsDeleteListener listener) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.gpx = gpxFile;
|
this.gpx = gpxFile;
|
||||||
this.selectedItems = selectedItems;
|
this.selectedItems = selectedItems;
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
package net.osmand.plus.myplaces;
|
package net.osmand.plus.myplaces;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
import android.graphics.Typeface;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup.LayoutParams;
|
import android.view.ViewGroup.LayoutParams;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
@ -17,56 +18,127 @@ import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.widget.ListPopupWindow;
|
import androidx.appcompat.widget.ListPopupWindow;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
import net.osmand.AndroidUtils;
|
import net.osmand.AndroidUtils;
|
||||||
import net.osmand.GPXUtilities;
|
import net.osmand.GPXUtilities;
|
||||||
import net.osmand.GPXUtilities.GPXFile;
|
import net.osmand.GPXUtilities.GPXFile;
|
||||||
import net.osmand.GPXUtilities.WptPt;
|
import net.osmand.GPXUtilities.WptPt;
|
||||||
|
import net.osmand.data.FavouritePoint;
|
||||||
|
import net.osmand.plus.FavouritesDbHelper;
|
||||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||||
import net.osmand.plus.mapmarkers.MapMarkersHelper;
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||||
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||||
import net.osmand.plus.OsmandApplication;
|
import net.osmand.plus.OsmandApplication;
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.UiUtilities;
|
||||||
import net.osmand.plus.activities.EditFavoriteGroupDialogFragment.FavoriteColorAdapter;
|
import net.osmand.plus.activities.EditFavoriteGroupDialogFragment.FavoriteColorAdapter;
|
||||||
|
import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.activities.SavingTrackHelper;
|
import net.osmand.plus.activities.SavingTrackHelper;
|
||||||
import net.osmand.plus.activities.TrackActivity;
|
import net.osmand.plus.activities.TrackActivity;
|
||||||
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
|
||||||
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
|
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
|
||||||
|
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
|
||||||
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
|
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
|
||||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||||
|
import net.osmand.plus.helpers.FontCache;
|
||||||
|
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
||||||
|
import net.osmand.plus.mapmarkers.MapMarkersHelper;
|
||||||
|
import net.osmand.plus.measurementtool.OptionsDividerItem;
|
||||||
|
import net.osmand.plus.myplaces.DeletePointsTask.OnPointsDeleteListener;
|
||||||
|
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||||
|
import net.osmand.plus.track.TrackMenuFragment;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static net.osmand.plus.settings.bottomsheets.BooleanPreferenceBottomSheet.getCustomButtonView;
|
||||||
|
import static net.osmand.plus.settings.bottomsheets.BooleanPreferenceBottomSheet.updateCustomButtonView;
|
||||||
|
|
||||||
|
public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment implements OnPointsDeleteListener {
|
||||||
|
|
||||||
public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment {
|
|
||||||
public static final String TAG = EditTrackGroupDialogFragment.class.getSimpleName();
|
public static final String TAG = EditTrackGroupDialogFragment.class.getSimpleName();
|
||||||
|
|
||||||
|
private OsmandApplication app;
|
||||||
|
|
||||||
private GpxDisplayGroup group;
|
private GpxDisplayGroup group;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createMenuItems(Bundle savedInstanceState) {
|
public void createMenuItems(Bundle savedInstanceState) {
|
||||||
final OsmandApplication app = getMyApplication();
|
app = requiredMyApplication();
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
items.add(new TitleItem(getCategoryName(app, group.getName())));
|
items.add(new TitleItem(getCategoryName(app, group.getName())));
|
||||||
|
|
||||||
BaseBottomSheetItem editNameItem = new SimpleBottomSheetItem.Builder()
|
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(group.getGpx().path);
|
||||||
.setIcon(getContentIcon(R.drawable.ic_action_edit_dark))
|
if (group.getType() == GpxDisplayItemType.TRACK_POINTS && selectedGpxFile != null) {
|
||||||
.setTitle(getString(R.string.edit_name))
|
items.add(createShowOnMapItem(selectedGpxFile));
|
||||||
.setLayoutId(R.layout.bottom_sheet_item_simple)
|
}
|
||||||
|
items.add(createEditNameItem());
|
||||||
|
items.add(new OptionsDividerItem(app));
|
||||||
|
|
||||||
|
// items.add(createCopyToMarkersItem());
|
||||||
|
items.add(createCopyToFavoritesItem());
|
||||||
|
items.add(new OptionsDividerItem(app));
|
||||||
|
|
||||||
|
items.add(createDeleteGroupItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseBottomSheetItem createShowOnMapItem(final SelectedGpxFile selectedGpxFile) {
|
||||||
|
final String name = Algorithms.isEmpty(group.getName()) ? null : group.getName();
|
||||||
|
boolean checked = !selectedGpxFile.getHiddenGroups().contains(name);
|
||||||
|
final ApplicationMode mode = app.getSettings().getApplicationMode();
|
||||||
|
final BottomSheetItemWithCompoundButton[] showOnMapItem = new BottomSheetItemWithCompoundButton[1];
|
||||||
|
showOnMapItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder()
|
||||||
|
.setCompoundButtonColorId(mode.getIconColorInfo().getColor(nightMode))
|
||||||
|
.setChecked(checked)
|
||||||
|
.setTitle(getString(R.string.shared_string_show_on_map))
|
||||||
|
.setCustomView(getCustomButtonView(app, mode, checked, nightMode))
|
||||||
.setOnClickListener(new View.OnClickListener() {
|
.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Activity activity = getActivity();
|
boolean checked = !showOnMapItem[0].isChecked();
|
||||||
|
if (checked) {
|
||||||
|
selectedGpxFile.removeHiddenGroups(name);
|
||||||
|
} else {
|
||||||
|
selectedGpxFile.addHiddenGroups(name);
|
||||||
|
}
|
||||||
|
app.getSelectedGpxHelper().updateSelectedGpxFile(selectedGpxFile);
|
||||||
|
|
||||||
|
showOnMapItem[0].setChecked(checked);
|
||||||
|
updateCustomButtonView(app, mode, v, checked, nightMode);
|
||||||
|
|
||||||
|
FragmentActivity activity = getActivity();
|
||||||
|
if (activity instanceof MapActivity) {
|
||||||
|
((MapActivity) activity).refreshMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create();
|
||||||
|
return showOnMapItem[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseBottomSheetItem createEditNameItem() {
|
||||||
|
return new SimpleBottomSheetItem.Builder()
|
||||||
|
.setIcon(getContentIcon(R.drawable.ic_action_name_field))
|
||||||
|
.setTitle(getString(R.string.shared_string_rename))
|
||||||
|
.setLayoutId(R.layout.bottom_sheet_item_simple)
|
||||||
|
.setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp)
|
||||||
|
.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
final FragmentActivity activity = getActivity();
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
AlertDialog.Builder b = new AlertDialog.Builder(activity);
|
AlertDialog.Builder b = new AlertDialog.Builder(activity);
|
||||||
b.setTitle(R.string.favorite_group_name);
|
b.setTitle(R.string.favorite_group_name);
|
||||||
|
@ -86,11 +158,8 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
||||||
String name = nameEditText.getText().toString();
|
String name = nameEditText.getText().toString();
|
||||||
boolean nameChanged = !Algorithms.objectEquals(group.getName(), name);
|
boolean nameChanged = !Algorithms.objectEquals(group.getName(), name);
|
||||||
if (nameChanged) {
|
if (nameChanged) {
|
||||||
TrackActivity trackActivity = getTrackActivity();
|
new UpdateGpxCategoryTask(activity, group, name)
|
||||||
if (trackActivity != null) {
|
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
new UpdateGpxCategoryTask(trackActivity, group, name)
|
|
||||||
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dismiss();
|
dismiss();
|
||||||
}
|
}
|
||||||
|
@ -100,20 +169,118 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.create();
|
.create();
|
||||||
items.add(editNameItem);
|
}
|
||||||
|
|
||||||
|
private BaseBottomSheetItem createCopyToMarkersItem() {
|
||||||
|
return new SimpleBottomSheetItem.Builder()
|
||||||
|
.setIcon(getContentIcon(R.drawable.ic_action_copy))
|
||||||
|
.setTitle(getString(R.string.copy_to_map_markers))
|
||||||
|
.setLayoutId(R.layout.bottom_sheet_item_simple)
|
||||||
|
.setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp)
|
||||||
|
.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
// MapMarkersHelper markersHelper = app.getMapMarkersHelper();
|
||||||
|
// MapMarkersGroup markersGroup = markersHelper.getMarkersGroup(group);
|
||||||
|
// if (markersGroup != null) {
|
||||||
|
// markersHelper.removeMarkersGroup(markersGroup);
|
||||||
|
// } else {
|
||||||
|
// markersHelper.addOrEnableGroup(group);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseBottomSheetItem createCopyToFavoritesItem() {
|
||||||
|
return new SimpleBottomSheetItem.Builder()
|
||||||
|
.setIcon(getContentIcon(R.drawable.ic_action_copy))
|
||||||
|
.setTitle(getString(R.string.copy_to_map_favorites))
|
||||||
|
.setLayoutId(R.layout.bottom_sheet_item_simple)
|
||||||
|
.setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp)
|
||||||
|
.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
saveGroupToFavorites();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveGroupToFavorites() {
|
||||||
|
FragmentActivity activity = getActivity();
|
||||||
|
if (activity != null) {
|
||||||
|
AlertDialog.Builder b = new AlertDialog.Builder(activity);
|
||||||
|
final EditText editText = new EditText(activity);
|
||||||
|
String name = group.getModifiableList().iterator().next().group.getName();
|
||||||
|
if (name.indexOf('\n') > 0) {
|
||||||
|
name = name.substring(0, name.indexOf('\n'));
|
||||||
|
}
|
||||||
|
editText.setText(name);
|
||||||
|
int leftMargin = AndroidUtils.dpToPx(activity, 16f);
|
||||||
|
int topMargin = AndroidUtils.dpToPx(activity, 8f);
|
||||||
|
editText.setPadding(leftMargin, topMargin, leftMargin, topMargin);
|
||||||
|
b.setTitle(R.string.save_as_favorites_points);
|
||||||
|
b.setView(editText);
|
||||||
|
b.setPositiveButton(R.string.shared_string_save, new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
String category = editText.getText().toString();
|
||||||
|
FavouritesDbHelper favouritesDbHelper = app.getFavorites();
|
||||||
|
for (GpxDisplayItem item : group.getModifiableList()) {
|
||||||
|
if (item.locationStart != null) {
|
||||||
|
FavouritePoint fp = FavouritePoint.fromWpt(item.locationStart, app, category);
|
||||||
|
if (!Algorithms.isEmpty(item.description)) {
|
||||||
|
fp.setDescription(item.description);
|
||||||
|
}
|
||||||
|
favouritesDbHelper.addFavourite(fp, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
favouritesDbHelper.saveCurrentPointsIntoFile();
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
b.setNegativeButton(R.string.shared_string_cancel, null);
|
||||||
|
b.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseBottomSheetItem createDeleteGroupItem() {
|
||||||
|
String delete = app.getString(R.string.shared_string_delete);
|
||||||
|
Typeface typeface = FontCache.getRobotoMedium(app);
|
||||||
|
return new SimpleBottomSheetItem.Builder()
|
||||||
|
.setTitleColorId(R.color.color_osm_edit_delete)
|
||||||
|
.setIcon(getIcon(R.drawable.ic_action_delete_dark, R.color.color_osm_edit_delete))
|
||||||
|
.setTitle(UiUtilities.createCustomFontSpannable(typeface, delete, delete))
|
||||||
|
.setLayoutId(R.layout.bottom_sheet_item_simple_pad_32dp)
|
||||||
|
.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
deleteGroupItems();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteGroupItems() {
|
||||||
|
Set<GpxDisplayItem> items = new HashSet<>(group.getModifiableList());
|
||||||
|
new DeletePointsTask(app, group.getGpx(), items, this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BaseBottomSheetItem createChangeColorItem() {
|
||||||
final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
|
final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
|
||||||
final View changeColorView = View.inflate(new ContextThemeWrapper(getContext(), themeRes),
|
final View changeColorView = View.inflate(new ContextThemeWrapper(getContext(), themeRes),
|
||||||
R.layout.change_fav_color, null);
|
R.layout.change_fav_color, null);
|
||||||
((ImageView) changeColorView.findViewById(R.id.change_color_icon))
|
((ImageView) changeColorView.findViewById(R.id.change_color_icon))
|
||||||
.setImageDrawable(getContentIcon(R.drawable.ic_action_appearance));
|
.setImageDrawable(getContentIcon(R.drawable.ic_action_appearance));
|
||||||
updateColorView((ImageView) changeColorView.findViewById(R.id.colorImage));
|
updateColorView((ImageView) changeColorView.findViewById(R.id.colorImage));
|
||||||
BaseBottomSheetItem changeColorItem = new BaseBottomSheetItem.Builder()
|
return new BaseBottomSheetItem.Builder()
|
||||||
.setCustomView(changeColorView)
|
.setCustomView(changeColorView)
|
||||||
.setOnClickListener(new View.OnClickListener() {
|
.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Activity activity = getActivity();
|
final FragmentActivity activity = getActivity();
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
final ListPopupWindow popup = new ListPopupWindow(activity);
|
final ListPopupWindow popup = new ListPopupWindow(activity);
|
||||||
popup.setAnchorView(v);
|
popup.setAnchorView(v);
|
||||||
|
@ -135,11 +302,8 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
||||||
Integer color = colorAdapter.getItem(position);
|
Integer color = colorAdapter.getItem(position);
|
||||||
if (color != null) {
|
if (color != null) {
|
||||||
if (color != group.getColor()) {
|
if (color != group.getColor()) {
|
||||||
TrackActivity trackActivity = getTrackActivity();
|
new UpdateGpxCategoryTask(activity, group, color)
|
||||||
if (trackActivity != null) {
|
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
new UpdateGpxCategoryTask(trackActivity, group, color)
|
|
||||||
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
popup.dismiss();
|
popup.dismiss();
|
||||||
|
@ -151,8 +315,6 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.create();
|
.create();
|
||||||
items.add(changeColorItem);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -163,15 +325,6 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private TrackActivity getTrackActivity() {
|
|
||||||
Activity activity = getActivity();
|
|
||||||
if (activity != null && activity instanceof TrackActivity) {
|
|
||||||
return (TrackActivity) activity;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getCategoryName(@NonNull Context ctx, String category) {
|
private static String getCategoryName(@NonNull Context ctx, String category) {
|
||||||
return Algorithms.isEmpty(category) ? ctx.getString(R.string.shared_string_waypoints) : category;
|
return Algorithms.isEmpty(category) ? ctx.getString(R.string.shared_string_waypoints) : category;
|
||||||
}
|
}
|
||||||
|
@ -181,24 +334,38 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
||||||
if (color == 0) {
|
if (color == 0) {
|
||||||
colorImageView.setImageDrawable(getContentIcon(R.drawable.ic_action_circle));
|
colorImageView.setImageDrawable(getContentIcon(R.drawable.ic_action_circle));
|
||||||
} else {
|
} else {
|
||||||
colorImageView.setImageDrawable(getMyApplication().getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, color));
|
colorImageView.setImageDrawable(app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showInstance(FragmentManager fragmentManager, GpxDisplayGroup group) {
|
public static void showInstance(FragmentManager fragmentManager, GpxDisplayGroup group, Fragment target) {
|
||||||
EditTrackGroupDialogFragment f = (EditTrackGroupDialogFragment) fragmentManager
|
if (!fragmentManager.isStateSaved() && fragmentManager.findFragmentByTag(TAG) == null) {
|
||||||
.findFragmentByTag(EditTrackGroupDialogFragment.TAG);
|
EditTrackGroupDialogFragment fragment = new EditTrackGroupDialogFragment();
|
||||||
if (f == null ) {
|
fragment.group = group;
|
||||||
f = new EditTrackGroupDialogFragment();
|
fragment.setRetainInstance(true);
|
||||||
f.group = group;
|
fragment.setTargetFragment(target, 0);
|
||||||
f.show(fragmentManager, EditTrackGroupDialogFragment.TAG);
|
fragment.show(fragmentManager, TAG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPointsDeletionStarted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPointsDeleted() {
|
||||||
|
Fragment fragment = getTargetFragment();
|
||||||
|
if (fragment instanceof TrackMenuFragment) {
|
||||||
|
((TrackMenuFragment) fragment).updateContent();
|
||||||
|
}
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
private static class UpdateGpxCategoryTask extends AsyncTask<Void, Void, Void> {
|
private static class UpdateGpxCategoryTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
private OsmandApplication app;
|
private OsmandApplication app;
|
||||||
private WeakReference<TrackActivity> activityRef;
|
private WeakReference<FragmentActivity> activityRef;
|
||||||
|
|
||||||
private GpxDisplayGroup group;
|
private GpxDisplayGroup group;
|
||||||
|
|
||||||
|
@ -208,20 +375,20 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
||||||
private ProgressDialog progressDialog;
|
private ProgressDialog progressDialog;
|
||||||
private boolean wasUpdated = false;
|
private boolean wasUpdated = false;
|
||||||
|
|
||||||
private UpdateGpxCategoryTask(@NonNull TrackActivity activity, @NonNull GpxDisplayGroup group) {
|
private UpdateGpxCategoryTask(@NonNull FragmentActivity activity, @NonNull GpxDisplayGroup group) {
|
||||||
this.app = (OsmandApplication) activity.getApplication();
|
this.app = (OsmandApplication) activity.getApplication();
|
||||||
activityRef = new WeakReference<>(activity);
|
activityRef = new WeakReference<>(activity);
|
||||||
|
|
||||||
this.group = group;
|
this.group = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateGpxCategoryTask(@NonNull TrackActivity activity, @NonNull GpxDisplayGroup group,
|
UpdateGpxCategoryTask(@NonNull FragmentActivity activity, @NonNull GpxDisplayGroup group,
|
||||||
@NonNull String newCategory) {
|
@NonNull String newCategory) {
|
||||||
this(activity, group);
|
this(activity, group);
|
||||||
this.newCategory = newCategory;
|
this.newCategory = newCategory;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateGpxCategoryTask(@NonNull TrackActivity activity, @NonNull GpxDisplayGroup group,
|
UpdateGpxCategoryTask(@NonNull FragmentActivity activity, @NonNull GpxDisplayGroup group,
|
||||||
@NonNull Integer newColor) {
|
@NonNull Integer newColor) {
|
||||||
this(activity, group);
|
this(activity, group);
|
||||||
this.newColor = newColor;
|
this.newColor = newColor;
|
||||||
|
@ -229,7 +396,7 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPreExecute() {
|
protected void onPreExecute() {
|
||||||
TrackActivity activity = activityRef.get();
|
FragmentActivity activity = activityRef.get();
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
progressDialog = new ProgressDialog(activity);
|
progressDialog = new ProgressDialog(activity);
|
||||||
progressDialog.setTitle(EditTrackGroupDialogFragment.getCategoryName(app, group.getName()));
|
progressDialog.setTitle(EditTrackGroupDialogFragment.getCategoryName(app, group.getName()));
|
||||||
|
@ -293,9 +460,15 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
|
||||||
progressDialog.dismiss();
|
progressDialog.dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackActivity activity = activityRef.get();
|
FragmentActivity activity = activityRef.get();
|
||||||
if (activity != null) {
|
if (activity instanceof TrackActivity) {
|
||||||
activity.loadGpx();
|
((TrackActivity) activity).loadGpx();
|
||||||
|
} else if (activity instanceof MapActivity) {
|
||||||
|
MapActivity mapActivity = (MapActivity) activity;
|
||||||
|
TrackMenuFragment fragment = mapActivity.getTrackMenuFragment();
|
||||||
|
if (fragment != null) {
|
||||||
|
fragment.updateContent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1007,7 +1007,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
FragmentActivity activity = getActivity();
|
FragmentActivity activity = getActivity();
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
EditTrackGroupDialogFragment.showInstance(activity.getSupportFragmentManager(), group);
|
EditTrackGroupDialogFragment.showInstance(activity.getSupportFragmentManager(), group, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -122,14 +122,14 @@ public class BooleanPreferenceBottomSheet extends BasePreferenceBottomSheet {
|
||||||
return R.string.shared_string_close;
|
return R.string.shared_string_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static View getCustomButtonView(OsmandApplication app, ApplicationMode mode, boolean checked, boolean nightMode) {
|
public static View getCustomButtonView(OsmandApplication app, ApplicationMode mode, boolean checked, boolean nightMode) {
|
||||||
View customView = UiUtilities.getInflater(app, nightMode).inflate(R.layout.bottom_sheet_item_preference_switch, null);
|
View customView = UiUtilities.getInflater(app, nightMode).inflate(R.layout.bottom_sheet_item_preference_switch, null);
|
||||||
updateCustomButtonView(app, mode, customView, checked, nightMode);
|
updateCustomButtonView(app, mode, customView, checked, nightMode);
|
||||||
|
|
||||||
return customView;
|
return customView;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void updateCustomButtonView(OsmandApplication app, ApplicationMode mode, View customView, boolean checked, boolean nightMode) {
|
public static void updateCustomButtonView(OsmandApplication app, ApplicationMode mode, View customView, boolean checked, boolean nightMode) {
|
||||||
Context themedCtx = UiUtilities.getThemedContext(app, nightMode);
|
Context themedCtx = UiUtilities.getThemedContext(app, nightMode);
|
||||||
View buttonView = customView.findViewById(R.id.button_container);
|
View buttonView = customView.findViewById(R.id.button_container);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ public class SegmentsCard extends BaseCard {
|
||||||
|
|
||||||
private TrackDisplayHelper displayHelper;
|
private TrackDisplayHelper displayHelper;
|
||||||
private GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT};
|
private GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT};
|
||||||
private SegmentGPXAdapter adapter;
|
|
||||||
private SegmentActionsListener listener;
|
private SegmentActionsListener listener;
|
||||||
|
|
||||||
public SegmentsCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper,
|
public SegmentsCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper,
|
||||||
|
|
|
@ -112,10 +112,16 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public float getMiddleStateKoef() {
|
public float getMiddleStateKoef() {
|
||||||
return 0.5f;
|
return 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getInitialMenuState() {
|
||||||
|
return MenuState.HALF_SCREEN;
|
||||||
|
}
|
||||||
|
|
||||||
public TrackDrawInfo getTrackDrawInfo() {
|
public TrackDrawInfo getTrackDrawInfo() {
|
||||||
return trackDrawInfo;
|
return trackDrawInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
package net.osmand.plus.track;
|
package net.osmand.plus.track;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import net.osmand.GPXUtilities.GPXFile;
|
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.data.QuadRect;
|
||||||
import net.osmand.plus.GPXDatabase.GpxDataItem;
|
import net.osmand.plus.GPXDatabase.GpxDataItem;
|
||||||
import net.osmand.plus.GpxSelectionHelper;
|
import net.osmand.plus.GpxSelectionHelper;
|
||||||
|
@ -17,10 +12,6 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||||
import net.osmand.plus.OsmandApplication;
|
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.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -163,21 +154,4 @@ public class TrackDisplayHelper {
|
||||||
}
|
}
|
||||||
return list;
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,27 @@
|
||||||
package net.osmand.plus.track;
|
package net.osmand.plus.track;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.DecelerateInterpolator;
|
||||||
|
import android.widget.EditText;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
|
@ -33,6 +39,7 @@ import net.osmand.GPXUtilities.TrkSegment;
|
||||||
import net.osmand.Location;
|
import net.osmand.Location;
|
||||||
import net.osmand.PlatformUtil;
|
import net.osmand.PlatformUtil;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
|
import net.osmand.data.PointDescription;
|
||||||
import net.osmand.data.QuadRect;
|
import net.osmand.data.QuadRect;
|
||||||
import net.osmand.data.RotatedTileBox;
|
import net.osmand.data.RotatedTileBox;
|
||||||
import net.osmand.plus.GpxDbHelper;
|
import net.osmand.plus.GpxDbHelper;
|
||||||
|
@ -61,6 +68,7 @@ import net.osmand.plus.measurementtool.GpxData;
|
||||||
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
||||||
import net.osmand.plus.measurementtool.MeasurementToolFragment;
|
import net.osmand.plus.measurementtool.MeasurementToolFragment;
|
||||||
import net.osmand.plus.myplaces.AvailableGPXFragment.GpxInfo;
|
import net.osmand.plus.myplaces.AvailableGPXFragment.GpxInfo;
|
||||||
|
import net.osmand.plus.myplaces.DeletePointsTask.OnPointsDeleteListener;
|
||||||
import net.osmand.plus.myplaces.MoveGpxFileBottomSheet;
|
import net.osmand.plus.myplaces.MoveGpxFileBottomSheet;
|
||||||
import net.osmand.plus.myplaces.MoveGpxFileBottomSheet.OnTrackFileMoveListener;
|
import net.osmand.plus.myplaces.MoveGpxFileBottomSheet.OnTrackFileMoveListener;
|
||||||
import net.osmand.plus.myplaces.SegmentActionsListener;
|
import net.osmand.plus.myplaces.SegmentActionsListener;
|
||||||
|
@ -70,6 +78,7 @@ import net.osmand.plus.osmedit.OsmEditingPlugin;
|
||||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
|
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
|
||||||
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
|
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
|
||||||
|
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
|
||||||
import net.osmand.plus.widgets.IconPopupMenu;
|
import net.osmand.plus.widgets.IconPopupMenu;
|
||||||
import net.osmand.util.Algorithms;
|
import net.osmand.util.Algorithms;
|
||||||
import net.osmand.util.MapUtils;
|
import net.osmand.util.MapUtils;
|
||||||
|
@ -94,9 +103,12 @@ import static net.osmand.plus.track.OptionsCard.RENAME_BUTTON_INDEX;
|
||||||
import static net.osmand.plus.track.OptionsCard.SHARE_BUTTON_INDEX;
|
import static net.osmand.plus.track.OptionsCard.SHARE_BUTTON_INDEX;
|
||||||
import static net.osmand.plus.track.OptionsCard.SHOW_ON_MAP_BUTTON_INDEX;
|
import static net.osmand.plus.track.OptionsCard.SHOW_ON_MAP_BUTTON_INDEX;
|
||||||
import static net.osmand.plus.track.OptionsCard.UPLOAD_OSM_BUTTON_INDEX;
|
import static net.osmand.plus.track.OptionsCard.UPLOAD_OSM_BUTTON_INDEX;
|
||||||
|
import static net.osmand.plus.track.TrackPointsCard.ADD_WAYPOINT_INDEX;
|
||||||
|
import static net.osmand.plus.track.TrackPointsCard.DELETE_WAYPOINTS_INDEX;
|
||||||
|
|
||||||
public class TrackMenuFragment extends ContextMenuScrollFragment implements CardListener,
|
public class TrackMenuFragment extends ContextMenuScrollFragment implements CardListener,
|
||||||
SegmentActionsListener, RenameCallback, OnTrackFileMoveListener, OsmAndLocationListener, OsmAndCompassListener {
|
SegmentActionsListener, RenameCallback, OnTrackFileMoveListener, OnPointsDeleteListener,
|
||||||
|
OsmAndLocationListener, OsmAndCompassListener {
|
||||||
|
|
||||||
public static final String TAG = TrackMenuFragment.class.getName();
|
public static final String TAG = TrackMenuFragment.class.getName();
|
||||||
private static final Log log = PlatformUtil.getLog(TrackMenuFragment.class);
|
private static final Log log = PlatformUtil.getLog(TrackMenuFragment.class);
|
||||||
|
@ -105,37 +117,46 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
private TrackDisplayHelper displayHelper;
|
private TrackDisplayHelper displayHelper;
|
||||||
private SelectedGpxFile selectedGpxFile;
|
private SelectedGpxFile selectedGpxFile;
|
||||||
|
|
||||||
private View routeMenuTopShadowAll;
|
|
||||||
private TextView headerTitle;
|
|
||||||
private ImageView headerIcon;
|
|
||||||
private BottomNavigationView bottomNav;
|
|
||||||
private TrackMenuType menuType = TrackMenuType.OVERVIEW;
|
private TrackMenuType menuType = TrackMenuType.OVERVIEW;
|
||||||
private SegmentsCard segmentsCard;
|
private SegmentsCard segmentsCard;
|
||||||
private OptionsCard optionsCard;
|
private OptionsCard optionsCard;
|
||||||
private DescriptionCard descriptionCard;
|
private DescriptionCard descriptionCard;
|
||||||
private OverviewCard overviewCard;
|
private OverviewCard overviewCard;
|
||||||
|
private TrackPointsCard pointsCard;
|
||||||
|
|
||||||
|
private TextView headerTitle;
|
||||||
|
private ImageView headerIcon;
|
||||||
|
private View toolbarContainer;
|
||||||
|
private View searchContainer;
|
||||||
|
private ImageView searchButton;
|
||||||
|
private EditText searchEditText;
|
||||||
|
private TextView toolbarTextView;
|
||||||
|
private View routeMenuTopShadowAll;
|
||||||
|
private BottomNavigationView bottomNav;
|
||||||
|
|
||||||
|
private String gpxTitle;
|
||||||
private TrackChartPoints trackChartPoints;
|
private TrackChartPoints trackChartPoints;
|
||||||
|
|
||||||
private int menuTitleHeight;
|
|
||||||
private String gpxTitle;
|
|
||||||
private UpdateLocationViewCache updateLocationViewCache;
|
|
||||||
private Location lastLocation = null;
|
|
||||||
private Float heading;
|
private Float heading;
|
||||||
|
private Location lastLocation;
|
||||||
|
private UpdateLocationViewCache updateLocationViewCache;
|
||||||
private boolean locationUpdateStarted;
|
private boolean locationUpdateStarted;
|
||||||
|
|
||||||
|
private int menuTitleHeight;
|
||||||
|
private int toolbarHeightPx;
|
||||||
|
|
||||||
public enum TrackMenuType {
|
public enum TrackMenuType {
|
||||||
OVERVIEW(R.id.action_overview, R.string.shared_string_overview),
|
OVERVIEW(R.id.action_overview, R.string.shared_string_overview),
|
||||||
TRACK(R.id.action_track, R.string.shared_string_gpx_tracks),
|
TRACK(R.id.action_track, R.string.shared_string_gpx_tracks),
|
||||||
POINTS(R.id.action_points, R.string.shared_string_gpx_points),
|
POINTS(R.id.action_points, R.string.shared_string_gpx_points),
|
||||||
OPTIONS(R.id.action_options, R.string.shared_string_options);
|
OPTIONS(R.id.action_options, R.string.shared_string_options);
|
||||||
|
|
||||||
TrackMenuType(@DrawableRes int iconId, @StringRes int titleId) {
|
TrackMenuType(int menuItemId, @StringRes int titleId) {
|
||||||
this.iconId = iconId;
|
this.menuItemId = menuItemId;
|
||||||
this.titleId = titleId;
|
this.titleId = titleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int iconId;
|
public final int menuItemId;
|
||||||
public final int titleId;
|
public final int titleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +177,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getToolbarHeight() {
|
public int getToolbarHeight() {
|
||||||
return 0;
|
return toolbarHeightPx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getMiddleStateKoef() {
|
public float getMiddleStateKoef() {
|
||||||
|
@ -183,6 +204,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
app = requireMyApplication();
|
app = requireMyApplication();
|
||||||
GpxDbHelper gpxDbHelper = app.getGpxDbHelper();
|
GpxDbHelper gpxDbHelper = app.getGpxDbHelper();
|
||||||
displayHelper = new TrackDisplayHelper(app);
|
displayHelper = new TrackDisplayHelper(app);
|
||||||
|
updateLocationViewCache = app.getUIUtilities().getUpdateLocationViewCache();
|
||||||
|
|
||||||
Bundle arguments = getArguments();
|
Bundle arguments = getArguments();
|
||||||
if (arguments != null) {
|
if (arguments != null) {
|
||||||
|
@ -200,6 +222,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
String fileName = Algorithms.getFileWithoutDirs(getGpx().path);
|
String fileName = Algorithms.getFileWithoutDirs(getGpx().path);
|
||||||
gpxTitle = GpxUiHelper.getGpxTitle(fileName);
|
gpxTitle = GpxUiHelper.getGpxTitle(fileName);
|
||||||
}
|
}
|
||||||
|
toolbarHeightPx = getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GPXFile getGpx() {
|
public GPXFile getGpx() {
|
||||||
|
@ -214,7 +237,10 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
routeMenuTopShadowAll = view.findViewById(R.id.route_menu_top_shadow_all);
|
routeMenuTopShadowAll = view.findViewById(R.id.route_menu_top_shadow_all);
|
||||||
headerTitle = view.findViewById(R.id.title);
|
headerTitle = view.findViewById(R.id.title);
|
||||||
headerIcon = view.findViewById(R.id.icon_view);
|
headerIcon = view.findViewById(R.id.icon_view);
|
||||||
updateLocationViewCache = app.getUIUtilities().getUpdateLocationViewCache();
|
toolbarContainer = view.findViewById(R.id.context_menu_toolbar_container);
|
||||||
|
toolbarTextView = view.findViewById(R.id.toolbar_title);
|
||||||
|
searchButton = view.findViewById(R.id.search_button);
|
||||||
|
searchContainer = view.findViewById(R.id.search_container);
|
||||||
|
|
||||||
if (isPortrait()) {
|
if (isPortrait()) {
|
||||||
AndroidUiHelper.updateVisibility(getTopShadow(), true);
|
AndroidUiHelper.updateVisibility(getTopShadow(), true);
|
||||||
|
@ -226,6 +252,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
}
|
}
|
||||||
|
|
||||||
setupCards();
|
setupCards();
|
||||||
|
setupToolbar();
|
||||||
updateHeader();
|
updateHeader();
|
||||||
setupButtons(view);
|
setupButtons(view);
|
||||||
enterTrackAppearanceMode();
|
enterTrackAppearanceMode();
|
||||||
|
@ -261,6 +288,74 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
boolean isOptions = menuType == TrackMenuType.OPTIONS;
|
boolean isOptions = menuType == TrackMenuType.OPTIONS;
|
||||||
setHeaderTitle(isOptions ? app.getString(menuType.titleId) : gpxTitle, !isOptions);
|
setHeaderTitle(isOptions ? app.getString(menuType.titleId) : gpxTitle, !isOptions);
|
||||||
}
|
}
|
||||||
|
if (menuType == TrackMenuType.POINTS) {
|
||||||
|
AndroidUiHelper.updateVisibility(searchButton, true);
|
||||||
|
} else {
|
||||||
|
AndroidUiHelper.updateVisibility(toolbarTextView, true);
|
||||||
|
AndroidUiHelper.updateVisibility(searchButton, false);
|
||||||
|
AndroidUiHelper.updateVisibility(searchContainer, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupToolbar() {
|
||||||
|
toolbarTextView.setText(gpxTitle);
|
||||||
|
|
||||||
|
ImageView closeButton = toolbarContainer.findViewById(R.id.close_button);
|
||||||
|
closeButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (menuType == TrackMenuType.POINTS) {
|
||||||
|
AndroidUiHelper.updateVisibility(toolbarTextView, true);
|
||||||
|
AndroidUiHelper.updateVisibility(searchButton, true);
|
||||||
|
AndroidUiHelper.updateVisibility(searchContainer, false);
|
||||||
|
}
|
||||||
|
openMenuHeaderOnly();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
closeButton.setImageResource(AndroidUtils.getNavigationIconResId(toolbarContainer.getContext()));
|
||||||
|
|
||||||
|
searchButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
AndroidUiHelper.updateVisibility(searchContainer, true);
|
||||||
|
AndroidUiHelper.updateVisibility(searchButton, false);
|
||||||
|
AndroidUiHelper.updateVisibility(toolbarTextView, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
searchEditText = toolbarContainer.findViewById(R.id.searchEditText);
|
||||||
|
searchEditText.setHint(R.string.search_poi_filter);
|
||||||
|
searchEditText.addTextChangedListener(
|
||||||
|
new TextWatcher() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
if (pointsCard != null) {
|
||||||
|
pointsCard.filter(s.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
ImageView clearButton = toolbarContainer.findViewById(R.id.clearButton);
|
||||||
|
clearButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (!Algorithms.isEmpty(searchEditText.getText())) {
|
||||||
|
searchEditText.setText("");
|
||||||
|
searchEditText.setSelection(0);
|
||||||
|
}
|
||||||
|
if (pointsCard != null) {
|
||||||
|
pointsCard.updateContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupCards() {
|
private void setupCards() {
|
||||||
|
@ -296,13 +391,25 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
if (descriptionCard != null && descriptionCard.getView() != null) {
|
if (descriptionCard != null && descriptionCard.getView() != null) {
|
||||||
ViewGroup parent = ((ViewGroup) descriptionCard.getView().getParent());
|
ViewGroup parent = ((ViewGroup) descriptionCard.getView().getParent());
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
cardsContainer.removeView(descriptionCard.getView());
|
parent.removeView(descriptionCard.getView());
|
||||||
}
|
}
|
||||||
cardsContainer.addView(descriptionCard.getView());
|
cardsContainer.addView(descriptionCard.getView());
|
||||||
} else {
|
} else {
|
||||||
descriptionCard = new DescriptionCard(getMapActivity(), displayHelper.getGpx());
|
descriptionCard = new DescriptionCard(getMapActivity(), displayHelper.getGpx());
|
||||||
cardsContainer.addView(descriptionCard.build(mapActivity));
|
cardsContainer.addView(descriptionCard.build(mapActivity));
|
||||||
}
|
}
|
||||||
|
} else if (menuType == TrackMenuType.POINTS) {
|
||||||
|
if (pointsCard != null && pointsCard.getView() != null) {
|
||||||
|
ViewGroup parent = (ViewGroup) pointsCard.getView().getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
parent.removeAllViews();
|
||||||
|
}
|
||||||
|
cardsContainer.addView(pointsCard.getView());
|
||||||
|
} else {
|
||||||
|
pointsCard = new TrackPointsCard(mapActivity, displayHelper);
|
||||||
|
pointsCard.setListener(this);
|
||||||
|
cardsContainer.addView(pointsCard.build(mapActivity));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,12 +425,14 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
protected void setViewY(int y, boolean animated, boolean adjustMapPos) {
|
protected void setViewY(int y, boolean animated, boolean adjustMapPos) {
|
||||||
super.setViewY(y, animated, adjustMapPos);
|
super.setViewY(y, animated, adjustMapPos);
|
||||||
updateStatusBarColor();
|
updateStatusBarColor();
|
||||||
|
updateToolbar(y, animated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateMainViewLayout(int posY) {
|
protected void updateMainViewLayout(int posY) {
|
||||||
super.updateMainViewLayout(posY);
|
super.updateMainViewLayout(posY);
|
||||||
updateStatusBarColor();
|
updateStatusBarColor();
|
||||||
|
updateToolbar(posY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -484,7 +593,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
if (Build.VERSION.SDK_INT >= 23 && !nightMode) {
|
if (Build.VERSION.SDK_INT >= 23 && !nightMode) {
|
||||||
view.setSystemUiVisibility(view.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
view.setSystemUiVisibility(view.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||||
}
|
}
|
||||||
return nightMode ? R.color.divider_color_dark : R.color.divider_color_light;
|
return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light;
|
||||||
} else {
|
} else {
|
||||||
if (Build.VERSION.SDK_INT >= 23 && !nightMode) {
|
if (Build.VERSION.SDK_INT >= 23 && !nightMode) {
|
||||||
view.setSystemUiVisibility(view.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
view.setSystemUiVisibility(view.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||||
|
@ -522,8 +631,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
if (mapActivity == null) {
|
if (mapActivity == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final GPXFile gpxFile = getGpx();
|
||||||
if (card instanceof OptionsCard || card instanceof OverviewCard) {
|
if (card instanceof OptionsCard || card instanceof OverviewCard) {
|
||||||
final GPXFile gpxFile = getGpx();
|
|
||||||
if (buttonIndex == SHOW_ON_MAP_BUTTON_INDEX) {
|
if (buttonIndex == SHOW_ON_MAP_BUTTON_INDEX) {
|
||||||
boolean gpxFileSelected = !isGpxFileSelected(app, gpxFile);
|
boolean gpxFileSelected = !isGpxFileSelected(app, gpxFile);
|
||||||
app.getSelectedGpxHelper().selectGpxFile(gpxFile, gpxFileSelected, false);
|
app.getSelectedGpxHelper().selectGpxFile(gpxFile, gpxFileSelected, false);
|
||||||
|
@ -615,6 +724,25 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
});
|
});
|
||||||
builder.show();
|
builder.show();
|
||||||
}
|
}
|
||||||
|
} else if (card instanceof TrackPointsCard) {
|
||||||
|
if (buttonIndex == ADD_WAYPOINT_INDEX) {
|
||||||
|
PointDescription pointDescription = new PointDescription(PointDescription.POINT_TYPE_WPT, app.getString(R.string.add_waypoint));
|
||||||
|
QuadRect rect = displayHelper.getRect();
|
||||||
|
NewGpxPoint newGpxPoint = new NewGpxPoint(gpxFile, pointDescription, rect);
|
||||||
|
|
||||||
|
mapActivity.getMapView().fitRectToMap(rect.left, rect.right, rect.top, rect.bottom,
|
||||||
|
(int) rect.width(), (int) rect.height(), 0);
|
||||||
|
mapActivity.getMapLayers().getContextMenuLayer().enterAddGpxPointMode(newGpxPoint);
|
||||||
|
|
||||||
|
hide();
|
||||||
|
} else if (buttonIndex == DELETE_WAYPOINTS_INDEX) {
|
||||||
|
TrackPointsCard pointsCard = (TrackPointsCard) card;
|
||||||
|
if (pointsCard.isSelectionMode()) {
|
||||||
|
pointsCard.deleteItemsAction();
|
||||||
|
} else {
|
||||||
|
pointsCard.setSelectionMode(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,6 +755,34 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateToolbar(int y, boolean animated) {
|
||||||
|
final MapActivity mapActivity = getMapActivity();
|
||||||
|
if (mapActivity != null) {
|
||||||
|
if (toolbarContainer != null && isPortrait()) {
|
||||||
|
if (animated) {
|
||||||
|
final float toolbarAlpha = getToolbarAlpha(y);
|
||||||
|
if (toolbarAlpha > 0) {
|
||||||
|
updateVisibility(toolbarContainer, true);
|
||||||
|
}
|
||||||
|
toolbarContainer.animate().alpha(toolbarAlpha)
|
||||||
|
.setDuration(ContextMenuFragment.ANIMATION_DURATION)
|
||||||
|
.setInterpolator(new DecelerateInterpolator())
|
||||||
|
.setListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
updateVisibility(toolbarContainer, toolbarAlpha);
|
||||||
|
mapActivity.updateStatusBarColor();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.start();
|
||||||
|
} else {
|
||||||
|
updateToolbarVisibility(toolbarContainer, y);
|
||||||
|
mapActivity.updateStatusBarColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onHeaderClick() {
|
protected void onHeaderClick() {
|
||||||
adjustMapPosition(getViewY());
|
adjustMapPosition(getViewY());
|
||||||
|
@ -664,7 +820,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
@Override
|
@Override
|
||||||
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||||
for (TrackMenuType type : TrackMenuType.values()) {
|
for (TrackMenuType type : TrackMenuType.values()) {
|
||||||
if (type.iconId == item.getItemId()) {
|
if (type.menuItemId == item.getItemId()) {
|
||||||
menuType = type;
|
menuType = type;
|
||||||
setupCards();
|
setupCards();
|
||||||
updateHeader();
|
updateHeader();
|
||||||
|
@ -687,6 +843,9 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
if (descriptionCard != null) {
|
if (descriptionCard != null) {
|
||||||
descriptionCard.updateContent();
|
descriptionCard.updateContent();
|
||||||
}
|
}
|
||||||
|
if (pointsCard != null) {
|
||||||
|
pointsCard.updateContent();
|
||||||
|
}
|
||||||
setupCards();
|
setupCards();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,6 +859,18 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPointsDeletionStarted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPointsDeleted() {
|
||||||
|
if (pointsCard != null) {
|
||||||
|
pointsCard.onPointsDeleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPointSelected(TrkSegment segment, double lat, double lon) {
|
public void onPointSelected(TrkSegment segment, double lat, double lon) {
|
||||||
if (trackChartPoints == null) {
|
if (trackChartPoints == null) {
|
||||||
|
@ -729,7 +900,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
TrackDetailsMenu trackDetailsMenu = getMapActivity().getTrackDetailsMenu();
|
TrackDetailsMenu trackDetailsMenu = getMapActivity().getTrackDetailsMenu();
|
||||||
trackDetailsMenu.setGpxItem(gpxItem);
|
trackDetailsMenu.setGpxItem(gpxItem);
|
||||||
trackDetailsMenu.show();
|
trackDetailsMenu.show();
|
||||||
close();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -783,7 +954,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
private void editSegment(TrkSegment segment) {
|
private void editSegment(TrkSegment segment) {
|
||||||
GPXFile gpxFile = getGpx();
|
GPXFile gpxFile = getGpx();
|
||||||
openPlanRoute(new GpxData(gpxFile));
|
openPlanRoute(new GpxData(gpxFile));
|
||||||
close();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openPlanRoute(GpxData gpxData) {
|
public void openPlanRoute(GpxData gpxData) {
|
||||||
|
@ -834,12 +1005,24 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close() {
|
private void hide() {
|
||||||
try {
|
try {
|
||||||
MapActivity mapActivity = getMapActivity();
|
MapActivity mapActivity = getMapActivity();
|
||||||
if (mapActivity != null) {
|
if (mapActivity != null) {
|
||||||
FragmentManager fragmentManager = mapActivity.getSupportFragmentManager();
|
FragmentManager fragmentManager = mapActivity.getSupportFragmentManager();
|
||||||
fragmentManager.beginTransaction().remove(this).commitAllowingStateLoss();
|
fragmentManager.beginTransaction().hide(this).commit();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
try {
|
||||||
|
MapActivity mapActivity = getMapActivity();
|
||||||
|
if (mapActivity != null) {
|
||||||
|
FragmentManager fragmentManager = mapActivity.getSupportFragmentManager();
|
||||||
|
fragmentManager.beginTransaction().show(this).commit();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e);
|
log.error(e);
|
||||||
|
@ -859,7 +1042,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
||||||
|
|
||||||
mapActivity.getSupportFragmentManager()
|
mapActivity.getSupportFragmentManager()
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.replace(R.id.fragmentContainer, fragment, fragment.getFragmentTag())
|
.replace(R.id.fragmentContainer, fragment, TAG)
|
||||||
.addToBackStack(fragment.getFragmentTag())
|
.addToBackStack(fragment.getFragmentTag())
|
||||||
.commitAllowingStateLoss();
|
.commitAllowingStateLoss();
|
||||||
return true;
|
return true;
|
||||||
|
|
639
OsmAnd/src/net/osmand/plus/track/TrackPointsCard.java
Normal file
639
OsmAnd/src/net/osmand/plus/track/TrackPointsCard.java
Normal file
|
@ -0,0 +1,639 @@
|
||||||
|
package net.osmand.plus.track;
|
||||||
|
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.text.style.ForegroundColorSpan;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.ExpandableListView;
|
||||||
|
import android.widget.ExpandableListView.OnChildClickListener;
|
||||||
|
import android.widget.Filter;
|
||||||
|
import android.widget.Filterable;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import net.osmand.AndroidUtils;
|
||||||
|
import net.osmand.Collator;
|
||||||
|
import net.osmand.GPXUtilities.WptPt;
|
||||||
|
import net.osmand.OsmAndCollator;
|
||||||
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||||
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||||
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||||
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.UiUtilities;
|
||||||
|
import net.osmand.plus.activities.MapActivity;
|
||||||
|
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
|
||||||
|
import net.osmand.plus.base.PointImageDrawable;
|
||||||
|
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||||
|
import net.osmand.plus.myplaces.DeletePointsTask;
|
||||||
|
import net.osmand.plus.myplaces.DeletePointsTask.OnPointsDeleteListener;
|
||||||
|
import net.osmand.plus.myplaces.EditTrackGroupDialogFragment;
|
||||||
|
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||||
|
import net.osmand.util.Algorithms;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class TrackPointsCard extends BaseCard implements OnChildClickListener, OnPointsDeleteListener {
|
||||||
|
|
||||||
|
public static final int ADD_WAYPOINT_INDEX = 0;
|
||||||
|
public static final int DELETE_WAYPOINTS_INDEX = 1;
|
||||||
|
|
||||||
|
private final TrackDisplayHelper displayHelper;
|
||||||
|
private final GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_POINTS, GpxDisplayItemType.TRACK_ROUTE_POINTS};
|
||||||
|
|
||||||
|
private final Set<Integer> selectedGroups = new LinkedHashSet<>();
|
||||||
|
private final LinkedHashMap<GpxDisplayItemType, Set<GpxDisplayItem>> selectedItems = new LinkedHashMap<>();
|
||||||
|
private boolean selectionMode;
|
||||||
|
|
||||||
|
private final PointGPXAdapter adapter;
|
||||||
|
private ExpandableListView listView;
|
||||||
|
|
||||||
|
public TrackPointsCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper) {
|
||||||
|
super(mapActivity);
|
||||||
|
this.displayHelper = displayHelper;
|
||||||
|
adapter = new PointGPXAdapter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSelectionMode() {
|
||||||
|
return selectionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectionMode(boolean selectionMode) {
|
||||||
|
this.selectionMode = selectionMode;
|
||||||
|
adapter.notifyDataSetInvalidated();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCardLayoutId() {
|
||||||
|
return R.layout.track_points_card;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateContent() {
|
||||||
|
listView = view.findViewById(android.R.id.list);
|
||||||
|
listView.setOnChildClickListener(this);
|
||||||
|
|
||||||
|
adapter.setFilterResults(null);
|
||||||
|
adapter.synchronizeGroups(getOriginalGroups());
|
||||||
|
if (listView.getAdapter() == null) {
|
||||||
|
listView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
if (!adapter.isEmpty() && listView.getFooterViewsCount() == 0) {
|
||||||
|
LayoutInflater inflater = UiUtilities.getInflater(mapActivity, nightMode);
|
||||||
|
listView.addFooterView(inflater.inflate(R.layout.list_shadow_footer, listView, false));
|
||||||
|
addActions(inflater);
|
||||||
|
}
|
||||||
|
expandAllGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addActions(LayoutInflater inflater) {
|
||||||
|
View view = inflater.inflate(R.layout.preference_category_with_descr, listView, false);
|
||||||
|
TextView title = view.findViewById(android.R.id.title);
|
||||||
|
title.setText(R.string.shared_string_actions);
|
||||||
|
|
||||||
|
AndroidUiHelper.updateVisibility(view.findViewById(android.R.id.icon), false);
|
||||||
|
AndroidUiHelper.updateVisibility(view.findViewById(android.R.id.summary), false);
|
||||||
|
listView.addFooterView(view);
|
||||||
|
|
||||||
|
addWaypointAction(inflater);
|
||||||
|
deleteWaypointAction(inflater);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addWaypointAction(LayoutInflater inflater) {
|
||||||
|
View view = inflater.inflate(R.layout.preference_button, listView, false);
|
||||||
|
TextView addWaypointTitle = view.findViewById(android.R.id.title);
|
||||||
|
ImageView addWaypointIcon = view.findViewById(android.R.id.icon);
|
||||||
|
|
||||||
|
addWaypointTitle.setText(R.string.add_waypoint);
|
||||||
|
addWaypointIcon.setImageDrawable(getContentIcon(R.drawable.ic_action_name_field));
|
||||||
|
|
||||||
|
AndroidUiHelper.updateVisibility(view.findViewById(R.id.divider), true);
|
||||||
|
|
||||||
|
view.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
CardListener listener = getListener();
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onCardButtonPressed(TrackPointsCard.this, ADD_WAYPOINT_INDEX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
listView.addFooterView(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteWaypointAction(LayoutInflater inflater) {
|
||||||
|
View view = inflater.inflate(R.layout.preference_button, listView, false);
|
||||||
|
TextView deleteWaypointsTitle = view.findViewById(android.R.id.title);
|
||||||
|
ImageView deleteWaypointsIcon = view.findViewById(android.R.id.icon);
|
||||||
|
|
||||||
|
deleteWaypointsTitle.setText(R.string.delete_waypoints);
|
||||||
|
deleteWaypointsIcon.setImageDrawable(getColoredIcon(R.drawable.ic_action_delete_dark, R.color.color_osm_edit_delete));
|
||||||
|
|
||||||
|
view.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
CardListener listener = getListener();
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onCardButtonPressed(TrackPointsCard.this, DELETE_WAYPOINTS_INDEX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
listView.addFooterView(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expandAllGroups() {
|
||||||
|
for (int i = 0; i < adapter.getGroupCount(); i++) {
|
||||||
|
listView.expandGroup(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<GpxDisplayGroup> getOriginalGroups() {
|
||||||
|
return displayHelper.getOriginalGroups(filterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteItemsAction() {
|
||||||
|
int size = getSelectedItemsCount();
|
||||||
|
if (size > 0) {
|
||||||
|
AlertDialog.Builder b = new AlertDialog.Builder(mapActivity);
|
||||||
|
b.setMessage(app.getString(R.string.points_delete_multiple, size));
|
||||||
|
b.setPositiveButton(R.string.shared_string_delete, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
deleteItems();
|
||||||
|
setSelectionMode(false);
|
||||||
|
adapter.notifyDataSetInvalidated();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
b.setNegativeButton(R.string.shared_string_cancel, null);
|
||||||
|
b.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteItems() {
|
||||||
|
new DeletePointsTask(app, displayHelper.getGpx(), getSelectedItems(), this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<GpxDisplayItem> getSelectedItems() {
|
||||||
|
Set<GpxDisplayItem> result = new LinkedHashSet<>();
|
||||||
|
for (Set<GpxDisplayItem> set : selectedItems.values()) {
|
||||||
|
if (set != null) {
|
||||||
|
result.addAll(set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSelectionMode() {
|
||||||
|
int size = getSelectedItemsCount();
|
||||||
|
app.showToastMessage(size + " " + app.getString(R.string.shared_string_selected_lowercase));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSelectedItemsCount() {
|
||||||
|
int count = 0;
|
||||||
|
for (Set<GpxDisplayItem> set : selectedItems.values()) {
|
||||||
|
if (set != null) {
|
||||||
|
count += set.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPointsDeletionStarted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPointsDeleted() {
|
||||||
|
selectedItems.clear();
|
||||||
|
selectedGroups.clear();
|
||||||
|
adapter.synchronizeGroups(getOriginalGroups());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void filter(String text) {
|
||||||
|
adapter.getFilter().filter(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PointGPXAdapter extends OsmandBaseExpandableListAdapter implements Filterable {
|
||||||
|
|
||||||
|
private final List<GpxDisplayGroup> groups = new ArrayList<>();
|
||||||
|
private final Map<GpxDisplayGroup, List<GpxDisplayItem>> itemGroups = new LinkedHashMap<>();
|
||||||
|
private final Comparator<String> comparator;
|
||||||
|
private Filter pointsFilter;
|
||||||
|
private Set<?> filteredItems;
|
||||||
|
|
||||||
|
PointGPXAdapter() {
|
||||||
|
final Collator collator = OsmAndCollator.primaryCollator();
|
||||||
|
comparator = new Comparator<String>() {
|
||||||
|
@Override
|
||||||
|
public int compare(String s1, String s2) {
|
||||||
|
return collator.compare(s1, s2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void synchronizeGroups(@NonNull List<GpxDisplayGroup> displayGroups) {
|
||||||
|
groups.clear();
|
||||||
|
itemGroups.clear();
|
||||||
|
Set<?> filtered = filteredItems;
|
||||||
|
Collections.sort(displayGroups, new Comparator<GpxDisplayGroup>() {
|
||||||
|
@Override
|
||||||
|
public int compare(GpxDisplayGroup g1, GpxDisplayGroup g2) {
|
||||||
|
int i1 = g1.getType().ordinal();
|
||||||
|
int i2 = g2.getType().ordinal();
|
||||||
|
return i1 < i2 ? -1 : (i1 == i2 ? 0 : 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
List<GpxDisplayGroup> trackPointsGroups = new ArrayList<>();
|
||||||
|
List<GpxDisplayGroup> routePointsGroups = new ArrayList<>();
|
||||||
|
for (GpxDisplayGroup group : displayGroups) {
|
||||||
|
if (group.getType() == GpxDisplayItemType.TRACK_POINTS) {
|
||||||
|
trackPointsGroups.add(group);
|
||||||
|
} else if (group.getType() == GpxDisplayItemType.TRACK_ROUTE_POINTS) {
|
||||||
|
routePointsGroups.add(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processDisplayGroups(trackPointsGroups, filtered);
|
||||||
|
processDisplayGroups(routePointsGroups, filtered);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processDisplayGroups(List<GpxDisplayGroup> displayGroups, Set<?> filteredItems) {
|
||||||
|
for (int i = 0; i < displayGroups.size(); i++) {
|
||||||
|
GpxDisplayGroup group = displayGroups.get(i);
|
||||||
|
if (group.getModifiableList().isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Map<String, List<GpxDisplayItem>> itemsMap = collectItemsByCategory(group, i);
|
||||||
|
if (filteredItems != null) {
|
||||||
|
itemsMap = filterItems(itemsMap, filteredItems);
|
||||||
|
}
|
||||||
|
if (!Algorithms.isEmpty(itemsMap)) {
|
||||||
|
setCollectedItems(group, itemsMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, List<GpxDisplayItem>> collectItemsByCategory(GpxDisplayGroup group, int index) {
|
||||||
|
Map<String, List<GpxDisplayItem>> itemsMap = new HashMap<>();
|
||||||
|
|
||||||
|
for (GpxDisplayItem item : group.getModifiableList()) {
|
||||||
|
String category;
|
||||||
|
if (item.locationStart != null) {
|
||||||
|
if (group.getType() == GpxDisplayItemType.TRACK_POINTS) {
|
||||||
|
category = item.locationStart.category;
|
||||||
|
if (Algorithms.isEmpty(category)) {
|
||||||
|
category = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
category = app.getString(R.string.route_points) + " " + (index + 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
category = "";
|
||||||
|
}
|
||||||
|
List<GpxDisplayItem> items = itemsMap.get(category);
|
||||||
|
if (items == null) {
|
||||||
|
items = new ArrayList<>();
|
||||||
|
itemsMap.put(category, items);
|
||||||
|
}
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
return itemsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, List<GpxDisplayItem>> filterItems(Map<String, List<GpxDisplayItem>> itemsMap, Set<?> filteredItems) {
|
||||||
|
Map<String, List<GpxDisplayItem>> itemsMapFiltered = new HashMap<>();
|
||||||
|
for (Entry<String, List<GpxDisplayItem>> e : itemsMap.entrySet()) {
|
||||||
|
String category = e.getKey();
|
||||||
|
List<GpxDisplayItem> items = e.getValue();
|
||||||
|
if (filteredItems.contains(category)) {
|
||||||
|
itemsMapFiltered.put(category, items);
|
||||||
|
} else {
|
||||||
|
for (GpxDisplayItem i : items) {
|
||||||
|
if (filteredItems.contains(i)) {
|
||||||
|
List<GpxDisplayItem> itemsFiltered = itemsMapFiltered.get(category);
|
||||||
|
if (itemsFiltered == null) {
|
||||||
|
itemsFiltered = new ArrayList<>();
|
||||||
|
itemsMapFiltered.put(category, itemsFiltered);
|
||||||
|
}
|
||||||
|
itemsFiltered.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itemsMapFiltered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCollectedItems(GpxDisplayGroup group, Map<String, List<GpxDisplayItem>> itemsMap) {
|
||||||
|
List<String> categories = new ArrayList<>(itemsMap.keySet());
|
||||||
|
Collections.sort(categories, comparator);
|
||||||
|
for (String category : categories) {
|
||||||
|
List<GpxDisplayItem> values = itemsMap.get(category);
|
||||||
|
GpxDisplayGroup headerGroup = group.cloneInstance();
|
||||||
|
headerGroup.setName(category);
|
||||||
|
for (GpxDisplayItem i : values) {
|
||||||
|
if (i.locationStart != null && i.locationStart.getColor() != 0) {
|
||||||
|
headerGroup.setColor(i.locationStart.getColor(group.getColor()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<GpxDisplayItem> headerGroupItems = headerGroup.getModifiableList();
|
||||||
|
headerGroupItems.clear();
|
||||||
|
headerGroupItems.addAll(values);
|
||||||
|
itemGroups.put(headerGroup, values);
|
||||||
|
this.groups.add(headerGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getGroupCount() {
|
||||||
|
return groups.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GpxDisplayGroup getGroup(int groupPosition) {
|
||||||
|
return groups.get(groupPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getGroupId(int groupPosition) {
|
||||||
|
return groupPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChildrenCount(int groupPosition) {
|
||||||
|
return itemGroups.get(groups.get(groupPosition)).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GpxDisplayItem getChild(int groupPosition, int childPosition) {
|
||||||
|
return itemGroups.get(groups.get(groupPosition)).get(childPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getChildId(int groupPosition, int childPosition) {
|
||||||
|
return groupPosition * 10000 + childPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChildSelectable(int groupPosition, int childPosition) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasStableIds() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
|
||||||
|
final GpxDisplayGroup group = getGroup(groupPosition);
|
||||||
|
View row = convertView;
|
||||||
|
if (row == null) {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(view.getContext());
|
||||||
|
row = inflater.inflate(R.layout.wpt_list_item, parent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
row.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (listView.isGroupExpanded(groupPosition)) {
|
||||||
|
listView.collapseGroup(groupPosition);
|
||||||
|
} else {
|
||||||
|
listView.expandGroup(groupPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
String categoryName = group.getName();
|
||||||
|
if (TextUtils.isEmpty(categoryName)) {
|
||||||
|
categoryName = app.getString(R.string.shared_string_gpx_points);
|
||||||
|
}
|
||||||
|
SpannableStringBuilder text = new SpannableStringBuilder(categoryName)
|
||||||
|
.append(" – ")
|
||||||
|
.append(String.valueOf(getChildrenCount(groupPosition)));
|
||||||
|
text.setSpan(new ForegroundColorSpan(AndroidUtils.getColorFromAttr(view.getContext(), R.attr.wikivoyage_primary_text_color)),
|
||||||
|
0, categoryName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
text.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.wikivoyage_secondary_text)),
|
||||||
|
categoryName.length() + 1, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
|
TextView title = row.findViewById(R.id.label);
|
||||||
|
title.setText(text);
|
||||||
|
|
||||||
|
ImageView icon = row.findViewById(R.id.icon);
|
||||||
|
icon.setImageDrawable(getContentIcon(R.drawable.ic_action_folder));
|
||||||
|
|
||||||
|
boolean expanded = listView.isGroupExpanded(groupPosition);
|
||||||
|
ImageView expandImage = row.findViewById(R.id.expand_image);
|
||||||
|
expandImage.setImageDrawable(getContentIcon(expanded ? R.drawable.ic_action_arrow_up : R.drawable.ic_action_arrow_down));
|
||||||
|
|
||||||
|
final CheckBox checkBox = (CheckBox) row.findViewById(R.id.toggle_item);
|
||||||
|
if (selectionMode) {
|
||||||
|
checkBox.setChecked(selectedGroups.contains(groupPosition));
|
||||||
|
checkBox.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
List<GpxDisplayItem> items = itemGroups.get(group);
|
||||||
|
setGroupSelection(items, groupPosition, checkBox.isChecked());
|
||||||
|
adapter.notifyDataSetInvalidated();
|
||||||
|
updateSelectionMode();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AndroidUiHelper.updateVisibility(checkBox, true);
|
||||||
|
} else {
|
||||||
|
AndroidUiHelper.updateVisibility(checkBox, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageView options = (ImageView) row.findViewById(R.id.options);
|
||||||
|
options.setImageDrawable(getContentIcon(R.drawable.ic_overflow_menu_white));
|
||||||
|
options.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
EditTrackGroupDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
|
||||||
|
group, mapActivity.getTrackMenuFragment());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AndroidUiHelper.updateVisibility(expandImage, true);
|
||||||
|
AndroidUiHelper.updateVisibility(row.findViewById(R.id.divider), true);
|
||||||
|
AndroidUiHelper.updateVisibility(row.findViewById(R.id.description), false);
|
||||||
|
AndroidUiHelper.updateVisibility(row.findViewById(R.id.list_divider), false);
|
||||||
|
AndroidUiHelper.updateVisibility(row.findViewById(R.id.group_divider), true);
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
|
||||||
|
View row = convertView;
|
||||||
|
if (row == null) {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(view.getContext());
|
||||||
|
row = inflater.inflate(R.layout.wpt_list_item, parent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final GpxDisplayGroup group = getGroup(groupPosition);
|
||||||
|
final GpxDisplayItem gpxItem = getChild(groupPosition, childPosition);
|
||||||
|
|
||||||
|
TextView title = row.findViewById(R.id.label);
|
||||||
|
title.setText(gpxItem.name);
|
||||||
|
|
||||||
|
TextView description = row.findViewById(R.id.description);
|
||||||
|
if (!Algorithms.isEmpty(gpxItem.description)) {
|
||||||
|
description.setText(gpxItem.description);
|
||||||
|
AndroidUiHelper.updateVisibility(description, true);
|
||||||
|
} else {
|
||||||
|
AndroidUiHelper.updateVisibility(description, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final CheckBox checkBox = (CheckBox) row.findViewById(R.id.toggle_item);
|
||||||
|
if (selectionMode) {
|
||||||
|
checkBox.setVisibility(View.VISIBLE);
|
||||||
|
checkBox.setChecked(selectedItems.get(group.getType()) != null && selectedItems.get(group.getType()).contains(gpxItem));
|
||||||
|
checkBox.setOnClickListener(new View.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (checkBox.isChecked()) {
|
||||||
|
Set<GpxDisplayItem> set = selectedItems.get(group.getType());
|
||||||
|
if (set != null) {
|
||||||
|
set.add(gpxItem);
|
||||||
|
} else {
|
||||||
|
set = new LinkedHashSet<>();
|
||||||
|
set.add(gpxItem);
|
||||||
|
selectedItems.put(group.getType(), set);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Set<GpxDisplayItem> set = selectedItems.get(group.getType());
|
||||||
|
if (set != null) {
|
||||||
|
set.remove(gpxItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateSelectionMode();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AndroidUiHelper.updateVisibility(checkBox, true);
|
||||||
|
AndroidUiHelper.updateVisibility(row.findViewById(R.id.icon), false);
|
||||||
|
} else {
|
||||||
|
ImageView icon = row.findViewById(R.id.icon);
|
||||||
|
if (GpxDisplayItemType.TRACK_POINTS == group.getType()) {
|
||||||
|
WptPt wpt = gpxItem.locationStart;
|
||||||
|
int groupColor = wpt.getColor(group.getColor());
|
||||||
|
if (groupColor == 0) {
|
||||||
|
groupColor = ContextCompat.getColor(app, R.color.gpx_color_point);
|
||||||
|
}
|
||||||
|
icon.setImageDrawable(PointImageDrawable.getFromWpt(app, groupColor, false, wpt));
|
||||||
|
} else {
|
||||||
|
icon.setImageDrawable(getContentIcon(R.drawable.ic_action_marker_dark));
|
||||||
|
}
|
||||||
|
AndroidUiHelper.updateVisibility(icon, true);
|
||||||
|
AndroidUiHelper.updateVisibility(checkBox, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidUiHelper.updateVisibility(row.findViewById(R.id.divider), false);
|
||||||
|
AndroidUiHelper.updateVisibility(row.findViewById(R.id.options), false);
|
||||||
|
AndroidUiHelper.updateVisibility(row.findViewById(R.id.list_divider), true);
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setGroupSelection(List<GpxDisplayItem> items, int groupPosition, boolean select) {
|
||||||
|
GpxDisplayGroup group = groups.get(groupPosition);
|
||||||
|
if (select) {
|
||||||
|
selectedGroups.add(groupPosition);
|
||||||
|
if (items != null) {
|
||||||
|
Set<GpxDisplayItem> set = selectedItems.get(group.getType());
|
||||||
|
if (set != null) {
|
||||||
|
set.addAll(items);
|
||||||
|
} else {
|
||||||
|
set = new LinkedHashSet<>(items);
|
||||||
|
selectedItems.put(group.getType(), set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selectedGroups.remove(groupPosition);
|
||||||
|
selectedItems.remove(group.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Filter getFilter() {
|
||||||
|
if (pointsFilter == null) {
|
||||||
|
pointsFilter = new PointsFilter();
|
||||||
|
}
|
||||||
|
return pointsFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilterResults(Set<?> values) {
|
||||||
|
this.filteredItems = values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PointsFilter extends Filter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FilterResults performFiltering(CharSequence constraint) {
|
||||||
|
FilterResults results = new FilterResults();
|
||||||
|
if (constraint == null || constraint.length() == 0) {
|
||||||
|
results.values = null;
|
||||||
|
results.count = 1;
|
||||||
|
} else {
|
||||||
|
Set<Object> filter = new HashSet<>();
|
||||||
|
String cs = constraint.toString().toLowerCase();
|
||||||
|
List<GpxDisplayGroup> groups = getOriginalGroups();
|
||||||
|
if (groups != null) {
|
||||||
|
for (GpxDisplayGroup g : groups) {
|
||||||
|
for (GpxDisplayItem i : g.getModifiableList()) {
|
||||||
|
if (i.name.toLowerCase().contains(cs)) {
|
||||||
|
filter.add(i);
|
||||||
|
} else if (i.locationStart != null && !TextUtils.isEmpty(i.locationStart.category)
|
||||||
|
&& i.locationStart.category.toLowerCase().contains(cs)) {
|
||||||
|
filter.add(i.locationStart.category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results.values = filter;
|
||||||
|
results.count = filter.size();
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void publishResults(CharSequence constraint, FilterResults results) {
|
||||||
|
synchronized (adapter) {
|
||||||
|
adapter.setFilterResults((Set<?>) results.values);
|
||||||
|
List<GpxDisplayGroup> groups = getOriginalGroups();
|
||||||
|
if (groups != null) {
|
||||||
|
adapter.synchronizeGroups(groups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
expandAllGroups();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,19 +6,20 @@ import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import net.osmand.GPXUtilities.GPXFile;
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
import net.osmand.data.PointDescription;
|
import net.osmand.data.PointDescription;
|
||||||
import net.osmand.data.QuadRect;
|
import net.osmand.data.QuadRect;
|
||||||
import net.osmand.data.RotatedTileBox;
|
import net.osmand.data.RotatedTileBox;
|
||||||
import net.osmand.GPXUtilities.GPXFile;
|
|
||||||
import net.osmand.plus.UiUtilities;
|
|
||||||
import net.osmand.plus.R;
|
import net.osmand.plus.R;
|
||||||
|
import net.osmand.plus.UiUtilities;
|
||||||
import net.osmand.plus.activities.MapActivity;
|
import net.osmand.plus.activities.MapActivity;
|
||||||
import net.osmand.plus.activities.TrackActivity;
|
import net.osmand.plus.activities.TrackActivity;
|
||||||
import net.osmand.plus.mapcontextmenu.MapContextMenu;
|
import net.osmand.plus.mapcontextmenu.MapContextMenu;
|
||||||
import net.osmand.plus.mapcontextmenu.editors.RtePtEditor;
|
import net.osmand.plus.mapcontextmenu.editors.RtePtEditor;
|
||||||
import net.osmand.plus.mapcontextmenu.editors.WptPtEditor;
|
import net.osmand.plus.mapcontextmenu.editors.WptPtEditor;
|
||||||
import net.osmand.plus.mapcontextmenu.editors.WptPtEditor.OnDismissListener;
|
import net.osmand.plus.mapcontextmenu.editors.WptPtEditor.OnDismissListener;
|
||||||
|
import net.osmand.plus.track.TrackMenuFragment;
|
||||||
import net.osmand.plus.views.layers.ContextMenuLayer;
|
import net.osmand.plus.views.layers.ContextMenuLayer;
|
||||||
|
|
||||||
public class AddGpxPointBottomSheetHelper implements OnDismissListener {
|
public class AddGpxPointBottomSheetHelper implements OnDismissListener {
|
||||||
|
@ -73,7 +74,7 @@ public class AddGpxPointBottomSheetHelper implements OnDismissListener {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
hide();
|
hide();
|
||||||
contextMenuLayer.cancelAddGpxPoint();
|
contextMenuLayer.cancelAddGpxPoint();
|
||||||
openTrackActivity();
|
onClose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -140,7 +141,16 @@ public class AddGpxPointBottomSheetHelper implements OnDismissListener {
|
||||||
if (contextMenu.isVisible() && contextMenu.isClosable()) {
|
if (contextMenu.isVisible() && contextMenu.isClosable()) {
|
||||||
contextMenu.close();
|
contextMenu.close();
|
||||||
}
|
}
|
||||||
openTrackActivity();
|
onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClose() {
|
||||||
|
TrackMenuFragment fragment = mapActivity.getTrackMenuFragment();
|
||||||
|
if (fragment != null) {
|
||||||
|
fragment.show();
|
||||||
|
} else {
|
||||||
|
openTrackActivity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openTrackActivity() {
|
private void openTrackActivity() {
|
||||||
|
|
|
@ -574,7 +574,6 @@ public class ContextMenuLayer extends OsmandMapLayer {
|
||||||
public void cancelAddGpxPoint() {
|
public void cancelAddGpxPoint() {
|
||||||
cancelApplyingNewMarkerPosition = true;
|
cancelApplyingNewMarkerPosition = true;
|
||||||
quitAddGpxPoint();
|
quitAddGpxPoint();
|
||||||
activity.getContextMenu().show();
|
|
||||||
applyingMarkerLatLon = null;
|
applyingMarkerLatLon = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -516,7 +516,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
for (WptPt wpt : getListStarPoints(g)) {
|
for (WptPt wpt : getListStarPoints(g)) {
|
||||||
if (wpt.lat >= latLonBounds.bottom && wpt.lat <= latLonBounds.top
|
if (wpt.lat >= latLonBounds.bottom && wpt.lat <= latLonBounds.top
|
||||||
&& wpt.lon >= latLonBounds.left && wpt.lon <= latLonBounds.right
|
&& wpt.lon >= latLonBounds.left && wpt.lon <= latLonBounds.right
|
||||||
&& wpt != contextMenuLayer.getMoveableObject()) {
|
&& wpt != contextMenuLayer.getMoveableObject() && !isPointHidden(g, wpt)) {
|
||||||
pointFileMap.put(wpt, g);
|
pointFileMap.put(wpt, g);
|
||||||
MapMarker marker = null;
|
MapMarker marker = null;
|
||||||
if (synced) {
|
if (synced) {
|
||||||
|
@ -777,6 +777,14 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
return g.getGpxFile().getPoints();
|
return g.getGpxFile().getPoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPointHidden(SelectedGpxFile selectedGpxFile, WptPt point) {
|
||||||
|
if (!Algorithms.isEmpty(selectedGpxFile.getHiddenGroups())) {
|
||||||
|
return selectedGpxFile.getHiddenGroups().contains(point.category);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) {
|
private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) {
|
||||||
return (Math.abs(objx - ex) <= radius && Math.abs(objy - ey) <= radius);
|
return (Math.abs(objx - ex) <= radius && Math.abs(objy - ey) <= radius);
|
||||||
}
|
}
|
||||||
|
@ -790,6 +798,9 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
||||||
List<WptPt> pts = getListStarPoints(g);
|
List<WptPt> pts = getListStarPoints(g);
|
||||||
// int fcolor = g.getColor() == 0 ? clr : g.getColor();
|
// int fcolor = g.getColor() == 0 ? clr : g.getColor();
|
||||||
for (WptPt n : pts) {
|
for (WptPt n : pts) {
|
||||||
|
if (isPointHidden(g, n)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
int x = (int) tb.getPixXFromLatLon(n.lat, n.lon);
|
int x = (int) tb.getPixXFromLatLon(n.lat, n.lon);
|
||||||
int y = (int) tb.getPixYFromLatLon(n.lat, n.lon);
|
int y = (int) tb.getPixYFromLatLon(n.lat, n.lon);
|
||||||
if (calculateBelongs(ex, ey, x, y, r)) {
|
if (calculateBelongs(ex, ey, x, y, r)) {
|
||||||
|
|
Loading…
Reference in a new issue