- Files:
-
- 15 added
- 22 deleted
- 45 edited
Legend:
- Unmodified
- Added
- Removed
-
/.classpath
r30 r20 2 2 <classpath> 3 3 <classpathentry kind="src" path="src"/> 4 <classpathentry including="images/" kind="src" path=""/>5 4 <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> 6 5 <classpathentry sourcepath="/home/imi/src/jdom-1.0/src" kind="lib" path="lib/jdom.jar"/> -
/src/org/openstreetmap/josm/actions/AboutAction.java
r30 r20 13 13 import java.util.regex.Pattern; 14 14 15 import javax.swing.AbstractAction; 15 16 import javax.swing.JEditorPane; 16 17 import javax.swing.JLabel; … … 23 24 import javax.swing.event.HyperlinkListener; 24 25 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; 28 29 29 30 /** … … 35 36 * @author imi 36 37 */ 37 public class AboutAction extends JosmAction {38 public class AboutAction extends AbstractAction { 38 39 39 40 public AboutAction() { 40 super("About", "about", "Display the about screen.", KeyEvent.VK_A, null); 41 super("About", ImageProvider.get("about")); 42 putValue(MNEMONIC_KEY, KeyEvent.VK_A); 43 putValue(SHORT_DESCRIPTION, "Display the about screen."); 41 44 } 42 45 -
/src/org/openstreetmap/josm/actions/AutoScaleAction.java
r30 r20 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; 6 11 import org.openstreetmap.josm.gui.MapFrame; 7 12 import org.openstreetmap.josm.gui.MapView; … … 11 16 * @author imi 12 17 */ 13 public class AutoScaleAction extends JosmAction {18 public class AutoScaleAction extends AbstractAction { 14 19 /** 15 20 * The mapView this action operates on. … … 18 23 19 24 public AutoScaleAction(MapFrame mapFrame) { 20 super("Auto Scale", "autoscale", "Zoom the view to show the whole layer. Disabled if the view is moved.", 21 KeyEvent.VK_A, null); 25 super("Auto Scale", ImageProvider.get("autoscale")); 22 26 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); 23 33 } 24 34 -
/src/org/openstreetmap/josm/actions/ExitAction.java
r30 r20 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; 5 9 6 10 /** … … 9 13 * @author imi 10 14 */ 11 public class ExitAction extends JosmAction {15 public class ExitAction extends AbstractAction { 12 16 13 17 /** … … 15 19 */ 16 20 public ExitAction() { 17 super("Exit", "exit", "Exit the application.", KeyEvent.VK_X, null); 21 super("Exit", ImageProvider.get("exit")); 22 putValue(MNEMONIC_KEY, KeyEvent.VK_X); 23 putValue(SHORT_DESCRIPTION, "Exit the application."); 18 24 } 19 25 -
/src/org/openstreetmap/josm/actions/OpenOsmServerAction.java
r30 r20 5 5 import java.awt.event.ActionEvent; 6 6 import java.awt.event.ActionListener; 7 import java.awt.event.InputEvent;8 7 import java.awt.event.KeyEvent; 9 import java.io.IOException;10 8 9 import javax.swing.AbstractAction; 11 10 import javax.swing.DefaultListModel; 12 11 import javax.swing.JButton; … … 17 16 import javax.swing.JScrollPane; 18 17 import javax.swing.JTextField; 19 import javax.swing.KeyStroke;20 18 import javax.swing.event.ListSelectionEvent; 21 19 import javax.swing.event.ListSelectionListener; 22 20 23 import org.jdom.JDOMException;24 import org.openstreetmap.josm.Main;25 21 import org.openstreetmap.josm.data.GeoPoint; 26 22 import org.openstreetmap.josm.data.osm.DataSet; 27 23 import org.openstreetmap.josm.gui.BookmarkList; 28 24 import org.openstreetmap.josm.gui.GBC; 25 import org.openstreetmap.josm.gui.ImageProvider; 26 import org.openstreetmap.josm.gui.Main; 29 27 import org.openstreetmap.josm.gui.MapFrame; 30 28 import org.openstreetmap.josm.gui.MapView; 31 29 import org.openstreetmap.josm.gui.BookmarkList.Bookmark; 32 30 import org.openstreetmap.josm.gui.layer.Layer; 33 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 34 import org.openstreetmap.josm.gui.layer.RawGpsDataLayer; 35 import org.openstreetmap.josm.io.OsmServerReader; 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; 36 35 37 36 /** … … 43 42 * @author imi 44 43 */ 45 public class OpenOsmServerAction extends JosmAction {44 public class OpenOsmServerAction extends AbstractAction { 46 45 47 JTextField[] latlon = new JTextField[]{46 private JTextField[] latlon = new JTextField[]{ 48 47 new JTextField(9), 49 48 new JTextField(9), 50 49 new JTextField(9), 51 50 new JTextField(9)}; 52 JCheckBox rawGps = new JCheckBox("Open as raw gps data", false);51 private JCheckBox rawGps = new JCheckBox("Open as raw gps data", false); 53 52 54 53 public OpenOsmServerAction() { 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)); 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."); 57 57 } 58 58 … … 82 82 for (JTextField f : latlon) 83 83 f.setCaretPosition(0); 84 rawGps.setSelected( mv.getActiveLayer() instanceof RawGpsDataLayer);84 rawGps.setSelected(!mv.getActiveLayer().isEditable()); 85 85 } 86 86 … … 144 144 return; 145 145 } 146 Osm ServerReader osmReader = new OsmServerReader(Main.pref.osmDataServer,147 b.latlon[0], b.latlon[1], b.latlon[2], b.latlon[3]);146 OsmReader osmReader = new OsmReader(Main.pref.osmDataServer, 147 rawGps.isSelected(), 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 download 152 if (dataSet.nodes.isEmpty()) 153 JOptionPane.showMessageDialog(Main.main, "No data imported."); 154 149 155 String name = latlon[0].getText()+" "+latlon[1].getText()+" x "+ 150 156 latlon[2].getText()+" "+latlon[3].getText(); 151 157 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 } 158 Layer layer = LayerFactory.create(dataSet, name, rawGps.isSelected()); 164 159 165 160 if (Main.main.getMapFrame() == null) … … 167 162 else 168 163 Main.main.getMapFrame().mapView.addLayer(layer); 169 } catch ( JDOMException x) {164 } catch (ParseException x) { 170 165 x.printStackTrace(); 171 166 JOptionPane.showMessageDialog(Main.main, x.getMessage()); 172 } catch ( IOException x) {167 } catch (ConnectionException x) { 173 168 x.printStackTrace(); 174 169 JOptionPane.showMessageDialog(Main.main, x.getMessage()); … … 183 178 * checkbox. 184 179 */ 185 Bookmark readBookmark() {180 private Bookmark readBookmark() { 186 181 try { 187 182 Bookmark b = new Bookmark(); -
/src/org/openstreetmap/josm/actions/PreferencesAction.java
r30 r20 4 4 import java.awt.event.KeyEvent; 5 5 6 import javax.swing.AbstractAction; 7 8 import org.openstreetmap.josm.gui.ImageProvider; 6 9 import org.openstreetmap.josm.gui.PreferenceDialog; 7 10 … … 11 14 * @author imi 12 15 */ 13 public class PreferencesAction extends JosmAction {16 public class PreferencesAction extends AbstractAction { 14 17 15 18 /** … … 17 20 */ 18 21 public PreferencesAction() { 19 super("Preferences", "preference", "Open a preferences page for global settings.", 20 KeyEvent.VK_P, null); 22 super("Preferences", ImageProvider.get("preference")); 23 putValue(MNEMONIC_KEY, KeyEvent.VK_P); 24 putValue(SHORT_DESCRIPTION, "Open a preferences page for global settings."); 21 25 } 22 26 -
/src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java
r30 r20 4 4 import java.awt.Graphics; 5 5 import java.awt.Point; 6 import java.awt.event.ActionEvent;7 6 import java.awt.event.KeyEvent; 8 7 import java.awt.event.MouseEvent; 9 8 import java.awt.event.MouseListener; 10 9 11 import org.openstreetmap.josm.Main; 12 import org.openstreetmap.josm.command.AddCommand; 10 import javax.swing.JOptionPane; 11 12 import org.openstreetmap.josm.data.osm.DataSet; 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; 16 18 import org.openstreetmap.josm.gui.MapFrame; 17 19 … … 20 22 * starting node and dragging to the ending node. 21 23 * 24 * If the Alt key was pressed when releasing the mouse, this action tries to 25 * add the line segment to a track. The new line segment gets added to all tracks 26 * of the first node that end in the first node. If no tracks are found, the 27 * line segment gets added to all tracks in the second node that start with 28 * the second node. 29 * 22 30 * No line segment can be created if there is already a line segment containing 23 * both nodes .31 * both nodes in the same order. 24 32 * 25 33 * @author imi … … 46 54 */ 47 55 public AddLineSegmentAction(MapFrame mapFrame) { 48 super("Add Line Segment", "addlinesegment", "Add a line segment between two nodes.", KeyEvent.VK_ G, mapFrame);56 super("Add Line Segment", "addlinesegment", "Add a line segment between two nodes.", KeyEvent.VK_L, mapFrame); 49 57 } 50 58 … … 62 70 mv.removeMouseMotionListener(this); 63 71 drawHint(false); 64 }65 66 67 @Override68 public void actionPerformed(ActionEvent e) {69 super.actionPerformed(e);70 makeLineSegment();71 72 } 72 73 … … 107 108 108 109 /** 109 * If left button was released, try to create the line segment. 110 * Create the line segment if first and second are different and there is 111 * not already a line segment. 110 112 */ 111 113 @Override 112 114 public void mouseReleased(MouseEvent e) { 113 if (e.getButton() == MouseEvent.BUTTON1) { 114 makeLineSegment(); 115 first = null; // release line segment drawing 116 } 117 } 115 if (e.getButton() != MouseEvent.BUTTON1) 116 return; 118 117 119 /**120 * Create the line segment if first and second are different and there is121 * not already a line segment.122 */123 private void makeLineSegment() {124 118 if (first == null || second == null) { 125 119 first = null; … … 132 126 Node start = first; 133 127 Node end = second; 134 first = second;128 first = null; 135 129 second = null; 136 130 137 131 if (start != end) { 132 DataSet ds = mv.getActiveDataSet(); 133 138 134 // try to find a line segment 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. 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 } 142 141 143 142 LineSegment ls = new LineSegment(start, end); 144 mv.editLayer().add(new AddCommand(Main.main.ds, ls)); 143 boolean foundTrack = false; 144 145 if (((e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0)) { 146 // find a track for the new line segment 147 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); 145 164 } 146 165 147 166 mv.repaint(); 148 167 } … … 167 186 hintDrawn = !hintDrawn; 168 187 } 188 189 @Override 190 protected boolean isEditMode() { 191 return true; 192 } 169 193 } -
/src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java
r30 r20 4 4 import java.awt.event.MouseEvent; 5 5 6 import org.openstreetmap.josm.Main;7 import org.openstreetmap.josm.command.AddCommand;8 6 import org.openstreetmap.josm.data.osm.Node; 9 7 import org.openstreetmap.josm.gui.MapFrame; … … 50 48 Node node = new Node(); 51 49 node.coor = mv.getPoint(e.getX(), e.getY(), true); 52 mv. editLayer().add(new AddCommand(Main.main.ds, node));50 mv.getActiveDataSet().nodes.add(node); 53 51 mv.repaint(); 54 52 } 55 53 } 54 55 @Override 56 protected boolean isEditMode() { 57 return true; 58 } 56 59 } -
/src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java
r30 r20 2 2 3 3 import java.awt.Rectangle; 4 import java.awt.event.ActionEvent;5 4 import java.awt.event.KeyEvent; 6 5 import java.util.Collection; 7 import java.util.Iterator;8 6 import java.util.LinkedList; 9 7 10 import org.openstreetmap.josm.Main; 11 import org.openstreetmap.josm.command.AddCommand; 8 import org.openstreetmap.josm.data.osm.DataSet; 12 9 import org.openstreetmap.josm.data.osm.LineSegment; 13 10 import org.openstreetmap.josm.data.osm.OsmPrimitive; … … 62 59 } 63 60 64 65 @Override66 public void actionPerformed(ActionEvent e) {67 makeTrack();68 super.actionPerformed(e);69 }70 71 61 /** 72 62 * If Shift is pressed, only add the selected line segments to the selection. … … 86 76 return; // not allowed together 87 77 78 DataSet ds = mv.getActiveDataSet(); 79 88 80 if (!ctrl && !shift) 89 Main.main.ds.clearSelection(); // new selection will replace the old.81 ds.clearSelection(); // new selection will replace the old. 90 82 91 83 Collection<OsmPrimitive> selectionList = selectionManager.getObjectsInRectangle(r,alt); 92 84 for (OsmPrimitive osm : selectionList) 93 osm.setSelected(!ctrl );85 osm.setSelected(!ctrl, ds); 94 86 95 87 mv.repaint(); // from now on, the map has to be repainted. … … 98 90 return; // no new track yet. 99 91 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(); 92 Collection<OsmPrimitive> selection = ds.getSelected(); 108 93 if (selection.isEmpty()) 109 94 return; … … 113 98 for (OsmPrimitive osm : selection) { 114 99 if (osm instanceof Track) 115 lineSegments.addAll(((Track)osm).segments );100 lineSegments.addAll(((Track)osm).segments()); 116 101 else if (osm instanceof LineSegment) 117 102 lineSegments.add((LineSegment)osm); 118 103 } 119 120 // sort the line segments in best possible order. This is done by:121 // 0 if no elements in list, quit122 // 1 taking the first ls as pivot, remove it from list123 // 2 searching for a connection at start or end of pivot124 // 3 if found, attach it, remove it from list, goto 2125 // 4 if not found, save the pivot-string and goto 0126 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 149 104 Track t = new Track(); 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(); 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; 155 114 } 156 115 } -
/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java
r30 r20 1 1 package org.openstreetmap.josm.actions.mapmode; 2 2 3 import java.awt.event.ActionEvent;4 3 import java.awt.event.KeyEvent; 5 4 import java.awt.event.MouseEvent; 6 5 import java.util.ArrayList; 7 import java.util.Collection; 8 import java.util.HashSet; 9 import java.util.Iterator; 6 import java.util.HashMap; 10 7 import java.util.LinkedList; 8 import java.util.Map; 11 9 12 10 import javax.swing.JOptionPane; 13 11 14 import org.openstreetmap.josm.Main;15 import org.openstreetmap.josm.command.CombineAndDeleteCommand;16 import org.openstreetmap.josm.command.DeleteCommand;17 12 import org.openstreetmap.josm.data.osm.DataSet; 13 import org.openstreetmap.josm.data.osm.Key; 18 14 import org.openstreetmap.josm.data.osm.LineSegment; 19 15 import org.openstreetmap.josm.data.osm.Node; 20 16 import org.openstreetmap.josm.data.osm.OsmPrimitive; 21 17 import org.openstreetmap.josm.data.osm.Track; 18 import org.openstreetmap.josm.gui.Main; 22 19 import org.openstreetmap.josm.gui.MapFrame; 23 20 … … 35 32 * tries to combine the referencing objects as follows: 36 33 * 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. 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. 40 44 * 41 45 * Combining is only possible, if both objects that should be combined have no … … 51 55 * 52 56 * If the user enters the mapmode and any object is selected, all selected 53 * objects that can be deleted will. Combining applies to the selected objects.57 * objects get deleted. Combining applies to the selected objects. 54 58 * 55 59 * @author imi … … 62 66 */ 63 67 public DeleteAction(MapFrame mapFrame) { 64 super("Delete", "delete", "Delete nodes, streets or areas.", KeyEvent.VK_D , mapFrame);68 super("Delete", "delete", "Delete nodes, streets or areas.", KeyEvent.VK_DELETE, mapFrame); 65 69 } 66 70 … … 77 81 } 78 82 79 80 @Override81 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 changes88 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 105 83 /** 106 84 * If user clicked with the left button, delete the nearest object. … … 116 94 return; 117 95 96 DataSet ds = mv.getActiveDataSet(); 97 118 98 if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0) 119 deleteWithReferences(sel );99 deleteWithReferences(sel, ds); 120 100 else 121 delete(sel, true);101 delete(sel, ds); 122 102 123 103 mv.repaint(); … … 146 126 * TODO If you delete x, then a,B,C and x gets deleted. A now consist of b only. 147 127 * If you delete a or b, then A, a, b and z gets deleted. 148 * 128 * 149 129 * @param osm The object to delete. 150 130 */ 151 private void deleteWithReferences(OsmPrimitive osm ) {152 // collect all tracks, areas and line segments that should be deleted131 private void deleteWithReferences(OsmPrimitive osm, DataSet ds) { 132 // collect all tracks, areas and pending line segments that should be deleted 153 133 ArrayList<Track> tracksToDelete = new ArrayList<Track>(); 154 134 ArrayList<LineSegment> lineSegmentsToDelete = new ArrayList<LineSegment>(); … … 156 136 if (osm instanceof Node) { 157 137 // delete any track and line segment the node is in. 158 for (Track t : Main.main.ds.tracks)159 for (LineSegment ls : t.segments )160 if (ls. start == osm || ls.end== osm)138 for (Track t : ds.tracks()) 139 for (LineSegment ls : t.segments()) 140 if (ls.getStart() == osm || ls.getEnd() == osm) 161 141 tracksToDelete.add(t); 162 for (LineSegment ls : Main.main.ds.lineSegments)163 if (ls. start == osm || ls.end== osm)142 for (LineSegment ls : ds.pendingLineSegments()) 143 if (ls.getStart() == osm || ls.getEnd() == osm) 164 144 lineSegmentsToDelete.add(ls); 165 145 … … 167 147 LineSegment lineSegment = (LineSegment)osm; 168 148 lineSegmentsToDelete.add(lineSegment); 169 for (Track t : Main.main.ds.tracks)170 for (LineSegment ls : t.segments )149 for (Track t : ds.tracks()) 150 for (LineSegment ls : t.segments()) 171 151 if (lineSegment == ls) 172 152 tracksToDelete.add(t); … … 177 157 ArrayList<Node> checkUnreferencing = new ArrayList<Node>(); 178 158 for (Track t : tracksToDelete) { 179 for (LineSegment ls : t.segments ) {180 checkUnreferencing.add(ls. start);181 checkUnreferencing.add(ls. end);159 for (LineSegment ls : t.segments()) { 160 checkUnreferencing.add(ls.getStart()); 161 checkUnreferencing.add(ls.getEnd()); 182 162 } 183 163 } 184 164 for (LineSegment ls : lineSegmentsToDelete) { 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); 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 192 175 // removing all unreferenced nodes 193 for (Node n : checkUnreferencing) 194 if (!isReferenced(n)) 195 deleteData.add(n); 176 for (Node n : checkUnreferencing) { 177 if (!isReferenced(n, ds)) 178 ds.nodes.remove(n); 179 } 196 180 // now, all references are killed. Delete the node (if it was a node) 197 181 if (osm instanceof Node) 198 deleteData.add(osm); 199 200 mv.editLayer().add(new DeleteCommand(Main.main.ds, deleteData)); 182 ds.nodes.remove(osm); 201 183 } 202 184 … … 207 189 * 208 190 * @param osm The object to delete. 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; 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 } 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) { 228 for (LineSegment ls : Main.main.ds.lineSegments) 229 if (ls.start == n || ls.end == n) 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) 230 234 return true; 231 235 // TODO areas … … 239 243 * 240 244 * @param n The node that is going to be deleted. 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; 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."; 320 321 // 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) 274 365 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 } 284 285 // Ok, we can combine. Do it. 286 mv.editLayer().add(new CombineAndDeleteCommand(ds, first, second)); 366 else if (second != null && first != null) 367 first.putAll(second); 368 return first; 369 } 370 371 @Override 372 protected boolean isEditMode() { 287 373 return true; 288 374 } -
/src/org/openstreetmap/josm/actions/mapmode/MapMode.java
r30 r20 6 6 import java.awt.event.MouseMotionListener; 7 7 8 import org.openstreetmap.josm.actions.JosmAction; 8 import javax.swing.AbstractAction; 9 import javax.swing.JComponent; 10 import javax.swing.KeyStroke; 11 12 import org.openstreetmap.josm.gui.ImageProvider; 9 13 import org.openstreetmap.josm.gui.MapFrame; 10 14 import org.openstreetmap.josm.gui.MapView; 15 import org.openstreetmap.josm.gui.MapView.LayerChangeListener; 16 import org.openstreetmap.josm.gui.layer.Layer; 11 17 12 18 /** … … 18 24 * control. 19 25 */ 20 abstract public class MapMode extends JosmAction implements MouseListener, MouseMotionListener {26 abstract public class MapMode extends AbstractAction implements MouseListener, MouseMotionListener { 21 27 22 28 /** … … 36 42 */ 37 43 public MapMode(String name, String iconName, String tooltip, int mnemonic, MapFrame mapFrame) { 38 super(name, "mapmode/"+iconName, tooltip, mnemonic, null); 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); 39 50 this.mapFrame = mapFrame; 40 51 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 }); 41 59 } 60 61 /** 62 * Subclasses should return whether they want to edit the map data or 63 * whether they are read-only. 64 */ 65 abstract protected boolean isEditMode(); 42 66 43 67 /** … … 63 87 mapFrame.selectMapMode(this); 64 88 } 65 89 66 90 /** 67 91 * Does nothing. Only to subclass. -
/src/org/openstreetmap/josm/actions/mapmode/MoveAction.java
r30 r20 6 6 import java.awt.event.MouseEvent; 7 7 import java.util.Collection; 8 import java.util.HashSet; 8 9 9 import org.openstreetmap.josm.Main; 10 import org.openstreetmap.josm.command.MoveCommand; 11 import org.openstreetmap.josm.data.GeoPoint; 10 import org.openstreetmap.josm.data.osm.DataSet; 11 import org.openstreetmap.josm.data.osm.Node; 12 12 import org.openstreetmap.josm.data.osm.OsmPrimitive; 13 13 import org.openstreetmap.josm.gui.MapFrame; … … 75 75 } 76 76 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; 77 int dx = e.getX() - mousePos.x; 78 int dy = e.getY() - mousePos.y; 81 79 if (dx == 0 && dy == 0) 82 80 return; 83 81 84 Collection<OsmPrimitive> selection = Main.main.ds.getSelected(); 85 mv.editLayer().add(new MoveCommand(selection, dx, dy)); 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 } 94 mv.repaint(); 86 95 87 mv.repaint();88 96 mousePos = e.getPoint(); 89 97 } … … 103 111 return; 104 112 105 if (Main.main.ds.getSelected().size() == 0) { 113 DataSet ds = mv.getActiveDataSet(); 114 115 if (ds.getSelected().size() == 0) { 106 116 OsmPrimitive osm = mv.getNearest(e.getPoint(), (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0); 107 117 if (osm != null) 108 osm.setSelected(true );118 osm.setSelected(true, ds); 109 119 singleOsmPrimitive = osm; 110 120 mv.repaint(); … … 124 134 mv.setCursor(oldCursor); 125 135 if (singleOsmPrimitive != null) { 126 singleOsmPrimitive.setSelected(false );136 singleOsmPrimitive.setSelected(false, mv.getActiveDataSet()); 127 137 mv.repaint(); 128 138 } 129 139 } 140 141 @Override 142 protected boolean isEditMode() { 143 return true; 144 } 130 145 } -
/src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java
r30 r20 5 5 import java.util.Collection; 6 6 7 import org.openstreetmap.josm. Main;7 import org.openstreetmap.josm.data.osm.DataSet; 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 89 91 if (!ctrl && !shift) 90 Main.main.ds.clearSelection(); // new selection will replace the old.92 ds.clearSelection(); // new selection will replace the old. 91 93 92 94 Collection<OsmPrimitive> selectionList = selectionManager.getObjectsInRectangle(r,alt); 93 95 for (OsmPrimitive osm : selectionList) 94 osm.setSelected(!ctrl );96 osm.setSelected(!ctrl, ds); 95 97 mv.repaint(); 96 98 } 99 100 @Override 101 protected boolean isEditMode() { 102 return false; 103 } 97 104 } -
/src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java
r30 r20 68 68 selectionManager.unregister(mv); 69 69 } 70 71 @Override 72 protected boolean isEditMode() { 73 return false; 74 } 70 75 } -
/src/org/openstreetmap/josm/data/Bounds.java
r30 r20 45 45 this.max = max; 46 46 } 47 48 /**49 * @return The bounding rectangle that covers <code>this</code> and50 * 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> and64 * 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 }75 47 } -
/src/org/openstreetmap/josm/data/Preferences.java
r30 r20 134 134 mergeNodes = root.getChild("mergeNodes") != null; 135 135 drawRawGpsLines = root.getChild("drawRawGpsLines") != null; 136 forceRawGpsLines = root.getChild("forceRawGpsLines") != null;137 136 } catch (Exception e) { 138 137 if (e instanceof PreferencesException) … … 157 156 if (drawRawGpsLines) 158 157 children.add(new Element("drawRawGpsLines")); 159 if (forceRawGpsLines)160 children.add(new Element("forceRawGpsLines"));161 158 Element osmServer = new Element("osm-server"); 162 159 osmServer.getChildren().add(new Element("url").setText(osmDataServer)); … … 180 177 } 181 178 179 182 180 // projection change listener stuff 183 181 … … 186 184 */ 187 185 private Collection<PropertyChangeListener> listener = new LinkedList<PropertyChangeListener>(); 188 189 186 /** 190 187 * Add a listener of projection changes to the list of listeners. -
/src/org/openstreetmap/josm/data/SelectionTracker.java
r30 r20 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 SelectionEventState state = SelectionEventState.WAITING;66 transient private SelectionEventState state = SelectionEventState.WAITING; 67 67 68 68 /** 69 69 * A list of listeners to selection changed events. 70 70 */ 71 transient Collection<SelectionChangedListener> listeners = new LinkedList<SelectionChangedListener>();71 transient private Collection<SelectionChangedListener> listeners = new LinkedList<SelectionChangedListener>(); 72 72 73 73 -
/src/org/openstreetmap/josm/data/osm/DataSet.java
r30 r20 2 2 3 3 import java.util.Collection; 4 import java.util.Collections; 4 5 import java.util.HashMap; 5 6 import java.util.HashSet; 7 import java.util.Iterator; 6 8 import java.util.LinkedList; 7 9 import java.util.Map; 10 import java.util.Set; 8 11 9 12 import org.openstreetmap.josm.data.Bounds; … … 11 14 12 15 /** 13 * DataSet is the data behind the application. It can consist of only a few14 * points up to the whole osm database. DataSet's can be merged together, 15 * s aved, (up/down/disk)loaded etc.16 * DataSet is the data behind one window in the application. It can consist of only a few 17 * points up to the whole osm database. DataSet's can be merged together, split up into 18 * several different ones, saved, (up/down/disk)loaded etc. 16 19 * 17 * Note, that DataSet is not an osm-primitive and so has no key association18 * but a fewmembers to store some information.20 * Note, that DataSet is not an osm-primitive, so it has no key association but a few 21 * members to store some information. 19 22 * 20 23 * @author imi 21 24 */ 22 public class DataSet extends SelectionTracker {25 public class DataSet extends SelectionTracker implements Cloneable { 23 26 24 27 /** … … 30 33 31 34 /** 32 * All line segments goes here, even when they are in a track. 33 */ 34 public Collection<LineSegment> lineSegments = new LinkedList<LineSegment>(); 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>(); 35 39 36 40 /** … … 41 45 * track list. 42 46 */ 43 public Collection<Track> tracks = new LinkedList<Track>(); 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 } 44 103 45 104 /** … … 111 170 public void clearSelection() { 112 171 clearSelection(nodes); 113 clearSelection(lineSegments);114 172 clearSelection(tracks); 173 for (Track t : tracks) 174 clearSelection(t.segments()); 115 175 } 116 176 … … 122 182 public Collection<OsmPrimitive> getSelected() { 123 183 Collection<OsmPrimitive> sel = getSelected(nodes); 124 sel.addAll(getSelected( lineSegments));184 sel.addAll(getSelected(pendingLineSegments)); 125 185 sel.addAll(getSelected(tracks)); 186 for (Track t : tracks) 187 sel.addAll(getSelected(t.segments())); 126 188 return sel; 127 189 } … … 131 193 * The objects imported are not cloned, so from now on, these data belong 132 194 * to both datasets. So use mergeFrom only if you are about to abandon the 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 * 195 * other dataset or this dataset. 196 * 142 197 * @param ds The DataSet to merge into this one. 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; 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 } 200 216 } 201 217 } 202 if (!found) 203 trackToAdd.add(otherTrack); 204 } 205 tracks.addAll(trackToAdd); 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()); 206 245 } 207 246 … … 214 253 return; 215 254 for (OsmPrimitive osm : list) { 216 osm.setSelected(false );255 osm.setSelected(false, this); 217 256 if (osm.keys != null) 218 257 clearSelection(osm.keys.keySet()); … … 236 275 return sel; 237 276 } 277 278 279 @Override 280 public DataSet clone() { 281 try {return (DataSet)super.clone();} catch (CloneNotSupportedException e) {} 282 return null; 283 } 238 284 } -
/src/org/openstreetmap/josm/data/osm/Key.java
r30 r20 1 1 package org.openstreetmap.josm.data.osm; 2 2 3 import java.util.Collection; 3 4 import java.util.HashMap; 5 import java.util.LinkedList; 4 6 import java.util.Map; 5 7 … … 22 24 * All keys are stored here. 23 25 */ 24 p ublic static finalMap<String, Key> allKeys = new HashMap<String, Key>();26 private static Map<String, Key> allKeys = new HashMap<String, Key>(); 25 27 26 28 /** … … 47 49 } 48 50 51 /** 52 * Return an empty list, since keys cannot have nodes. 53 */ 54 @Override 55 public Collection<Node> getAllNodes() { 56 return new LinkedList<Node>(); 57 } 58 49 59 @Override 50 60 public void visit(Visitor visitor) { 51 61 visitor.visit(this); 52 62 } 53 54 @Override55 public String toString() {56 return name;57 }58 63 } -
/src/org/openstreetmap/josm/data/osm/LineSegment.java
r30 r20 1 1 package org.openstreetmap.josm.data.osm; 2 3 import java.util.Collection; 4 import java.util.Collections; 5 import java.util.LinkedList; 2 6 3 7 import org.openstreetmap.josm.data.osm.visitor.Visitor; … … 14 18 * The starting node of the line segment 15 19 */ 16 publicNode start;20 Node start; 17 21 18 22 /** 19 23 * The ending node of the line segment 20 24 */ 21 public Node end; 25 Node end; 26 27 /** 28 * The tracks, this line segment is part of. 29 */ 30 transient Collection<Track> parent = new LinkedList<Track>(); 22 31 23 32 /** … … 29 38 this.start = start; 30 39 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 @Override 80 public Collection<Node> getAllNodes() { 81 LinkedList<Node> nodes = new LinkedList<Node>(); 82 nodes.add(getStart()); 83 nodes.add(getEnd()); 84 return nodes; 31 85 } 32 86 -
/src/org/openstreetmap/josm/data/osm/Node.java
r30 r20 1 1 package org.openstreetmap.josm.data.osm; 2 3 import java.util.Collection; 4 import java.util.Collections; 5 import java.util.LinkedList; 2 6 3 7 import org.openstreetmap.josm.data.GeoPoint; … … 17 21 public GeoPoint coor; 18 22 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 @Override 56 public Collection<Node> getAllNodes() { 57 LinkedList<Node> nodes = new LinkedList<Node>(); 58 nodes.add(this); 59 return nodes; 60 } 61 19 62 @Override 20 63 public void visit(Visitor visitor) { -
/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
r30 r20 1 1 package org.openstreetmap.josm.data.osm; 2 2 3 import java.util.Collection; 3 4 import java.util.Map; 4 5 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 * 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. 23 * If set to true, this object has been modified in the current session. 26 24 */ 27 public long id = 0;28 25 transient public boolean modified = false; 26 29 27 /** 30 28 * If set to true, this object is currently selected. 31 29 */ 32 30 transient private boolean selected = false; 31 32 /** 33 * Return a list of all nodes, this osmPrimitive consists of. Does return 34 * an empty list, if it is an primitive that cannot have nodes (e.g. Key) 35 * TODO replace with visitor 36 */ 37 abstract public Collection<Node> getAllNodes(); 33 38 34 39 /** … … 66 71 * changed later, if the value actualy changed. 67 72 * @param selected Whether the primitive should be selected or not. 73 * @param ds The dataSet, this primitive is in. 68 74 */ 69 public void setSelected(boolean selected ) {75 public void setSelected(boolean selected, DataSet ds) { 70 76 if (selected != this.selected) 71 Main.main.ds.fireSelectionChanged();77 ds.fireSelectionChanged(); 72 78 this.selected = selected; 73 79 } … … 79 85 return selected; 80 86 } 81 82 83 /**84 * Equal, if the id is equal. If both ids are 0, use the super classes equal85 * instead.86 */87 @Override88 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 @Override101 public int hashCode() {102 return id == 0 ? super.hashCode() : (int)id;103 }104 87 } -
/src/org/openstreetmap/josm/data/osm/Track.java
r30 r20 2 2 3 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.Collections; 4 6 import java.util.List; 5 7 … … 16 18 * All track segments in this track 17 19 */ 18 p ublicfinal List<LineSegment> segments = new ArrayList<LineSegment>();20 private final List<LineSegment> segments = new ArrayList<LineSegment>(); 19 21 20 22 … … 24 26 public void add(LineSegment ls) { 25 27 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 @Override 73 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(); 26 89 } 27 90 … … 38 101 if (segments.isEmpty()) 39 102 return null; 40 return segments.get(segments.size()-1). end;103 return segments.get(segments.size()-1).getEnd(); 41 104 } 42 105 … … 63 126 if (segments.isEmpty()) 64 127 return null; 65 return segments.get(0). start;128 return segments.get(0).getStart(); 66 129 } 67 130 -
/src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java
r30 r20 19 19 * @author imi 20 20 */ 21 public class SelectionComponentVisitor implements Visitor {21 public class SelectionComponentVisitor extends Visitor { 22 22 23 23 /** … … 34 34 * A key icon and the name of the key. 35 35 */ 36 @Override 36 37 public void visit(Key k) { 37 38 name = k.name; … … 44 45 * "(x1,y1) -> (x2,y2)" is displayed with the nodes coordinates. 45 46 */ 47 @Override 46 48 public void visit(LineSegment ls) { 47 49 String name = getName(ls.keys); 48 50 if (name == null) 49 name = "("+ls. start.coor.lat+","+ls.start.coor.lon+") -> ("+ls.end.coor.lat+","+ls.end.coor.lon+")";51 name = "("+ls.getStart().coor.lat+","+ls.getStart().coor.lon+") -> ("+ls.getEnd().coor.lat+","+ls.getEnd().coor.lon+")"; 50 52 51 53 this.name = name; … … 57 59 * is displayed. 58 60 */ 61 @Override 59 62 public void visit(Node n) { 60 63 String name = getName(n.keys); … … 70 73 * is displayed with x beeing the number of nodes in the track. 71 74 */ 75 @Override 72 76 public void visit(Track t) { 73 77 String name = getName(t.keys); 74 78 if (name == null) { 75 79 Set<Node> nodes = new HashSet<Node>(); 76 for (LineSegment ls : t.segments ) {77 nodes.add(ls. start);78 nodes.add(ls. end);80 for (LineSegment ls : t.segments()) { 81 nodes.add(ls.getStart()); 82 nodes.add(ls.getEnd()); 79 83 } 80 84 name = "("+nodes.size()+" nodes)"; -
/src/org/openstreetmap/josm/data/osm/visitor/Visitor.java
r30 r20 12 12 * @author imi 13 13 */ 14 public interfaceVisitor {15 void visit(Node n);16 void visit(LineSegment ls);17 void visit(Track t);18 void visit(Key k);14 abstract public class Visitor { 15 public void visit(Node n) {} 16 public void visit(LineSegment ls) {} 17 public void visit(Track t) {} 18 public void visit(Key k) {} 19 19 } -
/src/org/openstreetmap/josm/data/projection/Projection.java
r30 r20 8 8 import javax.swing.event.ChangeListener; 9 9 10 import org.openstreetmap.josm.data.Bounds;11 10 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 bounding rectangle (regarding lat/lon).73 * Initialize itself with the given dataSet. 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 dataSet 85 * The dataset, which will be displayed on screen. Later, all 86 * projections should be relative to the given dataset. Any 87 * reverse projections (xy2latlon) can be assumed to be in near 88 * distance to nodes of this dataset (that means, it is ok, if 89 * there is a conversion error, if the requested x/y to xy2latlon 90 * is far away from any coordinate in the dataset) 83 91 */ 84 public void init( Bounds b) {}92 public void init(DataSet dataSet) {} 85 93 86 94 /** -
/src/org/openstreetmap/josm/data/projection/UTM.java
r30 r20 15 15 import javax.swing.SpinnerNumberModel; 16 16 17 import org.openstreetmap.josm.Main;18 17 import org.openstreetmap.josm.data.Bounds; 19 18 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; 21 22 22 23 /** … … 79 80 }; 80 81 81 private enum Hemisphere {north, south} 82 private enum Hemisphere {north, south}; 82 83 83 84 /** … … 101 102 * Spinner with all possible zones for the configuration panel 102 103 */ 103 JSpinner zoneSpinner;104 private JSpinner zoneSpinner; 104 105 /** 105 106 * Hemisphere combo for the configuration panel 106 107 */ 107 JComboBox hemisphereCombo;108 private JComboBox hemisphereCombo; 108 109 109 110 … … 186 187 * @author imi 187 188 */ 188 private staticclass ZoneData {189 private class ZoneData { 189 190 int zone = 0; 190 191 Hemisphere hemisphere = Hemisphere.north; … … 192 193 /** 193 194 * Try to autodetect the zone and hemisphere from the dataset. 195 * @param dataSet The dataset to extrakt zone information from. 194 196 * @return The zone data extrakted from the dataset. 195 197 */ 196 ZoneData autoDetect(Bounds b) {198 private ZoneData autoDetect(DataSet dataSet) { 197 199 ZoneData zd = new ZoneData(); 200 201 Bounds b = dataSet.getBoundsLatLon(); 198 202 if (b == null) 199 203 return zd; … … 230 234 */ 231 235 @Override 232 public void init( Bounds b) {236 public void init(DataSet dataSet) { 233 237 if (zone == 0) { 234 ZoneData zd = autoDetect( b);238 ZoneData zd = autoDetect(dataSet); 235 239 zone = zd.zone; 236 240 hemisphere = zd.hemisphere; … … 270 274 public void actionPerformed(ActionEvent e) { 271 275 if (Main.main.getMapFrame() != null) { 272 ZoneData zd = autoDetect(Main.main.ds.getBoundsLatLon()); 276 DataSet ds = Main.main.getMapFrame().mapView.getActiveDataSet(); 277 ZoneData zd = autoDetect(ds); 273 278 if (zd.zone == 0) 274 279 JOptionPane.showMessageDialog(Main.main, "Autodetection failed. Maybe the data set contain too few information."); -
/src/org/openstreetmap/josm/gui/BookmarkList.java
r30 r20 16 16 import javax.swing.JOptionPane; 17 17 18 import org.openstreetmap.josm.Main;19 18 import org.openstreetmap.josm.data.Preferences; 20 19 -
/src/org/openstreetmap/josm/gui/IconToggleButton.java
r30 r20 25 25 // Tooltip 26 26 String toolTipText = ""; 27 Object o = action.getValue(Action. SHORT_DESCRIPTION);27 Object o = action.getValue(Action.LONG_DESCRIPTION); 28 28 if (o != null) 29 toolTipText = o.toString(); 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 } 30 39 setToolTipText(toolTipText); 31 40 -
/src/org/openstreetmap/josm/gui/ImageProvider.java
r30 r20 13 13 import javax.swing.ImageIcon; 14 14 15 import org.openstreetmap.josm.Main;16 17 15 /** 18 16 * Helperclass to support the application with images. … … 25 23 * @author imi 26 24 */ 27 public enum OverlayPosition {NORTHWEST, NORTHEAST, SOUTHWEST, SOUTHEAST} 25 public enum OverlayPosition {NORTHWEST, NORTHEAST, SOUTHWEST, SOUTHEAST}; 28 26 29 27 /** -
/src/org/openstreetmap/josm/gui/MapFrame.java
r30 r20 4 4 import java.awt.Component; 5 5 import java.awt.Container; 6 import java.awt.event.WindowAdapter; 7 import java.awt.event.WindowEvent; 6 8 import java.beans.PropertyChangeEvent; 7 9 import java.beans.PropertyChangeListener; 8 10 9 11 import javax.swing.AbstractButton; 10 import javax.swing.BoxLayout;11 12 import javax.swing.ButtonGroup; 12 13 import javax.swing.JPanel; … … 18 19 import org.openstreetmap.josm.actions.mapmode.AddNodeAction; 19 20 import org.openstreetmap.josm.actions.mapmode.AddTrackAction; 21 import org.openstreetmap.josm.actions.mapmode.CombineAction; 20 22 import org.openstreetmap.josm.actions.mapmode.DeleteAction; 21 23 import org.openstreetmap.josm.actions.mapmode.MapMode; … … 52 54 */ 53 55 public MapStatus statusLine; 54 /**55 * The action to open the layer list56 */57 private LayerList layerList;58 /**59 * Action to open the properties panel for the selected objects60 */61 private PropertiesDialog propertiesDialog;62 /**63 * Action to open a list of all selected objects64 */65 private SelectionListDialog selectionListDialog;66 56 67 57 /** … … 86 76 toolBarActions.add(new IconToggleButton(this, new AddLineSegmentAction(this))); 87 77 toolBarActions.add(new IconToggleButton(this, new AddTrackAction(this))); 78 toolBarActions.add(new IconToggleButton(this, new CombineAction(this))); 88 79 toolBarActions.add(new IconToggleButton(this, new DeleteAction(this))); 89 80 … … 108 99 }); 109 100 110 JPanel toggleDialogs = new JPanel(); 111 add(toggleDialogs, BorderLayout.EAST); 101 // layer list 102 toolBarActions.add(new IconToggleButton(this, new LayerList(this))); 103 104 // properties 105 toolBarActions.add(new IconToggleButton(this, new PropertiesDialog(this))); 112 106 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); 120 107 // selection dialog 108 SelectionListDialog selectionList = new SelectionListDialog(this); 109 final IconToggleButton buttonSelection = new IconToggleButton(this, selectionList); 110 selectionList.addWindowListener(new WindowAdapter(){ 111 @Override 112 public void windowClosing(WindowEvent e) { 113 buttonSelection.setSelected(false); 114 } 115 }); 116 toolBarActions.add(buttonSelection); 121 117 122 118 // status line below the map -
/src/org/openstreetmap/josm/gui/MapStatus.java
r30 r20 47 47 * The position of the mouse cursor. 48 48 */ 49 JTextField positionText = new JTextField("-000.00000000000000 -000.00000000000000".length());49 private 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 JTextField nameText = new JTextField(30);53 private JTextField nameText = new JTextField(30); 54 54 55 55 /** … … 147 147 * The last sent mouse movement event. 148 148 */ 149 MouseState mouseState = new MouseState();149 private MouseState mouseState = new MouseState(); 150 150 151 151 /** -
/src/org/openstreetmap/josm/gui/MapView.java
r30 r20 17 17 import javax.swing.event.ChangeListener; 18 18 19 import org.openstreetmap.josm.Main;20 19 import org.openstreetmap.josm.data.Bounds; 21 20 import org.openstreetmap.josm.data.GeoPoint; … … 27 26 import org.openstreetmap.josm.data.projection.Projection; 28 27 import org.openstreetmap.josm.gui.layer.Layer; 29 import org.openstreetmap.josm.gui.layer.OsmDataLayer;30 28 31 29 /** 32 30 * This is a component used in the MapFrame for browsing the map. It use is to 33 31 * 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 /**79 75 * The layer from the layers list that is currently active. 80 76 */ … … 90 86 */ 91 87 public MapView(Layer layer) { 88 if (layer.getDataSet() == null) 89 throw new IllegalArgumentException("Initial layer must have a dataset."); 90 92 91 addComponentListener(new ComponentAdapter(){ 93 92 @Override … … 103 102 addLayer(layer); 104 103 Main.pref.addPropertyChangeListener(this); 104 105 // init screen 106 recalculateCenterScale(); 105 107 } 106 108 … … 110 112 */ 111 113 public void addLayer(Layer layer) { 112 // initialize the projection if it is the first layer113 if (layers.isEmpty())114 Main.pref.getProjection().init(layer.getBoundsLatLon());115 116 // reinitialize layer's data117 layer.init(Main.pref.getProjection());118 119 if (layer instanceof OsmDataLayer) {120 if (editLayer != null) {121 // merge the layer into the existing one122 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 layer132 114 layers.add(0,layer); 115 116 DataSet ds = layer.getDataSet(); 117 118 if (ds != null) { 119 // initialize the projection if it was the first layer 120 if (layers.size() == 1) 121 Main.pref.getProjection().init(ds); 122 123 // initialize the dataset in the new layer 124 for (Node n : ds.nodes) 125 Main.pref.getProjection().latlon2xy(n.coor); 126 } 133 127 134 128 for (LayerChangeListener l : listeners) 135 129 l.layerAdded(layer); 136 130 137 // autoselect the new layer138 131 setActiveLayer(layer); 139 132 } 140 133 141 134 /** 142 135 * Remove the layer from the mapview. If the layer was in the list before, … … 147 140 for (LayerChangeListener l : listeners) 148 141 l.layerRemoved(layer); 149 if (layer == editLayer)150 editLayer = null;151 142 } 152 143 … … 241 232 OsmPrimitive minPrimitive = null; 242 233 234 // calculate the object based on the current active dataset. 235 DataSet ds = getActiveDataSet(); 236 243 237 // nodes 244 for (Node n : Main.main.ds.nodes) {238 for (Node n : ds.nodes) { 245 239 Point sp = getScreenPoint(n.coor); 246 240 double dist = p.distanceSq(sp); … … 254 248 255 249 // pending line segments 256 for (LineSegment ls : Main.main.ds.lineSegments) {257 Point A = getScreenPoint(ls. start.coor);258 Point B = getScreenPoint(ls. end.coor);250 for (LineSegment ls : ds.pendingLineSegments()) { 251 Point A = getScreenPoint(ls.getStart().coor); 252 Point B = getScreenPoint(ls.getEnd().coor); 259 253 double c = A.distanceSq(B); 260 254 double a = p.distanceSq(B); … … 269 263 // tracks & line segments 270 264 minDistanceSq = Double.MAX_VALUE; 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);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); 275 269 double c = A.distanceSq(B); 276 270 double a = p.distanceSq(B); … … 326 320 for (int i = layers.size()-1; i >= 0; --i) { 327 321 Layer l = layers.get(i); 328 if (l. visible)322 if (l.isVisible()) 329 323 l.paint(g, this); 330 324 } … … 338 332 // reset all datasets. 339 333 Projection p = Main.pref.getProjection(); 340 for (Node n : Main.main.ds.nodes) 341 p.latlon2xy(n.coor); 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 } 342 340 recalculateCenterScale(); 343 341 } … … 377 375 378 376 377 /** 378 * Return the dataSet for the current selected layer. If the active layer 379 * 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 379 394 /** 380 395 * Change to the new projection. Recalculate the dataset and zoom, if autoZoom … … 410 425 h = 20; 411 426 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 427 Bounds bounds = getActiveDataSet().getBoundsXY(); 428 423 429 boolean oldAutoScale = autoScale; 424 430 GeoPoint oldCenter = center; … … 473 479 /** 474 480 * 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.476 481 */ 477 482 public void setActiveLayer(Layer layer) { … … 480 485 Layer old = activeLayer; 481 486 activeLayer = layer; 482 if (layer instanceof OsmDataLayer)483 Main.main.ds = ((OsmDataLayer)layer).data;484 487 if (old != layer) { 488 if (old != null && old.getDataSet() != null) 489 old.getDataSet().clearSelection(); 485 490 for (LayerChangeListener l : listeners) 486 491 l.activeLayerChange(old, layer); … … 495 500 return activeLayer; 496 501 } 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 }507 502 } -
/src/org/openstreetmap/josm/gui/PreferenceDialog.java
r30 r20 28 28 import javax.swing.UIManager.LookAndFeelInfo; 29 29 30 import org.openstreetmap.josm.Main;31 30 import org.openstreetmap.josm.data.Preferences; 32 31 import org.openstreetmap.josm.data.Preferences.PreferencesException; … … 91 90 * Indicate, that the application has to be restarted for the settings to take effect. 92 91 */ 93 boolean requiresRestart = false;92 private boolean requiresRestart = false; 94 93 /** 95 94 * ComboBox with all look and feels. 96 95 */ 97 JComboBox lafCombo = new JComboBox(UIManager.getInstalledLookAndFeels());96 private JComboBox lafCombo = new JComboBox(UIManager.getInstalledLookAndFeels()); 98 97 /** 99 98 * Combobox with all projections available 100 99 */ 101 JComboBox projectionCombo = new JComboBox(Preferences.allProjections.clone());100 private JComboBox projectionCombo = new JComboBox(Preferences.allProjections.clone()); 102 101 /** 103 102 * The main tab panel. … … 108 107 * Editfield for the Base url to the REST API from OSM. 109 108 */ 110 JTextField osmDataServer = new JTextField(20);109 private JTextField osmDataServer = new JTextField(20); 111 110 /** 112 111 * Editfield for the username to the OSM account. 113 112 */ 114 JTextField osmDataUsername = new JTextField(20);113 private JTextField osmDataUsername = new JTextField(20); 115 114 /** 116 115 * Passwordfield for the userpassword of the REST API. 117 116 */ 118 JPasswordField osmDataPassword = new JPasswordField(20);117 private JPasswordField osmDataPassword = new JPasswordField(20); 119 118 /** 120 119 * The checkbox stating whether nodes should be merged together. 121 120 */ 122 JCheckBox drawRawGpsLines = new JCheckBox("Draw lines between raw gps points.");121 private JCheckBox drawRawGpsLines = new JCheckBox("Draw lines between raw gps points."); 123 122 /** 124 123 * The checkbox stating whether raw gps lines should be forced. 125 124 */ 126 JCheckBox forceRawGpsLines = new JCheckBox("Force lines if no line segments imported.");125 private JCheckBox forceRawGpsLines = new JCheckBox("Force lines if no line segments imported."); 127 126 /** 128 127 * The checkbox stating whether nodes should be merged together. 129 128 */ 130 JCheckBox mergeNodes = new JCheckBox("Merge nodes with equal latitude/longitude.");129 private JCheckBox mergeNodes = new JCheckBox("Merge nodes with equal latitude/longitude."); 131 130 132 131 /** -
/src/org/openstreetmap/josm/gui/SelectionManager.java
r30 r20 15 15 import java.util.LinkedList; 16 16 17 import org.openstreetmap.josm. Main;17 import org.openstreetmap.josm.data.osm.DataSet; 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 for (Node n : Main.main.ds.nodes) { 274 DataSet ds = mv.getActiveDataSet(); 275 for (Node n : ds.nodes) { 275 276 if (r.contains(mv.getScreenPoint(n.coor))) 276 277 selection.add(n); … … 278 279 279 280 // pending line segments 280 for (LineSegment ls : Main.main.ds.lineSegments)281 for (LineSegment ls : ds.pendingLineSegments()) 281 282 if (rectangleContainLineSegment(r, alt, ls)) 282 283 selection.add(ls); 283 284 284 285 // tracks 285 for (Track t : Main.main.ds.tracks) {286 boolean wholeTrackSelected = !t.segments .isEmpty();287 for (LineSegment ls : t.segments )286 for (Track t : ds.tracks()) { 287 boolean wholeTrackSelected = !t.segments().isEmpty(); 288 for (LineSegment ls : t.segments()) 288 289 if (rectangleContainLineSegment(r, alt, ls)) 289 290 selection.add(ls); … … 310 311 private boolean rectangleContainLineSegment(Rectangle r, boolean alt, LineSegment ls) { 311 312 if (alt) { 312 Point p1 = mv.getScreenPoint(ls. start.coor);313 Point p2 = mv.getScreenPoint(ls. end.coor);313 Point p1 = mv.getScreenPoint(ls.getStart().coor); 314 Point p2 = mv.getScreenPoint(ls.getEnd().coor); 314 315 if (r.intersectsLine(p1.x, p1.y, p2.x, p2.y)) 315 316 return true; 316 317 } else { 317 if (r.contains(mv.getScreenPoint(ls. start.coor))318 && r.contains(mv.getScreenPoint(ls. end.coor)))318 if (r.contains(mv.getScreenPoint(ls.getStart().coor)) 319 && r.contains(mv.getScreenPoint(ls.getEnd().coor))) 319 320 return true; 320 321 } -
/src/org/openstreetmap/josm/gui/dialogs/LayerList.java
r30 r20 23 23 import javax.swing.event.ListSelectionListener; 24 24 25 import org.openstreetmap.josm.Main;26 25 import org.openstreetmap.josm.data.osm.DataSet; 27 26 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 DefaultListModel model = new DefaultListModel();44 private DefaultListModel model = new DefaultListModel(); 45 45 /** 46 46 * The list component holding all layers. 47 47 */ 48 JList layers = new JList(model);48 private JList layers = new JList(model); 49 49 /** 50 50 * The invisible icon blended over invisible layers. 51 51 */ 52 static final Icon invisible = ImageProvider.get("layer", "invisible");52 private 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("Layers", "List of all layers", "layerlist", KeyEvent.VK_L, "Open a list of all loaded layers."); 77 setPreferredSize(new Dimension(320,100)); 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)); 78 79 add(new JScrollPane(layers), BorderLayout.CENTER); 79 80 layers.setBackground(UIManager.getColor("Button.background")); … … 83 84 Layer layer = (Layer)value; 84 85 JLabel label = (JLabel)super.getListCellRendererComponent(list, 85 layer. name, index, isSelected, cellHasFocus);86 layer.getName(), index, isSelected, cellHasFocus); 86 87 Icon icon = layer.getIcon(); 87 if (!layer. visible)88 if (!layer.isVisible()) 88 89 icon = ImageProvider.overlay(icon, invisible, ImageProvider.OverlayPosition.SOUTHEAST); 89 90 label.setIcon(icon); 90 label.setToolTipText(layer.getToolTipText()); 91 92 DataSet ds = layer.getDataSet(); 93 if (ds != null) { 94 label.setToolTipText(ds.nodes.size()+" nodes, "+ 95 ds.tracks().size()+" tracks"); 96 } 91 97 return label; 92 98 } … … 94 100 95 101 final MapView mapView = mapFrame.mapView; 96 102 97 103 Collection<Layer> data = mapView.getAllLayers(); 98 104 for (Layer l : data) … … 109 115 }); 110 116 mapView.addLayerChangeListener(this); 111 117 112 118 // Buttons 113 119 JPanel buttonPanel = new JPanel(new GridLayout(1, 5)); … … 142 148 public void actionPerformed(ActionEvent e) { 143 149 Layer l = (Layer)layers.getSelectedValue(); 144 l. visible = !l.visible;150 l.setVisible(!l.isVisible()); 145 151 mapView.repaint(); 146 152 layers.repaint(); … … 154 160 if (model.size() == 1) { 155 161 Main.main.setMapFrame(null, null); 156 Main.main.ds = new DataSet();157 162 } else { 158 163 int sel = layers.getSelectedIndex(); … … 168 173 mergeButton.setToolTipText("Merge the selected layer into the layer directly below."); 169 174 mergeButton.addActionListener(new ActionListener(){ 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 }); 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 }); 178 185 buttonPanel.add(mergeButton); 179 186 … … 186 193 * Updates the state of the Buttons. 187 194 */ 188 void updateButtonEnabled() {195 private void updateButtonEnabled() { 189 196 int sel = layers.getSelectedIndex(); 190 197 Layer l = (Layer)layers.getSelectedValue(); 191 198 boolean enable = model.getSize() > 1; 192 199 enable = enable && sel < model.getSize()-1; 193 enable = enable && l.isMergable((Layer)model.get(sel+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(); 194 203 mergeButton.setEnabled(enable); 195 204 upButton.setEnabled(sel > 0); -
/src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java
r30 r20 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;10 3 import java.awt.event.KeyEvent; 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 4 23 import javax.swing.JButton; 24 import javax.swing.JComboBox; 25 import javax.swing.JDialog; 5 import javax.swing.BorderFactory; 6 import javax.swing.Box; 26 7 import javax.swing.JLabel; 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; 8 import javax.swing.border.Border; 35 9 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; 10 import org.openstreetmap.josm.gui.Main; 42 11 import org.openstreetmap.josm.gui.MapFrame; 43 import org.openstreetmap.josm.gui.MapView;44 12 45 13 /** 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. 14 * Open a Property dialog for the current visible map. When saving to own josm- 15 * data format, the properties are saved along. 59 16 * 60 17 * @author imi 61 18 */ 62 public class PropertiesDialog extends ToggleDialog implements SelectionChangedListener{19 public class PropertiesDialog extends ToggleDialog { 63 20 64 /**65 * Watches for double clicks and start editing or new property, depending on the66 * location, the click was.67 * @author imi68 */69 public class DblClickWatch extends MouseAdapter {70 @Override71 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 row85 * @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 key127 mv.editLayer().add(new ChangeKeyValueCommand(sel, Key.get(key), value));128 129 if (value == null)130 selectionChanged(sel); // update whole table131 else132 PropertiesDialog.this.repaint(); // repaint is enough133 }134 135 /**136 * Open the add selection dialog and add a new key/value to the table (and to the137 * 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 table174 }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 table185 }186 187 /**188 * The property data.189 */190 private final DefaultTableModel data = new DefaultTableModel(){191 @Override192 public boolean isCellEditable(int row, int column) {193 return false;194 }195 @Override196 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 209 21 /** 210 22 * Create a new PropertiesDialog 211 23 */ 212 24 public PropertiesDialog(MapFrame mapFrame) { 213 super( "Properties", "Properties Dialog", "properties", KeyEvent.VK_P, "Property for selected objects.");214 mv = mapFrame.mapView;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); 215 27 216 setPreferredSize(new Dimension(320,150)); 28 final Border panelBorder = BorderFactory.createEmptyBorder(5,0,0,0); 29 Box panel = Box.createVerticalBox(); 217 30 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); 31 JLabel todo = new JLabel("Nothing implemented yet."); 32 todo.setBorder(panelBorder); 33 panel.add(todo); 244 34 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 } 35 panel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); 36 setContentPane(panel); 37 pack(); 38 setResizable(false); 321 39 } 322 40 } -
/src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
r30 r20 3 3 import java.awt.BorderLayout; 4 4 import java.awt.Component; 5 import java.awt.Dimension;6 5 import java.awt.event.ActionEvent; 7 6 import java.awt.event.ActionListener; … … 17 16 import javax.swing.ListSelectionModel; 18 17 19 import org.openstreetmap.josm.Main;20 18 import org.openstreetmap.josm.data.SelectionChangedListener; 19 import org.openstreetmap.josm.data.osm.DataSet; 21 20 import org.openstreetmap.josm.data.osm.OsmPrimitive; 22 21 import org.openstreetmap.josm.data.osm.visitor.SelectionComponentVisitor; 23 22 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; 25 28 26 29 /** … … 31 34 * @author imi 32 35 */ 33 public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener {36 public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener, LayerChangeListener { 34 37 35 38 /** … … 41 44 */ 42 45 private JList displaylist = new JList(list); 46 /** 47 * The dataset, all selections are part of. 48 */ 49 private final MapView mapView; 43 50 44 51 /** … … 47 54 */ 48 55 public SelectionListDialog(MapFrame mapFrame) { 49 super("Current Selection", "Selection List", "selectionlist", KeyEvent.VK_E, "Open a selection list window."); 50 setPreferredSize(new Dimension(320,150)); 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); 51 60 displaylist.setCellRenderer(new DefaultListCellRenderer(){ 52 61 private SelectionComponentVisitor visitor = new SelectionComponentVisitor(); … … 64 73 displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 65 74 66 add(new JScrollPane(displaylist), BorderLayout.CENTER);75 getContentPane().add(new JScrollPane(displaylist), BorderLayout.CENTER); 67 76 68 77 JButton button = new JButton("Select", ImageProvider.get("mapmode", "selection")); … … 73 82 } 74 83 }); 75 add(button, BorderLayout.SOUTH);84 getContentPane().add(button, BorderLayout.SOUTH); 76 85 77 selectionChanged( Main.main.ds.getSelected());86 selectionChanged(mapView.getActiveDataSet().getSelected()); 78 87 } 79 88 … … 81 90 public void setVisible(boolean b) { 82 91 if (b) { 83 Main.main.ds.addSelectionChangedListener(this); 84 selectionChanged(Main.main.ds.getSelected()); 92 mapView.addLayerChangeListener(this); 93 mapView.getActiveDataSet().addSelectionChangedListener(this); 94 selectionChanged(mapView.getActiveDataSet().getSelected()); 85 95 } else { 86 Main.main.ds.removeSelectionChangedListener(this); 96 mapView.removeLayerChangeListener(this); 97 mapView.getActiveDataSet().removeSelectionChangedListener(this); 87 98 } 88 99 super.setVisible(b); … … 107 118 */ 108 119 public void updateMap() { 109 Main.main.ds.clearSelection(); 120 DataSet ds = mapView.getActiveDataSet(); 121 ds.clearSelection(); 110 122 for (int i = 0; i < list.getSize(); ++i) 111 123 if (displaylist.isSelectedIndex(i)) 112 ((OsmPrimitive)list.get(i)).setSelected(true );124 ((OsmPrimitive)list.get(i)).setSelected(true, ds); 113 125 Main.main.getMapFrame().repaint(); 114 126 } 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 LayerChangeListener 139 */ 140 public void layerAdded(Layer newLayer) {} 141 /** 142 * Does nothing. Only to satisfy LayerChangeListener 143 */ 144 public void layerRemoved(Layer oldLayer) {} 115 145 } -
/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
r30 r20 1 1 package org.openstreetmap.josm.gui.dialogs; 2 2 3 import java.awt.BorderLayout;4 3 import java.awt.event.ActionEvent; 4 import java.beans.PropertyChangeEvent; 5 import java.beans.PropertyChangeListener; 5 6 import java.util.HashMap; 6 7 import java.util.Map; … … 8 9 import javax.swing.AbstractButton; 9 10 import javax.swing.Action; 10 import javax.swing. BorderFactory;11 import javax.swing.J Label;12 import javax.swing. JPanel;11 import javax.swing.JComponent; 12 import javax.swing.JDialog; 13 import javax.swing.KeyStroke; 13 14 14 15 import org.openstreetmap.josm.gui.ImageProvider; 16 import org.openstreetmap.josm.gui.Main; 17 import org.openstreetmap.josm.gui.MapFrame; 15 18 16 19 /** … … 20 23 * @author imi 21 24 */ 22 public class ToggleDialog extends J Panelimplements Action {25 public class ToggleDialog extends JDialog implements Action { 23 26 24 27 /** … … 26 29 * @param title The title of the dialog. 27 30 */ 28 public ToggleDialog(String title, String name, String iconName, int mnemonic, String tooltip) { 31 public ToggleDialog(MapFrame mapFrame, String title, String name, String iconName, int mnemonic, String tooltip) { 32 super(Main.main, title, false); 29 33 putValue(SMALL_ICON, ImageProvider.get("dialogs", iconName)); 30 34 putValue(NAME, name); 31 35 putValue(MNEMONIC_KEY, mnemonic); 32 putValue(SHORT_DESCRIPTION, tooltip); 33 34 setLayout(new BorderLayout()); 35 add(new JLabel(title), BorderLayout.NORTH); 36 setVisible(false); 37 setBorder(BorderFactory.createEtchedBorder()); 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 }); 38 47 } 39 48 -
/src/org/openstreetmap/josm/gui/layer/Layer.java
r30 r20 5 5 import javax.swing.Icon; 6 6 7 import org.openstreetmap.josm.data.Bounds; 8 import org.openstreetmap.josm.data.projection.Projection; 7 import org.openstreetmap.josm.data.osm.DataSet; 9 8 import org.openstreetmap.josm.gui.MapView; 10 9 … … 24 23 * @author imi 25 24 */ 26 abstract public classLayer {25 public interface Layer { 27 26 28 27 /** 29 * The visibility state of the layer. 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. 30 33 */ 31 public boolean visible = true; 32 /** 33 * The name of this layer. 34 */ 35 public final String name; 34 void paint(Graphics g, MapView mv); 36 35 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);49 36 /** 50 37 * Return a representative small image for this layer. The image must not 51 38 * be larger than 64 pixel in any dimension. 52 39 */ 53 abstract publicIcon getIcon();40 Icon getIcon(); 54 41 55 42 /** 56 * @return A small tooltip hint about some statistics for this layer.43 * Provide a human readable name (may be in html format). 57 44 */ 58 abstract public String getToolTipText(); 45 String getName(); 46 47 /** 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. 51 */ 52 DataSet getDataSet(); 53 54 /** 55 * @return <code>true</code>, if the map data can be edited. 56 */ 57 boolean isEditable(); 59 58 60 59 /** 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. 60 * @return <code>true</code>, if the layer is visible 66 61 */ 67 abstract public void mergeFrom(Layer from);62 boolean isVisible(); 68 63 69 64 /** 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. 65 * Set the visibility state of the layer. 72 66 */ 73 abstract public boolean isMergable(Layer other); 74 75 /** 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. 79 */ 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(); 88 89 /** 90 * Initialize the internal dataset with the given projection. 91 */ 92 abstract public void init(Projection projection); 67 void setVisible(boolean visible); 93 68 } -
/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
r30 r20 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;7 2 8 3 import javax.swing.Icon; 9 4 10 import org.openstreetmap.josm.Main;11 import org.openstreetmap.josm.command.Command;12 import org.openstreetmap.josm.data.Bounds;13 5 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;21 6 import org.openstreetmap.josm.gui.ImageProvider; 22 import org.openstreetmap.josm.gui. MapView;7 import org.openstreetmap.josm.gui.engine.SimpleEngine; 23 8 24 9 /** 25 * A layer holding data from a specific dataset. 10 * A layer holding data imported from the osm server. 11 * 26 12 * The data can be fully edited. 27 13 * 28 14 * @author imi 29 15 */ 30 public class OsmDataLayer extends Layer {16 public class OsmDataLayer extends DataLayer { 31 17 32 18 private static Icon icon; 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 19 45 20 /** 46 21 * Construct a OsmDataLayer. 47 22 */ 48 public OsmDataLayer(DataSet data, String name) { 49 super(name); 50 this.data = data; 23 protected OsmDataLayer(DataSet dataSet, String name) { 24 super(dataSet, new SimpleEngine(), name); 51 25 } 52 26 … … 55 29 * updated by a background thread to not disturb the running programm. 56 30 */ 57 @Override58 31 public Icon getIcon() { 59 32 if (icon == null) … … 62 35 } 63 36 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 } 37 public boolean isEditable() { 38 return true; 180 39 } 181 40 } -
/src/org/openstreetmap/josm/gui/layer/RawGpsDataLayer.java
r30 r20 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;9 2 10 3 import javax.swing.Icon; 11 4 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; 5 import org.openstreetmap.josm.data.osm.DataSet; 16 6 import org.openstreetmap.josm.gui.ImageProvider; 17 import org.openstreetmap.josm.gui. MapView;7 import org.openstreetmap.josm.gui.engine.RawGpsEngine; 18 8 19 9 /** … … 23 13 * @author imi 24 14 */ 25 public class RawGpsDataLayer extends Layer {15 public class RawGpsDataLayer extends DataLayer { 26 16 27 17 private static Icon icon; 28 18 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 }); 19 protected RawGpsDataLayer(DataSet dataSet, String name) { 20 super(dataSet, new RawGpsEngine(), name); 48 21 } 49 22 … … 51 24 * Return a static icon. 52 25 */ 53 @Override54 26 public Icon getIcon() { 55 27 if (icon == null) … … 58 30 } 59 31 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); 32 public boolean isEditable() { 33 return false; 144 34 } 145 35 } -
/src/org/openstreetmap/josm/io/GpxReader.java
r30 r20 9 9 import org.jdom.Namespace; 10 10 import org.jdom.input.SAXBuilder; 11 import org.openstreetmap.josm.Main;12 11 import org.openstreetmap.josm.data.GeoPoint; 13 12 import org.openstreetmap.josm.data.osm.DataSet; … … 17 16 import org.openstreetmap.josm.data.osm.OsmPrimitive; 18 17 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 {27 public class GpxReader implements DataReader { 28 28 29 29 /** 30 30 * The GPX namespace used. 31 31 */ 32 p ublic static finalNamespace GPX = Namespace.getNamespace("http://www.topografix.com/GPX/1/0");32 private static 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" , "http://www.openstreetmap.org");36 private static final Namespace OSM = Namespace.getNamespace("osm"); 37 37 38 38 /** … … 40 40 */ 41 41 public Reader source; 42 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 43 49 /** 44 50 * Construct a parser from a specific data source. 45 51 * @param source The data source, as example a FileReader to read from a file. 46 */ 47 public GpxReader(Reader source) { 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) { 48 57 this.source = source; 58 this.rawGps = rawGps; 49 59 } 50 60 … … 52 62 * Read the input stream and return a DataSet from the stream. 53 63 */ 54 public DataSet parse() throws JDOMException, IOException {64 public DataSet parse() throws ParseException, ConnectionException { 55 65 try { 56 66 final SAXBuilder builder = new SAXBuilder(); 57 67 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 58 73 return parseDataSet(root); 59 74 } catch (NullPointerException npe) { 60 throw new JDOMException("NullPointerException. Probably a tag name mismatch.", npe);75 throw new ParseException("NullPointerException. Probably a tag name mismatch.", npe); 61 76 } catch (ClassCastException cce) { 62 throw new JDOMException("ClassCastException. Probably a tag does not contain the correct type.", 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); 63 82 } 64 83 } … … 75 94 Float.parseFloat(e.getAttributeValue("lat")), 76 95 Float.parseFloat(e.getAttributeValue("lon"))); 96 97 if (rawGps) 98 return data; 77 99 78 100 for (Object o : e.getChildren()) { … … 115 137 private void parseTrack(Element e, DataSet ds) { 116 138 Track track = new Track(); 117 boolean realLineSegment = false; // is this track just a fake?118 119 139 for (Object o : e.getChildren()) { 120 140 Element child = (Element)o; … … 129 149 else { 130 150 LineSegment lineSegment = new LineSegment(start, node); 131 parseKeyValueExtensions(lineSegment, child.getChild("extensions", GPX)); 151 if (!rawGps) 152 parseKeyValueExtensions(lineSegment, ((Element)w).getChild("extensions", GPX)); 132 153 track.add(lineSegment); 133 154 start = null; 134 155 } 135 156 } 136 } else if (child.getName().equals("extensions")) { 157 } 158 159 if (rawGps) 160 continue; 161 162 if (child.getName().equals("extensions")) 137 163 parseKeyValueExtensions(track, child); 138 if (child.getChild("segment", OSM) != null) 139 realLineSegment = true; 140 } else if (child.getName().equals("link")) 164 else if (child.getName().equals("link")) 141 165 parseKeyValueLink(track, child); 142 166 else 143 167 parseKeyValueTag(track, child); 144 168 } 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 } 169 ds.addTrack(track); 151 170 } 152 171 … … 164 183 * @return Either the parameter node or the old node found in the dataset. 165 184 */ 166 private Node addNode (DataSet data, Node node) {167 if (Main.pref.mergeNodes )185 private Node addNode (DataSet data, Node node) { 186 if (Main.pref.mergeNodes || rawGps) 168 187 for (Node n : data.nodes) 169 188 if (node.coor.equalsLatLon(n.coor)) … … 184 203 private void parseKeyValueExtensions(OsmPrimitive osm, Element e) { 185 204 if (e != null) { 205 if (osm.keys == null) 206 osm.keys = new HashMap<Key, String>(); 186 207 for (Object o : e.getChildren("property", OSM)) { 187 if (osm.keys == null)188 osm.keys = new HashMap<Key, String>();189 208 Element child = (Element)o; 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 } 209 Key key = Key.get(child.getAttributeValue("name")); 210 osm.keys.put(key, child.getAttributeValue("value")); 198 211 } 199 212 } -
/src/org/openstreetmap/josm/io/GpxWriter.java
r30 r20 14 14 import org.jdom.output.Format; 15 15 import org.jdom.output.XMLOutputter; 16 import org.openstreetmap.josm. Main;16 import org.openstreetmap.josm.data.osm.DataSet; 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; 49 53 50 54 /** … … 53 57 * 54 58 * @param out The Writer to store the result data in. 55 */ 56 public GpxWriter(Writer out) { 59 * @param ds The dataset to store. 60 */ 61 public GpxWriter(Writer out, DataSet ds) { 62 this.ds = ds; 57 63 this.out = out; 58 64 } … … 80 86 Element e = new Element("gpx", GPX); 81 87 e.setAttribute("version", "1.0"); 82 e.setAttribute("creator", "JOSM Beta 2");88 e.setAttribute("creator", "JOSM Beta"); 83 89 // for getting all unreferenced waypoints in the wpt-list 84 LinkedList<Node> nodes = new LinkedList<Node>( Main.main.ds.nodes);90 LinkedList<Node> nodes = new LinkedList<Node>(ds.nodes); 85 91 86 92 // tracks 87 for (Track t : Main.main.ds.tracks) {93 for (Track t : ds.tracks()) { 88 94 Element tElem = new Element("trk", GPX); 89 95 if (t.keys != null) { … … 99 105 } 100 106 // line segments 101 for (LineSegment ls : t.segments) { 102 tElem.getChildren().add(parseLineSegment(ls)); 103 nodes.remove(ls.start); 104 nodes.remove(ls.end); 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); 105 116 } 106 107 117 e.getChildren().add(tElem); 108 118 } 109 119 110 // encode pending line segments as tracks111 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 122 120 // waypoints (missing nodes) 123 121 for (Node n : nodes) … … 125 123 126 124 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;141 125 } 142 126 … … 235 219 if (keys.isEmpty()) 236 220 return; 237 Element extensions = e.getChild("extensions" , GPX);221 Element extensions = e.getChild("extensions"); 238 222 if (extensions == null) 239 223 e.getChildren().add(extensions = new Element("extensions", GPX)); -
/src/org/openstreetmap/josm/io/OsmReader.java
r30 r20 1 1 package org.openstreetmap.josm.io; 2 2 3 import java.awt.Font; 4 import java.awt.GridBagLayout; 3 5 import java.io.IOException; 6 import java.io.InputStreamReader; 4 7 import java.io.Reader; 5 import java.util.Collection; 6 import java.util.HashMap; 7 import java.util.StringTokenizer; 8 import java.net.Authenticator; 9 import java.net.HttpURLConnection; 10 import java.net.PasswordAuthentication; 11 import java.net.URL; 8 12 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; 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 14 19 import org.openstreetmap.josm.data.osm.DataSet; 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; 20 import org.openstreetmap.josm.gui.GBC; 21 import org.openstreetmap.josm.gui.Main; 20 22 21 23 /** 22 * Reads an osm xml stream and construct a DataSet out of it.24 * This DataReader read directly from the REST API of the osm server. 23 25 * 24 26 * @author imi 25 27 */ 26 public class OsmReader {28 public class OsmReader implements DataReader { 27 29 28 30 /** 29 * The data source from this reader.31 * The url string of the desired map data. 30 32 */ 31 public Reader source; 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; 32 46 33 47 /** 34 * Construct a parser from a specific data source. 35 * @param source The data source, as example a FileReader to read from a file. 48 * Construct the reader and store the information for attaching 36 49 */ 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 } 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="; 58 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; 85 } 86 passwordtried = true; 87 return new PasswordAuthentication(username, password.toCharArray()); 88 } 89 }); 56 90 } 57 91 58 92 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."); 88 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), ""); 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); 101 109 } 102 110 } 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); 103 120 } 104 121 } 105 106 /**107 * Read a data set from the element.108 * @param e The element to parse109 * @return The DataSet read from the element110 * @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" and139 * "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;188 }189 }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 the206 * preference setting "mergeNodes". Return the node in the list that correspond207 * 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. You210 * 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;223 }224 122 }
Note:
See TracChangeset
for help on using the changeset viewer.