Skip to content

Commit

Permalink
Return issues if any from replace operation
Browse files Browse the repository at this point in the history
This adds code to show a modal in the style of the tag conflict one if
we needed to extract a tagged node and a preference to determine the
distance at which we start doing that.
  • Loading branch information
simonpoole committed Oct 16, 2024
1 parent 3548c4e commit 9025cbb
Show file tree
Hide file tree
Showing 19 changed files with 194 additions and 43 deletions.
15 changes: 12 additions & 3 deletions src/main/java/de/blau/android/Logic.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
import de.blau.android.osm.RelationMemberDescription;
import de.blau.android.osm.RelationMemberPosition;
import de.blau.android.osm.RelationUtils;
import de.blau.android.osm.ReplaceIssue;
import de.blau.android.osm.Result;
import de.blau.android.osm.Server;
import de.blau.android.osm.Storage;
Expand Down Expand Up @@ -2115,7 +2116,7 @@ private void handleDelegatorException(@Nullable final FragmentActivity activity,
* @param way the way to split
* @param node the node at which the way should be split
* @param fromEnd create new Way from Nodes after node
* @return a Result object containing the new Way or null if failed
* @return a List of Result objects containing the new Way and any issues
* @throws OsmIllegalOperationException if the operation failed
* @throws StorageException if we ran out of memory
*/
Expand Down Expand Up @@ -2740,8 +2741,10 @@ public synchronized void performAppendAppend(@Nullable final Activity activity,
* @param activity optional Activity
* @param target way that will get the new geometry
* @param geometry list of GeoPoint with the new geometry
* @return a List of Result elements
*/
public synchronized <T extends GeoPoint> void performReplaceGeometry(@Nullable final FragmentActivity activity, @NonNull Way target,
@NonNull
public synchronized <T extends GeoPoint> List<Result> performReplaceGeometry(@Nullable final FragmentActivity activity, @NonNull Way target,
@NonNull List<T> geometry) {
StorageDelegator delegator = getDelegator();
createCheckpoint(activity, R.string.undo_action_replace_geometry);
Expand Down Expand Up @@ -2773,11 +2776,17 @@ public synchronized <T extends GeoPoint> void performReplaceGeometry(@Nullable f
}
delegator.replaceWayNodes(newNodes, target);
// final act: delete all unused untagged nodes left
List<Result> result = new ArrayList<>();
for (Node n : targetNodes) {
if (!n.isTagged() && !n.hasParentRelations() && getWaysForNode(n).isEmpty()) {
performEraseNode(activity, n, false);
} else {
Result r = new Result(n);
r.addIssue(ReplaceIssue.EXTRACTED_NODE);
result.add(r);
}
}
return result;
} catch (OsmIllegalOperationException | StorageException ex) {
handleDelegatorException(activity, ex);
throw ex; // rethrow
Expand All @@ -2799,7 +2808,7 @@ private Node findTargetNode(@NonNull List<Node> targetNodes, double newLon, doub
for (Node target : targetNodes) {
double distance = GeoMath.haversineDistance(target.getLon() / 1E7D, target.getLat() / 1E7D, newLon, newLat);
if (distance < bestDistance) {
if (target.hasTags() && distance > 1) { // only use tagged nodes if they are really close to new
if (target.hasTags() && prefs != null && distance > prefs.getReplaceTolerance()) { // only use tagged nodes if they are really close to new
// position
continue;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.blau.android.dialogs;

import static de.blau.android.contract.Constants.LOG_TAG_LEN;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -34,30 +36,64 @@
import de.blau.android.util.ThemeUtils;
import de.blau.android.util.Util;

public class TagConflictDialog extends ImmersiveDialogFragment {
private static final String DEBUG_TAG = TagConflictDialog.class.getSimpleName().substring(0, Math.min(23, TagConflictDialog.class.getSimpleName().length()));
public class ElementIssueDialog extends ImmersiveDialogFragment {
private static final int TAG_LEN = Math.min(LOG_TAG_LEN, ElementIssueDialog.class.getSimpleName().length());
private static final String DEBUG_TAG = ElementIssueDialog.class.getSimpleName().substring(0, TAG_LEN);

private static final String TAG = "fragment_tag_conflict";
private static final String TAG = "fragment_element_issue";

private static final String TITLE_KEY = "title_key";
private static final String MESSAGE_KEY = "message_key";
private static final String TIP_KEY_KEY = "tip_key_key";
private static final String TIP_KEY = "tip_key";
private static final String RESULTS_KEY = "results";

private int titleRes;
private int messageRes;
private int tipKeyRes;
private int tipRes;
private List<Result> result;

/**
* Show a dialog with a list of tag conflict issues
*
* @param activity the calling FragmentActivity
* @param result the List of Result elements
*/
public static void showTagConflictDialog(@NonNull AppCompatActivity activity, @NonNull List<Result> result) {
showDialog(activity, R.string.tag_conflict_title, R.string.tag_conflict_message, R.string.tip_tag_conflict_key, R.string.tip_tag_conflict, result);
}

/**
* Show a dialog with a list of issues caused by replacing geometry
*
* @param activity the calling FragmentActivity
* @param result the List of Result elements
*/
public static void showReplaceGeometryIssuetDialog(@NonNull AppCompatActivity activity, @NonNull List<Result> result) {
showDialog(activity, R.string.replace_geometry_issue_title, R.string.replace_geometry_issue_message, R.string.tip_replace_geometry_key,
R.string.tip_replace_geometry, result);
}

/**
* Show a dialog with a list of issues
*
* @param activity the calling FragmentActivity
* @param titleRes resource id for the title
* @param messageRes resource if for the message
* @param tipKeyRes tip key resource
* @param tipRes tip message resource
* @param result the List of Result elements
*/
public static void showDialog(@NonNull AppCompatActivity activity, @NonNull List<Result> result) {
private static void showDialog(@NonNull AppCompatActivity activity, int titleRes, int messageRes, int tipKeyRes, int tipRes, @NonNull List<Result> result) {
dismissDialog(activity);
try {
FragmentManager fm = activity.getSupportFragmentManager();
if (activity instanceof Main) {
((Main) activity).descheduleAutoLock();
}
TagConflictDialog tagConflictFragment = newInstance(result);
tagConflictFragment.show(fm, TAG);
ElementIssueDialog elementIssueFragment = newInstance(titleRes, messageRes, tipKeyRes, tipRes, result);
elementIssueFragment.show(fm, TAG);
} catch (IllegalStateException isex) {
Log.e(DEBUG_TAG, "showDialog", isex);
}
Expand All @@ -75,12 +111,20 @@ private static void dismissDialog(@NonNull AppCompatActivity activity) {
/**
* Create new instance of this object
*
* @param titleRes resource id for the title
* @param messageRes resource if for the message
* @param tipKeyRes tip key resource
* @param tipRes tip message resource
* @param result the List of Result elements
* @return a TagConflictDialog instance
*/
private static TagConflictDialog newInstance(@NonNull List<Result> result) {
TagConflictDialog f = new TagConflictDialog();
private static ElementIssueDialog newInstance(int titleRes, int messageRes, int tipKeyRes, int tipRes, @NonNull List<Result> result) {
ElementIssueDialog f = new ElementIssueDialog();
Bundle args = new Bundle();
args.putInt(TITLE_KEY, titleRes);
args.putInt(MESSAGE_KEY, messageRes);
args.putInt(TIP_KEY_KEY, tipKeyRes);
args.putInt(TIP_KEY, tipRes);
args.putSerializable(RESULTS_KEY, (Serializable) result);

f.setArguments(args);
Expand All @@ -95,19 +139,28 @@ private static TagConflictDialog newInstance(@NonNull List<Result> result) {
public AppCompatDialog onCreateDialog(Bundle savedInstanceState) {
if (savedInstanceState != null) {
Log.d(DEBUG_TAG, "Recreating from saved state");
titleRes = savedInstanceState.getInt(TITLE_KEY);
messageRes = savedInstanceState.getInt(MESSAGE_KEY);
tipKeyRes = savedInstanceState.getInt(TIP_KEY_KEY);
tipRes = savedInstanceState.getInt(TIP_KEY);
result = Util.getSerializeableArrayList(savedInstanceState, RESULTS_KEY, Result.class);
// restore the elements
for (Result r : result) {
r.restoreElement(App.getDelegator());
}
} else {
Bundle args = getArguments();
titleRes = args.getInt(TITLE_KEY);
messageRes = args.getInt(MESSAGE_KEY);
tipKeyRes = args.getInt(TIP_KEY_KEY);
tipRes = args.getInt(TIP_KEY);
result = Util.getSerializeableArrayList(getArguments(), RESULTS_KEY, Result.class);
}
final LayoutInflater inflater = ThemeUtils.getLayoutInflater(getActivity());
View layout = inflater.inflate(R.layout.tag_conflict, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(R.string.tag_conflict_title);
builder.setMessage(R.string.tag_conflict_message);
builder.setTitle(titleRes);
builder.setMessage(messageRes);

ListView list = layout.findViewById(R.id.elements);
list.setAdapter(new ResultArrayAdapter(getContext(), R.layout.tag_conflict_item, R.id.text1, result));
Expand All @@ -129,7 +182,7 @@ public AppCompatDialog onCreateDialog(Bundle savedInstanceState) {
public void onStart() {
super.onStart();
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
Tip.showDialog(getActivity(), R.string.tip_tag_conflict_key, R.string.tip_tag_conflict);
Tip.showDialog(getActivity(), tipKeyRes, tipRes);
}

@Override
Expand All @@ -144,6 +197,10 @@ public void onDismiss(DialogInterface dialog) {
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(DEBUG_TAG, "onSaveInstanceState");
outState.putInt(TITLE_KEY, titleRes);
outState.putInt(MESSAGE_KEY, messageRes);
outState.putInt(TIP_KEY_KEY, tipKeyRes);
outState.putInt(TIP_KEY, tipRes);
List<Result> toSave = new ArrayList<>();
// directly saving OsmElements is a bad idea
// we need to copy everything as otherwise we
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/de/blau/android/dialogs/UploadConflict.java
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ private void setMergedTags(@NonNull final FragmentActivity activity, @NonNull fi
if (mergeResult.hasIssue()) {
((Main) activity).edit(into);
// NOTE Arrays.asList doesn't work here
TagConflictDialog.showDialog(((Main) activity), de.blau.android.util.Util.wrapInList(mergeResult));
ElementIssueDialog.showTagConflictDialog(((Main) activity), de.blau.android.util.Util.wrapInList(mergeResult));
} else {
restartHandler.onSuccess();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
import de.blau.android.Main;
import de.blau.android.PostAsyncActionHandler;
import de.blau.android.R;
import de.blau.android.dialogs.ElementIssueDialog;
import de.blau.android.dialogs.ErrorAlert;
import de.blau.android.dialogs.TagConflictDialog;
import de.blau.android.osm.Node;
import de.blau.android.osm.OsmElement;
import de.blau.android.osm.RelationUtils;
Expand Down Expand Up @@ -473,7 +473,7 @@ public void saveState(@NonNull SerializableState state) {
protected void checkSplitResult(@NonNull Way originalWay, @Nullable List<Result> resultList) {
saveSplitResult(originalWay, resultList);
if (!savedResults.isEmpty()) {
TagConflictDialog.showDialog(main, new ArrayList<>(savedResults.values()));
ElementIssueDialog.showTagConflictDialog(main, new ArrayList<>(savedResults.values()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import de.blau.android.App;
import de.blau.android.Map;
import de.blau.android.R;
import de.blau.android.dialogs.TagConflictDialog;
import de.blau.android.dialogs.ElementIssueDialog;
import de.blau.android.exception.OsmIllegalOperationException;
import de.blau.android.osm.Node;
import de.blau.android.osm.OsmElement;
Expand All @@ -36,7 +36,7 @@

public class MultiSelectWithGeometryActionModeCallback extends MultiSelectActionModeCallback {

private static final int TAG_LEN = Math.min(LOG_TAG_LEN, EasyEditActionModeCallback.class.getSimpleName().length());
private static final int TAG_LEN = Math.min(LOG_TAG_LEN, MultiSelectWithGeometryActionModeCallback.class.getSimpleName().length());
private static final String DEBUG_TAG = MultiSelectWithGeometryActionModeCallback.class.getSimpleName().substring(0, TAG_LEN);

private static final int MENUITEM_MERGE = ElementSelectionActionModeCallback.LAST_REGULAR_MENUITEM + 1;
Expand Down Expand Up @@ -308,7 +308,7 @@ void mergeWays() {
final Result r = result.get(0);
main.startSupportActionMode(new WaySelectionActionModeCallback(manager, (Way) r.getElement()));
if (result.size() > 1 || r.hasIssue()) {
TagConflictDialog.showDialog(main, result);
ElementIssueDialog.showTagConflictDialog(main, result);
}
} catch (OsmIllegalOperationException | IllegalStateException e) {
ScreenMessage.barError(main, e.getLocalizedMessage());
Expand All @@ -331,7 +331,7 @@ private void mergePolygons() {
main.startSupportActionMode(new RelationSelectionActionModeCallback(manager, (Relation) e));
}
if (result.size() > 1 || r.hasIssue()) {
TagConflictDialog.showDialog(main, result);
ElementIssueDialog.showTagConflictDialog(main, result);
}
} catch (OsmIllegalOperationException | IllegalStateException e) {
ScreenMessage.barError(main, e.getLocalizedMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import androidx.appcompat.view.ActionMode;
import de.blau.android.DisambiguationMenu;
import de.blau.android.R;
import de.blau.android.dialogs.TagConflictDialog;
import de.blau.android.dialogs.ElementIssueDialog;
import de.blau.android.easyedit.turnrestriction.FromElementWithViaNodeActionModeCallback;
import de.blau.android.exception.OsmIllegalOperationException;
import de.blau.android.exception.StorageException;
Expand Down Expand Up @@ -236,7 +236,7 @@ private void mergeNodeWith(@NonNull List<OsmElement> target) {
manager.editElement(newElement);
}
if (result.size() > 1 || result.get(0).hasIssue()) {
TagConflictDialog.showDialog(main, result);
ElementIssueDialog.showTagConflictDialog(main, result);
} else {
ScreenMessage.toastTopInfo(main, R.string.toast_merged);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import de.blau.android.App;
import de.blau.android.Logic;
import de.blau.android.R;
import de.blau.android.dialogs.TagConflictDialog;
import de.blau.android.dialogs.ElementIssueDialog;
import de.blau.android.exception.OsmIllegalOperationException;
import de.blau.android.exception.StorageException;
import de.blau.android.osm.GeoPoint;
Expand Down Expand Up @@ -103,16 +103,22 @@ public boolean handleElementClick(OsmElement element) { // NOSONAR
Logic logic = App.getLogic();
try {
if (target instanceof Way) {
logic.performReplaceGeometry(main, (Way) target, ((Way) element).getNodes());
final List<Result> result = logic.performReplaceGeometry(main, (Way) target, ((Way) element).getNodes());
AlertDialog.Builder builder = new AlertDialog.Builder(main);
builder.setTitle(R.string.remove_geometry_source);
builder.setPositiveButton(R.string.Yes, (dialog, id) -> logic.performEraseWay(main, ((Way) element), true, false));
builder.setNegativeButton(R.string.No, null);
AlertDialog d = builder.create();
d.setOnDismissListener((DialogInterface dialog) -> main.startSupportActionMode(new WaySelectionActionModeCallback(manager, (Way) target)));
d.setOnDismissListener((DialogInterface dialog) -> {
main.startSupportActionMode(new WaySelectionActionModeCallback(manager, (Way) target));
if (!result.isEmpty()) {
ElementIssueDialog.showReplaceGeometryIssuetDialog(main, result);
}
});
d.show();
}
if (target instanceof Node) {
// arguably this section should really be in Logic
logic.createCheckpoint(main, R.string.undo_action_replace_geometry);
Node toReplace = findYoungestUntaggedNode((Way) element);
logic.setTags(main, Node.NAME, target.getOsmId(), null, false);
Expand All @@ -124,7 +130,7 @@ public boolean handleElementClick(OsmElement element) { // NOSONAR
MergeAction.checkForMergedTags(targetTags, element.getTags(), mergedTags, r);
logic.setTags(main, Way.NAME, element.getOsmId(), mergedTags, false);
if (mergeResult.size() > 1 || r.hasIssue()) {
TagConflictDialog.showDialog(main, mergeResult);
ElementIssueDialog.showTagConflictDialog(main, mergeResult);
}
logic.deselectAll();
logic.addSelectedWay((Way) element);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.blau.android.easyedit;

import static de.blau.android.contract.Constants.LOG_TAG_LEN;

import java.util.List;
import java.util.Set;

Expand All @@ -9,15 +11,18 @@
import androidx.annotation.NonNull;
import androidx.appcompat.view.ActionMode;
import de.blau.android.R;
import de.blau.android.dialogs.TagConflictDialog;
import de.blau.android.dialogs.ElementIssueDialog;
import de.blau.android.exception.OsmIllegalOperationException;
import de.blau.android.osm.OsmElement;
import de.blau.android.osm.Result;
import de.blau.android.osm.Way;
import de.blau.android.util.ScreenMessage;

public class WayMergingActionModeCallback extends NonSimpleActionModeCallback {
private static final String DEBUG_TAG = "WayMerging...";

private static final int TAG_LEN = Math.min(LOG_TAG_LEN, WayMergingActionModeCallback.class.getSimpleName().length());
private static final String DEBUG_TAG = WayMergingActionModeCallback.class.getSimpleName().substring(0, TAG_LEN);

private final Way way;
private final Set<OsmElement> ways;

Expand Down Expand Up @@ -61,7 +66,7 @@ public boolean handleElementClick(OsmElement element) { // due to clickableEleme
Result r = result.get(0);
main.startSupportActionMode(new WaySelectionActionModeCallback(manager, (Way) r.getElement()));
if (result.size() > 1 || r.hasIssue()) {
TagConflictDialog.showDialog(main, result);
ElementIssueDialog.showTagConflictDialog(main, result);
}
} catch (OsmIllegalOperationException e) {
ScreenMessage.barError(main, e.getLocalizedMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import androidx.appcompat.view.ActionMode;
import de.blau.android.App;
import de.blau.android.R;
import de.blau.android.dialogs.TagConflictDialog;
import de.blau.android.dialogs.ElementIssueDialog;
import de.blau.android.easyedit.route.RouteSegmentActionModeCallback;
import de.blau.android.easyedit.turnrestriction.FromElementActionModeCallback;
import de.blau.android.exception.OsmIllegalOperationException;
Expand Down Expand Up @@ -217,7 +217,7 @@ private void reverseWay(@NonNull final Way way) {
try {
List<Result> result = logic.performReverse(main, way);
if (!result.isEmpty()) {
TagConflictDialog.showDialog(main, result);
ElementIssueDialog.showTagConflictDialog(main, result);
}
} catch (OsmIllegalOperationException | StorageException ex) {
// toast has already been displayed
Expand Down
Loading

0 comments on commit 9025cbb

Please sign in to comment.