Changeset 31 in josm


Ignore:
Timestamp:
2005-12-06T23:23:20+01:00 (18 years ago)
Author:
imi
Message:
  • fixed broken stuff from last checkin
  • complete undo and redo
  • futher simplification in DeleteAction
Files:
6 added
1 deleted
16 edited

Legend:

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

    r30 r31  
    1919import org.openstreetmap.josm.actions.OpenOsmServerAction;
    2020import org.openstreetmap.josm.actions.PreferencesAction;
     21import org.openstreetmap.josm.actions.RedoAction;
    2122import org.openstreetmap.josm.actions.SaveAction;
    2223import org.openstreetmap.josm.actions.UndoAction;
     
    6162         */
    6263        private MapFrame mapFrame;
     64
     65        public final UndoAction undoAction;
     66        public final RedoAction redoAction;
    6367       
    6468        /**
     
    7983                SaveAction saveAction = new SaveAction();
    8084                ExitAction exitAction = new ExitAction();
    81                 UndoAction undoAction = new UndoAction();
     85                undoAction = new UndoAction();
     86                redoAction = new RedoAction();
    8287                PreferencesAction preferencesAction = new PreferencesAction();
    8388                AboutAction aboutAction = new AboutAction();
     
    104109                editMenu.setMnemonic('E');
    105110                editMenu.add(undoAction);
     111                editMenu.add(redoAction);
    106112                editMenu.addSeparator();
    107113                editMenu.add(preferencesAction);
     
    122128                toolBar.addSeparator();
    123129                toolBar.add(undoAction);
     130                toolBar.add(redoAction);
    124131                toolBar.addSeparator();
    125132                toolBar.add(preferencesAction);
  • src/org/openstreetmap/josm/actions/UndoAction.java

    r30 r31  
    2222        public UndoAction() {
    2323                super("Undo", "undo", "Undo the last action.", null, KeyStroke.getAWTKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK));
     24                setEnabled(false);
    2425        }
    25        
     26
    2627        public void actionPerformed(ActionEvent e) {
    2728                if (Main.main.getMapFrame() == null)
  • src/org/openstreetmap/josm/actions/mapmode/AddTrackAction.java

    r30 r31  
    149149                Track t = new Track();
    150150                for (LineSegment ls : sortedLineSegments)
    151                         t.add(ls);
     151                        t.segments.add(ls);
    152152                mv.editLayer().add(new AddCommand(Main.main.ds, t));
    153153                Main.main.ds.clearSelection();
  • src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java

    r30 r31  
    44import java.awt.event.KeyEvent;
    55import java.awt.event.MouseEvent;
    6 import java.util.ArrayList;
    76import java.util.Collection;
    8 import java.util.HashSet;
    9 import java.util.Iterator;
     7import java.util.Collections;
    108import java.util.LinkedList;
    119
     
    1311
    1412import org.openstreetmap.josm.Main;
    15 import org.openstreetmap.josm.command.CombineAndDeleteCommand;
     13import org.openstreetmap.josm.command.Command;
    1614import org.openstreetmap.josm.command.DeleteCommand;
    17 import org.openstreetmap.josm.data.osm.DataSet;
    18 import org.openstreetmap.josm.data.osm.LineSegment;
    19 import org.openstreetmap.josm.data.osm.Node;
     15import org.openstreetmap.josm.command.SequenceCommand;
    2016import org.openstreetmap.josm.data.osm.OsmPrimitive;
    21 import org.openstreetmap.josm.data.osm.Track;
     17import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
    2218import org.openstreetmap.josm.gui.MapFrame;
    2319
    2420/**
    2521 * An action that enables the user to delete nodes and other objects.
    26  * 
     22 *
    2723 * The user can click on an object, which get deleted if possible. When Ctrl is
    2824 * pressed when releasing the button, the objects and all its references are
    29  * deleted as well. The exact definition of "all its references" are in
     25 * deleted. The exact definition of "all its references" are in
    3026 * @see #deleteWithReferences(OsmPrimitive)
    3127 *
    3228 * Pressing Alt will select the track instead of a line segment, as usual.
     29 *
     30 * If the user did not press Ctrl and the object has any references, the user
     31 * is informed and nothing is deleted.
    3332 *
    34  * If the user presses Ctrl, no combining is possible. Otherwise, DeleteAction
    35  * tries to combine the referencing objects as follows:
    36  *
    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.
    40  *
    41  * Combining is only possible, if both objects that should be combined have no
    42  * key with a different property value. The remaining keys are merged together.
    43  *
    44  * If a node is part of an area with more than 3 nodes, the node is removed from
    45  * the area and the area has now one fewer node.
    46  *
    47  * If combining fails, the node has still references and the user did not hold
    48  * Ctrl down, the deleting fails, the action informs the user and nothing is
    49  * deleted.
    50  *
    51  *
    5233 * If the user enters the mapmode and any object is selected, all selected
    53  * objects that can be deleted will. Combining applies to the selected objects.
     34 * objects that can be deleted will.
    5435 *
    5536 * @author imi
     
    6243         */
    6344        public DeleteAction(MapFrame mapFrame) {
    64                 super("Delete", "delete", "Delete nodes, streets or areas.", KeyEvent.VK_D, mapFrame);
     45                super("Delete", "delete", "Delete nodes, streets or segments.", KeyEvent.VK_D, mapFrame);
    6546        }
    6647
     
    8263                super.actionPerformed(e);
    8364                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                 }
     65                if (ctrl)
     66                        deleteWithReferences(Main.main.ds.getSelected());
     67                else
     68                        delete(Main.main.ds.getSelected(), false);
    10269                mv.repaint();
    10370        }
     
    11784
    11885                if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0)
    119                         deleteWithReferences(sel);
     86                        deleteWithReferences(Collections.singleton(sel));
    12087                else
    121                         delete(sel, true);
     88                        delete(Collections.singleton(sel), true);
    12289
    12390                mv.repaint();
     
    12592
    12693        /**
    127          * Delete the primitive and everything it references or beeing directly
    128          * referenced by, except of nodes which are deleted only if passed
    129          * directly or become unreferenced while deleting other objects.
    130          *
    131          * Nothing is combined as in @see #delete(OsmPrimitive).
     94         * Delete the primitives and everything they references.
    13295         *
    133          * Example (A is a track of line segment a and b. z is a node):
    134          *
    135          *              A
    136          *   B   x        z
    137          *  -----*--------+-----
    138          *       |     a      b
    139          *       |C
    140          *       |
    141          *       *y
    142          *       
    143          * If you delete C, C and y (since now unreferenced) gets deleted.
    144          * If you delete A, then A, a, b and z (since now unreferenced) gets deleted.
    145          * If you delete y, then y and C gets deleted.
    146          * TODO If you delete x, then a,B,C and x gets deleted. A now consist of b only.
    147          * If you delete a or b, then A, a, b and z gets deleted.
     96         * If a node is deleted, the node and all line segments, tracks and areas
     97         * the node is part of are deleted as well.
    14898         *
    149          * @param osm The object to delete.
     99         * If a line segment is deleted, all tracks the line segment is part of
     100         * are deleted as well. No nodes are deleted.
     101         *
     102         * If a track is deleted, only the track and no line segments or nodes are
     103         * deleted.
     104         *
     105         * If an area is deleted, only the area gets deleted.
     106         *
     107         * @param selection The list of all object to be deleted.
    150108         */
    151         private void deleteWithReferences(OsmPrimitive osm) {
    152                 // collect all tracks, areas and line segments that should be deleted
    153                 ArrayList<Track> tracksToDelete = new ArrayList<Track>();
    154                 ArrayList<LineSegment> lineSegmentsToDelete = new ArrayList<LineSegment>();
    155 
    156                 if (osm instanceof Node) {
    157                         // delete any track and line segment the node is in.
    158                         for (Track t : Main.main.ds.tracks)
    159                                 for (LineSegment ls : t.segments)
    160                                         if (ls.start == osm || ls.end == osm)
    161                                                 tracksToDelete.add(t);
    162                         for (LineSegment ls : Main.main.ds.lineSegments)
    163                                 if (ls.start == osm || ls.end == osm)
    164                                         lineSegmentsToDelete.add(ls);
    165                                
    166                 } else if (osm instanceof LineSegment) {
    167                         LineSegment lineSegment = (LineSegment)osm;
    168                         lineSegmentsToDelete.add(lineSegment);
    169                         for (Track t : Main.main.ds.tracks)
    170                                 for (LineSegment ls : t.segments)
    171                                         if (lineSegment == ls)
    172                                                 tracksToDelete.add(t);
    173                 } else if (osm instanceof Track) {
    174                         tracksToDelete.add((Track)osm);
    175                 }
    176                 // collect all nodes, that could be unreferenced after deletion
    177                 ArrayList<Node> checkUnreferencing = new ArrayList<Node>();
    178                 for (Track t : tracksToDelete) {
    179                         for (LineSegment ls : t.segments) {
    180                                 checkUnreferencing.add(ls.start);
    181                                 checkUnreferencing.add(ls.end);
    182                         }
    183                 }
    184                 for (LineSegment ls : lineSegmentsToDelete) {
    185                         checkUnreferencing.add(ls.start);
    186                         checkUnreferencing.add(ls.end);
    187                 }
    188 
    189                 Collection<OsmPrimitive> deleteData = new LinkedList<OsmPrimitive>();
    190                 deleteData.addAll(tracksToDelete);
    191                 deleteData.addAll(lineSegmentsToDelete);
    192                 // removing all unreferenced nodes
    193                 for (Node n : checkUnreferencing)
    194                         if (!isReferenced(n))
    195                                 deleteData.add(n);
    196                 // now, all references are killed. Delete the node (if it was a node)
    197                 if (osm instanceof Node)
    198                         deleteData.add(osm);
    199 
    200                 mv.editLayer().add(new DeleteCommand(Main.main.ds, deleteData));
     109        private void deleteWithReferences(Collection<OsmPrimitive> selection) {
     110                Collection<Command> deleteCommands = new LinkedList<Command>();
     111                for (OsmPrimitive osm : selection)
     112                        deleteCommands.add(new DeleteCommand(Main.main.ds, osm));
     113                mv.editLayer().add(new SequenceCommand(deleteCommands));
    201114        }
    202115
    203116        /**
    204          * Try to delete the given primitive. If the primitive is a node and
    205          * used somewhere, try to combine the references to make the node unused.
    206          * If this fails, inform the user and do not delete.
     117         * Try to delete all given primitives. If a primitive is
     118         * used somewhere and that "somewhere" is not going to be deleted,
     119         * inform the user and do not delete.
    207120         *
    208          * @param osm The object to delete.
     121         * @param selection The objects to delete.
    209122         * @param msgBox Whether a message box for errors should be shown
    210          * @return <code>true</code> if the object could be deleted
    211123         */
    212         private boolean delete(OsmPrimitive osm, boolean msgBox) {
    213                 if (osm instanceof Node && isReferenced((Node)osm))
    214                         return combineAndDelete((Node)osm, msgBox);
    215                 Collection<OsmPrimitive> c = new LinkedList<OsmPrimitive>();
    216                 c.add(osm);
    217                 mv.editLayer().add(new DeleteCommand(Main.main.ds, c));
    218                 return true;
    219         }
    220 
    221        
    222         /**
    223          * Return <code>true</code>, if the node is used by anything in the map.
    224          * @param n The node to check.
    225          * @return Whether the node is used by a track or area.
    226          */
    227         private boolean isReferenced(Node n) {
    228                 for (LineSegment ls : Main.main.ds.lineSegments)
    229                         if (ls.start == n || ls.end == n)
    230                                 return true;
    231                 // TODO areas
    232                 return false;
    233         }
    234 
    235         /**
    236          * Try to combine all objects when deleting the node n. If combining is not
    237          * possible, return an error string why. Otherwise, combine it and return
    238          * <code>null</code>.
    239          *
    240          * @param n The node that is going to be deleted.
    241          * @param msgBox Whether a message box should be displayed in case of problems
    242          * @return <code>true</code> if combining suceded.
    243          */
    244         private boolean combineAndDelete(Node n, boolean msgBox) {
    245                 DataSet ds = Main.main.ds;
    246                 Collection<LineSegment> lineSegmentsUsed = new HashSet<LineSegment>();
    247                 for (LineSegment ls : ds.lineSegments)
    248                         if (ls.start == n || ls.end == n)
    249                                 lineSegmentsUsed.add(ls);
    250 
    251                 if (lineSegmentsUsed.isEmpty())
    252                         // should not be called
    253                         throw new IllegalStateException();
    254                
    255                 if (lineSegmentsUsed.size() == 1) {
    256                         if (msgBox)
    257                                 JOptionPane.showMessageDialog(Main.main, "Node used by a line segment. Delete this first.");
    258                         return false;
     124        private void delete(Collection<OsmPrimitive> selection, boolean msgBox) {
     125                Collection<Command> deleteCommands = new LinkedList<Command>();
     126                for (OsmPrimitive osm : selection) {
     127                        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(Main.main.ds);
     128                        osm.visit(v);
     129                        if (!selection.containsAll(v.data)) {
     130                                if (msgBox)
     131                                        JOptionPane.showMessageDialog(Main.main, "This object is in use.");
     132                        } else
     133                                deleteCommands.add(new DeleteCommand(Main.main.ds, osm));
    259134                }
    260                        
    261                 if (lineSegmentsUsed.size() > 2) {
    262                         if (msgBox)
    263                                 JOptionPane.showMessageDialog(Main.main, "Node used by more than two line segments. Delete them first.");
    264                         return false;
    265                 }
    266                
    267                 Iterator<LineSegment> it = lineSegmentsUsed.iterator();
    268                 LineSegment first = it.next();
    269                 LineSegment second = it.next();
    270                
    271                 // wrong direction?
    272                 if (first.start == second.end) {
    273                         LineSegment t = first;
    274                         first = second;
    275                         second = t;
    276                 }
    277                
    278                 // combinable?
    279                 if (first.end != second.start || !first.end.keyPropertiesMergable(second.start)) {
    280                         if (msgBox)
    281                                 JOptionPane.showMessageDialog(Main.main, "Node used by line segments that cannot be combined.");
    282                         return false;
    283                 }
    284 
    285                 // Ok, we can combine. Do it.
    286                 mv.editLayer().add(new CombineAndDeleteCommand(ds, first, second));
    287                 return true;
     135                mv.editLayer().add(new SequenceCommand(deleteCommands));
    288136        }
    289137}
  • src/org/openstreetmap/josm/actions/mapmode/MoveAction.java

    r23 r31  
    88
    99import org.openstreetmap.josm.Main;
     10import org.openstreetmap.josm.command.Command;
    1011import org.openstreetmap.josm.command.MoveCommand;
    1112import org.openstreetmap.josm.data.GeoPoint;
     
    8384
    8485                Collection<OsmPrimitive> selection = Main.main.ds.getSelected();
    85                 mv.editLayer().add(new MoveCommand(selection, dx, dy));
     86                Command c = mv.editLayer().lastCommand();
     87                if (c instanceof MoveCommand && MoveCommand.getAffectedNodes(selection).equals(((MoveCommand)c).objects))
     88                        ((MoveCommand)c).moveAgain(dx,dy);
     89                else
     90                        mv.editLayer().add(new MoveCommand(selection, dx, dy));
    8691               
    8792                mv.repaint();
  • src/org/openstreetmap/josm/command/AddCommand.java

    r30 r31  
    11package org.openstreetmap.josm.command;
    22
    3 import java.awt.Component;
    43import java.util.Collection;
    54
    6 import javax.swing.JLabel;
    7 
    85import org.openstreetmap.josm.data.osm.DataSet;
    9 import org.openstreetmap.josm.data.osm.Key;
    10 import org.openstreetmap.josm.data.osm.LineSegment;
    11 import org.openstreetmap.josm.data.osm.Node;
    126import org.openstreetmap.josm.data.osm.OsmPrimitive;
    13 import org.openstreetmap.josm.data.osm.Track;
    14 import org.openstreetmap.josm.data.osm.visitor.SelectionComponentVisitor;
    15 import org.openstreetmap.josm.data.osm.visitor.Visitor;
     7import org.openstreetmap.josm.data.osm.visitor.AddVisitor;
     8import org.openstreetmap.josm.data.osm.visitor.DeleteVisitor;
    169
    1710/**
     
    2619         * The dataset this command operates on.
    2720         */
    28         DataSet ds;
     21        private DataSet ds;
    2922
    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        
    5223        /**
    5324         * The primitive to add to the dataset.
     
    6435
    6536        public void executeCommand() {
    66                 osm.visit(new AddVisitor());
     37                osm.visit(new AddVisitor(ds));
    6738        }
    6839
    6940        public void undoCommand() {
    70                 osm.visit(new RemoveVisitor());
     41                osm.visit(new DeleteVisitor(ds));
    7142        }
    7243
    73         public Component commandDescription() {
    74                 SelectionComponentVisitor v = new SelectionComponentVisitor();
    75                 osm.visit(v);
    76                 return new JLabel("Add "+v.name, v.icon, JLabel.LEADING);
    77         }
    78        
    7944        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    8045                added.add(osm);
  • src/org/openstreetmap/josm/command/ChangeKeyValueCommand.java

    r30 r31  
    11package org.openstreetmap.josm.command;
    22
    3 import java.awt.Component;
    43import java.util.Collection;
    54import java.util.HashMap;
     
    87import java.util.List;
    98import java.util.Map;
    10 
    11 import javax.swing.JLabel;
    129
    1310import org.openstreetmap.josm.data.osm.Key;
     
    7774        }
    7875
    79         public Component commandDescription() {
    80                 String objStr = objects.size()+" object" + (objects.size()==1?"":"s");
    81                 if (value == null)
    82                         return new JLabel("Delete the key '"+key+"' of "+objStr);
    83                 return new JLabel("Change the key '"+key+"' of "+objStr+" to '"+value+"'");
    84         }
    85 
    8676        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    8777                modified.addAll(objects);
  • src/org/openstreetmap/josm/command/Command.java

    r30 r31  
    11package org.openstreetmap.josm.command;
    22
    3 import java.awt.Component;
    43import java.util.Collection;
    54
     
    3231       
    3332        /**
    34          * Give a description of the command as component to draw
    35          */
    36         Component commandDescription();
    37        
    38         /**
    3933         * Fill in the changed data this command operates on.
    4034         * Add to the lists, don't clear them.
  • src/org/openstreetmap/josm/command/DeleteCommand.java

    r30 r31  
    11package org.openstreetmap.josm.command;
    22
    3 import java.awt.Component;
    43import java.util.Collection;
    5 
    6 import javax.swing.JLabel;
     4import java.util.HashSet;
    75
    86import org.openstreetmap.josm.data.osm.DataSet;
    9 import org.openstreetmap.josm.data.osm.Key;
    10 import org.openstreetmap.josm.data.osm.LineSegment;
    11 import org.openstreetmap.josm.data.osm.Node;
    127import org.openstreetmap.josm.data.osm.OsmPrimitive;
    13 import org.openstreetmap.josm.data.osm.Track;
     8import org.openstreetmap.josm.data.osm.visitor.AddVisitor;
     9import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
     10import org.openstreetmap.josm.data.osm.visitor.DeleteVisitor;
    1411import org.openstreetmap.josm.data.osm.visitor.Visitor;
    1512
     
    2320         * The dataset this command operates on.
    2421         */
    25         DataSet ds;
     22        final DataSet ds;
     23        /**
     24         * The primitive that get deleted.
     25         */
     26        final Collection<OsmPrimitive> data = new HashSet<OsmPrimitive>();
    2627
    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        
    51         /**
    52          * The primitives that are going to deleted.
    53          */
    54         private final Collection<OsmPrimitive> data;
    55        
    56         public DeleteCommand(DataSet ds, Collection<OsmPrimitive> data) {
     28        public DeleteCommand(DataSet ds, OsmPrimitive osm) {
    5729                this.ds = ds;
    58                 this.data = data;
     30                CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(ds);
     31                osm.visit(v);
     32                data.addAll(v.data);
     33                data.add(osm);
    5934        }
    6035       
    6136        public void executeCommand() {
    62                 Visitor v = new DeleteVisitor();
     37                Visitor v = new DeleteVisitor(ds);
    6338                for (OsmPrimitive osm : data)
    6439                        osm.visit(v);
     
    6641
    6742        public void undoCommand() {
    68                 Visitor v = new AddVisitor();
     43                Visitor v = new AddVisitor(ds);
    6944                for (OsmPrimitive osm : data)
    7045                        osm.visit(v);
    71         }
    72 
    73         public Component commandDescription() {
    74                 return new JLabel("Delete "+data.size()+" primitives");
    7546        }
    7647
  • src/org/openstreetmap/josm/command/MoveCommand.java

    r30 r31  
    11package org.openstreetmap.josm.command;
    22
    3 import java.awt.Component;
    43import java.awt.geom.Point2D;
    54import java.util.Collection;
     
    76import java.util.LinkedList;
    87import java.util.List;
    9 
    10 import javax.swing.JLabel;
    118
    129import org.openstreetmap.josm.data.osm.Node;
     
    2522         * The objects that should be moved.
    2623         */
    27         private List<OsmPrimitive> objects;
     24        public List<Node> objects = new LinkedList<Node>();
    2825        /**
    2926         * x difference movement. Coordinates are in northern/eastern
     
    3835         * x/y List of all old positions of the objects.
    3936         */
    40         private List<Point2D.Double> oldPositions;
    41        
     37        private List<Point2D.Double> oldPositions = new LinkedList<Point2D.Double>();
     38
    4239        /**
    4340         * Create a MoveCommand and assign the initial object set and movement vector.
    4441         */
    4542        public MoveCommand(Collection<OsmPrimitive> objects, double x, double y) {
    46                 this.objects = new LinkedList<OsmPrimitive>(objects);
    4743                this.x = x;
    4844                this.y = y;
     45                this.objects = getAffectedNodes(objects);
     46                for (Node n : this.objects)
     47                        oldPositions.add(new Point2D.Double(n.coor.x, n.coor.y));
    4948        }
    5049
    51         public void executeCommand() {
     50        /**
     51         * @return a list of all nodes that will be moved if using the given set of
     52         * objects.
     53         */
     54        public static List<Node> getAffectedNodes(Collection<OsmPrimitive> objects) {
    5255                AllNodesVisitor visitor = new AllNodesVisitor();
    5356                for (OsmPrimitive osm : objects)
    5457                        osm.visit(visitor);
    55                 for (Node n : visitor.nodes) {
     58                return new LinkedList<Node>(visitor.nodes);
     59        }
     60       
     61        /**
     62         * Move the same set of objects again by the specified vector. The vectors
     63         * are added together and so the resulting will be moved to the previous
     64         * vector plus this one.
     65         *
     66         * The move is immediatly executed and any undo will undo both vectors to
     67         * the original position the objects had before first moving.
     68         */
     69        public void moveAgain(double x, double y) {
     70                for (Node n : objects) {
     71                        n.coor.x += x;
     72                        n.coor.y += y;
     73                }
     74                this.x += x;
     75                this.y += y;
     76        }
     77       
     78        public void executeCommand() {
     79                for (Node n : objects) {
    5680                        n.coor.x += x;
    5781                        n.coor.y += y;
     
    6084
    6185        public void undoCommand() {
    62                 AllNodesVisitor visitor = new AllNodesVisitor();
    63                 for (OsmPrimitive osm : objects)
    64                         osm.visit(visitor);
    6586                Iterator<Point2D.Double> it = oldPositions.iterator();
    66                 for (Node n : visitor.nodes) {
     87                for (Node n : objects) {
    6788                        Point2D.Double p = it.next();
    6889                        n.coor.x = p.x;
     
    7192        }
    7293
    73         public Component commandDescription() {
    74                 String xstr = Math.abs(x) + (x < 0 ? "W" : "E");
    75                 String ystr = Math.abs(y) + (y < 0 ? "S" : "N");
    76                 return new JLabel("Move "+objects.size()+" primitives "+xstr+" "+ystr);
    77         }
    78 
    7994        public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    8095                for (OsmPrimitive osm : objects)
    81                         if (!modified.contains(osm))
    82                                 modified.add(osm);
     96                        modified.add(osm);
    8397        }
    8498}
  • src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r30 r31  
    1515abstract public class OsmPrimitive {
    1616
     17        private static int idcount = 0;
     18        public OsmPrimitive() {
     19                id = ++idcount;
     20        }
     21       
    1722        /**
    1823         * The key/value list for this primitive.
  • src/org/openstreetmap/josm/data/osm/Track.java

    r23 r31  
    1919
    2020       
    21         /**
    22          * Add the line segment to the track.
    23          */
    24         public void add(LineSegment ls) {
    25                 segments.add(ls);
    26         }
    27 
    2821        /**
    2922         * Return the last node in the track. This is the node, which no line segment
  • src/org/openstreetmap/josm/gui/PreferenceDialog.java

    r30 r31  
    243243                map.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
    244244
    245                
     245
    246246                tabPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
    247247       
     
    261261                pack();
    262262                Dimension s = Main.main.getSize();
    263                 setLocation(s.width/2-getWidth()/2, s.height/2-getHeight()/2);
     263                setLocation(Main.main.getX()+s.width/2-getWidth()/2, Main.main.getY()+s.height/2-getHeight()/2);
    264264        }
    265265
  • src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java

    r30 r31  
    22
    33import java.awt.Graphics;
    4 import java.io.FileWriter;
    5 import java.io.StringWriter;
    64import java.util.LinkedList;
     5import java.util.Stack;
    76
    87import javax.swing.Icon;
     
    1615import org.openstreetmap.josm.data.osm.Track;
    1716import org.openstreetmap.josm.data.osm.visitor.BoundingVisitor;
    18 import org.openstreetmap.josm.data.osm.visitor.CsvVisitor;
    1917import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor;
    2018import org.openstreetmap.josm.data.projection.Projection;
     
    4139         */
    4240        private LinkedList<Command> commands = new LinkedList<Command>();
    43         private LinkedList<String> debugDsBefore = new LinkedList<String>();
     41        /**
     42         * The stack for redoing commands
     43         */
     44        private Stack<Command> redoCommands = new Stack<Command>();
    4445
    4546        /**
     
    7172                SimplePaintVisitor visitor = new SimplePaintVisitor(g, mv, null);
    7273
     74                for (LineSegment ls : data.lineSegments)
     75                        visitor.visit(ls);
    7376                for (Track t : data.tracks)
    7477                        visitor.visit(t);
    75                 for (LineSegment ls : data.lineSegments)
    76                         visitor.visit(ls);
    7778                for (Node n : data.nodes)
    7879                        visitor.visit(n);
     
    117118
    118119        /**
     120         * @return the last command added or <code>null</code> if no command in queue.
     121         */
     122        public Command lastCommand() {
     123                return commands.isEmpty() ? null : commands.getLast();
     124        }
     125       
     126        /**
    119127         * Execute the command and add it to the intern command queue. Also mark all
    120128         * primitives in the command as modified.
    121129         */
    122130        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                
    139131                c.executeCommand();
    140132                commands.add(c);
     133                redoCommands.clear();
     134                // TODO: Replace with listener scheme
     135                Main.main.undoAction.setEnabled(true);
     136                Main.main.redoAction.setEnabled(false);
    141137        }
    142138
     
    149145                Command c = commands.removeLast();
    150146                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                 }
     147                redoCommands.push(c);
     148                //TODO: Replace with listener scheme
     149                Main.main.undoAction.setEnabled(!commands.isEmpty());
     150                Main.main.redoAction.setEnabled(true);
     151        }
     152        /**
     153         * Redoes the last undoed command.
     154         */
     155        public void redo() {
     156                if (redoCommands.isEmpty())
     157                        return;
     158                Command c = redoCommands.pop();
     159                c.executeCommand();
     160                commands.add(c);
     161                //TODO: Replace with listener scheme
     162                Main.main.undoAction.setEnabled(true);
     163                Main.main.redoAction.setEnabled(!redoCommands.isEmpty());
    180164        }
    181165}
  • src/org/openstreetmap/josm/io/GpxReader.java

    r30 r31  
    130130                                                LineSegment lineSegment = new LineSegment(start, node);
    131131                                                parseKeyValueExtensions(lineSegment, child.getChild("extensions", GPX));
    132                                                 track.add(lineSegment);
     132                                                track.segments.add(lineSegment);
    133133                                                start = null;
    134134                                        }
  • src/org/openstreetmap/josm/io/OsmServerReader.java

    r29 r31  
    9494         */
    9595        private Reader getReader(String urlStr) throws IOException {
    96                 System.out.println(urlStr);
    9796                initAuthentication();
    9897                URL url = new URL(urlStr);
Note: See TracChangeset for help on using the changeset viewer.