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

Last change on this file since 15652 was 15013, checked in by Don-vip, 5 years ago

remove duplicated code

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