- Timestamp:
- 2008-11-14T01:09:29+01:00 (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
r999 r1078 10 10 import java.awt.Component; 11 11 import java.awt.Graphics; 12 import java.awt.Graphics2D; 12 13 import java.awt.GridBagLayout; 13 14 import java.awt.Point; 15 import java.awt.Rectangle; 16 import java.awt.TexturePaint; 14 17 import java.awt.event.ActionEvent; 18 import java.awt.geom.Area; 19 import java.awt.image.BufferedImage; 15 20 import java.io.File; 16 21 import java.util.Collection; … … 66 71 public class OsmDataLayer extends Layer { 67 72 68 public final static class DataCountVisitor implements Visitor { 69 public final int[] normal = new int[3]; 70 public final int[] deleted = new int[3]; 71 public final String[] names = {"node", "way", "relation"}; 72 73 private void inc(final OsmPrimitive osm, final int i) { 74 normal[i]++; 75 if (osm.deleted) 76 deleted[i]++; 77 } 78 79 public void visit(final Node n) { 80 inc(n, 0); 81 } 82 83 public void visit(final Way w) { 84 inc(w, 1); 85 } 86 public void visit(final Relation w) { 87 inc(w, 2); 88 } 89 } 90 91 public interface ModifiedChangedListener { 92 void modifiedChanged(boolean value, OsmDataLayer source); 93 } 94 public interface CommandQueueListener { 95 void commandChanged(int queueSize, int redoSize); 96 } 97 98 /** 99 * @deprecated Use Main.main.undoRedo.add(...) instead. 100 */ 101 @Deprecated public void add(final Command c) { 102 Main.main.undoRedo.add(c); 103 } 104 105 /** 106 * The data behind this layer. 107 */ 108 public final DataSet data; 109 110 /** 111 * Whether the data of this layer was modified during the session. 112 */ 113 private boolean modified = false; 114 /** 115 * Whether the data was modified due an upload of the data to the server. 116 */ 117 public boolean uploadedModified = false; 118 119 public final LinkedList<ModifiedChangedListener> listenerModified = new LinkedList<ModifiedChangedListener>(); 120 public final LinkedList<DataChangeListener> listenerDataChanged = new LinkedList<DataChangeListener>(); 121 122 /** 123 * Construct a OsmDataLayer. 124 */ 125 public OsmDataLayer(final DataSet data, final String name, final File associatedFile) { 126 super(name); 127 this.data = data; 128 this.associatedFile = associatedFile; 129 } 130 131 /** 132 * TODO: @return Return a dynamic drawn icon of the map data. The icon is 133 * updated by a background thread to not disturb the running programm. 134 */ 135 @Override public Icon getIcon() { 136 return ImageProvider.get("layer", "osmdata_small"); 137 } 138 139 /** 140 * Draw all primitives in this layer but do not draw modified ones (they 141 * are drawn by the edit layer). 142 * Draw nodes last to overlap the ways they belong to. 143 */ 144 @Override public void paint(final Graphics g, final MapView mv) { 145 boolean inactive = Main.map.mapView.getActiveLayer() != this && Main.pref.getBoolean("draw.data.inactive_color", true); 146 boolean virtual = !inactive && Main.map.mapView.useVirtualNodes(); 147 if (Main.pref.getBoolean("draw.data.downloaded_area", true)) { 148 // FIXME this is inefficient; instead a proper polygon has to be built, and instead 149 // of drawing the outline, the outlying areas should perhaps be shaded. 150 for (DataSource src : data.dataSources) { 151 if (src.bounds != null && !src.bounds.min.equals(src.bounds.max)) { 152 EastNorth en1 = Main.proj.latlon2eastNorth(src.bounds.min); 153 EastNorth en2 = Main.proj.latlon2eastNorth(src.bounds.max); 154 Point p1 = mv.getPoint(en1); 155 Point p2 = mv.getPoint(en2); 156 Color color = inactive ? Main.pref.getColor(marktr("inactive"), Color.DARK_GRAY) : 157 Main.pref.getColor(marktr("downloaded Area"), Color.YELLOW); 158 g.setColor(color); 159 g.drawRect(Math.min(p1.x,p2.x), Math.min(p1.y, p2.y), Math.abs(p2.x-p1.x), Math.abs(p2.y-p1.y)); 160 } 161 } 162 } 163 164 165 SimplePaintVisitor painter; 166 if (Main.pref.getBoolean("draw.wireframe")) 167 painter = new SimplePaintVisitor(); 168 else 169 painter = new MapPaintVisitor(); 170 painter.setGraphics(g); 171 painter.setNavigatableComponent(mv); 172 painter.inactive = inactive; 173 painter.visitAll(data, virtual); 174 Main.map.conflictDialog.paintConflicts(g, mv); 175 } 176 177 @Override public String getToolTipText() { 178 String tool = ""; 179 tool += undeletedSize(data.nodes)+" "+trn("node", "nodes", undeletedSize(data.nodes))+", "; 180 tool += undeletedSize(data.ways)+" "+trn("way", "ways", undeletedSize(data.ways)); 181 if (associatedFile != null) 182 tool = "<html>"+tool+"<br>"+associatedFile.getPath()+"</html>"; 183 return tool; 184 } 185 186 @Override public void mergeFrom(final Layer from) { 187 final MergeVisitor visitor = new MergeVisitor(data,((OsmDataLayer)from).data); 188 for (final OsmPrimitive osm : ((OsmDataLayer)from).data.allPrimitives()) 189 osm.visit(visitor); 190 visitor.fixReferences(); 191 192 // copy the merged layer's data source info 193 for (DataSource src : ((OsmDataLayer)from).data.dataSources) 194 data.dataSources.add(src); 195 fireDataChange(); 196 // repaint to make sure new data is displayed properly. 197 Main.map.mapView.repaint(); 198 199 if (visitor.conflicts.isEmpty()) 200 return; 201 final ConflictDialog dlg = Main.map.conflictDialog; 202 dlg.add(visitor.conflicts); 203 JOptionPane.showMessageDialog(Main.parent,tr("There were conflicts during import.")); 204 if (!dlg.isVisible()) 205 dlg.action.actionPerformed(new ActionEvent(this, 0, "")); 206 } 207 208 @Override public boolean isMergable(final Layer other) { 209 return other instanceof OsmDataLayer; 210 } 211 212 @Override public void visitBoundingBox(final BoundingXYVisitor v) { 213 for (final Node n : data.nodes) 214 if (!n.deleted && !n.incomplete) 215 v.visit(n); 216 } 217 218 /** 219 * Clean out the data behind the layer. This means clearing the redo/undo lists, 220 * really deleting all deleted objects and reset the modified flags. This is done 221 * after a successfull upload. 222 * 223 * @param processed A list of all objects that were actually uploaded. 224 * May be <code>null</code>, which means nothing has been uploaded but 225 * saved to disk instead. Note that an empty collection for "processed" 226 * means that an upload has been attempted but failed. 227 */ 228 public void cleanData(final Collection<OsmPrimitive> processed, boolean dataAdded) { 229 230 // return immediately if an upload attempt failed 231 if (processed != null && processed.isEmpty() && !dataAdded) 232 return; 233 234 Main.main.undoRedo.clean(); 235 236 // if uploaded, clean the modified flags as well 237 if (processed != null) { 238 final Set<OsmPrimitive> processedSet = new HashSet<OsmPrimitive>(processed); 239 for (final Iterator<Node> it = data.nodes.iterator(); it.hasNext();) 240 cleanIterator(it, processedSet); 241 for (final Iterator<Way> it = data.ways.iterator(); it.hasNext();) 242 cleanIterator(it, processedSet); 243 for (final Iterator<Relation> it = data.relations.iterator(); it.hasNext();) 244 cleanIterator(it, processedSet); 245 } 246 247 // update the modified flag 248 if (associatedFile != null && processed != null && !dataAdded) 249 return; // do nothing when uploading non-harmful changes. 250 251 // modified if server changed the data (esp. the id). 252 uploadedModified = associatedFile != null && processed != null && dataAdded; 253 setModified(uploadedModified); 254 } 255 256 /** 257 * Clean the modified flag for the given iterator over a collection if it is in the 258 * list of processed entries. 259 * 260 * @param it The iterator to change the modified and remove the items if deleted. 261 * @param processed A list of all objects that have been successfully progressed. 262 * If the object in the iterator is not in the list, nothing will be changed on it. 263 */ 264 private void cleanIterator(final Iterator<? extends OsmPrimitive> it, final Collection<OsmPrimitive> processed) { 265 final OsmPrimitive osm = it.next(); 266 if (!processed.remove(osm)) 267 return; 268 osm.modified = false; 269 if (osm.deleted) 270 it.remove(); 271 } 272 273 public boolean isModified() { 274 return modified; 275 } 276 277 public void setModified(final boolean modified) { 278 if (modified == this.modified) 279 return; 280 this.modified = modified; 281 for (final ModifiedChangedListener l : listenerModified) 282 l.modifiedChanged(modified, this); 283 } 284 285 /** 286 * @return The number of not-deleted primitives in the list. 287 */ 288 private int undeletedSize(final Collection<? extends OsmPrimitive> list) { 289 int size = 0; 290 for (final OsmPrimitive osm : list) 291 if (!osm.deleted) 292 size++; 293 return size; 294 } 295 296 @Override public Object getInfoComponent() { 297 final DataCountVisitor counter = new DataCountVisitor(); 298 for (final OsmPrimitive osm : data.allPrimitives()) 299 osm.visit(counter); 300 final JPanel p = new JPanel(new GridBagLayout()); 301 p.add(new JLabel(tr("{0} consists of:", name)), GBC.eol()); 302 for (int i = 0; i < counter.normal.length; ++i) { 303 String s = counter.normal[i]+" "+trn(counter.names[i],counter.names[i]+"s",counter.normal[i]); 304 if (counter.deleted[i] > 0) 305 s += tr(" ({0} deleted.)",counter.deleted[i]); 306 p.add(new JLabel(s, ImageProvider.get("data", counter.names[i]), JLabel.HORIZONTAL), GBC.eop().insets(15,0,0,0)); 307 } 308 return p; 309 } 310 311 @Override public Component[] getMenuEntries() { 312 if (Main.applet) { 313 return new Component[]{ 314 new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)), 315 new JMenuItem(new LayerListDialog.DeleteLayerAction(this)), 316 new JSeparator(), 317 new JMenuItem(new RenameLayerAction(associatedFile, this)), 318 new JSeparator(), 319 new JMenuItem(new LayerListPopup.InfoAction(this))}; 320 } 321 return new Component[]{ 322 new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)), 323 new JMenuItem(new LayerListDialog.DeleteLayerAction(this)), 324 new JSeparator(), 325 new JMenuItem(new SaveAction(this)), 326 new JMenuItem(new SaveAsAction(this)), 327 new JMenuItem(new GpxExportAction(this)), 328 new JMenuItem(new ConvertToGpxLayerAction()), 329 new JSeparator(), 330 new JMenuItem(new RenameLayerAction(associatedFile, this)), 331 new JSeparator(), 332 new JMenuItem(new LayerListPopup.InfoAction(this))}; 333 } 334 335 public void fireDataChange() { 336 for (DataChangeListener dcl : listenerDataChanged) { 337 dcl.dataChanged(this); 338 } 339 } 340 341 public static GpxData toGpxData(DataSet data) { 342 GpxData gpxData = new GpxData(); 343 HashSet<Node> doneNodes = new HashSet<Node>(); 344 for (Way w : data.ways) { 345 if (w.incomplete || w.deleted) continue; 346 GpxTrack trk = new GpxTrack(); 347 gpxData.tracks.add(trk); 348 349 if (w.get("name") != null) 350 trk.attr.put("name", w.get("name")); 351 352 ArrayList<WayPoint> trkseg = null; 353 for (Node n : w.nodes) { 354 if (n.incomplete || n.deleted) { 355 trkseg = null; 356 continue; 357 } 358 if (trkseg == null) { 359 trkseg = new ArrayList<WayPoint>(); 360 trk.trackSegs.add(trkseg); 361 } 362 if (!n.tagged) { 363 doneNodes.add(n); 364 } 365 WayPoint wpt = new WayPoint(n.coor); 366 if (n.timestamp != null) 367 { 368 wpt.attr.put("time", n.timestamp); 369 wpt.setTime(); 370 } 371 trkseg.add(wpt); 372 } 373 } 374 375 // what is this loop meant to do? it creates waypoints but never 376 // records them? 377 for (Node n : data.nodes) { 378 if (n.incomplete || n.deleted || doneNodes.contains(n)) continue; 379 WayPoint wpt = new WayPoint(n.coor); 380 if (n.timestamp != null) { 381 wpt.attr.put("time", n.timestamp); 382 wpt.setTime(); 383 } 384 if (n.keys != null && n.keys.containsKey("name")) { 385 wpt.attr.put("name", n.keys.get("name")); 386 } 387 } 388 return gpxData; 389 } 390 391 public GpxData toGpxData() { 392 return toGpxData(data); 393 } 394 395 public class ConvertToGpxLayerAction extends AbstractAction { 396 public ConvertToGpxLayerAction() { 397 super(tr("Convert to GPX layer"), ImageProvider.get("converttogpx")); 398 } 399 public void actionPerformed(ActionEvent e) { 400 Main.main.addLayer(new GpxLayer(toGpxData(), tr("Converted from: {0}", name))); 401 Main.main.removeLayer(OsmDataLayer.this); 402 } 403 } 73 public final static class DataCountVisitor implements Visitor { 74 public final int[] normal = new int[3]; 75 public final int[] deleted = new int[3]; 76 public final String[] names = {"node", "way", "relation"}; 77 78 private void inc(final OsmPrimitive osm, final int i) { 79 normal[i]++; 80 if (osm.deleted) 81 deleted[i]++; 82 } 83 84 public void visit(final Node n) { 85 inc(n, 0); 86 } 87 88 public void visit(final Way w) { 89 inc(w, 1); 90 } 91 public void visit(final Relation w) { 92 inc(w, 2); 93 } 94 } 95 96 public interface ModifiedChangedListener { 97 void modifiedChanged(boolean value, OsmDataLayer source); 98 } 99 public interface CommandQueueListener { 100 void commandChanged(int queueSize, int redoSize); 101 } 102 103 /** 104 * @deprecated Use Main.main.undoRedo.add(...) instead. 105 */ 106 @Deprecated public void add(final Command c) { 107 Main.main.undoRedo.add(c); 108 } 109 110 /** 111 * The data behind this layer. 112 */ 113 public final DataSet data; 114 115 /** 116 * Whether the data of this layer was modified during the session. 117 */ 118 private boolean modified = false; 119 /** 120 * Whether the data was modified due an upload of the data to the server. 121 */ 122 public boolean uploadedModified = false; 123 124 public final LinkedList<ModifiedChangedListener> listenerModified = new LinkedList<ModifiedChangedListener>(); 125 public final LinkedList<DataChangeListener> listenerDataChanged = new LinkedList<DataChangeListener>(); 126 127 /** 128 * a paint texture for non-downloaded area 129 */ 130 private TexturePaint hatched; 131 132 /** 133 * Construct a OsmDataLayer. 134 */ 135 public OsmDataLayer(final DataSet data, final String name, final File associatedFile) { 136 super(name); 137 this.data = data; 138 this.associatedFile = associatedFile; 139 140 BufferedImage bi = new BufferedImage(15, 15, BufferedImage.TYPE_INT_RGB); 141 Graphics2D big = bi.createGraphics(); 142 big.setColor(Main.pref.getColor(marktr("background"), Color.BLACK)); 143 big.fillRect(0,0,15,15); 144 big.setColor(Main.pref.getColor(marktr("downloaded Area"), Color.YELLOW)); 145 big.drawLine(0,15,15,0); 146 Rectangle r = new Rectangle(0, 0, 15,15); 147 hatched = new TexturePaint(bi, r); 148 } 149 150 /** 151 * TODO: @return Return a dynamic drawn icon of the map data. The icon is 152 * updated by a background thread to not disturb the running programm. 153 */ 154 @Override public Icon getIcon() { 155 return ImageProvider.get("layer", "osmdata_small"); 156 } 157 158 /** 159 * Draw all primitives in this layer but do not draw modified ones (they 160 * are drawn by the edit layer). 161 * Draw nodes last to overlap the ways they belong to. 162 */ 163 @Override public void paint(final Graphics g, final MapView mv) { 164 boolean inactive = Main.map.mapView.getActiveLayer() != this && Main.pref.getBoolean("draw.data.inactive_color", true); 165 boolean virtual = !inactive && Main.map.mapView.useVirtualNodes(); 166 if (Main.pref.getBoolean("draw.data.downloaded_area", true)) { 167 // initialize area with current viewport 168 Area b = new Area(Main.map.mapView.getBounds()); 169 170 // now succesively subtract downloaded areas 171 for (DataSource src : data.dataSources) { 172 if (src.bounds != null && !src.bounds.min.equals(src.bounds.max)) { 173 EastNorth en1 = Main.proj.latlon2eastNorth(src.bounds.min); 174 EastNorth en2 = Main.proj.latlon2eastNorth(src.bounds.max); 175 Point p1 = mv.getPoint(en1); 176 Point p2 = mv.getPoint(en2); 177 Rectangle r = new Rectangle(Math.min(p1.x, p2.x),Math.min(p1.y, p2.y),Math.abs(p2.x-p1.x),Math.abs(p2.y-p1.y)); 178 b.subtract(new Area(r)); 179 } 180 } 181 182 // paint remainder 183 ((Graphics2D)g).setPaint(hatched); 184 ((Graphics2D)g).fill(b); 185 } 186 187 SimplePaintVisitor painter; 188 if (Main.pref.getBoolean("draw.wireframe")) 189 painter = new SimplePaintVisitor(); 190 else 191 painter = new MapPaintVisitor(); 192 painter.setGraphics(g); 193 painter.setNavigatableComponent(mv); 194 painter.inactive = inactive; 195 painter.visitAll(data, virtual); 196 Main.map.conflictDialog.paintConflicts(g, mv); 197 } 198 199 @Override public String getToolTipText() { 200 String tool = ""; 201 tool += undeletedSize(data.nodes)+" "+trn("node", "nodes", undeletedSize(data.nodes))+", "; 202 tool += undeletedSize(data.ways)+" "+trn("way", "ways", undeletedSize(data.ways)); 203 if (associatedFile != null) 204 tool = "<html>"+tool+"<br>"+associatedFile.getPath()+"</html>"; 205 return tool; 206 } 207 208 @Override public void mergeFrom(final Layer from) { 209 final MergeVisitor visitor = new MergeVisitor(data,((OsmDataLayer)from).data); 210 for (final OsmPrimitive osm : ((OsmDataLayer)from).data.allPrimitives()) 211 osm.visit(visitor); 212 visitor.fixReferences(); 213 214 // copy the merged layer's data source info 215 for (DataSource src : ((OsmDataLayer)from).data.dataSources) 216 data.dataSources.add(src); 217 fireDataChange(); 218 // repaint to make sure new data is displayed properly. 219 Main.map.mapView.repaint(); 220 221 if (visitor.conflicts.isEmpty()) 222 return; 223 final ConflictDialog dlg = Main.map.conflictDialog; 224 dlg.add(visitor.conflicts); 225 JOptionPane.showMessageDialog(Main.parent,tr("There were conflicts during import.")); 226 if (!dlg.isVisible()) 227 dlg.action.actionPerformed(new ActionEvent(this, 0, "")); 228 } 229 230 @Override public boolean isMergable(final Layer other) { 231 return other instanceof OsmDataLayer; 232 } 233 234 @Override public void visitBoundingBox(final BoundingXYVisitor v) { 235 for (final Node n : data.nodes) 236 if (!n.deleted && !n.incomplete) 237 v.visit(n); 238 } 239 240 /** 241 * Clean out the data behind the layer. This means clearing the redo/undo lists, 242 * really deleting all deleted objects and reset the modified flags. This is done 243 * after a successfull upload. 244 * 245 * @param processed A list of all objects that were actually uploaded. 246 * May be <code>null</code>, which means nothing has been uploaded but 247 * saved to disk instead. Note that an empty collection for "processed" 248 * means that an upload has been attempted but failed. 249 */ 250 public void cleanData(final Collection<OsmPrimitive> processed, boolean dataAdded) { 251 252 // return immediately if an upload attempt failed 253 if (processed != null && processed.isEmpty() && !dataAdded) 254 return; 255 256 Main.main.undoRedo.clean(); 257 258 // if uploaded, clean the modified flags as well 259 if (processed != null) { 260 final Set<OsmPrimitive> processedSet = new HashSet<OsmPrimitive>(processed); 261 for (final Iterator<Node> it = data.nodes.iterator(); it.hasNext();) 262 cleanIterator(it, processedSet); 263 for (final Iterator<Way> it = data.ways.iterator(); it.hasNext();) 264 cleanIterator(it, processedSet); 265 for (final Iterator<Relation> it = data.relations.iterator(); it.hasNext();) 266 cleanIterator(it, processedSet); 267 } 268 269 // update the modified flag 270 if (associatedFile != null && processed != null && !dataAdded) 271 return; // do nothing when uploading non-harmful changes. 272 273 // modified if server changed the data (esp. the id). 274 uploadedModified = associatedFile != null && processed != null && dataAdded; 275 setModified(uploadedModified); 276 } 277 278 /** 279 * Clean the modified flag for the given iterator over a collection if it is in the 280 * list of processed entries. 281 * 282 * @param it The iterator to change the modified and remove the items if deleted. 283 * @param processed A list of all objects that have been successfully progressed. 284 * If the object in the iterator is not in the list, nothing will be changed on it. 285 */ 286 private void cleanIterator(final Iterator<? extends OsmPrimitive> it, final Collection<OsmPrimitive> processed) { 287 final OsmPrimitive osm = it.next(); 288 if (!processed.remove(osm)) 289 return; 290 osm.modified = false; 291 if (osm.deleted) 292 it.remove(); 293 } 294 295 public boolean isModified() { 296 return modified; 297 } 298 299 public void setModified(final boolean modified) { 300 if (modified == this.modified) 301 return; 302 this.modified = modified; 303 for (final ModifiedChangedListener l : listenerModified) 304 l.modifiedChanged(modified, this); 305 } 306 307 /** 308 * @return The number of not-deleted primitives in the list. 309 */ 310 private int undeletedSize(final Collection<? extends OsmPrimitive> list) { 311 int size = 0; 312 for (final OsmPrimitive osm : list) 313 if (!osm.deleted) 314 size++; 315 return size; 316 } 317 318 @Override public Object getInfoComponent() { 319 final DataCountVisitor counter = new DataCountVisitor(); 320 for (final OsmPrimitive osm : data.allPrimitives()) 321 osm.visit(counter); 322 final JPanel p = new JPanel(new GridBagLayout()); 323 p.add(new JLabel(tr("{0} consists of:", name)), GBC.eol()); 324 for (int i = 0; i < counter.normal.length; ++i) { 325 String s = counter.normal[i]+" "+trn(counter.names[i],counter.names[i]+"s",counter.normal[i]); 326 if (counter.deleted[i] > 0) 327 s += tr(" ({0} deleted.)",counter.deleted[i]); 328 p.add(new JLabel(s, ImageProvider.get("data", counter.names[i]), JLabel.HORIZONTAL), GBC.eop().insets(15,0,0,0)); 329 } 330 return p; 331 } 332 333 @Override public Component[] getMenuEntries() { 334 if (Main.applet) { 335 return new Component[]{ 336 new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)), 337 new JMenuItem(new LayerListDialog.DeleteLayerAction(this)), 338 new JSeparator(), 339 new JMenuItem(new RenameLayerAction(associatedFile, this)), 340 new JSeparator(), 341 new JMenuItem(new LayerListPopup.InfoAction(this))}; 342 } 343 return new Component[]{ 344 new JMenuItem(new LayerListDialog.ShowHideLayerAction(this)), 345 new JMenuItem(new LayerListDialog.DeleteLayerAction(this)), 346 new JSeparator(), 347 new JMenuItem(new SaveAction(this)), 348 new JMenuItem(new SaveAsAction(this)), 349 new JMenuItem(new GpxExportAction(this)), 350 new JMenuItem(new ConvertToGpxLayerAction()), 351 new JSeparator(), 352 new JMenuItem(new RenameLayerAction(associatedFile, this)), 353 new JSeparator(), 354 new JMenuItem(new LayerListPopup.InfoAction(this))}; 355 } 356 357 public void fireDataChange() { 358 for (DataChangeListener dcl : listenerDataChanged) { 359 dcl.dataChanged(this); 360 } 361 } 362 363 public static GpxData toGpxData(DataSet data) { 364 GpxData gpxData = new GpxData(); 365 HashSet<Node> doneNodes = new HashSet<Node>(); 366 for (Way w : data.ways) { 367 if (w.incomplete || w.deleted) continue; 368 GpxTrack trk = new GpxTrack(); 369 gpxData.tracks.add(trk); 370 371 if (w.get("name") != null) 372 trk.attr.put("name", w.get("name")); 373 374 ArrayList<WayPoint> trkseg = null; 375 for (Node n : w.nodes) { 376 if (n.incomplete || n.deleted) { 377 trkseg = null; 378 continue; 379 } 380 if (trkseg == null) { 381 trkseg = new ArrayList<WayPoint>(); 382 trk.trackSegs.add(trkseg); 383 } 384 if (!n.tagged) { 385 doneNodes.add(n); 386 } 387 WayPoint wpt = new WayPoint(n.coor); 388 if (n.timestamp != null) 389 { 390 wpt.attr.put("time", n.timestamp); 391 wpt.setTime(); 392 } 393 trkseg.add(wpt); 394 } 395 } 396 397 // what is this loop meant to do? it creates waypoints but never 398 // records them? 399 for (Node n : data.nodes) { 400 if (n.incomplete || n.deleted || doneNodes.contains(n)) continue; 401 WayPoint wpt = new WayPoint(n.coor); 402 if (n.timestamp != null) { 403 wpt.attr.put("time", n.timestamp); 404 wpt.setTime(); 405 } 406 if (n.keys != null && n.keys.containsKey("name")) { 407 wpt.attr.put("name", n.keys.get("name")); 408 } 409 } 410 return gpxData; 411 } 412 413 public GpxData toGpxData() { 414 return toGpxData(data); 415 } 416 417 public class ConvertToGpxLayerAction extends AbstractAction { 418 public ConvertToGpxLayerAction() { 419 super(tr("Convert to GPX layer"), ImageProvider.get("converttogpx")); 420 } 421 public void actionPerformed(ActionEvent e) { 422 Main.main.addLayer(new GpxLayer(toGpxData(), tr("Converted from: {0}", name))); 423 Main.main.removeLayer(OsmDataLayer.this); 424 } 425 } 404 426 405 427 public boolean containsPoint(LatLon coor)
Note:
See TracChangeset
for help on using the changeset viewer.