source: josm/src/org/openstreetmap/josm/actions/mapmode/AddWayAction.java@ 184

Last change on this file since 184 was 184, checked in by imi, 17 years ago
  • added reorder action to order the segments in a way
File size: 7.7 KB
Line 
1package org.openstreetmap.josm.actions.mapmode;
2
3import static org.openstreetmap.josm.tools.I18n.tr;
4import static org.openstreetmap.josm.tools.I18n.trn;
5
6import java.awt.event.KeyEvent;
7import java.awt.event.MouseEvent;
8import java.util.Arrays;
9import java.util.Collection;
10import java.util.HashSet;
11import java.util.LinkedList;
12
13import javax.swing.JOptionPane;
14
15import org.openstreetmap.josm.Main;
16import org.openstreetmap.josm.actions.ReorderAction;
17import org.openstreetmap.josm.command.AddCommand;
18import org.openstreetmap.josm.command.ChangeCommand;
19import org.openstreetmap.josm.command.DeleteCommand;
20import org.openstreetmap.josm.data.SelectionChangedListener;
21import org.openstreetmap.josm.data.osm.OsmPrimitive;
22import org.openstreetmap.josm.data.osm.Segment;
23import org.openstreetmap.josm.data.osm.Way;
24import org.openstreetmap.josm.gui.MapFrame;
25import org.openstreetmap.josm.tools.ImageProvider;
26
27/**
28 * Add a new way. The action is split into the first phase, where a new way get
29 * created or selected and the second, where this way is modified.
30 *
31 * Way creation mode:
32 * If there is a selection when the mode is entered, all segments in this
33 * selection form a new way. All non-segment objects are deselected. If there
34 * were ways selected, the user is asked whether to select all segments of these
35 * ways or not, except there is exactly one way selected, which enter the
36 * edit ways mode for this way immediatly.
37 *
38 * If there is no selection on entering, and the user clicks on an segment,
39 * the way editing starts the with a new way and this segment. If the user click
40 * on a way (not holding Alt down), then this way is edited in the way edit mode.
41 *
42 * Way editing mode:
43 * The user can click on subsequent segments. If the segment belonged to the way
44 * it get removed from the way. Elsewhere it get added to the way. JOSM try to add
45 * the segment in the correct position. This is done by searching for connections
46 * to the segment at its 'to' node which are also in the way. The segemnt is
47 * inserted in the way as predecessor of the found segment (or at last segment, if
48 * nothing found).
49 *
50 * @author imi
51 */
52public class AddWayAction extends MapMode implements SelectionChangedListener {
53 private Way way;
54
55 /**
56 * Create a new AddWayAction.
57 * @param mapFrame The MapFrame this action belongs to.
58 * @param followMode The mode to go into when finished creating a way.
59 */
60 public AddWayAction(MapFrame mapFrame) {
61 super(tr("Add Way"), "addway", tr("Add a new way to the data."), KeyEvent.VK_W, mapFrame, ImageProvider.getCursor("normal", "way"));
62
63 Main.ds.addSelectionChangedListener(this);
64 }
65
66 @Override public void enterMode() {
67 super.enterMode();
68 way = makeWay();
69 Main.ds.setSelected(way);
70 Main.map.mapView.addMouseListener(this);
71 }
72
73 @Override public void exitMode() {
74 super.exitMode();
75 way = null;
76 Main.map.mapView.removeMouseListener(this);
77 }
78
79 @Override public void mouseClicked(MouseEvent e) {
80 if (e.getButton() != MouseEvent.BUTTON1)
81 return;
82
83 Segment s = Main.map.mapView.getNearestSegment(e.getPoint());
84 if (s == null)
85 return;
86
87 // special case for initial selecting one way
88 if (way == null && (e.getModifiers() & MouseEvent.ALT_DOWN_MASK) == 0) {
89 Way w = Main.map.mapView.getNearestWay(e.getPoint());
90 if (w != null) {
91 way = w;
92 Main.ds.setSelected(way);
93 for (Segment seg : way.segments) {
94 if (seg.incomplete) {
95 JOptionPane.showMessageDialog(Main.parent,tr("Warning: This way is incomplete. Try to download it, before adding segments."));
96 return;
97 }
98 }
99 return;
100 }
101 }
102
103 if (way != null && way.segments.contains(s)) {
104 Way copy = new Way(way);
105
106 copy.segments.remove(s);
107 if (copy.segments.isEmpty()) {
108 Main.main.editLayer().add(new DeleteCommand(Arrays.asList(new OsmPrimitive[]{way})));
109 way = null;
110 } else
111 Main.main.editLayer().add(new ChangeCommand(way, copy));
112 } else {
113 if (way == null) {
114 way = new Way();
115 way.segments.add(s);
116 Main.main.editLayer().add(new AddCommand(way));
117 } else {
118 Way copy = new Way(way);
119 int i;
120 for (i = 0; i < way.segments.size(); ++i)
121 if (way.segments.get(i).from == s.to)
122 break;
123 copy.segments.add(i, s);
124 Main.main.editLayer().add(new ChangeCommand(way, copy));
125 }
126 }
127 Main.ds.setSelected(way);
128 }
129
130 /**
131 * Form a way, either out of the (one) selected way or by creating a way over the selected
132 * line segments.
133 */
134 private Way makeWay() {
135 Collection<OsmPrimitive> selection = Main.ds.getSelected();
136 if (selection.isEmpty())
137 return null;
138
139 if (selection.size() == 1 && selection.iterator().next() instanceof Way) {
140 Way way = (Way)selection.iterator().next();
141 for (Segment seg : way.segments) {
142 if (seg.incomplete) {
143 JOptionPane.showMessageDialog(Main.parent, tr("Warning: This way is incomplete. Try to download it, before adding segments."));
144 break;
145 }
146 }
147 return way;
148 }
149
150 HashSet<Segment> segmentSet = new HashSet<Segment>();
151 int numberOfSelectedWays = 0;
152 for (OsmPrimitive osm : selection) {
153 if (osm instanceof Way)
154 numberOfSelectedWays++;
155 else if (osm instanceof Segment)
156 segmentSet.add((Segment)osm);
157 }
158
159 Way wayToAdd = null;
160 boolean reordered = false;
161 if (numberOfSelectedWays > 0) {
162 int answer = JOptionPane.showConfirmDialog(Main.parent,trn("{0} way has been selected.\nDo you wish to select all segments belonging to the way instead?","{0} ways have been selected.\nDo you wish to select all segments belonging to the ways instead?",numberOfSelectedWays,numberOfSelectedWays),tr("Add segments from ways"), JOptionPane.YES_NO_OPTION);
163 if (answer == JOptionPane.YES_OPTION) {
164 for (OsmPrimitive osm : selection)
165 if (osm instanceof Way)
166 segmentSet.addAll(((Way)osm).segments);
167 } else if (numberOfSelectedWays == 1) {
168 answer = JOptionPane.showConfirmDialog(Main.parent,tr("Do you want to add all other selected segments to the one selected way?"),tr("Add segments to way?"), JOptionPane.YES_NO_OPTION);
169 if (answer == JOptionPane.YES_OPTION) {
170 for (OsmPrimitive osm : selection) {
171 if (osm instanceof Way) {
172 wayToAdd = (Way)osm;
173 answer = JOptionPane.showConfirmDialog(Main.parent,tr("Reorder all line segments?"), tr("Reorder?"), JOptionPane.YES_NO_CANCEL_OPTION);
174 if (answer == JOptionPane.CANCEL_OPTION)
175 return wayToAdd;
176 if (answer == JOptionPane.YES_OPTION) {
177 segmentSet.addAll(wayToAdd.segments);
178 reordered = true;
179 } else
180 segmentSet.removeAll(wayToAdd.segments);
181 break;
182 }
183 }
184 }
185 }
186 }
187
188 if (segmentSet.isEmpty())
189 return null;
190
191 LinkedList<Segment> sortedSegments = ReorderAction.sortSegments(segmentSet);
192
193 if (wayToAdd != null) {
194 Way w = new Way(wayToAdd);
195 if (reordered)
196 w.segments.clear();
197 w.segments.addAll(sortedSegments);
198 Main.main.editLayer().add(new ChangeCommand(wayToAdd, w));
199 return wayToAdd;
200 }
201
202 if (JOptionPane.YES_OPTION != JOptionPane.showConfirmDialog(Main.parent,trn("Create a new way out of {0} segment?","Create a new way out of {0} segments?",sortedSegments.size(),sortedSegments.size()), tr("Create new way"), JOptionPane.YES_NO_OPTION))
203 return null;
204
205 Way w = new Way();
206 w.segments.addAll(sortedSegments);
207 Main.main.editLayer().add(new AddCommand(w));
208 return w;
209 }
210
211 public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
212 if (newSelection.size() == 1) {
213 OsmPrimitive osm = newSelection.iterator().next();
214 way = osm instanceof Way ? (Way)osm : null;
215 } else
216 way = null;
217 }
218}
Note: See TracBrowser for help on using the repository browser.