Merge branch 'feature_dots'

This commit is contained in:
unknown 2014-06-18 12:29:32 +03:00
commit 4e8c2e6476
5 changed files with 316 additions and 160 deletions

View file

@ -4,24 +4,36 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="6dip"
android:weightSum="6">
android:weightSum="1"
android:background="?android:attr/activatedBackgroundIndicator">
<ImageView android:id="@+id/point_icon"
android:layout_width="32dp"
android:padding="3dp"
android:layout_marginLeft="5dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/>
<TextView android:id="@+id/index"
android:layout_marginLeft="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:visibility="gone"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="5"/>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_marginLeft="6dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="10dp"
android:layout_weight="1"/>
<TextView
android:id="@+id/date_or_distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_gravity="center_vertical"/>
</LinearLayout>

View file

@ -9,24 +9,22 @@
<TextView android:id="@+id/gpx_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:layout_marginLeft="10dp"
android:textSize="20sp"/>
<TextView android:id="@+id/points_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:textSize="20sp"/>
<Button android:id="@+id/done"
android:layout_width="wrap_content"
android:layout_marginRight="6dp"
android:layout_height="wrap_content"
android:text="done"/>
</LinearLayout>
<ListView android:id="@+id/pointsListView"
<ListView android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
android:layout_height="fill_parent"
style="@style/OsmandListView"/>
</LinearLayout>

View file

@ -2,4 +2,8 @@
<resources>
<string name="route_points_no_gpx">No gpx</string>
<string name="mark_as_current">Mark as current</string>
<string name="marking_as_visited">Marking as visited…</string>
<string name="current_route">Current route:</string>
<string name="done">Done</string>
<string name="marking_as_unvisited">Marking as unvisited...</string>
</resources>

View file

@ -1,20 +1,26 @@
package net.osmand.plus.routepointsnavigation;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.*;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.*;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.*;
import net.osmand.CallbackWithObject;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.activities.OsmandExpandableListActivity;
import net.osmand.plus.*;
import net.osmand.plus.activities.OsmandListActivity;
import net.osmand.plus.helpers.GpxUiHelper;
import org.w3c.dom.Text;
import net.osmand.util.MapUtils;
import java.io.File;
import java.util.*;
@ -22,33 +28,25 @@ import java.util.*;
/**
* Created by Bars on 13.06.2014.
*/
public class RoutePointsActivity extends SherlockFragmentActivity {
public class RoutePointsActivity extends OsmandListActivity {
private static final String CURRENT_ROUTE_KEY = "CurrentRoute";
private File file;
private GPXUtilities.GPXFile gpx;
private RoutePointsPlugin plugin;
private OsmandApplication app;
private GPXUtilities.Route currentRoute;
private List<GPXUtilities.WptPt> pointsList;
private List<GPXUtilities.WptPt> sortedPointsList;
private List<Long> pointsStatus;
//saves indexed of sorted list
private List<Integer> pointsIndex;
//needed to save user selection
private List<Boolean> pointsChangedState;
private List<Boolean> pointsStartState;
private RoutePointsPlugin plugin;
private int selectedItemIndex;
private ListView listView;
private ActionMode actionMode;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -61,17 +59,6 @@ public class RoutePointsActivity extends SherlockFragmentActivity {
prepareView();
}
Button done = (Button) findViewById(R.id.done);
done.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
saveStatus();
GPXUtilities.WptPt point = plugin.getCurrentPoint();
app.getSettings().setMapLocationToShow(point.lat, point.lon, app.getSettings().getMapZoomToShow());
finish();
}
});
super.onCreate(savedInstanceState);
}
@ -104,68 +91,57 @@ public class RoutePointsActivity extends SherlockFragmentActivity {
private void prepareView() {
TextView gpxName = (TextView) findViewById(R.id.gpx_name);
String fileName = gpx.path.substring(gpx.path.lastIndexOf("/") + 1,gpx.path.lastIndexOf("."));
String fileName = getString(R.string.current_route) + " " + gpx.path.substring(gpx.path.lastIndexOf("/") + 1, gpx.path.lastIndexOf("."));
gpxName.setText(fileName);
TextView visited = (TextView) findViewById(R.id.points_count);
visited.setText(plugin.getVisitedAllString());
visited.setText("(" + plugin.getVisitedAllString() + ")");
loadCurrentRoute();
pointsList = currentRoute.points;
sortPoints();
pointsStatus = getAllPointsStatus();
pointsStartState = getPointsState();
pointsChangedState = new ArrayList<Boolean>(pointsStartState);
displayListView();
}
private void displayListView() {
ArrayList<PointItem> pointItemsList = new ArrayList<PointItem>();
for (int i = 0; i < pointsList.size(); i++) {
String pointName = pointsList.get(i).name;
for (int i = 0; i < sortedPointsList.size(); i++) {
String pointName = sortedPointsList.get(i).name;
if (pointsStatus.get(i) != 0) {
String dateString = DateFormat.format("MM/dd/yyyy hh:mm:ss", new Date(pointsStatus.get(i))).toString();
String dateString;
Date date = new Date(pointsStatus.get(i));
if (DateFormat.is24HourFormat(app)) {
dateString = DateFormat.format("MM/dd k:mm", date).toString();
} else {
dateString = DateFormat.format("MM/dd h:mm", date).toString() + DateFormat.format("aa", date).toString();
}
pointItemsList.add(new PointItem(true, pointName, dateString));
} else {
pointItemsList.add(new PointItem(false, pointName, ""));
if (i == 0) {
pointItemsList.add(new PointItem(false, pointName, ""));
continue;
}
GPXUtilities.WptPt first = sortedPointsList.get(i - 1);
GPXUtilities.WptPt second = sortedPointsList.get(i);
double d = MapUtils.getDistance(first.lat, first.lon, second.lat, second.lon);
String distance = OsmAndFormatter.getFormattedDistance((float) d, app);
pointItemsList.add(new PointItem(false, pointName, distance));
}
}
PointItemAdapter adapter = new PointItemAdapter(this, R.layout.route_point_info, pointItemsList);
listView = (ListView) findViewById(R.id.pointsListView);
ListView listView = getListView();
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
selectedItemIndex = i;
final PopupMenu popup = new PopupMenu(RoutePointsActivity.this, view);
final Menu menu = popup.getMenu();
menu.add(getString(R.string.mark_as_current));
menu.add(getString(R.string.mark_as_visited));
menu.add(getString(R.string.show_on_map));
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
if (menuItem.getTitle().equals(getResources().getString(R.string.mark_as_current))) {
plugin.setCurrentPoint(pointsList.get(selectedItemIndex));
} else if (menuItem.getTitle().equals(getResources().getString(R.string.show_on_map))) {
GPXUtilities.WptPt point = pointsList.get(selectedItemIndex);
app.getSettings().setMapLocationToShow(point.lat, point.lon, app.getSettings().getMapZoomToShow());
finish();
} else {
//inverts selection state of item
boolean state = pointsChangedState.get(selectedItemIndex);
pointsChangedState.set(selectedItemIndex,!state);
}
return true;
}
});
popup.show();
view.setSelected(true);
actionMode = getActivity().startActionMode(mActionModeCallback);
}
});
}
@ -181,83 +157,57 @@ public class RoutePointsActivity extends SherlockFragmentActivity {
for (GPXUtilities.Route route : gpx.routes) {
if (route.name.equals(routeName)) {
currentRoute = route;
return;
}
}
}
currentRoute = gpx.routes.get(0);
}
private List<Long> getAllPointsStatus() {
List<Long> pointsStatus = new ArrayList<Long>();
for (int i = 0; i < pointsList.size(); i++) {
for (int i = 0; i < sortedPointsList.size(); i++) {
pointsStatus.add(plugin.getPointStatus(pointsIndex.get(i)));
}
return pointsStatus;
}
private void saveStatus() {
for (int i = 0; i < pointsChangedState.size(); i++) {
boolean newValue = pointsChangedState.get(i);
//if values is the same - there's no need to save data
if (newValue != pointsStartState.get(i)) {
int indexToWrite = pointsIndex.get(i);
plugin.setPointStatus(indexToWrite, newValue);
}
}
saveGPXFile();
}
private void sortPoints() {
sortedPointsList = plugin.getPoints();
List<GPXUtilities.WptPt> listToSort = new ArrayList<GPXUtilities.WptPt>();
List<Integer> indexItemsAtTheEnd = new ArrayList<Integer>();
pointsIndex = new ArrayList<Integer>();
listToSort.add(plugin.getCurrentPoint());
int curPointInd = plugin.getCurrentPointIndex();
pointsIndex.add(curPointInd);
for (int i = 0; i < pointsList.size(); i++) {
for (int i = 0; i < sortedPointsList.size(); i++) {
if (i == curPointInd) {
continue;
}
long status = plugin.getPointStatus(i);
if (status == 0L) {
listToSort.add(pointsList.get(i));
listToSort.add(sortedPointsList.get(i));
pointsIndex.add(i);
} else {
indexItemsAtTheEnd.add(i);
}
}
List<Long> timeOfVisits = new ArrayList<Long>();
for(int i=0; i<indexItemsAtTheEnd.size();i++){
timeOfVisits.add(plugin.getPointStatus(indexItemsAtTheEnd.get(i)));
}
quickSort(timeOfVisits,indexItemsAtTheEnd,0, indexItemsAtTheEnd.size());
for (int i : indexItemsAtTheEnd) {
listToSort.add(pointsList.get(i));
listToSort.add(sortedPointsList.get(i));
pointsIndex.add(i);
}
pointsList = listToSort;
}
private void saveGPXFile() {
GPXUtilities.writeGpxFile(new File(gpx.path), gpx, app);
}
public List<Boolean> getPointsState() {
List<Boolean> status = new ArrayList<Boolean>();
for (int i = 0; i < pointsStatus.size(); i++) {
if (pointsStatus.get(i) == 0) {
status.add(false);
} else {
status.add(true);
}
}
return status;
}
private boolean[] toPrimitiveArray(final List<Boolean> booleanList) {
final boolean[] primitives = new boolean[booleanList.size()];
int index = 0;
for (Boolean object : booleanList) {
primitives[index++] = object;
}
return primitives;
sortedPointsList = listToSort;
pointsStatus = getAllPointsStatus();
}
private class PointItemAdapter extends ArrayAdapter<PointItem> {
@ -272,9 +222,10 @@ public class RoutePointsActivity extends SherlockFragmentActivity {
}
private class ViewHolder {
ImageView image;
TextView index;
TextView name;
TextView date;
TextView dateOrDistance;
}
@Override
@ -287,8 +238,9 @@ public class RoutePointsActivity extends SherlockFragmentActivity {
holder = new ViewHolder();
holder.index = (TextView) convertView.findViewById(R.id.index);
holder.date = (TextView) convertView.findViewById(R.id.date);
holder.dateOrDistance = (TextView) convertView.findViewById(R.id.date_or_distance);
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.image = (ImageView) convertView.findViewById(R.id.point_icon);
convertView.setTag(holder);
} else {
@ -297,20 +249,23 @@ public class RoutePointsActivity extends SherlockFragmentActivity {
PointItem point = pointsList.get(position);
holder.index.setText(String.valueOf(position));
String pointName = point.getName();
int pos = pointName.indexOf(":");
holder.name.setText(pointName.substring(0, pos));
holder.name.setText(point.getName());
holder.dateOrDistance.setText(String.valueOf(point.getTime()));
if (point.isSelected()) {
holder.image.setImageResource(R.drawable.ic_action_ok_dark);
holder.name.setTextColor(getResources().getColor(R.color.osmbug_closed));
holder.date.setText(String.valueOf(point.getTime()));
holder.dateOrDistance.setTextColor(getResources().getColor(R.color.color_unknown));
} else {
if (sortedPointsList.get(position).equals(plugin.getCurrentPoint())) {
holder.image.setImageResource(R.drawable.ic_action_signpost_dark);
} else {
holder.image.setImageResource(R.drawable.ic_action_marker_dark);
}
holder.name.setTextColor(getResources().getColor(R.color.color_update));
holder.date.setText("");
holder.dateOrDistance.setTextColor(getResources().getColor(R.color.osmbug_not_submitted));
}
return convertView;
}
}
//this class needed to represent route point in UI
@ -340,5 +295,158 @@ public class RoutePointsActivity extends SherlockFragmentActivity {
public void setSelected(boolean selected) {
this.visited = selected;
}
}
private void revertPointStatusAsync(final GPXUtilities.WptPt point) {
new AsyncTask<GPXUtilities.WptPt, Void, Void>() {
private ProgressDialog dlg;
protected void onPreExecute() {
dlg = new ProgressDialog(getActivity());
if (plugin.getPointStatus(point) == 0){
dlg.setTitle(R.string.marking_as_visited);
} else {
dlg.setTitle(getString(R.string.marking_as_unvisited));
}
dlg.setMessage(point.name);
dlg.show();
}
@Override
protected Void doInBackground(GPXUtilities.WptPt... params) {
long status = plugin.getPointStatus(point);
if (status == 0){
plugin.setPointStatus(point, true);
} else {
plugin.setPointStatus(point, false);
}
GPXUtilities.writeGpxFile(new File(gpx.path), gpx, app);
return null;
}
protected void onPostExecute(Void result) {
//to avoid illegal argument exception when rotating phone during loading
try {
dlg.dismiss();
} catch (Exception ex) {
ex.printStackTrace();
}
sortPoints();
displayListView();
}
}.execute(point);
}
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuItem item = menu.add(getString(R.string.mark_as_current));
item.setIcon(R.drawable.ic_action_signpost_dark);
item = menu.add(getString(R.string.mark_as_visited));
item.setIcon(R.drawable.ic_action_ok_dark);
item = menu.add(getString(R.string.show_on_map));
item.setIcon(R.drawable.ic_action_map_marker_dark);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
if (menuItem.getTitle().equals(getResources().getString(R.string.mark_as_current))) {
plugin.setCurrentPoint(sortedPointsList.get(selectedItemIndex));
sortPoints();
displayListView();
} else if (menuItem.getTitle().equals(getResources().getString(R.string.show_on_map))) {
GPXUtilities.WptPt point = sortedPointsList.get(selectedItemIndex);
app.getSettings().setMapLocationToShow(point.lat, point.lon, app.getSettings().getMapZoomToShow());
finish();
} else {
//inverts selection state of item
revertPointStatusAsync(sortedPointsList.get(selectedItemIndex));
sortPoints();
displayListView();
}
actionMode.finish();
return true;
}
@Override
public void onDestroyActionMode(ActionMode actionMode) {
}
};
@Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
com.actionbarsherlock.view.MenuItem doneItem = menu.add(getString(R.string.done));
doneItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
doneItem.setIcon(R.drawable.ic_action_map_marker_dark);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) {
if (item.getTitle().equals(getString(R.string.done))) {
GPXUtilities.WptPt point = plugin.getCurrentPoint();
app.getSettings().setMapLocationToShow(point.lat, point.lon, app.getSettings().getMapZoomToShow());
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
private void quickSort(List<Long> valuesList, List<Integer> indexList, int beginIdx, int len) {
if (len <= 1) {
return;
}
final int endIdx = beginIdx + len - 1;
// Pivot selection
final int pivotPos = beginIdx + len / 2;
final long pivot = valuesList.get(pivotPos);
swap(valuesList, indexList, pivotPos, endIdx);
// partitioning
int p = beginIdx;
for (int i = beginIdx; i != endIdx; ++i) {
if (valuesList.get(i) <= pivot) {
swap(valuesList, indexList, i, p++);
}
}
swap(valuesList, indexList, p, endIdx);
// recursive call
quickSort(valuesList, indexList, beginIdx, p - beginIdx);
quickSort(valuesList, indexList, p + 1, endIdx - p);
}
private void swap(List<Long> valuesList, List<Integer> indexList, int piviotPos, int endIndex){
long value = valuesList.get(piviotPos);
valuesList.set(piviotPos, valuesList.get(endIndex));
valuesList.set(endIndex,value);
int index = indexList.get(piviotPos);
indexList.set(piviotPos,indexList.get(endIndex));
indexList.set(endIndex,index);
}
private Activity getActivity() {
return this;
}
}

View file

@ -29,28 +29,28 @@ public class RoutePointsPlugin extends OsmandPlugin {
private GPXUtilities.GPXFile gpx;
private GPXUtilities.Route currentRoute;
private GPXUtilities.WptPt currentPoint;
private int currentPointPos;
private RoutePointsLayer routeStepsLayer;
private List<GPXUtilities.WptPt> pointsList;
private TextInfoWidget routeStepsControl;
private int visitedCount;
private Integer currentPointIndex;
public RoutePointsPlugin(OsmandApplication app) {
ApplicationMode. regWidget("route_steps", (ApplicationMode[]) null);
ApplicationMode.regWidget("route_steps", (ApplicationMode[]) null);
this.app = app;
}
public void setCurrentPoint(GPXUtilities.WptPt point) {
currentPoint = point;
int number = findPointPosition(point);
currentPointPos = number;
currentPointIndex = number;
}
public void setCurrentPoint(int number) {
currentPoint = pointsList.get(number);
currentPointPos = number;
currentPointIndex = number;
}
public List<GPXUtilities.WptPt> getPoints() {
@ -77,18 +77,22 @@ public class RoutePointsPlugin extends OsmandPlugin {
return true;
}
public GPXUtilities.WptPt getCurrentPoint(){
if (currentPoint == null){
for (int i =0; i< pointsList.size(); i++){
if (getPointStatus(i) == 0){
public GPXUtilities.WptPt getCurrentPoint() {
if (currentPoint == null) {
for (int i = 0; i < pointsList.size(); i++) {
if (getPointStatus(i) == 0) {
currentPoint = pointsList.get(i);
currentPointIndex = i;
break;
}
}
}
return currentPoint;
}
public GPXUtilities.GPXFile getGpx(){ return gpx;}
public GPXUtilities.GPXFile getGpx() {
return gpx;
}
public void setGpx(GPXUtilities.GPXFile gpx) {
this.gpx = gpx;
@ -118,8 +122,8 @@ public class RoutePointsPlugin extends OsmandPlugin {
}
public GPXUtilities.WptPt getNextPoint() {
if (pointsList.size() > currentPointPos + 1) {
return pointsList.get(currentPointPos + 1);
if (pointsList.size() > currentPointIndex + 1) {
return pointsList.get(currentPointIndex + 1);
} else {
return null;
}
@ -139,7 +143,7 @@ public class RoutePointsPlugin extends OsmandPlugin {
@Override
public void updateLayers(OsmandMapTileView mapView, MapActivity activity) {
if (routeStepsLayer == null){
if (routeStepsLayer == null) {
registerLayers(activity);
}
@ -148,7 +152,9 @@ public class RoutePointsPlugin extends OsmandPlugin {
}
}
public String getVisitedAllString(){ return String.valueOf(visitedCount) + "/" + String.valueOf(pointsList.size());}
public String getVisitedAllString() {
return String.valueOf(visitedCount) + "/" + String.valueOf(pointsList.size());
}
private TextInfoWidget createRouteStepsInfoControl(final MapActivity map, Paint paintText, Paint paintSubText) {
TextInfoWidget routeStepsControl = new TextInfoWidget(map, 0, paintText, paintSubText) {
@ -156,7 +162,7 @@ public class RoutePointsPlugin extends OsmandPlugin {
@Override()
public boolean updateInfo(OsmandMapLayer.DrawSettings drawSettings) {
if (gpx != null) {
setText(String.valueOf(visitedCount) + "/",String.valueOf(pointsList.size()));
setText(String.valueOf(visitedCount) + "/", String.valueOf(pointsList.size()));
} else {
setText(app.getString(R.string.route_points_no_gpx), "");
@ -178,13 +184,19 @@ public class RoutePointsPlugin extends OsmandPlugin {
return routeStepsControl;
}
public void refreshPointsStatus(){
public void refreshPointsStatus() {
visitedCount = 0;
for (int i=0; i< pointsList.size();i++){
if (getPointStatus(i) != 0){ visitedCount++;}
for (int i = 0; i < pointsList.size(); i++) {
if (getPointStatus(i) != 0) {
visitedCount++;
}
}
}
public long getPointStatus(GPXUtilities.WptPt point){
return getPointStatus(findPointPosition(point));
}
public long getPointStatus(int numberOfPoint) {
Map<String, String> map = currentRoute.getExtensionsToRead();
@ -198,10 +210,10 @@ public class RoutePointsPlugin extends OsmandPlugin {
}
//saves point status value to gpx extention file
public void setPointStatus(int numberOfPoint, boolean status) {
public void setPointStatus(GPXUtilities.WptPt point, boolean status) {
Map<String, String> map = currentRoute.getExtensionsToWrite();
String mapKey = POINT_KEY + numberOfPoint + VISITED_KEY;
int pos = findPointPosition(point);
String mapKey = POINT_KEY + pos + VISITED_KEY;
if (status) {
//value is current time
Calendar c = Calendar.getInstance();
@ -213,4 +225,26 @@ public class RoutePointsPlugin extends OsmandPlugin {
refreshPointsStatus();
}
//saves point status value to gpx extention file
public void markPointAsVisited(GPXUtilities.WptPt point) {
if (point.equals(currentPoint)){
currentPoint = null;
}
int pos = findPointPosition(point);
Map<String, String> map = currentRoute.getExtensionsToWrite();
String mapKey = POINT_KEY + pos + VISITED_KEY;
//value is current time
Calendar c = Calendar.getInstance();
long number = c.getTimeInMillis();
map.put(mapKey, String.valueOf(number));
refreshPointsStatus();
}
public Integer getCurrentPointIndex() {
return currentPointIndex;
}
}