source: josm/trunk/src/org/openstreetmap/josm/actions/UnJoinNodeWayAction.java@ 17379

Last change on this file since 17379 was 17188, checked in by Klumbumbus, 4 years ago

fix #19851 - Fix shortcut names

  • Property svn:eol-style set to native
File size: 6.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trn;
7
8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.util.ArrayList;
11import java.util.Collection;
12import java.util.HashSet;
13import java.util.LinkedList;
14import java.util.List;
15import java.util.stream.Collectors;
16
17import javax.swing.JOptionPane;
18
19import org.openstreetmap.josm.command.RemoveNodesCommand;
20import org.openstreetmap.josm.data.UndoRedoHandler;
21import org.openstreetmap.josm.data.osm.DataSet;
22import org.openstreetmap.josm.data.osm.Node;
23import org.openstreetmap.josm.data.osm.OsmPrimitive;
24import org.openstreetmap.josm.data.osm.Way;
25import org.openstreetmap.josm.gui.Notification;
26import org.openstreetmap.josm.tools.Shortcut;
27
28/**
29 * Disconnect nodes from a way they currently belong to.
30 * @since 6253
31 */
32public class UnJoinNodeWayAction extends JosmAction {
33
34 /**
35 * Constructs a new {@code UnJoinNodeWayAction}.
36 */
37 public UnJoinNodeWayAction() {
38 super(tr("Disconnect Node from Way"), "unjoinnodeway",
39 tr("Disconnect nodes from a way they currently belong to"),
40 Shortcut.registerShortcut("tools:unjoinnodeway",
41 tr("Tools: {0}", tr("Disconnect Node from Way")), KeyEvent.VK_J, Shortcut.ALT), true);
42 setHelpId(ht("/Action/UnJoinNodeWay"));
43 }
44
45 /**
46 * Called when the action is executed.
47 */
48 @Override
49 public void actionPerformed(ActionEvent e) {
50
51 final DataSet dataSet = getLayerManager().getEditDataSet();
52 List<Node> selectedNodes = new ArrayList<>(dataSet.getSelectedNodes());
53 List<Way> selectedWays = new ArrayList<>(dataSet.getSelectedWays());
54
55 selectedNodes = cleanSelectedNodes(selectedWays, selectedNodes);
56
57 List<Way> applicableWays = getApplicableWays(selectedWays, selectedNodes);
58
59 if (applicableWays == null) {
60 notify(tr("Select at least one node to be disconnected."),
61 JOptionPane.WARNING_MESSAGE);
62 return;
63 } else if (applicableWays.isEmpty()) {
64 notify(trn("Selected node cannot be disconnected from anything.",
65 "Selected nodes cannot be disconnected from anything.",
66 selectedNodes.size()),
67 JOptionPane.WARNING_MESSAGE);
68 return;
69 } else if (applicableWays.size() > 1) {
70 notify(trn("There is more than one way using the node you selected. "
71 + "Please select the way also.",
72 "There is more than one way using the nodes you selected. "
73 + "Please select the way also.",
74 selectedNodes.size()),
75 JOptionPane.WARNING_MESSAGE);
76 return;
77 } else if (applicableWays.get(0).getRealNodesCount() < selectedNodes.size() + 2) {
78 // there is only one affected way, but removing the selected nodes would only leave it
79 // with less than 2 nodes
80 notify(trn("The affected way would disappear after disconnecting the "
81 + "selected node.",
82 "The affected way would disappear after disconnecting the "
83 + "selected nodes.",
84 selectedNodes.size()),
85 JOptionPane.WARNING_MESSAGE);
86 return;
87 }
88
89 // Finally, applicableWays contains only one perfect way
90 Way selectedWay = applicableWays.get(0);
91
92 // I'm sure there's a better way to handle this
93 UndoRedoHandler.getInstance().add(
94 new RemoveNodesCommand(selectedWay, new HashSet<>(selectedNodes)));
95 }
96
97 /**
98 * Send a notification message.
99 * @param msg Message to be sent.
100 * @param messageType Nature of the message.
101 */
102 public void notify(String msg, int messageType) {
103 new Notification(msg).setIcon(messageType).show();
104 }
105
106 /**
107 * Removes irrelevant nodes from user selection.
108 *
109 * The action can be performed reliably even if we remove :
110 * * Nodes not referenced by any ways
111 * * When only one way is selected, nodes not part of this way (#10396).
112 *
113 * @param selectedWays List of user selected way.
114 * @param selectedNodes List of user selected nodes.
115 * @return New list of nodes cleaned of irrelevant nodes.
116 */
117 private List<Node> cleanSelectedNodes(List<Way> selectedWays,
118 List<Node> selectedNodes) {
119
120 // List of node referenced by a route
121 List<Node> resultingNodes = selectedNodes.stream()
122 .filter(n -> n.isReferredByWays(1))
123 .collect(Collectors.toCollection(LinkedList::new));
124 // If exactly one selected way, remove node not referencing par this way.
125 if (selectedWays.size() == 1) {
126 Way w = selectedWays.get(0);
127 resultingNodes.removeIf(n -> !w.containsNode(n));
128 }
129 // Warn if nodes were removed
130 if (resultingNodes.size() != selectedNodes.size()) {
131 notify(tr("Some irrelevant nodes have been removed from the selection"),
132 JOptionPane.INFORMATION_MESSAGE);
133 }
134 return resultingNodes;
135 }
136
137 /**
138 * Find ways to which the disconnect can be applied. This is the list of ways
139 * with more than two nodes which pass through all the given nodes, intersected
140 * with the selected ways (if any)
141 * @param selectedWays List of user selected ways.
142 * @param selectedNodes List of user selected nodes.
143 * @return List of relevant ways
144 */
145 static List<Way> getApplicableWays(List<Way> selectedWays, List<Node> selectedNodes) {
146 if (selectedNodes.isEmpty())
147 return null;
148
149 // List of ways shared by all nodes
150 List<Way> result = new ArrayList<>(selectedNodes.get(0).getParentWays());
151 for (int i = 1; i < selectedNodes.size(); i++) {
152 List<Way> ref = selectedNodes.get(i).getParentWays();
153 result.removeIf(way -> !ref.contains(way));
154 }
155
156 // Remove broken ways
157 result.removeIf(way -> way.getNodesCount() <= 2);
158
159 if (selectedWays.isEmpty())
160 return result;
161 else {
162 // Return only selected ways
163 result.removeIf(way -> !selectedWays.contains(way));
164 return result;
165 }
166 }
167
168 @Override
169 protected void updateEnabledState() {
170 updateEnabledStateOnCurrentSelection();
171 }
172
173 @Override
174 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
175 updateEnabledStateOnModifiableSelection(selection);
176 }
177}
Note: See TracBrowser for help on using the repository browser.