Ticket #164: continuous-selection

File continuous-selection, 6.8 KB (added by guilhem.bonnefille@…, 19 years ago)

The patch

Line 
1Add a continuous selection
2
3From: <>
4
5Select all continuous segments
6---
7
8 images/mapmode/selection/continuous.png | Bin
9 .../josm/actions/mapmode/SelectionAction.java | 121 ++++++++++++++++++++---
10 2 files changed, 106 insertions(+), 15 deletions(-)
11
12diff --git a/images/mapmode/selection/continuous.png b/images/mapmode/selection/continuous.png
13new file mode 100644
14index 0000000..6c05cb7
15Binary files /dev/null and b/images/mapmode/selection/continuous.png differ
16diff --git a/src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java b/src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
17index 62d747b..3ad577d 100644
18--- a/src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
19+++ b/src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
20@@ -63,7 +63,7 @@ import org.openstreetmap.josm.tools.ImageProvider;
21 */
22 public class SelectionAction extends MapMode implements SelectionEnded {
23
24- enum Mode {select, straight}
25+ enum Mode {select, straight, continuous}
26 private final Mode mode;
27
28 public static class Group extends GroupAction {
29@@ -72,6 +72,7 @@ public class SelectionAction extends MapMode implements SelectionEnded {
30 putValue("help", "Action/Selection");
31 actions.add(new SelectionAction(mf, tr("Selection"), Mode.select, tr("Select objects by dragging or clicking.")));
32 actions.add(new SelectionAction(mf, tr("Straight line"), Mode.straight, tr("Select objects in a straight line.")));
33+ actions.add(new SelectionAction(mf, tr("Continuous segments"), Mode.continuous, tr("Select continuous segments.")));
34 setCurrent(0);
35 }
36 }
37@@ -85,10 +86,10 @@ public class SelectionAction extends MapMode implements SelectionEnded {
38 private Node straightStart = null;
39 private Node lastEnd = null;
40 private Collection<OsmPrimitive> oldSelection = null;
41-
42+
43 //TODO: Implement reverse references into data objects and remove this
44 private final Map<Node, Collection<Segment>> reverseSegmentMap = new HashMap<Node, Collection<Segment>>();
45-
46+
47 /**
48 * Create a new SelectionAction in the given frame.
49 * @param mapFrame The frame this action belongs to
50@@ -104,13 +105,19 @@ public class SelectionAction extends MapMode implements SelectionEnded {
51 super.enterMode();
52 if (mode == Mode.select)
53 selectionManager.register(Main.map.mapView);
54- else {
55+ else if (mode == Mode.straight) {
56 Main.map.mapView.addMouseMotionListener(this);
57 Main.map.mapView.addMouseListener(this);
58 for (Segment s : Main.ds.segments) {
59 addBackReference(s.from, s);
60 addBackReference(s.to, s);
61 }
62+ } else if (mode == Mode.continuous) {
63+ Main.map.mapView.addMouseListener(this);
64+ for (Segment s : Main.ds.segments) {
65+ addBackReference(s.from, s);
66+ addBackReference(s.to, s);
67+ }
68 }
69 }
70
71@@ -127,10 +134,12 @@ public class SelectionAction extends MapMode implements SelectionEnded {
72 super.exitMode();
73 if (mode == Mode.select)
74 selectionManager.unregister(Main.map.mapView);
75- else {
76+ else if (mode == Mode.straight) {
77 Main.map.mapView.removeMouseMotionListener(this);
78 Main.map.mapView.removeMouseListener(this);
79 reverseSegmentMap.clear();
80+ } else if (mode == Mode.continuous) {
81+ Main.map.mapView.removeMouseListener(this);
82 }
83 }
84
85@@ -169,25 +178,60 @@ public class SelectionAction extends MapMode implements SelectionEnded {
86 straightStart = lastEnd;
87 if (straightStart != null && lastEnd != null && straightStart != lastEnd && old != lastEnd) {
88 Collection<OsmPrimitive> path = new HashSet<OsmPrimitive>();
89- Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
90 path.add(straightStart);
91 calculateShortestPath(path, straightStart, lastEnd);
92- if ((e.getModifiers() & MouseEvent.CTRL_MASK) != 0) {
93- sel.addAll(oldSelection);
94- sel.removeAll(path);
95- } else if ((e.getModifiers() & MouseEvent.SHIFT_MASK) != 0) {
96- sel = path;
97- sel.addAll(oldSelection);
98- } else
99- sel = path;
100- Main.ds.setSelected(sel);
101+ updateSelection(e, path);
102 }
103 }
104
105+ /**
106+ * Update the selection.
107+ *
108+ * Handles the modifier key.
109+ *
110+ * @param e
111+ * @param path the path to use for updating.
112+ */
113+ private void updateSelection(MouseEvent e, Collection<OsmPrimitive> path) {
114+ Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
115+ if ((e.getModifiers() & MouseEvent.CTRL_MASK) != 0) {
116+ sel.addAll(oldSelection);
117+ sel.removeAll(path);
118+ } else if ((e.getModifiers() & MouseEvent.SHIFT_MASK) != 0) {
119+ sel = path;
120+ sel.addAll(oldSelection);
121+ } else
122+ sel = path;
123+ Main.ds.setSelected(sel);
124+ }
125+
126+ /**
127+ * Continuous selection.
128+ *
129+ * Does a continuous selection.
130+ *
131+ * @param e
132+ */
133+ private void continuousSelection(MouseEvent e) {
134+ // Retrieve the initial segment
135+ Segment initialSegment = Main.map.mapView.getNearestSegment(e.getPoint());
136+ if (initialSegment != null) {
137+ // Initialise the path
138+ Collection<OsmPrimitive> path = new HashSet<OsmPrimitive>();
139+ path.add(initialSegment);
140+ // Fill the path with continuous segments
141+ calculateContinuousPath(path, initialSegment);
142+ // Update the selection with the path
143+ updateSelection(e, path);
144+ }
145+ }
146+
147 @Override public void mousePressed(MouseEvent e) {
148 straightStart = Main.map.mapView.getNearestNode(e.getPoint());
149 lastEnd = null;
150 oldSelection = Main.ds.getSelected();
151+
152+ if (mode == Mode.continuous) continuousSelection(e);
153 }
154
155 @Override public void mouseReleased(MouseEvent e) {
156@@ -234,4 +278,51 @@ public class SelectionAction extends MapMode implements SelectionEnded {
157 }
158 return null;
159 }
160+
161+ /**
162+ * Get the continuous path.
163+ *
164+ * @param path Path to fill in
165+ * @param initial initial segment
166+ */
167+ private void calculateContinuousPath(Collection<OsmPrimitive> path, Segment initial) {
168+ Segment current = null;
169+ Segment next = initial;
170+ Collection<Segment> c = null;
171+ // Reverse order
172+ while ((current = next) != null && (c = reverseSegmentMap.get(current.from)) != null && c.size() == 2) {
173+ for (Segment s : c) {
174+ if (s != current) {
175+ // s is the other segment connected to current node
176+ if (s != initial && s.to == current.from) {
177+ // s is the preceding segment
178+ path.add(s);
179+ next = s;
180+ } else
181+ // s and next are connected to the same node, but in opposite direction.
182+ // Stop here.
183+ next = null;
184+ }
185+ }
186+ }
187+
188+ next = initial;
189+ // Correct order
190+ while ((current = next) != null && (c = reverseSegmentMap.get(current.to)) != null && c.size() == 2) {
191+ for (Segment s : c) {
192+ if (s != current) {
193+ // s is the other segment connected to current node
194+ if (s != initial && s.from == current.to) {
195+ // s is the preceding segment
196+ path.add(s);
197+ next = s;
198+ } else
199+ // s and next are connected to the same node, but in opposite direction.
200+ // Stop here.
201+ next = null;
202+ }
203+ }
204+ }
205+
206+ }
207 }