Add move point mode

This commit is contained in:
PavelRatushny 2017-08-09 18:34:34 +03:00
parent ccd69672cc
commit de9530af0d
5 changed files with 323 additions and 19 deletions

View file

@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:background="@color/color_transparent"
android:clickable="true">
@ -38,6 +39,21 @@
android:background="@null"
tools:src="@drawable/ic_action_ruler"/>
<ImageView
android:id="@+id/move_point_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:background="@null"
tools:src="@drawable/ic_action_measure_point"
android:visibility="gone"/>
<ImageView
android:id="@+id/up_down_button"
android:layout_width="wrap_content"
@ -76,6 +92,21 @@
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_list_text_size"
tools:text="points: 3"/>
<TextView
android:id="@+id/move_point_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="4dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="4dp"
android:layout_marginStart="8dp"
android:layout_toEndOf="@id/move_point_icon"
android:layout_toRightOf="@id/move_point_icon"
android:textAppearance="@style/TextAppearance.ListItemTitle"
android:text="@string/move_point"
android:visibility="gone"/>
</RelativeLayout>
<View
@ -108,7 +139,7 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="52dp">
<ImageButton
android:id="@+id/undo_point_button"
@ -160,6 +191,41 @@
android:paddingRight="8dp"
android:text="@string/shared_string_add"
android:textColor="@color/color_white"/>
<Button
android:id="@+id/apply_point_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:background="@drawable/btn_round_blue"
android:minHeight="36dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="@string/shared_string_apply"
android:textColor="@color/color_white"
android:visibility="gone"/>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/cancel_button"
android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"
android:paddingEnd="12dp"
android:paddingLeft="16dp"
android:paddingRight="12dp"
android:paddingStart="16dp"
android:text="@string/shared_string_cancel"
android:textColor="?attr/color_dialog_buttons"
osmand:textAllCapsCompat="true"
osmand:typeface="@string/font_roboto_medium"
android:visibility="gone"/>
</RelativeLayout>
</LinearLayout>

View file

@ -2677,4 +2677,5 @@
<string name="import_track">Import track</string>
<string name="import_track_desc">File %1$s does not contain waypoints, import it as a track?</string>
<string name="save_as_new_segment">Save as new segment</string>
<string name="move_point">Move Point</string>
</resources>

View file

@ -23,6 +23,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
@ -46,12 +47,14 @@ import net.osmand.plus.measurementtool.adapter.MeasurementToolItemTouchHelperCal
import net.osmand.plus.measurementtool.command.AddPointCommand;
import net.osmand.plus.measurementtool.command.ClearPointsCommand;
import net.osmand.plus.measurementtool.command.CommandManager;
import net.osmand.plus.measurementtool.command.MovePointCommand;
import net.osmand.plus.measurementtool.command.RemovePointCommand;
import net.osmand.plus.measurementtool.command.ReorderPointCommand;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
import net.osmand.plus.widgets.IconPopupMenu;
import net.osmand.plus.widgets.TextViewEx;
import java.io.File;
import java.text.MessageFormat;
@ -79,8 +82,14 @@ public class MeasurementToolFragment extends Fragment {
private Drawable downIcon;
private View pointsListContainer;
private ImageView upDownBtn;
private ImageButton undoBtn;
private ImageButton redoBtn;
private ImageView undoBtn;
private ImageView redoBtn;
private TextViewEx cancelButton;
private ImageView movePointIcon;
private TextView movePointText;
private ImageView rulerIcon;
private Button addPointButton;
private Button applyMovePointButton;
private boolean wasCollapseButtonVisible;
private boolean pointsListOpened;
@ -118,16 +127,28 @@ public class MeasurementToolFragment extends Fragment {
distanceTv = (TextView) mainView.findViewById(R.id.measurement_distance_text_view);
pointsTv = (TextView) mainView.findViewById(R.id.measurement_points_text_view);
((ImageView) mainView.findViewById(R.id.ruler_icon))
.setImageDrawable(iconsCache.getIcon(R.drawable.ic_action_ruler, R.color.color_myloc_distance));
rulerIcon = (ImageView) mainView.findViewById(R.id.ruler_icon);
rulerIcon.setImageDrawable(iconsCache.getIcon(R.drawable.ic_action_ruler, R.color.color_myloc_distance));
upDownBtn = ((ImageView) mainView.findViewById(R.id.up_down_button));
movePointIcon = (ImageView) mainView.findViewById(R.id.move_point_icon);
movePointIcon.setImageDrawable(iconsCache.getIcon(R.drawable.ic_action_measure_point, R.color.color_myloc_distance));
movePointText = (TextView) mainView.findViewById(R.id.move_point_text);
upDownBtn = (ImageView) mainView.findViewById(R.id.up_down_button);
upDownBtn.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_arrow_up));
cancelButton = (TextViewEx) mainView.findViewById(R.id.cancel_button);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
cancelMovePointMode();
}
});
mainView.findViewById(R.id.up_down_row).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!pointsListOpened && measurementLayer.getPointsCount() > 0) {
if (!pointsListOpened && measurementLayer.getPointsCount() > 0 && !measurementLayer.isInMovePointMode()) {
showPointsList();
} else {
hidePointsList();
@ -135,6 +156,14 @@ public class MeasurementToolFragment extends Fragment {
}
});
applyMovePointButton = (Button) mainView.findViewById(R.id.apply_point_button);
applyMovePointButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
applyMovePointMode();
}
});
undoBtn = ((ImageButton) mainView.findViewById(R.id.undo_point_button));
redoBtn = ((ImageButton) mainView.findViewById(R.id.redo_point_button));
@ -172,7 +201,8 @@ public class MeasurementToolFragment extends Fragment {
}
});
mainView.findViewById(R.id.add_point_button).setOnClickListener(new View.OnClickListener() {
addPointButton = (Button) mainView.findViewById(R.id.add_point_button);
addPointButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addPoint();
@ -186,6 +216,16 @@ public class MeasurementToolFragment extends Fragment {
}
});
measurementLayer.setOnEnterMovePointModeListener(new MeasurementToolLayer.OnEnterMovePointModeListener() {
@Override
public void onEnterMovePointMode() {
if (pointsListOpened) {
hidePointsList();
}
enterMovePointMode();
}
});
disable(undoBtn, redoBtn, upDownBtn);
enterMeasurementMode();
@ -301,6 +341,61 @@ public class MeasurementToolFragment extends Fragment {
return view;
}
private void cancelMovePointMode() {
exitMovePointMode();
MeasurementToolLayer measurementToolLayer = getMeasurementLayer();
if (measurementToolLayer != null) {
measurementToolLayer.exitMovePointMode();
}
}
private void applyMovePointMode() {
exitMovePointMode();
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
WptPt newPoint = measurementLayer.getMovedPointToApply();
WptPt oldPoint = measurementLayer.getPreviouslyMovedPoint();
int position = measurementLayer.getMovePointPosition();
commandManager.execute(new MovePointCommand(measurementLayer, oldPoint, newPoint, position));
enable(undoBtn, upDownBtn);
disable(redoBtn);
updateText();
adapter.notifyDataSetChanged();
saved = false;
measurementLayer.exitMovePointMode();
measurementLayer.refreshMap();
}
}
private void enterMovePointMode() {
rulerIcon.setVisibility(View.GONE);
distanceTv.setVisibility(View.GONE);
pointsTv.setVisibility(View.GONE);
upDownBtn.setVisibility(View.GONE);
undoBtn.setVisibility(View.GONE);
redoBtn.setVisibility(View.GONE);
addPointButton.setVisibility(View.GONE);
movePointIcon.setVisibility(View.VISIBLE);
movePointText.setVisibility(View.VISIBLE);
cancelButton.setVisibility(View.VISIBLE);
applyMovePointButton.setVisibility(View.VISIBLE);
}
private void exitMovePointMode() {
movePointIcon.setVisibility(View.GONE);
movePointText.setVisibility(View.GONE);
cancelButton.setVisibility(View.GONE);
applyMovePointButton.setVisibility(View.GONE);
rulerIcon.setVisibility(View.VISIBLE);
distanceTv.setVisibility(View.VISIBLE);
pointsTv.setVisibility(View.VISIBLE);
upDownBtn.setVisibility(View.VISIBLE);
undoBtn.setVisibility(View.VISIBLE);
redoBtn.setVisibility(View.VISIBLE);
addPointButton.setVisibility(View.VISIBLE);
}
private void hidePointsListIfNoPoints() {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {

View file

@ -6,6 +6,7 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.util.Log;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
@ -28,10 +29,12 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
private OsmandMapTileView view;
private boolean inMeasurementMode;
private boolean inMovePointMode;
private final LinkedList<WptPt> measurementPoints = new LinkedList<>();
private Bitmap centerIconDay;
private Bitmap centerIconNight;
private Bitmap pointIcon;
private Bitmap movePointIcon;
private Paint bitmapPaint;
private final RenderingLineAttributes lineAttrs = new RenderingLineAttributes("measureDistanceLine");
private final Path path = new Path();
@ -40,6 +43,9 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
private final TIntArrayList tx = new TIntArrayList();
private final TIntArrayList ty = new TIntArrayList();
private OnSingleTapListener singleTapListener;
private OnEnterMovePointModeListener enterMovePointModeListener;
private int movePointPos;
private WptPt previouslyMovedPoint;
@Override
public void initLayer(OsmandMapTileView view) {
@ -48,6 +54,7 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
centerIconDay = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_day);
centerIconNight = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_night);
pointIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pedestrian_location);
movePointIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_mapillary_location);
bitmapPaint = new Paint();
bitmapPaint.setAntiAlias(true);
@ -62,10 +69,26 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
this.singleTapListener = listener;
}
void setOnEnterMovePointModeListener(OnEnterMovePointModeListener listener) {
this.enterMovePointModeListener = listener;
}
WptPt getPreviouslyMovedPoint() {
return previouslyMovedPoint;
}
int getMovePointPosition() {
return movePointPos;
}
public boolean isInMeasurementMode() {
return inMeasurementMode;
}
public boolean isInMovePointMode() {
return inMovePointMode;
}
void setInMeasurementMode(boolean inMeasurementMode) {
this.inMeasurementMode = inMeasurementMode;
}
@ -102,11 +125,50 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
return false;
}
@Override
public boolean onLongPressEvent(PointF point, RotatedTileBox tileBox) {
if (inMovePointMode || measurementPoints.size() == 0) {
return false;
}
double pressedPointLat = tileBox.getLatFromPixel(point.x, point.y);
double pressedPointLon = tileBox.getLonFromPixel(point.x, point.y);
getPointToMove(pressedPointLat, pressedPointLon);
if (movePointPos != -1) {
enterMovingPointMode();
if (inMeasurementMode && inMovePointMode && enterMovePointModeListener != null) {
enterMovePointModeListener.onEnterMovePointMode();
}
}
return false;
}
private void enterMovingPointMode() {
inMovePointMode = true;
moveMapToPoint(movePointPos);
}
private void getPointToMove(double lat, double lon) {
double lowestDistance = Double.MAX_VALUE;
for (int i = 0; i < measurementPoints.size(); i++) {
WptPt pt = measurementPoints.get(i);
double latDiff = pt.getLatitude() - lat;
double lonDiff = pt.getLongitude() - lon;
double distToPoint = Math.sqrt(Math.pow(latDiff, 2) + Math.pow(lonDiff, 2));
if (distToPoint < lowestDistance) {
lowestDistance = distToPoint;
previouslyMovedPoint = new WptPt(pt);
movePointPos = i;
}
}
}
@Override
public void onDraw(Canvas canvas, RotatedTileBox tb, DrawSettings settings) {
if (inMeasurementMode) {
lineAttrs.updatePaints(view, settings, tb);
drawCenterIcon(canvas, tb, tb.getCenterPixelPoint(), settings.isNightMode());
if (!inMovePointMode) {
drawCenterIcon(canvas, tb, tb.getCenterPixelPoint(), settings.isNightMode());
}
if (measurementPoints.size() > 0) {
path.reset();
@ -114,8 +176,15 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
ty.reset();
for (int i = 0; i < measurementPoints.size(); i++) {
WptPt pt = measurementPoints.get(i);
int locX = tb.getPixXFromLonNoRot(pt.lon);
int locY = tb.getPixYFromLatNoRot(pt.lat);
int locX;
int locY;
if (inMovePointMode && movePointPos == i) {
locX = tb.getCenterPixelX();
locY = tb.getCenterPixelY();
} else {
locX = tb.getPixXFromLonNoRot(pt.lon);
locY = tb.getPixYFromLatNoRot(pt.lat);
}
if (i == 0) {
path.moveTo(locX, locY);
} else {
@ -124,22 +193,37 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
tx.add(locX);
ty.add(locY);
}
path.lineTo(tb.getCenterPixelX(), tb.getCenterPixelY());
tx.add(tb.getCenterPixelX());
ty.add(tb.getCenterPixelY());
if (!inMovePointMode) {
path.lineTo(tb.getCenterPixelX(), tb.getCenterPixelY());
tx.add(tb.getCenterPixelX());
ty.add(tb.getCenterPixelY());
}
calculatePath(tb, tx, ty, path);
canvas.drawPath(path, lineAttrs.paint);
for (WptPt pt : measurementPoints) {
if (tb.containsLatLon(pt.lat, pt.lon)) {
int locX = tb.getPixXFromLonNoRot(pt.lon);
int locY = tb.getPixYFromLatNoRot(pt.lat);
canvas.drawBitmap(pointIcon, locX - marginX, locY - marginY, bitmapPaint);
for (int i = 0; i < measurementPoints.size(); i++) {
WptPt pt = measurementPoints.get(i);
if (inMovePointMode && i == movePointPos) {
int locX = tb.getCenterPixelX();
int locY = tb.getCenterPixelY();
canvas.drawBitmap(movePointIcon, locX - marginX, locY - marginY, bitmapPaint);
} else {
if (tb.containsLatLon(pt.lat, pt.lon)) {
int locX = tb.getPixXFromLonNoRot(pt.lon);
int locY = tb.getPixYFromLatNoRot(pt.lat);
canvas.drawBitmap(pointIcon, locX - marginX, locY - marginY, bitmapPaint);
}
}
}
}
}
}
void exitMovePointMode() {
inMovePointMode = false;
movePointPos = -1;
previouslyMovedPoint = null;
}
private void drawCenterIcon(Canvas canvas, RotatedTileBox tb, QuadPoint center, boolean nightMode) {
canvas.rotate(-tb.getRotate(), center.x, center.y);
if (nightMode) {
@ -177,6 +261,15 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
return null;
}
WptPt getMovedPointToApply() {
RotatedTileBox tb = view.getCurrentRotatedTileBox();
LatLon latLon = tb.getCenterLatLon();
WptPt pt = measurementPoints.get(movePointPos);
pt.lat = latLon.getLatitude();
pt.lon = latLon.getLongitude();
return pt;
}
public WptPt removePoint(int position) {
WptPt res = measurementPoints.remove(position);
view.refreshMap();
@ -242,4 +335,8 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
interface OnSingleTapListener {
void onSingleTap();
}
interface OnEnterMovePointModeListener {
void onEnterMovePointMode();
}
}

View file

@ -0,0 +1,45 @@
package net.osmand.plus.measurementtool.command;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
public class MovePointCommand implements Command {
private final MeasurementToolLayer measurementLayer;
private final WptPt oldPoint;
private final WptPt newPoint;
private final int position;
public MovePointCommand (MeasurementToolLayer measurementLayer, WptPt oldPoint, WptPt newPoint, int position) {
this.measurementLayer = measurementLayer;
this.oldPoint = oldPoint;
this.newPoint = newPoint;
this.position = position;
}
@Override
public boolean execute() {
return true;
}
@Override
public void undo() {
replacePointWithOldOne();
}
@Override
public void redo() {
replacePointWithNewOne();
}
private void replacePointWithOldOne() {
measurementLayer.getMeasurementPoints().remove(position);
measurementLayer.getMeasurementPoints().add(position, oldPoint);
}
private void replacePointWithNewOne() {
measurementLayer.getMeasurementPoints().remove(position);
measurementLayer.getMeasurementPoints().add(position, newPoint);
}
}