Changeset 30 in josm


Ignore:
Timestamp:
2005-12-03T14:14:35+01:00 (18 years ago)
Author:
imi
Message:
  • Removed edit layer, combine action, save gpx (integrated in normal save)
  • Simplified and unified shortkeys
  • many small code simplifications
  • added undo
  • broken checkin!
Files:
2 added
9 deleted
38 edited

Legend:

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

    r29 r30  
    2020import org.openstreetmap.josm.actions.PreferencesAction;
    2121import org.openstreetmap.josm.actions.SaveAction;
    22 import org.openstreetmap.josm.actions.SaveGpxAction;
    2322import org.openstreetmap.josm.actions.UndoAction;
    2423import org.openstreetmap.josm.data.Preferences;
     
    7978                OpenAction openAction = new OpenAction();
    8079                SaveAction saveAction = new SaveAction();
    81                 SaveGpxAction saveGpxAction = new SaveGpxAction();
    8280                ExitAction exitAction = new ExitAction();
    8381                UndoAction undoAction = new UndoAction();
     
    9391                fileMenu.add(openAction);
    9492                fileMenu.add(saveAction);
    95                 fileMenu.add(saveGpxAction);
    9693                fileMenu.addSeparator();
    9794                fileMenu.add(exitAction);
     
    106103                JMenu editMenu = new JMenu("Edit");
    107104                editMenu.setMnemonic('E');
    108                 //editMenu.add(undoAction);
     105                editMenu.add(undoAction);
    109106                editMenu.addSeparator();
    110107                editMenu.add(preferencesAction);
     
    123120                toolBar.add(openAction);
    124121                toolBar.add(saveAction);
    125                 toolBar.add(saveGpxAction);
    126122                toolBar.addSeparator();
    127                 //toolBar.add(undoAction);
     123                toolBar.add(undoAction);
    128124                toolBar.addSeparator();
    129125                toolBar.add(preferencesAction);
  • src/org/openstreetmap/josm/actions/AboutAction.java

    r27 r30  
    1313import java.util.regex.Pattern;
    1414
    15 import javax.swing.AbstractAction;
    1615import javax.swing.JEditorPane;
    1716import javax.swing.JLabel;
     
    3635 * @author imi
    3736 */
    38 public class AboutAction extends AbstractAction {
     37public class AboutAction extends JosmAction {
    3938       
    4039        public AboutAction() {
    41                 super("About", ImageProvider.get("about"));
    42                 putValue(MNEMONIC_KEY, KeyEvent.VK_A);
    43                 putValue(SHORT_DESCRIPTION, "Display the about screen.");
     40                super("About", "about", "Display the about screen.", KeyEvent.VK_A, null);
    4441        }
    4542       
  • src/org/openstreetmap/josm/actions/AutoScaleAction.java

    r17 r30  
    44import java.awt.event.KeyEvent;
    55
    6 import javax.swing.AbstractAction;
    7 import javax.swing.JComponent;
    8 import javax.swing.KeyStroke;
    9 
    10 import org.openstreetmap.josm.gui.ImageProvider;
    116import org.openstreetmap.josm.gui.MapFrame;
    127import org.openstreetmap.josm.gui.MapView;
     
    1611 * @author imi
    1712 */
    18 public class AutoScaleAction extends AbstractAction {
     13public class AutoScaleAction extends JosmAction {
    1914        /**
    2015         * The mapView this action operates on.
     
    2318       
    2419        public AutoScaleAction(MapFrame mapFrame) {
    25                 super("Auto Scale", ImageProvider.get("autoscale"));
     20                super("Auto Scale", "autoscale", "Zoom the view to show the whole layer. Disabled if the view is moved.",
     21                                KeyEvent.VK_A, null);
    2622                mapView = mapFrame.mapView;
    27                 putValue(MNEMONIC_KEY, KeyEvent.VK_A);
    28                 putValue(SHORT_DESCRIPTION, "Zoom the view to show the whole layer. Disabled if the view is moved.");
    29                 KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0);
    30                 putValue(ACCELERATOR_KEY, ks);
    31                 mapFrame.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, this);
    32                 mapFrame.getActionMap().put(this, this);
    3323        }
    3424
  • src/org/openstreetmap/josm/actions/ExitAction.java

    r17 r30  
    33import java.awt.event.ActionEvent;
    44import java.awt.event.KeyEvent;
    5 
    6 import javax.swing.AbstractAction;
    7 
    8 import org.openstreetmap.josm.gui.ImageProvider;
    95
    106/**
     
    139 * @author imi
    1410 */
    15 public class ExitAction extends AbstractAction {
     11public class ExitAction extends JosmAction {
    1612
    1713        /**
     
    1915         */
    2016        public ExitAction() {
    21                 super("Exit", ImageProvider.get("exit"));
    22                 putValue(MNEMONIC_KEY, KeyEvent.VK_X);
    23                 putValue(SHORT_DESCRIPTION, "Exit the application.");
     17                super("Exit", "exit", "Exit the application.", KeyEvent.VK_X, null);
    2418        }
    2519       
  • src/org/openstreetmap/josm/actions/OpenAction.java

    r29 r30  
    1010import java.util.Collection;
    1111
    12 import javax.swing.AbstractAction;
    1312import javax.swing.Box;
    1413import javax.swing.JCheckBox;
     
    2423import org.openstreetmap.josm.data.GeoPoint;
    2524import org.openstreetmap.josm.data.osm.DataSet;
    26 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2725import org.openstreetmap.josm.gui.GBC;
    28 import org.openstreetmap.josm.gui.ImageProvider;
    2926import org.openstreetmap.josm.gui.MapFrame;
    3027import org.openstreetmap.josm.gui.layer.Layer;
     
    4138 * @author imi
    4239 */
    43 public class OpenAction extends AbstractAction {
     40public class OpenAction extends JosmAction {
    4441
    4542        /**
     
    4744         */
    4845        public OpenAction() {
    49                 super("Open", ImageProvider.get("open"));
    50                 putValue(ACCELERATOR_KEY, KeyStroke.getAWTKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
    51                 putValue(MNEMONIC_KEY, KeyEvent.VK_O);
    52                 putValue(SHORT_DESCRIPTION, "Open a file.");
     46                super("Open", "open", "Open a file.", null, KeyStroke.getAWTKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
    5347        }
    5448
     
    9690                                layer = new RawGpsDataLayer(data, filename.getName());
    9791                        } else {
    98                                 DataSet dataSet = filename.getName().toLowerCase().endsWith("gpx") ?
     92                                DataSet dataSet = filename.getName().toLowerCase().endsWith(".gpx") ?
    9993                                                new GpxReader(new FileReader(filename)).parse() :
    10094                                                new OsmReader(new FileReader(filename)).parse();
    101                                 Collection<OsmPrimitive> l = Main.main.ds.mergeFrom(dataSet);
    102                                 layer = new OsmDataLayer(l, filename.getName());
     95                                layer = new OsmDataLayer(dataSet, filename.getName());
    10396                        }
    10497                       
  • src/org/openstreetmap/josm/actions/OpenOsmServerAction.java

    r24 r30  
    55import java.awt.event.ActionEvent;
    66import java.awt.event.ActionListener;
     7import java.awt.event.InputEvent;
    78import java.awt.event.KeyEvent;
    89import java.io.IOException;
    9 import java.util.Collection;
    1010
    11 import javax.swing.AbstractAction;
    1211import javax.swing.DefaultListModel;
    1312import javax.swing.JButton;
     
    1817import javax.swing.JScrollPane;
    1918import javax.swing.JTextField;
     19import javax.swing.KeyStroke;
    2020import javax.swing.event.ListSelectionEvent;
    2121import javax.swing.event.ListSelectionListener;
     
    2525import org.openstreetmap.josm.data.GeoPoint;
    2626import org.openstreetmap.josm.data.osm.DataSet;
    27 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2827import org.openstreetmap.josm.gui.BookmarkList;
    2928import org.openstreetmap.josm.gui.GBC;
    30 import org.openstreetmap.josm.gui.ImageProvider;
    3129import org.openstreetmap.josm.gui.MapFrame;
    3230import org.openstreetmap.josm.gui.MapView;
     
    4543 * @author imi
    4644 */
    47 public class OpenOsmServerAction extends AbstractAction {
     45public class OpenOsmServerAction extends JosmAction {
    4846
    4947        JTextField[] latlon = new JTextField[]{
     
    5553
    5654        public OpenOsmServerAction() {
    57                 super("Connect to OSM", ImageProvider.get("connectosm"));
    58                 putValue(MNEMONIC_KEY, KeyEvent.VK_C);
    59                 putValue(SHORT_DESCRIPTION, "Open a connection to the OSM server.");
     55                super("Connect to OSM", "connectosm", "Open a connection to the OSM server.", KeyEvent.VK_C,
     56                                KeyStroke.getAWTKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
    6057        }
    6158
     
    163160                                        JOptionPane.showMessageDialog(Main.main, "No data imported.");
    164161                               
    165                                 Collection<OsmPrimitive> data = Main.main.ds.mergeFrom(dataSet);
    166                                 layer = new OsmDataLayer(data, name);
     162                                layer = new OsmDataLayer(dataSet, name);
    167163                        }
    168164
  • src/org/openstreetmap/josm/actions/PreferencesAction.java

    r24 r30  
    22
    33import java.awt.event.ActionEvent;
    4 import java.awt.event.InputEvent;
    54import java.awt.event.KeyEvent;
    65
    7 import javax.swing.AbstractAction;
    8 import javax.swing.KeyStroke;
    9 
    10 import org.openstreetmap.josm.gui.ImageProvider;
    116import org.openstreetmap.josm.gui.PreferenceDialog;
    127
     
    1611 * @author imi
    1712 */
    18 public class PreferencesAction extends AbstractAction {
     13public class PreferencesAction extends JosmAction {
    1914
    2015        /**
     
    2217         */
    2318        public PreferencesAction() {
    24                 super("Preferences", ImageProvider.get("preference"));
    25                 putValue(ACCELERATOR_KEY, KeyStroke.getAWTKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK));
    26                 putValue(MNEMONIC_KEY, KeyEvent.VK_P);
    27                 putValue(SHORT_DESCRIPTION, "Open a preferences page for global settings.");
     19                super("Preferences", "preference", "Open a preferences page for global settings.",
     20                                KeyEvent.VK_P, null);
    2821        }
    2922
  • src/org/openstreetmap/josm/actions/SaveAction.java

    r24 r30  
    88import java.io.IOException;
    99
    10 import javax.swing.AbstractAction;
    1110import javax.swing.JFileChooser;
    1211import javax.swing.JOptionPane;
     
    1514
    1615import org.openstreetmap.josm.Main;
    17 import org.openstreetmap.josm.gui.ImageProvider;
     16import org.openstreetmap.josm.io.GpxWriter;
    1817import org.openstreetmap.josm.io.OsmWriter;
    1918
     
    2524 * @author imi
    2625 */
    27 public class SaveAction extends AbstractAction {
     26public class SaveAction extends JosmAction {
    2827
    2928        /**
     
    3130         */
    3231        public SaveAction() {
    33                 super("Save", ImageProvider.get("save"));
    34                 putValue(ACCELERATOR_KEY, KeyStroke.getAWTKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
    35                 putValue(SHORT_DESCRIPTION, "Save the current data.");
     32                super("Save", "save", "Save the current data.", null, KeyStroke.getAWTKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
    3633        }
    3734       
     
    4643                        public boolean accept(File f) {
    4744                                String name = f.getName().toLowerCase();
    48                                 return f.isDirectory() || name.endsWith(".xml");
     45                                return f.isDirectory() || name.endsWith(".xml") || name.endsWith(".gpx");
    4946                        }
    5047                        @Override
    5148                        public String getDescription() {
    52                                 return "XML Files";
     49                                return "GPX or XML Files";
    5350                        }
    5451                });
     
    6057                try {
    6158                        FileWriter fileWriter = new FileWriter(file);
    62                         OsmWriter out = new OsmWriter(fileWriter, Main.main.ds);
    63                         out.output();
     59                        if (file.getName().endsWith(".gpx"))
     60                                new GpxWriter(fileWriter).output();
     61                        else
     62                                new OsmWriter(fileWriter, Main.main.ds).output();
    6463                        fileWriter.close();
    6564                } catch (IOException e) {
  • src/org/openstreetmap/josm/actions/UndoAction.java

    r29 r30  
    44import java.awt.event.InputEvent;
    55import java.awt.event.KeyEvent;
    6 import java.util.LinkedList;
    76
    8 import javax.swing.AbstractAction;
    97import javax.swing.KeyStroke;
    108
    119import org.openstreetmap.josm.Main;
    12 import org.openstreetmap.josm.command.Command;
    13 import org.openstreetmap.josm.gui.ImageProvider;
    1410
    1511
     
    1915 * @author imi
    2016 */
    21 public class UndoAction extends AbstractAction {
     17public class UndoAction extends JosmAction {
    2218
    2319        /**
     
    2521         */
    2622        public UndoAction() {
    27                 super("Undo", ImageProvider.get("undo"));
    28                 putValue(ACCELERATOR_KEY, KeyStroke.getAWTKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK));
    29                 putValue(SHORT_DESCRIPTION, "Undo the last action.");
     23                super("Undo", "undo", "Undo the last action.", null, KeyStroke.getAWTKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK));
    3024        }
    3125       
     
    3327                if (Main.main.getMapFrame() == null)
    3428                        return;
    35                 LinkedList<Command> commands = Main.main.getMapFrame().mapView.editLayer().commands;
    36                 if (commands.isEmpty())
    37                         return;
    38                 Command c = commands.getLast();
    39                 //c.undoCommand();
    40                 commands.removeLast();
    4129                Main.main.getMapFrame().repaint();
     30                Main.main.getMapFrame().mapView.editLayer().undo();
    4231        }
    4332}
  • src/org/openstreetmap/josm/actions/mapmode/AddLineSegmentAction.java

    r24 r30  
    44import java.awt.Graphics;
    55import java.awt.Point;
     6import java.awt.event.ActionEvent;
    67import java.awt.event.KeyEvent;
    78import java.awt.event.MouseEvent;
    89import java.awt.event.MouseListener;
    9 
    10 import javax.swing.JOptionPane;
    1110
    1211import org.openstreetmap.josm.Main;
     
    1514import org.openstreetmap.josm.data.osm.Node;
    1615import org.openstreetmap.josm.data.osm.OsmPrimitive;
    17 import org.openstreetmap.josm.data.osm.Track;
    1816import org.openstreetmap.josm.gui.MapFrame;
    1917
     
    2220 * starting node and dragging to the ending node.
    2321 *
    24  * If the Alt key was pressed when releasing the mouse, this action tries to
    25  * add the line segment to a track. The new line segment gets added to all tracks
    26  * of the first node that end in the first node. If no tracks are found, the
    27  * line segment gets added to all tracks in the second node that start with
    28  * the second node.
    29  *
    3022 * No line segment can be created if there is already a line segment containing
    31  * both nodes in the same order.
     23 * both nodes.
    3224 *
    3325 * @author imi
     
    7264        }
    7365
     66       
     67        @Override
     68        public void actionPerformed(ActionEvent e) {
     69                super.actionPerformed(e);
     70                makeLineSegment();
     71        }
     72
    7473        /**
    7574         * If user clicked on a node, start the dragging with that node.
     
    108107
    109108        /**
     109         * If left button was released, try to create the line segment.
     110         */
     111        @Override
     112        public void mouseReleased(MouseEvent e) {
     113                if (e.getButton() == MouseEvent.BUTTON1) {
     114                        makeLineSegment();
     115                        first = null; // release line segment drawing
     116                }
     117        }
     118
     119        /**
    110120         * Create the line segment if first and second are different and there is
    111121         * not already a line segment.
    112122         */
    113         @Override
    114         public void mouseReleased(MouseEvent e) {
    115                 if (e.getButton() != MouseEvent.BUTTON1)
    116                         return;
    117 
     123        private void makeLineSegment() {
    118124                if (first == null || second == null) {
    119125                        first = null;
     
    126132                Node start = first;
    127133                Node end = second;
    128                 first = null;
     134                first = second;
    129135                second = null;
    130136               
    131137                if (start != end) {
    132138                        // try to find a line segment
    133                         for (Track t : Main.main.ds.tracks)
    134                                 for (LineSegment ls : t.segments)
    135                                         if (start == ls.start && end == ls.end) {
    136                                                 JOptionPane.showMessageDialog(Main.main, "There is already an line segment with the same direction between the selected nodes.");
    137                                                 return;
    138                                         }
     139                        for (LineSegment ls : Main.main.ds.lineSegments)
     140                                if ((start == ls.start && end == ls.end) || (end == ls.start && start == ls.end))
     141                                        return; // already a line segment here - be happy, do nothing.
    139142
    140143                        LineSegment ls = new LineSegment(start, end);
    141                         mv.editLayer().add(new AddCommand(ls));
     144                        mv.editLayer().add(new AddCommand(Main.main.ds, ls));
    142145                }
    143                
     146
    144147                mv.repaint();
    145148        }
  • src/org/openstreetmap/josm/actions/mapmode/AddNodeAction.java

    r23 r30  
    44import java.awt.event.MouseEvent;
    55
     6import org.openstreetmap.josm.Main;
    67import org.openstreetmap.josm.command.AddCommand;
    78import org.openstreetmap.josm.data.osm.Node;
     
    4950                        Node node = new Node();
    5051                        node.coor = mv.getPoint(e.getX(), e.getY(), true);
    51                         mv.editLayer().add(new AddCommand(node));
     52                        mv.editLayer().add(new AddCommand(Main.main.ds, node));
    5253                        mv.repaint();
    5354                }
  • src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java

    r23 r30  
    22
    33import java.awt.Rectangle;
     4import java.awt.event.ActionEvent;
    45import java.awt.event.KeyEvent;
    56import java.util.Collection;
     
    6162        }
    6263
     64       
     65        @Override
     66        public void actionPerformed(ActionEvent e) {
     67                makeTrack();
     68                super.actionPerformed(e);
     69        }
     70
    6371        /**
    6472         * If Shift is pressed, only add the selected line segments to the selection.
     
    9098                        return; // no new track yet.
    9199               
     100                makeTrack();
     101        }
     102
     103        /**
     104         * Just make a track of all selected items.
     105         */
     106        private void makeTrack() {
    92107                Collection<OsmPrimitive> selection = Main.main.ds.getSelected();
    93108                if (selection.isEmpty())
     
    135150                for (LineSegment ls : sortedLineSegments)
    136151                        t.add(ls);
    137                 mv.editLayer().add(new AddCommand(t));
     152                mv.editLayer().add(new AddCommand(Main.main.ds, t));
    138153                Main.main.ds.clearSelection();
     154                mv.repaint();
    139155        }
    140156}
  • src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java

    r23 r30  
    11package org.openstreetmap.josm.actions.mapmode;
    22
     3import java.awt.event.ActionEvent;
    34import java.awt.event.KeyEvent;
    45import java.awt.event.MouseEvent;
    56import java.util.ArrayList;
    67import java.util.Collection;
     8import java.util.HashSet;
     9import java.util.Iterator;
    710import java.util.LinkedList;
    811
     
    1215import org.openstreetmap.josm.command.CombineAndDeleteCommand;
    1316import org.openstreetmap.josm.command.DeleteCommand;
    14 import org.openstreetmap.josm.command.CombineAndDeleteCommand.LineSegmentCombineEntry;
     17import org.openstreetmap.josm.data.osm.DataSet;
    1518import org.openstreetmap.josm.data.osm.LineSegment;
    1619import org.openstreetmap.josm.data.osm.Node;
     
    3235 * tries to combine the referencing objects as follows:
    3336 *
    34  * If a node is part of exactly two line segments from a track, the two line
    35  * segments are combined into one. The first line segment spans now to the end
    36  * of the second and the second line segment gets deleted. This is checked for
    37  * every track.
    38  *
    39  * If a node is the end of the ending line segment of one track and the start of
    40  * exactly one other tracks start segment, the tracks are combined into one track,
    41  * deleting the second track and keeping the first one. The ending line segment
    42  * of the fist track is combined with the starting line segment of the second
    43  * track.
     37 * If a node is part of exactly two line segments, the two line segments are
     38 * combined into one. The first line segment spans now to the end of the
     39 * second and the second line segment gets deleted.
    4440 *
    4541 * Combining is only possible, if both objects that should be combined have no
     
    5551 *
    5652 * If the user enters the mapmode and any object is selected, all selected
    57  * objects get deleted. Combining applies to the selected objects.
     53 * objects that can be deleted will. Combining applies to the selected objects.
    5854 *
    5955 * @author imi
     
    6662         */
    6763        public DeleteAction(MapFrame mapFrame) {
    68                 super("Delete", "delete", "Delete nodes, streets or areas.", KeyEvent.VK_DELETE, mapFrame);
     64                super("Delete", "delete", "Delete nodes, streets or areas.", KeyEvent.VK_D, mapFrame);
    6965        }
    7066
     
    8177        }
    8278
     79       
     80        @Override
     81        public void actionPerformed(ActionEvent e) {
     82                super.actionPerformed(e);
     83                boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
     84                Collection<OsmPrimitive> selection = Main.main.ds.getSelected();
     85               
     86                int selSize = 0;
     87                // loop as long as the selection size changes
     88                while(selSize != selection.size()) {
     89                        selSize = selection.size();
     90
     91                        for (Iterator<OsmPrimitive> it = selection.iterator(); it.hasNext();) {
     92                                OsmPrimitive osm = it.next();
     93                                if (ctrl) {
     94                                        deleteWithReferences(osm);
     95                                        it.remove();
     96                                } else {
     97                                        if (delete(osm, false))
     98                                                it.remove();
     99                                }
     100                        }
     101                }
     102                mv.repaint();
     103        }
     104
    83105        /**
    84106         * If user clicked with the left button, delete the nearest object.
     
    97119                        deleteWithReferences(sel);
    98120                else
    99                         delete(sel);
     121                        delete(sel, true);
    100122
    101123                mv.repaint();
     
    124146         * TODO If you delete x, then a,B,C and x gets deleted. A now consist of b only.
    125147         * If you delete a or b, then A, a, b and z gets deleted.
    126          *
     148         * 
    127149         * @param osm The object to delete.
    128150         */
    129151        private void deleteWithReferences(OsmPrimitive osm) {
    130                 // collect all tracks, areas and pending line segments that should be deleted
     152                // collect all tracks, areas and line segments that should be deleted
    131153                ArrayList<Track> tracksToDelete = new ArrayList<Track>();
    132154                ArrayList<LineSegment> lineSegmentsToDelete = new ArrayList<LineSegment>();
     
    138160                                        if (ls.start == osm || ls.end == osm)
    139161                                                tracksToDelete.add(t);
    140                         for (LineSegment ls : Main.main.ds.pendingLineSegments)
     162                        for (LineSegment ls : Main.main.ds.lineSegments)
    141163                                if (ls.start == osm || ls.end == osm)
    142164                                        lineSegmentsToDelete.add(ls);
     
    164186                        checkUnreferencing.add(ls.end);
    165187                }
    166                
     188
    167189                Collection<OsmPrimitive> deleteData = new LinkedList<OsmPrimitive>();
    168190                deleteData.addAll(tracksToDelete);
     
    175197                if (osm instanceof Node)
    176198                        deleteData.add(osm);
    177                
    178                 mv.editLayer().add(new DeleteCommand(deleteData));
     199
     200                mv.editLayer().add(new DeleteCommand(Main.main.ds, deleteData));
    179201        }
    180202
     
    185207         *
    186208         * @param osm The object to delete.
    187          */
    188         private void delete(OsmPrimitive osm) {
    189                 if (osm instanceof Node && isReferenced((Node)osm)) {
    190                         combineAndDelete((Node)osm);
    191                         return;
    192                 }
     209         * @param msgBox Whether a message box for errors should be shown
     210         * @return <code>true</code> if the object could be deleted
     211         */
     212        private boolean delete(OsmPrimitive osm, boolean msgBox) {
     213                if (osm instanceof Node && isReferenced((Node)osm))
     214                        return combineAndDelete((Node)osm, msgBox);
    193215                Collection<OsmPrimitive> c = new LinkedList<OsmPrimitive>();
    194216                c.add(osm);
    195                 mv.editLayer().add(new DeleteCommand(c));
     217                mv.editLayer().add(new DeleteCommand(Main.main.ds, c));
     218                return true;
    196219        }
    197220
     
    203226         */
    204227        private boolean isReferenced(Node n) {
    205                 for (Track t : Main.main.ds.tracks)
    206                         for (LineSegment ls : t.segments)
    207                                 if (ls.start == n || ls.end == n)
    208                                         return true;
    209                 for (LineSegment ls : Main.main.ds.pendingLineSegments)
     228                for (LineSegment ls : Main.main.ds.lineSegments)
    210229                        if (ls.start == n || ls.end == n)
    211230                                return true;
     
    220239         *
    221240         * @param n The node that is going to be deleted.
    222          * @return <code>null</code> if combining suceded or an error string if there
    223          *              are problems combining the node.
    224          */
    225         private void combineAndDelete(Node n) {
    226                 // first, check for pending line segments
    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                         }
    232                
    233                 // These line segments must be combined within the track combining
    234                 ArrayList<LineSegment> pendingLineSegmentsForTrack = new ArrayList<LineSegment>();
    235 
    236                 // try to combine line segments
    237                
    238                 // These line segments are combinable. The inner arraylist has always
    239                 // two elements. The keys maps to the track, the line segments are in.
    240                 Collection<LineSegmentCombineEntry> lineSegments = new ArrayList<LineSegmentCombineEntry>();
    241                
    242                 for (Track t : Main.main.ds.tracks) {
    243                         ArrayList<LineSegment> current = new ArrayList<LineSegment>();
    244                         for (LineSegment ls : t.segments)
    245                                 if (ls.start == n || ls.end == n)
    246                                         current.add(ls);
    247                         if (!current.isEmpty()) {
    248                                 if (current.size() > 2) {
    249                                         JOptionPane.showMessageDialog(Main.main, "Node used by more than two line segments.");
    250                                         return;
    251                                 }
    252                                 if (current.size() == 1 &&
    253                                                 (current.get(0) == t.getStartingSegment() || current.get(0) == t.getEndingSegment()))
    254                                         pendingLineSegmentsForTrack.add(current.get(0));
    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                                 }
    269                         }
    270                 }
    271                
    272                 // try to combine tracks
    273                 ArrayList<Track> tracks = new ArrayList<Track>();
    274                 for (Track t : Main.main.ds.tracks)
    275                         if (t.getStartingNode() == n || t.getEndingNode() == n)
    276                                 tracks.add(t);
    277                 if (!tracks.isEmpty()) {
    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                         }
    286                         Track t1 = tracks.get(0);
    287                         Track t2 = tracks.get(1);
    288                         if (t1.getStartingNode() != t2.getEndingNode() &&
    289                                         t2.getStartingNode() != t1.getEndingNode()) {
    290                                 if (t1.getStartingNode() == t2.getStartingNode() ||
    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                         }
    302                 }
    303                
    304                 // try to match the pending line segments
    305                 if (pendingLineSegmentsForTrack.size() == 2) {
    306                         LineSegment l1 = pendingLineSegmentsForTrack.get(0);
    307                         LineSegment l2 = pendingLineSegmentsForTrack.get(1);
    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)
    313                                 pendingLineSegmentsForTrack.clear(); // resolved.
    314                 }
    315                
    316                 // still pending line segments?
    317                 if (!pendingLineSegmentsForTrack.isEmpty()) {
    318                         JOptionPane.showMessageDialog(Main.main, "Node used by tracks that cannot be combined.");
    319                         return;
     241         * @param msgBox Whether a message box should be displayed in case of problems
     242         * @return <code>true</code> if combining suceded.
     243         */
     244        private boolean combineAndDelete(Node n, boolean msgBox) {
     245                DataSet ds = Main.main.ds;
     246                Collection<LineSegment> lineSegmentsUsed = new HashSet<LineSegment>();
     247                for (LineSegment ls : ds.lineSegments)
     248                        if (ls.start == n || ls.end == n)
     249                                lineSegmentsUsed.add(ls);
     250
     251                if (lineSegmentsUsed.isEmpty())
     252                        // should not be called
     253                        throw new IllegalStateException();
     254               
     255                if (lineSegmentsUsed.size() == 1) {
     256                        if (msgBox)
     257                                JOptionPane.showMessageDialog(Main.main, "Node used by a line segment. Delete this first.");
     258                        return false;
     259                }
     260                       
     261                if (lineSegmentsUsed.size() > 2) {
     262                        if (msgBox)
     263                                JOptionPane.showMessageDialog(Main.main, "Node used by more than two line segments. Delete them first.");
     264                        return false;
     265                }
     266               
     267                Iterator<LineSegment> it = lineSegmentsUsed.iterator();
     268                LineSegment first = it.next();
     269                LineSegment second = it.next();
     270               
     271                // wrong direction?
     272                if (first.start == second.end) {
     273                        LineSegment t = first;
     274                        first = second;
     275                        second = t;
     276                }
     277               
     278                // combinable?
     279                if (first.end != second.start || !first.end.keyPropertiesMergable(second.start)) {
     280                        if (msgBox)
     281                                JOptionPane.showMessageDialog(Main.main, "Node used by line segments that cannot be combined.");
     282                        return false;
    320283                }
    321284
    322285                // Ok, we can combine. Do it.
    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));
     286                mv.editLayer().add(new CombineAndDeleteCommand(ds, first, second));
     287                return true;
    326288        }
    327289}
  • src/org/openstreetmap/josm/actions/mapmode/MapMode.java

    r23 r30  
    66import java.awt.event.MouseMotionListener;
    77
    8 import javax.swing.AbstractAction;
    9 import javax.swing.JComponent;
    10 import javax.swing.KeyStroke;
    11 
    12 import org.openstreetmap.josm.gui.ImageProvider;
     8import org.openstreetmap.josm.actions.JosmAction;
    139import org.openstreetmap.josm.gui.MapFrame;
    1410import org.openstreetmap.josm.gui.MapView;
     
    2218 * control.
    2319 */
    24 abstract public class MapMode extends AbstractAction implements MouseListener, MouseMotionListener {
     20abstract public class MapMode extends JosmAction implements MouseListener, MouseMotionListener {
    2521
    2622        /**
     
    4036         */
    4137        public MapMode(String name, String iconName, String tooltip, int mnemonic, MapFrame mapFrame) {
    42                 super(name, ImageProvider.get("mapmode", iconName));
    43                 putValue(MNEMONIC_KEY, mnemonic);
    44                 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(mnemonic,0));
    45                 putValue(LONG_DESCRIPTION, tooltip);
    46                 mapFrame.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(mnemonic,0), this);
    47                 mapFrame.getActionMap().put(this, this);
     38                super(name, "mapmode/"+iconName, tooltip, mnemonic, null);
    4839                this.mapFrame = mapFrame;
    4940                mv = mapFrame.mapView;
  • src/org/openstreetmap/josm/command/AddCommand.java

    r23 r30  
    33import java.awt.Component;
    44import java.util.Collection;
    5 import java.util.Iterator;
    65
    76import javax.swing.JLabel;
    87
    9 import org.openstreetmap.josm.Main;
     8import org.openstreetmap.josm.data.osm.DataSet;
    109import org.openstreetmap.josm.data.osm.Key;
    1110import org.openstreetmap.josm.data.osm.LineSegment;
     
    2221 * @author imi
    2322 */
    24 public class AddCommand implements Command, Visitor {
     23public class AddCommand implements Command {
    2524
     25        /**
     26         * The dataset this command operates on.
     27         */
     28        DataSet ds;
     29
     30        /**
     31         * Helper that adds the object
     32         * @author imi
     33         */
     34        private final class AddVisitor implements Visitor {
     35                public void visit(Node n) {ds.nodes.add(n);}
     36                public void visit(LineSegment ls) {ds.lineSegments.add(ls);}
     37                public void visit(Track t) {ds.tracks.add(t);}
     38                public void visit(Key k) {throw new IllegalStateException("Keys are added by using ChangeKeyValueCommand");}
     39        }
     40
     41        /**
     42         * Helper that deletes the object (for undo)
     43         * @author imi
     44         */
     45        private final class RemoveVisitor implements Visitor {
     46                public void visit(Node n) {ds.nodes.remove(n);}
     47                public void visit(LineSegment ls) {ds.lineSegments.remove(ls);}
     48                public void visit(Track t) {ds.tracks.remove(t);}
     49                public void visit(Key k) {throw new IllegalStateException("Keys are added by using ChangeKeyValueCommand");}
     50        }
     51       
    2652        /**
    2753         * The primitive to add to the dataset.
     
    3258         * Create the command and specify the element to add.
    3359         */
    34         public AddCommand(OsmPrimitive osm) {
     60        public AddCommand(DataSet ds, OsmPrimitive osm) {
     61                this.ds = ds;
    3562                this.osm = osm;
    3663        }
    3764
    3865        public void executeCommand() {
    39                 osm.visit(this);
     66                osm.visit(new AddVisitor());
    4067        }
    41        
     68
     69        public void undoCommand() {
     70                osm.visit(new RemoveVisitor());
     71        }
     72
    4273        public Component commandDescription() {
    4374                SelectionComponentVisitor v = new SelectionComponentVisitor();
     
    4778       
    4879        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    49                 if (added != null && !added.contains(osm))
    50                         added.add(osm);
    51         }
    52 
    53         /**
    54          * Add the node to the nodes - list only.
    55          * @param n The node to add.
    56          */
    57         public void visit(Node n) {
    58                 Main.main.ds.nodes.add(n);
    59         }
    60 
    61         /**
    62          * Add the line segment to the list of pending line segments.
    63          * @param ls The line segment to add.
    64          */
    65         public void visit(LineSegment ls) {
    66                 Main.main.ds.pendingLineSegments.add(ls);
    67                 Main.main.ds.addBackReference(ls.start, ls);
    68                 Main.main.ds.addBackReference(ls.end, ls);
    69         }
    70 
    71         /**
    72          * Add the track to the dataset. Remove all line segments that were pending
    73          * from the dataset.
    74          */
    75         public void visit(Track t) {
    76                 Main.main.ds.tracks.add(t);
    77                 for (Iterator<LineSegment> it =  Main.main.ds.pendingLineSegments.iterator(); it.hasNext();)
    78                         if (t.segments.contains(it.next()))
    79                                 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                 }
    85         }
    86 
    87         /**
    88          * Add the key to the parent specified by the constructor
    89          */
    90         public void visit(Key k) {
    91                 throw new IllegalStateException("Keys are added by using ChangeKeyValueCommand");
     80                added.add(osm);
    9281        }
    9382}
  • src/org/openstreetmap/josm/command/ChangeKeyValueCommand.java

    r24 r30  
    44import java.util.Collection;
    55import java.util.HashMap;
     6import java.util.Iterator;
     7import java.util.LinkedList;
     8import java.util.List;
     9import java.util.Map;
    610
    711import javax.swing.JLabel;
     
    2125         * All primitives, that are affected with this command.
    2226         */
    23         private final Collection<OsmPrimitive> objects;
     27        private final List<OsmPrimitive> objects;
    2428        /**
    2529         * The key that is subject to change.
     
    3236         */
    3337        private final String value;
     38       
     39        /**
     40         * These are the old values of the objects to do a proper undo.
     41         */
     42        private List<Map<Key, String>> oldProperties;
    3443
    3544        public ChangeKeyValueCommand(Collection<OsmPrimitive> objects, Key key, String value) {
    36                 this.objects = objects;
     45                this.objects = new LinkedList<OsmPrimitive>(objects);
    3746                this.key = key;
    3847                this.value = value;
     
    4049       
    4150        public void executeCommand() {
     51                // save old
     52                oldProperties = new LinkedList<Map<Key, String>>();
     53                for (OsmPrimitive osm : objects)
     54                        oldProperties.add(osm.keys == null ? null : new HashMap<Key, String>(osm.keys));
     55                       
    4256                if (value == null) {
    4357                        for (OsmPrimitive osm : objects) {
     
    5771        }
    5872
     73        public void undoCommand() {
     74                Iterator<Map<Key, String>> it = oldProperties.iterator();
     75                for (OsmPrimitive osm : objects)
     76                        osm.keys = it.next();
     77        }
     78
    5979        public Component commandDescription() {
    6080                String objStr = objects.size()+" object" + (objects.size()==1?"":"s");
  • src/org/openstreetmap/josm/command/CombineAndDeleteCommand.java

    r23 r30  
    33import java.awt.Component;
    44import java.util.Collection;
     5import java.util.HashMap;
     6import java.util.Iterator;
     7import java.util.LinkedList;
     8import java.util.List;
    59import java.util.Map;
    610
    711import javax.swing.JLabel;
    812
    9 import org.openstreetmap.josm.Main;
    1013import org.openstreetmap.josm.data.osm.DataSet;
    1114import org.openstreetmap.josm.data.osm.Key;
    1215import org.openstreetmap.josm.data.osm.LineSegment;
    13 import org.openstreetmap.josm.data.osm.Node;
    1416import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1517import org.openstreetmap.josm.data.osm.Track;
     
    1921 * This is a combination of first combining objects to get a node free of
    2022 * references and then delete that node. It is used by the delete action.
     23 *
     24 * The rules is as follow:
     25 * If the node to delete is between exact two line segments, which are
     26 * in a straight (not pointing together), the second line segment is deleted
     27 * and the first now spans to the last node of the second line segment.
     28 *
    2129 * @author imi
    2230 */
     
    2432
    2533        /**
    26          * This class is used as one line segment pair that needs to get combined
    27          * for the node to be deleted.
    28          * @author imi
     34         * The dataset, this command operates on.
    2935         */
    30         public static class LineSegmentCombineEntry {
    31                 public LineSegment first, second;
    32                 public Track track;
    33         }
     36        private DataSet ds;
     37        /**
     38         * This line segment is combined with the second line segment.
     39         * The node that get deleted is the end of this segment.
     40         */
     41        private LineSegment first;
     42        /**
     43         * This line segment is deleted by the combining.
     44         * The node that get deleted is the start of this segment.
     45         */
     46        private LineSegment second;
     47
     48        /**
     49         * The tracks (if any) the line segments are part of.
     50         */
     51        private List<Track> track;
     52
     53       
     54        // stuff for undo
     55
     56        /**
     57         * The old properties of the first line segment (for undo)
     58         */
     59        private Map<Key, String> oldProperties;
     60        /**
     61         * The positions of the second line segment in the tracks (if any track)
     62         */
     63        private List<Integer> lineSegmentTrackPos;
    3464       
    3565        /**
    36          * The node that get deleted
     66         * Create the command and assign the data entries.
     67         * @param ds     The dataset this command operates on.
     68         * @param first  The line segment that remain alive
     69         * @param second The line segment that get deleted
    3770         */
    38         private Node node;
    39         /**
    40          * These line segments are
    41          */
    42         private Collection<LineSegmentCombineEntry> combineLineSegments;
    43         /**
    44          * These tracks are combined
    45          */
    46         private Track firstTrack, secondTrack;
    47         /**
    48          * This line segment is deleted together with the second track. It was the
    49          * first segment of the second track (the other line segments were integrated
    50          * into the first track).
    51          */
    52         private LineSegment firstOfSecond;
    53 
    54         /**
    55          * Create the command and assign the data entries.
    56          */
    57         public CombineAndDeleteCommand(Node nodeToDelete,
    58                         Collection<LineSegmentCombineEntry> combineLineSegments,
    59                         Track firstTrack, Track secondTrack) {
    60                 node = nodeToDelete;
    61                 this.combineLineSegments = combineLineSegments;
    62                 this.firstTrack = firstTrack;
    63                 this.secondTrack = secondTrack;
     71        public CombineAndDeleteCommand(DataSet ds, LineSegment first, LineSegment second) {
     72                this.ds = ds;
     73                this.first = first;
     74                this.second = second;
     75                if (first.end != second.start)
     76                        throw new IllegalArgumentException();
    6477        }
    6578       
    6679        public void executeCommand() {
    67                 // line segments
    68                 DataSet ds = Main.main.ds;
    69                 for (LineSegmentCombineEntry e : combineLineSegments) {
    70                         if (e.first.start == e.second.end) {
    71                                 LineSegment tmp = e.first;
    72                                 e.first = e.second;
    73                                 e.second = tmp;
     80                first.end = second.end;
     81                oldProperties = new HashMap<Key, String>(first.keys);
     82                first.keys = mergeKeys(first.keys, second.keys);
     83
     84                // delete second line segment
     85                for (Track t : ds.tracks) {
     86                        if (t.segments.contains(second)) {
     87                                if (track == null)
     88                                        track = new LinkedList<Track>();
     89                                track.add(t);
    7490                        }
    75                         e.first.end = e.second.end;
    76                         e.first.keys = mergeKeys(e.first.keys, e.second.keys);
    77                         e.track.segments.remove(e.second);
    7891                }
     92                if (track != null) {
     93                        lineSegmentTrackPos = new LinkedList<Integer>();
     94                        for (Track t : track) {
     95                                int i = t.segments.indexOf(second);
     96                                if (i != -1)
     97                                        t.segments.remove(second);
     98                                lineSegmentTrackPos.add(i);
     99                        }
     100                }
     101                ds.lineSegments.remove(second);
    79102               
    80                 // tracks
    81                 if (firstTrack != null && secondTrack != null) {
    82                         if (firstTrack.getStartingNode() == secondTrack.getEndingNode()) {
    83                                 Track t = firstTrack;
    84                                 firstTrack = secondTrack;
    85                                 secondTrack = t;
     103                // delete node
     104                ds.nodes.remove(second.start);
     105        }
     106
     107        public void undoCommand() {
     108                ds.nodes.add(second.start);
     109                ds.lineSegments.add(second);
     110               
     111                if (track != null) {
     112                        Iterator<Track> it = track.iterator();
     113                        for (int i : lineSegmentTrackPos) {
     114                                Track t = it.next();
     115                                if (i != -1)
     116                                        t.segments.add(i, second);
    86117                        }
    87                         // concatenate the line segments.
    88                         LineSegment lastOfFirst = firstTrack.getEndingSegment();
    89                         firstOfSecond = secondTrack.getStartingSegment();
    90                         lastOfFirst.end = firstOfSecond.end;
    91                         lastOfFirst.keys = mergeKeys(lastOfFirst.keys, firstOfSecond.keys);
    92                         secondTrack.segments.remove(firstOfSecond);
    93                         // move the remaining line segments to first track.
    94                         firstTrack.segments.addAll(secondTrack.segments);
    95                         ds.tracks.remove(secondTrack);
    96118                }
    97                 ds.nodes.remove(node);
    98                 ds.rebuildBackReferences();
     119                first.keys = oldProperties;
     120                first.end = second.start;
    99121        }
    100122
     
    115137        public Component commandDescription() {
    116138                SelectionComponentVisitor v = new SelectionComponentVisitor();
    117                 v.visit(node);
     139                v.visit(second.start);
    118140                return new JLabel("Remove "+v.name, v.icon, JLabel.LEADING);
    119141        }
    120142
    121143        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    122                 deleted.add(node);
    123                 if (firstTrack != null)
    124                         modified.add(firstTrack);
    125                 if (secondTrack != null)
    126                         deleted.add(secondTrack);
    127                 if (firstOfSecond != null)
    128                         deleted.add(firstOfSecond);
    129                 for (LineSegmentCombineEntry e : combineLineSegments) {
    130                         modified.add(e.first);
    131                         deleted.add(e.second);
    132                         modified.add(e.track);
    133                 }
     144                deleted.add(second);
     145                deleted.add(second.start);
     146                modified.add(first);
     147                if (track != null)
     148                        modified.addAll(track);
    134149        }
    135150
  • src/org/openstreetmap/josm/command/Command.java

    r23 r30  
    1111 * one atomic action on a specific dataset, such as move or delete.
    1212 *
     13 * Remember, that the command must be executable and undoable, even if the
     14 * Main.main.ds has changed, so the command must save the dataset it operates on
     15 * if necessary.
     16 *
    1317 * @author imi
    1418 */
     
    2125
    2226        /**
     27         * Undoes the command.
     28         * It can be assumed, that all objects are in the same state they were before.
     29         * It can also be assumed that executeCommand was called exactly once before.
     30         */
     31        void undoCommand();
     32       
     33        /**
    2334         * Give a description of the command as component to draw
    2435         */
     
    2637       
    2738        /**
    28          * Fill in the changed data this command operates on (for sending to the server).
    29          * Add to the lists, don't clear them. The lists can be <code>null</code>
    30          * in which case they are ignored.
     39         * Fill in the changed data this command operates on.
     40         * Add to the lists, don't clear them.
    3141         *
    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>
     42         * @param modified  The modified primitives
     43         * @param deleted   The deleted primitives
     44         * @param added         The added primitives
    3545         */
    3646        void fillModifiedData(Collection<OsmPrimitive> modified,
  • src/org/openstreetmap/josm/command/DeleteCommand.java

    r23 r30  
    33import java.awt.Component;
    44import java.util.Collection;
    5 import java.util.LinkedList;
    65
    76import javax.swing.JLabel;
    87
    9 import org.openstreetmap.josm.Main;
     8import org.openstreetmap.josm.data.osm.DataSet;
    109import org.openstreetmap.josm.data.osm.Key;
    1110import org.openstreetmap.josm.data.osm.LineSegment;
     
    1918 * @author imi
    2019 */
    21 public class DeleteCommand implements Command, Visitor {
     20public class DeleteCommand implements Command {
    2221
     22        /**
     23         * The dataset this command operates on.
     24         */
     25        DataSet ds;
     26
     27        /**
     28         * Helper that adds the object.
     29         * @author imi
     30         */
     31        private final class AddVisitor implements Visitor {
     32                public void visit(Node n) {ds.nodes.add(n);}
     33                public void visit(LineSegment ls) {ds.lineSegments.add(ls);}
     34                public void visit(Track t) {ds.tracks.add(t);}
     35                public void visit(Key k) {throw new IllegalStateException("Keys are added by using ChangeKeyValueCommand");}
     36        }
     37
     38        /**
     39         * Helper that deletes the object. Does not respect back reference cache.
     40         * @author imi
     41         */
     42        private final class DeleteVisitor implements Visitor {
     43                public void visit(Node n) {ds.nodes.remove(n);}
     44                public void visit(LineSegment ls) {ds.lineSegments.remove(ls);}
     45                public void visit(Track t) {ds.tracks.remove(t);}
     46                public void visit(Key k) {throw new IllegalStateException("Keys are added by using ChangeKeyValueCommand");}
     47        }
     48       
     49       
     50       
    2351        /**
    2452         * The primitives that are going to deleted.
     
    2654        private final Collection<OsmPrimitive> data;
    2755       
    28         public DeleteCommand(Collection<OsmPrimitive> data) {
     56        public DeleteCommand(DataSet ds, Collection<OsmPrimitive> data) {
     57                this.ds = ds;
    2958                this.data = data;
    3059        }
    3160       
    3261        public void executeCommand() {
     62                Visitor v = new DeleteVisitor();
    3363                for (OsmPrimitive osm : data)
    34                         osm.visit(this);
     64                        osm.visit(v);
     65        }
     66
     67        public void undoCommand() {
     68                Visitor v = new AddVisitor();
     69                for (OsmPrimitive osm : data)
     70                        osm.visit(v);
    3571        }
    3672
     
    3975        }
    4076
    41         public void fillModifiedData(Collection<OsmPrimitive> modified,
    42                         Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    43                 if (deleted != null)
    44                         deleted.addAll(data);
     77        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     78                deleted.addAll(data);
    4579        }
    46 
    47 
    48         public void visit(Node n) {
    49                 Main.main.ds.nodes.remove(n);
    50                 Main.main.ds.removeBackReference(n);
    51         }
    52 
    53         public void visit(LineSegment ls) {
    54                 Main.main.ds.pendingLineSegments.remove(ls);
    55                 LinkedList<Track> tracksToDelete = new LinkedList<Track>();
    56                 for (Track t : Main.main.ds.tracks) {
    57                         t.segments.remove(ls);
    58                         if (t.segments.isEmpty())
    59                                 tracksToDelete.add(t);
    60                 }
    61                 for (Track t : tracksToDelete) {
    62                         Main.main.ds.tracks.remove(t);
    63                         Main.main.ds.removeBackReference(t);
    64                 }
    65                 Main.main.ds.removeBackReference(ls);
    66         }
    67 
    68         public void visit(Track t) {
    69                 Main.main.ds.tracks.remove(t);
    70                 for (LineSegment ls : t.segments)
    71                         Main.main.ds.pendingLineSegments.add(ls);
    72                 Main.main.ds.removeBackReference(t);
    73         }
    74 
    75         public void visit(Key k) {
    76                 // TODO
    77         }
    78 
    7980}
  • src/org/openstreetmap/josm/command/MoveCommand.java

    r23 r30  
    22
    33import java.awt.Component;
     4import java.awt.geom.Point2D;
    45import java.util.Collection;
     6import java.util.Iterator;
     7import java.util.LinkedList;
     8import java.util.List;
    59
    610import javax.swing.JLabel;
     
    2125         * The objects that should be moved.
    2226         */
    23         private Collection<OsmPrimitive> objects;
     27        private List<OsmPrimitive> objects;
    2428        /**
    2529         * x difference movement. Coordinates are in northern/eastern
     
    3236
    3337        /**
     38         * x/y List of all old positions of the objects.
     39         */
     40        private List<Point2D.Double> oldPositions;
     41       
     42        /**
    3443         * Create a MoveCommand and assign the initial object set and movement vector.
    3544         */
    3645        public MoveCommand(Collection<OsmPrimitive> objects, double x, double y) {
    37                 this.objects = objects;
     46                this.objects = new LinkedList<OsmPrimitive>(objects);
    3847                this.x = x;
    3948                this.y = y;
    40         }
    41 
    42         /**
    43          * Move the objects additional to the current movement.
    44          */
    45         public void move(double x, double y) {
    46                 this.x += x;
    47                 this.y += y;
    4849        }
    4950
     
    5859        }
    5960
     61        public void undoCommand() {
     62                AllNodesVisitor visitor = new AllNodesVisitor();
     63                for (OsmPrimitive osm : objects)
     64                        osm.visit(visitor);
     65                Iterator<Point2D.Double> it = oldPositions.iterator();
     66                for (Node n : visitor.nodes) {
     67                        Point2D.Double p = it.next();
     68                        n.coor.x = p.x;
     69                        n.coor.y = p.y;
     70                }
     71        }
     72
    6073        public Component commandDescription() {
    6174                String xstr = Math.abs(x) + (x < 0 ? "W" : "E");
     
    6578
    6679        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    67                 if (modified != null)
    68                         for (OsmPrimitive osm : objects)
    69                                 if (!modified.contains(osm))
    70                                         modified.add(osm);
     80                for (OsmPrimitive osm : objects)
     81                        if (!modified.contains(osm))
     82                                modified.add(osm);
    7183        }
    7284}
  • src/org/openstreetmap/josm/data/Preferences.java

    r23 r30  
    4545         */
    4646        private boolean drawRawGpsLines = false;
    47         /**
    48          * Whether deleted objects should be drawn in a dark color.
    49          */
    50         private boolean drawDeleted = false;
    5147        /**
    5248         * Force the drawing of lines between raw gps points if there are no
     
    139135                        drawRawGpsLines = root.getChild("drawRawGpsLines") != null;
    140136                        forceRawGpsLines = root.getChild("forceRawGpsLines") != null;
    141                         drawDeleted = root.getChild("drawDeleted") != null;
    142137                } catch (Exception e) {
    143138                        if (e instanceof PreferencesException)
     
    162157                if (drawRawGpsLines)
    163158                        children.add(new Element("drawRawGpsLines"));
    164                 if (drawDeleted)
    165                         children.add(new Element("drawDeleted"));
    166159                if (forceRawGpsLines)
    167160                        children.add(new Element("forceRawGpsLines"));
     
    256249                return forceRawGpsLines;
    257250        }
    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         }
    266251}
  • src/org/openstreetmap/josm/data/osm/DataSet.java

    r28 r30  
    66import java.util.LinkedList;
    77import java.util.Map;
    8 import java.util.Set;
    98
    109import org.openstreetmap.josm.data.Bounds;
    1110import org.openstreetmap.josm.data.SelectionTracker;
    12 import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
    1311
    1412/**
    15  * DataSet is the data behind one window in the application. It can consist of only a few
    16  * points up to the whole osm database. DataSet's can be merged together, split up into
    17  * several different ones, saved, (up/down/disk)loaded etc.
     13 * DataSet is the data behind the application. It can consist of only a few
     14 * points up to the whole osm database. DataSet's can be merged together,
     15 * saved, (up/down/disk)loaded etc.
    1816 *
    19  * Note, that DataSet is not an osm-primitive, it is not within
    20  * org.openstreetmap.josm.data.osm and has no key association but a few
    21  * members to store some information.
     17 * Note, that DataSet is not an osm-primitive and so has no key association
     18 * but a few members to store some information.
    2219 *
    2320 * @author imi
    2421 */
    25 public class DataSet extends SelectionTracker implements Cloneable {
     22public class DataSet extends SelectionTracker {
    2623
    2724        /**
     
    3330
    3431        /**
    35          * All pending line segments goes here. Pending line segments are those, that
    36          * are in this list but are in no track.
    37          */
    38         public Collection<LineSegment> pendingLineSegments = new LinkedList<LineSegment>();
     32         * All line segments goes here, even when they are in a track.
     33         */
     34        public Collection<LineSegment> lineSegments = new LinkedList<LineSegment>();
    3935
    4036        /**
     
    4743        public Collection<Track> tracks = new LinkedList<Track>();
    4844
    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        
    15245        /**
    15346         * Return the bounds of this DataSet, depending on X/Y values.
     
    218111        public void clearSelection() {
    219112                clearSelection(nodes);
    220                 clearSelection(pendingLineSegments);
     113                clearSelection(lineSegments);
    221114                clearSelection(tracks);
    222                 for (Track t : tracks)
    223                         clearSelection(t.segments);
    224115        }
    225116
     
    231122        public Collection<OsmPrimitive> getSelected() {
    232123                Collection<OsmPrimitive> sel = getSelected(nodes);
    233                 sel.addAll(getSelected(pendingLineSegments));
     124                sel.addAll(getSelected(lineSegments));
    234125                sel.addAll(getSelected(tracks));
    235                 for (Track t : tracks)
    236                         sel.addAll(getSelected(t.segments));
    237126                return sel;
    238127        }
     
    249138         * Tracks are merged, if they consist of the same line segments.
    250139         *
    251          * Additional to that, every two objects with the same id are merged.
     140         * TODO Additional to that, every two objects with the same id are merged.
    252141         *
    253142         * @param ds    The DataSet to merge into this one.
    254          * @return A list of all primitives that were used in the conjunction. That
    255          *              is all used primitives (the merged primitives and all added ones).
    256          */
    257         public Collection<OsmPrimitive> mergeFrom(DataSet ds) {
    258                 Collection<OsmPrimitive> data = new LinkedList<OsmPrimitive>();
    259 
    260                 Set<LineSegment> myLineSegments = new HashSet<LineSegment>();
    261                 myLineSegments.addAll(pendingLineSegments);
    262                 for (Track t : tracks)
    263                         myLineSegments.addAll(t.segments);
     143         */
     144        public void mergeFrom(DataSet ds) {
     145                // merge nodes
    264146               
    265                 Set<LineSegment> otherLineSegments = new HashSet<LineSegment>();
    266                 otherLineSegments.addAll(ds.pendingLineSegments);
    267                 for (Track t : ds.tracks)
    268                         otherLineSegments.addAll(t.segments);
    269                
    270                
    271                 // merge nodes
    272 
    273147                Map<Node, Node> nodeMap = new HashMap<Node, Node>();
     148
    274149                // find mergable
    275150                for (Node otherNode : ds.nodes)
     
    278153                                        nodeMap.put(otherNode, myNode);
    279154                // add
    280                 data.addAll(new HashSet<Node>(nodeMap.values()));
    281                 for (Node n : ds.nodes) {
    282                         if (!nodeMap.containsKey(n)) {
     155                for (Node n : ds.nodes)
     156                        if (!nodeMap.containsKey(n))
    283157                                nodes.add(n);
    284                                 data.add(n);
    285                         }
    286                 }
    287158                // reassign
    288                 for (LineSegment ls : otherLineSegments) {
     159                for (LineSegment ls : ds.lineSegments) {
    289160                        Node n = nodeMap.get(ls.start);
    290161                        if (n != null)
     
    300171                Map<LineSegment, LineSegment> lsMap = new HashMap<LineSegment, LineSegment>();
    301172                // find mergable
    302                 for (LineSegment otherLS : otherLineSegments)
    303                         for (LineSegment myLS : myLineSegments)
     173                for (LineSegment otherLS : ds.lineSegments)
     174                        for (LineSegment myLS : lineSegments)
    304175                                if (otherLS.start == myLS.start && otherLS.end == myLS.end)
    305176                                        lsMap.put(otherLS, myLS);
    306                 // add pendings (ls from track are added later
    307                 data.addAll(new HashSet<LineSegment>(lsMap.values()));
    308                 for (LineSegment ls : ds.pendingLineSegments) {
    309                         if (!lsMap.containsKey(ls)) {
    310                                 pendingLineSegments.add(ls);
    311                                 data.add(ls);
    312                         }
    313                 }
     177                // add ls
     178                for (LineSegment ls : ds.lineSegments)
     179                        if (!lsMap.containsKey(ls))
     180                                lineSegments.add(ls);
    314181                // reassign
    315182                for (Track t : ds.tracks) {
     
    323190
    324191                // merge tracks
     192               
    325193                LinkedList<Track> trackToAdd = new LinkedList<Track>();
    326194                for (Track otherTrack : ds.tracks) {
     
    329197                                if (myTrack.segments.equals(otherTrack.segments)) {
    330198                                        found = true;
    331                                         data.add(myTrack);
    332199                                        break;
    333200                                }
     
    336203                                trackToAdd.add(otherTrack);
    337204                }
    338                 data.addAll(trackToAdd);
    339205                tracks.addAll(trackToAdd);
    340 
    341                 rebuildBackReferences();
    342                 return data;
    343206        }
    344207
     
    373236                return sel;
    374237        }
    375 
    376 
    377         @Override
    378         public DataSet clone() {
    379                 try {return (DataSet)super.clone();} catch (CloneNotSupportedException e) {}
    380                 return null;
    381         }
    382238}
  • src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r28 r30  
    2727        public long id = 0;
    2828
    29         /**
    30          * If set to true, this object has been modified in the current session.
    31          */
    32         transient public boolean modified = false;
    33        
    3429        /**
    3530         * If set to true, this object is currently selected.
  • src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java

    r23 r30  
    44import java.awt.Graphics;
    55import java.awt.Point;
    6 import java.util.Collection;
    76
    8 import org.openstreetmap.josm.Main;
    97import org.openstreetmap.josm.data.osm.Key;
    108import org.openstreetmap.josm.data.osm.LineSegment;
     
    5149        /**
    5250         * Draw a small rectangle.
    53          *
    54          * - White if selected (as always)
    55          * - Yellow, if not used by any tracks or areas.
    56          * - Green, if only used by pending line segments.
    57          * - Darkblue, if used in tracks but are only as inbound node. Inbound are
    58          *   all nodes, that have only line segments of the same track and
    59          *   at least two different line segments attached.
    60          * - Red otherwise (means, this is a dead end or is part of more than
    61          *   one track).
     51         * White if selected (as always) or red otherwise.
    6252         *
    6353         * @param n The node to draw.
    6454         */
    6555        public void visit(Node n) {
    66                 if (n.isSelected()) {
    67                         drawNode(n, Color.WHITE); // selected
    68                         return;
    69                 }
    70 
    71                 Collection<LineSegment> lineSegments = Main.main.ds.nodeLsRef.get(n);
    72                 if (lineSegments == null || lineSegments.isEmpty()) {
    73                         drawNode(n, Color.YELLOW); // single waypoint only
    74                         return;
    75                 }
    76 
    77                 Collection<Track> tracks = Main.main.ds.nodeTrackRef.get(n);
    78                 if (tracks == null || tracks.isEmpty()) {
    79                         drawNode(n, Color.GREEN); // pending line
    80                         return;
    81                 }
    82                 if (tracks.size() > 1) {
    83                         drawNode(n, Color.RED); // more than one track
    84                         return;
    85                 }
    86                 int segmentUsed = 0;
    87                 for (LineSegment ls : tracks.iterator().next().segments)
    88                         if (n == ls.start || n == ls.end)
    89                                 ++segmentUsed;
    90                 drawNode(n, segmentUsed > 1 ? darkblue : Color.RED);
     56                drawNode(n, n.isSelected() ? Color.WHITE : Color.RED);
    9157        }
    9258
     59        /**
     60         * Draw just a line between the points.
     61         * White if selected (as always) or green otherwise.
     62         */
    9363        public void visit(LineSegment ls) {
    94                 if (forceColor != null)
    95                         g.setColor(forceColor);
    96                 else if (ls.isSelected())
    97                         g.setColor(Color.WHITE);
    98                 else if (Main.main.ds.pendingLineSegments.contains(ls))
    99                         g.setColor(darkgreen);
    100                 else
    101                         g.setColor(darkblue);
    102                 Point p1 = mv.getScreenPoint(ls.start.coor);
    103                 Point p2 = mv.getScreenPoint(ls.end.coor);
    104                 g.drawLine(p1.x, p1.y, p2.x, p2.y);
     64                drawLineSegment(ls, darkgreen);
    10565        }
    10666
     
    11171        public void visit(Track t) {
    11272                for (LineSegment ls : t.segments)
    113                         visit(ls);
     73                        drawLineSegment(ls, darkblue);
    11474        }
    11575
     76        /**
     77         * Do not draw a key.
     78         */
    11679        public void visit(Key k) {
    11780        }
     
    12891                g.drawRect(p.x-1, p.y-1, 2, 2);
    12992        }
     93
     94        /**
     95         * Draw a line with the given color.
     96         */
     97        private void drawLineSegment(LineSegment ls, Color col) {
     98                if (forceColor != null)
     99                        col = forceColor;
     100                else if (ls.isSelected())
     101                        col = Color.WHITE;
     102                g.setColor(col);
     103                Point p1 = mv.getScreenPoint(ls.start.coor);
     104                Point p2 = mv.getScreenPoint(ls.end.coor);
     105                g.drawLine(p1.x, p1.y, p2.x, p2.y);
     106        }
    130107}
  • src/org/openstreetmap/josm/gui/IconToggleButton.java

    r8 r30  
    2525                // Tooltip
    2626                String toolTipText = "";
    27                 Object o = action.getValue(Action.LONG_DESCRIPTION);
     27                Object o = action.getValue(Action.SHORT_DESCRIPTION);
    2828                if (o != null)
    29                         toolTipText += o.toString();
    30                 o = action.getValue(Action.ACCELERATOR_KEY);
    31                 if (o != null) {
    32                         String ksName = o.toString();
    33                         if (ksName.startsWith("pressed "))
    34                                 ksName = ksName.substring("pressed ".length());
    35                         else if (ksName.startsWith("released "))
    36                                 ksName = ksName.substring("released ".length());
    37                         toolTipText += " Shortcut: "+ksName;
    38                 }
     29                        toolTipText = o.toString();
    3930                setToolTipText(toolTipText);
    4031               
  • src/org/openstreetmap/josm/gui/MapFrame.java

    r17 r30  
    44import java.awt.Component;
    55import java.awt.Container;
    6 import java.awt.event.WindowAdapter;
    7 import java.awt.event.WindowEvent;
    86import java.beans.PropertyChangeEvent;
    97import java.beans.PropertyChangeListener;
    108
    119import javax.swing.AbstractButton;
     10import javax.swing.BoxLayout;
    1211import javax.swing.ButtonGroup;
    1312import javax.swing.JPanel;
     
    1918import org.openstreetmap.josm.actions.mapmode.AddNodeAction;
    2019import org.openstreetmap.josm.actions.mapmode.AddTrackAction;
    21 import org.openstreetmap.josm.actions.mapmode.CombineAction;
    2220import org.openstreetmap.josm.actions.mapmode.DeleteAction;
    2321import org.openstreetmap.josm.actions.mapmode.MapMode;
     
    5452         */
    5553        public MapStatus statusLine;
     54        /**
     55         * The action to open the layer list
     56         */
     57        private LayerList layerList;
     58        /**
     59         * Action to open the properties panel for the selected objects
     60         */
     61        private PropertiesDialog propertiesDialog;
     62        /**
     63         * Action to open a list of all selected objects
     64         */
     65        private SelectionListDialog selectionListDialog;
    5666
    5767        /**
     
    7686                toolBarActions.add(new IconToggleButton(this, new AddLineSegmentAction(this)));
    7787                toolBarActions.add(new IconToggleButton(this, new AddTrackAction(this)));
    78                 toolBarActions.add(new IconToggleButton(this, new CombineAction(this)));
    7988                toolBarActions.add(new IconToggleButton(this, new DeleteAction(this)));
    8089
     
    99108                });
    100109
    101                 // layer list
    102                 toolBarActions.add(new IconToggleButton(this, new LayerList(this)));
     110                JPanel toggleDialogs = new JPanel();
     111                add(toggleDialogs, BorderLayout.EAST);
     112
     113                toggleDialogs.setLayout(new BoxLayout(toggleDialogs, BoxLayout.Y_AXIS));
     114                toolBarActions.add(new IconToggleButton(this, layerList = new LayerList(this)));
     115                toggleDialogs.add(layerList);
     116                toolBarActions.add(new IconToggleButton(this, propertiesDialog = new PropertiesDialog(this)));
     117                toggleDialogs.add(propertiesDialog);
     118                toolBarActions.add(new IconToggleButton(this, selectionListDialog = new SelectionListDialog(this)));
     119                toggleDialogs.add(selectionListDialog);
    103120               
    104                 // properties
    105                 toolBarActions.add(new IconToggleButton(this, new PropertiesDialog(this)));
    106 
    107                 // selection dialog
    108                 SelectionListDialog selectionList = new SelectionListDialog(this);
    109                 final IconToggleButton buttonSelection = new IconToggleButton(this, selectionList);
    110                 selectionList.addWindowListener(new WindowAdapter(){
    111                         @Override
    112                         public void windowClosing(WindowEvent e) {
    113                                 buttonSelection.setSelected(false);
    114                         }
    115                 });
    116                 toolBarActions.add(buttonSelection);
    117121
    118122                // status line below the map
  • src/org/openstreetmap/josm/gui/MapView.java

    r29 r30  
    2020import org.openstreetmap.josm.data.Bounds;
    2121import org.openstreetmap.josm.data.GeoPoint;
     22import org.openstreetmap.josm.data.osm.DataSet;
    2223import org.openstreetmap.josm.data.osm.LineSegment;
    2324import org.openstreetmap.josm.data.osm.Node;
     
    2526import org.openstreetmap.josm.data.osm.Track;
    2627import org.openstreetmap.josm.data.projection.Projection;
    27 import org.openstreetmap.josm.gui.layer.EditLayer;
    2828import org.openstreetmap.josm.gui.layer.Layer;
     29import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    2930
    3031/**
     
    7475         * Direct link to the edit layer (if any) in the layers list.
    7576         */
    76         private EditLayer editLayer;
     77        private OsmDataLayer editLayer;
    7778        /**
    7879         * The layer from the layers list that is currently active.
     
    109110         */
    110111        public void addLayer(Layer layer) {
    111                 if (layer instanceof EditLayer) {
     112                // initialize the projection if it is the first layer
     113                if (layers.isEmpty())
     114                        Main.pref.getProjection().init(layer.getBoundsLatLon());
     115
     116                // reinitialize layer's data
     117                layer.init(Main.pref.getProjection());
     118
     119                if (layer instanceof OsmDataLayer) {
    112120                        if (editLayer != null) {
    113                                 // there can only be one EditLayer
     121                                // merge the layer into the existing one
     122                                if (!editLayer.isMergable(layer))
     123                                        throw new IllegalArgumentException("Cannot merge argument");
    114124                                editLayer.mergeFrom(layer);
     125                                repaint();
    115126                                return;
    116127                        }
    117                         editLayer = (EditLayer)layer;
    118                 }
    119                
     128                        editLayer = (OsmDataLayer)layer;
     129                }
     130
     131                // add as a new layer
    120132                layers.add(0,layer);
    121 
    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());
    128133
    129134                for (LayerChangeListener l : listeners)
    130135                        l.layerAdded(layer);
    131136
     137                // autoselect the new layer
    132138                setActiveLayer(layer);
    133139        }
     
    248254               
    249255                // pending line segments
    250                 for (LineSegment ls : Main.main.ds.pendingLineSegments) {
     256                for (LineSegment ls : Main.main.ds.lineSegments) {
    251257                        Point A = getScreenPoint(ls.start.coor);
    252258                        Point B = getScreenPoint(ls.end.coor);
     
    467473        /**
    468474         * Set the active selection to the given value and raise an layerchange event.
     475         * Also, swap the active dataset in Main.main if it is a datalayer.
    469476         */
    470477        public void setActiveLayer(Layer layer) {
     
    473480                Layer old = activeLayer;
    474481                activeLayer = layer;
     482                if (layer instanceof OsmDataLayer)
     483                        Main.main.ds = ((OsmDataLayer)layer).data;
    475484                if (old != layer) {
    476485                        for (LayerChangeListener l : listeners)
     
    491500         *              So editLayer does never return <code>null</code>.
    492501         */
    493         public EditLayer editLayer() {
     502        public OsmDataLayer editLayer() {
    494503                if (editLayer == null)
    495                         addLayer(new EditLayer(this));
     504                        addLayer(new OsmDataLayer(new DataSet(), "unnamed"));
    496505                return editLayer;
    497506        }
  • src/org/openstreetmap/josm/gui/PreferenceDialog.java

    r23 r30  
    6262                        Main.pref.setDrawRawGpsLines(drawRawGpsLines.isSelected());
    6363                        Main.pref.setForceRawGpsLines(forceRawGpsLines.isSelected());
    64                         Main.pref.setDrawDeleted(drawDeleted.isSelected());
    6564                        try {
    6665                                Main.pref.save();
     
    126125         */
    127126        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.");
    132127        /**
    133128         * The checkbox stating whether nodes should be merged together.
     
    203198                forceRawGpsLines.setSelected(Main.pref.isForceRawGpsLines());
    204199                forceRawGpsLines.setEnabled(drawRawGpsLines.isSelected());
    205                 drawDeleted.setToolTipText("Draw dark hints where objects were deleted.");
    206                 drawDeleted.setSelected(Main.pref.isDrawDeleted());
    207200                mergeNodes.setToolTipText("When importing GPX data, all nodes with exact the same lat/lon are merged.");
    208201                mergeNodes.setSelected(Main.pref.mergeNodes);
     
    219212                display.add(drawRawGpsLines, GBC.eol().insets(20,0,0,0));
    220213                display.add(forceRawGpsLines, GBC.eol().insets(40,0,0,0));
    221                 display.add(drawDeleted, GBC.eol().insets(20,0,0,0));
    222214                display.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
    223215
  • src/org/openstreetmap/josm/gui/SelectionManager.java

    r23 r30  
    278278                       
    279279                        // pending line segments
    280                         for (LineSegment ls : Main.main.ds.pendingLineSegments)
     280                        for (LineSegment ls : Main.main.ds.lineSegments)
    281281                                if (rectangleContainLineSegment(r, alt, ls))
    282282                                        selection.add(ls);
  • src/org/openstreetmap/josm/gui/dialogs/LayerList.java

    r29 r30  
    7474         */
    7575        public LayerList(MapFrame mapFrame) {
    76                 super(mapFrame, "Layers", "List of all layers", "layerlist", KeyEvent.VK_L, "Open a list of all loaded layers.");
    77                 setSize(250,256);
    78                 setMinimumSize(new Dimension(70,70));
     76                super("Layers", "List of all layers", "layerlist", KeyEvent.VK_L, "Open a list of all loaded layers.");
     77                setPreferredSize(new Dimension(320,100));
    7978                add(new JScrollPane(layers), BorderLayout.CENTER);
    8079                layers.setBackground(UIManager.getColor("Button.background"));
  • src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java

    r29 r30  
    33import java.awt.BorderLayout;
    44import java.awt.Component;
     5import java.awt.Dimension;
    56import java.awt.Font;
    67import java.awt.GridLayout;
     
    210211         */
    211212        public PropertiesDialog(MapFrame mapFrame) {
    212                 super(mapFrame, "Properties", "Properties Dialog", "properties", KeyEvent.VK_P, "Property for selected objects.");
     213                super("Properties", "Properties Dialog", "properties", KeyEvent.VK_P, "Property for selected objects.");
    213214                mv = mapFrame.mapView;
    214215
    215                 setLayout(new BorderLayout());
    216                 setSize(350,450);
     216                setPreferredSize(new Dimension(320,150));
    217217               
    218218                data.setColumnIdentifiers(new String[]{"Key", "Value"});
     
    241241                JScrollPane scrollPane = new JScrollPane(propertyTable);
    242242                scrollPane.addMouseListener(new DblClickWatch());
    243                 getContentPane().add(scrollPane, BorderLayout.CENTER);
     243                add(scrollPane, BorderLayout.CENTER);
    244244               
    245245                JPanel buttonPanel = new JPanel(new GridLayout(1,3));
     
    264264                buttonPanel.add(createButton("Add", "Add a new key/value pair to all objects", KeyEvent.VK_A, buttonAction));
    265265                buttonPanel.add(createButton("Edit", "Edit the value of the selected key for all objects", KeyEvent.VK_E, buttonAction));
    266                 buttonPanel.add(createButton("Delete", "Delete the selected key in all objects", KeyEvent.VK_DELETE, buttonAction));
    267                 getContentPane().add(buttonPanel, BorderLayout.SOUTH);
     266                buttonPanel.add(createButton("Delete", "Delete the selected key in all objects", KeyEvent.VK_D, buttonAction));
     267                add(buttonPanel, BorderLayout.SOUTH);
    268268        }
    269269       
  • src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java

    r22 r30  
    33import java.awt.BorderLayout;
    44import java.awt.Component;
     5import java.awt.Dimension;
    56import java.awt.event.ActionEvent;
    67import java.awt.event.ActionListener;
     
    4647         */
    4748        public SelectionListDialog(MapFrame mapFrame) {
    48                 super(mapFrame, "Current Selection", "Selection List", "selectionlist", KeyEvent.VK_E, "Open a selection list window.");
    49                 setLayout(new BorderLayout());
    50                 setSize(300,400);
     49                super("Current Selection", "Selection List", "selectionlist", KeyEvent.VK_E, "Open a selection list window.");
     50                setPreferredSize(new Dimension(320,150));
    5151                displaylist.setCellRenderer(new DefaultListCellRenderer(){
    5252                        private SelectionComponentVisitor visitor = new SelectionComponentVisitor();
     
    6464                displaylist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    6565
    66                 getContentPane().add(new JScrollPane(displaylist), BorderLayout.CENTER);
     66                add(new JScrollPane(displaylist), BorderLayout.CENTER);
    6767
    6868                JButton button = new JButton("Select", ImageProvider.get("mapmode", "selection"));
     
    7373                        }
    7474                });
    75                 getContentPane().add(button, BorderLayout.SOUTH);
     75                add(button, BorderLayout.SOUTH);
    7676
    7777                selectionChanged(Main.main.ds.getSelected());
  • src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java

    r21 r30  
    11package org.openstreetmap.josm.gui.dialogs;
    22
     3import java.awt.BorderLayout;
    34import java.awt.event.ActionEvent;
    4 import java.beans.PropertyChangeEvent;
    5 import java.beans.PropertyChangeListener;
    65import java.util.HashMap;
    76import java.util.Map;
     
    98import javax.swing.AbstractButton;
    109import javax.swing.Action;
    11 import javax.swing.JComponent;
    12 import javax.swing.JDialog;
    13 import javax.swing.KeyStroke;
     10import javax.swing.BorderFactory;
     11import javax.swing.JLabel;
     12import javax.swing.JPanel;
    1413
    15 import org.openstreetmap.josm.Main;
    1614import org.openstreetmap.josm.gui.ImageProvider;
    17 import org.openstreetmap.josm.gui.MapFrame;
    1815
    1916/**
     
    2320 * @author imi
    2421 */
    25 public class ToggleDialog extends JDialog implements Action {
     22public class ToggleDialog extends JPanel implements Action {
    2623
    2724        /**
     
    2926         * @param title The title of the dialog.
    3027         */
    31         public ToggleDialog(MapFrame mapFrame, String title, String name, String iconName, int mnemonic, String tooltip) {
    32                 super(Main.main, title, false);
     28        public ToggleDialog(String title, String name, String iconName, int mnemonic, String tooltip) {
    3329                putValue(SMALL_ICON, ImageProvider.get("dialogs", iconName));
    3430                putValue(NAME, name);
    3531                putValue(MNEMONIC_KEY, mnemonic);
    36                 KeyStroke ks = KeyStroke.getKeyStroke(mnemonic,0);
    37                 putValue(ACCELERATOR_KEY, ks);
    38                 mapFrame.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, this);
    39                 mapFrame.getActionMap().put(this, this);
    40                 putValue(LONG_DESCRIPTION, tooltip);
    41                 mapFrame.addPropertyChangeListener("visible", new PropertyChangeListener(){
    42                         public void propertyChange(PropertyChangeEvent evt) {
    43                                 if (evt.getNewValue() == Boolean.FALSE)
    44                                         setVisible(false);
    45                         }
    46                 });
     32                putValue(SHORT_DESCRIPTION, tooltip);
     33               
     34                setLayout(new BorderLayout());
     35                add(new JLabel(title), BorderLayout.NORTH);
     36                setVisible(false);
     37                setBorder(BorderFactory.createEtchedBorder());
    4738        }
    4839
  • src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java

    r23 r30  
    22
    33import java.awt.Graphics;
    4 import java.util.Collection;
     4import java.io.FileWriter;
     5import java.io.StringWriter;
     6import java.util.LinkedList;
    57
    68import javax.swing.Icon;
    79
     10import org.openstreetmap.josm.Main;
     11import org.openstreetmap.josm.command.Command;
    812import org.openstreetmap.josm.data.Bounds;
     13import org.openstreetmap.josm.data.osm.DataSet;
     14import org.openstreetmap.josm.data.osm.LineSegment;
    915import org.openstreetmap.josm.data.osm.Node;
    10 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    11 import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
     16import org.openstreetmap.josm.data.osm.Track;
    1217import org.openstreetmap.josm.data.osm.visitor.BoundingVisitor;
     18import org.openstreetmap.josm.data.osm.visitor.CsvVisitor;
    1319import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor;
    1420import org.openstreetmap.josm.data.projection.Projection;
     
    1723
    1824/**
    19  * A layer holding data imported from the osm server.
    20  *
     25 * A layer holding data from a specific dataset.
    2126 * The data can be fully edited.
    2227 *
     
    2833
    2934        /**
    30          * The data behind this layer. A list of primitives which are also in Main.main.ds.
     35         * The data behind this layer.
    3136         */
    32         private final Collection<OsmPrimitive> data;
     37        public final DataSet data;
     38
     39        /**
     40         * All commands that were made on the dataset.
     41         */
     42        private LinkedList<Command> commands = new LinkedList<Command>();
     43        private LinkedList<String> debugDsBefore = new LinkedList<String>();
    3344
    3445        /**
    3546         * Construct a OsmDataLayer.
    3647         */
    37         public OsmDataLayer(Collection<OsmPrimitive> data, String name) {
     48        public OsmDataLayer(DataSet data, String name) {
    3849                super(name);
    3950                this.data = data;
     
    5970        public void paint(Graphics g, MapView mv) {
    6071                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);
     72
     73                for (Track t : data.tracks)
     74                        visitor.visit(t);
     75                for (LineSegment ls : data.lineSegments)
     76                        visitor.visit(ls);
     77                for (Node n : data.nodes)
     78                        visitor.visit(n);
    6879        }
    6980
    7081        @Override
    7182        public String getToolTipText() {
    72                 return data.size()+" primitives.";
     83                return data.nodes.size()+" nodes, "+data.tracks.size()+" streets.";
    7384        }
    7485
    7586        @Override
    7687        public void mergeFrom(Layer from) {
    77                 OsmDataLayer layer = (OsmDataLayer)from;
    78                 data.addAll(layer.data);
     88                data.mergeFrom(((OsmDataLayer)from).data);
    7989        }
    8090
     
    8797        public Bounds getBoundsLatLon() {
    8898                BoundingVisitor b = new BoundingVisitor(BoundingVisitor.Type.LATLON);
    89                 for (OsmPrimitive osm : data)
    90                         osm.visit(b);
     99                for (Node n : data.nodes)
     100                        b.visit(n);
    91101                return b.bounds;
    92102        }
     
    95105        public Bounds getBoundsXY() {
    96106                BoundingVisitor b = new BoundingVisitor(BoundingVisitor.Type.XY);
    97                 for (OsmPrimitive osm : data)
    98                         osm.visit(b);
     107                for (Node n : data.nodes)
     108                        b.visit(n);
    99109                return b.bounds;
    100110        }
     
    102112        @Override
    103113        public void init(Projection projection) {
    104                 for (OsmPrimitive osm : data)
    105                         for (Node n : AllNodesVisitor.getAllNodes(osm))
    106                                 projection.latlon2xy(n.coor);
     114                for (Node n : data.nodes)
     115                        projection.latlon2xy(n.coor);
     116        }
     117
     118        /**
     119         * Execute the command and add it to the intern command queue. Also mark all
     120         * primitives in the command as modified.
     121         */
     122        public void add(Command c) {
     123                StringWriter sw = new StringWriter();
     124                CsvVisitor v = new CsvVisitor(sw);
     125                for (Node n : Main.main.ds.nodes) {
     126                        v.visit(n);
     127                        sw.append('\n');
     128                }
     129                for (LineSegment ls : Main.main.ds.lineSegments) {
     130                        v.visit(ls);
     131                        sw.append('\n');
     132                }
     133                for (Track t : Main.main.ds.tracks) {
     134                        v.visit(t);
     135                        sw.append('\n');
     136                }
     137                debugDsBefore.add(sw.getBuffer().toString());
     138               
     139                c.executeCommand();
     140                commands.add(c);
     141        }
     142
     143        /**
     144         * Undoes the last added command.
     145         */
     146        public void undo() {
     147                if (commands.isEmpty())
     148                        return;
     149                Command c = commands.removeLast();
     150                c.undoCommand();
     151               
     152                //DEBUG
     153                StringWriter sw = new StringWriter();
     154                CsvVisitor v = new CsvVisitor(sw);
     155                for (Node n : Main.main.ds.nodes) {
     156                        v.visit(n);
     157                        sw.append('\n');
     158                }
     159                for (LineSegment ls : Main.main.ds.lineSegments) {
     160                        v.visit(ls);
     161                        sw.append('\n');
     162                }
     163                for (Track t : Main.main.ds.tracks) {
     164                        v.visit(t);
     165                        sw.append('\n');
     166                }
     167                String s = Main.main.getMapFrame().mapView.editLayer().debugDsBefore.removeLast();
     168                if (!s.equals(sw.getBuffer().toString())) {
     169                        try {
     170                                FileWriter fw = new FileWriter("/home/imi/richtig");
     171                                fw.append(sw.getBuffer().toString());
     172                                fw.close();
     173                                fw = new FileWriter("/home/imi/falsch");
     174                                fw.append(s);
     175                                fw.close();
     176                        } catch (Exception x) {
     177                                x.printStackTrace();
     178                        }
     179                }
    107180        }
    108181}
  • src/org/openstreetmap/josm/io/GpxReader.java

    r29 r30  
    115115        private void parseTrack(Element e, DataSet ds) {
    116116                Track track = new Track();
    117                 boolean pendingLS = false; // is this track just a fake?
     117                boolean realLineSegment = false; // is this track just a fake?
    118118
    119119                for (Object o : e.getChildren()) {
     
    137137                                parseKeyValueExtensions(track, child);
    138138                                if (child.getChild("segment", OSM) != null)
    139                                         pendingLS = true;
     139                                        realLineSegment = true;
    140140                        } else if (child.getName().equals("link"))
    141141                                parseKeyValueLink(track, child);
     
    143143                                parseKeyValueTag(track, child);
    144144                }
    145                 if (pendingLS && track.segments.size() == 1)
    146                         ds.pendingLineSegments.add(track.segments.get(0));
    147                 else
     145                if (realLineSegment && track.segments.size() == 1)
     146                        ds.lineSegments.add(track.segments.get(0));
     147                else {
    148148                        ds.tracks.add(track);
     149                        ds.lineSegments.addAll(track.segments);
     150                }
    149151        }
    150152       
  • src/org/openstreetmap/josm/io/GpxWriter.java

    r29 r30  
    109109               
    110110                // encode pending line segments as tracks
    111                 for (LineSegment ls : Main.main.ds.pendingLineSegments) {
     111                for (LineSegment ls : Main.main.ds.lineSegments) {
    112112                        Element t = new Element("trk", GPX);
    113113                        t.getChildren().add(parseLineSegment(ls));
  • src/org/openstreetmap/josm/io/OsmReader.java

    r29 r30  
    118118                        else if (child.getName().equals("segment")) {
    119119                                LineSegment ls = parseLineSegment(child, data);
    120                                 if (data.pendingLineSegments.contains(ls))
     120                                if (data.lineSegments.contains(ls))
    121121                                        throw new JDOMException("Double segment definition "+ls.id);
    122122                                for (Track t : data.tracks)
    123123                                        if (t.segments.contains(ls))
    124124                                                throw new JDOMException("Double segment definition "+ls.id);
    125                                 data.pendingLineSegments.add(ls);
     125                                data.lineSegments.add(ls);
    126126                        } else if (child.getName().equals("track")) {
    127127                                Track track = parseTrack(child, data);
     
    175175                        Element child = (Element)o;
    176176                        long id = Long.parseLong(child.getAttributeValue("uid"));
    177                         LineSegment ls = findLineSegment(data.pendingLineSegments, id);
     177                        LineSegment ls = findLineSegment(data.lineSegments, id);
    178178                        if (ls != null) {
    179179                                track.segments.add(ls);
    180                                 data.pendingLineSegments.remove(ls);
     180                                data.lineSegments.remove(ls);
    181181                                continue;
    182182                        }
  • src/org/openstreetmap/josm/io/OsmWriter.java

    r27 r30  
    6262                for (Node n : ds.nodes)
    6363                        list.add(parseNode(n, properties));
    64                 for (LineSegment ls : ds.pendingLineSegments)
     64                for (LineSegment ls : ds.lineSegments)
    6565                        list.add(parseLineSegment(ls, properties));
    6666                // all other line segments
     
    159159                for (OsmPrimitive osm : ds.nodes)
    160160                        addIdAndKeyIds(osm, ids);
    161                 for (OsmPrimitive osm : ds.pendingLineSegments)
     161                for (OsmPrimitive osm : ds.lineSegments)
    162162                        addIdAndKeyIds(osm, ids);
    163163                for (Track t : ds.tracks) {
Note: See TracChangeset for help on using the changeset viewer.