| 61 | | if (!checkSelection(selection)) { |
| 62 | | JOptionPane.showMessageDialog(Main.parent, tr("The current selection cannot be used for unglueing.")); |
| 63 | | return; |
| 64 | | } |
| 65 | | |
| 66 | | int count = 0; |
| 67 | | for (Way w : Main.ds.ways) { |
| 68 | | if (w.deleted || w.incomplete || w.nodes.size() < 1) continue; |
| 69 | | if (!w.nodes.contains(selectedNode)) continue; |
| 70 | | count++; |
| 71 | | } |
| 72 | | if (count < 2) { |
| 73 | | JOptionPane.showMessageDialog(Main.parent, tr("You must select a node that is used by at least 2 ways.")); |
| 74 | | return; |
| | 62 | if (checkSelection(selection)) { |
| | 63 | int count = 0; |
| | 64 | for (Way w : Main.ds.ways) { |
| | 65 | if (w.deleted || w.incomplete || w.nodes.size() < 1) continue; |
| | 66 | if (!w.nodes.contains(selectedNode)) continue; |
| | 67 | count++; |
| | 68 | } |
| | 69 | if (count < 2) { |
| | 70 | JOptionPane.showMessageDialog(Main.parent, tr("This node is not glued to anything else.")); |
| | 71 | } else { |
| | 72 | // and then do the work. |
| | 73 | unglueWays(); |
| | 74 | } |
| | 75 | } else if (checkSelection2(selection)) { |
| | 76 | ArrayList<Node> tmpNodes = new ArrayList<Node>(); |
| | 77 | for (Node n : selectedNodes) { |
| | 78 | int count = 0; |
| | 79 | for (Way w : Main.ds.ways) { |
| | 80 | if (w.deleted || w.incomplete || w.nodes.size() < 1) continue; |
| | 81 | if (!w.nodes.contains(n)) continue; |
| | 82 | count++; |
| | 83 | } |
| | 84 | if (count >= 2) { |
| | 85 | tmpNodes.add(n); |
| | 86 | } |
| | 87 | } |
| | 88 | if (tmpNodes.size() < 1) { |
| | 89 | if (selection.size() > 1) { |
| | 90 | JOptionPane.showMessageDialog(Main.parent, tr("None of these nodes is glued to anything else.")); |
| | 91 | } else { |
| | 92 | JOptionPane.showMessageDialog(Main.parent, tr("None of this way's nodes is glued to anything else.")); |
| | 93 | } |
| | 94 | } else { |
| | 95 | // and then do the work. |
| | 96 | selectedNodes = tmpNodes; |
| | 97 | unglueWays2(); |
| | 98 | } |
| | 99 | } else { |
| | 100 | JOptionPane.showMessageDialog(Main.parent, |
| | 101 | tr("The current selection cannot be used for unglueing.")+"\n"+ |
| | 102 | "\n"+ |
| | 103 | tr("Select either:")+"\n"+ |
| | 104 | tr("* One node that is used by more than one way, or")+"\n"+ |
| | 105 | tr("* One node that is used by more than one way and one of those ways, or")+"\n"+ |
| | 106 | tr("* One way that has one or more nodes that are used by more than one way, or")+"\n"+ |
| | 107 | tr("* One way and one or more of its nodes that are used by more than one way.")+"\n"+ |
| | 108 | "\n"+ |
| | 109 | tr("Note: If a way is selected, this way will get fresh copies of the unglued\n"+ |
| | 110 | "nodes and the new nodes will be selected. Otherwise, all ways will get their\n"+ |
| | 111 | "own copy and all nodes will be selected.") |
| | 112 | ); |
| 112 | | private boolean modifyWay(boolean firstway, Way w, List<Command> cmds, |
| 113 | | List<Node> newNodes) { |
| | 159 | /** |
| | 160 | * Checks if the selection consists of something we can work with. |
| | 161 | * Checks only if the number and type of items selected looks good; |
| | 162 | * does not check whether the selected items are really a valid |
| | 163 | * input for splitting (this would be too expensive to be carried |
| | 164 | * out from the selectionChanged listener). |
| | 165 | * |
| | 166 | * Returns true if one way and any number of nodes that are part of |
| | 167 | * that way are selected. Note: "any" can be none, then all nodes of |
| | 168 | * the way are used. |
| | 169 | * |
| | 170 | * The way will be put into the object variable "selectedWay", the |
| | 171 | * nodes into "selectedNodes". |
| | 172 | */ |
| | 173 | private boolean checkSelection2(Collection<? extends OsmPrimitive> selection) { |
| | 174 | if (selection.size() < 1) |
| | 175 | return false; |
| | 176 | |
| | 177 | selectedWay = null; |
| | 178 | for (OsmPrimitive p : selection) { |
| | 179 | if (p instanceof Way) { |
| | 180 | if (selectedWay != null) { |
| | 181 | return false; |
| | 182 | } |
| | 183 | selectedWay = (Way) p; |
| | 184 | } |
| | 185 | } |
| | 186 | if (selectedWay == null) { |
| | 187 | return false; |
| | 188 | } |
| | 189 | |
| | 190 | selectedNodes = new ArrayList<Node>(); |
| | 191 | for (OsmPrimitive p : selection) { |
| | 192 | if (p instanceof Node) { |
| | 193 | Node n = (Node) p; |
| | 194 | if (!selectedWay.nodes.contains(n)) { |
| | 195 | return false; |
| | 196 | } |
| | 197 | selectedNodes.add(n); |
| | 198 | } |
| | 199 | } |
| | 200 | |
| | 201 | if (selectedNodes.size() < 1) { |
| | 202 | selectedNodes.addAll(selectedWay.nodes); |
| | 203 | } |
| | 204 | |
| | 205 | return true; |
| | 206 | } |
| | 207 | |
| | 208 | /** |
| | 209 | * dupe the given node of the given way |
| | 210 | * |
| | 211 | * -> the new node will be put into the parameter newNodes. |
| | 212 | * -> the add-node command will be put into the parameter cmds. |
| | 213 | * -> the changed way will be returned and must be put into cmds by the caller! |
| | 214 | */ |
| | 215 | private Way modifyWay(Node originalNode, Way w, List<Command> cmds, List<Node> newNodes) { |
| 116 | | if (selectedNode == pushNode) { |
| 117 | | if (firstway) { |
| 118 | | // reuse the old node for the first (==a random) way |
| 119 | | firstway = false; |
| 120 | | } else { |
| 121 | | // clone the node for all other ways |
| 122 | | pushNode = new Node(selectedNode); |
| 123 | | pushNode.id = 0; |
| 124 | | newNodes.add(pushNode); |
| 125 | | cmds.add(new AddCommand(pushNode)); |
| 126 | | } |
| | 218 | if (originalNode == pushNode) { |
| | 219 | // clone the node for all other ways |
| | 220 | pushNode = new Node(pushNode); |
| | 221 | pushNode.id = 0; |
| | 222 | newNodes.add(pushNode); |
| | 223 | cmds.add(new AddCommand(pushNode)); |
| 141 | | private void unglueWays() { |
| 142 | | |
| 143 | | LinkedList<Command> cmds = new LinkedList<Command>(); |
| 144 | | List<Node> newNodes = new LinkedList<Node>(); |
| 145 | | |
| 146 | | if (selectedWay == null) { |
| 147 | | |
| 148 | | boolean firstway = true; |
| 149 | | // modify all ways containing the nodes |
| 150 | | for (Way w : Main.ds.ways) { |
| 151 | | if (w.deleted || w.incomplete || w.nodes.size() < 1) continue; |
| 152 | | if (!w.nodes.contains(selectedNode)) continue; |
| 153 | | |
| 154 | | firstway = modifyWay(firstway, w, cmds, newNodes); |
| 155 | | } |
| 156 | | } else { |
| 157 | | modifyWay(false, selectedWay, cmds, newNodes); |
| 158 | | } |
| 159 | | |
| | 237 | private void fixRelations(Node originalNode, List<Command> cmds, List<Node> newNodes) { |
| | 274 | /** |
| | 275 | * dupe a single node into as many nodes as there are ways using it, OR |
| | 276 | * |
| | 277 | * dupe a single node once, and put the copy on the selected way |
| | 278 | */ |
| | 279 | private void unglueWays() { |
| | 280 | LinkedList<Command> cmds = new LinkedList<Command>(); |
| | 281 | List<Node> newNodes = new LinkedList<Node>(); |
| | 282 | |
| | 283 | if (selectedWay == null) { |
| | 284 | boolean firstway = true; |
| | 285 | // modify all ways containing the nodes |
| | 286 | for (Way w : Main.ds.ways) { |
| | 287 | if (w.deleted || w.incomplete || w.nodes.size() < 1) continue; |
| | 288 | if (!w.nodes.contains(selectedNode)) continue; |
| | 289 | if (!firstway) cmds.add(new ChangeCommand(w, modifyWay(selectedNode, w, cmds, newNodes))); |
| | 290 | firstway = false; |
| | 291 | } |
| | 292 | } else { |
| | 293 | cmds.add(new ChangeCommand(selectedWay, modifyWay(selectedNode, selectedWay, cmds, newNodes))); |
| | 294 | } |
| | 295 | |
| | 296 | fixRelations(selectedNode, cmds, newNodes); |
| | 297 | |
| | 298 | Main.main.undoRedo.add(new SequenceCommand(tr("Dupe into {0} nodes", newNodes.size()+1), cmds)); |
| | 299 | if (selectedWay == null) { // if a node has been selected, new selection is ALL nodes |
| | 300 | newNodes.add(selectedNode); |
| | 301 | } // if a node and a way has been selected, new selection is only the new node that was added to the selected way |
| | 302 | Main.ds.setSelected(newNodes); |
| 203 | | public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) { |
| 204 | | setEnabled(checkSelection(newSelection)); |
| | 309 | private void unglueWays2() { |
| | 310 | LinkedList<Command> cmds = new LinkedList<Command>(); |
| | 311 | List<Node> allNewNodes = new LinkedList<Node>(); |
| | 312 | Way tmpWay = selectedWay; |
| | 313 | |
| | 314 | for (Node n : selectedNodes) { |
| | 315 | List<Node> newNodes = new LinkedList<Node>(); |
| | 316 | tmpWay = modifyWay(n, tmpWay, cmds, newNodes); |
| | 317 | fixRelations(n, cmds, newNodes); |
| | 318 | allNewNodes.addAll(newNodes); |
| | 319 | } |
| | 320 | cmds.add(new ChangeCommand(selectedWay, tmpWay)); // only one changeCommand for a way, else garbage will happen |
| | 321 | |
| | 322 | Main.main.undoRedo.add(new SequenceCommand(tr("Dupe {0} nodes into {1} nodes", selectedNodes.size(), selectedNodes.size()+allNewNodes.size()), cmds)); |
| | 323 | Main.ds.setSelected(allNewNodes); |