Changeset 329 in josm for branch/0.5/src/org/openstreetmap/josm/actions/mapmode
- Timestamp:
- 2007-09-24T01:36:24+02:00 (18 years ago)
- Location:
- branch/0.5/src/org/openstreetmap/josm/actions/mapmode
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
branch/0.5/src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java
r314 r329 24 24 import org.openstreetmap.josm.data.osm.Node; 25 25 import org.openstreetmap.josm.data.osm.OsmPrimitive; 26 import org.openstreetmap.josm.data.osm.Segment;27 26 import org.openstreetmap.josm.data.osm.Way; 27 import org.openstreetmap.josm.data.osm.WaySegment; 28 28 import org.openstreetmap.josm.gui.MapFrame; 29 29 import org.openstreetmap.josm.tools.ImageProvider; … … 33 33 * and there is it. Nothing more, nothing less. 34 34 * 35 * FIXME: "nothing more, nothing less" is a bit out-of-date 36 * 35 37 * Newly created nodes are selected. Shift modifier does not cancel the old 36 38 * selection as usual. … … 41 43 public class AddNodeAction extends MapMode { 42 44 43 enum Mode {node, node segment, autonode}45 enum Mode {node, nodeway, autonode} 44 46 private final Mode mode; 45 47 … … 49 51 putValue("help", "Action/AddNode"); 50 52 actions.add(new AddNodeAction(mf,tr("Add node"), Mode.node, tr("Add a new node to the map"))); 51 actions.add(new AddNodeAction(mf, tr("Add node into segment"), Mode.nodesegment,tr( "Add a node into an existingsegment")));52 actions.add(new AddNodeAction(mf, tr("Add node and connect"), Mode.autonode,tr( "Add a node and connect it to the selected node (with CTRL: add node into segment; with SHIFT: re-use existing node)")));53 actions.add(new AddNodeAction(mf, tr("Add node into way"), Mode.nodeway,tr( "Add a node into an existing way"))); 54 actions.add(new AddNodeAction(mf, tr("Add node and connect"), Mode.autonode,tr( "Add a node and connect it to the selected node (with CTRL: add node into way; with SHIFT: re-use existing node)"))); 53 55 setCurrent(0); 54 56 } … … 83 85 * position. 84 86 * 85 * If in nodesegment mode, add the node to the line segment by splitting the 86 * segment. The new created segment will be inserted in every way the segment 87 * was part of. 87 * If in nodeway mode, insert the node into the way. 88 88 */ 89 89 @Override public void mouseClicked(MouseEvent e) { … … 98 98 99 99 Command c = new AddCommand(n); 100 if (mode == Mode.node segment) {101 Segments = Main.map.mapView.getNearestSegment(e.getPoint());102 if (s == null) 100 if (mode == Mode.nodeway) { 101 WaySegment ws = Main.map.mapView.getNearestWaySegment(e.getPoint()); 102 if (ws == null) 103 103 return; 104 104 105 105 // see if another segment is also near 106 Segment other = Main.map.mapView.getNearestSegment(e.getPoint(), Collections.singleton(s)); 106 WaySegment other = Main.map.mapView.getNearestWaySegment(e.getPoint(), 107 Collections.singleton(ws)); 108 109 Node n1 = ws.way.nodes.get(ws.lowerIndex), 110 n2 = ws.way.nodes.get(ws.lowerIndex + 1); 107 111 108 112 if (other == null && (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) == 0) { 109 113 // moving the new point to the perpendicular point 110 // FIXME: when two segments are split, should move the new point to the 114 // FIXME: when two way segments are split, should move the new point to the 111 115 // intersection point! 112 EastNorth A = s.from.eastNorth;113 EastNorth B = s.to.eastNorth;116 EastNorth A = n1.eastNorth; 117 EastNorth B = n2.eastNorth; 114 118 double ab = A.distance(B); 115 119 double nb = n.eastNorth.distance(B); … … 124 128 125 129 // split the first segment 126 splitSegmentAtNode(s, n, cmds); 130 splitWaySegmentAtNode(ws, n, cmds); 127 131 128 132 // if a second segment was found, split that as well 129 if (other != null) splitSegmentAtNode(other, n, cmds); 133 if (other != null) splitWaySegmentAtNode(other, n, cmds); 130 134 131 135 c = new SequenceCommand(tr((other == null) ? 132 "Add node into segment" : "Add common node into twosegments"), cmds);136 "Add node into way" : "Add common node into two ways"), cmds); 133 137 } 134 138 … … 136 140 if (mode == Mode.autonode) { 137 141 138 Segment insertInto = null; 142 WaySegment insertInto = null; 139 143 Node reuseNode = null; 140 144 141 // If CTRL is held, insert the node into a potentially existing segment 145 // If CTRL is held, insert the node into a potentially existing way segment 142 146 if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0) { 143 insertInto = Main.map.mapView.getNearestSegment(e.getPoint()); 147 insertInto = Main.map.mapView.getNearestWaySegment(e.getPoint()); 148 if (insertInto == null) System.err.println("Couldn't find nearby way segment"); 144 149 if (insertInto == null) 145 150 return; … … 150 155 // continuation of the "add node and connect" stuff) 151 156 else if ((e.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) != 0) { 152 OsmPrimitive clicked = Main.map.mapView.getNearest(e.getPoint() , false);157 OsmPrimitive clicked = Main.map.mapView.getNearest(e.getPoint()); 153 158 if (clicked == null || !(clicked instanceof Node)) 154 159 return; … … 159 164 if (selection.size() == 1 && selection.iterator().next() instanceof Node) { 160 165 Node n1 = (Node)selection.iterator().next(); 166 161 167 Collection<Command> cmds = new LinkedList<Command>(); 162 168 163 169 if (reuseNode != null) { 164 170 // in re-use node mode, n1 must not be identical to clicked node 171 if (n1 == reuseNode) System.err.println("n1 == reuseNode"); 165 172 if (n1 == reuseNode) return; 166 173 // replace newly created node with existing node … … 171 178 } 172 179 173 Segment s = new Segment(n1, n); 174 180 /* Keep track of the way we change, it might be the same into 181 * which we insert the node. 182 */ 183 Way newInsertInto = null; 175 184 if (insertInto != null) 176 splitSegmentAtNode(insertInto, n, cmds); 177 178 cmds.add(new AddCommand(s)); 185 newInsertInto = splitWaySegmentAtNode(insertInto, n, cmds); 179 186 180 187 Way way = getWayForNode(n1); 181 if (way != null) { 182 Way newWay = new Way(way); 183 if (way.segments.get(0).from == n1) { 184 Node tmp = s.from; 185 s.from = s.to; 186 s.to = tmp; 187 newWay.segments.add(0, s); 188 } else 189 newWay.segments.add(s); 190 cmds.add(new ChangeCommand(way, newWay)); 191 } 192 193 c = new SequenceCommand(tr((insertInto == null) ? "Add node and connect" : "Add node into segment and connect"), cmds); 188 if (way == null) { 189 way = new Way(); 190 way.nodes.add(n1); 191 cmds.add(new AddCommand(way)); 192 } else { 193 if (insertInto != null && way == insertInto.way) { 194 way = newInsertInto; 195 } else { 196 Way wnew = new Way(way); 197 cmds.add(new ChangeCommand(way, wnew)); 198 way = wnew; 199 } 200 } 201 202 if (way.nodes.get(way.nodes.size() - 1) == n1) { 203 way.nodes.add(n); 204 } else { 205 way.nodes.add(0, n); 206 } 207 208 c = new SequenceCommand(tr((insertInto == null) ? "Add node and connect" : "Add node into way and connect"), cmds); 194 209 } 195 210 } … … 201 216 202 217 /** 203 * @return If the node is partof exactly one way, return this.218 * @return If the node is the end of exactly one way, return this. 204 219 * <code>null</code> otherwise. 205 220 */ … … 207 222 Way way = null; 208 223 for (Way w : Main.ds.ways) { 209 for (Segment s : w.segments) { 210 if (s.from == n || s.to == n) { 224 int i = w.nodes.indexOf(n); 225 if (i == -1) continue; 226 if (i == 0 || i == w.nodes.size() - 1) { 211 227 if (way != null) 212 228 return null; 213 if (s.from == s.to)214 return null;215 229 way = w; 216 230 } 217 231 } 218 }219 232 return way; 220 233 } 221 234 222 private void splitSegmentAtNode(Segment s, Node n, Collection<Command> cmds) { 223 Segment s1 = new Segment(s); 224 s1.to = n; 225 Segment s2 = new Segment(s.from, s.to); 226 s2.from = n; 227 if (s.keys != null) 228 s2.keys = new HashMap<String, String>(s.keys); 229 230 cmds.add(new ChangeCommand(s, s1)); 231 cmds.add(new AddCommand(s2)); 232 233 // Add the segment to every way 234 for (Way wold : Main.ds.ways) { 235 if (wold.segments.contains(s)) { 236 Way wnew = new Way(wold); 237 Collection<Segment> segs = new ArrayList<Segment>(wnew.segments); 238 wnew.segments.clear(); 239 for (Segment waySeg : segs) { 240 wnew.segments.add(waySeg); 241 if (waySeg == s) 242 wnew.segments.add(s2); 243 } 244 cmds.add(new ChangeCommand(wold, wnew)); 245 } 246 } 235 private Way splitWaySegmentAtNode(WaySegment ws, Node n, Collection<Command> cmds) { 236 Way wnew = new Way(ws.way); 237 wnew.nodes.add(ws.lowerIndex + 1, n); 238 cmds.add(new ChangeCommand(ws.way, wnew)); 239 return wnew; 247 240 } 248 241 } -
branch/0.5/src/org/openstreetmap/josm/actions/mapmode/AddSegmentAction.java
r301 r329 15 15 import org.openstreetmap.josm.Main; 16 16 import org.openstreetmap.josm.command.AddCommand; 17 import org.openstreetmap.josm.command.ChangeCommand; 17 18 import org.openstreetmap.josm.data.osm.Node; 18 19 import org.openstreetmap.josm.data.osm.OsmPrimitive; 19 import org.openstreetmap.josm.data.osm. Segment;20 import org.openstreetmap.josm.data.osm.Way; 20 21 import org.openstreetmap.josm.gui.MapFrame; 21 22 import org.openstreetmap.josm.tools.ImageProvider; … … 51 52 */ 52 53 public AddSegmentAction(MapFrame mapFrame) { 53 super(tr(" Add segment"),54 super(tr("Connect two nodes"), 54 55 "addsegment", 55 tr(" Add a segment betweentwo nodes."),56 tr("Connect two nodes using ways."), 56 57 KeyEvent.VK_G, 57 58 mapFrame, … … 72 73 } 73 74 74 75 /** 76 * Called when user hits space bar while dragging. 77 */ 75 78 @Override public void actionPerformed(ActionEvent e) { 76 79 super.actionPerformed(e); … … 85 88 return; 86 89 87 OsmPrimitive clicked = Main.map.mapView.getNearest(e.getPoint(), true); 88 if (clicked == null || !(clicked instanceof Node)) 89 return; 90 Node clicked = Main.map.mapView.getNearestNode(e.getPoint()); 91 if (clicked == null) return; 90 92 91 93 drawHint(false); 92 first = second = (Node)clicked;94 first = second = clicked; 93 95 } 94 96 … … 101 103 return; 102 104 103 OsmPrimitive clicked = Main.map.mapView.getNearest(e.getPoint(), (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0); 104 if (clicked == null || clicked == second || !(clicked instanceof Node)) 105 return; 105 Node hovered = Main.map.mapView.getNearestNode(e.getPoint()); 106 if (hovered == second) return; 106 107 107 108 drawHint(false); 108 109 second = (Node)clicked; 109 second = hovered; 110 110 drawHint(true); 111 111 } … … 116 116 @Override public void mouseReleased(MouseEvent e) { 117 117 if (e.getButton() == MouseEvent.BUTTON1) { 118 drawHint(false); 118 119 makeSegment(); 119 first = null; // release segment drawing120 first = null; 120 121 } 122 } 123 124 /** 125 * @return If the node is the end of exactly one way, return this. 126 * <code>null</code> otherwise. 127 */ 128 private Way getWayForNode(Node n) { 129 Way way = null; 130 for (Way w : Main.ds.ways) { 131 int i = w.nodes.indexOf(n); 132 if (i == -1) continue; 133 if (i == 0 || i == w.nodes.size() - 1) { 134 if (way != null) 135 return null; 136 way = w; 137 } 138 } 139 return way; 121 140 } 122 141 … … 126 145 */ 127 146 private void makeSegment() { 128 if (first == null || second == null) { 129 first = null; 130 second = null; 131 return; 132 } 133 134 drawHint(false); 147 Node n1 = first; 148 Node n2 = second; 135 149 136 Node start = first;137 Node end = second;150 // this is to allow continued segment drawing by hitting the space bar 151 // at every intermediate node 138 152 first = second; 139 153 second = null; 154 155 if (n1 == null || n2 == null || n1 == n2) return; 156 157 Way w = getWayForNode(n1); 158 Way wnew; 159 Collection<OsmPrimitive> sel = Main.ds.getSelected(); 140 160 141 if (start != end) { 142 // try to find a segment 143 for (Segment ls : Main.ds.segments) 144 if (!ls.deleted && ((start == ls.from && end == ls.to) || (end == ls.from && start == ls.to))) 145 return; // already a segment here - be happy, do nothing. 146 147 Segment ls = new Segment(start, end); 148 Main.main.undoRedo.add(new AddCommand(ls)); 149 Collection<OsmPrimitive> sel = Main.ds.getSelected(); 150 sel.add(ls); 161 if (w == null) { 162 // create a new way and add it to the current selection. 163 wnew = new Way(); 164 wnew.nodes.add(n1); 165 wnew.nodes.add(n2); 166 Main.main.undoRedo.add(new AddCommand(wnew)); 167 sel.add(wnew); 168 Main.ds.setSelected(sel); 169 } else { 170 // extend an existing way; only add to current selection if 171 // it is not already in there. 172 wnew = new Way(w); 173 if (wnew.nodes.get(wnew.nodes.size() - 1) == n1) { 174 wnew.nodes.add(n2); 175 } else { 176 wnew.nodes.add(0, n2); 177 } 178 Main.main.undoRedo.add(new ChangeCommand(w, wnew)); 179 // do not use wnew below; ChangeCommand only uses wnew as a 180 // message about changes to be done to w but will not replace w! 181 if (!sel.contains(w)) { 182 sel.add(w); 183 } 184 // do not move this into the if block above since it also 185 // fires the selection change event which is desired. 151 186 Main.ds.setSelected(sel); 152 187 } -
branch/0.5/src/org/openstreetmap/josm/actions/mapmode/AddWayAction.java
r301 r329 1 // License: GPL. Copyright 2007 by Immanuel Scholz and others2 package org.openstreetmap.josm.actions.mapmode;3 4 import static org.openstreetmap.josm.tools.I18n.tr;5 import static org.openstreetmap.josm.tools.I18n.trn;6 7 import java.awt.event.KeyEvent;8 import java.awt.event.MouseEvent;9 import java.util.Arrays;10 import java.util.Collection;11 import java.util.HashSet;12 import java.util.LinkedList;13 14 import javax.swing.JOptionPane;15 16 import org.openstreetmap.josm.Main;17 import org.openstreetmap.josm.actions.ReorderAction;18 import org.openstreetmap.josm.command.AddCommand;19 import org.openstreetmap.josm.command.ChangeCommand;20 import org.openstreetmap.josm.command.DeleteCommand;21 import org.openstreetmap.josm.data.SelectionChangedListener;22 import org.openstreetmap.josm.data.osm.DataSet;23 import org.openstreetmap.josm.data.osm.OsmPrimitive;24 import org.openstreetmap.josm.data.osm.Segment;25 import org.openstreetmap.josm.data.osm.Way;26 import org.openstreetmap.josm.gui.MapFrame;27 import org.openstreetmap.josm.tools.ImageProvider;28 29 /**30 * Add a new way. The action is split into the first phase, where a new way get31 * created or selected and the second, where this way is modified.32 *33 * Way creation mode:34 * If there is a selection when the mode is entered, all segments in this35 * selection form a new way. All non-segment objects are deselected. If there36 * were ways selected, the user is asked whether to select all segments of these37 * ways or not, except there is exactly one way selected, which enter the38 * edit ways mode for this way immediatly.39 *40 * If there is no selection on entering, and the user clicks on an segment,41 * the way editing starts the with a new way and this segment. If the user click42 * on a way (not holding Alt down), then this way is edited in the way edit mode.43 *44 * Way editing mode:45 * The user can click on subsequent segments. If the segment belonged to the way46 * it get removed from the way. Elsewhere it get added to the way. JOSM try to add47 * the segment in the correct position. This is done by searching for connections48 * to the segment at its 'to' node which are also in the way. The segemnt is49 * inserted in the way as predecessor of the found segment (or at last segment, if50 * nothing found).51 *52 * @author imi53 */54 public class AddWayAction extends MapMode implements SelectionChangedListener {55 private Way way;56 57 /**58 * Create a new AddWayAction.59 * @param mapFrame The MapFrame this action belongs to.60 * @param followMode The mode to go into when finished creating a way.61 */62 public AddWayAction(MapFrame mapFrame) {63 super(tr("Add Way"), "addway", tr("Add a new way to the data."), KeyEvent.VK_W, mapFrame, ImageProvider.getCursor("normal", "way"));64 DataSet.listeners.add(this);65 }66 67 @Override public void enterMode() {68 super.enterMode();69 way = makeWay();70 Main.ds.setSelected(way);71 Main.map.mapView.addMouseListener(this);72 }73 74 @Override public void exitMode() {75 super.exitMode();76 way = null;77 Main.map.mapView.removeMouseListener(this);78 }79 80 @Override public void mouseClicked(MouseEvent e) {81 if (e.getButton() != MouseEvent.BUTTON1)82 return;83 84 Segment s = Main.map.mapView.getNearestSegment(e.getPoint());85 if (s == null)86 return;87 88 // special case for initial selecting one way89 if (way == null && (e.getModifiers() & MouseEvent.ALT_DOWN_MASK) == 0) {90 Way w = Main.map.mapView.getNearestWay(e.getPoint());91 if (w != null) {92 way = w;93 Main.ds.setSelected(way);94 for (Segment seg : way.segments) {95 if (seg.incomplete) {96 JOptionPane.showMessageDialog(Main.parent,tr("Warning: This way is incomplete. Try to download it before adding segments."));97 return;98 }99 }100 return;101 }102 }103 104 if (way != null && way.segments.contains(s)) {105 Way copy = new Way(way);106 107 copy.segments.remove(s);108 if (copy.segments.isEmpty()) {109 Main.main.undoRedo.add(new DeleteCommand(Arrays.asList(new OsmPrimitive[]{way})));110 way = null;111 } else112 Main.main.undoRedo.add(new ChangeCommand(way, copy));113 } else {114 if (way == null) {115 way = new Way();116 way.segments.add(s);117 Main.main.undoRedo.add(new AddCommand(way));118 } else {119 Way copy = new Way(way);120 int i;121 for (i = 0; i < way.segments.size(); ++i)122 if (way.segments.get(i).from == s.to)123 break;124 copy.segments.add(i, s);125 Main.main.undoRedo.add(new ChangeCommand(way, copy));126 }127 }128 Main.ds.setSelected(way);129 }130 131 /**132 * Form a way, either out of the (one) selected way or by creating a way over the selected133 * line segments.134 */135 private Way makeWay() {136 Collection<OsmPrimitive> selection = Main.ds.getSelected();137 if (selection.isEmpty())138 return null;139 140 if (selection.size() == 1 && selection.iterator().next() instanceof Way) {141 Way way = (Way)selection.iterator().next();142 for (Segment seg : way.segments) {143 if (seg.incomplete) {144 JOptionPane.showMessageDialog(Main.parent, tr("Warning: This way is incomplete. Try to download it before adding segments."));145 break;146 }147 }148 return way;149 }150 151 HashSet<Segment> segmentSet = new HashSet<Segment>();152 int numberOfSelectedWays = 0;153 for (OsmPrimitive osm : selection) {154 if (osm instanceof Way)155 numberOfSelectedWays++;156 else if (osm instanceof Segment)157 segmentSet.add((Segment)osm);158 }159 160 Way wayToAdd = null;161 boolean reordered = false;162 if (numberOfSelectedWays > 0) {163 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);164 if (answer == JOptionPane.YES_OPTION) {165 for (OsmPrimitive osm : selection)166 if (osm instanceof Way)167 segmentSet.addAll(((Way)osm).segments);168 } else if (numberOfSelectedWays == 1) {169 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);170 if (answer == JOptionPane.YES_OPTION) {171 for (OsmPrimitive osm : selection) {172 if (osm instanceof Way) {173 wayToAdd = (Way)osm;174 answer = JOptionPane.showConfirmDialog(Main.parent,tr("Reorder all line segments?"), tr("Reorder?"), JOptionPane.YES_NO_CANCEL_OPTION);175 if (answer == JOptionPane.CANCEL_OPTION)176 return wayToAdd;177 if (answer == JOptionPane.YES_OPTION) {178 segmentSet.addAll(wayToAdd.segments);179 reordered = true;180 } else181 segmentSet.removeAll(wayToAdd.segments);182 break;183 }184 }185 }186 }187 }188 189 if (segmentSet.isEmpty())190 return null;191 192 LinkedList<Segment> rawSegments = new LinkedList<Segment>(segmentSet);193 LinkedList<Segment> sortedSegments = ReorderAction.sortSegments(rawSegments, true);194 195 if (wayToAdd != null) {196 Way w = new Way(wayToAdd);197 if (reordered)198 w.segments.clear();199 w.segments.addAll(sortedSegments);200 Main.main.undoRedo.add(new ChangeCommand(wayToAdd, w));201 return wayToAdd;202 }203 204 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))205 return null;206 207 Way w = new Way();208 w.segments.addAll(sortedSegments);209 Main.main.undoRedo.add(new AddCommand(w));210 return w;211 }212 213 public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {214 if (newSelection.size() == 1) {215 OsmPrimitive osm = newSelection.iterator().next();216 way = osm instanceof Way ? (Way)osm : null;217 } else218 way = null;219 }220 } -
branch/0.5/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
r301 r329 24 24 import org.openstreetmap.josm.data.osm.Node; 25 25 import org.openstreetmap.josm.data.osm.OsmPrimitive; 26 import org.openstreetmap.josm.data.osm.Segment;27 26 import org.openstreetmap.josm.data.osm.Way; 28 27 import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor; … … 38 37 * @see #deleteWithReferences(OsmPrimitive) 39 38 * 40 * Pressing Alt will select the way instead of a segment, as usual.41 *42 39 * If the user did not press Ctrl and the object has any references, the user 43 40 * is informed and nothing is deleted. … … 57 54 super(tr("Delete"), 58 55 "delete", 59 tr("Delete nodes , streets or segments."),56 tr("Delete nodes or ways."), 60 57 KeyEvent.VK_D, 61 58 mapFrame, … … 92 89 return; 93 90 94 OsmPrimitive sel = Main.map.mapView.getNearest(e.getPoint() , (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0);91 OsmPrimitive sel = Main.map.mapView.getNearest(e.getPoint()); 95 92 if (sel == null) 96 93 return; … … 105 102 106 103 /** 107 * Delete the primitives and everything they reference s.104 * Delete the primitives and everything they reference. 108 105 * 109 * If a node is deleted, the node and all segments,ways andareas106 * If a node is deleted, the node and all ways and relations 110 107 * the node is part of are deleted as well. 111 108 * 112 * If a segment is deleted, all ways the segment is part of 113 * are deleted as well. No nodes are deleted. 109 * If a way is deleted, all relations the way is member of are also deleted. 114 110 * 115 * If a way is deleted, only the way and no segments or nodes are 116 * deleted. 117 * 118 * If an area is deleted, only the area gets deleted. 111 * If a way is deleted, only the way and no nodes are deleted. 119 112 * 120 113 * @param selection The list of all object to be deleted. … … 134 127 * inform the user and do not delete. 135 128 * 136 * If deleting a node which is part of exactly two segments, and both segments 137 * have no conflicting keys, join them and remove the node. 138 * If the two segments are part of the same way, remove the deleted segment 139 * from the way. 129 * If a node is to be deleted which is in the middle of exactly one way, 130 * the node is removed from the way's node list and after that removed 131 * itself. 140 132 * 141 133 * @param selection The objects to delete. … … 149 141 if (!selection.containsAll(v.data)) { 150 142 if (osm instanceof Node && joinIfPossible) { 151 String reason = deleteNodeAndJoin Segment((Node)osm);143 String reason = deleteNodeAndJoinWay((Node)osm); 152 144 if (reason != null && msgBox) { 153 145 JOptionPane.showMessageDialog(Main.parent,tr("Cannot delete node.")+" "+reason); … … 167 159 } 168 160 169 private String deleteNodeAndJoinSegment(Node n) { 170 ArrayList<Segment> segs = new ArrayList<Segment>(2); 171 for (Segment s : Main.ds.segments) { 172 if (!s.deleted && (s.from == n || s.to == n)) { 173 if (segs.size() > 1) 174 return tr("Used by more than two segments."); 175 segs.add(s); 176 } 177 } 178 if (segs.size() != 2) 179 return tr("Used by only one segment."); 180 Segment seg1 = segs.get(0); 181 Segment seg2 = segs.get(1); 182 if (seg1.from == seg2.to) { 183 Segment s = seg1; 184 seg1 = seg2; 185 seg2 = s; 186 } 187 if (seg1.from == seg2.from || seg1.to == seg2.to) 188 return tr("Wrong direction of segments."); 189 for (Entry<String, String> e : seg1.entrySet()) 190 if (seg2.keySet().contains(e.getKey()) && !seg2.get(e.getKey()).equals(e.getValue())) 191 return tr("Conflicting keys"); 192 ArrayList<Way> ways = new ArrayList<Way>(2); 161 private String deleteNodeAndJoinWay(Node n) { 162 ArrayList<Way> ways = new ArrayList<Way>(1); 193 163 for (Way w : Main.ds.ways) { 194 if (w.deleted) 195 continue; 196 if ((w.segments.contains(seg1) && !w.segments.contains(seg2)) || (w.segments.contains(seg2) && !w.segments.contains(seg1))) 197 return tr("Segments are part of different ways."); 198 if (w.segments.contains(seg1) && w.segments.contains(seg2)) 164 if (!w.deleted && w.nodes.contains(n)) { 199 165 ways.add(w); 200 166 } 201 Segment s = new Segment(seg1);202 s.to = seg2.to;203 if (s.keys == null)204 s.keys = seg2.keys;205 else if (seg2.keys != null)206 s.keys.putAll(seg2.keys);207 Collection<Command> cmds = new LinkedList<Command>();208 for (Way w : ways) {209 Way copy = new Way(w);210 copy.segments.remove(seg2);211 cmds.add(new ChangeCommand(w, copy));212 167 } 213 cmds.add(new ChangeCommand(seg1, s)); 214 cmds.add(new DeleteCommand(Arrays.asList(new OsmPrimitive[]{n, seg2}))); 215 Main.main.undoRedo.add(new SequenceCommand(tr("Delete Node"), cmds)); 168 169 if (ways.size() > 1) 170 return tr("Used by more than one way."); 171 172 if (ways.size() == 1) { 173 // node in way 174 Way w = ways.get(0); 175 176 int i = w.nodes.indexOf(n); 177 if (w.nodes.lastIndexOf(n) != i) 178 return tr("Occurs more than once in the same way."); 179 if (i == 0 || i == w.nodes.size() - 1) 180 return tr("Is at the end of a way"); 181 182 Way wnew = new Way(w); 183 wnew.nodes.remove(i); 184 185 Collection<Command> cmds = new LinkedList<Command>(); 186 cmds.add(new ChangeCommand(w, wnew)); 187 cmds.add(new DeleteCommand(Collections.singleton(n))); 188 Main.main.undoRedo.add(new SequenceCommand(tr("Delete Node"), cmds)); 189 } else { 190 // unwayed node 191 Main.main.undoRedo.add(new DeleteCommand(Collections.singleton(n))); 192 } 216 193 return null; 217 194 } -
branch/0.5/src/org/openstreetmap/josm/actions/mapmode/MapMode.java
r298 r329 15 15 /** 16 16 * A class implementing MapMode is able to be selected as an mode for map editing. 17 * As example scrolling the map is a MapMode, connecting Nodes to new Segments17 * As example scrolling the map is a MapMode, connecting Nodes to new Ways 18 18 * is another. 19 19 * -
branch/0.5/src/org/openstreetmap/josm/actions/mapmode/MoveAction.java
r312 r329 162 162 163 163 Collection<OsmPrimitive> sel = Main.ds.getSelected(); 164 OsmPrimitive osm = Main.map.mapView.getNearest(e.getPoint() , (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0);164 OsmPrimitive osm = Main.map.mapView.getNearest(e.getPoint()); 165 165 if (osm != null) { 166 166 if (!sel.contains(osm)) -
branch/0.5/src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
r298 r329 17 17 import org.openstreetmap.josm.data.osm.Node; 18 18 import org.openstreetmap.josm.data.osm.OsmPrimitive; 19 import org.openstreetmap.josm.data.osm.Segment;20 19 import org.openstreetmap.josm.gui.MapFrame; 21 20 import org.openstreetmap.josm.gui.SelectionManager; … … 55 54 * pixel are considered "only click". If that happens, the nearest Node will 56 55 * be selected if there is any within 10 pixel range. If there is no Node within 57 * 10 pixel, the nearest Segment (or Street, if user hold down the Alt-Key)58 * within 10 pixel range is selected. If there is no Segment within10 pixel59 * and the user clicked in or 10 pixel away from an area,this area is selected.60 * If there is even no area, nothing is selected.Shift and Ctrl key applies to61 * this as usual. For more,@see MapView#getNearest(Point, boolean)56 * 10 pixel, the nearest Way within 10 pixel range is selected. If there is no 57 * Way within 10 pixel and the user clicked in or 10 pixel away from an area, 58 * this area is selected. If there is even no area, nothing is selected. 59 * Shift and Ctrl key applies to this as usual. For more, 60 * @see MapView#getNearest(Point) 62 61 * 63 62 * @author imi … … 65 64 public class SelectionAction extends MapMode implements SelectionEnded { 66 65 67 enum Mode {select, straight}68 private final Mode mode;69 70 66 public static class Group extends GroupAction { 71 67 public Group(MapFrame mf) { 72 68 super(KeyEvent.VK_S,0); 73 69 putValue("help", "Action/Selection"); 74 actions.add(new SelectionAction(mf, tr("Selection"), Mode.select, tr("Select objects by dragging or clicking."))); 75 actions.add(new SelectionAction(mf, tr("Straight line"), Mode.straight, tr("Select objects in a straight line."))); 70 actions.add(new SelectionAction(mf, tr("Selection"), tr("Select objects by dragging or clicking."))); 76 71 setCurrent(0); 77 72 } … … 84 79 private SelectionManager selectionManager; 85 80 86 private Node straightStart = null;87 private Node lastEnd = null;88 private Collection<OsmPrimitive> oldSelection = null;89 90 //TODO: Implement reverse references into data objects and remove this91 private final Map<Node, Collection<Segment>> reverseSegmentMap = new HashMap<Node, Collection<Segment>>();92 93 81 /** 94 82 * Create a new SelectionAction in the given frame. 95 83 * @param mapFrame The frame this action belongs to 96 84 */ 97 public SelectionAction(MapFrame mapFrame, String name, Mode mode, String desc) { 98 super(name, "selection/"+mode, desc, mapFrame, ImageProvider.getCursor("normal", "selection")); 99 this.mode = mode; 100 putValue("help", "Action/Selection/"+Character.toUpperCase(mode.toString().charAt(0))+mode.toString().substring(1)); 85 public SelectionAction(MapFrame mapFrame, String name, String desc) { 86 super(name, "selection/select", desc, mapFrame, ImageProvider.getCursor("normal", "selection")); 87 putValue("help", "Action/Selection"); 101 88 this.selectionManager = new SelectionManager(this, false, mapFrame.mapView); 102 89 } … … 104 91 @Override public void enterMode() { 105 92 super.enterMode(); 106 if (mode == Mode.select)107 93 selectionManager.register(Main.map.mapView); 108 else {109 Main.map.mapView.addMouseMotionListener(this);110 Main.map.mapView.addMouseListener(this);111 for (Segment s : Main.ds.segments) {112 addBackReference(s.from, s);113 addBackReference(s.to, s);114 }115 }116 }117 118 private void addBackReference(Node n, Segment s) {119 Collection<Segment> c = reverseSegmentMap.get(n);120 if (c == null) {121 c = new HashSet<Segment>();122 reverseSegmentMap.put(n, c);123 }124 c.add(s);125 94 } 126 95 127 96 @Override public void exitMode() { 128 97 super.exitMode(); 129 if (mode == Mode.select)130 98 selectionManager.unregister(Main.map.mapView); 131 else {132 Main.map.mapView.removeMouseMotionListener(this);133 Main.map.mapView.removeMouseListener(this);134 reverseSegmentMap.clear();135 }136 99 } 137 100 … … 163 126 Main.map.mapView.repaint(); 164 127 } 165 166 @Override public void mouseDragged(MouseEvent e) {167 Node old = lastEnd;168 lastEnd = Main.map.mapView.getNearestNode(e.getPoint());169 if (straightStart == null)170 straightStart = lastEnd;171 if (straightStart != null && lastEnd != null && straightStart != lastEnd && old != lastEnd) {172 Collection<OsmPrimitive> path = new HashSet<OsmPrimitive>();173 Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();174 path.add(straightStart);175 calculateShortestPath(path, straightStart, lastEnd);176 if ((e.getModifiers() & MouseEvent.CTRL_MASK) != 0) {177 sel.addAll(oldSelection);178 sel.removeAll(path);179 } else if ((e.getModifiers() & MouseEvent.SHIFT_MASK) != 0) {180 sel = path;181 sel.addAll(oldSelection);182 } else183 sel = path;184 Main.ds.setSelected(sel);185 }186 }187 188 @Override public void mousePressed(MouseEvent e) {189 straightStart = Main.map.mapView.getNearestNode(e.getPoint());190 lastEnd = null;191 oldSelection = Main.ds.getSelected();192 }193 194 @Override public void mouseReleased(MouseEvent e) {195 straightStart = null;196 lastEnd = null;197 oldSelection = null;198 }199 200 /**201 * Get the shortest path by stepping through the node with a common segment with start202 * and nearest to the end (greedy algorithm).203 */204 private void calculateShortestPath(Collection<OsmPrimitive> path, Node start, Node end) {205 for (Node pivot = start; pivot != null;)206 pivot = addNearest(path, pivot, end);207 }208 209 private Node addNearest(Collection<OsmPrimitive> path, Node start, Node end) {210 Collection<Segment> c = reverseSegmentMap.get(start);211 if (c == null)212 return null; // start may be a waypoint without segments213 double min = Double.MAX_VALUE;214 Node next = null;215 Segment seg = null;216 for (Segment s : c) {217 Node other = s.from == start ? s.to : s.from;218 if (other == end) {219 next = other;220 seg = s;221 min = 0;222 break;223 }224 double distance = other.eastNorth.distance(end.eastNorth);225 if (distance < min) {226 min = distance;227 next = other;228 seg = s;229 }230 }231 if (min < start.eastNorth.distance(end.eastNorth) && next != null) {232 path.add(next);233 path.add(seg);234 return next;235 }236 return null;237 }238 128 }
Note:
See TracChangeset
for help on using the changeset viewer.