Skip to content

Commit cadddb6

Browse files
committed
Add 'replace selected' action to relation editor
1 parent f8e3481 commit cadddb6

File tree

5 files changed

+158
-13
lines changed

5 files changed

+158
-13
lines changed
Lines changed: 15 additions & 0 deletions
Loading

src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
import org.openstreetmap.josm.gui.dialogs.relation.actions.RefreshAction;
8989
import org.openstreetmap.josm.gui.dialogs.relation.actions.RemoveAction;
9090
import org.openstreetmap.josm.gui.dialogs.relation.actions.RemoveSelectedAction;
91+
import org.openstreetmap.josm.gui.dialogs.relation.actions.ReplaceSelectedAction;
9192
import org.openstreetmap.josm.gui.dialogs.relation.actions.ReverseAction;
9293
import org.openstreetmap.josm.gui.dialogs.relation.actions.SelectAction;
9394
import org.openstreetmap.josm.gui.dialogs.relation.actions.SelectPrimitivesForSelectedMembersAction;
@@ -737,10 +738,13 @@ protected static JToolBar buildSelectionControlButtonToolbar(IRelationEditorActi
737738
new AddSelectedAtEndAction(editorAccess)
738739
));
739740
groups.add(buildNativeGroup(20,
741+
new ReplaceSelectedAction(editorAccess)
742+
));
743+
groups.add(buildNativeGroup(30,
740744
new SelectedMembersForSelectionAction(editorAccess),
741745
new SelectPrimitivesForSelectedMembersAction(editorAccess)
742746
));
743-
groups.add(buildNativeGroup(30,
747+
groups.add(buildNativeGroup(40,
744748
new RemoveSelectedAction(editorAccess)
745749
));
746750
groups.addAll(RelationEditorHooks.getSelectActions());

src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,42 @@ public void updateRole(int[] idx, String role) {
520520
addToSelectedMembers(selected);
521521
}
522522

523+
/**
524+
* updates the referenced primitive of the members given by the index in <code>index</code>
525+
*
526+
* @param index the index to update
527+
* @param newPrimitive the new primitive
528+
* @since xxx
529+
*/
530+
public void updateMemberPrimitive(int index, OsmPrimitive newPrimitive) {
531+
if (index >= members.size()) {
532+
return;
533+
}
534+
535+
RelationMember newMember = new RelationMember(members.get(index).getRole(), newPrimitive);
536+
updateMember(index, newMember);
537+
}
538+
539+
/**
540+
* replace the member at <code>index</code> with a new one
541+
*
542+
* @param index the index to update
543+
* @param newMember the new member
544+
* @since xxx
545+
*/
546+
public void updateMember(int index, RelationMember newMember) {
547+
if (index >= members.size()) {
548+
return;
549+
}
550+
551+
RelationMember oldMember = members.get(index);
552+
if (oldMember.equals(newMember))
553+
return;
554+
555+
setValue(index, newMember);
556+
fireTableDataChanged();
557+
}
558+
523559
/**
524560
* Get the currently selected relation members
525561
*

src/org/openstreetmap/josm/gui/dialogs/relation/actions/AddFromSelectionAction.java

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,61 @@ protected boolean isPotentialDuplicate(OsmPrimitive primitive) {
2929
return editorAccess.getMemberTableModel().hasMembersReferringTo(Collections.singleton(primitive));
3030
}
3131

32+
/**
33+
* Check and filter a list of primitives before adding them as relation members.
34+
* Prompt users for confirmation when duplicates are detected and prevent relation loops.
35+
*
36+
* @param primitives The primitives to be checked and filtered
37+
* @return The primitives to add to the relation. Never {@code null}, but may be an empty list.
38+
* @throws AddAbortException when a relation loop is detected
39+
*/
3240
protected List<OsmPrimitive> filterConfirmedPrimitives(List<OsmPrimitive> primitives) throws AddAbortException {
41+
return filterConfirmedPrimitives(primitives, false);
42+
}
43+
44+
/**
45+
* Check and filter a list of primitives before adding them as relation members.
46+
* Prompt users for confirmation when duplicates are detected and prevent relation loops.
47+
*
48+
* @param primitives The primitives to be checked and filtered
49+
* @param abortOnSkip If the user decides to not add a primitive or adding a primitive would
50+
* cause a relation loop, abort (throw {@code AddAbortException})
51+
* @return The primitives to add to the relation. Never {@code null}, but may be an empty list.
52+
* @throws AddAbortException when a relation loop is detected or {@code abortOnSkip} is
53+
* {@code true} <i>and</i> the user decides to not add a primitive.
54+
* @since xxx
55+
*/
56+
protected List<OsmPrimitive> filterConfirmedPrimitives(List<OsmPrimitive> primitives, boolean abortOnSkip) throws AddAbortException {
3357
if (Utils.isEmpty(primitives))
3458
return primitives;
3559
List<OsmPrimitive> ret = new ArrayList<>();
3660
ConditionalOptionPaneUtil.startBulkOperation("add_primitive_to_relation");
37-
for (OsmPrimitive primitive : primitives) {
38-
if (primitive instanceof Relation) {
39-
List<Relation> loop = RelationChecker.checkAddMember(editorAccess.getEditor().getRelation(), (Relation) primitive);
40-
if (!loop.isEmpty() && loop.get(0).equals(loop.get(loop.size() - 1))) {
41-
GenericRelationEditor.warnOfCircularReferences(primitive, loop);
42-
continue;
61+
try {
62+
for (OsmPrimitive primitive : primitives) {
63+
if (primitive instanceof Relation) {
64+
List<Relation> loop = RelationChecker.checkAddMember(editorAccess.getEditor().getRelation(), (Relation) primitive);
65+
if (!loop.isEmpty() && loop.get(0).equals(loop.get(loop.size() - 1))) {
66+
GenericRelationEditor.warnOfCircularReferences(primitive, loop);
67+
if (abortOnSkip) {
68+
throw new AddAbortException();
69+
}
70+
continue;
71+
}
4372
}
44-
}
45-
if (isPotentialDuplicate(primitive)) {
46-
if (GenericRelationEditor.confirmAddingPrimitive(primitive)) {
73+
if (isPotentialDuplicate(primitive)) {
74+
if (GenericRelationEditor.confirmAddingPrimitive(primitive)) {
75+
ret.add(primitive);
76+
} else if (abortOnSkip) {
77+
throw new AddAbortException();
78+
}
79+
} else {
4780
ret.add(primitive);
4881
}
49-
} else {
50-
ret.add(primitive);
5182
}
83+
} finally {
84+
ConditionalOptionPaneUtil.endBulkOperation("add_primitive_to_relation");
5285
}
53-
ConditionalOptionPaneUtil.endBulkOperation("add_primitive_to_relation");
86+
5487
return ret;
5588
}
5689
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// License: GPL. For details, see LICENSE file.
2+
package org.openstreetmap.josm.gui.dialogs.relation.actions;
3+
4+
import static org.openstreetmap.josm.tools.I18n.tr;
5+
6+
import java.awt.event.ActionEvent;
7+
import java.util.List;
8+
9+
import org.openstreetmap.josm.data.osm.OsmPrimitive;
10+
import org.openstreetmap.josm.gui.dialogs.relation.GenericRelationEditor.AddAbortException;
11+
import org.openstreetmap.josm.tools.ImageProvider;
12+
import org.openstreetmap.josm.tools.Logging;
13+
14+
/**
15+
* Replace selected relation members with the objects selected in the current dataset
16+
* @since xxx
17+
*/
18+
public class ReplaceSelectedAction extends AddFromSelectionAction {
19+
20+
/**
21+
* Constructs a new {@code ReplaceSelectedAction}.
22+
* @param editorAccess An interface to access the relation editor contents.
23+
*/
24+
public ReplaceSelectedAction(IRelationEditorActionAccess editorAccess) {
25+
super(editorAccess, IRelationEditorUpdateOn.MEMBER_TABLE_SELECTION, IRelationEditorUpdateOn.SELECTION_TABLE_CHANGE);
26+
putValue(SHORT_DESCRIPTION, tr("Replace selected members with selected objects"));
27+
new ImageProvider("dialogs/relation", "replaceselectedright").getResource().attachImageIcon(this, true);
28+
updateEnabledState();
29+
}
30+
31+
@Override
32+
protected void updateEnabledState() {
33+
int numSelected = getSelectionTableModel().getRowCount();
34+
setEnabled(numSelected > 0 &&
35+
numSelected == getMemberTableModel().getSelectedIndices().length);
36+
}
37+
38+
@Override
39+
public void actionPerformed(ActionEvent e) {
40+
try {
41+
int[] selectedMemberIndices = getMemberTableModel().getSelectedIndices();
42+
List<OsmPrimitive> selection = getSelectionTableModel().getSelection();
43+
int numSelectedPrimitives = selection.size();
44+
if (numSelectedPrimitives != selectedMemberIndices.length) {
45+
return;
46+
}
47+
48+
List<OsmPrimitive> filteredSelection = filterConfirmedPrimitives(selection, true);
49+
50+
for (int i = 0; i < selectedMemberIndices.length; i++) {
51+
getMemberTableModel().updateMemberPrimitive(selectedMemberIndices[i], filteredSelection.get(i));
52+
}
53+
} catch (AddAbortException ex) {
54+
Logging.trace(ex);
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)