Changeset 23 in josm


Ignore:
Timestamp:
2005-10-27T00:38:03+02:00 (14 years ago)
Author:
imi
Message:
  • added commands to support undo later
  • added Edit-Layer concept
  • painting of deleted objects
Files:
8 added
3 deleted
37 edited
1 moved

Legend:

Unmodified
Added
Removed
  • src/org/openstreetmap/josm/Main.java

    r22 r23  
    44import java.awt.BorderLayout;
    55import java.awt.Container;
    6 import java.util.Collection;
    7 import java.util.LinkedList;
    86
    97import javax.swing.JFrame;
     
    2220import org.openstreetmap.josm.actions.PreferencesAction;
    2321import org.openstreetmap.josm.actions.SaveGpxAction;
    24 import org.openstreetmap.josm.command.Command;
    25 import org.openstreetmap.josm.command.DataSet;
    2622import org.openstreetmap.josm.data.Preferences;
    2723import org.openstreetmap.josm.data.Preferences.PreferencesException;
     24import org.openstreetmap.josm.data.osm.DataSet;
    2825import org.openstreetmap.josm.gui.ImageProvider;
    2926import org.openstreetmap.josm.gui.MapFrame;
     
    4542         */
    4643        public final static Preferences pref = new Preferences();
    47 
    48         /**
    49          * The global command queue since last save. So if you reload the data from disk
    50          * (or from OSM server, if nothing changed on server) and reapply the commands,
    51          * you should get the same result as currently displaying.
    52          */
    53         public Collection<Command> commands = new LinkedList<Command>();
    5444
    5545        /**
     
    121111                // creating toolbar
    122112                JToolBar toolBar = new JToolBar();
    123                 toolBar.setFloatable(true);
     113                toolBar.setFloatable(false);
    124114                toolBar.add(openServerAction);
    125115                toolBar.add(openGpxAction);
  • src/org/openstreetmap/josm/actions/OpenGpxAction.java

    r21 r23  
    77import java.io.FileReader;
    88import java.io.IOException;
     9import java.util.Collection;
    910
    1011import javax.swing.AbstractAction;
     
    1718import javax.swing.filechooser.FileFilter;
    1819
     20import org.jdom.JDOMException;
    1921import org.openstreetmap.josm.Main;
    20 import org.openstreetmap.josm.command.DataSet;
     22import org.openstreetmap.josm.data.GeoPoint;
     23import org.openstreetmap.josm.data.osm.DataSet;
     24import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2125import org.openstreetmap.josm.gui.GBC;
    2226import org.openstreetmap.josm.gui.ImageProvider;
    2327import org.openstreetmap.josm.gui.MapFrame;
    2428import org.openstreetmap.josm.gui.layer.Layer;
    25 import org.openstreetmap.josm.gui.layer.LayerFactory;
     29import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     30import org.openstreetmap.josm.gui.layer.RawGpsDataLayer;
    2631import org.openstreetmap.josm.io.GpxReader;
    27 import org.openstreetmap.josm.io.DataReader.ConnectionException;
    28 import org.openstreetmap.josm.io.DataReader.ParseException;
     32import org.openstreetmap.josm.io.RawGpsReader;
    2933
    3034/**
     
    8387               
    8488                try {
    85                         DataSet dataSet = new GpxReader(new FileReader(gpxFile), rawGps.isSelected()).parse();
    86 
    87                         Layer layer = LayerFactory.create(dataSet, gpxFile.getName(), rawGps.isSelected());
     89                        Layer layer;
     90                        if (rawGps.isSelected()) {
     91                                Collection<Collection<GeoPoint>> data = new RawGpsReader(new FileReader(gpxFile)).parse();
     92                                layer = new RawGpsDataLayer(data, gpxFile.getName());
     93                        } else {
     94                                DataSet dataSet = new GpxReader(new FileReader(gpxFile)).parse();
     95                                Collection<OsmPrimitive> l = Main.main.ds.mergeFrom(dataSet);
     96                                layer = new OsmDataLayer(l, gpxFile.getName());
     97                        }
    8898                       
    8999                        if (Main.main.getMapFrame() == null || !newLayer.isSelected())
     
    92102                                Main.main.getMapFrame().mapView.addLayer(layer);
    93103                       
    94                 } catch (ParseException x) {
     104                } catch (JDOMException x) {
    95105                        x.printStackTrace();
    96106                        JOptionPane.showMessageDialog(Main.main, x.getMessage());
     
    98108                        x.printStackTrace();
    99109                        JOptionPane.showMessageDialog(Main.main, "Could not read '"+gpxFile.getName()+"'\n"+x.getMessage());
    100                 } catch (ConnectionException x) {
    101                         x.printStackTrace();
    102                         JOptionPane.showMessageDialog(Main.main, x.getMessage());
    103110                }
    104111        }
  • src/org/openstreetmap/josm/actions/OpenOsmServerAction.java

    r22 r23  
    66import java.awt.event.ActionListener;
    77import java.awt.event.KeyEvent;
     8import java.io.IOException;
     9import java.util.Collection;
    810
    911import javax.swing.AbstractAction;
     
    1921import javax.swing.event.ListSelectionListener;
    2022
     23import org.jdom.JDOMException;
    2124import org.openstreetmap.josm.Main;
    22 import org.openstreetmap.josm.command.DataSet;
    2325import org.openstreetmap.josm.data.GeoPoint;
     26import org.openstreetmap.josm.data.osm.DataSet;
     27import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2428import org.openstreetmap.josm.gui.BookmarkList;
    2529import org.openstreetmap.josm.gui.GBC;
     
    2933import org.openstreetmap.josm.gui.BookmarkList.Bookmark;
    3034import org.openstreetmap.josm.gui.layer.Layer;
    31 import org.openstreetmap.josm.gui.layer.LayerFactory;
     35import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     36import org.openstreetmap.josm.gui.layer.RawGpsDataLayer;
    3237import org.openstreetmap.josm.io.OsmReader;
    33 import org.openstreetmap.josm.io.DataReader.ConnectionException;
    34 import org.openstreetmap.josm.io.DataReader.ParseException;
    3538
    3639/**
     
    8285                        for (JTextField f : latlon)
    8386                                f.setCaretPosition(0);
    84                         rawGps.setSelected(!mv.getActiveLayer().isEditable());
     87                        rawGps.setSelected(mv.getActiveLayer() instanceof RawGpsDataLayer);
    8588                }
    8689
     
    145148                }
    146149                OsmReader osmReader = new OsmReader(Main.pref.osmDataServer,
    147                                 rawGps.isSelected(), b.latlon[0], b.latlon[1], b.latlon[2], b.latlon[3]);
     150                                b.latlon[0], b.latlon[1], b.latlon[2], b.latlon[3]);
    148151                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 
    155152                        String name = latlon[0].getText()+" "+latlon[1].getText()+" x "+
    156153                                        latlon[2].getText()+" "+latlon[3].getText();
    157154                       
    158                         Layer layer = LayerFactory.create(dataSet, name, rawGps.isSelected());
     155                        Layer layer;
     156                        if (rawGps.isSelected()) {
     157                                layer = new RawGpsDataLayer(osmReader.parseRawGps(), name);
     158                        } else {
     159                                DataSet dataSet = osmReader.parseOsm();
     160                                if (dataSet == null)
     161                                        return; // user cancelled download
     162                                if (dataSet.nodes.isEmpty())
     163                                        JOptionPane.showMessageDialog(Main.main, "No data imported.");
     164                               
     165                                Collection<OsmPrimitive> data = Main.main.ds.mergeFrom(dataSet);
     166                                layer = new OsmDataLayer(data, name);
     167                        }
    159168
    160169                        if (Main.main.getMapFrame() == null)
     
    162171                        else
    163172                                Main.main.getMapFrame().mapView.addLayer(layer);
    164                 } catch (ParseException x) {
     173                } catch (JDOMException x) {
    165174                        x.printStackTrace();
    166175                        JOptionPane.showMessageDialog(Main.main, x.getMessage());
    167                 } catch (ConnectionException x) {
     176                } catch (IOException x) {
    168177                        x.printStackTrace();
    169178                        JOptionPane.showMessageDialog(Main.main, x.getMessage());
  • src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java

    r22 r23  
    1212import org.openstreetmap.josm.Main;
    1313import org.openstreetmap.josm.command.AddCommand;
    14 import org.openstreetmap.josm.command.Command;
    1514import org.openstreetmap.josm.data.osm.LineSegment;
    1615import org.openstreetmap.josm.data.osm.Node;
     
    132131                if (start != end) {
    133132                        // try to find a line segment
    134                         for (Track t : Main.main.ds.tracks())
    135                                 for (LineSegment ls : t.segments())
    136                                         if (start == ls.getStart() && end == ls.getEnd()) {
     133                        for (Track t : Main.main.ds.tracks)
     134                                for (LineSegment ls : t.segments)
     135                                        if (start == ls.start && end == ls.end) {
    137136                                                JOptionPane.showMessageDialog(Main.main, "There is already an line segment with the same direction between the selected nodes.");
    138137                                                return;
     
    140139
    141140                        LineSegment ls = new LineSegment(start, end);
    142                         Command c = new AddCommand(ls);
    143                         c.executeCommand();
    144                         Main.main.commands.add(c);
     141                        mv.editLayer().add(new AddCommand(ls));
    145142                }
    146143               
     
    167164                hintDrawn = !hintDrawn;
    168165        }
    169 
    170         @Override
    171         protected boolean isEditMode() {
    172                 return true;
    173         }
    174166}
  • src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java

    r22 r23  
    44import java.awt.event.MouseEvent;
    55
    6 import org.openstreetmap.josm.Main;
    76import org.openstreetmap.josm.command.AddCommand;
    8 import org.openstreetmap.josm.command.Command;
    97import org.openstreetmap.josm.data.osm.Node;
    108import org.openstreetmap.josm.gui.MapFrame;
     
    5149                        Node node = new Node();
    5250                        node.coor = mv.getPoint(e.getX(), e.getY(), true);
    53                         Command c = new AddCommand(node);
    54                         c.executeCommand();
    55                         Main.main.commands.add(c);
     51                        mv.editLayer().add(new AddCommand(node));
    5652                        mv.repaint();
    5753                }
    5854        }
    59 
    60         @Override
    61         protected boolean isEditMode() {
    62                 return true;
    63         }
    6455}
  • src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java

    r22 r23  
    44import java.awt.event.KeyEvent;
    55import java.util.Collection;
     6import java.util.Iterator;
    67import java.util.LinkedList;
    78
    89import org.openstreetmap.josm.Main;
    910import org.openstreetmap.josm.command.AddCommand;
    10 import org.openstreetmap.josm.command.Command;
    1111import org.openstreetmap.josm.data.osm.LineSegment;
    1212import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    9898                for (OsmPrimitive osm : selection) {
    9999                        if (osm instanceof Track)
    100                                 lineSegments.addAll(((Track)osm).segments());
     100                                lineSegments.addAll(((Track)osm).segments);
    101101                        else if (osm instanceof LineSegment)
    102102                                lineSegments.add((LineSegment)osm);
    103103                }
     104               
     105                // sort the line segments in best possible order. This is done by:
     106                // 0  if no elements in list, quit
     107                // 1  taking the first ls as pivot, remove it from list
     108                // 2  searching for a connection at start or end of pivot
     109                // 3  if found, attach it, remove it from list, goto 2
     110                // 4  if not found, save the pivot-string and goto 0
     111                LinkedList<LineSegment> sortedLineSegments = new LinkedList<LineSegment>();
     112                while (!lineSegments.isEmpty()) {
     113                        LinkedList<LineSegment> pivotList = new LinkedList<LineSegment>();
     114                        pivotList.add(lineSegments.getFirst());
     115                        lineSegments.removeFirst();
     116                        for (boolean found = true; found;) {
     117                                found = false;
     118                                for (Iterator<LineSegment> it = lineSegments.iterator(); it.hasNext();) {
     119                                        LineSegment ls = it.next();
     120                                        if (ls.start == pivotList.getLast().end) {
     121                                                pivotList.addLast(ls);
     122                                                it.remove();
     123                                                found = true;
     124                                        } else if (ls.end == pivotList.getFirst().start) {
     125                                                pivotList.addFirst(ls);
     126                                                it.remove();
     127                                                found = true;
     128                                        }
     129                                }
     130                        }
     131                        sortedLineSegments.addAll(pivotList);
     132                }
     133               
    104134                Track t = new Track();
    105                 for (LineSegment ls : lineSegments)
     135                for (LineSegment ls : sortedLineSegments)
    106136                        t.add(ls);
    107                 Command c = new AddCommand(t);
    108                 c.executeCommand();
    109                 Main.main.commands.add(c);
     137                mv.editLayer().add(new AddCommand(t));
    110138                Main.main.ds.clearSelection();
    111139        }
    112 
    113         @Override
    114         protected boolean isEditMode() {
    115                 return true;
    116         }
    117140}
  • src/org/openstreetmap/josm/actions/mapmode/CombineAction.java

    r22 r23  
    1111import org.openstreetmap.josm.Main;
    1212import org.openstreetmap.josm.command.CombineCommand;
    13 import org.openstreetmap.josm.command.Command;
    1413import org.openstreetmap.josm.data.osm.LineSegment;
    1514import org.openstreetmap.josm.data.osm.Node;
     
    150149                else if (first instanceof Track && second instanceof Track && !first.keyPropertiesMergable(second))
    151150                        JOptionPane.showMessageDialog(Main.main, "Cannot combine because of different properties.");
    152                 else {
    153                         Command c = new CombineCommand(first, second);
    154                         c.executeCommand();
    155                         Main.main.commands.add(c);
    156                 }
     151                else
     152                        mv.editLayer().add(new CombineCommand(first, second));
    157153                mv.repaint();
    158154        }
     
    188184                if (osm instanceof LineSegment) {
    189185                        LineSegment ls = (LineSegment)osm;
    190                         Point start = mv.getScreenPoint(ls.getStart().coor);
    191                         Point end = mv.getScreenPoint(ls.getEnd().coor);
    192                         if (Main.main.ds.pendingLineSegments().contains(osm) && g.getColor() == Color.GRAY)
     186                        Point start = mv.getScreenPoint(ls.start.coor);
     187                        Point end = mv.getScreenPoint(ls.end.coor);
     188                        if (Main.main.ds.pendingLineSegments.contains(osm) && g.getColor() == Color.GRAY)
    193189                                g.drawLine(start.x, start.y, end.x, end.y);
    194190                        else
    195191                                g.drawLine(start.x, start.y, end.x, end.y);
    196192                } else if (osm instanceof Track) {
    197                         for (LineSegment ls : ((Track)osm).segments())
     193                        for (LineSegment ls : ((Track)osm).segments)
    198194                                draw(g, ls);
    199195                }
    200196        }
    201 
    202         @Override
    203         protected boolean isEditMode() {
    204                 return true;
    205         }
    206197}
  • src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java

    r22 r23  
    44import java.awt.event.MouseEvent;
    55import java.util.ArrayList;
    6 import java.util.HashMap;
     6import java.util.Collection;
    77import java.util.LinkedList;
    8 import java.util.Map;
    98
    109import javax.swing.JOptionPane;
    1110
    1211import org.openstreetmap.josm.Main;
    13 import org.openstreetmap.josm.data.osm.Key;
     12import org.openstreetmap.josm.command.CombineAndDeleteCommand;
     13import org.openstreetmap.josm.command.DeleteCommand;
     14import org.openstreetmap.josm.command.CombineAndDeleteCommand.LineSegmentCombineEntry;
    1415import org.openstreetmap.josm.data.osm.LineSegment;
    1516import org.openstreetmap.josm.data.osm.Node;
     
    133134                if (osm instanceof Node) {
    134135                        // delete any track and line segment the node is in.
    135                         for (Track t : Main.main.ds.tracks())
    136                                 for (LineSegment ls : t.segments())
    137                                         if (ls.getStart() == osm || ls.getEnd() == osm)
     136                        for (Track t : Main.main.ds.tracks)
     137                                for (LineSegment ls : t.segments)
     138                                        if (ls.start == osm || ls.end == osm)
    138139                                                tracksToDelete.add(t);
    139                         for (LineSegment ls : Main.main.ds.pendingLineSegments())
    140                                 if (ls.getStart() == osm || ls.getEnd() == osm)
     140                        for (LineSegment ls : Main.main.ds.pendingLineSegments)
     141                                if (ls.start == osm || ls.end == osm)
    141142                                        lineSegmentsToDelete.add(ls);
    142143                               
     
    144145                        LineSegment lineSegment = (LineSegment)osm;
    145146                        lineSegmentsToDelete.add(lineSegment);
    146                         for (Track t : Main.main.ds.tracks())
    147                                 for (LineSegment ls : t.segments())
     147                        for (Track t : Main.main.ds.tracks)
     148                                for (LineSegment ls : t.segments)
    148149                                        if (lineSegment == ls)
    149150                                                tracksToDelete.add(t);
     
    154155                ArrayList<Node> checkUnreferencing = new ArrayList<Node>();
    155156                for (Track t : tracksToDelete) {
    156                         for (LineSegment ls : t.segments()) {
    157                                 checkUnreferencing.add(ls.getStart());
    158                                 checkUnreferencing.add(ls.getEnd());
     157                        for (LineSegment ls : t.segments) {
     158                                checkUnreferencing.add(ls.start);
     159                                checkUnreferencing.add(ls.end);
    159160                        }
    160161                }
    161162                for (LineSegment ls : lineSegmentsToDelete) {
    162                         checkUnreferencing.add(ls.getStart());
    163                         checkUnreferencing.add(ls.getEnd());
    164                 }
    165                
    166                 // delete tracks and areas
    167                 for (Track t : tracksToDelete)
    168                         Main.main.ds.removeTrack(t);
    169                 for (LineSegment ls : lineSegmentsToDelete)
    170                         Main.main.ds.destroyPendingLineSegment(ls);
    171 
     163                        checkUnreferencing.add(ls.start);
     164                        checkUnreferencing.add(ls.end);
     165                }
     166               
     167                Collection<OsmPrimitive> deleteData = new LinkedList<OsmPrimitive>();
     168                deleteData.addAll(tracksToDelete);
     169                deleteData.addAll(lineSegmentsToDelete);
    172170                // removing all unreferenced nodes
    173                 for (Node n : checkUnreferencing) {
     171                for (Node n : checkUnreferencing)
    174172                        if (!isReferenced(n))
    175                                 Main.main.ds.nodes.remove(n);
    176                 }
     173                                deleteData.add(n);
    177174                // now, all references are killed. Delete the node (if it was a node)
    178175                if (osm instanceof Node)
    179                         Main.main.ds.nodes.remove(osm);
     176                        deleteData.add(osm);
     177               
     178                mv.editLayer().add(new DeleteCommand(deleteData));
    180179        }
    181180
     
    188187         */
    189188        private void delete(OsmPrimitive osm) {
    190                 if (osm instanceof Node) {
    191                         Node n = (Node)osm;
    192                         if (isReferenced(n)) {
    193                                 String combined = combine(n);
    194                                 if (combined != null) {
    195                                         JOptionPane.showMessageDialog(Main.main, combined);
    196                                         return;
    197                                 }
    198                         }
    199                         // now, the node isn't referenced anymore, so delete it.
    200                         Main.main.ds.nodes.remove(n);
    201                 } else if (osm instanceof LineSegment) {
    202                         LinkedList<Track> tracksToDelete = new LinkedList<Track>();
    203                         for (Track t : Main.main.ds.tracks()) {
    204                                 t.remove((LineSegment)osm);
    205                                 if (t.segments().isEmpty())
    206                                         tracksToDelete.add(t);
    207                         }
    208                         for (Track t : tracksToDelete)
    209                                 Main.main.ds.removeTrack(t);
    210                         Main.main.ds.destroyPendingLineSegment((LineSegment)osm);
    211                 } else if (osm instanceof Track) {
    212                         Main.main.ds.removeTrack((Track)osm);
    213                         for (LineSegment ls : ((Track)osm).segments())
    214                                 Main.main.ds.addPendingLineSegment(ls);
    215                 }
     189                if (osm instanceof Node && isReferenced((Node)osm)) {
     190                        combineAndDelete((Node)osm);
     191                        return;
     192                }
     193                Collection<OsmPrimitive> c = new LinkedList<OsmPrimitive>();
     194                c.add(osm);
     195                mv.editLayer().add(new DeleteCommand(c));
    216196        }
    217197
     
    223203         */
    224204        private boolean isReferenced(Node n) {
    225                 for (Track t : Main.main.ds.tracks())
    226                         for (LineSegment ls : t.segments())
    227                                 if (ls.getStart() == n || ls.getEnd() == n)
     205                for (Track t : Main.main.ds.tracks)
     206                        for (LineSegment ls : t.segments)
     207                                if (ls.start == n || ls.end == n)
    228208                                        return true;
    229                 for (LineSegment ls : Main.main.ds.pendingLineSegments())
    230                         if (ls.getStart() == n || ls.getEnd() == n)
     209                for (LineSegment ls : Main.main.ds.pendingLineSegments)
     210                        if (ls.start == n || ls.end == n)
    231211                                return true;
    232212                // TODO areas
     
    243223         *              are problems combining the node.
    244224         */
    245         private String combine(Node n) {
     225        private void combineAndDelete(Node n) {
    246226                // first, check for pending line segments
    247                 for (LineSegment ls : Main.main.ds.pendingLineSegments())
    248                         if (n == ls.getStart() || n == ls.getEnd())
    249                                 return "Node used by a line segment which is not part of any track. Remove this first.";
     227                for (LineSegment ls : Main.main.ds.pendingLineSegments)
     228                        if (n == ls.start || n == ls.end) {
     229                                JOptionPane.showMessageDialog(Main.main, "Node used by a line segment which is not part of any track. Remove this first.");
     230                                return;
     231                        }
    250232               
    251233                // These line segments must be combined within the track combining
     
    256238                // These line segments are combinable. The inner arraylist has always
    257239                // two elements. The keys maps to the track, the line segments are in.
    258                 HashMap<ArrayList<LineSegment>, Track> lineSegments = new HashMap<ArrayList<LineSegment>, Track>();
    259                
    260                 for (Track t : Main.main.ds.tracks()) {
     240                Collection<LineSegmentCombineEntry> lineSegments = new ArrayList<LineSegmentCombineEntry>();
     241               
     242                for (Track t : Main.main.ds.tracks) {
    261243                        ArrayList<LineSegment> current = new ArrayList<LineSegment>();
    262                         for (LineSegment ls : t.segments())
    263                                 if (ls.getStart() == n || ls.getEnd() == n)
     244                        for (LineSegment ls : t.segments)
     245                                if (ls.start == n || ls.end == n)
    264246                                        current.add(ls);
    265247                        if (!current.isEmpty()) {
    266                                 if (current.size() > 2)
    267                                         return "Node used by more than two line segments.";
     248                                if (current.size() > 2) {
     249                                        JOptionPane.showMessageDialog(Main.main, "Node used by more than two line segments.");
     250                                        return;
     251                                }
    268252                                if (current.size() == 1 &&
    269253                                                (current.get(0) == t.getStartingSegment() || current.get(0) == t.getEndingSegment()))
    270254                                        pendingLineSegmentsForTrack.add(current.get(0));
    271                                 else if (current.get(0).getEnd() != current.get(1).getStart() &&
    272                                                 current.get(1).getEnd() != current.get(0).getStart())
    273                                         return "Node used by line segments that points together.";
    274                                 else if (!current.get(0).keyPropertiesMergable(current.get(1)))
    275                                         return "Node used by line segments with different properties.";
    276                                 else
    277                                         lineSegments.put(current, t);
     255                                else if (current.get(0).end != current.get(1).start &&
     256                                                current.get(1).end != current.get(0).start) {
     257                                        JOptionPane.showMessageDialog(Main.main, "Node used by line segments that points together.");
     258                                        return;
     259                                } else if (!current.get(0).keyPropertiesMergable(current.get(1))) {
     260                                        JOptionPane.showMessageDialog(Main.main, "Node used by line segments with different properties.");
     261                                        return;
     262                                } else {
     263                                        LineSegmentCombineEntry e = new LineSegmentCombineEntry();
     264                                        e.first = current.get(0);
     265                                        e.second = current.get(1);
     266                                        e.track = t;
     267                                        lineSegments.add(e);
     268                                }
    278269                        }
    279270                }
     
    281272                // try to combine tracks
    282273                ArrayList<Track> tracks = new ArrayList<Track>();
    283                 for (Track t : Main.main.ds.tracks())
     274                for (Track t : Main.main.ds.tracks)
    284275                        if (t.getStartingNode() == n || t.getEndingNode() == n)
    285276                                tracks.add(t);
    286277                if (!tracks.isEmpty()) {
    287                         if (tracks.size() > 2)
    288                                 return "Node used by more than two tracks.";
    289                         if (tracks.size() == 1)
    290                                 return "Node used by a track.";
     278                        if (tracks.size() > 2) {
     279                                JOptionPane.showMessageDialog(Main.main, "Node used by more than two tracks.");
     280                                return;
     281                        }
     282                        if (tracks.size() == 1) {
     283                                JOptionPane.showMessageDialog(Main.main, "Node used by a track.");
     284                                return;
     285                        }
    291286                        Track t1 = tracks.get(0);
    292287                        Track t2 = tracks.get(1);
     
    294289                                        t2.getStartingNode() != t1.getEndingNode()) {
    295290                                if (t1.getStartingNode() == t2.getStartingNode() ||
    296                                                 t1.getEndingNode() == t2.getEndingNode())
    297                                         return "Node used by tracks that point together.";
    298                                 return "Node used by tracks that cannot be combined.";
    299                         }
    300                         if (!t1.keyPropertiesMergable(t2))
    301                                 return "Node used by tracks with different properties.";
     291                                                t1.getEndingNode() == t2.getEndingNode()) {
     292                                        JOptionPane.showMessageDialog(Main.main, "Node used by tracks that point together.");
     293                                        return;
     294                                }
     295                                JOptionPane.showMessageDialog(Main.main, "Node used by tracks that cannot be combined.");
     296                                return;
     297                        }
     298                        if (!t1.keyPropertiesMergable(t2)) {
     299                                JOptionPane.showMessageDialog(Main.main, "Node used by tracks with different properties.");
     300                                return;
     301                        }
    302302                }
    303303               
     
    306306                        LineSegment l1 = pendingLineSegmentsForTrack.get(0);
    307307                        LineSegment l2 = pendingLineSegmentsForTrack.get(1);
    308                         if (l1.getStart() == l2.getStart() || l1.getEnd() == l2.getEnd())
    309                                 return "Node used by line segments that points together.";
    310                         if (l1.getStart() == l2.getEnd() || l2.getStart() == l1.getEnd())
     308                        if (l1.start == l2.start || l1.end == l2.end) {
     309                                JOptionPane.showMessageDialog(Main.main, "Node used by line segments that points together.");
     310                                return;
     311                        }
     312                        if (l1.start == l2.end || l2.start == l1.end)
    311313                                pendingLineSegmentsForTrack.clear(); // resolved.
    312314                }
    313315               
    314316                // still pending line segments?
    315                 if (!pendingLineSegmentsForTrack.isEmpty())
    316                         return "Node used by tracks that cannot be combined.";
     317                if (!pendingLineSegmentsForTrack.isEmpty()) {
     318                        JOptionPane.showMessageDialog(Main.main, "Node used by tracks that cannot be combined.");
     319                        return;
     320                }
    317321
    318322                // Ok, we can combine. Do it.
    319                 // line segments
    320                 for (ArrayList<LineSegment> list : lineSegments.keySet()) {
    321                         LineSegment first = list.get(0);
    322                         LineSegment second = list.get(1);
    323                         if (first.getStart() == second.getEnd()) {
    324                                 first = second;
    325                                 second = list.get(0);
    326                         }
    327                         first.setEnd(second.getEnd());
    328                         first.keys = mergeKeys(first.keys, second.keys);
    329                         lineSegments.get(list).remove(second);
    330                 }
    331                
    332                 // tracks
    333                 if (!tracks.isEmpty()) {
    334                         Track first = tracks.get(0);
    335                         Track second = tracks.get(1);
    336                         if (first.getStartingNode() == second.getEndingNode()) {
    337                                 first = second;
    338                                 second = tracks.get(0);
    339                         }
    340                         // concatenate the line segments.
    341                         LineSegment lastOfFirst = first.getEndingSegment();
    342                         LineSegment firstOfSecond = second.getStartingSegment();
    343                         lastOfFirst.setEnd(firstOfSecond.getEnd());
    344                         lastOfFirst.keys = mergeKeys(lastOfFirst.keys, firstOfSecond.keys);
    345                         second.remove(firstOfSecond);
    346                         // move the remaining line segments to first track.
    347                         first.addAll(second.segments());
    348                         Main.main.ds.removeTrack(second);
    349                 }
    350                
    351                 return null;
    352         }
    353 
    354         /**
    355          * Merges the second parameter into the first and return the merged map.
    356          * @param first The first map that will hold keys.
    357          * @param second The map to merge with the first.
    358          * @return The merged key map.
    359          */
    360         private Map<Key, String> mergeKeys(Map<Key, String> first, Map<Key, String> second) {
    361                 if (first == null)
    362                         first = second;
    363                 else if (second != null && first != null)
    364                         first.putAll(second);
    365                 return first;
    366         }
    367 
    368         @Override
    369         protected boolean isEditMode() {
    370                 return true;
     323                Track firstTrack = tracks.isEmpty() ? null : tracks.get(0);
     324                Track secondTrack = tracks.isEmpty() ? null : tracks.get(1);
     325                mv.editLayer().add(new CombineAndDeleteCommand(n, lineSegments, firstTrack, secondTrack));
    371326        }
    372327}
  • src/org/openstreetmap/josm/actions/mapmode/MapMode.java

    r22 r23  
    1313import org.openstreetmap.josm.gui.MapFrame;
    1414import org.openstreetmap.josm.gui.MapView;
    15 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
    16 import org.openstreetmap.josm.gui.layer.Layer;
    1715
    1816/**
     
    5048                this.mapFrame = mapFrame;
    5149                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                 });
    5950        }
    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();
    6651
    6752        /**
  • src/org/openstreetmap/josm/actions/mapmode/MoveAction.java

    r22 r23  
    88
    99import org.openstreetmap.josm.Main;
    10 import org.openstreetmap.josm.command.Command;
    1110import org.openstreetmap.josm.command.MoveCommand;
    1211import org.openstreetmap.josm.data.GeoPoint;
     
    8483
    8584                Collection<OsmPrimitive> selection = Main.main.ds.getSelected();
    86                 Command c = new MoveCommand(selection, dx, dy);
    87                 c.executeCommand();
    88                 Main.main.commands.add(c);
     85                mv.editLayer().add(new MoveCommand(selection, dx, dy));
    8986               
    9087                mv.repaint();
     
    131128                }
    132129        }
    133 
    134         @Override
    135         protected boolean isEditMode() {
    136                 return true;
    137         }
    138130}
  • src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java

    r22 r23  
    9595                mv.repaint();
    9696        }
    97 
    98         @Override
    99         protected boolean isEditMode() {
    100                 return false;
    101         }
    10297}
  • src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java

    r17 r23  
    6868                selectionManager.unregister(mv);
    6969        }
    70 
    71         @Override
    72         protected boolean isEditMode() {
    73                 return false;
    74         }
    7570}
  • src/org/openstreetmap/josm/command/AddCommand.java

    r22 r23  
    4343                SelectionComponentVisitor v = new SelectionComponentVisitor();
    4444                osm.visit(v);
    45                 return new JLabel(v.name, v.icon, JLabel.LEADING);
     45                return new JLabel("Add "+v.name, v.icon, JLabel.LEADING);
    4646        }
    4747       
    4848        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    49                 if (!added.contains(osm))
     49                if (added != null && !added.contains(osm))
    5050                        added.add(osm);
    5151        }
     
    6565        public void visit(LineSegment ls) {
    6666                Main.main.ds.pendingLineSegments.add(ls);
     67                Main.main.ds.addBackReference(ls.start, ls);
     68                Main.main.ds.addBackReference(ls.end, ls);
    6769        }
    6870
     
    7476                Main.main.ds.tracks.add(t);
    7577                for (Iterator<LineSegment> it =  Main.main.ds.pendingLineSegments.iterator(); it.hasNext();)
    76                         if (t.segments().contains(it.next()))
     78                        if (t.segments.contains(it.next()))
    7779                                it.remove();
     80                for (LineSegment ls : t.segments) {
     81                        Main.main.ds.addBackReference(ls, t);
     82                        Main.main.ds.addBackReference(ls.start, t);
     83                        Main.main.ds.addBackReference(ls.end, t);
     84                }
    7885        }
    7986
  • src/org/openstreetmap/josm/command/CombineCommand.java

    r22 r23  
    4646        public void executeCommand() {
    4747                if (del instanceof LineSegment) {
    48                         LineSegment ls = (LineSegment)mod;
    49                         Track t = (Track)del;
    50                         if (!Main.main.ds.pendingLineSegments().contains(ls))
     48                        LineSegment ls = (LineSegment)del;
     49                        Track t = (Track)mod;
     50                        if (!Main.main.ds.pendingLineSegments.contains(ls))
    5151                                throw new IllegalStateException("Should not be able to select non-pending line segments.");
    5252                       
    5353                        Main.main.ds.pendingLineSegments.remove(ls);
    54                         if (t.getStartingNode() != ls.getEnd())
     54                        if (t.getStartingNode() != ls.end)
    5555                                t.add(ls);
    5656                        else
    57                                 t.addStart(ls);
     57                                t.segments.add(0,ls);
    5858                } else {
    5959                        Track t1 = (Track)mod;
    6060                        Track t2 = (Track)del;
    61                         t1.addAll(t2.segments());
     61                        t1.segments.addAll(t2.segments);
    6262                        if (t1.keys == null)
    6363                                t1.keys = t2.keys;
    6464                        else   
    6565                                t1.keys.putAll(t2.keys);
    66                         t2.destroy();
    6766                        Main.main.ds.tracks.remove(t2);
    6867                }
     68                Main.main.ds.rebuildBackReferences();
    6969        }
    7070
     
    8282       
    8383        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    84                 if (!modified.contains(mod))
     84                if (modified != null && !modified.contains(mod))
    8585                        modified.add(mod);
    86                 if (deleted.contains(del))
     86                if (deleted != null && deleted.contains(del))
    8787                        throw new IllegalStateException("Deleted object twice: "+del);
    8888                deleted.add(del);
  • src/org/openstreetmap/josm/command/Command.java

    r22 r23  
    2727        /**
    2828         * Fill in the changed data this command operates on (for sending to the server).
    29          * Add to the lists, don't clear them.
    30          * @param modified  The modified primitives
    31          * @param deleted   The deleted primitives
    32          * @param added         The added primitives
     29         * Add to the lists, don't clear them. The lists can be <code>null</code>
     30         * in which case they are ignored.
     31         *
     32         * @param modified  The modified primitives or <code>null</code>
     33         * @param deleted   The deleted primitives or <code>null</code>
     34         * @param added         The added primitives or <code>null</code>
    3335         */
    3436        void fillModifiedData(Collection<OsmPrimitive> modified,
  • src/org/openstreetmap/josm/command/MoveCommand.java

    r22 r23  
    33import java.awt.Component;
    44import java.util.Collection;
    5 import java.util.HashSet;
    65
    76import javax.swing.JLabel;
     
    98import org.openstreetmap.josm.data.osm.Node;
    109import org.openstreetmap.josm.data.osm.OsmPrimitive;
     10import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
    1111
    1212/**
     
    4949
    5050        public void executeCommand() {
    51                 Collection<Node> movingNodes = new HashSet<Node>();
     51                AllNodesVisitor visitor = new AllNodesVisitor();
    5252                for (OsmPrimitive osm : objects)
    53                         movingNodes.addAll(osm.getAllNodes());
    54                 for (Node n : movingNodes) {
     53                        osm.visit(visitor);
     54                for (Node n : visitor.nodes) {
    5555                        n.coor.x += x;
    5656                        n.coor.y += y;
     
    6565
    6666        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    67                 for (OsmPrimitive osm : objects)
    68                         if (!modified.contains(osm))
    69                                 modified.add(osm);
     67                if (modified != null)
     68                        for (OsmPrimitive osm : objects)
     69                                if (!modified.contains(osm))
     70                                        modified.add(osm);
    7071        }
    7172}
  • src/org/openstreetmap/josm/data/Bounds.java

    r1 r23  
    4545                this.max = max;
    4646        }
     47       
     48        /**
     49         * @return The bounding rectangle that covers <code>this</code> and
     50         *              the <code>other</code> bounds, regarding the x/y values.
     51         */
     52        public Bounds mergeXY(Bounds other) {
     53                GeoPoint nmin = new GeoPoint();
     54                nmin.x = Math.min(min.x, other.min.x);
     55                nmin.y = Math.min(min.y, other.min.y);
     56                GeoPoint nmax = new GeoPoint();
     57                nmax.x = Math.max(max.x, other.max.x);
     58                nmax.y = Math.max(max.y, other.max.y);
     59                return new Bounds(nmin, nmax);
     60        }
     61       
     62        /**
     63         * @return The bounding rectangle that covers <code>this</code> and
     64         *              the <code>other</code> bounds, regarding the lat/lon values.
     65         */
     66        public Bounds mergeLatLon(Bounds other) {
     67                GeoPoint nmin = new GeoPoint(
     68                                Math.min(min.lat, other.min.lat),
     69                                Math.min(min.lon, other.min.lon));
     70                GeoPoint nmax = new GeoPoint(
     71                                Math.max(max.lat, other.max.lat),
     72                                Math.max(max.lon, other.max.lon));
     73                return new Bounds(nmin, nmax);
     74        }
    4775}
  • src/org/openstreetmap/josm/data/Preferences.java

    r20 r23  
    4545         */
    4646        private boolean drawRawGpsLines = false;
     47        /**
     48         * Whether deleted objects should be drawn in a dark color.
     49         */
     50        private boolean drawDeleted = false;
    4751        /**
    4852         * Force the drawing of lines between raw gps points if there are no
     
    134138                        mergeNodes = root.getChild("mergeNodes") != null;
    135139                        drawRawGpsLines = root.getChild("drawRawGpsLines") != null;
     140                        forceRawGpsLines = root.getChild("forceRawGpsLines") != null;
     141                        drawDeleted = root.getChild("drawDeleted") != null;
    136142                } catch (Exception e) {
    137143                        if (e instanceof PreferencesException)
     
    156162                if (drawRawGpsLines)
    157163                        children.add(new Element("drawRawGpsLines"));
     164                if (drawDeleted)
     165                        children.add(new Element("drawDeleted"));
     166                if (forceRawGpsLines)
     167                        children.add(new Element("forceRawGpsLines"));
    158168                Element osmServer = new Element("osm-server");
    159169                osmServer.getChildren().add(new Element("url").setText(osmDataServer));
     
    177187        }
    178188
    179        
    180189        // projection change listener stuff
    181190       
     
    184193         */
    185194        private Collection<PropertyChangeListener> listener = new LinkedList<PropertyChangeListener>();
     195
    186196        /**
    187197         * Add a listener of projection changes to the list of listeners.
     
    246256                return forceRawGpsLines;
    247257        }
     258        public boolean isDrawDeleted() {
     259                return drawDeleted;
     260        }
     261        public void setDrawDeleted(boolean drawDeleted) {
     262                boolean old = this.drawDeleted;
     263                this.drawDeleted = drawDeleted;
     264                firePropertyChanged("drawDeleted", old, drawDeleted);
     265        }
    248266}
  • src/org/openstreetmap/josm/data/osm/DataSet.java

    r22 r23  
    1 package org.openstreetmap.josm.command;
     1package org.openstreetmap.josm.data.osm;
    22
    33import java.util.Collection;
    4 import java.util.Collections;
    54import java.util.HashMap;
    65import java.util.HashSet;
    7 import java.util.Iterator;
    86import java.util.LinkedList;
    97import java.util.Map;
     
    1210import org.openstreetmap.josm.data.Bounds;
    1311import org.openstreetmap.josm.data.SelectionTracker;
    14 import org.openstreetmap.josm.data.osm.LineSegment;
    15 import org.openstreetmap.josm.data.osm.Node;
    16 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    17 import org.openstreetmap.josm.data.osm.Track;
     12import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
    1813
    1914/**
     
    4136         * are in this list but are in no track.
    4237         */
    43         Collection<LineSegment> pendingLineSegments = new LinkedList<LineSegment>();
     38        public Collection<LineSegment> pendingLineSegments = new LinkedList<LineSegment>();
    4439
    4540        /**
     
    5045         * track list.
    5146         */
    52         Collection<Track> tracks = new LinkedList<Track>();
    53 
    54         /**
    55          * Add the track to the tracklist.
    56          */
    57         public void addTrack(Track t) {
    58                 tracks.add(t);
    59         }
    60         /**
    61          * Remove the track from the tracklist.
    62          */
    63         public void removeTrack(Track t) {
    64                 t.destroy();
    65                 tracks.remove(t);
    66         }
    67         /**
    68          * Return a read-only collection of all tracks
    69          */
    70         public Collection<Track> tracks() {
    71                 return Collections.unmodifiableCollection(tracks);
    72         }
    73 
    74         /**
    75          * Add a newly created line segment to the pending lines list.
    76          */
    77         public void addPendingLineSegment(LineSegment ls) {
    78                 pendingLineSegments.add(ls);
    79         }
    80         /**
    81          * Remove a line segment from the pending lines list, because it has been
    82          * assigned to the track.
    83          * @param ls The line segment from the pending list
    84          * @param t The track, that will hold the line segment
    85          * @param end <code>true</code> to attach on the end. <code>false</code>
    86          *              to attach on the beginning.
    87          */
    88         public void assignPendingLineSegment(LineSegment ls, Track t, boolean end) {
    89                 pendingLineSegments.remove(ls);
    90                 if (end)
    91                         t.add(ls);
    92                 else
    93                         t.addStart(ls);
    94         }
    95         /**
    96          * Delete the pending line segment without moving it anywhere.
    97          */
    98         public void destroyPendingLineSegment(LineSegment ls) {
    99                 pendingLineSegments.remove(ls);
    100                 ls.destroy();
    101         }
    102         /**
    103          * Return an read-only iterator over all pending line segments.
    104          */
    105         public Collection<LineSegment> pendingLineSegments() {
    106                 return Collections.unmodifiableCollection(pendingLineSegments);
    107         }
    108 
     47        public Collection<Track> tracks = new LinkedList<Track>();
     48
     49       
     50        /**
     51         * This is a list of all back references of nodes to their track usage.
     52         */
     53        public Map<Node, Set<Track>> nodeTrackRef = new HashMap<Node, Set<Track>>();
     54        /**
     55         * This is a list of all back references of nodes to their line segments.
     56         */
     57        public Map<Node, Set<LineSegment>> nodeLsRef = new HashMap<Node, Set<LineSegment>>();
     58        /**
     59         * This is a list of all back references of lines to their tracks.
     60         */
     61        public Map<LineSegment, Set<Track>> lsTrackRef = new HashMap<LineSegment, Set<Track>>();
     62
     63        /**
     64         * Add a back reference from the node to the line segment.
     65         */
     66        public void addBackReference(Node from, LineSegment to) {
     67                Set<LineSegment> references = nodeLsRef.get(from);
     68                if (references == null)
     69                        references = new HashSet<LineSegment>();
     70                references.add(to);
     71                nodeLsRef.put(from, references);
     72        }
     73        /**
     74         * Add a back reference from the node to the track.
     75         */
     76        public void addBackReference(Node from, Track to) {
     77                Set<Track> references = nodeTrackRef.get(from);
     78                if (references == null)
     79                        references = new HashSet<Track>();
     80                references.add(to);
     81                nodeTrackRef.put(from, references);
     82        }
     83        /**
     84         * Add a back reference from the line segment to the track.
     85         */
     86        public void addBackReference(LineSegment from, Track to) {
     87                Set<Track> references = lsTrackRef.get(from);
     88                if (references == null)
     89                        references = new HashSet<Track>();
     90                references.add(to);
     91                lsTrackRef.put(from, references);
     92        }
     93
     94        /**
     95         * Removes all references to and from this line segment.
     96         */
     97        public void removeBackReference(LineSegment ls) {
     98                Set<LineSegment> s = nodeLsRef.get(ls.start);
     99                if (s != null)
     100                        s.remove(ls);
     101                s = nodeLsRef.get(ls.end);
     102                if (s != null)
     103                        s.remove(ls);
     104                lsTrackRef.remove(ls);
     105        }
     106        /**
     107         * Removes all references to and from the node.
     108         */
     109        public void removeBackReference(Node n) {
     110                nodeLsRef.remove(n);
     111                nodeTrackRef.remove(n);
     112        }
     113        /**
     114         * Removes all references to and from the track.
     115         */
     116        public void removeBackReference(Track t) {
     117                Collection<Node> nodes = AllNodesVisitor.getAllNodes(t);
     118                for (Node n : nodes) {
     119                        Set<Track> s = nodeTrackRef.get(n);
     120                        if (s != null)
     121                                s.remove(t);
     122                }
     123                for (LineSegment ls : t.segments) {
     124                        Set<Track> s = lsTrackRef.get(ls);
     125                        if (s != null)
     126                                s.remove(t);
     127                }
     128        }
     129       
     130        /**
     131         * Rebuild the caches of back references.
     132         */
     133        public void rebuildBackReferences() {
     134                nodeTrackRef.clear();
     135                nodeLsRef.clear();
     136                lsTrackRef.clear();
     137                for (Track t : tracks) {
     138                        for (LineSegment ls : t.segments) {
     139                                addBackReference(ls.start, ls);
     140                                addBackReference(ls.end, ls);
     141                                addBackReference(ls.start, t);
     142                                addBackReference(ls.end, t);
     143                                addBackReference(ls, t);
     144                        }
     145                }
     146                for (LineSegment ls : pendingLineSegments) {
     147                        addBackReference(ls.start, ls);
     148                        addBackReference(ls.end, ls);
     149                }
     150        }
     151       
    109152        /**
    110153         * Return the bounds of this DataSet, depending on X/Y values.
     
    177220                clearSelection(tracks);
    178221                for (Track t : tracks)
    179                         clearSelection(t.segments());
     222                        clearSelection(t.segments);
    180223        }
    181224
     
    190233                sel.addAll(getSelected(tracks));
    191234                for (Track t : tracks)
    192                         sel.addAll(getSelected(t.segments()));
     235                        sel.addAll(getSelected(t.segments));
    193236                return sel;
    194237        }
     
    198241         * The objects imported are not cloned, so from now on, these data belong
    199242         * to both datasets. So use mergeFrom only if you are about to abandon the
    200          * other dataset or this dataset.
     243         * other dataset.
     244         *
     245         * Elements are tried to merged.
     246         * Nodes are merged first, if their lat/lon are equal.
     247         * Line segments are merged, if they have the same nodes.
     248         * Tracs are merged, if they consist of the same line segments.
     249         *
     250         * Additional to that, every two objects with the same id are merged.
    201251         *
    202252         * @param ds    The DataSet to merge into this one.
    203          * @param mergeEqualNodes If <code>true</code>, nodes with the same lat/lon
    204          *              are merged together.
    205          */
    206         public void mergeFrom(DataSet ds, boolean mergeEqualNodes) {
    207                 if (mergeEqualNodes && !nodes.isEmpty()) {
    208                         Map<Node, Node> mergeMap = new HashMap<Node, Node>();
    209                         Set<Node> nodesToAdd = new HashSet<Node>();
    210                         for (Node n : nodes) {
    211                                 for (Iterator<Node> it = ds.nodes.iterator(); it.hasNext();) {
    212                                         Node dsn = it.next();
    213                                         if (n.coor.equalsLatLon(dsn.coor)) {
    214                                                 mergeMap.put(dsn, n);
    215                                                 n.mergeFrom(dsn);
    216                                                 it.remove();
    217                                         } else {
    218                                                 nodesToAdd.add(dsn);
    219                                         }
     253         * @return A list of all primitives that were used in the conjunction. That
     254         *              is all used primitives (the merged primitives and all added ones).
     255         */
     256        public Collection<OsmPrimitive> mergeFrom(DataSet ds) {
     257                Collection<OsmPrimitive> data = new LinkedList<OsmPrimitive>();
     258
     259                Set<LineSegment> myLineSegments = new HashSet<LineSegment>();
     260                myLineSegments.addAll(pendingLineSegments);
     261                for (Track t : tracks)
     262                        myLineSegments.addAll(t.segments);
     263               
     264                Set<LineSegment> otherLineSegments = new HashSet<LineSegment>();
     265                otherLineSegments.addAll(ds.pendingLineSegments);
     266                for (Track t : ds.tracks)
     267                        otherLineSegments.addAll(t.segments);
     268               
     269               
     270                // merge nodes
     271
     272                Map<Node, Node> nodeMap = new HashMap<Node, Node>();
     273                // find mergable
     274                for (Node otherNode : ds.nodes)
     275                        for (Node myNode : nodes)
     276                                if (otherNode.coor.equalsLatLon(myNode.coor))
     277                                        nodeMap.put(otherNode, myNode);
     278                // add
     279                data.addAll(new HashSet<Node>(nodeMap.values()));
     280                for (Node n : ds.nodes) {
     281                        if (!nodeMap.containsKey(n)) {
     282                                nodes.add(n);
     283                                data.add(n);
     284                        }
     285                }
     286                // reassign
     287                for (LineSegment ls : otherLineSegments) {
     288                        Node n = nodeMap.get(ls.start);
     289                        if (n != null)
     290                                ls.start = n;
     291                        n = nodeMap.get(ls.end);
     292                        if (n != null)
     293                                ls.end = n;
     294                }
     295
     296
     297                // merge line segments
     298
     299                Map<LineSegment, LineSegment> lsMap = new HashMap<LineSegment, LineSegment>();
     300                // find mergable
     301                for (LineSegment otherLS : otherLineSegments)
     302                        for (LineSegment myLS : myLineSegments)
     303                                if (otherLS.start == myLS.start && otherLS.end == myLS.end)
     304                                        lsMap.put(otherLS, myLS);
     305                // add pendings (ls from track are added later
     306                for (LineSegment ls : ds.pendingLineSegments) {
     307                        if (!lsMap.containsKey(ls)) {
     308                                pendingLineSegments.add(ls);
     309                                data.add(ls);
     310                        }
     311                }
     312                // reassign
     313                for (Track t : ds.tracks) {
     314                        for (int i = 0; i < t.segments.size(); ++i) {
     315                                LineSegment newLS = lsMap.get(t.segments.get(i));
     316                                if (newLS != null)
     317                                        t.segments.set(i, newLS);
     318                        }
     319                }
     320               
     321               
     322                // merge tracks
     323                LinkedList<Track> trackToAdd = new LinkedList<Track>();
     324                for (Track otherTrack : ds.tracks) {
     325                        boolean found = false;
     326                        for (Track myTrack : tracks) {
     327                                if (myTrack.segments.equals(otherTrack.segments)) {
     328                                        found = true;
     329                                        data.add(myTrack);
     330                                        break;
    220331                                }
    221332                        }
    222                         nodes.addAll(nodesToAdd);
    223                         for (Track t : ds.tracks) {
    224                                 for (LineSegment ls : t.segments()) {
    225                                         Node n = mergeMap.get(ls.getStart());
    226                                         if (n != null)
    227                                                 ls.start = n;
    228                                         n = mergeMap.get(ls.getEnd());
    229                                         if (n != null)
    230                                                 ls.end = n;
    231                                 }
    232                         }
    233                         tracks.addAll(ds.tracks);
    234                         for (LineSegment ls : ds.pendingLineSegments) {
    235                                 Node n = mergeMap.get(ls.getStart());
    236                                 if (n != null)
    237                                         ls.start = n;
    238                                 n = mergeMap.get(ls.getEnd());
    239                                 if (n != null)
    240                                         ls.end = n;
    241                         }
    242                         pendingLineSegments.addAll(ds.pendingLineSegments);
    243                 } else {
    244                         nodes.addAll(ds.nodes);
    245                         tracks.addAll(ds.tracks);
    246                         pendingLineSegments.addAll(ds.pendingLineSegments);
    247                 }
     333                        if (!found)
     334                                trackToAdd.add(otherTrack);
     335                }
     336                data.addAll(trackToAdd);
     337                tracks.addAll(trackToAdd);
     338
     339                rebuildBackReferences();
     340                return data;
    248341        }
    249342
  • src/org/openstreetmap/josm/data/osm/Key.java

    r9 r23  
    11package org.openstreetmap.josm.data.osm;
    22
    3 import java.util.Collection;
    43import java.util.HashMap;
    5 import java.util.LinkedList;
    64import java.util.Map;
    75
     
    4947        }
    5048       
    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 
    5949        @Override
    6050        public void visit(Visitor visitor) {
  • src/org/openstreetmap/josm/data/osm/LineSegment.java

    r21 r23  
    11package org.openstreetmap.josm.data.osm;
    2 
    3 import java.util.Collection;
    4 import java.util.Collections;
    5 import java.util.LinkedList;
    62
    73import org.openstreetmap.josm.data.osm.visitor.Visitor;
     
    2622
    2723        /**
    28          * The tracks, this line segment is part of.
    29          */
    30         transient Collection<Track> parent = new LinkedList<Track>();
    31 
    32         /**
    3324         * Create an line segment from the given starting and ending node
    3425         * @param start Starting node of the line segment.
     
    3829                this.start = start;
    3930                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         public 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;
    8531        }
    8632
  • src/org/openstreetmap/josm/data/osm/Node.java

    r17 r23  
    11package org.openstreetmap.josm.data.osm;
    2 
    3 import java.util.Collection;
    4 import java.util.Collections;
    5 import java.util.LinkedList;
    62
    73import org.openstreetmap.josm.data.GeoPoint;
     
    2117        public GeoPoint coor;
    2218
    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 
    6219        @Override
    6320        public void visit(Visitor visitor) {
  • src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r22 r23  
    11package org.openstreetmap.josm.data.osm;
    22
    3 import java.util.Collection;
    43import java.util.Map;
    54
     
    2019         */
    2120        public Map<Key, String> keys;
    22        
     21
     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.
     26         */
     27        public long id = 0;
     28
    2329        /**
    2430         * If set to true, this object has been modified in the current session.
     
    3036         */
    3137        transient private boolean selected = false;
    32 
    33         /**
    34          * Return a list of all nodes, this osmPrimitive consists of. Does return
    35          * an empty list, if it is an primitive that cannot have nodes (e.g. Key)
    36          * TODO replace with visitor
    37          */
    38         abstract public Collection<Node> getAllNodes();
    3938
    4039        /**
  • src/org/openstreetmap/josm/data/osm/Track.java

    r21 r23  
    22
    33import java.util.ArrayList;
    4 import java.util.Collection;
    5 import java.util.Collections;
    64import java.util.List;
    75
     
    1816         * All track segments in this track
    1917         */
    20         private final List<LineSegment> segments = new ArrayList<LineSegment>();
     18        public final List<LineSegment> segments = new ArrayList<LineSegment>();
    2119
    2220       
     
    2624        public void add(LineSegment ls) {
    2725                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         public void destroy() {
    83                 for (LineSegment ls : segments) {
    84                         ls.parent.remove(this);
    85                         if (ls.parent.isEmpty())
    86                                 ls.destroy();
    87                 }
    88                 segments.clear();
    8926        }
    9027
     
    10138                if (segments.isEmpty())
    10239                        return null;
    103                 return segments.get(segments.size()-1).getEnd();
     40                return segments.get(segments.size()-1).end;
    10441        }
    10542       
     
    12663                if (segments.isEmpty())
    12764                        return null;
    128                 return segments.get(0).getStart();
     65                return segments.get(0).start;
    12966        }
    13067       
  • src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java

    r21 r23  
    4747                String name = getName(ls.keys);
    4848                if (name == null)
    49                         name = "("+ls.getStart().coor.lat+","+ls.getStart().coor.lon+") -> ("+ls.getEnd().coor.lat+","+ls.getEnd().coor.lon+")";
     49                        name = "("+ls.start.coor.lat+","+ls.start.coor.lon+") -> ("+ls.end.coor.lat+","+ls.end.coor.lon+")";
    5050                       
    5151                this.name = name;
     
    7474                if (name == null) {
    7575                        Set<Node> nodes = new HashSet<Node>();
    76                         for (LineSegment ls : t.segments()) {
    77                                 nodes.add(ls.getStart());
    78                                 nodes.add(ls.getEnd());
     76                        for (LineSegment ls : t.segments) {
     77                                nodes.add(ls.start);
     78                                nodes.add(ls.end);
    7979                        }
    8080                        name = "("+nodes.size()+" nodes)";
  • src/org/openstreetmap/josm/data/projection/Projection.java

    r22 r23  
    88import javax.swing.event.ChangeListener;
    99
     10import org.openstreetmap.josm.data.Bounds;
    1011import org.openstreetmap.josm.data.GeoPoint;
    1112
     
    7071
    7172        /**
    72          * Initialize itself with the given dataSet.
     73         * Initialize itself with the given bounding rectangle (regarding lat/lon).
    7374         *
    7475         * This function should initialize own parameters needed to do the
     
    8182         * to initialize their data members.
    8283         */
    83         public void init() {}
     84        public void init(Bounds b) {}
    8485       
    8586        /**
  • src/org/openstreetmap/josm/data/projection/UTM.java

    r22 r23  
    186186         * @author imi
    187187         */
    188         private class ZoneData {
     188        private static class ZoneData {
    189189                int zone = 0;
    190190                Hemisphere hemisphere = Hemisphere.north;
     
    194194         * @return The zone data extrakted from the dataset.
    195195         */
    196         ZoneData autoDetect() {
     196        ZoneData autoDetect(Bounds b) {
    197197                ZoneData zd = new ZoneData();
    198                
    199                 Bounds b = Main.main.ds.getBoundsLatLon();
    200198                if (b == null)
    201199                        return zd;
     
    232230         */
    233231        @Override
    234         public void init() {
     232        public void init(Bounds b) {
    235233                if (zone == 0) {
    236                         ZoneData zd = autoDetect();
     234                        ZoneData zd = autoDetect(b);
    237235                        zone = zd.zone;
    238236                        hemisphere = zd.hemisphere;
     
    272270                        public void actionPerformed(ActionEvent e) {
    273271                                if (Main.main.getMapFrame() != null) {
    274                                         ZoneData zd = autoDetect();
     272                                        ZoneData zd = autoDetect(Main.main.ds.getBoundsLatLon());
    275273                                        if (zd.zone == 0)
    276274                                                JOptionPane.showMessageDialog(Main.main, "Autodetection failed. Maybe the data set contain too few information.");
  • src/org/openstreetmap/josm/gui/MapView.java

    r22 r23  
    1818
    1919import org.openstreetmap.josm.Main;
    20 import org.openstreetmap.josm.command.DataSet;
    2120import org.openstreetmap.josm.data.Bounds;
    2221import org.openstreetmap.josm.data.GeoPoint;
     
    2625import org.openstreetmap.josm.data.osm.Track;
    2726import org.openstreetmap.josm.data.projection.Projection;
     27import org.openstreetmap.josm.gui.layer.EditLayer;
    2828import org.openstreetmap.josm.gui.layer.Layer;
    2929
     
    7272        private ArrayList<Layer> layers = new ArrayList<Layer>();
    7373        /**
     74         * Direct link to the edit layer (if any) in the layers list.
     75         */
     76        private EditLayer editLayer;
     77        /**
    7478         * The layer from the layers list that is currently active.
    7579         */
     
    98102                addLayer(layer);
    99103                Main.pref.addPropertyChangeListener(this);
    100 
    101                 // init screen
    102                 recalculateCenterScale();
    103104        }
    104105
     
    108109         */
    109110        public void addLayer(Layer layer) {
     111                if (layer instanceof EditLayer) {
     112                        if (editLayer != null) {
     113                                // there can only be one EditLayer
     114                                editLayer.mergeFrom(layer);
     115                                return;
     116                        }
     117                        editLayer = (EditLayer)layer;
     118                }
     119               
    110120                layers.add(0,layer);
    111121
    112                 if (layer.dataSet != null) {
    113                         // initialize the projection if it was the first layer
    114                         if (layers.size() == 1)
    115                                 Main.pref.getProjection().init();
    116                        
    117                         // initialize the dataset in the new layer
    118                         for (Node n : layer.dataSet.nodes)
    119                                 Main.pref.getProjection().latlon2xy(n.coor);
    120                 }
     122                // initialize the projection if it is the first layer
     123                if (layers.size() == 1)
     124                        Main.pref.getProjection().init(layer.getBoundsLatLon());
     125
     126                // reinitialize layer's data
     127                layer.init(Main.pref.getProjection());
    121128
    122129                for (LayerChangeListener l : listeners)
     
    125132                setActiveLayer(layer);
    126133        }
    127        
     134
    128135        /**
    129136         * Remove the layer from the mapview. If the layer was in the list before,
     
    239246               
    240247                // pending line segments
    241                 for (LineSegment ls : Main.main.ds.pendingLineSegments()) {
    242                         Point A = getScreenPoint(ls.getStart().coor);
    243                         Point B = getScreenPoint(ls.getEnd().coor);
     248                for (LineSegment ls : Main.main.ds.pendingLineSegments) {
     249                        Point A = getScreenPoint(ls.start.coor);
     250                        Point B = getScreenPoint(ls.end.coor);
    244251                        double c = A.distanceSq(B);
    245252                        double a = p.distanceSq(B);
     
    254261                // tracks & line segments
    255262                minDistanceSq = Double.MAX_VALUE;
    256                 for (Track t : Main.main.ds.tracks()) {
    257                         for (LineSegment ls : t.segments()) {
    258                                 Point A = getScreenPoint(ls.getStart().coor);
    259                                 Point B = getScreenPoint(ls.getEnd().coor);
     263                for (Track t : Main.main.ds.tracks) {
     264                        for (LineSegment ls : t.segments) {
     265                                Point A = getScreenPoint(ls.start.coor);
     266                                Point B = getScreenPoint(ls.end.coor);
    260267                                double c = A.distanceSq(B);
    261268                                double a = p.distanceSq(B);
     
    323330                // reset all datasets.
    324331                Projection p = Main.pref.getProjection();
    325                 for (Layer l : layers) {
    326                         DataSet ds = l.dataSet;
    327                         if (ds != null)
    328                                 for (Node n : ds.nodes)
    329                                         p.latlon2xy(n.coor);
    330                 }
     332                for (Node n : Main.main.ds.nodes)
     333                        p.latlon2xy(n.coor);
    331334                recalculateCenterScale();
    332335        }
     
    399402                                h = 20;
    400403                       
    401                         Bounds bounds = Main.main.ds.getBoundsXY();
    402                        
     404                        Bounds bounds = null;
     405                        for (Layer l : layers) {
     406                                if (bounds == null)
     407                                        bounds = l.getBoundsXY();
     408                                else
     409                                        bounds = bounds.mergeXY(l.getBoundsXY());
     410                        }
     411
    403412                        boolean oldAutoScale = autoScale;
    404413                        GeoPoint oldCenter = center;
     
    460469                activeLayer = layer;
    461470                if (old != layer) {
    462                         if (old != null && old.dataSet != null)
    463                                 old.dataSet.clearSelection();
    464471                        for (LayerChangeListener l : listeners)
    465472                                l.activeLayerChange(old, layer);
     
    474481                return activeLayer;
    475482        }
     483
     484        /**
     485         * @return The current edit layer. If no edit layer exist, one is created.
     486         *              So editLayer does never return <code>null</code>.
     487         */
     488        public EditLayer editLayer() {
     489                if (editLayer == null)
     490                        addLayer(new EditLayer(this));
     491                return editLayer;
     492        }
    476493}
  • src/org/openstreetmap/josm/gui/PreferenceDialog.java

    r22 r23  
    6262                        Main.pref.setDrawRawGpsLines(drawRawGpsLines.isSelected());
    6363                        Main.pref.setForceRawGpsLines(forceRawGpsLines.isSelected());
     64                        Main.pref.setDrawDeleted(drawDeleted.isSelected());
    6465                        try {
    6566                                Main.pref.save();
     
    125126         */
    126127        JCheckBox forceRawGpsLines = new JCheckBox("Force lines if no line segments imported.");
     128        /**
     129         * The checkbox stating whether deleted nodes should be drawn.
     130         */
     131        JCheckBox drawDeleted = new JCheckBox("Draw deleted lines.");
    127132        /**
    128133         * The checkbox stating whether nodes should be merged together.
     
    198203                forceRawGpsLines.setSelected(Main.pref.isForceRawGpsLines());
    199204                forceRawGpsLines.setEnabled(drawRawGpsLines.isSelected());
     205                drawDeleted.setToolTipText("Draw dark hints where objects were deleted.");
     206                drawDeleted.setSelected(Main.pref.isDrawDeleted());
    200207                mergeNodes.setToolTipText("When importing GPX data, all nodes with exact the same lat/lon are merged.");
    201208                mergeNodes.setSelected(Main.pref.mergeNodes);
     
    212219                display.add(drawRawGpsLines, GBC.eol().insets(20,0,0,0));
    213220                display.add(forceRawGpsLines, GBC.eol().insets(40,0,0,0));
     221                display.add(drawDeleted, GBC.eol().insets(20,0,0,0));
    214222                display.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
    215223
  • src/org/openstreetmap/josm/gui/SelectionManager.java

    r22 r23  
    278278                       
    279279                        // pending line segments
    280                         for (LineSegment ls : Main.main.ds.pendingLineSegments())
     280                        for (LineSegment ls : Main.main.ds.pendingLineSegments)
    281281                                if (rectangleContainLineSegment(r, alt, ls))
    282282                                        selection.add(ls);
    283283
    284284                        // tracks
    285                         for (Track t : Main.main.ds.tracks()) {
    286                                 boolean wholeTrackSelected = !t.segments().isEmpty();
    287                                 for (LineSegment ls : t.segments())
     285                        for (Track t : Main.main.ds.tracks) {
     286                                boolean wholeTrackSelected = !t.segments.isEmpty();
     287                                for (LineSegment ls : t.segments)
    288288                                        if (rectangleContainLineSegment(r, alt, ls))
    289289                                                selection.add(ls);
     
    310310        private boolean rectangleContainLineSegment(Rectangle r, boolean alt, LineSegment ls) {
    311311                if (alt) {
    312                         Point p1 = mv.getScreenPoint(ls.getStart().coor);
    313                         Point p2 = mv.getScreenPoint(ls.getEnd().coor);
     312                        Point p1 = mv.getScreenPoint(ls.start.coor);
     313                        Point p2 = mv.getScreenPoint(ls.end.coor);
    314314                        if (r.intersectsLine(p1.x, p1.y, p2.x, p2.y))
    315315                                return true;
    316316                } else {
    317                         if (r.contains(mv.getScreenPoint(ls.getStart().coor))
    318                                         && r.contains(mv.getScreenPoint(ls.getEnd().coor)))
     317                        if (r.contains(mv.getScreenPoint(ls.start.coor))
     318                                        && r.contains(mv.getScreenPoint(ls.end.coor)))
    319319                                return true;
    320320                }
  • src/org/openstreetmap/josm/gui/dialogs/LayerList.java

    r22 r23  
    88import java.awt.event.ActionListener;
    99import java.awt.event.KeyEvent;
    10 import java.io.IOException;
    1110import java.util.Collection;
    1211
     
    1716import javax.swing.JLabel;
    1817import javax.swing.JList;
    19 import javax.swing.JOptionPane;
    2018import javax.swing.JPanel;
    2119import javax.swing.JScrollPane;
     
    2624
    2725import org.openstreetmap.josm.Main;
    28 import org.openstreetmap.josm.command.DataSet;
    2926import org.openstreetmap.josm.gui.ImageProvider;
    3027import org.openstreetmap.josm.gui.MapFrame;
     
    3229import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
    3330import org.openstreetmap.josm.gui.layer.Layer;
    34 import org.openstreetmap.josm.io.OsmWriter;
    3531
    3632/**
     
    7268         */
    7369        private JButton deleteButton = new JButton(ImageProvider.get("dialogs", "delete"));
    74         /**
    75          * Button for connecting disconnecting to the server.
    76          */
    77         private JButton uploadButton = new JButton(ImageProvider.get("dialogs", "condiscon"));
    7870
    7971        /**
     
    9688                                        icon = ImageProvider.overlay(icon, invisible, ImageProvider.OverlayPosition.SOUTHEAST);
    9789                                label.setIcon(icon);
    98 
    99                                 DataSet ds = layer.dataSet;
    100                                 if (ds != null) {
    101                                         label.setToolTipText(ds.nodes.size()+" nodes, "+
    102                                                         ds.tracks().size()+" tracks");
    103                                 }
     90                                label.setToolTipText(layer.getToolTipText());
    10491                                return label;
    10592                        }
     
    182169                        public void actionPerformed(ActionEvent e) {
    183170                                Layer lFrom = (Layer)layers.getSelectedValue();
    184                                 DataSet dsFrom = lFrom.dataSet;
    185171                                Layer lTo = (Layer)model.get(layers.getSelectedIndex()+1);
    186                                 DataSet dsTo = lTo.dataSet;
    187                                 dsTo.mergeFrom(dsFrom, Main.pref.mergeNodes);
     172                                lTo.mergeFrom(lFrom);
    188173                                layers.setSelectedValue(lTo, true);
    189174                                mapView.removeLayer(lFrom);
     
    192177                buttonPanel.add(mergeButton);
    193178
    194                 uploadButton.setToolTipText("Upload changes to the server.");
    195                 uploadButton.addActionListener(new ActionListener(){
    196                         public void actionPerformed(ActionEvent e) {
    197                                 OsmWriter con = new OsmWriter(Main.pref.osmDataServer, Main.main.commands);
    198                                 try {
    199                                         con.output();
    200                                 } catch (IOException x) {
    201                                         x.printStackTrace();
    202                                         JOptionPane.showMessageDialog(Main.main, "Not all changes could be uploaded.");
    203                                 }
    204                         }
    205                 });
    206                 buttonPanel.add(uploadButton);
    207                
    208179                add(buttonPanel, BorderLayout.SOUTH);
    209180               
     
    219190                boolean enable = model.getSize() > 1;
    220191                enable = enable && sel < model.getSize()-1;
    221                 enable = enable && l.dataSet != null;
    222                 enable = enable && ((Layer)model.get(sel+1)).dataSet != null;
    223                 enable = enable && l.isEditable() == ((Layer)model.get(sel+1)).isEditable();
     192                enable = enable && l.isMergable((Layer)model.get(sel+1));
    224193                mergeButton.setEnabled(enable);
    225194                upButton.setEnabled(sel > 0);
  • src/org/openstreetmap/josm/gui/layer/Layer.java

    r22 r23  
    55import javax.swing.Icon;
    66
     7import org.openstreetmap.josm.data.Bounds;
     8import org.openstreetmap.josm.data.projection.Projection;
    79import org.openstreetmap.josm.gui.MapView;
    810
     
    3234         */
    3335        public final String name;
    34        
     36
    3537        /**
    3638         * Create the layer and fill in the necessary components.
     
    5254
    5355        /**
    54          * @return <code>true</code>, if the map data can be edited.
     56         * @return A small tooltip hint about some statistics for this layer.
    5557         */
    56         public boolean isEditable() {
    57                 return false;
    58         }
     58        abstract public String getToolTipText();
     59
     60        /**
     61         * Merges the given layer into this layer. Throws if the layer types are
     62         * incompatible.
     63         * @param from The layer that get merged into this one. After the merge,
     64         *              the other layer is not usable anymore and passing to one others
     65         *              mergeFrom should be one of the last things to do with a layer.
     66         */
     67        abstract public void mergeFrom(Layer from);
     68       
     69        /**
     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.
     72         */
     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);
    5993}
  • src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java

    r22 r23  
    11package org.openstreetmap.josm.gui.layer;
    22
    3 import java.awt.Color;
    43import java.awt.Graphics;
    5 import java.awt.Point;
    64import java.util.Collection;
    7 import java.util.HashSet;
    85
    96import javax.swing.Icon;
    107
    11 import org.openstreetmap.josm.Main;
    12 import org.openstreetmap.josm.data.osm.Key;
    13 import org.openstreetmap.josm.data.osm.LineSegment;
     8import org.openstreetmap.josm.data.Bounds;
    149import org.openstreetmap.josm.data.osm.Node;
    1510import org.openstreetmap.josm.data.osm.OsmPrimitive;
    16 import org.openstreetmap.josm.data.osm.Track;
    17 import org.openstreetmap.josm.data.osm.visitor.Visitor;
     11import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
     12import org.openstreetmap.josm.data.osm.visitor.BoundingVisitor;
     13import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor;
     14import org.openstreetmap.josm.data.projection.Projection;
    1815import org.openstreetmap.josm.gui.ImageProvider;
    1916import org.openstreetmap.josm.gui.MapView;
     
    2623 * @author imi
    2724 */
    28 public class OsmDataLayer extends Layer implements Visitor {
     25public class OsmDataLayer extends Layer {
    2926
    3027        private static Icon icon;
    31         private final static Color darkblue = new Color(0,0,128);
    32         private final static Color darkgreen = new Color(0,128,0);
    3328
    3429        /**
     
    3833
    3934        /**
    40          * The mapview we are currently drawing on.
    41          */
    42         private MapView mv;
    43         /**
    44          * The graphic environment we are drawing with.
    45          */
    46         private Graphics g;
    47        
    48         /**
    4935         * Construct a OsmDataLayer.
    5036         */
    51         protected OsmDataLayer(Collection<OsmPrimitive> data, String name) {
     37        public OsmDataLayer(Collection<OsmPrimitive> data, String name) {
    5238                super(name);
    5339                this.data = data;
     
    6551        }
    6652
     53        /**
     54         * Draw all primitives in this layer but do not draw modified ones (they
     55         * are drawn by the edit layer).
     56         * Draw nodes last to overlap the line segments they belong to.
     57         */
    6758        @Override
    68         public boolean isEditable() {
    69                 return true;
     59        public void paint(Graphics g, MapView mv) {
     60                SimplePaintVisitor visitor = new SimplePaintVisitor(g, mv, null);
     61                // first draw the tracks (and line segments)
     62                for (OsmPrimitive osm : data)
     63                        if (!osm.modified && !(osm instanceof Node))
     64                                osm.visit(visitor);
     65                for (OsmPrimitive osm : data)
     66                        if (!osm.modified && osm instanceof Node)
     67                                osm.visit(visitor);
    7068        }
    7169
    7270        @Override
    73         public void paint(Graphics g, MapView mv) {
    74                 this.mv = mv;
    75                 this.g = g;
    76                 for (OsmPrimitive osm : data)
    77                         osm.visit(this);
     71        public String getToolTipText() {
     72                return data.size()+" primitives.";
    7873        }
    7974
    80         /**
    81          * Draw a small rectangle.
    82          *
    83          * - White if selected (as always)
    84          * - Yellow, if not used by any tracks or areas.
    85          * - Green, if only used by pending line segments.
    86          * - Darkblue, if used in tracks but are only as inbound node. Inbound are
    87          *   all nodes, that have only line segments of the same track and
    88          *   at least two different line segments attached.
    89          * - Red otherwise (means, this is a dead end or is part of more than
    90          *   one track).
    91          *
    92          * @param n The node to draw.
    93          */
    94         public void visit(Node n) {
    95                 if (n.isSelected()) {
    96                         drawNode(n, Color.WHITE); // selected
    97                         return;
    98                 }
    99 
    100                 Collection<LineSegment> lineSegments = n.getParentSegments();
    101                 if (lineSegments.isEmpty()) {
    102                         drawNode(n, Color.YELLOW); // single waypoint only
    103                         return;
    104                 }
    105                
    106                 HashSet<Track> tracks = new HashSet<Track>();
    107                 for (LineSegment ls : lineSegments)
    108                         tracks.addAll(ls.getParents());
    109                 if (tracks.isEmpty()) {
    110                         drawNode(n, Color.GREEN); // pending line
    111                         return;
    112                 }
    113                 if (tracks.size() > 1) {
    114                         drawNode(n, Color.RED); // more than one track
    115                         return;
    116                 }
    117                 int segmentUsed = 0;
    118                 for (LineSegment ls : tracks.iterator().next().segments())
    119                         if (n == ls.getStart() || n == ls.getEnd())
    120                                 ++segmentUsed;
    121                 drawNode(n, segmentUsed > 1 ? darkblue : Color.RED);
     75        @Override
     76        public void mergeFrom(Layer from) {
     77                OsmDataLayer layer = (OsmDataLayer)from;
     78                data.addAll(layer.data);
    12279        }
    12380
    124         public void visit(LineSegment ls) {
    125                 g.setColor(ls.isSelected() ? Color.WHITE : darkblue);
    126                 if (Main.main.ds.pendingLineSegments().contains(ls))
    127                         g.setColor(darkgreen);
    128                 Point p1 = mv.getScreenPoint(ls.getStart().coor);
    129                 Point p2 = mv.getScreenPoint(ls.getEnd().coor);
    130                 g.drawLine(p1.x, p1.y, p2.x, p2.y);
     81        @Override
     82        public boolean isMergable(Layer other) {
     83                return other instanceof OsmDataLayer;
    13184        }
    13285
    133         /**
    134          * Draw a darkblue line for all line segments.
    135          * @param t The track to draw.
    136          */
    137         public void visit(Track t) {
    138                 for (LineSegment ls : t.segments())
    139                         ls.visit(this);
     86        @Override
     87        public Bounds getBoundsLatLon() {
     88                BoundingVisitor b = new BoundingVisitor(BoundingVisitor.Type.LATLON);
     89                for (OsmPrimitive osm : data)
     90                        osm.visit(b);
     91                return b.bounds;
    14092        }
    14193
    142         public void visit(Key k) {
     94        @Override
     95        public Bounds getBoundsXY() {
     96                BoundingVisitor b = new BoundingVisitor(BoundingVisitor.Type.XY);
     97                for (OsmPrimitive osm : data)
     98                        osm.visit(b);
     99                return b.bounds;
    143100        }
    144        
    145         /**
    146          * Draw the node as small rectangle with the given color.
    147          *
    148          * @param n             The node to draw.
    149          * @param color The color of the node.
    150          */
    151         private void drawNode(Node n, Color color) {
    152                 Point p = mv.getScreenPoint(n.coor);
    153                 g.setColor(color);
    154                 g.drawRect(p.x-1, p.y-1, 2, 2);
     101
     102        @Override
     103        public void init(Projection projection) {
     104                for (OsmPrimitive osm : data)
     105                        for (Node n : AllNodesVisitor.getAllNodes(osm))
     106                                projection.latlon2xy(n.coor);
    155107        }
    156108}
  • src/org/openstreetmap/josm/gui/layer/RawGpsDataLayer.java

    r22 r23  
    11package org.openstreetmap.josm.gui.layer;
     2
     3import java.awt.Color;
     4import java.awt.Graphics;
     5import java.awt.Point;
     6import java.beans.PropertyChangeEvent;
     7import java.beans.PropertyChangeListener;
     8import java.util.Collection;
    29
    310import javax.swing.Icon;
    411
    5 import org.openstreetmap.josm.command.DataSet;
     12import org.openstreetmap.josm.Main;
     13import org.openstreetmap.josm.data.Bounds;
     14import org.openstreetmap.josm.data.GeoPoint;
     15import org.openstreetmap.josm.data.projection.Projection;
    616import org.openstreetmap.josm.gui.ImageProvider;
     17import org.openstreetmap.josm.gui.MapView;
    718
    819/**
     
    1627        private static Icon icon;
    1728
    18         protected RawGpsDataLayer(DataSet dataSet, String name) {
     29        /**
     30         * A list of tracks which containing a list of points.
     31         */
     32        private final Collection<Collection<GeoPoint>> data;
     33
     34        public RawGpsDataLayer(Collection<Collection<GeoPoint>> data, String name) {
    1935                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                });
    2048        }
    2149
     
    2957                return icon;
    3058        }
     59
     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);
     144        }
    31145}
  • src/org/openstreetmap/josm/io/GpxReader.java

    r21 r23  
    1010import org.jdom.input.SAXBuilder;
    1111import org.openstreetmap.josm.Main;
    12 import org.openstreetmap.josm.command.DataSet;
    1312import org.openstreetmap.josm.data.GeoPoint;
     13import org.openstreetmap.josm.data.osm.DataSet;
    1414import org.openstreetmap.josm.data.osm.Key;
    1515import org.openstreetmap.josm.data.osm.LineSegment;
     
    2525 * @author imi
    2626 */
    27 public class GpxReader implements DataReader {
     27public class GpxReader {
    2828
    2929        /**
    3030         * The GPX namespace used.
    3131         */
    32         private static Namespace GPX = Namespace.getNamespace("http://www.topografix.com/GPX/1/0");
     32        public static final Namespace GPX = Namespace.getNamespace("http://www.topografix.com/GPX/1/0");
    3333        /**
    3434         * The OSM namespace used (for extensions).
     
    4040         */
    4141        public Reader source;
    42         /**
    43          * If <code>true</code>, only nodes and tracks are imported (but no key/value
    44          * pairs). That is to support background gps information as an hint for
    45          * real OSM data.
    46          */
    47         private final boolean rawGps;
    4842       
    4943        /**
    5044         * Construct a parser from a specific data source.
    5145         * @param source The data source, as example a FileReader to read from a file.
    52          * @param rawGps Whether the gpx file describes raw gps data. Only very few
    53          *              information (only nodes and line segments) imported for raw gps to
    54          *              save memory.
    55          */
    56         public GpxReader(Reader source, boolean rawGps) {
     46         */
     47        public GpxReader(Reader source) {
    5748                this.source = source;
    58                 this.rawGps = rawGps;
    5949        }
    6050       
     
    6252         * Read the input stream and return a DataSet from the stream.
    6353         */
    64         public DataSet parse() throws ParseException, ConnectionException {
     54        public DataSet parse() throws JDOMException, IOException {
    6555                try {
    6656                        final SAXBuilder builder = new SAXBuilder();
    6757                        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                        
    7358                        return parseDataSet(root);
    7459                } catch (NullPointerException npe) {
    75                         throw new ParseException("NullPointerException. Probably a tag name mismatch.", npe);
     60                        throw new JDOMException("NullPointerException. Probably a tag name mismatch.", npe);
    7661                } catch (ClassCastException cce) {
    77                         throw new ParseException("ClassCastException. Probably a tag does not contain the correct type.", cce);
    78                 } catch (JDOMException e) {
    79                         throw new ParseException("The data could not be parsed. Reason: "+e.getMessage(), e);
    80                 } catch (IOException e) {
    81                         throw new ConnectionException("The data could not be retrieved. Reason: "+e.getMessage(), e);
     62                        throw new JDOMException("ClassCastException. Probably a tag does not contain the correct type.", cce);
    8263                }
    8364        }
     
    9475                        Float.parseFloat(e.getAttributeValue("lat")),
    9576                        Float.parseFloat(e.getAttributeValue("lon")));
    96                
    97                 if (rawGps)
    98                         return data;
    9977               
    10078                for (Object o : e.getChildren()) {
     
    149127                                        else {
    150128                                                LineSegment lineSegment = new LineSegment(start, node);
    151                                                 if (!rawGps)
    152                                                         parseKeyValueExtensions(lineSegment, ((Element)w).getChild("extensions", GPX));
     129                                                parseKeyValueExtensions(lineSegment, ((Element)w).getChild("extensions", GPX));
    153130                                                track.add(lineSegment);
    154131                                                start = null;
     
    156133                                }
    157134                        }
    158                        
    159                         if (rawGps)
    160                                 continue;
    161135                       
    162136                        if (child.getName().equals("extensions"))
     
    167141                                parseKeyValueTag(track, child);
    168142                }
    169                 ds.addTrack(track);
     143                ds.tracks.add(track);
    170144        }
    171145       
     
    184158         */
    185159        private Node addNode (DataSet data, Node node) {
    186                 if (Main.pref.mergeNodes || rawGps)
     160                if (Main.pref.mergeNodes)
    187161                        for (Node n : data.nodes)
    188162                                if (node.coor.equalsLatLon(n.coor))
  • src/org/openstreetmap/josm/io/GpxWriter.java

    r22 r23  
    8585
    8686                // tracks
    87                 for (Track t : Main.main.ds.tracks()) {
     87                for (Track t : Main.main.ds.tracks) {
    8888                        Element tElem = new Element("trk", GPX);
    8989                        if (t.keys != null) {
     
    9999                        }
    100100                        // line segments
    101                         for (LineSegment ls : t.segments()) {
     101                        for (LineSegment ls : t.segments) {
    102102                                Element lsElem = new Element("trkseg", GPX);
    103103                                if (ls.keys != null)
    104104                                addPropertyExtensions(lsElem, ls.keys);
    105                                 lsElem.getChildren().add(parseWaypoint(ls.getStart(), "trkpt"));
    106                                 lsElem.getChildren().add(parseWaypoint(ls.getEnd(), "trkpt"));
    107                                 nodes.remove(ls.getStart());
    108                                 nodes.remove(ls.getEnd());
     105                                lsElem.getChildren().add(parseWaypoint(ls.start, "trkpt"));
     106                                lsElem.getChildren().add(parseWaypoint(ls.end, "trkpt"));
     107                                nodes.remove(ls.start);
     108                                nodes.remove(ls.end);
    109109                                tElem.getChildren().add(lsElem);
    110110                        }
  • src/org/openstreetmap/josm/io/OsmConnection.java

    r22 r23  
    2323 */
    2424public class OsmConnection {
    25        
    26 
    2725
    2826        /**
  • src/org/openstreetmap/josm/io/OsmReader.java

    r22 r23  
    66import java.net.HttpURLConnection;
    77import java.net.URL;
     8import java.util.Collection;
     9import java.util.LinkedList;
    810
    9 import org.openstreetmap.josm.command.DataSet;
     11import org.jdom.JDOMException;
     12import org.openstreetmap.josm.data.GeoPoint;
     13import org.openstreetmap.josm.data.osm.DataSet;
    1014
    1115/**
     
    1418 * @author imi
    1519 */
    16 public class OsmReader extends OsmConnection implements DataReader {
     20public class OsmReader extends OsmConnection {
    1721
    1822        /**
     
    2024         */
    2125        private String urlStr;
    22         /**
    23          * Whether importing the raw trackpoints or the regular osm map information
    24          */
    25         private boolean rawGps;
     26        private final double lat1;
     27        private final double lon1;
     28        private final double lat2;
     29        private final double lon2;
    2630       
    2731        /**
    2832         * Construct the reader and store the information for attaching
    2933         */
    30         public OsmReader(String server, boolean rawGps,
     34        public OsmReader(String server,
    3135                        double lat1, double lon1, double lat2, double lon2) {
    32                 this.rawGps = rawGps;
     36                this.lon2 = lon2;
     37                this.lat2 = lat2;
     38                this.lon1 = lon1;
     39                this.lat1 = lat1;
    3340                urlStr = server.endsWith("/") ? server : server+"/";
    34                 if (rawGps)
    35                         urlStr += "trackpoints?bbox="+lat1+","+lon1+","+lat2+","+lon2+"&page=";
    36                 else
    37                         urlStr += "map?bbox="+lon1+","+lat1+","+lon2+","+lat2;
    3841        }
    3942
    4043
    41         public DataSet parse() throws ParseException, ConnectionException {
    42                 Reader in;
    43                 initAuthentication();
    44                 try {
    45                         if (rawGps) {
    46                                 DataSet ds = new DataSet();
    47                                 for (int i = 0;;++i) {
    48                                         URL url = new URL(urlStr+i);
    49                                         System.out.println(url);
    50                                         HttpURLConnection con = (HttpURLConnection)url.openConnection();
    51                                         con.setConnectTimeout(20000);
    52                                         if (con.getResponseCode() == 401 && isCancelled())
    53                                                 return null;
    54                                         in = new InputStreamReader(con.getInputStream());
    55                                         DataSet currentData = new GpxReader(in, true).parse();
    56                                         if (currentData.nodes.isEmpty())
    57                                                 return ds;
    58                                         ds.mergeFrom(currentData, true);
     44        /**
     45         * Retrieve raw gps trackpoints from the server API.
     46         * @return A list of all primitives retrieved. Currently, the list of lists
     47         *              contain only one list, since the server cannot distinguish between
     48         *              tracks.
     49         */
     50        public Collection<Collection<GeoPoint>> parseRawGps() throws IOException, JDOMException {
     51                String url = urlStr+"trackpoints?bbox="+lat1+","+lon1+","+lat2+","+lon2+"&page=";
     52                Collection<Collection<GeoPoint>> data = new LinkedList<Collection<GeoPoint>>();
     53                Collection<GeoPoint> list = new LinkedList<GeoPoint>();
     54               
     55                for (int i = 0;;++i) {
     56                        Reader r = getReader(url+i);
     57                        if (r == null)
     58                                break;
     59                        RawGpsReader gpsReader = new RawGpsReader(r);
     60                        Collection<Collection<GeoPoint>> allTracks = gpsReader.parse();
     61                        boolean foundSomething = false;
     62                        for (Collection<GeoPoint> t : allTracks) {
     63                                if (!t.isEmpty()) {
     64                                        foundSomething = true;
     65                                        list.addAll(t);
    5966                                }
    6067                        }
    61                         URL url = new URL(urlStr);
    62                         HttpURLConnection con = (HttpURLConnection)url.openConnection();
    63                         con.setConnectTimeout(20000);
    64                         if (con.getResponseCode() == 401 && isCancelled())
    65                                 return null;
    66                         in = new InputStreamReader(con.getInputStream());
    67                         return new GpxReader(in, false).parse();
    68                 } catch (IOException e) {
    69                         throw new ConnectionException("Failed to open server connection\n"+e.getMessage(), e);
     68                        if (!foundSomething)
     69                                break;
    7070                }
     71
     72                data.add(list);
     73                return data;
     74        }
     75
     76
     77        /**
     78         * Read the data from the osm server address.
     79         * @return A data set containing all data retrieved from that url
     80         */
     81        public DataSet parseOsm() throws JDOMException, IOException {
     82                Reader r = getReader(urlStr+"map?bbox="+lon1+","+lat1+","+lon2+","+lat2);
     83                if (r == null)
     84                        return null;
     85                return new GpxReader(r).parse();
     86        }
     87
     88
     89        /**
     90         * Open a connection to the given url and return a reader on the input stream
     91         * from that connection. In case of user cancel, return <code>null</code>.
     92         * @param url The exact url to connect to.
     93         * @return An reader reading the input stream (servers answer) or <code>null</code>.
     94         */
     95        private Reader getReader(String urlStr) throws IOException {
     96                System.out.println(urlStr);
     97                initAuthentication();
     98                URL url = new URL(urlStr);
     99                HttpURLConnection con = (HttpURLConnection)url.openConnection();
     100                con.setConnectTimeout(20000);
     101                if (con.getResponseCode() == 401 && isCancelled())
     102                        return null;
     103                return new InputStreamReader(con.getInputStream());
    71104        }
    72105}
Note: See TracChangeset for help on using the changeset viewer.