- Files:
-
- 28 added
- 12 deleted
- 45 edited
Legend:
- Unmodified
- Added
- Removed
-
/.classpath
r20 r30 2 2 <classpath> 3 3 <classpathentry kind="src" path="src"/> 4 <classpathentry including="images/" kind="src" path=""/> 4 5 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> 5 6 <classpathentry sourcepath="/home/imi/src/jdom-1.0/src" kind="lib" path="lib/jdom.jar"/> -
/src/org/openstreetmap/josm/actions/AboutAction.java
r20 r30 13 13 import java.util.regex.Pattern; 14 14 15 import javax.swing.AbstractAction;16 15 import javax.swing.JEditorPane; 17 16 import javax.swing.JLabel; … … 24 23 import javax.swing.event.HyperlinkListener; 25 24 25 import org.openstreetmap.josm.Main; 26 26 import org.openstreetmap.josm.gui.GBC; 27 27 import org.openstreetmap.josm.gui.ImageProvider; 28 import org.openstreetmap.josm.gui.Main;29 28 30 29 /** … … 36 35 * @author imi 37 36 */ 38 public class AboutAction extends AbstractAction {37 public class AboutAction extends JosmAction { 39 38 40 39 public AboutAction() { 41 super("About", ImageProvider.get("about")); 42 putValue(MNEMONIC_KEY, KeyEvent.VK_A); 43 putValue(SHORT_DESCRIPTION, "Display the about screen."); 40 super("About", "about", "Display the about screen.", KeyEvent.VK_A, null); 44 41 } 45 42 -
/src/org/openstreetmap/josm/actions/AutoScaleAction.java
r20 r30 4 4 import java.awt.event.KeyEvent; 5 5 6 import javax.swing.AbstractAction;7 import javax.swing.JComponent;8 import javax.swing.KeyStroke;9 10 import org.openstreetmap.josm.gui.ImageProvider;11 6 import org.openstreetmap.josm.gui.MapFrame; 12 7 import org.openstreetmap.josm.gui.MapView; … … 16 11 * @author imi 17 12 */ 18 public class AutoScaleAction extends AbstractAction {13 public class AutoScaleAction extends JosmAction { 19 14 /** 20 15 * The mapView this action operates on. … … 23 18 24 19 public AutoScaleAction(MapFrame mapFrame) { 25 super("Auto Scale", ImageProvider.get("autoscale")); 20 super("Auto Scale", "autoscale", "Zoom the view to show the whole layer. Disabled if the view is moved.", 21 KeyEvent.VK_A, null); 26 22 mapView = mapFrame.mapView; 27 putValue(MNEMONIC_KEY, KeyEvent.VK_A);28 putValue(SHORT_DESCRIPTION, "Zoom the view to show the whole layer. Disabled if the view is moved.");29 KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0);30 putValue(ACCELERATOR_KEY, ks);31 mapFrame.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, this);32 mapFrame.getActionMap().put(this, this);33 23 } 34 24 -
/src/org/openstreetmap/josm/actions/ExitAction.java
r20 r30 3 3 import java.awt.event.ActionEvent; 4 4 import java.awt.event.KeyEvent; 5 6 import javax.swing.AbstractAction;7 8 import org.openstreetmap.josm.gui.ImageProvider;9 5 10 6 /** … … 13 9 * @author imi 14 10 */ 15 public class ExitAction extends AbstractAction {11 public class ExitAction extends JosmAction { 16 12 17 13 /** … … 19 15 */ 20 16 public ExitAction() { 21 super("Exit", ImageProvider.get("exit")); 22 putValue(MNEMONIC_KEY, KeyEvent.VK_X); 23 putValue(SHORT_DESCRIPTION, "Exit the application."); 17 super("Exit", "exit", "Exit the application.", KeyEvent.VK_X, null); 24 18 } 25 19 -
/src/org/openstreetmap/josm/actions/OpenOsmServerAction.java
r20 r30 5 5 import java.awt.event.ActionEvent; 6 6 import java.awt.event.ActionListener; 7 import java.awt.event.InputEvent; 7 8 import java.awt.event.KeyEvent; 9 import java.io.IOException; 8 10 9 import javax.swing.AbstractAction;10 11 import javax.swing.DefaultListModel; 11 12 import javax.swing.JButton; … … 16 17 import javax.swing.JScrollPane; 17 18 import javax.swing.JTextField; 19 import javax.swing.KeyStroke; 18 20 import javax.swing.event.ListSelectionEvent; 19 21 import javax.swing.event.ListSelectionListener; 20 22 23 import org.jdom.JDOMException; 24 import org.openstreetmap.josm.Main; 21 25 import org.openstreetmap.josm.data.GeoPoint; 22 26 import org.openstreetmap.josm.data.osm.DataSet; 23 27 import org.openstreetmap.josm.gui.BookmarkList; 24 28 import org.openstreetmap.josm.gui.GBC; 25 import org.openstreetmap.josm.gui.ImageProvider;26 import org.openstreetmap.josm.gui.Main;27 29 import org.openstreetmap.josm.gui.MapFrame; 28 30 import org.openstreetmap.josm.gui.MapView; 29 31 import org.openstreetmap.josm.gui.BookmarkList.Bookmark; 30 32 import org.openstreetmap.josm.gui.layer.Layer; 31 import org.openstreetmap.josm.gui.layer.LayerFactory; 32 import org.openstreetmap.josm.io.OsmReader; 33 import org.openstreetmap.josm.io.DataReader.ConnectionException; 34 import org.openstreetmap.josm.io.DataReader.ParseException; 33 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 34 import org.openstreetmap.josm.gui.layer.RawGpsDataLayer; 35 import org.openstreetmap.josm.io.OsmServerReader; 35 36 36 37 /** … … 42 43 * @author imi 43 44 */ 44 public class OpenOsmServerAction extends AbstractAction {45 public class OpenOsmServerAction extends JosmAction { 45 46 46 privateJTextField[] latlon = new JTextField[]{47 JTextField[] latlon = new JTextField[]{ 47 48 new JTextField(9), 48 49 new JTextField(9), 49 50 new JTextField(9), 50 51 new JTextField(9)}; 51 privateJCheckBox rawGps = new JCheckBox("Open as raw gps data", false);52 JCheckBox rawGps = new JCheckBox("Open as raw gps data", false); 52 53 53 54 public OpenOsmServerAction() { 54 super("Connect to OSM", ImageProvider.get("connectosm")); 55 putValue(MNEMONIC_KEY, KeyEvent.VK_C); 56 putValue(SHORT_DESCRIPTION, "Open a connection to the OSM server."); 55 super("Connect to OSM", "connectosm", "Open a connection to the OSM server.", KeyEvent.VK_C, 56 KeyStroke.getAWTKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)); 57 57 } 58 58 … … 82 82 for (JTextField f : latlon) 83 83 f.setCaretPosition(0); 84 rawGps.setSelected( !mv.getActiveLayer().isEditable());84 rawGps.setSelected(mv.getActiveLayer() instanceof RawGpsDataLayer); 85 85 } 86 86 … … 144 144 return; 145 145 } 146 Osm Reader osmReader = new OsmReader(Main.pref.osmDataServer,147 rawGps.isSelected(),b.latlon[0], b.latlon[1], b.latlon[2], b.latlon[3]);146 OsmServerReader osmReader = new OsmServerReader(Main.pref.osmDataServer, 147 b.latlon[0], b.latlon[1], b.latlon[2], b.latlon[3]); 148 148 try { 149 DataSet dataSet = osmReader.parse();150 if (dataSet == null)151 return; // user cancelled download152 if (dataSet.nodes.isEmpty())153 JOptionPane.showMessageDialog(Main.main, "No data imported.");154 155 149 String name = latlon[0].getText()+" "+latlon[1].getText()+" x "+ 156 150 latlon[2].getText()+" "+latlon[3].getText(); 157 151 158 Layer layer = LayerFactory.create(dataSet, name, rawGps.isSelected()); 152 Layer layer; 153 if (rawGps.isSelected()) { 154 layer = new RawGpsDataLayer(osmReader.parseRawGps(), name); 155 } else { 156 DataSet dataSet = osmReader.parseOsm(); 157 if (dataSet == null) 158 return; // user cancelled download 159 if (dataSet.nodes.isEmpty()) 160 JOptionPane.showMessageDialog(Main.main, "No data imported."); 161 162 layer = new OsmDataLayer(dataSet, name); 163 } 159 164 160 165 if (Main.main.getMapFrame() == null) … … 162 167 else 163 168 Main.main.getMapFrame().mapView.addLayer(layer); 164 } catch ( ParseException x) {169 } catch (JDOMException x) { 165 170 x.printStackTrace(); 166 171 JOptionPane.showMessageDialog(Main.main, x.getMessage()); 167 } catch ( ConnectionException x) {172 } catch (IOException x) { 168 173 x.printStackTrace(); 169 174 JOptionPane.showMessageDialog(Main.main, x.getMessage()); … … 178 183 * checkbox. 179 184 */ 180 privateBookmark readBookmark() {185 Bookmark readBookmark() { 181 186 try { 182 187 Bookmark b = new Bookmark(); -
/src/org/openstreetmap/josm/actions/PreferencesAction.java
r20 r30 4 4 import java.awt.event.KeyEvent; 5 5 6 import javax.swing.AbstractAction;7 8 import org.openstreetmap.josm.gui.ImageProvider;9 6 import org.openstreetmap.josm.gui.PreferenceDialog; 10 7 … … 14 11 * @author imi 15 12 */ 16 public class PreferencesAction extends AbstractAction {13 public class PreferencesAction extends JosmAction { 17 14 18 15 /** … … 20 17 */ 21 18 public PreferencesAction() { 22 super("Preferences", ImageProvider.get("preference")); 23 putValue(MNEMONIC_KEY, KeyEvent.VK_P); 24 putValue(SHORT_DESCRIPTION, "Open a preferences page for global settings."); 19 super("Preferences", "preference", "Open a preferences page for global settings.", 20 KeyEvent.VK_P, null); 25 21 } 26 22 -
/src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java
r20 r30 4 4 import java.awt.Graphics; 5 5 import java.awt.Point; 6 import java.awt.event.ActionEvent; 6 7 import java.awt.event.KeyEvent; 7 8 import java.awt.event.MouseEvent; 8 9 import java.awt.event.MouseListener; 9 10 10 import javax.swing.JOptionPane; 11 12 import org.openstreetmap.josm.data.osm.DataSet; 11 import org.openstreetmap.josm.Main; 12 import org.openstreetmap.josm.command.AddCommand; 13 13 import org.openstreetmap.josm.data.osm.LineSegment; 14 14 import org.openstreetmap.josm.data.osm.Node; 15 15 import org.openstreetmap.josm.data.osm.OsmPrimitive; 16 import org.openstreetmap.josm.data.osm.Track;17 import org.openstreetmap.josm.gui.Main;18 16 import org.openstreetmap.josm.gui.MapFrame; 19 17 … … 22 20 * starting node and dragging to the ending node. 23 21 * 24 * If the Alt key was pressed when releasing the mouse, this action tries to25 * add the line segment to a track. The new line segment gets added to all tracks26 * of the first node that end in the first node. If no tracks are found, the27 * line segment gets added to all tracks in the second node that start with28 * the second node.29 *30 22 * No line segment can be created if there is already a line segment containing 31 * both nodes in the same order.23 * both nodes. 32 24 * 33 25 * @author imi … … 54 46 */ 55 47 public AddLineSegmentAction(MapFrame mapFrame) { 56 super("Add Line Segment", "addlinesegment", "Add a line segment between two nodes.", KeyEvent.VK_ L, mapFrame);48 super("Add Line Segment", "addlinesegment", "Add a line segment between two nodes.", KeyEvent.VK_G, mapFrame); 57 49 } 58 50 … … 70 62 mv.removeMouseMotionListener(this); 71 63 drawHint(false); 64 } 65 66 67 @Override 68 public void actionPerformed(ActionEvent e) { 69 super.actionPerformed(e); 70 makeLineSegment(); 72 71 } 73 72 … … 108 107 109 108 /** 109 * If left button was released, try to create the line segment. 110 */ 111 @Override 112 public void mouseReleased(MouseEvent e) { 113 if (e.getButton() == MouseEvent.BUTTON1) { 114 makeLineSegment(); 115 first = null; // release line segment drawing 116 } 117 } 118 119 /** 110 120 * Create the line segment if first and second are different and there is 111 121 * not already a line segment. 112 122 */ 113 @Override 114 public void mouseReleased(MouseEvent e) { 115 if (e.getButton() != MouseEvent.BUTTON1) 116 return; 117 123 private void makeLineSegment() { 118 124 if (first == null || second == null) { 119 125 first = null; … … 126 132 Node start = first; 127 133 Node end = second; 128 first = null;134 first = second; 129 135 second = null; 130 136 131 137 if (start != end) { 132 DataSet ds = mv.getActiveDataSet();133 134 138 // try to find a line segment 135 for (Track t : ds.tracks()) 136 for (LineSegment ls : t.segments()) 137 if (start == ls.getStart() && end == ls.getEnd()) { 138 JOptionPane.showMessageDialog(Main.main, "There is already an line segment with the same direction between the selected nodes."); 139 return; 140 } 139 for (LineSegment ls : Main.main.ds.lineSegments) 140 if ((start == ls.start && end == ls.end) || (end == ls.start && start == ls.end)) 141 return; // already a line segment here - be happy, do nothing. 141 142 142 143 LineSegment ls = new LineSegment(start, end); 143 boolean foundTrack = false; 144 mv.editLayer().add(new AddCommand(Main.main.ds, ls)); 145 } 144 146 145 if (((e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0)) {146 // find a track for the new line segment147 for (Track t : ds.tracks()) {148 if (t.getEndingNode() == start) {149 t.add(ls);150 foundTrack = true;151 }152 }153 if (!foundTrack) {154 for (Track t : ds.tracks()) {155 if (t.getStartingNode() == end) {156 t.addStart(ls);157 foundTrack = true;158 }159 }160 }161 }162 if (!foundTrack)163 ds.addPendingLineSegment(ls);164 }165 166 147 mv.repaint(); 167 148 } … … 186 167 hintDrawn = !hintDrawn; 187 168 } 188 189 @Override190 protected boolean isEditMode() {191 return true;192 }193 169 } -
/src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java
r20 r30 4 4 import java.awt.event.MouseEvent; 5 5 6 import org.openstreetmap.josm.Main; 7 import org.openstreetmap.josm.command.AddCommand; 6 8 import org.openstreetmap.josm.data.osm.Node; 7 9 import org.openstreetmap.josm.gui.MapFrame; … … 48 50 Node node = new Node(); 49 51 node.coor = mv.getPoint(e.getX(), e.getY(), true); 50 mv. getActiveDataSet().nodes.add(node);52 mv.editLayer().add(new AddCommand(Main.main.ds, node)); 51 53 mv.repaint(); 52 54 } 53 55 } 54 55 @Override56 protected boolean isEditMode() {57 return true;58 }59 56 } -
/src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java
r20 r30 2 2 3 3 import java.awt.Rectangle; 4 import java.awt.event.ActionEvent; 4 5 import java.awt.event.KeyEvent; 5 6 import java.util.Collection; 7 import java.util.Iterator; 6 8 import java.util.LinkedList; 7 9 8 import org.openstreetmap.josm.data.osm.DataSet; 10 import org.openstreetmap.josm.Main; 11 import org.openstreetmap.josm.command.AddCommand; 9 12 import org.openstreetmap.josm.data.osm.LineSegment; 10 13 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 59 62 } 60 63 64 65 @Override 66 public void actionPerformed(ActionEvent e) { 67 makeTrack(); 68 super.actionPerformed(e); 69 } 70 61 71 /** 62 72 * If Shift is pressed, only add the selected line segments to the selection. … … 76 86 return; // not allowed together 77 87 78 DataSet ds = mv.getActiveDataSet();79 80 88 if (!ctrl && !shift) 81 ds.clearSelection(); // new selection will replace the old.89 Main.main.ds.clearSelection(); // new selection will replace the old. 82 90 83 91 Collection<OsmPrimitive> selectionList = selectionManager.getObjectsInRectangle(r,alt); 84 92 for (OsmPrimitive osm : selectionList) 85 osm.setSelected(!ctrl , ds);93 osm.setSelected(!ctrl); 86 94 87 95 mv.repaint(); // from now on, the map has to be repainted. … … 90 98 return; // no new track yet. 91 99 92 Collection<OsmPrimitive> selection = ds.getSelected(); 100 makeTrack(); 101 } 102 103 /** 104 * Just make a track of all selected items. 105 */ 106 private void makeTrack() { 107 Collection<OsmPrimitive> selection = Main.main.ds.getSelected(); 93 108 if (selection.isEmpty()) 94 109 return; … … 98 113 for (OsmPrimitive osm : selection) { 99 114 if (osm instanceof Track) 100 lineSegments.addAll(((Track)osm).segments ());115 lineSegments.addAll(((Track)osm).segments); 101 116 else if (osm instanceof LineSegment) 102 117 lineSegments.add((LineSegment)osm); 103 118 } 119 120 // sort the line segments in best possible order. This is done by: 121 // 0 if no elements in list, quit 122 // 1 taking the first ls as pivot, remove it from list 123 // 2 searching for a connection at start or end of pivot 124 // 3 if found, attach it, remove it from list, goto 2 125 // 4 if not found, save the pivot-string and goto 0 126 LinkedList<LineSegment> sortedLineSegments = new LinkedList<LineSegment>(); 127 while (!lineSegments.isEmpty()) { 128 LinkedList<LineSegment> pivotList = new LinkedList<LineSegment>(); 129 pivotList.add(lineSegments.getFirst()); 130 lineSegments.removeFirst(); 131 for (boolean found = true; found;) { 132 found = false; 133 for (Iterator<LineSegment> it = lineSegments.iterator(); it.hasNext();) { 134 LineSegment ls = it.next(); 135 if (ls.start == pivotList.getLast().end) { 136 pivotList.addLast(ls); 137 it.remove(); 138 found = true; 139 } else if (ls.end == pivotList.getFirst().start) { 140 pivotList.addFirst(ls); 141 it.remove(); 142 found = true; 143 } 144 } 145 } 146 sortedLineSegments.addAll(pivotList); 147 } 148 104 149 Track t = new Track(); 105 for (LineSegment ls : lineSegments) 106 ds.assignPendingLineSegment(ls, t, true); 107 ds.addTrack(t); 108 ds.clearSelection(); 109 } 110 111 @Override 112 protected boolean isEditMode() { 113 return true; 150 for (LineSegment ls : sortedLineSegments) 151 t.add(ls); 152 mv.editLayer().add(new AddCommand(Main.main.ds, t)); 153 Main.main.ds.clearSelection(); 154 mv.repaint(); 114 155 } 115 156 } -
/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
r20 r30 1 1 package org.openstreetmap.josm.actions.mapmode; 2 2 3 import java.awt.event.ActionEvent; 3 4 import java.awt.event.KeyEvent; 4 5 import java.awt.event.MouseEvent; 5 6 import java.util.ArrayList; 6 import java.util.HashMap; 7 import java.util.Collection; 8 import java.util.HashSet; 9 import java.util.Iterator; 7 10 import java.util.LinkedList; 8 import java.util.Map;9 11 10 12 import javax.swing.JOptionPane; 11 13 14 import org.openstreetmap.josm.Main; 15 import org.openstreetmap.josm.command.CombineAndDeleteCommand; 16 import org.openstreetmap.josm.command.DeleteCommand; 12 17 import org.openstreetmap.josm.data.osm.DataSet; 13 import org.openstreetmap.josm.data.osm.Key;14 18 import org.openstreetmap.josm.data.osm.LineSegment; 15 19 import org.openstreetmap.josm.data.osm.Node; 16 20 import org.openstreetmap.josm.data.osm.OsmPrimitive; 17 21 import org.openstreetmap.josm.data.osm.Track; 18 import org.openstreetmap.josm.gui.Main;19 22 import org.openstreetmap.josm.gui.MapFrame; 20 23 … … 32 35 * tries to combine the referencing objects as follows: 33 36 * 34 * If a node is part of exactly two line segments from a track, the two line 35 * segments are combined into one. The first line segment spans now to the end 36 * of the second and the second line segment gets deleted. This is checked for 37 * every track. 38 * 39 * If a node is the end of the ending line segment of one track and the start of 40 * exactly one other tracks start segment, the tracks are combined into one track, 41 * deleting the second track and keeping the first one. The ending line segment 42 * of the fist track is combined with the starting line segment of the second 43 * track. 37 * If a node is part of exactly two line segments, the two line segments are 38 * combined into one. The first line segment spans now to the end of the 39 * second and the second line segment gets deleted. 44 40 * 45 41 * Combining is only possible, if both objects that should be combined have no … … 55 51 * 56 52 * If the user enters the mapmode and any object is selected, all selected 57 * objects get deleted. Combining applies to the selected objects.53 * objects that can be deleted will. Combining applies to the selected objects. 58 54 * 59 55 * @author imi … … 66 62 */ 67 63 public DeleteAction(MapFrame mapFrame) { 68 super("Delete", "delete", "Delete nodes, streets or areas.", KeyEvent.VK_D ELETE, mapFrame);64 super("Delete", "delete", "Delete nodes, streets or areas.", KeyEvent.VK_D, mapFrame); 69 65 } 70 66 … … 81 77 } 82 78 79 80 @Override 81 public void actionPerformed(ActionEvent e) { 82 super.actionPerformed(e); 83 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 84 Collection<OsmPrimitive> selection = Main.main.ds.getSelected(); 85 86 int selSize = 0; 87 // loop as long as the selection size changes 88 while(selSize != selection.size()) { 89 selSize = selection.size(); 90 91 for (Iterator<OsmPrimitive> it = selection.iterator(); it.hasNext();) { 92 OsmPrimitive osm = it.next(); 93 if (ctrl) { 94 deleteWithReferences(osm); 95 it.remove(); 96 } else { 97 if (delete(osm, false)) 98 it.remove(); 99 } 100 } 101 } 102 mv.repaint(); 103 } 104 83 105 /** 84 106 * If user clicked with the left button, delete the nearest object. … … 94 116 return; 95 117 96 DataSet ds = mv.getActiveDataSet();97 98 118 if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0) 99 deleteWithReferences(sel , ds);119 deleteWithReferences(sel); 100 120 else 101 delete(sel, ds);121 delete(sel, true); 102 122 103 123 mv.repaint(); … … 126 146 * TODO If you delete x, then a,B,C and x gets deleted. A now consist of b only. 127 147 * If you delete a or b, then A, a, b and z gets deleted. 128 * 148 * 129 149 * @param osm The object to delete. 130 150 */ 131 private void deleteWithReferences(OsmPrimitive osm , DataSet ds) {132 // collect all tracks, areas and pendingline segments that should be deleted151 private void deleteWithReferences(OsmPrimitive osm) { 152 // collect all tracks, areas and line segments that should be deleted 133 153 ArrayList<Track> tracksToDelete = new ArrayList<Track>(); 134 154 ArrayList<LineSegment> lineSegmentsToDelete = new ArrayList<LineSegment>(); … … 136 156 if (osm instanceof Node) { 137 157 // delete any track and line segment the node is in. 138 for (Track t : ds.tracks())139 for (LineSegment ls : t.segments ())140 if (ls. getStart() == osm || ls.getEnd()== osm)158 for (Track t : Main.main.ds.tracks) 159 for (LineSegment ls : t.segments) 160 if (ls.start == osm || ls.end == osm) 141 161 tracksToDelete.add(t); 142 for (LineSegment ls : ds.pendingLineSegments())143 if (ls. getStart() == osm || ls.getEnd()== osm)162 for (LineSegment ls : Main.main.ds.lineSegments) 163 if (ls.start == osm || ls.end == osm) 144 164 lineSegmentsToDelete.add(ls); 145 165 … … 147 167 LineSegment lineSegment = (LineSegment)osm; 148 168 lineSegmentsToDelete.add(lineSegment); 149 for (Track t : ds.tracks())150 for (LineSegment ls : t.segments ())169 for (Track t : Main.main.ds.tracks) 170 for (LineSegment ls : t.segments) 151 171 if (lineSegment == ls) 152 172 tracksToDelete.add(t); … … 157 177 ArrayList<Node> checkUnreferencing = new ArrayList<Node>(); 158 178 for (Track t : tracksToDelete) { 159 for (LineSegment ls : t.segments ()) {160 checkUnreferencing.add(ls. getStart());161 checkUnreferencing.add(ls. getEnd());179 for (LineSegment ls : t.segments) { 180 checkUnreferencing.add(ls.start); 181 checkUnreferencing.add(ls.end); 162 182 } 163 183 } 164 184 for (LineSegment ls : lineSegmentsToDelete) { 165 checkUnreferencing.add(ls.getStart()); 166 checkUnreferencing.add(ls.getEnd()); 167 } 168 169 // delete tracks and areas 170 for (Track t : tracksToDelete) 171 ds.removeTrack(t); 172 for (LineSegment ls : lineSegmentsToDelete) 173 ds.destroyPendingLineSegment(ls); 174 185 checkUnreferencing.add(ls.start); 186 checkUnreferencing.add(ls.end); 187 } 188 189 Collection<OsmPrimitive> deleteData = new LinkedList<OsmPrimitive>(); 190 deleteData.addAll(tracksToDelete); 191 deleteData.addAll(lineSegmentsToDelete); 175 192 // removing all unreferenced nodes 176 for (Node n : checkUnreferencing) { 177 if (!isReferenced(n, ds)) 178 ds.nodes.remove(n); 179 } 193 for (Node n : checkUnreferencing) 194 if (!isReferenced(n)) 195 deleteData.add(n); 180 196 // now, all references are killed. Delete the node (if it was a node) 181 197 if (osm instanceof Node) 182 ds.nodes.remove(osm); 198 deleteData.add(osm); 199 200 mv.editLayer().add(new DeleteCommand(Main.main.ds, deleteData)); 183 201 } 184 202 … … 189 207 * 190 208 * @param osm The object to delete. 191 */ 192 private void delete(OsmPrimitive osm, DataSet ds) { 193 if (osm instanceof Node) { 194 Node n = (Node)osm; 195 if (isReferenced(n, ds)) { 196 String combined = combine(n, ds); 197 if (combined != null) { 198 JOptionPane.showMessageDialog(Main.main, combined); 199 return; 200 } 201 } 202 // now, the node isn't referenced anymore, so delete it. 203 ds.nodes.remove(n); 204 } else if (osm instanceof LineSegment) { 205 LinkedList<Track> tracksToDelete = new LinkedList<Track>(); 206 for (Track t : ds.tracks()) { 207 t.remove((LineSegment)osm); 208 if (t.segments().isEmpty()) 209 tracksToDelete.add(t); 210 } 211 for (Track t : tracksToDelete) 212 ds.removeTrack(t); 213 ds.destroyPendingLineSegment((LineSegment)osm); 214 } else if (osm instanceof Track) { 215 ds.removeTrack((Track)osm); 216 for (LineSegment ls : ((Track)osm).segments()) 217 ds.addPendingLineSegment(ls); 218 } 209 * @param msgBox Whether a message box for errors should be shown 210 * @return <code>true</code> if the object could be deleted 211 */ 212 private boolean delete(OsmPrimitive osm, boolean msgBox) { 213 if (osm instanceof Node && isReferenced((Node)osm)) 214 return combineAndDelete((Node)osm, msgBox); 215 Collection<OsmPrimitive> c = new LinkedList<OsmPrimitive>(); 216 c.add(osm); 217 mv.editLayer().add(new DeleteCommand(Main.main.ds, c)); 218 return true; 219 219 } 220 220 … … 225 225 * @return Whether the node is used by a track or area. 226 226 */ 227 private boolean isReferenced(Node n, DataSet ds) { 228 for (Track t : ds.tracks()) 229 for (LineSegment ls : t.segments()) 230 if (ls.getStart() == n || ls.getEnd() == n) 231 return true; 232 for (LineSegment ls : ds.pendingLineSegments()) 233 if (ls.getStart() == n || ls.getEnd() == n) 227 private boolean isReferenced(Node n) { 228 for (LineSegment ls : Main.main.ds.lineSegments) 229 if (ls.start == n || ls.end == n) 234 230 return true; 235 231 // TODO areas … … 243 239 * 244 240 * @param n The node that is going to be deleted. 245 * @return <code>null</code> if combining suceded or an error string if there 246 * are problems combining the node. 247 */ 248 private String combine(Node n, DataSet ds) { 249 // first, check for pending line segments 250 for (LineSegment ls : ds.pendingLineSegments()) 251 if (n == ls.getStart() || n == ls.getEnd()) 252 return "Node used by a line segment which is not part of any track. Remove this first."; 253 254 // These line segments must be combined within the track combining 255 ArrayList<LineSegment> pendingLineSegmentsForTrack = new ArrayList<LineSegment>(); 256 257 // try to combine line segments 258 259 // These line segments are combinable. The inner arraylist has always 260 // two elements. The keys maps to the track, the line segments are in. 261 HashMap<ArrayList<LineSegment>, Track> lineSegments = new HashMap<ArrayList<LineSegment>, Track>(); 262 263 for (Track t : ds.tracks()) { 264 ArrayList<LineSegment> current = new ArrayList<LineSegment>(); 265 for (LineSegment ls : t.segments()) 266 if (ls.getStart() == n || ls.getEnd() == n) 267 current.add(ls); 268 if (!current.isEmpty()) { 269 if (current.size() > 2) 270 return "Node used by more than two line segments."; 271 if (current.size() == 1 && 272 (current.get(0) == t.getStartingSegment() || current.get(0) == t.getEndingSegment())) 273 pendingLineSegmentsForTrack.add(current.get(0)); 274 else if (current.get(0).getEnd() != current.get(1).getStart() && 275 current.get(1).getEnd() != current.get(0).getStart()) 276 return "Node used by line segments that points together."; 277 else if (!current.get(0).keyPropertiesMergable(current.get(1))) 278 return "Node used by line segments with different properties."; 279 else 280 lineSegments.put(current, t); 281 } 282 } 283 284 // try to combine tracks 285 ArrayList<Track> tracks = new ArrayList<Track>(); 286 for (Track t : ds.tracks()) 287 if (t.getStartingNode() == n || t.getEndingNode() == n) 288 tracks.add(t); 289 if (!tracks.isEmpty()) { 290 if (tracks.size() > 2) 291 return "Node used by more than two tracks."; 292 if (tracks.size() == 1) 293 return "Node used by a track."; 294 Track t1 = tracks.get(0); 295 Track t2 = tracks.get(1); 296 if (t1.getStartingNode() != t2.getEndingNode() && 297 t2.getStartingNode() != t1.getEndingNode()) { 298 if (t1.getStartingNode() == t2.getStartingNode() || 299 t1.getEndingNode() == t2.getEndingNode()) 300 return "Node used by tracks that point together."; 301 return "Node used by tracks that cannot be combined."; 302 } 303 if (!t1.keyPropertiesMergable(t2)) 304 return "Node used by tracks with different properties."; 305 } 306 307 // try to match the pending line segments 308 if (pendingLineSegmentsForTrack.size() == 2) { 309 LineSegment l1 = pendingLineSegmentsForTrack.get(0); 310 LineSegment l2 = pendingLineSegmentsForTrack.get(1); 311 if (l1.getStart() == l2.getStart() || l1.getEnd() == l2.getEnd()) 312 return "Node used by line segments that points together."; 313 if (l1.getStart() == l2.getEnd() || l2.getStart() == l1.getEnd()) 314 pendingLineSegmentsForTrack.clear(); // resolved. 315 } 316 317 // still pending line segments? 318 if (!pendingLineSegmentsForTrack.isEmpty()) 319 return "Node used by tracks that cannot be combined."; 241 * @param msgBox Whether a message box should be displayed in case of problems 242 * @return <code>true</code> if combining suceded. 243 */ 244 private boolean combineAndDelete(Node n, boolean msgBox) { 245 DataSet ds = Main.main.ds; 246 Collection<LineSegment> lineSegmentsUsed = new HashSet<LineSegment>(); 247 for (LineSegment ls : ds.lineSegments) 248 if (ls.start == n || ls.end == n) 249 lineSegmentsUsed.add(ls); 250 251 if (lineSegmentsUsed.isEmpty()) 252 // should not be called 253 throw new IllegalStateException(); 254 255 if (lineSegmentsUsed.size() == 1) { 256 if (msgBox) 257 JOptionPane.showMessageDialog(Main.main, "Node used by a line segment. Delete this first."); 258 return false; 259 } 260 261 if (lineSegmentsUsed.size() > 2) { 262 if (msgBox) 263 JOptionPane.showMessageDialog(Main.main, "Node used by more than two line segments. Delete them first."); 264 return false; 265 } 266 267 Iterator<LineSegment> it = lineSegmentsUsed.iterator(); 268 LineSegment first = it.next(); 269 LineSegment second = it.next(); 270 271 // wrong direction? 272 if (first.start == second.end) { 273 LineSegment t = first; 274 first = second; 275 second = t; 276 } 277 278 // combinable? 279 if (first.end != second.start || !first.end.keyPropertiesMergable(second.start)) { 280 if (msgBox) 281 JOptionPane.showMessageDialog(Main.main, "Node used by line segments that cannot be combined."); 282 return false; 283 } 320 284 321 285 // Ok, we can combine. Do it. 322 // line segments 323 for (ArrayList<LineSegment> list : lineSegments.keySet()) { 324 LineSegment first = list.get(0); 325 LineSegment second = list.get(1); 326 if (first.getStart() == second.getEnd()) { 327 first = second; 328 second = list.get(0); 329 } 330 first.setEnd(second.getEnd()); 331 first.keys = mergeKeys(first.keys, second.keys); 332 lineSegments.get(list).remove(second); 333 } 334 335 // tracks 336 if (!tracks.isEmpty()) { 337 Track first = tracks.get(0); 338 Track second = tracks.get(1); 339 if (first.getStartingNode() == second.getEndingNode()) { 340 first = second; 341 second = tracks.get(0); 342 } 343 // concatenate the line segments. 344 LineSegment lastOfFirst = first.getEndingSegment(); 345 LineSegment firstOfSecond = second.getStartingSegment(); 346 lastOfFirst.setEnd(firstOfSecond.getEnd()); 347 lastOfFirst.keys = mergeKeys(lastOfFirst.keys, firstOfSecond.keys); 348 second.remove(firstOfSecond); 349 // move the remaining line segments to first track. 350 first.addAll(second.segments()); 351 ds.removeTrack(second); 352 } 353 354 return null; 355 } 356 357 /** 358 * Merges the second parameter into the first and return the merged map. 359 * @param first The first map that will hold keys. 360 * @param second The map to merge with the first. 361 * @return The merged key map. 362 */ 363 private Map<Key, String> mergeKeys(Map<Key, String> first, Map<Key, String> second) { 364 if (first == null) 365 first = second; 366 else if (second != null && first != null) 367 first.putAll(second); 368 return first; 369 } 370 371 @Override 372 protected boolean isEditMode() { 286 mv.editLayer().add(new CombineAndDeleteCommand(ds, first, second)); 373 287 return true; 374 288 } -
/src/org/openstreetmap/josm/actions/mapmode/MapMode.java
r20 r30 6 6 import java.awt.event.MouseMotionListener; 7 7 8 import javax.swing.AbstractAction; 9 import javax.swing.JComponent; 10 import javax.swing.KeyStroke; 11 12 import org.openstreetmap.josm.gui.ImageProvider; 8 import org.openstreetmap.josm.actions.JosmAction; 13 9 import org.openstreetmap.josm.gui.MapFrame; 14 10 import org.openstreetmap.josm.gui.MapView; 15 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;16 import org.openstreetmap.josm.gui.layer.Layer;17 11 18 12 /** … … 24 18 * control. 25 19 */ 26 abstract public class MapMode extends AbstractAction implements MouseListener, MouseMotionListener {20 abstract public class MapMode extends JosmAction implements MouseListener, MouseMotionListener { 27 21 28 22 /** … … 42 36 */ 43 37 public MapMode(String name, String iconName, String tooltip, int mnemonic, MapFrame mapFrame) { 44 super(name, ImageProvider.get("mapmode", iconName)); 45 putValue(MNEMONIC_KEY, mnemonic); 46 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(mnemonic,0)); 47 putValue(LONG_DESCRIPTION, tooltip); 48 mapFrame.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(mnemonic,0), this); 49 mapFrame.getActionMap().put(this, this); 38 super(name, "mapmode/"+iconName, tooltip, mnemonic, null); 50 39 this.mapFrame = mapFrame; 51 40 mv = mapFrame.mapView; 52 mv.addLayerChangeListener(new LayerChangeListener(){53 public void activeLayerChange(Layer oldLayer, Layer newLayer) {54 setEnabled(!isEditMode() || newLayer.isEditable());55 }56 public void layerAdded(Layer newLayer) {}57 public void layerRemoved(Layer oldLayer) {}58 });59 41 } 60 61 /**62 * Subclasses should return whether they want to edit the map data or63 * whether they are read-only.64 */65 abstract protected boolean isEditMode();66 42 67 43 /** … … 87 63 mapFrame.selectMapMode(this); 88 64 } 89 65 90 66 /** 91 67 * Does nothing. Only to subclass. -
/src/org/openstreetmap/josm/actions/mapmode/MoveAction.java
r20 r30 6 6 import java.awt.event.MouseEvent; 7 7 import java.util.Collection; 8 import java.util.HashSet;9 8 10 import org.openstreetmap.josm.data.osm.DataSet; 11 import org.openstreetmap.josm.data.osm.Node; 9 import org.openstreetmap.josm.Main; 10 import org.openstreetmap.josm.command.MoveCommand; 11 import org.openstreetmap.josm.data.GeoPoint; 12 12 import org.openstreetmap.josm.data.osm.OsmPrimitive; 13 13 import org.openstreetmap.josm.gui.MapFrame; … … 75 75 } 76 76 77 int dx = e.getX() - mousePos.x; 78 int dy = e.getY() - mousePos.y; 77 GeoPoint mouseGeo = mv.getPoint(e.getX(), e.getY(), false); 78 GeoPoint mouseStartGeo = mv.getPoint(mousePos.x, mousePos.y, false); 79 double dx = mouseGeo.x - mouseStartGeo.x; 80 double dy = mouseGeo.y - mouseStartGeo.y; 79 81 if (dx == 0 && dy == 0) 80 82 return; 81 83 82 Collection<OsmPrimitive> selection = mv.getActiveDataSet().getSelected(); 83 // creating a list of all nodes that should be moved. 84 Collection<Node> movingNodes = new HashSet<Node>(); 85 for (OsmPrimitive osm : selection) 86 movingNodes.addAll(osm.getAllNodes()); 87 88 for (Node n : movingNodes) { 89 Point pos = mv.getScreenPoint(n.coor); 90 pos.x += dx; 91 pos.y += dy; 92 n.coor = mv.getPoint(pos.x, pos.y, true); 93 } 84 Collection<OsmPrimitive> selection = Main.main.ds.getSelected(); 85 mv.editLayer().add(new MoveCommand(selection, dx, dy)); 86 94 87 mv.repaint(); 95 96 88 mousePos = e.getPoint(); 97 89 } … … 111 103 return; 112 104 113 DataSet ds = mv.getActiveDataSet(); 114 115 if (ds.getSelected().size() == 0) { 105 if (Main.main.ds.getSelected().size() == 0) { 116 106 OsmPrimitive osm = mv.getNearest(e.getPoint(), (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0); 117 107 if (osm != null) 118 osm.setSelected(true , ds);108 osm.setSelected(true); 119 109 singleOsmPrimitive = osm; 120 110 mv.repaint(); … … 134 124 mv.setCursor(oldCursor); 135 125 if (singleOsmPrimitive != null) { 136 singleOsmPrimitive.setSelected(false , mv.getActiveDataSet());126 singleOsmPrimitive.setSelected(false); 137 127 mv.repaint(); 138 128 } 139 129 } 140 141 @Override142 protected boolean isEditMode() {143 return true;144 }145 130 } -
/src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
r20 r30 5 5 import java.util.Collection; 6 6 7 import org.openstreetmap.josm. data.osm.DataSet;7 import org.openstreetmap.josm.Main; 8 8 import org.openstreetmap.josm.data.osm.OsmPrimitive; 9 9 import org.openstreetmap.josm.gui.MapFrame; … … 87 87 return; // not allowed together 88 88 89 DataSet ds = mv.getActiveDataSet();90 91 89 if (!ctrl && !shift) 92 ds.clearSelection(); // new selection will replace the old.90 Main.main.ds.clearSelection(); // new selection will replace the old. 93 91 94 92 Collection<OsmPrimitive> selectionList = selectionManager.getObjectsInRectangle(r,alt); 95 93 for (OsmPrimitive osm : selectionList) 96 osm.setSelected(!ctrl , ds);94 osm.setSelected(!ctrl); 97 95 mv.repaint(); 98 96 } 99 100 @Override101 protected boolean isEditMode() {102 return false;103 }104 97 } -
/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
r20 r30 68 68 selectionManager.unregister(mv); 69 69 } 70 71 @Override72 protected boolean isEditMode() {73 return false;74 }75 70 } -
/src/org/openstreetmap/josm/data/Bounds.java
r20 r30 45 45 this.max = max; 46 46 } 47 48 /** 49 * @return The bounding rectangle that covers <code>this</code> and 50 * the <code>other</code> bounds, regarding the x/y values. 51 */ 52 public Bounds mergeXY(Bounds other) { 53 GeoPoint nmin = new GeoPoint(); 54 nmin.x = Math.min(min.x, other.min.x); 55 nmin.y = Math.min(min.y, other.min.y); 56 GeoPoint nmax = new GeoPoint(); 57 nmax.x = Math.max(max.x, other.max.x); 58 nmax.y = Math.max(max.y, other.max.y); 59 return new Bounds(nmin, nmax); 60 } 61 62 /** 63 * @return The bounding rectangle that covers <code>this</code> and 64 * the <code>other</code> bounds, regarding the lat/lon values. 65 */ 66 public Bounds mergeLatLon(Bounds other) { 67 GeoPoint nmin = new GeoPoint( 68 Math.min(min.lat, other.min.lat), 69 Math.min(min.lon, other.min.lon)); 70 GeoPoint nmax = new GeoPoint( 71 Math.max(max.lat, other.max.lat), 72 Math.max(max.lon, other.max.lon)); 73 return new Bounds(nmin, nmax); 74 } 47 75 } -
/src/org/openstreetmap/josm/data/Preferences.java
r20 r30 134 134 mergeNodes = root.getChild("mergeNodes") != null; 135 135 drawRawGpsLines = root.getChild("drawRawGpsLines") != null; 136 forceRawGpsLines = root.getChild("forceRawGpsLines") != null; 136 137 } catch (Exception e) { 137 138 if (e instanceof PreferencesException) … … 156 157 if (drawRawGpsLines) 157 158 children.add(new Element("drawRawGpsLines")); 159 if (forceRawGpsLines) 160 children.add(new Element("forceRawGpsLines")); 158 161 Element osmServer = new Element("osm-server"); 159 162 osmServer.getChildren().add(new Element("url").setText(osmDataServer)); … … 177 180 } 178 181 179 180 182 // projection change listener stuff 181 183 … … 184 186 */ 185 187 private Collection<PropertyChangeListener> listener = new LinkedList<PropertyChangeListener>(); 188 186 189 /** 187 190 * Add a listener of projection changes to the list of listeners. -
/src/org/openstreetmap/josm/data/SelectionTracker.java
r20 r30 59 59 * @author imi 60 60 */ 61 private enum SelectionEventState {WAITING, COLLECTING, PURGING} ;61 private enum SelectionEventState {WAITING, COLLECTING, PURGING} 62 62 63 63 /** 64 64 * The state, regarding to the selection changing that we are in. 65 65 */ 66 transient privateSelectionEventState state = SelectionEventState.WAITING;66 transient SelectionEventState state = SelectionEventState.WAITING; 67 67 68 68 /** 69 69 * A list of listeners to selection changed events. 70 70 */ 71 transient privateCollection<SelectionChangedListener> listeners = new LinkedList<SelectionChangedListener>();71 transient Collection<SelectionChangedListener> listeners = new LinkedList<SelectionChangedListener>(); 72 72 73 73 -
/src/org/openstreetmap/josm/data/osm/DataSet.java
r20 r30 2 2 3 3 import java.util.Collection; 4 import java.util.Collections;5 4 import java.util.HashMap; 6 5 import java.util.HashSet; 7 import java.util.Iterator;8 6 import java.util.LinkedList; 9 7 import java.util.Map; 10 import java.util.Set;11 8 12 9 import org.openstreetmap.josm.data.Bounds; … … 14 11 15 12 /** 16 * DataSet is the data behind one window inthe application. It can consist of only a few17 * points up to the whole osm database. DataSet's can be merged together, split up into18 * s everal different ones, saved, (up/down/disk)loaded etc.13 * DataSet is the data behind the application. It can consist of only a few 14 * points up to the whole osm database. DataSet's can be merged together, 15 * saved, (up/down/disk)loaded etc. 19 16 * 20 * Note, that DataSet is not an osm-primitive , so it has no key association but a few21 * members to store some information.17 * Note, that DataSet is not an osm-primitive and so has no key association 18 * but a few members to store some information. 22 19 * 23 20 * @author imi 24 21 */ 25 public class DataSet extends SelectionTracker implements Cloneable{22 public class DataSet extends SelectionTracker { 26 23 27 24 /** … … 33 30 34 31 /** 35 * All pending line segments goes here. Pending line segments are those, that 36 * are in this list but are in no track. 37 */ 38 private Collection<LineSegment> pendingLineSegments = new LinkedList<LineSegment>(); 32 * All line segments goes here, even when they are in a track. 33 */ 34 public Collection<LineSegment> lineSegments = new LinkedList<LineSegment>(); 39 35 40 36 /** … … 45 41 * track list. 46 42 */ 47 private Collection<Track> tracks = new LinkedList<Track>(); 48 49 /** 50 * Add the track to the tracklist. 51 */ 52 public void addTrack(Track t) { 53 tracks.add(t); 54 } 55 /** 56 * Remove the track from the tracklist. 57 */ 58 public void removeTrack(Track t) { 59 t.destroy(); 60 tracks.remove(t); 61 } 62 /** 63 * Return a read-only collection of all tracks 64 */ 65 public Collection<Track> tracks() { 66 return Collections.unmodifiableCollection(tracks); 67 } 68 69 /** 70 * Add a newly created line segment to the pending lines list. 71 */ 72 public void addPendingLineSegment(LineSegment ls) { 73 pendingLineSegments.add(ls); 74 } 75 /** 76 * Remove a line segment from the pending lines list, because it has been 77 * assigned to the track. 78 * @param ls The line segment from the pending list 79 * @param t The track, that will hold the line segment 80 * @param end <code>true</code> to attach on the end. <code>false</code> 81 * to attach on the beginning. 82 */ 83 public void assignPendingLineSegment(LineSegment ls, Track t, boolean end) { 84 pendingLineSegments.remove(ls); 85 if (end) 86 t.add(ls); 87 else 88 t.addStart(ls); 89 } 90 /** 91 * Delete the pending line segment without moving it anywhere. 92 */ 93 public void destroyPendingLineSegment(LineSegment ls) { 94 pendingLineSegments.remove(ls); 95 ls.destroy(); 96 } 97 /** 98 * Return an read-only iterator over all pending line segments. 99 */ 100 public Collection<LineSegment> pendingLineSegments() { 101 return Collections.unmodifiableCollection(pendingLineSegments); 102 } 43 public Collection<Track> tracks = new LinkedList<Track>(); 103 44 104 45 /** … … 170 111 public void clearSelection() { 171 112 clearSelection(nodes); 113 clearSelection(lineSegments); 172 114 clearSelection(tracks); 173 for (Track t : tracks)174 clearSelection(t.segments());175 115 } 176 116 … … 182 122 public Collection<OsmPrimitive> getSelected() { 183 123 Collection<OsmPrimitive> sel = getSelected(nodes); 184 sel.addAll(getSelected( pendingLineSegments));124 sel.addAll(getSelected(lineSegments)); 185 125 sel.addAll(getSelected(tracks)); 186 for (Track t : tracks)187 sel.addAll(getSelected(t.segments()));188 126 return sel; 189 127 } … … 193 131 * The objects imported are not cloned, so from now on, these data belong 194 132 * to both datasets. So use mergeFrom only if you are about to abandon the 195 * other dataset or this dataset. 196 * 133 * other dataset. 134 * 135 * Elements are tried to merged. 136 * Nodes are merged first, if their lat/lon are equal. 137 * Line segments are merged, if they have the same nodes. 138 * Tracks are merged, if they consist of the same line segments. 139 * 140 * TODO Additional to that, every two objects with the same id are merged. 141 * 197 142 * @param ds The DataSet to merge into this one. 198 * @param mergeEqualNodes If <code>true</code>, nodes with the same lat/lon 199 * are merged together. 200 */ 201 public void mergeFrom(DataSet ds, boolean mergeEqualNodes) { 202 System.out.println(nodes.size()+" "+pendingLineSegments.size()+" "+tracks.size()); 203 if (mergeEqualNodes) { 204 Map<Node, Node> mergeMap = new HashMap<Node, Node>(); 205 Set<Node> nodesToAdd = new HashSet<Node>(); 206 for (Node n : nodes) { 207 for (Iterator<Node> it = ds.nodes.iterator(); it.hasNext();) { 208 Node dsn = it.next(); 209 if (n.coor.equalsLatLon(dsn.coor)) { 210 mergeMap.put(dsn, n); 211 n.mergeFrom(dsn); 212 it.remove(); 213 } else { 214 nodesToAdd.add(dsn); 215 } 143 */ 144 public void mergeFrom(DataSet ds) { 145 // merge nodes 146 147 Map<Node, Node> nodeMap = new HashMap<Node, Node>(); 148 149 // find mergable 150 for (Node otherNode : ds.nodes) 151 for (Node myNode : nodes) 152 if (otherNode.coor.equalsLatLon(myNode.coor)) 153 nodeMap.put(otherNode, myNode); 154 // add 155 for (Node n : ds.nodes) 156 if (!nodeMap.containsKey(n)) 157 nodes.add(n); 158 // reassign 159 for (LineSegment ls : ds.lineSegments) { 160 Node n = nodeMap.get(ls.start); 161 if (n != null) 162 ls.start = n; 163 n = nodeMap.get(ls.end); 164 if (n != null) 165 ls.end = n; 166 } 167 168 169 // merge line segments 170 171 Map<LineSegment, LineSegment> lsMap = new HashMap<LineSegment, LineSegment>(); 172 // find mergable 173 for (LineSegment otherLS : ds.lineSegments) 174 for (LineSegment myLS : lineSegments) 175 if (otherLS.start == myLS.start && otherLS.end == myLS.end) 176 lsMap.put(otherLS, myLS); 177 // add ls 178 for (LineSegment ls : ds.lineSegments) 179 if (!lsMap.containsKey(ls)) 180 lineSegments.add(ls); 181 // reassign 182 for (Track t : ds.tracks) { 183 for (int i = 0; i < t.segments.size(); ++i) { 184 LineSegment newLS = lsMap.get(t.segments.get(i)); 185 if (newLS != null) 186 t.segments.set(i, newLS); 187 } 188 } 189 190 191 // merge tracks 192 193 LinkedList<Track> trackToAdd = new LinkedList<Track>(); 194 for (Track otherTrack : ds.tracks) { 195 boolean found = false; 196 for (Track myTrack : tracks) { 197 if (myTrack.segments.equals(otherTrack.segments)) { 198 found = true; 199 break; 216 200 } 217 201 } 218 nodes.addAll(nodesToAdd); 219 for (Track t : ds.tracks) { 220 for (LineSegment ls : t.segments()) { 221 Node n = mergeMap.get(ls.getStart()); 222 if (n != null) 223 ls.start = n; 224 n = mergeMap.get(ls.getEnd()); 225 if (n != null) 226 ls.end = n; 227 } 228 } 229 tracks.addAll(ds.tracks); 230 for (LineSegment ls : ds.pendingLineSegments) { 231 Node n = mergeMap.get(ls.getStart()); 232 if (n != null) 233 ls.start = n; 234 n = mergeMap.get(ls.getEnd()); 235 if (n != null) 236 ls.end = n; 237 } 238 pendingLineSegments.addAll(ds.pendingLineSegments); 239 } else { 240 nodes.addAll(ds.nodes); 241 tracks.addAll(ds.tracks); 242 pendingLineSegments.addAll(ds.pendingLineSegments); 243 } 244 System.out.println(nodes.size()+" "+pendingLineSegments.size()+" "+tracks.size()); 202 if (!found) 203 trackToAdd.add(otherTrack); 204 } 205 tracks.addAll(trackToAdd); 245 206 } 246 207 … … 253 214 return; 254 215 for (OsmPrimitive osm : list) { 255 osm.setSelected(false , this);216 osm.setSelected(false); 256 217 if (osm.keys != null) 257 218 clearSelection(osm.keys.keySet()); … … 275 236 return sel; 276 237 } 277 278 279 @Override280 public DataSet clone() {281 try {return (DataSet)super.clone();} catch (CloneNotSupportedException e) {}282 return null;283 }284 238 } -
/src/org/openstreetmap/josm/data/osm/Key.java
r20 r30 1 1 package org.openstreetmap.josm.data.osm; 2 2 3 import java.util.Collection;4 3 import java.util.HashMap; 5 import java.util.LinkedList;6 4 import java.util.Map; 7 5 … … 24 22 * All keys are stored here. 25 23 */ 26 p rivate staticMap<String, Key> allKeys = new HashMap<String, Key>();24 public static final Map<String, Key> allKeys = new HashMap<String, Key>(); 27 25 28 26 /** … … 49 47 } 50 48 51 /**52 * Return an empty list, since keys cannot have nodes.53 */54 @Override55 public Collection<Node> getAllNodes() {56 return new LinkedList<Node>();57 }58 59 49 @Override 60 50 public void visit(Visitor visitor) { 61 51 visitor.visit(this); 62 52 } 53 54 @Override 55 public String toString() { 56 return name; 57 } 63 58 } -
/src/org/openstreetmap/josm/data/osm/LineSegment.java
r20 r30 1 1 package org.openstreetmap.josm.data.osm; 2 3 import java.util.Collection;4 import java.util.Collections;5 import java.util.LinkedList;6 2 7 3 import org.openstreetmap.josm.data.osm.visitor.Visitor; … … 18 14 * The starting node of the line segment 19 15 */ 20 Node start;16 public Node start; 21 17 22 18 /** 23 19 * The ending node of the line segment 24 20 */ 25 Node end; 26 27 /** 28 * The tracks, this line segment is part of. 29 */ 30 transient Collection<Track> parent = new LinkedList<Track>(); 21 public Node end; 31 22 32 23 /** … … 38 29 this.start = start; 39 30 this.end = end; 40 start.parentSegment.add(this);41 end.parentSegment.add(this);42 }43 44 /**45 * Return all parent tracks this line segment is part of. The list is readonly.46 */47 public Collection<Track> getParents() {48 return Collections.unmodifiableCollection(parent);49 }50 51 public void setStart(Node start) {52 this.start.parentSegment.remove(this);53 this.start = start;54 start.parentSegment.add(this);55 }56 public Node getStart() {57 return start;58 }59 public void setEnd(Node end) {60 this.end.parentSegment.remove(this);61 this.end = end;62 end.parentSegment.add(this);63 }64 public Node getEnd() {65 return end;66 }67 68 /**69 * The LineSegment is going to be destroyed. Unlink all back references.70 */71 void destroy() {72 start.parentSegment.remove(this);73 end.parentSegment.remove(this);74 }75 76 /**77 * Return start and end in a list.78 */79 @Override80 public Collection<Node> getAllNodes() {81 LinkedList<Node> nodes = new LinkedList<Node>();82 nodes.add(getStart());83 nodes.add(getEnd());84 return nodes;85 31 } 86 32 -
/src/org/openstreetmap/josm/data/osm/Node.java
r20 r30 1 1 package org.openstreetmap.josm.data.osm; 2 3 import java.util.Collection;4 import java.util.Collections;5 import java.util.LinkedList;6 2 7 3 import org.openstreetmap.josm.data.GeoPoint; … … 21 17 public GeoPoint coor; 22 18 23 /**24 * The list of line segments, this node is part of.25 */26 transient Collection<LineSegment> parentSegment = new LinkedList<LineSegment>();27 28 /**29 * Returns a read-only list of all segments this node is in.30 * @return A list of all segments. Readonly.31 */32 public Collection<LineSegment> getParentSegments() {33 return Collections.unmodifiableCollection(parentSegment);34 }35 36 /**37 * Merge the node given at parameter with this node.38 * All parents of the parameter-node become parents of this node.39 *40 * The argument node is not changed.41 *42 * @param node Merge the node to this.43 */44 public void mergeFrom(Node node) {45 parentSegment.addAll(node.parentSegment);46 if (keys == null)47 keys = node.keys;48 else if (node.keys != null)49 keys.putAll(node.keys);50 }51 52 /**53 * Return a list only this added.54 */55 @Override56 public Collection<Node> getAllNodes() {57 LinkedList<Node> nodes = new LinkedList<Node>();58 nodes.add(this);59 return nodes;60 }61 62 19 @Override 63 20 public void visit(Visitor visitor) { -
/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
r20 r30 1 1 package org.openstreetmap.josm.data.osm; 2 2 3 import java.util.Collection;4 3 import java.util.Map; 5 4 5 import org.openstreetmap.josm.Main; 6 6 import org.openstreetmap.josm.data.osm.visitor.Visitor; 7 7 … … 19 19 */ 20 20 public Map<Key, String> keys; 21 21 22 22 /** 23 * If set to true, this object has been modified in the current session. 23 * Unique identifier in OSM. This is used to reidentify objects in the server. 24 * An id of 0 means an unknown id. The object has not been uploaded yet to 25 * know what id it will get. 24 26 */ 25 transient public boolean modified = false;26 27 public long id = 0; 28 27 29 /** 28 30 * If set to true, this object is currently selected. 29 31 */ 30 32 transient private boolean selected = false; 31 32 /**33 * Return a list of all nodes, this osmPrimitive consists of. Does return34 * an empty list, if it is an primitive that cannot have nodes (e.g. Key)35 * TODO replace with visitor36 */37 abstract public Collection<Node> getAllNodes();38 33 39 34 /** … … 71 66 * changed later, if the value actualy changed. 72 67 * @param selected Whether the primitive should be selected or not. 73 * @param ds The dataSet, this primitive is in.74 68 */ 75 public void setSelected(boolean selected , DataSet ds) {69 public void setSelected(boolean selected) { 76 70 if (selected != this.selected) 77 ds.fireSelectionChanged();71 Main.main.ds.fireSelectionChanged(); 78 72 this.selected = selected; 79 73 } … … 85 79 return selected; 86 80 } 81 82 83 /** 84 * Equal, if the id is equal. If both ids are 0, use the super classes equal 85 * instead. 86 */ 87 @Override 88 public boolean equals(Object obj) { 89 if (!(obj instanceof OsmPrimitive)) 90 return false; 91 OsmPrimitive osm = (OsmPrimitive)obj; 92 if (id == 0 && osm.id == 0) 93 return super.equals(obj); 94 return id == osm.id; 95 } 96 97 /** 98 * Return the id as hashcode or supers hashcode if 0. 99 */ 100 @Override 101 public int hashCode() { 102 return id == 0 ? super.hashCode() : (int)id; 103 } 87 104 } -
/src/org/openstreetmap/josm/data/osm/Track.java
r20 r30 2 2 3 3 import java.util.ArrayList; 4 import java.util.Collection;5 import java.util.Collections;6 4 import java.util.List; 7 5 … … 18 16 * All track segments in this track 19 17 */ 20 p rivatefinal List<LineSegment> segments = new ArrayList<LineSegment>();18 public final List<LineSegment> segments = new ArrayList<LineSegment>(); 21 19 22 20 … … 26 24 public void add(LineSegment ls) { 27 25 segments.add(ls); 28 ls.parent.add(this);29 }30 31 /**32 * Add the line segment at first position to the track. First position means,33 * the line segment's start becomes the starting node.34 * @param ls The line segment to add at starting position.35 * @see #getStartingNode()36 */37 public void addStart(LineSegment ls) {38 segments.add(ls);39 ls.parent.add(this);40 }41 42 /**43 * Add all LineSegment's to the list of segments.44 * @param lineSegments The line segments to add.45 */46 public void addAll(Collection<? extends LineSegment> lineSegments) {47 segments.addAll(lineSegments);48 for (LineSegment ls : lineSegments)49 ls.parent.add(this);50 }51 52 /**53 * Remove the line segment from the track.54 */55 public void remove(LineSegment ls) {56 if (segments.remove(ls))57 if (!ls.parent.remove(this))58 throw new IllegalStateException("Parent violation detected.");59 }60 61 /**62 * Return an read-only collection. Do not alter the object returned.63 * @return The read-only Collection of all segments.64 */65 public Collection<LineSegment> segments() {66 return Collections.unmodifiableCollection(segments);67 }68 69 /**70 * Return a merge of getAllNodes - calls to the line segments.71 */72 @Override73 public Collection<Node> getAllNodes() {74 ArrayList<Node> nodes = new ArrayList<Node>();75 for (LineSegment ls : segments)76 nodes.addAll(ls.getAllNodes());77 return nodes;78 }79 /**80 * The track is going to be destroyed. Unlink all back references.81 */82 void destroy() {83 for (LineSegment ls : segments) {84 ls.parent.remove(this);85 if (ls.parent.isEmpty())86 ls.destroy();87 }88 segments.clear();89 26 } 90 27 … … 101 38 if (segments.isEmpty()) 102 39 return null; 103 return segments.get(segments.size()-1). getEnd();40 return segments.get(segments.size()-1).end; 104 41 } 105 42 … … 126 63 if (segments.isEmpty()) 127 64 return null; 128 return segments.get(0). getStart();65 return segments.get(0).start; 129 66 } 130 67 -
/src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java
r20 r30 19 19 * @author imi 20 20 */ 21 public class SelectionComponentVisitor extends Visitor {21 public class SelectionComponentVisitor implements Visitor { 22 22 23 23 /** … … 34 34 * A key icon and the name of the key. 35 35 */ 36 @Override37 36 public void visit(Key k) { 38 37 name = k.name; … … 45 44 * "(x1,y1) -> (x2,y2)" is displayed with the nodes coordinates. 46 45 */ 47 @Override48 46 public void visit(LineSegment ls) { 49 47 String name = getName(ls.keys); 50 48 if (name == null) 51 name = "("+ls. getStart().coor.lat+","+ls.getStart().coor.lon+") -> ("+ls.getEnd().coor.lat+","+ls.getEnd().coor.lon+")";49 name = "("+ls.start.coor.lat+","+ls.start.coor.lon+") -> ("+ls.end.coor.lat+","+ls.end.coor.lon+")"; 52 50 53 51 this.name = name; … … 59 57 * is displayed. 60 58 */ 61 @Override62 59 public void visit(Node n) { 63 60 String name = getName(n.keys); … … 73 70 * is displayed with x beeing the number of nodes in the track. 74 71 */ 75 @Override76 72 public void visit(Track t) { 77 73 String name = getName(t.keys); 78 74 if (name == null) { 79 75 Set<Node> nodes = new HashSet<Node>(); 80 for (LineSegment ls : t.segments ()) {81 nodes.add(ls. getStart());82 nodes.add(ls. getEnd());76 for (LineSegment ls : t.segments) { 77 nodes.add(ls.start); 78 nodes.add(ls.end); 83 79 } 84 80 name = "("+nodes.size()+" nodes)"; -
/src/org/openstreetmap/josm/data/osm/visitor/Visitor.java
r20 r30 12 12 * @author imi 13 13 */ 14 abstract public classVisitor {15 public void visit(Node n) {}16 public void visit(LineSegment ls) {}17 public void visit(Track t) {}18 public void visit(Key k) {}14 public interface Visitor { 15 void visit(Node n); 16 void visit(LineSegment ls); 17 void visit(Track t); 18 void visit(Key k); 19 19 } -
/src/org/openstreetmap/josm/data/projection/Projection.java
r20 r30 8 8 import javax.swing.event.ChangeListener; 9 9 10 import org.openstreetmap.josm.data.Bounds; 10 11 import org.openstreetmap.josm.data.GeoPoint; 11 import org.openstreetmap.josm.data.osm.DataSet;12 12 13 13 /** … … 71 71 72 72 /** 73 * Initialize itself with the given dataSet.73 * Initialize itself with the given bounding rectangle (regarding lat/lon). 74 74 * 75 75 * This function should initialize own parameters needed to do the … … 81 81 * This implementation does nothing. It is provided only for subclasses 82 82 * to initialize their data members. 83 *84 * @param dataSet85 * The dataset, which will be displayed on screen. Later, all86 * projections should be relative to the given dataset. Any87 * reverse projections (xy2latlon) can be assumed to be in near88 * distance to nodes of this dataset (that means, it is ok, if89 * there is a conversion error, if the requested x/y to xy2latlon90 * is far away from any coordinate in the dataset)91 83 */ 92 public void init( DataSet dataSet) {}84 public void init(Bounds b) {} 93 85 94 86 /** -
/src/org/openstreetmap/josm/data/projection/UTM.java
r20 r30 15 15 import javax.swing.SpinnerNumberModel; 16 16 17 import org.openstreetmap.josm.Main; 17 18 import org.openstreetmap.josm.data.Bounds; 18 19 import org.openstreetmap.josm.data.GeoPoint; 19 import org.openstreetmap.josm.data.osm.DataSet;20 20 import org.openstreetmap.josm.gui.GBC; 21 import org.openstreetmap.josm.gui.Main;22 21 23 22 /** … … 80 79 }; 81 80 82 private enum Hemisphere {north, south} ;81 private enum Hemisphere {north, south} 83 82 84 83 /** … … 102 101 * Spinner with all possible zones for the configuration panel 103 102 */ 104 privateJSpinner zoneSpinner;103 JSpinner zoneSpinner; 105 104 /** 106 105 * Hemisphere combo for the configuration panel 107 106 */ 108 privateJComboBox hemisphereCombo;107 JComboBox hemisphereCombo; 109 108 110 109 … … 187 186 * @author imi 188 187 */ 189 private class ZoneData {188 private static class ZoneData { 190 189 int zone = 0; 191 190 Hemisphere hemisphere = Hemisphere.north; … … 193 192 /** 194 193 * Try to autodetect the zone and hemisphere from the dataset. 195 * @param dataSet The dataset to extrakt zone information from.196 194 * @return The zone data extrakted from the dataset. 197 195 */ 198 private ZoneData autoDetect(DataSet dataSet) {196 ZoneData autoDetect(Bounds b) { 199 197 ZoneData zd = new ZoneData(); 200 201 Bounds b = dataSet.getBoundsLatLon();202 198 if (b == null) 203 199 return zd; … … 234 230 */ 235 231 @Override 236 public void init( DataSet dataSet) {232 public void init(Bounds b) { 237 233 if (zone == 0) { 238 ZoneData zd = autoDetect( dataSet);234 ZoneData zd = autoDetect(b); 239 235 zone = zd.zone; 240 236 hemisphere = zd.hemisphere; … … 274 270 public void actionPerformed(ActionEvent e) { 275 271 if (Main.main.getMapFrame() != null) { 276 DataSet ds = Main.main.getMapFrame().mapView.getActiveDataSet(); 277 ZoneData zd = autoDetect(ds); 272 ZoneData zd = autoDetect(Main.main.ds.getBoundsLatLon()); 278 273 if (zd.zone == 0) 279 274 JOptionPane.showMessageDialog(Main.main, "Autodetection failed. Maybe the data set contain too few information."); -
/src/org/openstreetmap/josm/gui/BookmarkList.java
r20 r30 16 16 import javax.swing.JOptionPane; 17 17 18 import org.openstreetmap.josm.Main; 18 19 import org.openstreetmap.josm.data.Preferences; 19 20 -
/src/org/openstreetmap/josm/gui/IconToggleButton.java
r20 r30 25 25 // Tooltip 26 26 String toolTipText = ""; 27 Object o = action.getValue(Action. LONG_DESCRIPTION);27 Object o = action.getValue(Action.SHORT_DESCRIPTION); 28 28 if (o != null) 29 toolTipText += o.toString(); 30 o = action.getValue(Action.ACCELERATOR_KEY); 31 if (o != null) { 32 String ksName = o.toString(); 33 if (ksName.startsWith("pressed ")) 34 ksName = ksName.substring("pressed ".length()); 35 else if (ksName.startsWith("released ")) 36 ksName = ksName.substring("released ".length()); 37 toolTipText += " Shortcut: "+ksName; 38 } 29 toolTipText = o.toString(); 39 30 setToolTipText(toolTipText); 40 31 -
/src/org/openstreetmap/josm/gui/ImageProvider.java
r20 r30 13 13 import javax.swing.ImageIcon; 14 14 15 import org.openstreetmap.josm.Main; 16 15 17 /** 16 18 * Helperclass to support the application with images. … … 23 25 * @author imi 24 26 */ 25 public enum OverlayPosition {NORTHWEST, NORTHEAST, SOUTHWEST, SOUTHEAST} ;27 public enum OverlayPosition {NORTHWEST, NORTHEAST, SOUTHWEST, SOUTHEAST} 26 28 27 29 /** -
/src/org/openstreetmap/josm/gui/MapFrame.java
r20 r30 4 4 import java.awt.Component; 5 5 import java.awt.Container; 6 import java.awt.event.WindowAdapter;7 import java.awt.event.WindowEvent;8 6 import java.beans.PropertyChangeEvent; 9 7 import java.beans.PropertyChangeListener; 10 8 11 9 import javax.swing.AbstractButton; 10 import javax.swing.BoxLayout; 12 11 import javax.swing.ButtonGroup; 13 12 import javax.swing.JPanel; … … 19 18 import org.openstreetmap.josm.actions.mapmode.AddNodeAction; 20 19 import org.openstreetmap.josm.actions.mapmode.AddTrackAction; 21 import org.openstreetmap.josm.actions.mapmode.CombineAction;22 20 import org.openstreetmap.josm.actions.mapmode.DeleteAction; 23 21 import org.openstreetmap.josm.actions.mapmode.MapMode; … … 54 52 */ 55 53 public MapStatus statusLine; 54 /** 55 * The action to open the layer list 56 */ 57 private LayerList layerList; 58 /** 59 * Action to open the properties panel for the selected objects 60 */ 61 private PropertiesDialog propertiesDialog; 62 /** 63 * Action to open a list of all selected objects 64 */ 65 private SelectionListDialog selectionListDialog; 56 66 57 67 /** … … 76 86 toolBarActions.add(new IconToggleButton(this, new AddLineSegmentAction(this))); 77 87 toolBarActions.add(new IconToggleButton(this, new AddTrackAction(this))); 78 toolBarActions.add(new IconToggleButton(this, new CombineAction(this)));79 88 toolBarActions.add(new IconToggleButton(this, new DeleteAction(this))); 80 89 … … 99 108 }); 100 109 101 // layer list 102 toolBarActions.add(new IconToggleButton(this, new LayerList(this))); 110 JPanel toggleDialogs = new JPanel(); 111 add(toggleDialogs, BorderLayout.EAST); 112 113 toggleDialogs.setLayout(new BoxLayout(toggleDialogs, BoxLayout.Y_AXIS)); 114 toolBarActions.add(new IconToggleButton(this, layerList = new LayerList(this))); 115 toggleDialogs.add(layerList); 116 toolBarActions.add(new IconToggleButton(this, propertiesDialog = new PropertiesDialog(this))); 117 toggleDialogs.add(propertiesDialog); 118 toolBarActions.add(new IconToggleButton(this, selectionListDialog = new SelectionListDialog(this))); 119 toggleDialogs.add(selectionListDialog); 103 120 104 // properties105 toolBarActions.add(new IconToggleButton(this, new PropertiesDialog(this)));106 107 // selection dialog108 SelectionListDialog selectionList = new SelectionListDialog(this);109 final IconToggleButton buttonSelection = new IconToggleButton(this, selectionList);110 selectionList.addWindowListener(new WindowAdapter(){111 @Override112 public void windowClosing(WindowEvent e) {113 buttonSelection.setSelected(false);114 }115 });116 toolBarActions.add(buttonSelection);117 121 118 122 // status line below the map -
/src/org/openstreetmap/josm/gui/MapStatus.java
r20 r30 47 47 * The position of the mouse cursor. 48 48 */ 49 privateJTextField positionText = new JTextField("-000.00000000000000 -000.00000000000000".length());49 JTextField positionText = new JTextField("-000.00000000000000 -000.00000000000000".length()); 50 50 /** 51 51 * The field holding the name of the object under the mouse. 52 52 */ 53 privateJTextField nameText = new JTextField(30);53 JTextField nameText = new JTextField(30); 54 54 55 55 /** … … 147 147 * The last sent mouse movement event. 148 148 */ 149 privateMouseState mouseState = new MouseState();149 MouseState mouseState = new MouseState(); 150 150 151 151 /** -
/src/org/openstreetmap/josm/gui/MapView.java
r20 r30 17 17 import javax.swing.event.ChangeListener; 18 18 19 import org.openstreetmap.josm.Main; 19 20 import org.openstreetmap.josm.data.Bounds; 20 21 import org.openstreetmap.josm.data.GeoPoint; … … 26 27 import org.openstreetmap.josm.data.projection.Projection; 27 28 import org.openstreetmap.josm.gui.layer.Layer; 29 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 28 30 29 31 /** 30 32 * This is a component used in the MapFrame for browsing the map. It use is to 31 33 * provide the MapMode's enough capabilities to operate. 32 *33 * MapView holds the map data, organize it, convert it, provide access to it.34 34 * 35 35 * MapView hold meta-data about the data set currently displayed, as scale level, … … 73 73 private ArrayList<Layer> layers = new ArrayList<Layer>(); 74 74 /** 75 * Direct link to the edit layer (if any) in the layers list. 76 */ 77 private OsmDataLayer editLayer; 78 /** 75 79 * The layer from the layers list that is currently active. 76 80 */ … … 86 90 */ 87 91 public MapView(Layer layer) { 88 if (layer.getDataSet() == null)89 throw new IllegalArgumentException("Initial layer must have a dataset.");90 91 92 addComponentListener(new ComponentAdapter(){ 92 93 @Override … … 102 103 addLayer(layer); 103 104 Main.pref.addPropertyChangeListener(this); 104 105 // init screen106 recalculateCenterScale();107 105 } 108 106 … … 112 110 */ 113 111 public void addLayer(Layer layer) { 112 // initialize the projection if it is the first layer 113 if (layers.isEmpty()) 114 Main.pref.getProjection().init(layer.getBoundsLatLon()); 115 116 // reinitialize layer's data 117 layer.init(Main.pref.getProjection()); 118 119 if (layer instanceof OsmDataLayer) { 120 if (editLayer != null) { 121 // merge the layer into the existing one 122 if (!editLayer.isMergable(layer)) 123 throw new IllegalArgumentException("Cannot merge argument"); 124 editLayer.mergeFrom(layer); 125 repaint(); 126 return; 127 } 128 editLayer = (OsmDataLayer)layer; 129 } 130 131 // add as a new layer 114 132 layers.add(0,layer); 115 116 DataSet ds = layer.getDataSet();117 118 if (ds != null) {119 // initialize the projection if it was the first layer120 if (layers.size() == 1)121 Main.pref.getProjection().init(ds);122 123 // initialize the dataset in the new layer124 for (Node n : ds.nodes)125 Main.pref.getProjection().latlon2xy(n.coor);126 }127 133 128 134 for (LayerChangeListener l : listeners) 129 135 l.layerAdded(layer); 130 136 137 // autoselect the new layer 131 138 setActiveLayer(layer); 132 139 } 133 140 134 141 /** 135 142 * Remove the layer from the mapview. If the layer was in the list before, … … 140 147 for (LayerChangeListener l : listeners) 141 148 l.layerRemoved(layer); 149 if (layer == editLayer) 150 editLayer = null; 142 151 } 143 152 … … 232 241 OsmPrimitive minPrimitive = null; 233 242 234 // calculate the object based on the current active dataset.235 DataSet ds = getActiveDataSet();236 237 243 // nodes 238 for (Node n : ds.nodes) {244 for (Node n : Main.main.ds.nodes) { 239 245 Point sp = getScreenPoint(n.coor); 240 246 double dist = p.distanceSq(sp); … … 248 254 249 255 // pending line segments 250 for (LineSegment ls : ds.pendingLineSegments()) {251 Point A = getScreenPoint(ls. getStart().coor);252 Point B = getScreenPoint(ls. getEnd().coor);256 for (LineSegment ls : Main.main.ds.lineSegments) { 257 Point A = getScreenPoint(ls.start.coor); 258 Point B = getScreenPoint(ls.end.coor); 253 259 double c = A.distanceSq(B); 254 260 double a = p.distanceSq(B); … … 263 269 // tracks & line segments 264 270 minDistanceSq = Double.MAX_VALUE; 265 for (Track t : ds.tracks()) {266 for (LineSegment ls : t.segments ()) {267 Point A = getScreenPoint(ls. getStart().coor);268 Point B = getScreenPoint(ls. getEnd().coor);271 for (Track t : Main.main.ds.tracks) { 272 for (LineSegment ls : t.segments) { 273 Point A = getScreenPoint(ls.start.coor); 274 Point B = getScreenPoint(ls.end.coor); 269 275 double c = A.distanceSq(B); 270 276 double a = p.distanceSq(B); … … 320 326 for (int i = layers.size()-1; i >= 0; --i) { 321 327 Layer l = layers.get(i); 322 if (l. isVisible())328 if (l.visible) 323 329 l.paint(g, this); 324 330 } … … 332 338 // reset all datasets. 333 339 Projection p = Main.pref.getProjection(); 334 for (Layer l : layers) { 335 DataSet ds = l.getDataSet(); 336 if (ds != null) 337 for (Node n : ds.nodes) 338 p.latlon2xy(n.coor); 339 } 340 for (Node n : Main.main.ds.nodes) 341 p.latlon2xy(n.coor); 340 342 recalculateCenterScale(); 341 343 } … … 375 377 376 378 377 /**378 * Return the dataSet for the current selected layer. If the active layer379 * does not have a dataset, return the DataSet from the next layer a.s.o.380 *381 * @return The DataSet of the current active layer.382 */383 public DataSet getActiveDataSet() {384 if (activeLayer.getDataSet() != null)385 return activeLayer.getDataSet();386 for (Layer l : layers) {387 DataSet ds = l.getDataSet();388 if (ds != null)389 return ds;390 }391 throw new IllegalStateException("No dataset found.");392 }393 394 379 /** 395 380 * Change to the new projection. Recalculate the dataset and zoom, if autoZoom … … 425 410 h = 20; 426 411 427 Bounds bounds = getActiveDataSet().getBoundsXY(); 428 412 Bounds bounds = null; 413 for (Layer l : layers) { 414 if (bounds == null) 415 bounds = l.getBoundsXY(); 416 else { 417 Bounds lb = l.getBoundsXY(); 418 if (lb != null) 419 bounds = bounds.mergeXY(lb); 420 } 421 } 422 429 423 boolean oldAutoScale = autoScale; 430 424 GeoPoint oldCenter = center; … … 479 473 /** 480 474 * Set the active selection to the given value and raise an layerchange event. 475 * Also, swap the active dataset in Main.main if it is a datalayer. 481 476 */ 482 477 public void setActiveLayer(Layer layer) { … … 485 480 Layer old = activeLayer; 486 481 activeLayer = layer; 482 if (layer instanceof OsmDataLayer) 483 Main.main.ds = ((OsmDataLayer)layer).data; 487 484 if (old != layer) { 488 if (old != null && old.getDataSet() != null)489 old.getDataSet().clearSelection();490 485 for (LayerChangeListener l : listeners) 491 486 l.activeLayerChange(old, layer); … … 500 495 return activeLayer; 501 496 } 497 498 /** 499 * @return The current edit layer. If no edit layer exist, one is created. 500 * So editLayer does never return <code>null</code>. 501 */ 502 public OsmDataLayer editLayer() { 503 if (editLayer == null) 504 addLayer(new OsmDataLayer(new DataSet(), "unnamed")); 505 return editLayer; 506 } 502 507 } -
/src/org/openstreetmap/josm/gui/PreferenceDialog.java
r20 r30 28 28 import javax.swing.UIManager.LookAndFeelInfo; 29 29 30 import org.openstreetmap.josm.Main; 30 31 import org.openstreetmap.josm.data.Preferences; 31 32 import org.openstreetmap.josm.data.Preferences.PreferencesException; … … 90 91 * Indicate, that the application has to be restarted for the settings to take effect. 91 92 */ 92 privateboolean requiresRestart = false;93 boolean requiresRestart = false; 93 94 /** 94 95 * ComboBox with all look and feels. 95 96 */ 96 privateJComboBox lafCombo = new JComboBox(UIManager.getInstalledLookAndFeels());97 JComboBox lafCombo = new JComboBox(UIManager.getInstalledLookAndFeels()); 97 98 /** 98 99 * Combobox with all projections available 99 100 */ 100 privateJComboBox projectionCombo = new JComboBox(Preferences.allProjections.clone());101 JComboBox projectionCombo = new JComboBox(Preferences.allProjections.clone()); 101 102 /** 102 103 * The main tab panel. … … 107 108 * Editfield for the Base url to the REST API from OSM. 108 109 */ 109 privateJTextField osmDataServer = new JTextField(20);110 JTextField osmDataServer = new JTextField(20); 110 111 /** 111 112 * Editfield for the username to the OSM account. 112 113 */ 113 privateJTextField osmDataUsername = new JTextField(20);114 JTextField osmDataUsername = new JTextField(20); 114 115 /** 115 116 * Passwordfield for the userpassword of the REST API. 116 117 */ 117 privateJPasswordField osmDataPassword = new JPasswordField(20);118 JPasswordField osmDataPassword = new JPasswordField(20); 118 119 /** 119 120 * The checkbox stating whether nodes should be merged together. 120 121 */ 121 privateJCheckBox drawRawGpsLines = new JCheckBox("Draw lines between raw gps points.");122 JCheckBox drawRawGpsLines = new JCheckBox("Draw lines between raw gps points."); 122 123 /** 123 124 * The checkbox stating whether raw gps lines should be forced. 124 125 */ 125 privateJCheckBox forceRawGpsLines = new JCheckBox("Force lines if no line segments imported.");126 JCheckBox forceRawGpsLines = new JCheckBox("Force lines if no line segments imported."); 126 127 /** 127 128 * The checkbox stating whether nodes should be merged together. 128 129 */ 129 privateJCheckBox mergeNodes = new JCheckBox("Merge nodes with equal latitude/longitude.");130 JCheckBox mergeNodes = new JCheckBox("Merge nodes with equal latitude/longitude."); 130 131 131 132 /** -
/src/org/openstreetmap/josm/gui/SelectionManager.java
r20 r30 15 15 import java.util.LinkedList; 16 16 17 import org.openstreetmap.josm. data.osm.DataSet;17 import org.openstreetmap.josm.Main; 18 18 import org.openstreetmap.josm.data.osm.LineSegment; 19 19 import org.openstreetmap.josm.data.osm.Node; … … 272 272 } else { 273 273 // nodes 274 DataSet ds = mv.getActiveDataSet(); 275 for (Node n : ds.nodes) { 274 for (Node n : Main.main.ds.nodes) { 276 275 if (r.contains(mv.getScreenPoint(n.coor))) 277 276 selection.add(n); … … 279 278 280 279 // pending line segments 281 for (LineSegment ls : ds.pendingLineSegments())280 for (LineSegment ls : Main.main.ds.lineSegments) 282 281 if (rectangleContainLineSegment(r, alt, ls)) 283 282 selection.add(ls); 284 283 285 284 // tracks 286 for (Track t : ds.tracks()) {287 boolean wholeTrackSelected = !t.segments ().isEmpty();288 for (LineSegment ls : t.segments ())285 for (Track t : Main.main.ds.tracks) { 286 boolean wholeTrackSelected = !t.segments.isEmpty(); 287 for (LineSegment ls : t.segments) 289 288 if (rectangleContainLineSegment(r, alt, ls)) 290 289 selection.add(ls); … … 311 310 private boolean rectangleContainLineSegment(Rectangle r, boolean alt, LineSegment ls) { 312 311 if (alt) { 313 Point p1 = mv.getScreenPoint(ls. getStart().coor);314 Point p2 = mv.getScreenPoint(ls. getEnd().coor);312 Point p1 = mv.getScreenPoint(ls.start.coor); 313 Point p2 = mv.getScreenPoint(ls.end.coor); 315 314 if (r.intersectsLine(p1.x, p1.y, p2.x, p2.y)) 316 315 return true; 317 316 } else { 318 if (r.contains(mv.getScreenPoint(ls. getStart().coor))319 && r.contains(mv.getScreenPoint(ls. getEnd().coor)))317 if (r.contains(mv.getScreenPoint(ls.start.coor)) 318 && r.contains(mv.getScreenPoint(ls.end.coor))) 320 319 return true; 321 320 } -
/src/org/openstreetmap/josm/gui/dialogs/LayerList.java
r20 r30 23 23 import javax.swing.event.ListSelectionListener; 24 24 25 import org.openstreetmap.josm.Main; 25 26 import org.openstreetmap.josm.data.osm.DataSet; 26 27 import org.openstreetmap.josm.gui.ImageProvider; 27 import org.openstreetmap.josm.gui.Main;28 28 import org.openstreetmap.josm.gui.MapFrame; 29 29 import org.openstreetmap.josm.gui.MapView; … … 42 42 * The data model for the list component. 43 43 */ 44 privateDefaultListModel model = new DefaultListModel();44 DefaultListModel model = new DefaultListModel(); 45 45 /** 46 46 * The list component holding all layers. 47 47 */ 48 privateJList layers = new JList(model);48 JList layers = new JList(model); 49 49 /** 50 50 * The invisible icon blended over invisible layers. 51 51 */ 52 privatestatic final Icon invisible = ImageProvider.get("layer", "invisible");52 static final Icon invisible = ImageProvider.get("layer", "invisible"); 53 53 54 54 /** … … 69 69 */ 70 70 private JButton deleteButton = new JButton(ImageProvider.get("dialogs", "delete")); 71 71 72 72 /** 73 73 * Create an layerlist and attach it to the given mapView. 74 74 */ 75 75 public LayerList(MapFrame mapFrame) { 76 super(mapFrame, "Layers", "List of all layers", "layerlist", KeyEvent.VK_L, "Open a list of all loaded layers."); 77 setSize(250,256); 78 setMinimumSize(new Dimension(70,70)); 76 super("Layers", "List of all layers", "layerlist", KeyEvent.VK_L, "Open a list of all loaded layers."); 77 setPreferredSize(new Dimension(320,100)); 79 78 add(new JScrollPane(layers), BorderLayout.CENTER); 80 79 layers.setBackground(UIManager.getColor("Button.background")); … … 84 83 Layer layer = (Layer)value; 85 84 JLabel label = (JLabel)super.getListCellRendererComponent(list, 86 layer. getName(), index, isSelected, cellHasFocus);85 layer.name, index, isSelected, cellHasFocus); 87 86 Icon icon = layer.getIcon(); 88 if (!layer. isVisible())87 if (!layer.visible) 89 88 icon = ImageProvider.overlay(icon, invisible, ImageProvider.OverlayPosition.SOUTHEAST); 90 89 label.setIcon(icon); 91 92 DataSet ds = layer.getDataSet(); 93 if (ds != null) { 94 label.setToolTipText(ds.nodes.size()+" nodes, "+ 95 ds.tracks().size()+" tracks"); 96 } 90 label.setToolTipText(layer.getToolTipText()); 97 91 return label; 98 92 } … … 100 94 101 95 final MapView mapView = mapFrame.mapView; 102 96 103 97 Collection<Layer> data = mapView.getAllLayers(); 104 98 for (Layer l : data) … … 115 109 }); 116 110 mapView.addLayerChangeListener(this); 117 111 118 112 // Buttons 119 113 JPanel buttonPanel = new JPanel(new GridLayout(1, 5)); … … 148 142 public void actionPerformed(ActionEvent e) { 149 143 Layer l = (Layer)layers.getSelectedValue(); 150 l. setVisible(!l.isVisible());144 l.visible = !l.visible; 151 145 mapView.repaint(); 152 146 layers.repaint(); … … 160 154 if (model.size() == 1) { 161 155 Main.main.setMapFrame(null, null); 156 Main.main.ds = new DataSet(); 162 157 } else { 163 158 int sel = layers.getSelectedIndex(); … … 173 168 mergeButton.setToolTipText("Merge the selected layer into the layer directly below."); 174 169 mergeButton.addActionListener(new ActionListener(){ 175 public void actionPerformed(ActionEvent e) { 176 Layer lFrom = (Layer)layers.getSelectedValue(); 177 DataSet dsFrom = lFrom.getDataSet(); 178 Layer lTo = (Layer)model.get(layers.getSelectedIndex()+1); 179 DataSet dsTo = lTo.getDataSet(); 180 dsTo.mergeFrom(dsFrom, Main.pref.mergeNodes); 181 layers.setSelectedValue(lTo, true); 182 mapView.removeLayer(lFrom); 183 } 184 }); 170 public void actionPerformed(ActionEvent e) { 171 Layer lFrom = (Layer)layers.getSelectedValue(); 172 Layer lTo = (Layer)model.get(layers.getSelectedIndex()+1); 173 lTo.mergeFrom(lFrom); 174 layers.setSelectedValue(lTo, true); 175 mapView.removeLayer(lFrom); 176 } 177 }); 185 178 buttonPanel.add(mergeButton); 186 179 … … 193 186 * Updates the state of the Buttons. 194 187 */ 195 privatevoid updateButtonEnabled() {188 void updateButtonEnabled() { 196 189 int sel = layers.getSelectedIndex(); 197 190 Layer l = (Layer)layers.getSelectedValue(); 198 191 boolean enable = model.getSize() > 1; 199 192 enable = enable && sel < model.getSize()-1; 200 enable = enable && l.getDataSet() != null; 201 enable = enable && ((Layer)model.get(sel+1)).getDataSet() != null; 202 enable = enable && l.isEditable() == ((Layer)model.get(sel+1)).isEditable(); 193 enable = enable && l.isMergable((Layer)model.get(sel+1)); 203 194 mergeButton.setEnabled(enable); 204 195 upButton.setEnabled(sel > 0); -
/src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java
r20 r30 1 1 package org.openstreetmap.josm.gui.dialogs; 2 2 3 import java.awt.BorderLayout; 4 import java.awt.Component; 5 import java.awt.Dimension; 6 import java.awt.Font; 7 import java.awt.GridLayout; 8 import java.awt.event.ActionEvent; 9 import java.awt.event.ActionListener; 3 10 import java.awt.event.KeyEvent; 4 5 import javax.swing.BorderFactory; 6 import javax.swing.Box; 11 import java.awt.event.MouseAdapter; 12 import java.awt.event.MouseEvent; 13 import java.awt.event.WindowEvent; 14 import java.awt.event.WindowFocusListener; 15 import java.util.Collection; 16 import java.util.HashMap; 17 import java.util.Iterator; 18 import java.util.TreeMap; 19 import java.util.TreeSet; 20 import java.util.Vector; 21 import java.util.Map.Entry; 22 23 import javax.swing.JButton; 24 import javax.swing.JComboBox; 25 import javax.swing.JDialog; 7 26 import javax.swing.JLabel; 8 import javax.swing.border.Border; 9 10 import org.openstreetmap.josm.gui.Main; 27 import javax.swing.JOptionPane; 28 import javax.swing.JPanel; 29 import javax.swing.JScrollPane; 30 import javax.swing.JTable; 31 import javax.swing.JTextField; 32 import javax.swing.ListSelectionModel; 33 import javax.swing.table.DefaultTableCellRenderer; 34 import javax.swing.table.DefaultTableModel; 35 36 import org.openstreetmap.josm.Main; 37 import org.openstreetmap.josm.command.ChangeKeyValueCommand; 38 import org.openstreetmap.josm.data.SelectionChangedListener; 39 import org.openstreetmap.josm.data.osm.Key; 40 import org.openstreetmap.josm.data.osm.OsmPrimitive; 41 import org.openstreetmap.josm.gui.ImageProvider; 11 42 import org.openstreetmap.josm.gui.MapFrame; 43 import org.openstreetmap.josm.gui.MapView; 12 44 13 45 /** 14 * Open a Property dialog for the current visible map. When saving to own josm- 15 * data format, the properties are saved along. 46 * This dialog displays the properties of the current selected primitives. 47 * 48 * If no object is selected, the dialog list is empty. 49 * If only one is selected, all properties of this object are selected. 50 * If more than one object are selected, the sum of all properties are displayed. If the 51 * different objects share the same property, the shared value is displayed. If they have 52 * different values, all of them are put in a combo box and the string "<different>" 53 * is displayed in italic. 54 * 55 * Below the list, the user can click on an add, modify and delete property button to 56 * edit the table selection value. 57 * 58 * The command is applied to all selected entries. 16 59 * 17 60 * @author imi 18 61 */ 19 public class PropertiesDialog extends ToggleDialog { 20 62 public class PropertiesDialog extends ToggleDialog implements SelectionChangedListener { 63 64 /** 65 * Watches for double clicks and start editing or new property, depending on the 66 * location, the click was. 67 * @author imi 68 */ 69 public class DblClickWatch extends MouseAdapter { 70 @Override 71 public void mouseClicked(MouseEvent e) { 72 if (e.getClickCount() < 2) 73 return; 74 if (e.getSource() instanceof JScrollPane) 75 add(); 76 else { 77 int row = propertyTable.rowAtPoint(e.getPoint()); 78 edit(row); 79 } 80 } 81 } 82 83 /** 84 * Edit the value in the table row 85 * @param row The row of the table, from which the value is edited. 86 */ 87 void edit(int row) { 88 String key = data.getValueAt(row, 0).toString(); 89 Collection<OsmPrimitive> sel = Main.main.ds.getSelected(); 90 String msg = "<html>This will change "+sel.size()+" object"+(sel.size()==1?"":"s")+".<br><br>"+ 91 "Please select a new value for '"+key+"'.<br>(Empty string deletes the key.)"; 92 final JComboBox combo = (JComboBox)data.getValueAt(row, 1); 93 JPanel p = new JPanel(new BorderLayout()); 94 p.add(new JLabel(msg+"</html>"), BorderLayout.NORTH); 95 p.add(combo, BorderLayout.CENTER); 96 97 final JOptionPane optionPane = new JOptionPane(p, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION); 98 final JDialog dlg = optionPane.createDialog(PropertiesDialog.this, "Change values?"); 99 dlg.addWindowFocusListener(new WindowFocusListener(){ 100 public void windowGainedFocus(WindowEvent e) { 101 combo.requestFocusInWindow(); 102 } 103 public void windowLostFocus(WindowEvent e) { 104 } 105 }); 106 combo.getEditor().addActionListener(new ActionListener(){ 107 public void actionPerformed(ActionEvent e) { 108 optionPane.setValue(JOptionPane.OK_OPTION); 109 dlg.setVisible(false); 110 } 111 }); 112 String oldComboEntry = combo.getEditor().getItem().toString(); 113 dlg.setVisible(true); 114 115 Object answer = optionPane.getValue(); 116 if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE || 117 (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION)) { 118 combo.getEditor().setItem(oldComboEntry); 119 return; 120 } 121 122 String value = combo.getEditor().getItem().toString(); 123 if (value.equals("<different>")) 124 return; 125 if (value.equals("")) 126 value = null; // delete the key 127 mv.editLayer().add(new ChangeKeyValueCommand(sel, Key.get(key), value)); 128 129 if (value == null) 130 selectionChanged(sel); // update whole table 131 else 132 PropertiesDialog.this.repaint(); // repaint is enough 133 } 134 135 /** 136 * Open the add selection dialog and add a new key/value to the table (and to the 137 * dataset, of course). 138 */ 139 void add() { 140 Collection<OsmPrimitive> sel = Main.main.ds.getSelected(); 141 142 JPanel p = new JPanel(new BorderLayout()); 143 p.add(new JLabel("<html>This will change "+sel.size()+" object"+(sel.size()==1?"":"s")+".<br><br>"+ 144 "Please select a key"), BorderLayout.NORTH); 145 Vector<String> allKeys = new Vector<String>(Key.allKeys.keySet()); 146 for (Iterator<String> it = allKeys.iterator(); it.hasNext();) { 147 String s = it.next(); 148 for (int i = 0; i < data.getRowCount(); ++i) { 149 if (s.equals(data.getValueAt(i, 0))) { 150 it.remove(); 151 break; 152 } 153 } 154 } 155 JComboBox keys = new JComboBox(allKeys); 156 keys.setEditable(true); 157 p.add(keys, BorderLayout.CENTER); 158 159 JPanel p2 = new JPanel(new BorderLayout()); 160 p.add(p2, BorderLayout.SOUTH); 161 p2.add(new JLabel("Please select a value"), BorderLayout.NORTH); 162 JTextField values = new JTextField(); 163 p2.add(values, BorderLayout.CENTER); 164 int answer = JOptionPane.showConfirmDialog(PropertiesDialog.this, p, 165 "Change values?", JOptionPane.OK_CANCEL_OPTION); 166 if (answer != JOptionPane.OK_OPTION) 167 return; 168 String key = keys.getEditor().getItem().toString(); 169 String value = values.getText(); 170 if (value.equals("")) 171 return; 172 mv.editLayer().add(new ChangeKeyValueCommand(sel, Key.get(key), value)); 173 selectionChanged(sel); // update table 174 } 175 176 /** 177 * Delete the keys from the given row. 178 * @param row The row, which key gets deleted from the dataset. 179 */ 180 private void delete(int row) { 181 String key = data.getValueAt(row, 0).toString(); 182 Collection<OsmPrimitive> sel = Main.main.ds.getSelected(); 183 mv.editLayer().add(new ChangeKeyValueCommand(sel, Key.get(key), null)); 184 selectionChanged(sel); // update table 185 } 186 187 /** 188 * The property data. 189 */ 190 private final DefaultTableModel data = new DefaultTableModel(){ 191 @Override 192 public boolean isCellEditable(int row, int column) { 193 return false; 194 } 195 @Override 196 public Class<?> getColumnClass(int columnIndex) { 197 return columnIndex == 1 ? JComboBox.class : String.class; 198 } 199 }; 200 /** 201 * The properties list. 202 */ 203 private final JTable propertyTable = new JTable(data); 204 /** 205 * The map view this dialog operates on. 206 */ 207 private final MapView mv; 208 21 209 /** 22 210 * Create a new PropertiesDialog 23 211 */ 24 212 public PropertiesDialog(MapFrame mapFrame) { 25 super(mapFrame, "Properties of "+Main.main.getNameOfLoadedMapFrame(), "Properties Dialog", "properties", KeyEvent.VK_P, "Property page for this map."); 26 putValue(MNEMONIC_KEY, KeyEvent.VK_P); 27 28 final Border panelBorder = BorderFactory.createEmptyBorder(5,0,0,0); 29 Box panel = Box.createVerticalBox(); 213 super("Properties", "Properties Dialog", "properties", KeyEvent.VK_P, "Property for selected objects."); 214 mv = mapFrame.mapView; 215 216 setPreferredSize(new Dimension(320,150)); 30 217 31 JLabel todo = new JLabel("Nothing implemented yet."); 32 todo.setBorder(panelBorder); 33 panel.add(todo); 218 data.setColumnIdentifiers(new String[]{"Key", "Value"}); 219 propertyTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 220 propertyTable.setDefaultRenderer(JComboBox.class, new DefaultTableCellRenderer(){ 221 @Override 222 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 223 Component c = super.getTableCellRendererComponent(table, value, isSelected, false, row, column); 224 if (c instanceof JLabel) { 225 String str = ((JComboBox)value).getEditor().getItem().toString(); 226 ((JLabel)c).setText(str); 227 if (str.equals("<different>")) 228 c.setFont(c.getFont().deriveFont(Font.ITALIC)); 229 } 230 return c; 231 } 232 }); 233 propertyTable.setDefaultRenderer(String.class, new DefaultTableCellRenderer(){ 234 @Override 235 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 236 return super.getTableCellRendererComponent(table, value, isSelected, false, row, column); 237 } 238 }); 239 propertyTable.addMouseListener(new DblClickWatch()); 240 241 JScrollPane scrollPane = new JScrollPane(propertyTable); 242 scrollPane.addMouseListener(new DblClickWatch()); 243 add(scrollPane, BorderLayout.CENTER); 34 244 35 panel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); 36 setContentPane(panel); 37 pack(); 38 setResizable(false); 245 JPanel buttonPanel = new JPanel(new GridLayout(1,3)); 246 ActionListener buttonAction = new ActionListener(){ 247 public void actionPerformed(ActionEvent e) { 248 int sel = propertyTable.getSelectedRow(); 249 if (e.getActionCommand().equals("Add")) 250 add(); 251 else if (e.getActionCommand().equals("Edit")) { 252 if (sel == -1) 253 JOptionPane.showMessageDialog(PropertiesDialog.this, "Please select the row to edit."); 254 else 255 edit(sel); 256 } else if (e.getActionCommand().equals("Delete")) { 257 if (sel == -1) 258 JOptionPane.showMessageDialog(PropertiesDialog.this, "Please select the row to delete."); 259 else 260 delete(sel); 261 } 262 } 263 }; 264 buttonPanel.add(createButton("Add", "Add a new key/value pair to all objects", KeyEvent.VK_A, buttonAction)); 265 buttonPanel.add(createButton("Edit", "Edit the value of the selected key for all objects", KeyEvent.VK_E, buttonAction)); 266 buttonPanel.add(createButton("Delete", "Delete the selected key in all objects", KeyEvent.VK_D, buttonAction)); 267 add(buttonPanel, BorderLayout.SOUTH); 268 } 269 270 private JButton createButton(String name, String tooltip, int mnemonic, ActionListener actionListener) { 271 JButton b = new JButton(name, ImageProvider.get("dialogs", name.toLowerCase())); 272 b.setActionCommand(name); 273 b.addActionListener(actionListener); 274 b.setToolTipText(tooltip); 275 b.setMnemonic(mnemonic); 276 return b; 277 } 278 279 @Override 280 public void setVisible(boolean b) { 281 if (b) { 282 Main.main.ds.addSelectionChangedListener(this); 283 selectionChanged(Main.main.ds.getSelected()); 284 } else { 285 Main.main.ds.removeSelectionChangedListener(this); 286 } 287 super.setVisible(b); 288 } 289 290 public void selectionChanged(Collection<OsmPrimitive> newSelection) { 291 if (propertyTable.getCellEditor() != null) 292 propertyTable.getCellEditor().cancelCellEditing(); 293 data.setRowCount(0); 294 TreeMap<String, Collection<String>> props = new TreeMap<String, Collection<String>>(); 295 HashMap<String, Integer> valueCounts = new HashMap<String, Integer>(); 296 for (OsmPrimitive osm : newSelection) { 297 if (osm.keys != null) { 298 for (Entry<Key, String> e : osm.keys.entrySet()) { 299 Collection<String> value = props.get(e.getKey().name); 300 if (value == null) { 301 value = new TreeSet<String>(); 302 props.put(e.getKey().name, value); 303 } 304 value.add(e.getValue()); 305 306 Integer count = valueCounts.get(e.getValue()); 307 if (count == null) 308 count = 0; 309 valueCounts.put(e.getValue(), count+1); 310 } 311 } 312 } 313 int selCount = newSelection.size(); 314 for (Entry<String, Collection<String>> e : props.entrySet()) { 315 JComboBox value = new JComboBox(e.getValue().toArray()); 316 value.setEditable(true); 317 if (e.getValue().size() > 1 || valueCounts.get(e.getValue().iterator().next()) != selCount) 318 value.getEditor().setItem("<different>"); 319 data.addRow(new Object[]{e.getKey(), value}); 320 } 39 321 } 40 322 } -
/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
r20 r30 3 3 import java.awt.BorderLayout; 4 4 import java.awt.Component; 5 import java.awt.Dimension; 5 6 import java.awt.event.ActionEvent; 6 7 import java.awt.event.ActionListener; … … 16 17 import javax.swing.ListSelectionModel; 17 18 19 import org.openstreetmap.josm.Main; 18 20 import org.openstreetmap.josm.data.SelectionChangedListener; 19 import org.openstreetmap.josm.data.osm.DataSet;20 21 import org.openstreetmap.josm.data.osm.OsmPrimitive; 21 22 import org.openstreetmap.josm.data.osm.visitor.SelectionComponentVisitor; 22 23 import org.openstreetmap.josm.gui.ImageProvider; 23 import org.openstreetmap.josm.gui.Main;24 24 import org.openstreetmap.josm.gui.MapFrame; 25 import org.openstreetmap.josm.gui.MapView;26 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;27 import org.openstreetmap.josm.gui.layer.Layer;28 25 29 26 /** … … 34 31 * @author imi 35 32 */ 36 public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener , LayerChangeListener{33 public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener { 37 34 38 35 /** … … 44 41 */ 45 42 private JList displaylist = new JList(list); 46 /**47 * The dataset, all selections are part of.48 */49 private final MapView mapView;50 43 51 44 /** … … 54 47 */ 55 48 public SelectionListDialog(MapFrame mapFrame) { 56 super(mapFrame, "Current Selection", "Selection List", "selectionlist", KeyEvent.VK_E, "Open a selection list window."); 57 this.mapView = mapFrame.mapView; 58 setLayout(new BorderLayout()); 59 setSize(300,400); 49 super("Current Selection", "Selection List", "selectionlist", KeyEvent.VK_E, "Open a selection list window."); 50 setPreferredSize(new Dimension(320,150)); 60 51 displaylist.setCellRenderer(new DefaultListCellRenderer(){ 61 52 private SelectionComponentVisitor visitor = new SelectionComponentVisitor(); … … 73 64 displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 74 65 75 getContentPane().add(new JScrollPane(displaylist), BorderLayout.CENTER);66 add(new JScrollPane(displaylist), BorderLayout.CENTER); 76 67 77 68 JButton button = new JButton("Select", ImageProvider.get("mapmode", "selection")); … … 82 73 } 83 74 }); 84 getContentPane().add(button, BorderLayout.SOUTH);75 add(button, BorderLayout.SOUTH); 85 76 86 selectionChanged( mapView.getActiveDataSet().getSelected());77 selectionChanged(Main.main.ds.getSelected()); 87 78 } 88 79 … … 90 81 public void setVisible(boolean b) { 91 82 if (b) { 92 mapView.addLayerChangeListener(this); 93 mapView.getActiveDataSet().addSelectionChangedListener(this); 94 selectionChanged(mapView.getActiveDataSet().getSelected()); 83 Main.main.ds.addSelectionChangedListener(this); 84 selectionChanged(Main.main.ds.getSelected()); 95 85 } else { 96 mapView.removeLayerChangeListener(this); 97 mapView.getActiveDataSet().removeSelectionChangedListener(this); 86 Main.main.ds.removeSelectionChangedListener(this); 98 87 } 99 88 super.setVisible(b); … … 118 107 */ 119 108 public void updateMap() { 120 DataSet ds = mapView.getActiveDataSet(); 121 ds.clearSelection(); 109 Main.main.ds.clearSelection(); 122 110 for (int i = 0; i < list.getSize(); ++i) 123 111 if (displaylist.isSelectedIndex(i)) 124 ((OsmPrimitive)list.get(i)).setSelected(true , ds);112 ((OsmPrimitive)list.get(i)).setSelected(true); 125 113 Main.main.getMapFrame().repaint(); 126 114 } 127 128 public void activeLayerChange(Layer oldLayer, Layer newLayer) {129 DataSet ds = oldLayer.getDataSet();130 if (ds != null)131 ds.removeSelectionChangedListener(this);132 ds = newLayer.getDataSet();133 if (ds != null)134 ds.addSelectionChangedListener(this);135 }136 137 /**138 * Does nothing. Only to satisfy LayerChangeListener139 */140 public void layerAdded(Layer newLayer) {}141 /**142 * Does nothing. Only to satisfy LayerChangeListener143 */144 public void layerRemoved(Layer oldLayer) {}145 115 } -
/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
r20 r30 1 1 package org.openstreetmap.josm.gui.dialogs; 2 2 3 import java.awt.BorderLayout; 3 4 import java.awt.event.ActionEvent; 4 import java.beans.PropertyChangeEvent;5 import java.beans.PropertyChangeListener;6 5 import java.util.HashMap; 7 6 import java.util.Map; … … 9 8 import javax.swing.AbstractButton; 10 9 import javax.swing.Action; 11 import javax.swing. JComponent;12 import javax.swing.J Dialog;13 import javax.swing. KeyStroke;10 import javax.swing.BorderFactory; 11 import javax.swing.JLabel; 12 import javax.swing.JPanel; 14 13 15 14 import org.openstreetmap.josm.gui.ImageProvider; 16 import org.openstreetmap.josm.gui.Main;17 import org.openstreetmap.josm.gui.MapFrame;18 15 19 16 /** … … 23 20 * @author imi 24 21 */ 25 public class ToggleDialog extends J Dialogimplements Action {22 public class ToggleDialog extends JPanel implements Action { 26 23 27 24 /** … … 29 26 * @param title The title of the dialog. 30 27 */ 31 public ToggleDialog(MapFrame mapFrame, String title, String name, String iconName, int mnemonic, String tooltip) { 32 super(Main.main, title, false); 28 public ToggleDialog(String title, String name, String iconName, int mnemonic, String tooltip) { 33 29 putValue(SMALL_ICON, ImageProvider.get("dialogs", iconName)); 34 30 putValue(NAME, name); 35 31 putValue(MNEMONIC_KEY, mnemonic); 36 KeyStroke ks = KeyStroke.getKeyStroke(mnemonic,0); 37 putValue(ACCELERATOR_KEY, ks); 38 mapFrame.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, this); 39 mapFrame.getActionMap().put(this, this); 40 putValue(LONG_DESCRIPTION, tooltip); 41 mapFrame.addPropertyChangeListener("visible", new PropertyChangeListener(){ 42 public void propertyChange(PropertyChangeEvent evt) { 43 if (evt.getNewValue() == Boolean.FALSE) 44 setVisible(false); 45 } 46 }); 32 putValue(SHORT_DESCRIPTION, tooltip); 33 34 setLayout(new BorderLayout()); 35 add(new JLabel(title), BorderLayout.NORTH); 36 setVisible(false); 37 setBorder(BorderFactory.createEtchedBorder()); 47 38 } 48 39 -
/src/org/openstreetmap/josm/gui/layer/Layer.java
r20 r30 5 5 import javax.swing.Icon; 6 6 7 import org.openstreetmap.josm.data.osm.DataSet; 7 import org.openstreetmap.josm.data.Bounds; 8 import org.openstreetmap.josm.data.projection.Projection; 8 9 import org.openstreetmap.josm.gui.MapView; 9 10 … … 23 24 * @author imi 24 25 */ 25 public interfaceLayer {26 abstract public class Layer { 26 27 27 28 /** 28 * Draw the layer on the given Graphics. The state of the graphics object 29 * can be changed (drawing color..) 30 * 31 * @param g The graphics to draw the layer on. 32 * @param mv The MapView with information about the screen layout. 29 * The visibility state of the layer. 33 30 */ 34 void paint(Graphics g, MapView mv); 31 public boolean visible = true; 32 /** 33 * The name of this layer. 34 */ 35 public final String name; 35 36 37 /** 38 * Create the layer and fill in the necessary components. 39 */ 40 public Layer(String name) { 41 this.name = name; 42 } 43 44 /** 45 * Paint the dataset using the engine set. 46 * @param mv The object that can translate GeoPoints to screen coordinates. 47 */ 48 abstract public void paint(Graphics g, MapView mv); 36 49 /** 37 50 * Return a representative small image for this layer. The image must not 38 51 * be larger than 64 pixel in any dimension. 39 52 */ 40 Icon getIcon();53 abstract public Icon getIcon(); 41 54 42 55 /** 43 * Provide a human readable name (may be in html format).56 * @return A small tooltip hint about some statistics for this layer. 44 57 */ 45 String getName(); 58 abstract public String getToolTipText(); 59 60 /** 61 * Merges the given layer into this layer. Throws if the layer types are 62 * incompatible. 63 * @param from The layer that get merged into this one. After the merge, 64 * the other layer is not usable anymore and passing to one others 65 * mergeFrom should be one of the last things to do with a layer. 66 */ 67 abstract public void mergeFrom(Layer from); 46 68 47 69 /** 48 * If the layer has a dataset it can provide, return it here. 49 * @return The dataset for this layer or <code>null</code> if no dataset 50 * is available. 70 * @param other The other layer that is tested to be mergable with this. 71 * @return Whether the other layer can be merged into this layer. 51 72 */ 52 DataSet getDataSet();73 abstract public boolean isMergable(Layer other); 53 74 54 75 /** 55 * @return <code>true</code>, if the map data can be edited. 76 * @return The bounding rectangle this layer occupies on screen when looking 77 * at lat/lon values or <code>null</code>, if infinite area or unknown 78 * area is occupied. 56 79 */ 57 boolean isEditable(); 80 abstract public Bounds getBoundsLatLon(); 81 82 /** 83 * @return The bounding rectangle this layer occupies on screen when looking 84 * at x/y values or <code>null</code>, if infinite area or unknown 85 * area is occupied. 86 */ 87 abstract public Bounds getBoundsXY(); 58 88 59 89 /** 60 * @return <code>true</code>, if the layer is visible90 * Initialize the internal dataset with the given projection. 61 91 */ 62 boolean isVisible(); 63 64 /** 65 * Set the visibility state of the layer. 66 */ 67 void setVisible(boolean visible); 92 abstract public void init(Projection projection); 68 93 } -
/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
r20 r30 1 1 package org.openstreetmap.josm.gui.layer; 2 3 import java.awt.Graphics; 4 import java.io.FileWriter; 5 import java.io.StringWriter; 6 import java.util.LinkedList; 2 7 3 8 import javax.swing.Icon; 4 9 10 import org.openstreetmap.josm.Main; 11 import org.openstreetmap.josm.command.Command; 12 import org.openstreetmap.josm.data.Bounds; 5 13 import org.openstreetmap.josm.data.osm.DataSet; 14 import org.openstreetmap.josm.data.osm.LineSegment; 15 import org.openstreetmap.josm.data.osm.Node; 16 import org.openstreetmap.josm.data.osm.Track; 17 import org.openstreetmap.josm.data.osm.visitor.BoundingVisitor; 18 import org.openstreetmap.josm.data.osm.visitor.CsvVisitor; 19 import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor; 20 import org.openstreetmap.josm.data.projection.Projection; 6 21 import org.openstreetmap.josm.gui.ImageProvider; 7 import org.openstreetmap.josm.gui. engine.SimpleEngine;22 import org.openstreetmap.josm.gui.MapView; 8 23 9 24 /** 10 * A layer holding data imported from the osm server. 11 * 25 * A layer holding data from a specific dataset. 12 26 * The data can be fully edited. 13 27 * 14 28 * @author imi 15 29 */ 16 public class OsmDataLayer extends DataLayer {30 public class OsmDataLayer extends Layer { 17 31 18 32 private static Icon icon; 19 33 34 /** 35 * The data behind this layer. 36 */ 37 public final DataSet data; 38 39 /** 40 * All commands that were made on the dataset. 41 */ 42 private LinkedList<Command> commands = new LinkedList<Command>(); 43 private LinkedList<String> debugDsBefore = new LinkedList<String>(); 44 20 45 /** 21 46 * Construct a OsmDataLayer. 22 47 */ 23 protected OsmDataLayer(DataSet dataSet, String name) { 24 super(dataSet, new SimpleEngine(), name); 48 public OsmDataLayer(DataSet data, String name) { 49 super(name); 50 this.data = data; 25 51 } 26 52 … … 29 55 * updated by a background thread to not disturb the running programm. 30 56 */ 57 @Override 31 58 public Icon getIcon() { 32 59 if (icon == null) … … 35 62 } 36 63 37 public boolean isEditable() { 38 return true; 64 /** 65 * Draw all primitives in this layer but do not draw modified ones (they 66 * are drawn by the edit layer). 67 * Draw nodes last to overlap the line segments they belong to. 68 */ 69 @Override 70 public void paint(Graphics g, MapView mv) { 71 SimplePaintVisitor visitor = new SimplePaintVisitor(g, mv, null); 72 73 for (Track t : data.tracks) 74 visitor.visit(t); 75 for (LineSegment ls : data.lineSegments) 76 visitor.visit(ls); 77 for (Node n : data.nodes) 78 visitor.visit(n); 79 } 80 81 @Override 82 public String getToolTipText() { 83 return data.nodes.size()+" nodes, "+data.tracks.size()+" streets."; 84 } 85 86 @Override 87 public void mergeFrom(Layer from) { 88 data.mergeFrom(((OsmDataLayer)from).data); 89 } 90 91 @Override 92 public boolean isMergable(Layer other) { 93 return other instanceof OsmDataLayer; 94 } 95 96 @Override 97 public Bounds getBoundsLatLon() { 98 BoundingVisitor b = new BoundingVisitor(BoundingVisitor.Type.LATLON); 99 for (Node n : data.nodes) 100 b.visit(n); 101 return b.bounds; 102 } 103 104 @Override 105 public Bounds getBoundsXY() { 106 BoundingVisitor b = new BoundingVisitor(BoundingVisitor.Type.XY); 107 for (Node n : data.nodes) 108 b.visit(n); 109 return b.bounds; 110 } 111 112 @Override 113 public void init(Projection projection) { 114 for (Node n : data.nodes) 115 projection.latlon2xy(n.coor); 116 } 117 118 /** 119 * Execute the command and add it to the intern command queue. Also mark all 120 * primitives in the command as modified. 121 */ 122 public void add(Command c) { 123 StringWriter sw = new StringWriter(); 124 CsvVisitor v = new CsvVisitor(sw); 125 for (Node n : Main.main.ds.nodes) { 126 v.visit(n); 127 sw.append('\n'); 128 } 129 for (LineSegment ls : Main.main.ds.lineSegments) { 130 v.visit(ls); 131 sw.append('\n'); 132 } 133 for (Track t : Main.main.ds.tracks) { 134 v.visit(t); 135 sw.append('\n'); 136 } 137 debugDsBefore.add(sw.getBuffer().toString()); 138 139 c.executeCommand(); 140 commands.add(c); 141 } 142 143 /** 144 * Undoes the last added command. 145 */ 146 public void undo() { 147 if (commands.isEmpty()) 148 return; 149 Command c = commands.removeLast(); 150 c.undoCommand(); 151 152 //DEBUG 153 StringWriter sw = new StringWriter(); 154 CsvVisitor v = new CsvVisitor(sw); 155 for (Node n : Main.main.ds.nodes) { 156 v.visit(n); 157 sw.append('\n'); 158 } 159 for (LineSegment ls : Main.main.ds.lineSegments) { 160 v.visit(ls); 161 sw.append('\n'); 162 } 163 for (Track t : Main.main.ds.tracks) { 164 v.visit(t); 165 sw.append('\n'); 166 } 167 String s = Main.main.getMapFrame().mapView.editLayer().debugDsBefore.removeLast(); 168 if (!s.equals(sw.getBuffer().toString())) { 169 try { 170 FileWriter fw = new FileWriter("/home/imi/richtig"); 171 fw.append(sw.getBuffer().toString()); 172 fw.close(); 173 fw = new FileWriter("/home/imi/falsch"); 174 fw.append(s); 175 fw.close(); 176 } catch (Exception x) { 177 x.printStackTrace(); 178 } 179 } 39 180 } 40 181 } -
/src/org/openstreetmap/josm/gui/layer/RawGpsDataLayer.java
r20 r30 1 1 package org.openstreetmap.josm.gui.layer; 2 3 import java.awt.Color; 4 import java.awt.Graphics; 5 import java.awt.Point; 6 import java.beans.PropertyChangeEvent; 7 import java.beans.PropertyChangeListener; 8 import java.util.Collection; 2 9 3 10 import javax.swing.Icon; 4 11 5 import org.openstreetmap.josm.data.osm.DataSet; 12 import org.openstreetmap.josm.Main; 13 import org.openstreetmap.josm.data.Bounds; 14 import org.openstreetmap.josm.data.GeoPoint; 15 import org.openstreetmap.josm.data.projection.Projection; 6 16 import org.openstreetmap.josm.gui.ImageProvider; 7 import org.openstreetmap.josm.gui. engine.RawGpsEngine;17 import org.openstreetmap.josm.gui.MapView; 8 18 9 19 /** … … 13 23 * @author imi 14 24 */ 15 public class RawGpsDataLayer extends DataLayer {25 public class RawGpsDataLayer extends Layer { 16 26 17 27 private static Icon icon; 18 28 19 protected RawGpsDataLayer(DataSet dataSet, String name) { 20 super(dataSet, new RawGpsEngine(), name); 29 /** 30 * A list of tracks which containing a list of points. 31 */ 32 private final Collection<Collection<GeoPoint>> data; 33 34 public RawGpsDataLayer(Collection<Collection<GeoPoint>> data, String name) { 35 super(name); 36 this.data = data; 37 Main.pref.addPropertyChangeListener(new PropertyChangeListener(){ 38 public void propertyChange(PropertyChangeEvent evt) { 39 if (Main.main.getMapFrame() == null) { 40 Main.pref.removePropertyChangeListener(this); 41 return; 42 } 43 if (evt.getPropertyName().equals("drawRawGpsLines") || 44 evt.getPropertyName().equals("drawRawGpsLines")) 45 Main.main.getMapFrame().repaint(); 46 } 47 }); 21 48 } 22 49 … … 24 51 * Return a static icon. 25 52 */ 53 @Override 26 54 public Icon getIcon() { 27 55 if (icon == null) … … 30 58 } 31 59 32 public boolean isEditable() { 33 return false; 60 @Override 61 public void paint(Graphics g, MapView mv) { 62 g.setColor(Color.GRAY); 63 Point old = null; 64 for (Collection<GeoPoint> c : data) { 65 if (!Main.pref.isForceRawGpsLines()) 66 old = null; 67 for (GeoPoint p : c) { 68 Point screen = mv.getScreenPoint(p); 69 if (Main.pref.isDrawRawGpsLines() && old != null) { 70 g.drawLine(old.x, old.y, screen.x, screen.y); 71 } else { 72 g.drawRect(screen.x, screen.y, 0, 0); 73 old = screen; 74 } 75 } 76 } 77 } 78 79 @Override 80 public String getToolTipText() { 81 return data.size()+" tracks."; 82 } 83 84 @Override 85 public void mergeFrom(Layer from) { 86 RawGpsDataLayer layer = (RawGpsDataLayer)from; 87 data.addAll(layer.data); 88 } 89 90 @Override 91 public boolean isMergable(Layer other) { 92 return other instanceof RawGpsDataLayer; 93 } 94 95 @Override 96 public Bounds getBoundsLatLon() { 97 GeoPoint min = null; 98 GeoPoint max = null; 99 for (Collection<GeoPoint> c : data) { 100 for (GeoPoint p : c) { 101 if (min == null) { 102 min = p.clone(); 103 max = p.clone(); 104 } else { 105 min.lat = Math.min(min.lat, p.lat); 106 min.lon = Math.min(min.lon, p.lon); 107 max.lat = Math.max(max.lat, p.lat); 108 max.lon = Math.max(max.lon, p.lon); 109 } 110 } 111 } 112 if (min == null) 113 return null; 114 return new Bounds(min, max); 115 } 116 117 @Override 118 public Bounds getBoundsXY() { 119 GeoPoint min = null; 120 GeoPoint max = null; 121 for (Collection<GeoPoint> c : data) { 122 for (GeoPoint p : c) { 123 if (min == null) { 124 min = p.clone(); 125 max = p.clone(); 126 } else { 127 min.x = Math.min(min.x, p.x); 128 min.y = Math.min(min.y, p.y); 129 max.x = Math.max(max.x, p.x); 130 max.y = Math.max(max.y, p.y); 131 } 132 } 133 } 134 if (min == null) 135 return null; 136 return new Bounds(min, max); 137 } 138 139 @Override 140 public void init(Projection projection) { 141 for (Collection<GeoPoint> c : data) 142 for (GeoPoint p : c) 143 projection.latlon2xy(p); 34 144 } 35 145 } -
/src/org/openstreetmap/josm/io/GpxReader.java
r20 r30 9 9 import org.jdom.Namespace; 10 10 import org.jdom.input.SAXBuilder; 11 import org.openstreetmap.josm.Main; 11 12 import org.openstreetmap.josm.data.GeoPoint; 12 13 import org.openstreetmap.josm.data.osm.DataSet; … … 16 17 import org.openstreetmap.josm.data.osm.OsmPrimitive; 17 18 import org.openstreetmap.josm.data.osm.Track; 18 import org.openstreetmap.josm.gui.Main;19 19 20 20 /** … … 25 25 * @author imi 26 26 */ 27 public class GpxReader implements DataReader{27 public class GpxReader { 28 28 29 29 /** 30 30 * The GPX namespace used. 31 31 */ 32 p rivate staticNamespace GPX = Namespace.getNamespace("http://www.topografix.com/GPX/1/0");32 public static final Namespace GPX = Namespace.getNamespace("http://www.topografix.com/GPX/1/0"); 33 33 /** 34 34 * The OSM namespace used (for extensions). 35 35 */ 36 private static final Namespace OSM = Namespace.getNamespace("osm" );36 private static final Namespace OSM = Namespace.getNamespace("osm", "http://www.openstreetmap.org"); 37 37 38 38 /** … … 40 40 */ 41 41 public Reader source; 42 /** 43 * If <code>true</code>, only nodes and tracks are imported (but no key/value 44 * pairs). That is to support background gps information as an hint for 45 * real OSM data. 46 */ 47 private final boolean rawGps; 48 42 49 43 /** 50 44 * Construct a parser from a specific data source. 51 45 * @param source The data source, as example a FileReader to read from a file. 52 * @param rawGps Whether the gpx file describes raw gps data. Only very few 53 * information (only nodes and line segments) imported for raw gps to 54 * save memory. 55 */ 56 public GpxReader(Reader source, boolean rawGps) { 46 */ 47 public GpxReader(Reader source) { 57 48 this.source = source; 58 this.rawGps = rawGps;59 49 } 60 50 … … 62 52 * Read the input stream and return a DataSet from the stream. 63 53 */ 64 public DataSet parse() throws ParseException, ConnectionException {54 public DataSet parse() throws JDOMException, IOException { 65 55 try { 66 56 final SAXBuilder builder = new SAXBuilder(); 67 57 Element root = builder.build(source).getRootElement(); 68 69 // HACK, since the osm server seem to not provide a namespace.70 if (root.getNamespacePrefix().equals(""))71 GPX = null;72 73 58 return parseDataSet(root); 74 59 } catch (NullPointerException npe) { 75 throw new ParseException("NullPointerException. Probably a tag name mismatch.", npe);60 throw new JDOMException("NullPointerException. Probably a tag name mismatch.", npe); 76 61 } catch (ClassCastException cce) { 77 throw new ParseException("ClassCastException. Probably a tag does not contain the correct type.", cce); 78 } catch (JDOMException e) { 79 throw new ParseException("The data could not be parsed. Reason: "+e.getMessage(), e); 80 } catch (IOException e) { 81 throw new ConnectionException("The data could not be retrieved. Reason: "+e.getMessage(), e); 62 throw new JDOMException("ClassCastException. Probably a tag does not contain the correct type.", cce); 82 63 } 83 64 } … … 94 75 Float.parseFloat(e.getAttributeValue("lat")), 95 76 Float.parseFloat(e.getAttributeValue("lon"))); 96 97 if (rawGps)98 return data;99 77 100 78 for (Object o : e.getChildren()) { … … 137 115 private void parseTrack(Element e, DataSet ds) { 138 116 Track track = new Track(); 117 boolean realLineSegment = false; // is this track just a fake? 118 139 119 for (Object o : e.getChildren()) { 140 120 Element child = (Element)o; … … 149 129 else { 150 130 LineSegment lineSegment = new LineSegment(start, node); 151 if (!rawGps) 152 parseKeyValueExtensions(lineSegment, ((Element)w).getChild("extensions", GPX)); 131 parseKeyValueExtensions(lineSegment, child.getChild("extensions", GPX)); 153 132 track.add(lineSegment); 154 133 start = null; 155 134 } 156 135 } 157 } 158 159 if (rawGps) 160 continue; 161 162 if (child.getName().equals("extensions")) 136 } else if (child.getName().equals("extensions")) { 163 137 parseKeyValueExtensions(track, child); 164 else if (child.getName().equals("link")) 138 if (child.getChild("segment", OSM) != null) 139 realLineSegment = true; 140 } else if (child.getName().equals("link")) 165 141 parseKeyValueLink(track, child); 166 142 else 167 143 parseKeyValueTag(track, child); 168 144 } 169 ds.addTrack(track); 145 if (realLineSegment && track.segments.size() == 1) 146 ds.lineSegments.add(track.segments.get(0)); 147 else { 148 ds.tracks.add(track); 149 ds.lineSegments.addAll(track.segments); 150 } 170 151 } 171 152 … … 183 164 * @return Either the parameter node or the old node found in the dataset. 184 165 */ 185 private Node addNode 186 if (Main.pref.mergeNodes || rawGps)166 private Node addNode(DataSet data, Node node) { 167 if (Main.pref.mergeNodes) 187 168 for (Node n : data.nodes) 188 169 if (node.coor.equalsLatLon(n.coor)) … … 203 184 private void parseKeyValueExtensions(OsmPrimitive osm, Element e) { 204 185 if (e != null) { 205 if (osm.keys == null)206 osm.keys = new HashMap<Key, String>();207 186 for (Object o : e.getChildren("property", OSM)) { 187 if (osm.keys == null) 188 osm.keys = new HashMap<Key, String>(); 208 189 Element child = (Element)o; 209 Key key = Key.get(child.getAttributeValue("name")); 210 osm.keys.put(key, child.getAttributeValue("value")); 190 String keyname = child.getAttributeValue("key"); 191 if (keyname != null) { 192 Key key = Key.get(keyname); 193 String value = child.getAttributeValue("value"); 194 if (value == null) 195 value = ""; 196 osm.keys.put(key, value); 197 } 211 198 } 212 199 } -
/src/org/openstreetmap/josm/io/GpxWriter.java
r20 r30 14 14 import org.jdom.output.Format; 15 15 import org.jdom.output.XMLOutputter; 16 import org.openstreetmap.josm. data.osm.DataSet;16 import org.openstreetmap.josm.Main; 17 17 import org.openstreetmap.josm.data.osm.Key; 18 18 import org.openstreetmap.josm.data.osm.LineSegment; … … 47 47 */ 48 48 private Writer out; 49 /**50 * The DataSet this outputter operates on.51 */52 private final DataSet ds;53 49 54 50 /** … … 57 53 * 58 54 * @param out The Writer to store the result data in. 59 * @param ds The dataset to store. 60 */ 61 public GpxWriter(Writer out, DataSet ds) { 62 this.ds = ds; 55 */ 56 public GpxWriter(Writer out) { 63 57 this.out = out; 64 58 } … … 86 80 Element e = new Element("gpx", GPX); 87 81 e.setAttribute("version", "1.0"); 88 e.setAttribute("creator", "JOSM Beta ");82 e.setAttribute("creator", "JOSM Beta2"); 89 83 // for getting all unreferenced waypoints in the wpt-list 90 LinkedList<Node> nodes = new LinkedList<Node>( ds.nodes);84 LinkedList<Node> nodes = new LinkedList<Node>(Main.main.ds.nodes); 91 85 92 86 // tracks 93 for (Track t : ds.tracks()) {87 for (Track t : Main.main.ds.tracks) { 94 88 Element tElem = new Element("trk", GPX); 95 89 if (t.keys != null) { … … 105 99 } 106 100 // line segments 107 for (LineSegment ls : t.segments()) { 108 Element lsElem = new Element("trkseg", GPX); 109 if (ls.keys != null) 110 addPropertyExtensions(lsElem, ls.keys); 111 lsElem.getChildren().add(parseWaypoint(ls.getStart(), "trkpt")); 112 lsElem.getChildren().add(parseWaypoint(ls.getEnd(), "trkpt")); 113 nodes.remove(ls.getStart()); 114 nodes.remove(ls.getEnd()); 115 tElem.getChildren().add(lsElem); 101 for (LineSegment ls : t.segments) { 102 tElem.getChildren().add(parseLineSegment(ls)); 103 nodes.remove(ls.start); 104 nodes.remove(ls.end); 116 105 } 106 117 107 e.getChildren().add(tElem); 118 108 } 119 109 110 // encode pending line segments as tracks 111 for (LineSegment ls : Main.main.ds.lineSegments) { 112 Element t = new Element("trk", GPX); 113 t.getChildren().add(parseLineSegment(ls)); 114 nodes.remove(ls.start); 115 nodes.remove(ls.end); 116 Element ext = new Element("extensions", GPX); 117 ext.getChildren().add(new Element("segment", OSM)); 118 t.getChildren().add(ext); 119 e.getChildren().add(t); 120 } 121 120 122 // waypoints (missing nodes) 121 123 for (Node n : nodes) … … 123 125 124 126 return e; 127 } 128 129 130 /** 131 * Parse a line segment and store it into a JDOM-Element. Return that element. 132 */ 133 @SuppressWarnings("unchecked") 134 private Element parseLineSegment(LineSegment ls) { 135 Element lsElem = new Element("trkseg", GPX); 136 if (ls.keys != null) 137 addPropertyExtensions(lsElem, ls.keys); 138 lsElem.getChildren().add(parseWaypoint(ls.start, "trkpt")); 139 lsElem.getChildren().add(parseWaypoint(ls.end, "trkpt")); 140 return lsElem; 125 141 } 126 142 … … 219 235 if (keys.isEmpty()) 220 236 return; 221 Element extensions = e.getChild("extensions" );237 Element extensions = e.getChild("extensions", GPX); 222 238 if (extensions == null) 223 239 e.getChildren().add(extensions = new Element("extensions", GPX)); -
/src/org/openstreetmap/josm/io/OsmReader.java
r20 r30 1 1 package org.openstreetmap.josm.io; 2 2 3 import java.awt.Font;4 import java.awt.GridBagLayout;5 3 import java.io.IOException; 6 import java.io.InputStreamReader;7 4 import java.io.Reader; 8 import java.net.Authenticator; 9 import java.net.HttpURLConnection; 10 import java.net.PasswordAuthentication; 11 import java.net.URL; 12 13 import javax.swing.JLabel; 14 import javax.swing.JOptionPane; 15 import javax.swing.JPanel; 16 import javax.swing.JPasswordField; 17 import javax.swing.JTextField; 18 5 import java.util.Collection; 6 import java.util.HashMap; 7 import java.util.StringTokenizer; 8 9 import org.jdom.Element; 10 import org.jdom.JDOMException; 11 import org.jdom.input.SAXBuilder; 12 import org.openstreetmap.josm.Main; 13 import org.openstreetmap.josm.data.GeoPoint; 19 14 import org.openstreetmap.josm.data.osm.DataSet; 20 import org.openstreetmap.josm.gui.GBC; 21 import org.openstreetmap.josm.gui.Main; 15 import org.openstreetmap.josm.data.osm.Key; 16 import org.openstreetmap.josm.data.osm.LineSegment; 17 import org.openstreetmap.josm.data.osm.Node; 18 import org.openstreetmap.josm.data.osm.OsmPrimitive; 19 import org.openstreetmap.josm.data.osm.Track; 22 20 23 21 /** 24 * This DataReader read directly from the REST API of the osm server.22 * Reads an osm xml stream and construct a DataSet out of it. 25 23 * 26 24 * @author imi 27 25 */ 28 public class OsmReader implements DataReader { 29 30 /** 31 * The url string of the desired map data. 32 */ 33 private String urlStr; 34 /** 35 * Whether importing the raw trackpoints or the regular osm map information 36 */ 37 private boolean rawGps; 38 /** 39 * Whether the user cancelled the password dialog 40 */ 41 private boolean cancelled = false; 42 /** 43 * Set to true, when the autenticator tried the password once. 44 */ 45 private boolean passwordtried = false; 46 47 /** 48 * Construct the reader and store the information for attaching 49 */ 50 public OsmReader(String server, boolean rawGps, 51 double lat1, double lon1, double lat2, double lon2) { 52 this.rawGps = rawGps; 53 urlStr = server.endsWith("/") ? server : server+"/"; 54 urlStr += rawGps?"trackpoints" : "map"; 55 urlStr += "?bbox="+lon1+","+lat1+","+lon2+","+lat2; 56 if (rawGps) 57 urlStr += "&page="; 26 public class OsmReader { 27 28 /** 29 * The data source from this reader. 30 */ 31 public Reader source; 32 33 /** 34 * Construct a parser from a specific data source. 35 * @param source The data source, as example a FileReader to read from a file. 36 */ 37 public OsmReader(Reader source) { 38 this.source = source; 39 } 40 static int i; 41 /** 42 * Read the input stream and return a DataSet from the stream. 43 */ 44 public DataSet parse() throws JDOMException, IOException { 45 try { 46 final SAXBuilder builder = new SAXBuilder(); 47 Element root = builder.build(source).getRootElement(); 48 return parseDataSet(root); 49 } catch (NumberFormatException nfe) { 50 throw new JDOMException("NumberFormatException. Probably a tag is missing.", nfe); 51 } catch (NullPointerException npe) { 52 throw new JDOMException("NullPointerException. Probably a tag name mismatch.", npe); 53 } catch (ClassCastException cce) { 54 throw new JDOMException("ClassCastException. Probably a tag does not contain the correct type.", cce); 55 } 56 } 57 58 59 /** 60 * Read one node. 61 * @param e The element to parse 62 * @return The Waypoint read from the element 63 * @throws JDOMException In case of a parsing error. 64 */ 65 private Node parseNode(Element e) throws JDOMException { 66 Node data = new Node(); 67 data.coor = new GeoPoint( 68 Float.parseFloat(e.getAttributeValue("lat")), 69 Float.parseFloat(e.getAttributeValue("lon"))); 70 if (Double.isNaN(data.coor.lat) || 71 data.coor.lat < -90 || data.coor.lat > 90 || 72 data.coor.lon < -180 || data.coor.lon > 180) 73 throw new JDOMException("Illegal lat or lon value: "+data.coor.lat+"/"+data.coor.lon); 74 parseCommon(data, e); 75 return data; 76 } 77 78 /** 79 * Parse the common part (properties and uid) of the element. 80 * @param data To store the data in. 81 * @param e The element to extract the common information. 82 * @throws JDOMException In case of a parsing error 83 */ 84 private void parseCommon(OsmPrimitive data, Element e) throws JDOMException { 85 data.id = Long.parseLong(e.getAttributeValue("uid")); 86 if (data.id == 0) 87 throw new JDOMException("Object has illegal or no id."); 58 88 59 HttpURLConnection.setFollowRedirects(true); 60 Authenticator.setDefault(new Authenticator(){ 61 @Override 62 protected PasswordAuthentication getPasswordAuthentication() { 63 String username = Main.pref.osmDataUsername; 64 String password = Main.pref.osmDataPassword; 65 if (passwordtried || "".equals(username) || password == null || "".equals(password)) { 66 JPanel p = new JPanel(new GridBagLayout()); 67 p.add(new JLabel("Username"), GBC.std().insets(0,0,10,0)); 68 JTextField usernameField = new JTextField("".equals(username) ? "" : username, 20); 69 p.add(usernameField, GBC.eol()); 70 p.add(new JLabel("Password"), GBC.std().insets(0,0,10,0)); 71 JPasswordField passwordField = new JPasswordField(password == null ? "" : password, 20); 72 p.add(passwordField, GBC.eol()); 73 JLabel warning = new JLabel("Warning: The password is transferred unencrypted."); 74 warning.setFont(warning.getFont().deriveFont(Font.ITALIC)); 75 p.add(warning, GBC.eol()); 76 int choice = JOptionPane.showConfirmDialog(Main.main, p, "Enter Password", JOptionPane.OK_CANCEL_OPTION); 77 if (choice == JOptionPane.CANCEL_OPTION) { 78 cancelled = true; 79 return null; 80 } 81 username = usernameField.getText(); 82 password = String.valueOf(passwordField.getPassword()); 83 if ("".equals(username)) 84 return null; 89 String propStr = e.getAttributeValue("tags"); 90 if (propStr != null && !propStr.equals("")) { 91 data.keys = new HashMap<Key, String>(); 92 StringTokenizer st = new StringTokenizer(propStr, ";"); 93 while (st.hasMoreTokens()) { 94 StringTokenizer t = new StringTokenizer(st.nextToken(), "="); 95 if (t.countTokens() > 1) 96 data.keys.put(Key.get(t.nextToken()), t.nextToken()); 97 else { 98 String token = t.nextToken(); 99 if (!" ".equals(token)) 100 data.keys.put(Key.get(token), ""); 85 101 } 86 passwordtried = true; 87 return new PasswordAuthentication(username, password.toCharArray()); 88 } 89 }); 90 } 91 92 93 public DataSet parse() throws ParseException, ConnectionException { 94 Reader in; 95 try { 96 if (rawGps) { 97 DataSet ds = new DataSet(); 98 for (int i = 0;;++i) { 99 URL url = new URL(urlStr+i); 100 HttpURLConnection con = (HttpURLConnection)url.openConnection(); 101 con.setConnectTimeout(20000); 102 if (con.getResponseCode() == 401 && cancelled) 103 return null; 104 in = new InputStreamReader(con.getInputStream()); 105 DataSet currentData = new GpxReader(in, true).parse(); 106 if (currentData.nodes.isEmpty()) 107 return ds; 108 ds.mergeFrom(currentData, true); 102 } 103 } 104 } 105 106 /** 107 * Read a data set from the element. 108 * @param e The element to parse 109 * @return The DataSet read from the element 110 * @throws JDOMException In case of a parsing error. 111 */ 112 private DataSet parseDataSet(Element e) throws JDOMException { 113 DataSet data = new DataSet(); 114 for (Object o : e.getChildren()) { 115 Element child = (Element)o; 116 if (child.getName().equals("node")) 117 addNode(data, parseNode(child)); 118 else if (child.getName().equals("segment")) { 119 LineSegment ls = parseLineSegment(child, data); 120 if (data.lineSegments.contains(ls)) 121 throw new JDOMException("Double segment definition "+ls.id); 122 for (Track t : data.tracks) 123 if (t.segments.contains(ls)) 124 throw new JDOMException("Double segment definition "+ls.id); 125 data.lineSegments.add(ls); 126 } else if (child.getName().equals("track")) { 127 Track track = parseTrack(child, data); 128 if (data.tracks.contains(track)) 129 throw new JDOMException("Double track definition "+track.id); 130 data.tracks.add(track); 131 } 132 } 133 134 return data; 135 } 136 137 /** 138 * Parse and return an line segment. The node information of the "from" and 139 * "to" attributes must already be in the dataset. 140 * @param e The line segment element to parse. 141 * @param data The dataset to obtain the node information from. 142 * @return The parsed line segment. 143 * @throws JDOMException In case of parsing errors. 144 */ 145 private LineSegment parseLineSegment(Element e, DataSet data) throws JDOMException { 146 long startId = Long.parseLong(e.getAttributeValue("from")); 147 long endId = Long.parseLong(e.getAttributeValue("to")); 148 149 Node start = null, end = null; 150 for (Node n : data.nodes) { 151 if (n.id == startId) 152 start = n; 153 if (n.id == endId) 154 end = n; 155 } 156 if (start == null || end == null) 157 throw new JDOMException("The 'from' or 'to' object has not been transfered before."); 158 LineSegment ls = new LineSegment(start, end); 159 parseCommon(ls, e); 160 return ls; 161 } 162 163 /** 164 * Parse and read a track from the element. 165 * 166 * @param e The element that contain the track. 167 * @param data The DataSet to get segment information from. 168 * @return The parsed track. 169 * @throws JDOMException In case of a parsing error. 170 */ 171 private Track parseTrack(Element e, DataSet data) throws JDOMException { 172 Track track = new Track(); 173 parseCommon(track, e); 174 for (Object o : e.getChildren("segment")) { 175 Element child = (Element)o; 176 long id = Long.parseLong(child.getAttributeValue("uid")); 177 LineSegment ls = findLineSegment(data.lineSegments, id); 178 if (ls != null) { 179 track.segments.add(ls); 180 data.lineSegments.remove(ls); 181 continue; 182 } 183 for (Track t : data.tracks) { 184 ls = findLineSegment(t.segments, id); 185 if (ls != null) { 186 track.segments.add(ls); 187 break; 109 188 } 110 189 } 111 URL url = new URL(urlStr); 112 HttpURLConnection con = (HttpURLConnection)url.openConnection(); 113 con.setConnectTimeout(20000); 114 if (con.getResponseCode() == 401 && cancelled) 115 return null; 116 in = new InputStreamReader(con.getInputStream()); 117 return new GpxReader(in, false).parse(); 118 } catch (IOException e) { 119 throw new ConnectionException("Failed to open server connection\n"+e.getMessage(), e); 120 } 190 } 191 return track; 192 } 193 194 /** 195 * Search for a segment in a collection by comparing the id. 196 */ 197 private LineSegment findLineSegment(Collection<LineSegment> segments, long id) { 198 for (LineSegment ls : segments) 199 if (ls.id == id) 200 return ls; 201 return null; 202 } 203 204 /** 205 * Adds the node to allNodes if it is not already listed. Does respect the 206 * preference setting "mergeNodes". Return the node in the list that correspond 207 * to the node in the list (either the new added or the old found). 208 * 209 * If reading raw gps data, mergeNodes are always on (To save memory. You 210 * can't edit raw gps nodes anyway.) 211 * 212 * @param data The DataSet to add the node to. 213 * @param node The node that should be added. 214 * @return Either the parameter node or the old node found in the dataset. 215 */ 216 private Node addNode(DataSet data, Node node) { 217 if (Main.pref.mergeNodes) 218 for (Node n : data.nodes) 219 if (node.coor.equalsLatLon(n.coor)) 220 return n; 221 data.nodes.add(node); 222 return node; 121 223 } 122 224 }
Note:
See TracChangeset
for help on using the changeset viewer.