| 70 | | private int initialMoveDelay = 200; |
| | 68 | private static int initialMoveDelay = 200; |
| | 69 | /** |
| | 70 | * For translation, a the initial EastNorths of node1 and node2 |
| | 71 | */ |
| | 72 | private EastNorth initialN1en; |
| | 73 | private EastNorth initialN2en; |
| | 74 | /** |
| | 75 | * This is to work around some deficiencies in MoveCommand when translating |
| | 76 | */ |
| | 77 | private double alreadyTranslatedX; |
| | 78 | private double alreadyTranslatedY; |
| 138 | | if (mode == Mode.EXTRUDE) { |
| 139 | | setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); |
| 140 | | } |
| 141 | | |
| 142 | | if (mousePos == null) { |
| 143 | | mousePos = e.getPoint(); |
| 144 | | return; |
| 145 | | } |
| 146 | | |
| 147 | | Main.map.mapView.repaint(); |
| 148 | | mousePos = e.getPoint(); |
| 149 | | |
| 150 | | } |
| 151 | | |
| 152 | | public void paint(Graphics g, MapView mv) { |
| 153 | | if (selectedSegment != null) { |
| 154 | | Node n1 = selectedSegment.way.getNode(selectedSegment.lowerIndex); |
| 155 | | Node n2 = selectedSegment.way.getNode(selectedSegment.lowerIndex + 1); |
| 156 | | |
| 157 | | EastNorth en1 = n1.getEastNorth(); |
| 158 | | EastNorth en2 = n2.getEastNorth(); |
| 159 | | EastNorth en3 = mv.getEastNorth(mousePos.x, mousePos.y); |
| 160 | | |
| | 147 | // calculate base - the point on the segment from which the distance to mouse pos is shortest |
| | 163 | Node n1 = selectedSegment.way.getNode(selectedSegment.lowerIndex); |
| | 164 | Node n2 = selectedSegment.way.getNode(selectedSegment.lowerIndex+1); |
| | 165 | |
| | 166 | if (mode == Mode.extrude) { |
| | 167 | // This doesn't seem to work so should it be here? |
| | 168 | setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); |
| | 169 | } else if (mode == Mode.translate) { |
| | 170 | Command c = !Main.main.undoRedo.commands.isEmpty() |
| | 171 | ? Main.main.undoRedo.commands.getLast() : null; |
| | 172 | if (c instanceof SequenceCommand) { |
| | 173 | c = ((SequenceCommand)c).getLastCommand(); |
| | 174 | } |
| | 175 | |
| | 176 | // Better way of testing list equality non-order-sensitively? |
| | 177 | if (c instanceof MoveCommand |
| | 178 | && ((MoveCommand)c).getMovedNodes().contains(n1) |
| | 179 | && ((MoveCommand)c).getMovedNodes().contains(n2) |
| | 180 | && ((MoveCommand)c).getMovedNodes().size() == 2) { |
| | 181 | // MoveCommand doesn't let us know how much it has already moved the selection |
| | 182 | // so we have to do some ugly record-keeping. |
| | 183 | double dx = xoff - alreadyTranslatedX; |
| | 184 | double dy = yoff - alreadyTranslatedY; |
| | 185 | ((MoveCommand)c).moveAgain(dx,dy); |
| | 186 | alreadyTranslatedX += dx; |
| | 187 | alreadyTranslatedY += dy; |
| | 188 | } else { |
| | 189 | Collection<OsmPrimitive> nodelist = new LinkedList<OsmPrimitive>(); |
| | 190 | nodelist.add(n1); |
| | 191 | nodelist.add(n2); |
| | 192 | Main.main.undoRedo.add(c = new MoveCommand(nodelist, xoff, yoff)); |
| | 193 | alreadyTranslatedX += xoff; |
| | 194 | alreadyTranslatedY += yoff; |
| | 195 | } |
| | 196 | } |
| | 197 | Main.map.mapView.repaint(); |
| | 198 | } |
| | 199 | } |
| | 200 | |
| | 201 | public void paint(Graphics g, MapView mv) { |
| | 202 | if (mode == Mode.select) { |
| | 203 | // Nothing to do |
| | 204 | } else { |
| 181 | | Point p1 = mv.getPoint(en1); |
| 182 | | Point p2 = mv.getPoint(en2); |
| 183 | | Point p3 = mv.getPoint(en1.add(xoff, yoff)); |
| 184 | | Point p4 = mv.getPoint(en2.add(xoff, yoff)); |
| | 209 | Point p1 = mv.getPoint(initialN1en); |
| | 210 | Point p2 = mv.getPoint(initialN2en); |
| | 211 | Point p3 = mv.getPoint(initialN1en.add(xoff, yoff)); |
| | 212 | Point p4 = mv.getPoint(initialN2en.add(xoff, yoff)); |
| 186 | | b.moveTo(p1.x, p1.y); b.lineTo(p3.x, p3.y); |
| 187 | | b.lineTo(p4.x, p4.y); b.lineTo(p2.x, p2.y); |
| 188 | | b.lineTo(p1.x, p1.y); |
| 189 | | g2.draw(b); |
| | 214 | if (mode == Mode.extrude) { |
| | 215 | b.moveTo(p1.x, p1.y); b.lineTo(p3.x, p3.y); |
| | 216 | b.lineTo(p4.x, p4.y); b.lineTo(p2.x, p2.y); |
| | 217 | b.lineTo(p1.x, p1.y); |
| | 218 | g2.draw(b); |
| | 219 | g2.setStroke(new BasicStroke(1)); |
| | 220 | } else if (mode == Mode.translate) { |
| | 221 | Line2D newline = new Line2D.Double(p3, p4); |
| | 222 | g2.draw(newline); |
| | 223 | g2.setStroke(new BasicStroke(2)); |
| | 224 | Line2D oldline = new Line2D.Double(p1, p2); |
| | 225 | g2.draw(oldline); |
| | 226 | } |
| | 227 | |
| 208 | | selectedSegment = |
| 209 | | Main.map.mapView.getNearestWaySegment(e.getPoint()); |
| | 248 | if (selectedSegment == null) { |
| | 249 | // If nothing gets caught, stay in select mode |
| | 250 | } else { |
| | 251 | // Otherwise switch to another mode |
| | 252 | if ( (e.getModifiers() & ActionEvent.CTRL_MASK) != 0 ) { |
| | 253 | mode = Mode.translate; |
| | 254 | alreadyTranslatedX = 0.0; |
| | 255 | alreadyTranslatedY = 0.0; |
| | 256 | } else { |
| | 257 | mode = Mode.extrude; |
| | 258 | getCurrentDataSet().setSelected(selectedSegment.way); |
| | 259 | } |
| 211 | | mode = (selectedSegment == null) ? Mode.select : Mode.EXTRUDE; |
| 212 | | oldCursor = Main.map.mapView.getCursor(); |
| | 261 | // For extrusion, these positions are actually never changed, |
| | 262 | // but keeping note of this anyway allows us to not continually |
| | 263 | // look it up and also allows us to unify code with the translate mode |
| | 264 | initialN1en = selectedSegment.way.getNode(selectedSegment.lowerIndex).getEastNorth(); |
| | 265 | initialN2en = selectedSegment.way.getNode(selectedSegment.lowerIndex + 1).getEastNorth(); |
| 232 | | restoreCursor(); |
| 233 | | if (selectedSegment == null) return; |
| 234 | | if (mousePos.distance(initialMousePos) > 10) { |
| 235 | | Node n1 = selectedSegment.way.getNode(selectedSegment.lowerIndex); |
| 236 | | Node n2 = selectedSegment.way.getNode(selectedSegment.lowerIndex+1); |
| 237 | | EastNorth en3 = n2.getEastNorth().add(xoff, yoff); |
| 238 | | Node n3 = new Node(Main.proj.eastNorth2latlon(en3)); |
| 239 | | EastNorth en4 = n1.getEastNorth().add(xoff, yoff); |
| 240 | | Node n4 = new Node(Main.proj.eastNorth2latlon(en4)); |
| 241 | | Way wnew = new Way(selectedSegment.way); |
| 242 | | wnew.addNode(selectedSegment.lowerIndex+1, n3); |
| 243 | | wnew.addNode(selectedSegment.lowerIndex+1, n4); |
| 244 | | if (wnew.getNodesCount() == 4) { |
| 245 | | wnew.addNode(n1); |
| | 291 | |
| | 292 | if (mode == mode.select) { |
| | 293 | // Nothing to be done |
| | 294 | } else { |
| | 295 | if (mode == mode.extrude) { |
| | 296 | if (e.getPoint().distance(initialMousePos) > 10) { |
| | 297 | // Commit extrusion |
| | 298 | |
| | 299 | Node n1 = selectedSegment.way.getNode(selectedSegment.lowerIndex); |
| | 300 | Node n2 = selectedSegment.way.getNode(selectedSegment.lowerIndex+1); |
| | 301 | EastNorth en3 = n2.getEastNorth().add(xoff, yoff); |
| | 302 | Node n3 = new Node(Main.proj.eastNorth2latlon(en3)); |
| | 303 | EastNorth en4 = n1.getEastNorth().add(xoff, yoff); |
| | 304 | Node n4 = new Node(Main.proj.eastNorth2latlon(en4)); |
| | 305 | Way wnew = new Way(selectedSegment.way); |
| | 306 | wnew.addNode(selectedSegment.lowerIndex+1, n3); |
| | 307 | wnew.addNode(selectedSegment.lowerIndex+1, n4); |
| | 308 | if (wnew.getNodesCount() == 4) { |
| | 309 | wnew.addNode(n1); |
| | 310 | } |
| | 311 | Collection<Command> cmds = new LinkedList<Command>(); |
| | 312 | cmds.add(new AddCommand(n4)); |
| | 313 | cmds.add(new AddCommand(n3)); |
| | 314 | cmds.add(new ChangeCommand(selectedSegment.way, wnew)); |
| | 315 | Command c = new SequenceCommand(tr("Extrude Way"), cmds); |
| | 316 | Main.main.undoRedo.add(c); |
| | 317 | } |
| | 318 | } else if (mode == mode.translate) { |
| | 319 | // I don't think there's anything to do |
| 247 | | Collection<Command> cmds = new LinkedList<Command>(); |
| 248 | | cmds.add(new AddCommand(n4)); |
| 249 | | cmds.add(new AddCommand(n3)); |
| 250 | | cmds.add(new ChangeCommand(selectedSegment.way, wnew)); |
| 251 | | Command c = new SequenceCommand(tr("Extrude Way"), cmds); |
| 252 | | Main.main.undoRedo.add(c); |
| | 321 | |
| | 322 | // Switch back into select mode |
| | 323 | restoreCursor(); |
| | 324 | Main.map.mapView.removeTemporaryLayer(this); |
| | 325 | selectedSegment = null; |
| | 326 | mode = Mode.select; |
| | 327 | |
| | 328 | updateStatusLine(); |
| | 329 | Main.map.mapView.repaint(); |