// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.utilsplugin2.actions;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.JOptionPane;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.JosmAction;
import org.openstreetmap.josm.actions.SplitWayAction;
import org.openstreetmap.josm.command.Command;
import org.openstreetmap.josm.command.SequenceCommand;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.gui.Notification;
import org.openstreetmap.josm.tools.Shortcut;
/**
* Splits selected ways on T-intersections. Target points should belong only to one way (except selected one),
* or two selected ways.
*
* @author Zverik
*/
public class SplitOnIntersectionsAction extends JosmAction {
private static final String TITLE = tr("Split adjacent ways");
public SplitOnIntersectionsAction() {
super(TITLE, "dumbutils/splitonintersections", tr("Split adjacent ways on T-intersections"),
Shortcut.registerShortcut("tools:splitonintersections", tr("Tool: {0}", tr("Split adjacent ways")),
KeyEvent.VK_P, Shortcut.ALT_CTRL_SHIFT), true);
}
@Override
public void actionPerformed(ActionEvent e) {
List<Command> list = new ArrayList<>();
List<Way> selectedWays = OsmPrimitive.getFilteredList(getLayerManager().getEditDataSet().getSelected(), Way.class);
Map<Way, List<Node>> splitWays = new HashMap<>();
for (Way way : selectedWays) {
if (way.getNodesCount() > 1 && !way.hasIncompleteNodes() && !way.isClosed())
for (Node node : new Node[] {way.getNode(0), way.getNode(way.getNodesCount() - 1)}) {
List<Way> refs = OsmPrimitive.getFilteredList(node.getReferrers(), Way.class);
refs.remove(way);
if (selectedWays.size() > 1) {
// When several ways are selected, split only those among selected
Iterator<Way> it = refs.iterator();
while (it.hasNext()) {
if (!selectedWays.contains(it.next()))
it.remove();
}
}
Iterator<Way> it = refs.iterator();
while (it.hasNext()) {
Way w = it.next();
if (w.isDeleted() || w.isIncomplete() || !w.isInnerNode(node))
it.remove();
}
if (refs.size() == 1) {
if (splitWays.containsKey(refs.get(0)))
splitWays.get(refs.get(0)).add(node);
else {
List<Node> nodes = new ArrayList<>(1);
nodes.add(node);
splitWays.put(refs.get(0), nodes);
}
} else if (refs.size() > 1) {
new Notification(
tr("There are several ways containing one of the splitting nodes. Select ways participating in this operation.")
).setIcon(JOptionPane.WARNING_MESSAGE).show();
return;
}
}
}
for (Way splitWay : splitWays.keySet()) {
List<List<Node>> wayChunks = SplitWayAction.buildSplitChunks(splitWay, splitWays.get(splitWay));
if (wayChunks != null) {
List<OsmPrimitive> sel = new ArrayList<>(selectedWays.size());
sel.addAll(selectedWays);
SplitWayAction.SplitWayResult result = SplitWayAction.splitWay(getLayerManager().getEditLayer(), splitWay, wayChunks, sel);
list.add(result.getCommand());
}
}
if (!list.isEmpty()) {
Main.main.undoRedo.add(list.size() == 1 ? list.get(0) : new SequenceCommand(TITLE, list));
getLayerManager().getEditDataSet().clearSelection();
}
}
@Override
protected void updateEnabledState() {
updateEnabledStateOnCurrentSelection();
}
@Override
protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
boolean ok = false;
if (selection != null)
for (OsmPrimitive p : selection) {
if (p instanceof Way)
ok = true;
else {
ok = false;
break;
}
}
setEnabled(ok);
}
}