diff --git a/OsmAnd/res/layout/gpx_item_altitude.xml b/OsmAnd/res/layout/gpx_item_altitude.xml index 342b69eef7..ed7f0eda6b 100644 --- a/OsmAnd/res/layout/gpx_item_altitude.xml +++ b/OsmAnd/res/layout/gpx_item_altitude.xml @@ -262,15 +262,31 @@ android:layout_width="match_parent" android:layout_height="48dp" android:orientation="horizontal" - android:background="?attr/selectableItemBackground" - android:paddingLeft="16dp" - android:paddingRight="16dp" android:gravity="center"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/gpx_split_segments_header.xml b/OsmAnd/res/layout/gpx_split_segments_header.xml new file mode 100644 index 0000000000..541877ace4 --- /dev/null +++ b/OsmAnd/res/layout/gpx_split_segments_header.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/tab_content.xml b/OsmAnd/res/layout/tab_content.xml index fc04add0c3..6270364930 100644 --- a/OsmAnd/res/layout/tab_content.xml +++ b/OsmAnd/res/layout/tab_content.xml @@ -3,7 +3,8 @@ android:layout_width="fill_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" - android:orientation="vertical"> + android:orientation="vertical" + android:id="@+id/track_activity_layout"> #2f7af5 #ff8800 + #2f7af5 + #ff8800 + #78909c @@ -249,4 +252,6 @@ #b20000 #197d2a + #b3b3b3 + \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 30e81bc244..64f7c47524 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -1009,6 +1009,12 @@ h Duration Distance + Average + %1$d of %2$d + Ascent/Descent + Moving time + Max/Min + Range Tours All Waypoints diff --git a/OsmAnd/src/net/osmand/plus/GPXDatabase.java b/OsmAnd/src/net/osmand/plus/GPXDatabase.java index f6c11bdfcc..62b8eae644 100644 --- a/OsmAnd/src/net/osmand/plus/GPXDatabase.java +++ b/OsmAnd/src/net/osmand/plus/GPXDatabase.java @@ -266,6 +266,7 @@ public class GPXDatabase { a.avgElevation = avgElevation; a.minElevation = minElevation; a.maxElevation = maxElevation; + a.minSpeed = maxSpeed; a.maxSpeed = maxSpeed; a.avgSpeed = avgSpeed; a.points = points; diff --git a/OsmAnd/src/net/osmand/plus/GPXUtilities.java b/OsmAnd/src/net/osmand/plus/GPXUtilities.java index 9ee25ad62e..d789d357e1 100644 --- a/OsmAnd/src/net/osmand/plus/GPXUtilities.java +++ b/OsmAnd/src/net/osmand/plus/GPXUtilities.java @@ -275,6 +275,7 @@ public class GPXUtilities { public double minElevation = 99999; public double maxElevation = -100; + public float minSpeed; public float maxSpeed = 0; public float avgSpeed; @@ -520,6 +521,7 @@ public class GPXUtilities { if (speed > 0) { totalSpeedSum += speed; + minSpeed = Math.min(speed, minSpeed); maxSpeed = Math.max(speed, maxSpeed); speedCount++; } diff --git a/OsmAnd/src/net/osmand/plus/activities/TrackActivity.java b/OsmAnd/src/net/osmand/plus/activities/TrackActivity.java index e5edbf2c03..86cbbc353e 100644 --- a/OsmAnd/src/net/osmand/plus/activities/TrackActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/TrackActivity.java @@ -4,6 +4,7 @@ import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; @@ -22,6 +23,7 @@ import net.osmand.plus.OsmAndAppCustomization; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.myplaces.FavoritesActivity; +import net.osmand.plus.myplaces.SplitSegmentFragment; import net.osmand.plus.myplaces.TrackPointFragment; import net.osmand.plus.myplaces.TrackSegmentFragment; import net.osmand.plus.views.controls.PagerSlidingTabStrip; @@ -124,6 +126,8 @@ public class TrackActivity extends TabActivity { Fragment frag = f.get(); if (frag instanceof TrackSegmentFragment) { ((TrackSegmentFragment) frag).updateContent(); + } else if (frag instanceof SplitSegmentFragment) { + ((SplitSegmentFragment) frag).reloadSplitFragment(); } else if (frag instanceof TrackPointFragment) { ((TrackPointFragment) frag).setContent(); } @@ -220,6 +224,20 @@ public class TrackActivity extends TabActivity { int itemId = item.getItemId(); switch (itemId) { case android.R.id.home: + int backStackEntriesCount = getSupportFragmentManager().getBackStackEntryCount(); + if (backStackEntriesCount > 0) { + FragmentManager.BackStackEntry backStackEntry = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1); + if (backStackEntry.getName().equals(SplitSegmentFragment.TAG)) { + for (WeakReference f : fragList) { + Fragment frag = f.get(); + if (frag instanceof TrackSegmentFragment) { + ((TrackSegmentFragment) frag).updateSplitView(); + } + } + getSupportFragmentManager().popBackStack(); + return true; + } + } if (getIntent().hasExtra(MapActivity.INTENT_KEY_PARENT_MAP_ACTIVITY)) { OsmAndAppCustomization appCustomization = getMyApplication().getAppCustomization(); final Intent favorites = new Intent(this, appCustomization.getFavoritesActivity()); @@ -234,6 +252,25 @@ public class TrackActivity extends TabActivity { return false; } + @Override + public void onBackPressed() { + int backStackEntriesCount = getSupportFragmentManager().getBackStackEntryCount(); + if (backStackEntriesCount > 0) { + FragmentManager.BackStackEntry backStackEntry = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1); + if (backStackEntry.getName().equals(SplitSegmentFragment.TAG)) { + for (WeakReference f : fragList) { + Fragment frag = f.get(); + if (frag instanceof TrackSegmentFragment) { + ((TrackSegmentFragment) frag).updateSplitView(); + } + } + getSupportFragmentManager().popBackStack(); + return; + } + } + super.onBackPressed(); + } + boolean isHavingWayPoints(){ return getGpx() != null && getGpx().hasWptPt(); } diff --git a/OsmAnd/src/net/osmand/plus/myplaces/SplitSegmentFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/SplitSegmentFragment.java new file mode 100644 index 0000000000..2526055e01 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/myplaces/SplitSegmentFragment.java @@ -0,0 +1,605 @@ +package net.osmand.plus.myplaces; + +import android.content.res.ColorStateList; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.ListPopupWindow; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; + +import net.osmand.AndroidUtils; +import net.osmand.plus.GPXUtilities; +import net.osmand.plus.GPXUtilities.GPXTrackAnalysis; +import net.osmand.plus.GpxSelectionHelper; +import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; +import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; +import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; +import net.osmand.plus.IconsCache; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.TrackActivity; +import net.osmand.plus.base.OsmAndListFragment; +import net.osmand.util.Algorithms; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +import gnu.trove.list.array.TIntArrayList; + +import static net.osmand.plus.myplaces.TrackSegmentFragment.ARG_TO_FILTER_SHORT_TRACKS; + +public class SplitSegmentFragment extends OsmAndListFragment { + + public final static String TAG = "SPLIT_SEGMENT_FRAGMENT"; + private OsmandApplication app; + + private SplitSegmentsAdapter adapter; + private View headerView; + + private GpxDisplayItemType[] filterTypes = { GpxDisplayItemType.TRACK_SEGMENT }; + private List options = new ArrayList<>(); + private List distanceSplit = new ArrayList<>(); + private TIntArrayList timeSplit = new TIntArrayList(); + private int selectedSplitInterval; + private IconsCache ic; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + app = getMyApplication(); + ic = app.getIconsCache(); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getListView().setBackgroundColor(getResources().getColor( + getMyApplication().getSettings().isLightContent() ? R.color.ctx_menu_info_view_bg_light + : R.color.ctx_menu_info_view_bg_dark)); + getMyActivity().onAttachFragment(this); + } + + @Override + public ArrayAdapter getAdapter() { + return adapter; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + setHasOptionsMenu(true); + View view = getActivity().getLayoutInflater().inflate(R.layout.update_index, container, false); + view.findViewById(R.id.header_layout).setVisibility(View.GONE); + + ListView listView = (ListView) view.findViewById(android.R.id.list); + listView.setDivider(null); + listView.setDividerHeight(0); + + adapter = new SplitSegmentsAdapter(new ArrayList()); + headerView = getActivity().getLayoutInflater().inflate(R.layout.gpx_split_segments_header, null, false); + ((ImageView) headerView.findViewById(R.id.header_split_image)).setImageDrawable(ic.getIcon(R.drawable.ic_action_split_interval, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + + listView.addHeaderView(headerView); + listView.addFooterView(getActivity().getLayoutInflater().inflate(R.layout.list_shadow_footer, null, false)); + updateHeader(); + + setListAdapter(adapter); + return view; + } + + private void updateHeader() { + final View splitIntervalView = headerView.findViewById(R.id.split_interval_view); + + if (getGpx() != null && !getGpx().showCurrentTrack && adapter.getCount() > 0) { + setupSplitIntervalView(splitIntervalView); + if (options.size() == 0) { + prepareSplitIntervalAdapterData(); + } + updateSplitIntervalView(splitIntervalView); + splitIntervalView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final ListPopupWindow popup = new ListPopupWindow(getActivity()); + popup.setAnchorView(splitIntervalView); + popup.setContentWidth(AndroidUtils.dpToPx(app, 200f)); + popup.setModal(true); + popup.setDropDownGravity(Gravity.RIGHT | Gravity.TOP); + popup.setVerticalOffset(AndroidUtils.dpToPx(app, -48f)); + popup.setHorizontalOffset(AndroidUtils.dpToPx(app, -6f)); + popup.setAdapter(new ArrayAdapter<>(getMyActivity(), + R.layout.popup_list_text_item, options)); + popup.setOnItemClickListener(new AdapterView.OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + selectedSplitInterval = position; + GpxSelectionHelper.SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(getGpx(), true, false); + final List groups = getDisplayGroups(); + if (groups.size() > 0) { + updateSplit(groups, sf); + } + popup.dismiss(); + updateSplitIntervalView(splitIntervalView); + } + }); + popup.show(); + } + }); + splitIntervalView.setVisibility(View.VISIBLE); + } else { + splitIntervalView.setVisibility(View.GONE); + } + } + + @Override + public void onResume() { + super.onResume(); + updateContent(); + } + + public void updateContent() { + adapter.clear(); + adapter.setNotifyOnChange(false); + GpxDisplayItem overviewSegments = getOverviewSegment(); + adapter.add(overviewSegments); + List splitSegments = getSplitSegments(); + adapter.addAll(splitSegments); + adapter.setNotifyOnChange(true); + adapter.notifyDataSetChanged(); + updateHeader(); + } + + private void updateSplit(List groups, GpxSelectionHelper.SelectedGpxFile sf) { + new SplitTrackAsyncTask(sf, groups).execute((Void) null); + } + + private void setupSplitIntervalView(View view) { + final TextView title = (TextView) view.findViewById(R.id.split_interval_title); + final TextView text = (TextView) view.findViewById(R.id.split_interval_text); + final ImageView img = (ImageView) view.findViewById(R.id.split_interval_arrow); + int colorId; + final List groups = getDisplayGroups(); + if (groups.size() > 0) { + colorId = app.getSettings().isLightContent() ? + R.color.primary_text_light : R.color.primary_text_dark; + } else { + colorId = app.getSettings().isLightContent() ? + R.color.secondary_text_light : R.color.secondary_text_dark; + } + int color = app.getResources().getColor(colorId); + title.setTextColor(color); + text.setTextColor(color); + img.setImageDrawable(app.getIconsCache().getIcon(R.drawable.ic_action_arrow_drop_down, colorId)); + } + + private void updateSplitIntervalView(View view) { + final TextView text = (TextView) view.findViewById(R.id.split_interval_text); + if (selectedSplitInterval == 0) { + text.setText(getString(R.string.shared_string_none)); + } else { + text.setText(options.get(selectedSplitInterval)); + } + } + + private GPXUtilities.GPXFile getGpx() { + return getMyActivity().getGpx(); + } + + public TrackActivity getMyActivity() { + return (TrackActivity) getActivity(); + } + + private void prepareSplitIntervalAdapterData() { + final List groups = getDisplayGroups(); + + options.add(app.getString(R.string.shared_string_none)); + distanceSplit.add(-1d); + timeSplit.add(-1); + addOptionSplit(30, true, groups); // 50 feet, 20 yards, 20 + // m + addOptionSplit(60, true, groups); // 100 feet, 50 yards, + // 50 m + addOptionSplit(150, true, groups); // 200 feet, 100 yards, + // 100 m + addOptionSplit(300, true, groups); // 500 feet, 200 yards, + // 200 m + addOptionSplit(600, true, groups); // 1000 feet, 500 yards, + // 500 m + addOptionSplit(1500, true, groups); // 2000 feet, 1000 yards, 1 km + addOptionSplit(3000, true, groups); // 1 mi, 2 km + addOptionSplit(6000, true, groups); // 2 mi, 5 km + addOptionSplit(15000, true, groups); // 5 mi, 10 km + + addOptionSplit(15, false, groups); + addOptionSplit(30, false, groups); + addOptionSplit(60, false, groups); + addOptionSplit(120, false, groups); + addOptionSplit(150, false, groups); + addOptionSplit(300, false, groups); + addOptionSplit(600, false, groups); + addOptionSplit(900, false, groups); + addOptionSplit(1800, false, groups); + addOptionSplit(3600, false, groups); + } + + private List getDisplayGroups() { + return filterGroups(true); + } + + private void addOptionSplit(int value, boolean distance, List model) { + if (distance) { + double dvalue = OsmAndFormatter.calculateRoundedDist(value, app); + options.add(OsmAndFormatter.getFormattedDistance((float) dvalue, app)); + distanceSplit.add(dvalue); + timeSplit.add(-1); + if (Math.abs(model.get(0).getSplitDistance() - dvalue) < 1) { + selectedSplitInterval = distanceSplit.size() - 1; + } + } else { + if (value < 60) { + options.add(value + " " + app.getString(R.string.int_seconds)); + } else if (value % 60 == 0) { + options.add((value / 60) + " " + app.getString(R.string.int_min)); + } else { + options.add((value / 60f) + " " + app.getString(R.string.int_min)); + } + distanceSplit.add(-1d); + timeSplit.add(value); + if (model.get(0).getSplitTime() == value) { + selectedSplitInterval = distanceSplit.size() - 1; + } + } + } + + private List filterGroups(boolean useDisplayGroups) { + List result = getMyActivity().getGpxFile(useDisplayGroups); + List groups = new ArrayList<>(); + for (GpxDisplayGroup group : result) { + boolean add = hasFilterType(group.getType()); + if (isArgumentTrue(ARG_TO_FILTER_SHORT_TRACKS)) { + Iterator item = group.getModifiableList().iterator(); + while (item.hasNext()) { + GpxDisplayItem it2 = item.next(); + if (it2.analysis != null && it2.analysis.totalDistance < 100) { + item.remove(); + } + } + if (group.getModifiableList().isEmpty()) { + add = false; + } + } + if (add) { + groups.add(group); + } + + } + return groups; + } + + private List getSplitSegments() { + List result = getMyActivity().getGpxFile(true); + List splitSegments = new ArrayList<>(); + if (result != null && result.size() > 0) { + if (result.get(0).isSplitDistance() || result.get(0).isSplitTime()) { + splitSegments.addAll(result.get(0).getModifiableList()); + } + } + return splitSegments; + } + + private GpxDisplayItem getOverviewSegment() { + List result = getMyActivity().getGpxFile(false); + GpxDisplayItem overviewSegment = null; + if (result.size() > 0) { + overviewSegment = result.get(0).getModifiableList().get(0); + } + return overviewSegment; + } + + private boolean isArgumentTrue(@NonNull String arg) { + return getArguments() != null && getArguments().getBoolean(arg); + } + + protected boolean hasFilterType(GpxDisplayItemType filterType) { + for (GpxDisplayItemType type : filterTypes) { + if (type == filterType) { + return true; + } + } + return false; + } + + public void reloadSplitFragment() { + getFragmentManager() + .beginTransaction() + .detach(this) + .attach(this) + .commit(); + } + + private class SplitSegmentsAdapter extends ArrayAdapter { + + SplitSegmentsAdapter(List items) { + super(getActivity(), 0, items); + } + + ColorStateList defaultTextColor; + + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { + GpxDisplayItem currentGpxDisplayItem = getItem(position); + if (convertView == null) { + convertView = getMyActivity().getLayoutInflater().inflate(R.layout.gpx_split_segment_fragment, parent, false); + } + TextView overviewTextView = (TextView) convertView.findViewById(R.id.overview_text); + ImageView overviewImageView = (ImageView) convertView.findViewById(R.id.overview_image); + if (position == 0) { + overviewImageView.setImageDrawable(ic.getIcon(R.drawable.ic_action_time_span_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + if (defaultTextColor == null) { + defaultTextColor = overviewTextView.getTextColors(); + } + overviewTextView.setTextColor(defaultTextColor); + overviewTextView.setText(app.getString(R.string.shared_string_overview)); + ((TextView) convertView.findViewById(R.id.fragment_count_text)).setText(""); + } else { + if (currentGpxDisplayItem != null && currentGpxDisplayItem.analysis != null) { + overviewTextView.setTextColor(app.getSettings().isLightContent() ? app.getResources().getColor(R.color.gpx_split_overview_light) : app.getResources().getColor(R.color.gpx_split_overview_dark)); + if (currentGpxDisplayItem.group.isSplitDistance()) { + overviewImageView.setImageDrawable(ic.getIcon(R.drawable.ic_action_track_16, app.getSettings().isLightContent() ? R.color.gpx_split_overview_light : R.color.gpx_split_overview_dark)); + overviewTextView.setText(""); + double metricStart = currentGpxDisplayItem.analysis.metricEnd - currentGpxDisplayItem.analysis.totalDistance; + overviewTextView.append(OsmAndFormatter.getFormattedDistance((float) metricStart, app)); + overviewTextView.append(" - "); + overviewTextView.append(OsmAndFormatter.getFormattedDistance((float) currentGpxDisplayItem.analysis.metricEnd, app)); + } else if (currentGpxDisplayItem.group.isSplitTime()) { + overviewImageView.setImageDrawable(ic.getIcon(R.drawable.ic_action_time_span_16, app.getSettings().isLightContent() ? R.color.gpx_split_overview_light : R.color.gpx_split_overview_dark)); + overviewTextView.setText(""); + double metricStart = currentGpxDisplayItem.analysis.metricEnd - (currentGpxDisplayItem.analysis.timeSpan / 1000); + overviewTextView.append(OsmAndFormatter.getFormattedDuration((int) metricStart, app)); + overviewTextView.append(" - "); + overviewTextView.append(OsmAndFormatter.getFormattedDuration((int) currentGpxDisplayItem.analysis.metricEnd, app)); + } + ((TextView) convertView.findViewById(R.id.fragment_count_text)).setText(app.getString(R.string.of, position, adapter.getCount() - 1)); + } + } + + ImageView distanceOrTimeSpanImageView = ((ImageView) convertView.findViewById(R.id.distance_or_timespan_image)); + if (position == 0) { + distanceOrTimeSpanImageView.setImageDrawable(ic.getIcon(R.drawable.ic_action_track_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + } else { + distanceOrTimeSpanImageView.setImageDrawable(ic.getIcon(R.drawable.ic_action_time_span_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + } + ((ImageView) convertView.findViewById(R.id.start_time_image)) + .setImageDrawable(ic.getIcon(R.drawable.ic_action_time_start_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + ((ImageView) convertView.findViewById(R.id.end_time_image)) + .setImageDrawable(ic.getIcon(R.drawable.ic_action_time_end_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + ((ImageView) convertView.findViewById(R.id.average_altitude_image)) + .setImageDrawable(ic.getIcon(R.drawable.ic_action_altitude_average_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + ((ImageView) convertView.findViewById(R.id.altitude_range_image)) + .setImageDrawable(ic.getIcon(R.drawable.ic_action_altitude_range_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + ((ImageView) convertView.findViewById(R.id.ascent_descent_image)) + .setImageDrawable(ic.getIcon(R.drawable.ic_action_altitude_descent_ascent_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + ((ImageView) convertView.findViewById(R.id.moving_time_image)) + .setImageDrawable(ic.getIcon(R.drawable.ic_action_time_moving_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + ((ImageView) convertView.findViewById(R.id.average_speed_image)) + .setImageDrawable(ic.getIcon(R.drawable.ic_action_speed_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + ((ImageView) convertView.findViewById(R.id.max_speed_image)) + .setImageDrawable(ic.getIcon(R.drawable.ic_action_max_speed_16, app.getSettings().isLightContent() ? R.color.gpx_split_segment_icon_color : 0)); + + if (currentGpxDisplayItem != null) { + GPXTrackAnalysis analysis = currentGpxDisplayItem.analysis; + if (analysis != null) { + TextView distanceOrTimeSpanValue = (TextView) convertView.findViewById(R.id.distance_or_time_span_value); + TextView distanceOrTimeSpanText = (TextView) convertView.findViewById(R.id.distance_or_time_span_text); + if (position == 0) { + distanceOrTimeSpanValue.setText(OsmAndFormatter.getFormattedDistance(analysis.totalDistance, app)); + distanceOrTimeSpanText.setText(app.getString(R.string.distance)); + } else { + if (analysis.timeSpan > 0) { + distanceOrTimeSpanValue.setText(OsmAndFormatter.getFormattedDuration((int) (analysis.timeSpan / 1000), app)); + } else { + distanceOrTimeSpanValue.setText("-"); + } + distanceOrTimeSpanText.setText(app.getString(R.string.shared_string_time_span)); + } + + TextView startTimeValue = (TextView) convertView.findViewById(R.id.start_time_value); + TextView startDateValue = (TextView) convertView.findViewById(R.id.start_date_value); + TextView endTimeValue = (TextView) convertView.findViewById(R.id.end_time_value); + TextView endDateValue = (TextView) convertView.findViewById(R.id.end_date_value); + if (analysis.timeSpan > 0) { + DateFormat tf = SimpleDateFormat.getTimeInstance(DateFormat.SHORT); + DateFormat df = SimpleDateFormat.getDateInstance(DateFormat.MEDIUM); + + Date start = new Date(analysis.startTime); + startTimeValue.setText(tf.format(start)); + startDateValue.setText(df.format(start)); + + Date end = new Date(analysis.endTime); + endTimeValue.setText(tf.format(end)); + endDateValue.setText(df.format(end)); + } else { + startTimeValue.setText("-"); + startDateValue.setText("-"); + endTimeValue.setText("-"); + endDateValue.setText("-"); + } + + View elevationDivider = convertView.findViewById(R.id.elevation_divider); + View elevationSection = convertView.findViewById(R.id.elevation_layout); + if (analysis.hasElevationData) { + elevationDivider.setVisibility(View.VISIBLE); + elevationSection.setVisibility(View.VISIBLE); + + ((TextView) convertView.findViewById(R.id.average_altitude_value)) + .setText(OsmAndFormatter.getFormattedAlt(analysis.avgElevation, app)); + + String min = OsmAndFormatter.getFormattedAlt(analysis.minElevation, app); + String max = OsmAndFormatter.getFormattedAlt(analysis.maxElevation, app); + String min_max_elevation = min.substring(0, min.indexOf(" ")).concat("/").concat(max); + if (min_max_elevation.length() > 9) { + (convertView.findViewById(R.id.min_altitude_value)) + .setVisibility(View.VISIBLE); + (convertView.findViewById(R.id.max_altitude_value)) + .setVisibility(View.VISIBLE); + ((TextView) convertView.findViewById(R.id.min_altitude_value)) + .setText(min); + ((TextView) convertView.findViewById(R.id.max_altitude_value)) + .setText(max); + (convertView.findViewById(R.id.min_max_altitude_value)) + .setVisibility(View.GONE); + } else { + (convertView.findViewById(R.id.min_max_altitude_value)) + .setVisibility(View.VISIBLE); + ((TextView) convertView.findViewById(R.id.min_max_altitude_value)) + .setText(min_max_elevation); + (convertView.findViewById(R.id.min_altitude_value)) + .setVisibility(View.GONE); + (convertView.findViewById(R.id.max_altitude_value)) + .setVisibility(View.GONE); + } + + TextView ascentValue = (TextView) convertView.findViewById(R.id.ascent_value); + TextView descentValue = (TextView) convertView.findViewById(R.id.descent_value); + TextView ascentDescentValue = (TextView) convertView.findViewById(R.id.ascent_descent_value); + + String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app); + String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app); + String asc_desc = asc.substring(0, asc.indexOf(" ")).concat("/").concat(desc); + if (asc_desc.length() > 9) { + ascentValue.setVisibility(View.VISIBLE); + descentValue.setVisibility(View.VISIBLE); + ascentValue.setText(asc); + descentValue.setText(desc); + ascentDescentValue.setVisibility(View.GONE); + } else { + ascentDescentValue.setVisibility(View.VISIBLE); + ascentDescentValue.setText(asc_desc); + ascentValue.setVisibility(View.GONE); + descentValue.setVisibility(View.GONE); + } + + } else { + elevationDivider.setVisibility(View.GONE); + elevationSection.setVisibility(View.GONE); + } + + View speedDivider = convertView.findViewById(R.id.speed_divider); + View speedSection = convertView.findViewById(R.id.speed_layout); + if (analysis.hasSpeedData) { + speedDivider.setVisibility(View.VISIBLE); + speedSection.setVisibility(View.VISIBLE); + + ((TextView) convertView.findViewById(R.id.moving_time_value)) + .setText(Algorithms.formatDuration((int) (analysis.timeMoving / 1000), app.accessibilityEnabled())); + ((TextView) convertView.findViewById(R.id.average_speed_value)) + .setText(OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app)); + + String maxSpeed = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app); + String minSpeed = OsmAndFormatter.getFormattedSpeed(analysis.minSpeed, app); + String max_min_speed = maxSpeed.substring(0, maxSpeed.indexOf(" ")).concat("/").concat(minSpeed.substring(0, minSpeed.indexOf(" "))); + if (minSpeed.substring(0, minSpeed.indexOf(" ")).equals("0") || minSpeed.substring(0, minSpeed.indexOf(" ")).equals("0.0")) { + (convertView.findViewById(R.id.max_speed_value)) + .setVisibility(View.VISIBLE); + (convertView.findViewById(R.id.min_speed_value)) + .setVisibility(View.GONE); + ((TextView) convertView.findViewById(R.id.max_speed_value)) + .setText(maxSpeed); + (convertView.findViewById(R.id.max_min_speed_value)) + .setVisibility(View.GONE); + ((TextView) convertView.findViewById(R.id.max_min_speed_text)) + .setText(app.getString(R.string.shared_string_max)); + } else if (max_min_speed.length() > 9) { + (convertView.findViewById(R.id.max_speed_value)) + .setVisibility(View.VISIBLE); + (convertView.findViewById(R.id.min_speed_value)) + .setVisibility(View.VISIBLE); + ((TextView) convertView.findViewById(R.id.max_speed_value)) + .setText(maxSpeed); + ((TextView) convertView.findViewById(R.id.min_speed_value)) + .setText(minSpeed); + (convertView.findViewById(R.id.max_min_speed_value)) + .setVisibility(View.GONE); + ((TextView) convertView.findViewById(R.id.max_min_speed_text)) + .setText(app.getString(R.string.max_min)); + } else { + (convertView.findViewById(R.id.max_min_speed_value)) + .setVisibility(View.VISIBLE); + ((TextView) convertView.findViewById(R.id.max_min_speed_value)) + .setText(max_min_speed); + (convertView.findViewById(R.id.max_speed_value)) + .setVisibility(View.GONE); + (convertView.findViewById(R.id.min_speed_value)) + .setVisibility(View.GONE); + ((TextView) convertView.findViewById(R.id.max_min_speed_text)) + .setText(app.getString(R.string.max_min)); + } + } else { + speedDivider.setVisibility(View.GONE); + speedSection.setVisibility(View.GONE); + } + } + } + return convertView; + } + } + + private class SplitTrackAsyncTask extends AsyncTask { + @Nullable + private final GpxSelectionHelper.SelectedGpxFile mSelectedGpxFile; + @NonNull private final TrackActivity mActivity; + + private final List groups; + + SplitTrackAsyncTask(@Nullable GpxSelectionHelper.SelectedGpxFile selectedGpxFile, List groups) { + mSelectedGpxFile = selectedGpxFile; + mActivity = getMyActivity(); + this.groups = groups; + } + + protected void onPostExecute(Void result) { + if (mSelectedGpxFile != null) { + mSelectedGpxFile.setDisplayGroups(getDisplayGroups()); + } + if (!mActivity.isFinishing()) { + mActivity.setProgressBarIndeterminateVisibility(false); + } + updateContent(); + } + + protected void onPreExecute() { + mActivity.setProgressBarIndeterminateVisibility(true); + } + + @Override + protected Void doInBackground(Void... params) { + for (GpxDisplayGroup model : groups) { + OsmandApplication application = mActivity.getMyApplication(); + if (selectedSplitInterval == 0) { + model.noSplit(application); + } else if (distanceSplit.get(selectedSplitInterval) > 0) { + model.splitByDistance(application, distanceSplit.get(selectedSplitInterval)); + } else if (timeSplit.get(selectedSplitInterval) > 0) { + model.splitByTime(application, timeSplit.get(selectedSplitInterval)); + } + } + + return null; + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java index 2f98dbec89..0ddbe9373f 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java @@ -134,6 +134,7 @@ public class TrackSegmentFragment extends OsmAndListFragment { private Paint paintIcon; private Bitmap pointSmall; private GpxDisplayItem generalDisplayItem; + private View splitIntervalView; private ImageView imageView; private RotatedTileBox rotatedTileBox; @@ -293,7 +294,7 @@ public class TrackSegmentFragment extends OsmAndListFragment { }); final View splitColorView = headerView.findViewById(R.id.split_color_view); final View divider = headerView.findViewById(R.id.divider); - final View splitIntervalView = headerView.findViewById(R.id.split_interval_view); + splitIntervalView = headerView.findViewById(R.id.split_interval_view); final View colorView = headerView.findViewById(R.id.color_view); final SwitchCompat vis = (SwitchCompat) headerView.findViewById(R.id.showOnMapToggle); final ProgressBar progressBar = (ProgressBar) headerView.findViewById(R.id.mapLoadProgress); @@ -466,6 +467,11 @@ public class TrackSegmentFragment extends OsmAndListFragment { } } + public void updateSplitView() { + prepareSplitIntervalAdapterData(); + updateSplitIntervalView(splitIntervalView); + } + private void refreshTrackBitmap() { currentTrackColor = app.getSettings().CURRENT_TRACK_COLOR.get(); if (mapBitmap != null) { @@ -1177,12 +1183,22 @@ public class TrackSegmentFragment extends OsmAndListFragment { view.findViewById(R.id.list_divider).setVisibility(View.GONE); view.findViewById(R.id.start_end_time).setVisibility(View.GONE); } - view.findViewById(R.id.details_view).setOnClickListener(new View.OnClickListener() { + view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - openDetails(GPXTabItemType.GPX_TAB_ITEM_GENERAL); + openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_GENERAL); } }); + if (getGpx().showCurrentTrack) { + view.findViewById(R.id.split_interval).setVisibility(View.GONE); + } else { + view.findViewById(R.id.split_interval).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + openSplitIntervalScreen(); + } + }); + } break; case GPX_TAB_ITEM_ALTITUDE: @@ -1221,12 +1237,22 @@ public class TrackSegmentFragment extends OsmAndListFragment { view.findViewById(R.id.list_divider).setVisibility(View.GONE); view.findViewById(R.id.ascent_descent).setVisibility(View.GONE); } - view.findViewById(R.id.details_view).setOnClickListener(new View.OnClickListener() { + view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - openDetails(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE); + openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE); } }); + if (getGpx().showCurrentTrack) { + view.findViewById(R.id.split_interval).setVisibility(View.GONE); + } else { + view.findViewById(R.id.split_interval).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + openSplitIntervalScreen(); + } + }); + } break; case GPX_TAB_ITEM_SPEED: @@ -1264,12 +1290,22 @@ public class TrackSegmentFragment extends OsmAndListFragment { view.findViewById(R.id.list_divider).setVisibility(View.GONE); view.findViewById(R.id.time_distance).setVisibility(View.GONE); } - view.findViewById(R.id.details_view).setOnClickListener(new View.OnClickListener() { + view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - openDetails(GPXTabItemType.GPX_TAB_ITEM_SPEED); + openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_SPEED); } }); + if (getGpx().showCurrentTrack) { + view.findViewById(R.id.split_interval).setVisibility(View.GONE); + } else { + view.findViewById(R.id.split_interval).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + openSplitIntervalScreen(); + } + }); + } break; } } @@ -1372,7 +1408,7 @@ public class TrackSegmentFragment extends OsmAndListFragment { } } - void openDetails(GPXTabItemType tabType) { + void openAnalyzeOnMap(GPXTabItemType tabType) { LatLon location = null; WptPt wpt = null; gpxItem.chartTypes = null; @@ -1435,6 +1471,14 @@ public class TrackSegmentFragment extends OsmAndListFragment { } } + void openSplitIntervalScreen() { + getMyActivity().getSupportFragmentManager() + .beginTransaction() + .replace(R.id.track_activity_layout, new SplitSegmentFragment()) + .addToBackStack(SplitSegmentFragment.TAG) + .commit(); + } + private class SplitTrackAsyncTask extends AsyncTask { @Nullable private final SelectedGpxFile mSelectedGpxFile;