Skip to content

Commit 0eae26d

Browse files
committed
Add 'replace selected' action to relation editor
1 parent 4bfe2b9 commit 0eae26d

File tree

5 files changed

+246
-13
lines changed

5 files changed

+246
-13
lines changed
Lines changed: 105 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
@@ -86,6 +86,7 @@
8686
import org.openstreetmap.josm.gui.dialogs.relation.actions.RefreshAction;
8787
import org.openstreetmap.josm.gui.dialogs.relation.actions.RemoveAction;
8888
import org.openstreetmap.josm.gui.dialogs.relation.actions.RemoveSelectedAction;
89+
import org.openstreetmap.josm.gui.dialogs.relation.actions.ReplaceSelectedAction;
8990
import org.openstreetmap.josm.gui.dialogs.relation.actions.ReverseAction;
9091
import org.openstreetmap.josm.gui.dialogs.relation.actions.SelectAction;
9192
import org.openstreetmap.josm.gui.dialogs.relation.actions.SelectPrimitivesForSelectedMembersAction;
@@ -703,10 +704,13 @@ protected static JToolBar buildSelectionControlButtonToolbar(IRelationEditorActi
703704
new AddSelectedAtEndAction(editorAccess)
704705
));
705706
groups.add(buildNativeGroup(20,
707+
new ReplaceSelectedAction(editorAccess)
708+
));
709+
groups.add(buildNativeGroup(30,
706710
new SelectedMembersForSelectionAction(editorAccess),
707711
new SelectPrimitivesForSelectedMembersAction(editorAccess)
708712
));
709-
groups.add(buildNativeGroup(30,
713+
groups.add(buildNativeGroup(40,
710714
new RemoveSelectedAction(editorAccess)
711715
));
712716
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
@@ -505,6 +505,42 @@ public void updateRole(int[] idx, String role) {
505505
addToSelectedMembers(selected);
506506
}
507507

508+
/**
509+
* updates the referenced primitive of the members given by the index in <code>index</code>
510+
*
511+
* @param index the index to update
512+
* @param newPrimitive the new primitive
513+
* @since xxx
514+
*/
515+
public void updateMemberPrimitive(int index, OsmPrimitive newPrimitive) {
516+
if (index >= members.size()) {
517+
return;
518+
}
519+
520+
RelationMember newMember = new RelationMember(members.get(index).getRole(), newPrimitive);
521+
updateMember(index, newMember);
522+
}
523+
524+
/**
525+
* replace the member at <code>index</code> with a new one
526+
*
527+
* @param index the index to update
528+
* @param newMember the new member
529+
* @since xxx
530+
*/
531+
public void updateMember(int index, RelationMember newMember) {
532+
if (index >= members.size()) {
533+
return;
534+
}
535+
536+
RelationMember oldMember = members.get(index);
537+
if (oldMember.equals(newMember))
538+
return;
539+
540+
setValue(index, newMember);
541+
fireTableDataChanged();
542+
}
543+
508544
/**
509545
* Get the currently selected relation members
510546
*

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

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,59 @@ 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 cause a relation loop, abort (throw {@code AddAbortException})
50+
* @return The primitives to add to the relation. Never {@code null}, but may be an empty list.
51+
* @throws AddAbortException when a relation loop is detected or {@code abortOnSkip} is {@code true} <i>and</i> the user decides to not add a primitive.
52+
* @since xxx
53+
*/
54+
protected List<OsmPrimitive> filterConfirmedPrimitives(List<OsmPrimitive> primitives, boolean abortOnSkip) throws AddAbortException {
3355
if (Utils.isEmpty(primitives))
3456
return primitives;
3557
List<OsmPrimitive> ret = new ArrayList<>();
3658
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;
59+
try {
60+
for (OsmPrimitive primitive : primitives) {
61+
if (primitive instanceof Relation) {
62+
List<Relation> loop = RelationChecker.checkAddMember(editorAccess.getEditor().getRelation(), (Relation) primitive);
63+
if (!loop.isEmpty() && loop.get(0).equals(loop.get(loop.size() - 1))) {
64+
GenericRelationEditor.warnOfCircularReferences(primitive, loop);
65+
if (abortOnSkip) {
66+
throw new AddAbortException();
67+
}
68+
continue;
69+
}
4370
}
44-
}
45-
if (isPotentialDuplicate(primitive)) {
46-
if (GenericRelationEditor.confirmAddingPrimitive(primitive)) {
71+
if (isPotentialDuplicate(primitive)) {
72+
if (GenericRelationEditor.confirmAddingPrimitive(primitive)) {
73+
ret.add(primitive);
74+
} else if (abortOnSkip) {
75+
throw new AddAbortException();
76+
}
77+
} else {
4778
ret.add(primitive);
4879
}
49-
} else {
50-
ret.add(primitive);
5180
}
81+
} finally {
82+
ConditionalOptionPaneUtil.endBulkOperation("add_primitive_to_relation");
5283
}
53-
ConditionalOptionPaneUtil.endBulkOperation("add_primitive_to_relation");
84+
5485
return ret;
5586
}
5687
}
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 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)