diff --git a/images/cursor/modifier/rope.png b/images/cursor/modifier/rope.png
new file mode 100644
index 0000000000000000000000000000000000000000..e46cc6e3fe772414beed9777143991b652f95506
GIT binary patch
literal 955
zcmbu7J!@295QWbg#SmCc3K1<NY!qw)!Vplgh`K=oF^2s>JB`Jl1Qk(P1qF#jRwNKC
zgppK!G%MPPMH+3xpf*Z~Y+)mUupm}iIG(wG!3(>WVcz%5bI#oRGt<Y)13L!*lqZi@
zYkUvpufLD~dq=m{fj-PkH6}_xghyC}Mo0v*au2s~4VQ3a(>%<=G)%&fXVpV3R6`{c
zc~v~bLNr7|K&5~OET91iu%I@jsm04YjhvH@xvRUlBge8bb5l2QLsGD*=BlpZiiF}>
zF&A|a7m$%x9p+GnI5?Hm6eBb#iNziVQ=8J%;$@_vtof*!m?8afEGt!0F-6)X1)HKK
zVgkA+6weyeAO_lF9>nBr#zFstphHqqjL@XyQF3rFwJA+4WOCVN%|}#`LDC<`vJz1N
zbEREUu&EFQb7ayCfLuJzpy`%TG7n<%Hsc@@4bvg1DMo1CBo;Y1nA(&^t|(8l&6*Fm
zF$PJ09Lq}hp%h<3+AS8$jpja!B_&jmd#<;LG8v0>a@&RBL@qq!@(ZkVP)wpUwYVjQ
zM^8PV3#<SgpbfNuCQt<`zz{M1quuNEy4~)|%1WoxX}8<0R;$@;R;$%Yr7|>>+Nbt!
zT;;2Dtu|f9__sCU;KF3}aO1}M^`$S{-VXO4o!z8Y?``?CV|j7g`3<N4)Ia=uH#XQ<
z7}+;=^7X>(mD{Cr+vlD%&b*o5HGbgI(>>3ZPSl1UJX~Af-8?w>a<s2D^8Q)h_vO#!
rk1rPMbGIJ<F8z3PdG+SkJAdzPuKgM-_fH+V$f1~=n6AD$a(4b7HS(J{
literal 0
HcmV?d00001
diff --git a/images/mapmode/rope.png b/images/mapmode/rope.png
new file mode 100644
index 0000000000000000000000000000000000000000..1fb5fdd140ad604ab89abd73fc9e1b2246c691e4
GIT binary patch
literal 1544
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
literal 0
HcmV?d00001
diff --git a/src/org/openstreetmap/josm/actions/LassoModeAction.java b/src/org/openstreetmap/josm/actions/LassoModeAction.java
new file mode 100644
index 0000000..fa6de28
-
|
+
|
|
| 1 | // License: GPL. For details, see LICENSE file. |
| 2 | package org.openstreetmap.josm.actions; |
| 3 | |
| 4 | import static org.openstreetmap.josm.tools.I18n.tr; |
| 5 | |
| 6 | import org.openstreetmap.josm.Main; |
| 7 | import org.openstreetmap.josm.actions.mapmode.MapMode; |
| 8 | |
| 9 | public class LassoModeAction extends MapMode { |
| 10 | |
| 11 | public LassoModeAction() { |
| 12 | super(tr("Lasso Mode"), |
| 13 | "rope", |
| 14 | tr("Toggle Lasso Mode (in contrast to Rectangle Mode)"), |
| 15 | null, |
| 16 | null); |
| 17 | } |
| 18 | |
| 19 | @Override |
| 20 | public void enterMode() { |
| 21 | super.enterMode(); |
| 22 | if (Main.map != null) { |
| 23 | Main.map.mapModeSelect.setLassoMode(true); |
| 24 | Main.map.mapModeSelect.enterMode(); |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | @Override |
| 29 | public void exitMode() { |
| 30 | super.exitMode(); |
| 31 | Main.map.mapModeSelect.setLassoMode(false); |
| 32 | Main.map.mapModeSelect.exitMode(); |
| 33 | } |
| 34 | } |
diff --git a/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java b/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
index ae2b496..cfe32f0 100644
a
|
b
|
public class SelectAction extends MapMode implements AWTEventListener, Selection
|
83 | 83 | scale("scale", null), |
84 | 84 | rotate("rotate", null), |
85 | 85 | merge("crosshair", null), |
| 86 | lasso("normal", "rope"), |
86 | 87 | merge_to_node("crosshair", "joinnode"), |
87 | 88 | move(Cursor.MOVE_CURSOR); |
88 | 89 | |
… |
… |
public class SelectAction extends MapMode implements AWTEventListener, Selection
|
98 | 99 | } |
99 | 100 | } |
100 | 101 | |
| 102 | private boolean lassoMode = false; |
| 103 | |
101 | 104 | // Cache previous mouse event (needed when only the modifier keys are |
102 | 105 | // pressed but the mouse isn't moved) |
103 | 106 | private MouseEvent oldEvent = null; |
… |
… |
public class SelectAction extends MapMode implements AWTEventListener, Selection
|
171 | 174 | super.enterMode(); |
172 | 175 | mv.addMouseListener(this); |
173 | 176 | mv.addMouseMotionListener(this); |
174 | | mv.setVirtualNodesEnabled( |
175 | | Main.pref.getInteger("mappaint.node.virtual-size", 8) != 0); |
| 177 | mv.setVirtualNodesEnabled(Main.pref.getInteger("mappaint.node.virtual-size", 8) != 0); |
176 | 178 | drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true); |
177 | 179 | // This is required to update the cursors when ctrl/shift/alt is pressed |
178 | 180 | try { |
… |
… |
public class SelectAction extends MapMode implements AWTEventListener, Selection
|
240 | 242 | c = "scale"; |
241 | 243 | break; |
242 | 244 | case select: |
243 | | c = "rect" + (shift ? "_add" : (ctrl ? "_rm" : "")); |
| 245 | if (lassoMode) { |
| 246 | c = "lasso"; |
| 247 | } else { |
| 248 | c = "rect" + (shift ? "_add" : (ctrl ? "_rm" : "")); |
| 249 | } |
244 | 250 | break; |
245 | 251 | } |
246 | 252 | return SelectActionCursor.valueOf(c).cursor(); |
… |
… |
public class SelectAction extends MapMode implements AWTEventListener, Selection
|
726 | 732 | break; |
727 | 733 | case select: |
728 | 734 | default: |
729 | | selectionManager.register(mv); |
| 735 | selectionManager.register(mv, lassoMode); |
730 | 736 | selectionManager.mousePressed(e); |
731 | 737 | break; |
732 | 738 | } |
… |
… |
public class SelectAction extends MapMode implements AWTEventListener, Selection
|
824 | 830 | |
825 | 831 | public void selectionEnded(Rectangle r, MouseEvent e) { |
826 | 832 | updateKeyModifiers(e); |
827 | | selectPrims(selectionManager.getObjectsInRectangle(r, alt), e, true, true); |
| 833 | mv.repaint(); |
| 834 | selectPrims(selectionManager.getSelectedObjects(alt), e, true, true); |
828 | 835 | } |
829 | 836 | |
830 | 837 | /** |
… |
… |
public class SelectAction extends MapMode implements AWTEventListener, Selection
|
973 | 980 | public boolean layerIsSupported(Layer l) { |
974 | 981 | return l instanceof OsmDataLayer; |
975 | 982 | } |
| 983 | |
| 984 | public void setLassoMode(boolean lassoMode) { |
| 985 | System.out.println(lassoMode); |
| 986 | this.selectionManager.setLassoMode(lassoMode); |
| 987 | this.lassoMode = lassoMode; |
| 988 | } |
976 | 989 | } |
diff --git a/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java b/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
index 942ef20..e62dd29 100644
a
|
b
|
public class ZoomAction extends MapMode implements SelectionEnded {
|
59 | 59 | |
60 | 60 | @Override public void enterMode() { |
61 | 61 | super.enterMode(); |
62 | | selectionManager.register(Main.map.mapView); |
| 62 | selectionManager.register(Main.map.mapView, false); |
63 | 63 | } |
64 | 64 | |
65 | 65 | @Override public void exitMode() { |
diff --git a/src/org/openstreetmap/josm/gui/MapFrame.java b/src/org/openstreetmap/josm/gui/MapFrame.java
index 70dd5c5..95add75 100644
a
|
b
|
import javax.swing.plaf.basic.BasicSplitPaneDivider;
|
40 | 40 | import javax.swing.plaf.basic.BasicSplitPaneUI; |
41 | 41 | |
42 | 42 | import org.openstreetmap.josm.Main; |
| 43 | import org.openstreetmap.josm.actions.LassoModeAction; |
43 | 44 | import org.openstreetmap.josm.actions.mapmode.DeleteAction; |
44 | 45 | import org.openstreetmap.josm.actions.mapmode.DrawAction; |
45 | 46 | import org.openstreetmap.josm.actions.mapmode.ExtrudeAction; |
… |
… |
public class MapFrame extends JPanel implements Destroyable, LayerChangeListener
|
108 | 109 | public PropertiesDialog propertiesDialog; |
109 | 110 | |
110 | 111 | // Map modes |
111 | | private final MapMode mapModeSelect; |
| 112 | public final SelectAction mapModeSelect; |
112 | 113 | private final MapMode mapModeDraw; |
113 | 114 | private final MapMode mapModeZoom; |
114 | 115 | |
… |
… |
public class MapFrame extends JPanel implements Destroyable, LayerChangeListener
|
158 | 159 | // toolbar |
159 | 160 | toolBarActions.setFloatable(false); |
160 | 161 | addMapMode(new IconToggleButton(mapModeSelect = new SelectAction(this))); |
| 162 | addMapMode(new IconToggleButton(new LassoModeAction(), true)); |
161 | 163 | addMapMode(new IconToggleButton(mapModeDraw = new DrawAction(this))); |
162 | 164 | addMapMode(new IconToggleButton(mapModeZoom = new ZoomAction(this))); |
163 | 165 | addMapMode(new IconToggleButton(new DeleteAction(this), true)); |
diff --git a/src/org/openstreetmap/josm/gui/SelectionManager.java b/src/org/openstreetmap/josm/gui/SelectionManager.java
index 305d306..5c14f01 100644
a
|
b
|
import java.awt.Color;
|
5 | 5 | import java.awt.Component; |
6 | 6 | import java.awt.Graphics; |
7 | 7 | import java.awt.Point; |
| 8 | import java.awt.Polygon; |
8 | 9 | import java.awt.Rectangle; |
9 | 10 | import java.awt.event.InputEvent; |
10 | 11 | import java.awt.event.MouseEvent; |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
96 | 97 | */ |
97 | 98 | private boolean aspectRatio; |
98 | 99 | |
| 100 | private boolean lassoMode; |
| 101 | private Polygon lasso = new Polygon(); |
| 102 | |
99 | 103 | /** |
100 | 104 | * Create a new SelectionManager. |
101 | 105 | * |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
115 | 119 | * Register itself at the given event source. |
116 | 120 | * @param eventSource The emitter of the mouse events. |
117 | 121 | */ |
118 | | public void register(NavigatableComponent eventSource) { |
| 122 | public void register(NavigatableComponent eventSource, boolean lassoMode) { |
| 123 | this.lassoMode = lassoMode; |
119 | 124 | eventSource.addMouseListener(this); |
120 | 125 | eventSource.addMouseMotionListener(this); |
121 | 126 | selectionEndedListener.addPropertyChangeListener(this); |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
146 | 151 | public void mousePressed(MouseEvent e) { |
147 | 152 | if (e.getButton() == MouseEvent.BUTTON1) { |
148 | 153 | mousePosStart = mousePos = e.getPoint(); |
| 154 | |
| 155 | lasso.reset(); |
| 156 | lasso.addPoint(mousePosStart.x, mousePosStart.y); |
149 | 157 | } |
150 | 158 | } |
151 | 159 | |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
159 | 167 | if (mousePosStart == null) { |
160 | 168 | mousePosStart = mousePos = e.getPoint(); |
161 | 169 | } |
162 | | paintRect(); |
| 170 | if (!lassoMode) { |
| 171 | paintRect(); |
| 172 | } |
163 | 173 | } |
164 | 174 | |
165 | 175 | if (buttonPressed == MouseEvent.BUTTON1_DOWN_MASK) { |
166 | 176 | mousePos = e.getPoint(); |
167 | | paintRect(); |
| 177 | if (lassoMode) { |
| 178 | paintLasso(); |
| 179 | } else { |
| 180 | paintRect(); |
| 181 | } |
168 | 182 | } else if (buttonPressed == (MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK)) { |
169 | 183 | mousePosStart.x += e.getX()-mousePos.x; |
170 | 184 | mousePosStart.y += e.getY()-mousePos.y; |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
181 | 195 | return; |
182 | 196 | if (mousePos == null || mousePosStart == null) |
183 | 197 | return; // injected release from outside |
184 | | |
185 | 198 | // disable the selection rect |
186 | | paintRect(); |
187 | | Rectangle r = getSelectionRectangle(); |
| 199 | Rectangle r; |
| 200 | if (!lassoMode) { |
| 201 | paintRect(); |
| 202 | r = getSelectionRectangle(); |
| 203 | |
| 204 | lasso = rectToPolygon(r); |
| 205 | } else { |
| 206 | lasso.addPoint(mousePos.x, mousePos.y); |
| 207 | r = lasso.getBounds(); |
| 208 | } |
188 | 209 | mousePosStart = null; |
189 | 210 | mousePos = null; |
190 | 211 | |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
208 | 229 | g.drawRect(r.x,r.y,r.width,r.height); |
209 | 230 | } |
210 | 231 | |
| 232 | private void paintLasso() { |
| 233 | if (mousePos == null || mousePosStart == null || mousePos == mousePosStart) { |
| 234 | return; |
| 235 | } |
| 236 | |
| 237 | Graphics g = nc.getGraphics(); |
| 238 | g.setColor(Color.WHITE); |
| 239 | |
| 240 | int lastPosX = lasso.xpoints[lasso.npoints - 1]; |
| 241 | int lastPosY = lasso.ypoints[lasso.npoints - 1]; |
| 242 | g.drawLine(lastPosX, lastPosY, mousePos.x, mousePos.y); |
| 243 | |
| 244 | lasso.addPoint(mousePos.x, mousePos.y); |
| 245 | } |
| 246 | |
211 | 247 | /** |
212 | 248 | * Calculate and return the current selection rectangle |
213 | 249 | * @return A rectangle that spans from mousePos to mouseStartPos |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
260 | 296 | } |
261 | 297 | |
262 | 298 | /** |
263 | | * Return a list of all objects in the rectangle, respecting the different |
| 299 | * Return a list of all objects in the selection, respecting the different |
264 | 300 | * modifier. |
265 | | * @param alt Whether the alt key was pressed, which means select all objects |
266 | | * that are touched, instead those which are completly covered. |
| 301 | * |
| 302 | * @param alt Whether the alt key was pressed, which means select all |
| 303 | * objects that are touched, instead those which are completely covered. |
267 | 304 | */ |
268 | | public Collection<OsmPrimitive> getObjectsInRectangle(Rectangle r, boolean alt) { |
| 305 | public Collection<OsmPrimitive> getSelectedObjects(boolean alt) { |
| 306 | |
269 | 307 | Collection<OsmPrimitive> selection = new LinkedList<OsmPrimitive>(); |
270 | 308 | |
271 | 309 | // whether user only clicked, not dragged. |
272 | | boolean clicked = r.width <= 2 && r.height <= 2; |
273 | | Point center = new Point(r.x+r.width/2, r.y+r.height/2); |
| 310 | boolean clicked = false; |
| 311 | Rectangle bounding = lasso.getBounds(); |
| 312 | if (bounding.height <= 2 && bounding.width <= 2) { |
| 313 | clicked = true; |
| 314 | } |
274 | 315 | |
275 | 316 | if (clicked) { |
| 317 | Point center = new Point(lasso.xpoints[0], lasso.ypoints[0]); |
276 | 318 | OsmPrimitive osm = nc.getNearestNodeOrWay(center, OsmPrimitive.isSelectablePredicate, false); |
277 | 319 | if (osm != null) { |
278 | 320 | selection.add(osm); |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
280 | 322 | } else { |
281 | 323 | // nodes |
282 | 324 | for (Node n : nc.getCurrentDataSet().getNodes()) { |
283 | | if (n.isSelectable() && r.contains(nc.getPoint(n))) { |
| 325 | if (n.isSelectable() && lasso.contains(nc.getPoint(n))) { |
284 | 326 | selection.add(n); |
285 | 327 | } |
286 | 328 | } |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
292 | 334 | } |
293 | 335 | if (alt) { |
294 | 336 | for (Node n : w.getNodes()) { |
295 | | if (!n.isIncomplete() && r.contains(nc.getPoint(n))) { |
| 337 | if (!n.isIncomplete() && lasso.contains(nc.getPoint(n))) { |
296 | 338 | selection.add(w); |
297 | 339 | break; |
298 | 340 | } |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
300 | 342 | } else { |
301 | 343 | boolean allIn = true; |
302 | 344 | for (Node n : w.getNodes()) { |
303 | | if (!n.isIncomplete() && !r.contains(nc.getPoint(n))) { |
| 345 | if (!n.isIncomplete() && !lasso.contains(nc.getPoint(n))) { |
304 | 346 | allIn = false; |
305 | 347 | break; |
306 | 348 | } |
… |
… |
public class SelectionManager implements MouseListener, MouseMotionListener, Pro
|
314 | 356 | return selection; |
315 | 357 | } |
316 | 358 | |
| 359 | private Polygon rectToPolygon(Rectangle r) { |
| 360 | Polygon poly = new Polygon(); |
| 361 | |
| 362 | poly.addPoint(r.x, r.y); |
| 363 | poly.addPoint(r.x, r.y + r.height); |
| 364 | poly.addPoint(r.x + r.width, r.y + r.height); |
| 365 | poly.addPoint(r.x + r.width, r.y); |
| 366 | |
| 367 | return poly; |
| 368 | } |
| 369 | |
| 370 | public void setLassoMode(boolean lassoMode) { |
| 371 | this.lassoMode = lassoMode; |
| 372 | } |
| 373 | |
317 | 374 | public void mouseClicked(MouseEvent e) {} |
318 | 375 | public void mouseEntered(MouseEvent e) {} |
319 | 376 | public void mouseExited(MouseEvent e) {} |