Add save as new track menu

This commit is contained in:
PavelRatushny 2017-08-17 12:25:27 +03:00
parent 2f557835ae
commit 971268480d
5 changed files with 367 additions and 65 deletions

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/bg_color"
android:orientation="vertical">
<ScrollView
android:id="@+id/save_as_new_track_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="8dp">
<TextView
android:id="@+id/save_as_new_track_title"
android:layout_width="match_parent"
android:layout_height="52dp"
android:gravity="center_vertical"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:text="@string/shared_string_save_as_gpx"
android:textAppearance="@style/TextAppearance.ListItemTitle"/>
<TextView
android:layout_width="match_parent"
android:layout_height="44dp"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:text="@string/measurement_tool_snap_to_road_descr"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"/>
<RelativeLayout
android:id="@+id/save_as_route_point_row"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="?attr/selectableItemBackground"
android:minHeight="48dp"
android:paddingEnd="16dp"
android:paddingStart="16dp">
<ImageView
android:id="@+id/route_point_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
tools:src="@drawable/ic_action_route_points"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/route_point_icon"
android:layout_toRightOf="@id/route_point_icon"
android:maxLines="1"
android:text="@string/save_as_route_point"
android:textAppearance="@style/TextAppearance.ListItemTitle"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/save_as_line_row"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="?attr/selectableItemBackground"
android:minHeight="48dp"
android:paddingEnd="16dp"
android:paddingStart="16dp">
<ImageView
android:id="@+id/line_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
tools:src="@drawable/ic_action_split_interval"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/line_icon"
android:layout_toRightOf="@id/line_icon"
android:maxLines="1"
android:text="@string/save_as_line"
android:textAppearance="@style/TextAppearance.ListItemTitle"/>
</RelativeLayout>
</LinearLayout>
</ScrollView>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dashboard_divider"/>
<FrameLayout
android:id="@+id/cancel_row"
android:layout_width="match_parent"
android:layout_height="@dimen/measure_distance_bottom_sheet_cancel_button_height"
android:background="?attr/selectableItemBackground">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/shared_string_cancel"
android:textAllCaps="true"
android:textColor="?attr/color_dialog_buttons"
android:textSize="14sp"
android:textStyle="bold"/>
</FrameLayout>
</LinearLayout>

View file

@ -9,6 +9,8 @@
3. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
-->
<string name="save_as_route_point">Save as Route Point</string>
<string name="save_as_line">Save as line</string>
<string name="route_point">Route point</string>
<string name="edit_line">Edit Line</string>
<string name="add_point_before">Add point before</string>

View file

@ -37,6 +37,7 @@ import net.osmand.plus.ApplicationMode;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.Route;
import net.osmand.plus.GPXUtilities.Track;
import net.osmand.plus.GPXUtilities.TrkSegment;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
@ -48,6 +49,7 @@ import net.osmand.plus.activities.TrackActivity.NewGpxLine;
import net.osmand.plus.activities.TrackActivity.NewGpxLine.LineType;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.measurementtool.SaveAsNewTrackBottomSheetDialogFragment.SaveAsNewTrackFragmentListener;
import net.osmand.plus.measurementtool.OptionsBottomSheetDialogFragment.OptionsFragmentListener;
import net.osmand.plus.measurementtool.SelectedPointBottomSheetDialogFragment.SelectedPointFragmentListener;
import net.osmand.plus.measurementtool.SnapToRoadBottomSheetDialogFragment.SnapToRoadFragmentListener;
@ -119,6 +121,8 @@ public class MeasurementToolFragment extends Fragment {
private int positionToAddPoint = -1;
private enum SaveType { ROUTE_POINT, LINE };
public void setNewGpxLine(NewGpxLine newGpxLine) {
this.newGpxLine = newGpxLine;
}
@ -149,6 +153,11 @@ public class MeasurementToolFragment extends Fragment {
if (snapToRoadFragment != null) {
((SnapToRoadBottomSheetDialogFragment) snapToRoadFragment).setListener(createSnapToRoadFragmentListener());
}
Fragment saveAsNewTrackFragment = mapActivity.getSupportFragmentManager().findFragmentByTag(SaveAsNewTrackBottomSheetDialogFragment.TAG);
if (saveAsNewTrackFragment != null) {
SaveAsNewTrackBottomSheetDialogFragment saveAsNewTrackBottomSheetDialogFragment = (SaveAsNewTrackBottomSheetDialogFragment) saveAsNewTrackFragment;
saveAsNewTrackBottomSheetDialogFragment.setListener(createSaveAsNewTrackFragmentListener());
}
commandManager.resetMeasurementLayer(measurementLayer);
iconsCache = mapActivity.getMyApplication().getIconsCache();
@ -527,7 +536,7 @@ public class MeasurementToolFragment extends Fragment {
public void saveAsNewTrackOnClick() {
if (mapActivity != null && measurementLayer != null) {
if (measurementLayer.getPointsCount() > 0) {
saveAsGpxOnClick(mapActivity);
openSaveAsNewTrackMenu(mapActivity);
} else {
Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show();
}
@ -705,6 +714,26 @@ public class MeasurementToolFragment extends Fragment {
fragment.show(mapActivity.getSupportFragmentManager(), SelectedPointBottomSheetDialogFragment.TAG);
}
private void openSaveAsNewTrackMenu(MapActivity mapActivity) {
SaveAsNewTrackBottomSheetDialogFragment fragment = new SaveAsNewTrackBottomSheetDialogFragment();
fragment.setListener(createSaveAsNewTrackFragmentListener());
fragment.show(mapActivity.getSupportFragmentManager(), SaveAsNewTrackBottomSheetDialogFragment.TAG);
}
private SaveAsNewTrackFragmentListener createSaveAsNewTrackFragmentListener() {
return new SaveAsNewTrackFragmentListener() {
@Override
public void saveAsRoutePointOnClick() {
saveAsGpx(SaveType.ROUTE_POINT);
}
@Override
public void saveAsLineOnClick() {
saveAsGpx(SaveType.LINE);
}
};
}
private AlertDialog showAddSegmentDialog(final MapActivity mapActivity) {
CallbackWithObject<GPXFile[]> callbackWithObject = new CallbackWithObject<GPXFile[]>() {
@Override
@ -984,81 +1013,84 @@ public class MeasurementToolFragment extends Fragment {
saveExistingGpx(gpx, showOnMap, lineType);
}
private void saveAsGpxOnClick(MapActivity mapActivity) {
final File dir = mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR);
final LayoutInflater inflater = mapActivity.getLayoutInflater();
final View view = inflater.inflate(R.layout.save_gpx_dialog, null);
final EditText nameEt = (EditText) view.findViewById(R.id.gpx_name_et);
final TextView fileExistsTv = (TextView) view.findViewById(R.id.file_exists_text_view);
final SwitchCompat showOnMapToggle = (SwitchCompat) view.findViewById(R.id.toggle_show_on_map);
showOnMapToggle.setChecked(true);
final String suggestedName = new SimpleDateFormat("yyyy-M-dd_HH-mm_EEE", Locale.US).format(new Date());
String displayedName = suggestedName;
File fout = new File(dir, suggestedName + GPX_SUFFIX);
int ind = 1;
while (fout.exists()) {
displayedName = suggestedName + "_" + (++ind);
fout = new File(dir, displayedName + GPX_SUFFIX);
}
nameEt.setText(displayedName);
nameEt.setSelection(displayedName.length());
final boolean[] textChanged = new boolean[1];
nameEt.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
private void saveAsGpx(final SaveType saveType) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
final File dir = mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR);
final LayoutInflater inflater = mapActivity.getLayoutInflater();
final View view = inflater.inflate(R.layout.save_gpx_dialog, null);
final EditText nameEt = (EditText) view.findViewById(R.id.gpx_name_et);
final TextView fileExistsTv = (TextView) view.findViewById(R.id.file_exists_text_view);
final SwitchCompat showOnMapToggle = (SwitchCompat) view.findViewById(R.id.toggle_show_on_map);
showOnMapToggle.setChecked(true);
final String suggestedName = new SimpleDateFormat("yyyy-M-dd_HH-mm_EEE", Locale.US).format(new Date());
String displayedName = suggestedName;
File fout = new File(dir, suggestedName + GPX_SUFFIX);
int ind = 1;
while (fout.exists()) {
displayedName = suggestedName + "_" + (++ind);
fout = new File(dir, displayedName + GPX_SUFFIX);
}
nameEt.setText(displayedName);
nameEt.setSelection(displayedName.length());
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
final boolean[] textChanged = new boolean[1];
nameEt.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
if (new File(dir, editable.toString() + GPX_SUFFIX).exists()) {
fileExistsTv.setVisibility(View.VISIBLE);
} else {
fileExistsTv.setVisibility(View.INVISIBLE);
}
textChanged[0] = true;
}
});
new AlertDialog.Builder(mapActivity)
.setTitle(R.string.enter_gpx_name)
.setView(view)
.setPositiveButton(R.string.shared_string_save, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final String name = nameEt.getText().toString();
String fileName = name + GPX_SUFFIX;
if (textChanged[0]) {
File fout = new File(dir, fileName);
int ind = 1;
while (fout.exists()) {
fileName = name + "_" + (++ind) + GPX_SUFFIX;
fout = new File(dir, fileName);
}
}
saveNewGpx(dir, fileName, showOnMapToggle.isChecked());
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
if (new File(dir, editable.toString() + GPX_SUFFIX).exists()) {
fileExistsTv.setVisibility(View.VISIBLE);
} else {
fileExistsTv.setVisibility(View.INVISIBLE);
}
})
.setNegativeButton(R.string.shared_string_cancel, null)
.show();
textChanged[0] = true;
}
});
new AlertDialog.Builder(mapActivity)
.setTitle(R.string.enter_gpx_name)
.setView(view)
.setPositiveButton(R.string.shared_string_save, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final String name = nameEt.getText().toString();
String fileName = name + GPX_SUFFIX;
if (textChanged[0]) {
File fout = new File(dir, fileName);
int ind = 1;
while (fout.exists()) {
fileName = name + "_" + (++ind) + GPX_SUFFIX;
fout = new File(dir, fileName);
}
}
saveNewGpx(dir, fileName, showOnMapToggle.isChecked(), saveType);
}
})
.setNegativeButton(R.string.shared_string_cancel, null)
.show();
}
}
private void saveNewGpx(File dir, String fileName, boolean checked) {
saveGpx(dir, fileName, checked, null, false, null);
private void saveNewGpx(File dir, String fileName, boolean checked, SaveType saveType) {
saveGpx(dir, fileName, checked, null, false, null, saveType);
}
private void saveExistingGpx(GPXFile gpx, boolean showOnMap, LineType lineType) {
saveGpx(null, null, showOnMap, gpx, true, lineType);
saveGpx(null, null, showOnMap, gpx, true, lineType, null);
}
private void saveGpx(final File dir, final String fileName, final boolean showOnMap, final GPXFile gpx, final boolean openTrackActivity, final LineType lineType) {
private void saveGpx(final File dir, final String fileName, final boolean showOnMap, final GPXFile gpx, final boolean openTrackActivity, final LineType lineType, final SaveType saveType) {
new AsyncTask<Void, Void, String>() {
private ProgressDialog progressDialog;
@ -1083,9 +1115,13 @@ public class MeasurementToolFragment extends Fragment {
GPXFile gpx = new GPXFile();
if (measurementLayer != null) {
List<WptPt> points = measurementLayer.getMeasurementPoints();
if (points.size() == 1) {
gpx.points.add(points.get(0));
} else if (points.size() > 1) {
if (saveType == SaveType.LINE) {
TrkSegment segment = new TrkSegment();
segment.points.addAll(points);
Track track = new Track();
track.segments.add(segment);
gpx.tracks.add(track);
} else if (saveType == SaveType.ROUTE_POINT) {
Route rt = new Route();
gpx.routes.add(rt);
rt.points.addAll(points);

View file

@ -0,0 +1,138 @@
package net.osmand.plus.measurementtool;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.base.BottomSheetDialogFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
public class SaveAsNewTrackBottomSheetDialogFragment extends BottomSheetDialogFragment {
public final static String TAG = "SaveAsNewTrackBottomSheetDialogFragment";
private SaveAsNewTrackFragmentListener listener;
private boolean nightMode;
private boolean portrait;
public void setListener(SaveAsNewTrackFragmentListener listener) {
this.listener = listener;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
nightMode = getMyApplication().getDaynightHelper().isNightModeForMapControls();
portrait = AndroidUiHelper.isOrientationPortrait(getActivity());
final OsmandSettings settings = getMyApplication().getSettings();
final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
final View mainView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.fragment_save_as_new_track_bottom_sheet_dialog, container);
if (portrait) {
AndroidUtils.setBackground(getActivity(), mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark);
}
if (nightMode) {
((TextView) mainView.findViewById(R.id.save_as_new_track_title)).setTextColor(getResources().getColor(R.color.ctx_menu_info_text_dark));
}
((ImageView) mainView.findViewById(R.id.route_point_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_route_points));
((ImageView) mainView.findViewById(R.id.line_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_split_interval));
mainView.findViewById(R.id.save_as_line_row).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.saveAsLineOnClick();
}
dismiss();
}
});
mainView.findViewById(R.id.save_as_route_point_row).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.saveAsRoutePointOnClick();
}
dismiss();
}
});
mainView.findViewById(R.id.cancel_row).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
}
});
final int screenHeight = AndroidUtils.getScreenHeight(getActivity());
final int statusBarHeight = AndroidUtils.getStatusBarHeight(getActivity());
final int navBarHeight = AndroidUtils.getNavBarHeight(getActivity());
mainView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
final View scrollView = mainView.findViewById(R.id.save_as_new_track_scroll_view);
int scrollViewHeight = scrollView.getHeight();
int dividerHeight = AndroidUtils.dpToPx(getContext(), 1);
int cancelButtonHeight = getContext().getResources().getDimensionPixelSize(R.dimen.measure_distance_bottom_sheet_cancel_button_height);
int spaceForScrollView = screenHeight - statusBarHeight - navBarHeight - dividerHeight - cancelButtonHeight;
if (scrollViewHeight > spaceForScrollView) {
scrollView.getLayoutParams().height = spaceForScrollView;
scrollView.requestLayout();
}
if (!portrait) {
if (screenHeight - statusBarHeight - mainView.getHeight()
>= AndroidUtils.dpToPx(getActivity(), 8)) {
AndroidUtils.setBackground(getActivity(), mainView, nightMode,
R.drawable.bg_bottom_sheet_topsides_landscape_light, R.drawable.bg_bottom_sheet_topsides_landscape_dark);
} else {
AndroidUtils.setBackground(getActivity(), mainView, nightMode,
R.drawable.bg_bottom_sheet_sides_landscape_light, R.drawable.bg_bottom_sheet_sides_landscape_dark);
}
}
ViewTreeObserver obs = mainView.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
}
});
return mainView;
}
@Override
public void onStart() {
super.onStart();
if (!portrait) {
final Window window = getDialog().getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.width = getActivity().getResources().getDimensionPixelSize(R.dimen.landscape_bottom_sheet_dialog_fragment_width);
window.setAttributes(params);
}
}
interface SaveAsNewTrackFragmentListener {
void saveAsRoutePointOnClick();
void saveAsLineOnClick();
}
}

View file

@ -48,6 +48,9 @@ public class SnapToRoadBottomSheetDialogFragment extends BottomSheetDialogFragme
final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
final View mainView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.fragment_snap_to_road_bottom_sheet_dialog, container);
if (portrait) {
AndroidUtils.setBackground(getActivity(), mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark);
}
mainView.findViewById(R.id.cancel_row).setOnClickListener(new View.OnClickListener() {
@Override