Changeset 329 in josm for branch/0.5/src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
- Timestamp:
- 2007-09-24T01:36:24+02:00 (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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 within 10 pixel59 * and the user clicked in or 10 pixel away from an area, this areais 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.