Changeset 7 in josm


Ignore:
Timestamp:
2005-10-02T20:32:00+02:00 (19 years ago)
Author:
imi
Message:

added mapmodes for adding and combining stuff. Reorganized images

Files:
13 added
1 deleted
20 edited
5 moved

Legend:

Unmodified
Added
Removed
  • src/org/openstreetmap/josm/actions/OpenGpxAction.java

    r2 r7  
    5656                        MapFrame map = new MapFrame(dataSet);
    5757                        Main.main.setMapFrame(gpxFile.getName(), map);
    58                         map.setVisible(true);
    5958                } catch (JDOMException x) {
    6059                        x.printStackTrace();
  • src/org/openstreetmap/josm/actions/mapmode/DebugAction.java

    r6 r7  
    88import java.awt.event.KeyEvent;
    99import java.awt.event.MouseEvent;
    10 import java.awt.event.MouseListener;
    11 import java.awt.event.MouseMotionListener;
    1210
    1311import javax.swing.JLabel;
     
    1614import org.openstreetmap.josm.data.osm.Track;
    1715import org.openstreetmap.josm.gui.MapFrame;
    18 import org.openstreetmap.josm.gui.MapView;
    1916
    2017/**
     
    2320 * @author imi
    2421 */
    25 public class DebugAction extends MapMode implements MouseMotionListener, MouseListener {
     22public class DebugAction extends MapMode {
    2623
    2724        private JLabel label = new JLabel();
     
    3229       
    3330        @Override
    34         public void registerListener(MapView mapView) {
    35                 mapView.addMouseMotionListener(this);
    36                 mapView.addMouseListener(this);
     31        public void registerListener() {
     32                super.registerListener();
     33                mv.addMouseMotionListener(this);
     34                mv.addMouseListener(this);
    3735                mapFrame.add(label, BorderLayout.SOUTH);
    3836        }
    3937
    4038        @Override
    41         public void unregisterListener(MapView mapView) {
    42                 mapView.removeMouseMotionListener(this);
    43                 mapView.removeMouseListener(this);
     39        public void unregisterListener() {
     40                super.unregisterListener();
     41                mv.removeMouseMotionListener(this);
     42                mv.removeMouseListener(this);
    4443                mapFrame.remove(label);
    4544        }
    4645
    47         public void mouseDragged(MouseEvent e) {
    48         }
    49 
    50         public void mouseMoved(MouseEvent e) {
    51         }
    52 
     46        @Override
    5347        public void mouseClicked(MouseEvent e) {
    5448                Graphics g = mapFrame.mapView.getGraphics();
     
    6660
    6761        private double perpendicularDistSq(double a, double b, double c) {
    68                 // I did this on paper by myself, so I am surprised too, that it is that
    69                 // performant ;-)
    7062                return a-(a-b+c)*(a-b+c)/4/c;
    7163        }
    72 
    73         public void mousePressed(MouseEvent e) {
    74         }
    75 
    76         public void mouseReleased(MouseEvent e) {
    77         }
    78 
    79         public void mouseEntered(MouseEvent e) {
    80         }
    81 
    82         public void mouseExited(MouseEvent e) {
    83         }
    84 
    8564}
  • src/org/openstreetmap/josm/actions/mapmode/MapMode.java

    r4 r7  
    22
    33import java.awt.event.ActionEvent;
     4import java.awt.event.MouseEvent;
     5import java.awt.event.MouseListener;
     6import java.awt.event.MouseMotionListener;
    47
    58import javax.swing.AbstractAction;
    69import javax.swing.ImageIcon;
     10import javax.swing.JComponent;
     11import javax.swing.KeyStroke;
    712
     13import org.openstreetmap.josm.data.osm.DataSet;
    814import org.openstreetmap.josm.gui.MapFrame;
    915import org.openstreetmap.josm.gui.MapView;
     
    1723 * control.
    1824 */
    19 abstract public class MapMode extends AbstractAction {
     25abstract public class MapMode extends AbstractAction implements MouseListener, MouseMotionListener {
    2026
    2127        /**
     
    2329         */
    2430        protected final MapFrame mapFrame;
     31        /**
     32         * Shortcut to the MapView.
     33         */
     34        protected final MapView mv;
     35        /**
     36         * Shortcut to the DataSet.
     37         */
     38        protected final DataSet ds;
    2539
    2640        /**
     
    3145         */
    3246        public MapMode(String name, String iconName, String tooltip, int mnemonic, MapFrame mapFrame) {
    33                 super(name, new ImageIcon("images/"+iconName+".png"));
     47                super(name, new ImageIcon("images/mapmode/"+iconName+".png"));
    3448                putValue(MNEMONIC_KEY, mnemonic);
     49                putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(mnemonic,0));
    3550                putValue(LONG_DESCRIPTION, tooltip);
     51                mapFrame.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(mnemonic,0), this);
     52                mapFrame.getActionMap().put(this, this);
    3653                this.mapFrame = mapFrame;
     54                mv = mapFrame.mapView;
     55                ds = mv.dataSet;
    3756        }
    3857       
     
    4160         * @param mapView       The view, where the listener should be registered.
    4261         */
    43         abstract public void registerListener(MapView mapView);
     62        public void registerListener() {
     63                firePropertyChange("active", false, true);
     64        }
    4465       
    4566        /**
     
    4768         * @param mapView       The view from which the listener should be deregistered.
    4869         */
    49         abstract public void unregisterListener(MapView mapView);
     70        public void unregisterListener() {
     71                firePropertyChange("active", true, false);
     72        }
    5073
    5174        /**
     
    5578                mapFrame.selectMapMode(this);
    5679        }
     80       
     81        /**
     82         * Does nothing. Only to subclass.
     83         */
     84        public void mouseClicked(MouseEvent e) {}
     85        /**
     86         * Does nothing. Only to subclass.
     87         */
     88        public void mousePressed(MouseEvent e) {}
     89        /**
     90         * Does nothing. Only to subclass.
     91         */
     92        public void mouseReleased(MouseEvent e) {}
     93        /**
     94         * Does nothing. Only to subclass.
     95         */
     96        public void mouseEntered(MouseEvent e) {}
     97        /**
     98         * Does nothing. Only to subclass.
     99         */
     100        public void mouseExited(MouseEvent e) {}
     101        /**
     102         * Does nothing. Only to subclass.
     103         */
     104        public void mouseMoved(MouseEvent e) {}
     105        /**
     106         * Does nothing. Only to subclass.
     107         */
     108        public void mouseDragged(MouseEvent e) {}
    57109}
  • src/org/openstreetmap/josm/actions/mapmode/MoveAction.java

    r4 r7  
    11package org.openstreetmap.josm.actions.mapmode;
    22
     3import java.awt.Cursor;
     4import java.awt.Point;
    35import java.awt.event.KeyEvent;
     6import java.awt.event.MouseEvent;
     7import java.util.Collection;
     8import java.util.HashSet;
    49
     10import org.openstreetmap.josm.data.osm.Node;
     11import org.openstreetmap.josm.data.osm.OsmPrimitive;
    512import org.openstreetmap.josm.gui.MapFrame;
    6 import org.openstreetmap.josm.gui.MapView;
    713
    814/**
     
    1016 *
    1117 * If any object is selected, all selected objects are moved. If no object is
    12  * selected, only nodes can be moved. In this case, the Node which is nearest to
    13  * the mouse cursor when the left mouse button is pressed get selected and moved.
    14  * (Of course, all primitives, which use this node are moved somewhat too).
     18 * selected, the nearest object will be selected and moved. In this case, the
     19 * object will be unselected as soon as movement stopped.
    1520 *
    1621 * @author imi
     
    1823public class MoveAction extends MapMode {
    1924
     25        /**
     26         * The old cursor before the user pressed the mouse button.
     27         */
     28        private Cursor oldCursor;
     29        /**
     30         * The position of the mouse before the user moves a node.
     31         */
     32        private Point mousePos;
     33        /**
     34         * Non-<code>null</code>, if no object was selected before movement
     35         * (and so the object get unselected after mouse release).
     36         */
     37        private OsmPrimitive singleOsmPrimitive;
     38
     39        /**
     40         * Create a new MoveAction
     41         * @param mapFrame The MapFrame, this action belongs to.
     42         */
    2043        public MoveAction(MapFrame mapFrame) {
    2144                super("Move", "move", "Move selected objects around", KeyEvent.VK_M, mapFrame);
     
    2346
    2447        @Override
    25         public void registerListener(MapView mapView) {
     48        public void registerListener() {
     49                super.registerListener();
     50                mv.addMouseListener(this);
     51                mv.addMouseMotionListener(this);
    2652        }
    2753
    2854        @Override
    29         public void unregisterListener(MapView mapView) {
     55        public void unregisterListener() {
     56                super.unregisterListener();
     57                mv.removeMouseListener(this);
     58                mv.removeMouseMotionListener(this);
    3059        }
    3160
     61       
     62        /**
     63         * If the left mouse button is pressed, move all currently selected
     64         * objects.
     65         */
     66        @Override
     67        public void mouseDragged(MouseEvent e) {
     68                if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
     69                        return;
     70               
     71                if (mousePos == null) {
     72                        mousePos = e.getPoint();
     73                        singleOsmPrimitive = null;
     74                }
     75
     76                int dx = e.getX() - mousePos.x;
     77                int dy = e.getY() - mousePos.y;
     78                if (dx == 0 && dy == 0)
     79                        return;
     80
     81                Collection<OsmPrimitive> selection = ds.getSelected();
     82                // creating a list of all nodes that should be moved.
     83                Collection<Node> movingNodes = new HashSet<Node>();
     84                for (OsmPrimitive osm : selection)
     85                        movingNodes.addAll(osm.getAllNodes());
     86
     87                for (Node n : movingNodes) {
     88                        Point pos = mv.getScreenPoint(n.coor);
     89                        pos.x += dx;
     90                        pos.y += dy;
     91                        n.coor = mv.getPoint(pos.x, pos.y, true);
     92                }
     93                mv.repaint();
     94               
     95                mousePos = e.getPoint();
     96        }
     97
     98        /**
     99         * Look, whether any object is selected. If not, select the nearest node.
     100         * If there are no nodes in the dataset, do nothing.
     101         *
     102         * If the user did not press the left mouse button, do nothing.
     103         *
     104         * Also remember the starting position of the movement and change the mouse
     105         * cursor to movement.
     106         */
     107        @Override
     108        public void mousePressed(MouseEvent e) {
     109                if (e.getButton() != MouseEvent.BUTTON1)
     110                        return;
     111
     112                if (ds.getSelected().size() == 0) {
     113                        OsmPrimitive osm = mv.getNearest(e.getPoint(), (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0);
     114                        if (osm != null)
     115                                osm.selected = true;
     116                        singleOsmPrimitive = osm;
     117                        mv.repaint();
     118                } else
     119                        singleOsmPrimitive = null;
     120               
     121                mousePos = e.getPoint();
     122                oldCursor = mv.getCursor();
     123                mv.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
     124        }
     125       
     126        /**
     127         * Restore the old mouse cursor.
     128         */
     129        @Override
     130        public void mouseReleased(MouseEvent e) {
     131                mv.setCursor(oldCursor);
     132                if (singleOsmPrimitive != null) {
     133                        singleOsmPrimitive.selected = false;
     134                        mv.repaint();
     135                }
     136        }
    32137}
  • src/org/openstreetmap/josm/actions/mapmode/SelectionAction.java

    r4 r7  
    11package org.openstreetmap.josm.actions.mapmode;
    22
    3 import java.awt.Point;
    43import java.awt.Rectangle;
    54import java.awt.event.KeyEvent;
    6 import java.awt.event.MouseEvent;
    7 import java.awt.geom.Point2D;
     5import java.util.Collection;
    86
    9 import org.openstreetmap.josm.data.osm.LineSegment;
    10 import org.openstreetmap.josm.data.osm.Node;
    117import org.openstreetmap.josm.data.osm.OsmPrimitive;
    12 import org.openstreetmap.josm.data.osm.Track;
    138import org.openstreetmap.josm.gui.MapFrame;
    14 import org.openstreetmap.josm.gui.MapView;
    159import org.openstreetmap.josm.gui.SelectionManager;
    1610import org.openstreetmap.josm.gui.SelectionManager.SelectionEnded;
     
    5246 * and the user clicked in or 10 pixel away from an area, this area is selected.
    5347 * If there is even no area, nothing is selected. Shift and Ctrl key applies to
    54  * this as usual.
     48 * this as usual. For more, @see MapView#getNearest(Point, boolean)
    5549 *
    5650 * @author imi
     
    5852public class SelectionAction extends MapMode implements SelectionEnded {
    5953
    60         /**
    61          * Shortcut for the MapView.
    62          */
    63         private MapView mv;
    6454        /**
    6555         * The SelectionManager that manages the selection rectangle.
     
    6959        /**
    7060         * Create a new SelectionAction in the given frame.
    71          * @param mapFrame
     61         * @param mapFrame The frame this action belongs to
    7262         */
    7363        public SelectionAction(MapFrame mapFrame) {
    7464                super("Selection", "selection", "Select objects by dragging or clicking", KeyEvent.VK_S, mapFrame);
    75                 this.mv = mapFrame.mapView;
    7665                this.selectionManager = new SelectionManager(this, false, mv);
    7766        }
    7867
    7968        @Override
    80         public void registerListener(MapView mapView) {
    81                 selectionManager.register(mapView);
     69        public void registerListener() {
     70                super.registerListener();
     71                selectionManager.register(mv);
    8272        }
    8373
    8474        @Override
    85         public void unregisterListener(MapView mapView) {
    86                 selectionManager.unregister(mapView);
     75        public void unregisterListener() {
     76                super.unregisterListener();
     77                selectionManager.unregister(mv);
    8778        }
    8879
     
    9182         * Check the state of the keys and buttons and set the selection accordingly.
    9283         */
    93         public void selectionEnded(Rectangle r, int modifiers) {
    94                 boolean shift = (modifiers & MouseEvent.SHIFT_DOWN_MASK) != 0;
    95                 boolean alt = (modifiers & MouseEvent.ALT_DOWN_MASK) != 0;
    96                 boolean ctrl = (modifiers & MouseEvent.CTRL_DOWN_MASK) != 0;
     84        public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
    9785                if (shift && ctrl)
    9886                        return; // not allowed together
    9987
    100                 if (!ctrl && !shift) {
    101                         // remove the old selection. The new selection will replace the old.
    102                         mv.dataSet.clearSelection();
    103                 }
     88                if (!ctrl && !shift)
     89                        ds.clearSelection(); // new selection will replace the old.
    10490
    105                 // now set the selection to this value
    106                 boolean selection = !ctrl;
    107 
    108                 // whether user only clicked, not dragged.
    109                 boolean clicked = r.width <= 2 && r.height <= 2;
    110                 Point2D.Double center = new Point2D.Double(r.getCenterX(), r.getCenterY());
    111 
    112                 try {
    113                         // nodes
    114                         double minDistanceSq = Double.MAX_VALUE;
    115                         OsmPrimitive minPrimitive = null;
    116                         for (Node n : mv.dataSet.allNodes) {
    117                                 Point sp = mv.getScreenPoint(n.coor);
    118                                 double dist = center.distanceSq(sp);
    119                                 if (clicked && minDistanceSq > dist && dist < 100) {
    120                                         minDistanceSq = center.distanceSq(sp);
    121                                         minPrimitive = n;
    122                                 } else if (r.contains(sp))
    123                                         n.selected = selection;
    124                         }
    125                         if (minPrimitive != null) {
    126                                 minPrimitive.selected = selection;
    127                                 return;
    128                         }
    129 
    130                         // tracks
    131                         minDistanceSq = Double.MAX_VALUE;
    132                         for (Track t : mv.dataSet.tracks) {
    133                                 boolean wholeTrackSelected = t.segments.size() > 0;
    134                                 for (LineSegment ls : t.segments) {
    135                                         if (clicked) {
    136                                                 Point A = mv.getScreenPoint(ls.start.coor);
    137                                                 Point B = mv.getScreenPoint(ls.end.coor);
    138                                                 double c = A.distanceSq(B);
    139                                                 double a = center.distanceSq(B);
    140                                                 double b = center.distanceSq(A);
    141                                                 double perDist = perpendicularDistSq(a,b,c);
    142                                                 if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
    143                                                         minDistanceSq = perDist;
    144                                                         if (alt)
    145                                                                 minPrimitive = t;
    146                                                         else
    147                                                                 minPrimitive = ls;
    148                                                 }
    149                                         } else {
    150                                                 if (alt) {
    151                                                         Point p1 = mv.getScreenPoint(ls.start.coor);
    152                                                         Point p2 = mv.getScreenPoint(ls.end.coor);
    153                                                         if (r.intersectsLine(p1.x, p1.y, p2.x, p2.y))
    154                                                                 ls.selected = selection;
    155                                                         else
    156                                                                 wholeTrackSelected = false;
    157                                                 } else {
    158                                                         if (r.contains(mv.getScreenPoint(ls.start.coor))
    159                                                                         && r.contains(mv.getScreenPoint(ls.end.coor)))
    160                                                                 ls.selected = selection;
    161                                                         else
    162                                                                 wholeTrackSelected = false;
    163                                                 }
    164                                         }
    165                                 }
    166                                 if (wholeTrackSelected && !clicked)
    167                                         t.selected = true;
    168                         }
    169                         if (minPrimitive != null) {
    170                                 minPrimitive.selected = selection;
    171                                 return;
    172                         }
    173                        
    174                         // TODO arrays
    175                 } finally {
    176                         mv.repaint();
    177                 }
    178         }
    179 
    180         /**
    181          * Calculates the squared perpendicular distance named "h" from a point C to the
    182          * straight line going to the points A and B, where the distance to B is
    183          * sqrt(a) and the distance to A is sqrt(b).
    184          *
    185          * Think of a, b and c as the squared line lengths of any ordinary triangle
    186          * A,B,C. a = BC, b = AC and c = AB. The straight line goes through A and B
    187          * and the desired return value is the perpendicular distance from C to c.
    188          *
    189          * @param a Squared distance from B to C.
    190          * @param b Squared distance from A to C.
    191          * @param c Squared distance from A to B.
    192          * @return The perpendicular distance from C to c.
    193          */
    194         private double perpendicularDistSq(double a, double b, double c) {
    195                 // I did this on paper by myself, so I am surprised too, that it is that
    196                 // performant ;-)
    197                 return a-(a-b+c)*(a-b+c)/4/c;
     91                Collection<OsmPrimitive> selectionList = selectionManager.getObjectsInRectangle(r,alt);
     92                for (OsmPrimitive osm : selectionList)
     93                        osm.selected = !ctrl;
     94                mv.repaint();
    19895        }
    19996}
  • src/org/openstreetmap/josm/actions/mapmode/ZoomAction.java

    r6 r7  
    3434         */
    3535        private final SelectionManager selectionManager;
    36        
    37        
     36
     37
    3838        /**
    3939         * Construct a ZoomAction without a label.
     
    4949         * Zoom to the rectangle on the map.
    5050         */
    51         public void selectionEnded(Rectangle r, int modifier) {
     51        public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
    5252                if (r.width >= 3 && r.height >= 3) {
    5353                        double scale = mv.getScale() * r.getWidth()/mv.getWidth();
     
    5858
    5959        @Override
    60         public void registerListener(MapView mapView) {
    61                 selectionManager.register(mapView);
     60        public void registerListener() {
     61                super.registerListener();
     62                selectionManager.register(mv);
    6263        }
    6364
    6465        @Override
    65         public void unregisterListener(MapView mapView) {
    66                 selectionManager.unregister(mapView);
     66        public void unregisterListener() {
     67                super.unregisterListener();
     68                selectionManager.unregister(mv);
    6769        }
    6870}
  • src/org/openstreetmap/josm/data/GeoPoint.java

    r6 r7  
    11package org.openstreetmap.josm.data;
     2
    23
    34
     
    6566                return super.hashCode();
    6667        }
     68
     69        /**
     70         * Return the squared distance of the northing/easting values between
     71         * this and the argument.
     72         *
     73         * @param other The other point to calculate the distance to.
     74         * @return The square of the distance between this and the other point,
     75         *              regarding to the x/y values.
     76         */
     77        public double distanceXY(GeoPoint other) {
     78                return (x-other.x)*(x-other.x)+(y-other.y)*(y-other.y);
     79        }
    6780       
    6881       
  • src/org/openstreetmap/josm/data/osm/DataSet.java

    r6 r7  
    22
    33import java.util.Collection;
    4 import java.util.List;
     4import java.util.HashSet;
     5import java.util.LinkedList;
    56
    67import org.openstreetmap.josm.data.Bounds;
     
    1920
    2021        /**
    21          * All nodes goes here, even when included in other data (tracks etc) listed.
     22         * All nodes goes here, even when included in other data (tracks etc).
    2223         * This enables the instant conversion of the whole DataSet by iterating over
    2324         * this data structure.
    2425         */
    25         public List<Node> allNodes;
     26        public Collection<Node> nodes = new LinkedList<Node>();
     27
     28        /**
     29         * All pending line segments goes here. Pending line segments are those, that
     30         * are in this list but are in no track.
     31         */
     32        public Collection<LineSegment> pendingLineSegments = new LinkedList<LineSegment>();
    2633
    2734        /**
     
    3239         * track list.
    3340         */
    34         public List<Track> tracks;
     41        public Collection<Track> tracks;
    3542
    3643        /**
     
    4451         */
    4552        public Bounds getBoundsXY() {
    46                 if (allNodes.size() == 0)
     53                if (nodes.isEmpty())
    4754                        return null;
    4855
    49                 Bounds b = new Bounds(allNodes.get(0).coor.clone(), allNodes.get(0).coor.clone());
    50                 for (Node w : allNodes)
     56                Node first = nodes.iterator().next();
     57                Bounds b = new Bounds(first.coor.clone(), first.coor.clone());
     58                for (Node w : nodes)
    5159                {
    5260                        if (Double.isNaN(w.coor.x) || Double.isNaN(w.coor.y))
     
    6573
    6674        /**
     75         * Return all tracks that contain the node. If nothing found, an empty array
     76         * is returned.
     77         *
     78         * @param node This node is searched.
     79         * @return All tracks, that reference the node in one of its line segments.
     80         */
     81        public Collection<Track> getReferencedTracks(Node n) {
     82                Collection<Track> all = new LinkedList<Track>();
     83                for (Track t : tracks) {
     84                        for (LineSegment ls : t.segments) {
     85                                if (ls.start == n || ls.end == n) {
     86                                        all.add(t);
     87                                        break;
     88                                }
     89                        }
     90                }
     91                return all;
     92        }
     93       
     94        /**
    6795         * Return the bounds of this DataSet, depending on lat/lon values.
    6896         * The min of the return value is the upper left GeoPoint, the max the lower
     
    75103         */
    76104        public Bounds getBoundsLatLon() {
    77                 if (allNodes.size() == 0)
     105                if (nodes.isEmpty())
    78106                        return null;
    79107
    80                 Bounds b = new Bounds(allNodes.get(0).coor.clone(), allNodes.get(0).coor.clone());
    81                 for (Node w : allNodes)
     108                Node first = nodes.iterator().next();
     109                Bounds b = new Bounds(first.coor.clone(), first.coor.clone());
     110                for (Node w : nodes)
    82111                {
    83112                        if (Double.isNaN(w.coor.lat) || Double.isNaN(w.coor.lon))
     
    99128         */
    100129        public void clearSelection() {
    101                 clearSelection(allNodes);
     130                clearSelection(nodes);
    102131                clearSelection(tracks);
    103132                for (Track t : tracks)
    104133                        clearSelection(t.segments);
     134        }
     135
     136        /**
     137         * Return a list of all selected objects. Even keys are returned.
     138         * @return List of all selected objects.
     139         */
     140        public Collection<OsmPrimitive> getSelected() {
     141                Collection<OsmPrimitive> sel = getSelected(nodes);
     142                sel.addAll(getSelected(pendingLineSegments));
     143                sel.addAll(getSelected(tracks));
     144                for (Track t : tracks)
     145                        sel.addAll(getSelected(t.segments));
     146                return sel;
    105147        }
    106148       
     
    118160                }
    119161        }
    120        
     162
     163        /**
     164         * Return all selected items in the collection.
     165         * @param list The collection from which the selected items are returned.
     166         */
     167        private Collection<OsmPrimitive> getSelected(Collection<? extends OsmPrimitive> list) {
     168                Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
     169                if (list == null)
     170                        return sel;
     171                for (OsmPrimitive osm : list) {
     172                        if (osm.selected)
     173                                sel.add(osm);
     174                        if (osm.keys != null)
     175                                sel.addAll(getSelected(osm.keys.keySet()));
     176                }
     177                return sel;
     178        }
     179
     180
    121181        @Override
    122182        public DataSet clone() {
  • src/org/openstreetmap/josm/data/osm/Key.java

    r1 r7  
    11package org.openstreetmap.josm.data.osm;
     2
     3import java.util.Collection;
     4import java.util.LinkedList;
    25
    36
     
    1316         */
    1417        public String name;
     18
     19        /**
     20         * Return an empty list, since keys cannot have nodes.
     21         */
     22        @Override
     23        public Collection<Node> getAllNodes() {
     24                return new LinkedList<Node>();
     25        }
     26
     27        /**
     28         * Keys are equal, when their name is equal, regardless of their other keys.
     29         */
     30        @Override
     31        public boolean equals(Object obj) {
     32                if (!(obj instanceof Key))
     33                        return false;
     34                return name.equals(((Key)obj).name);
     35        }
     36
     37        @Override
     38        public int hashCode() {
     39                return name.hashCode();
     40        }
    1541}
  • src/org/openstreetmap/josm/data/osm/LineSegment.java

    r1 r7  
    11package org.openstreetmap.josm.data.osm;
     2
     3import java.util.Collection;
     4import java.util.LinkedList;
    25
    36
     
    2831         */
    2932        public Node end;
     33
     34        /**
     35         * Return start and end in a list.
     36         */
     37        @Override
     38        public Collection<Node> getAllNodes() {
     39                LinkedList<Node> nodes = new LinkedList<Node>();
     40                nodes.add(start);
     41                nodes.add(end);
     42                return nodes;
     43        }
     44
     45        /**
     46         * Line segments are equal, if their starting and ending node and their
     47         * keys are equal.
     48         */
     49        @Override
     50        public boolean equals(Object obj) {
     51                if (!(obj instanceof LineSegment))
     52                        return false;
     53                return super.equals(obj) &&
     54                        start.equals(((LineSegment)obj).start) &&
     55                        end.equals(((LineSegment)obj).end);
     56        }
     57
     58        @Override
     59        public int hashCode() {
     60                return super.hashCode() + start.hashCode() + end.hashCode();
     61        }
    3062}       
  • src/org/openstreetmap/josm/data/osm/Node.java

    r6 r7  
    11package org.openstreetmap.josm.data.osm;
     2
     3import java.util.Collection;
     4import java.util.LinkedList;
    25
    36import org.openstreetmap.josm.data.GeoPoint;
     
    3639                return (coor == null ? 0 : coor.hashCode()) + super.hashCode();
    3740        }
     41
     42        /**
     43         * Return a list only this added.
     44         */
     45        @Override
     46        public Collection<Node> getAllNodes() {
     47                LinkedList<Node> nodes = new LinkedList<Node>();
     48                nodes.add(this);
     49                return nodes;
     50        }
    3851       
    3952       
  • src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r6 r7  
    11package org.openstreetmap.josm.data.osm;
    22
     3import java.util.Collection;
    34import java.util.Map;
    45
     
    1011 * @author imi
    1112 */
    12 public class OsmPrimitive {
     13abstract public class OsmPrimitive {
    1314
    1415        /**
     
    2728        transient public boolean selected = false;
    2829
     30        /**
     31         * Return a list of all nodes, this osmPrimitive consists of. Does return
     32         * an empty list, if it is an primitive that cannot have nodes (e.g. Key)
     33         */
     34        abstract public Collection<Node> getAllNodes();
     35
     36        /**
     37         * Return <code>true</code>, if either <code>this.keys</code> and
     38         * <code>other.keys</code> is <code>null</code> or if they do not share Keys
     39         * with different values.
     40         * 
     41         * @param other         The second key-set to compare with.
     42         * @return      True, if the keysets are mergable
     43         */
     44        public boolean keyPropertiesMergable(OsmPrimitive other) {
     45                if ((keys == null) != (other.keys == null))
     46                        return false;
     47
     48                if (keys != null) {
     49                        for (Key k : keys.keySet())
     50                                if (other.keys.containsKey(k) && !keys.get(k).equals(other.keys.get(k)))
     51                                        return false;
     52                        for (Key k : other.keys.keySet())
     53                                if (keys.containsKey(k) && !other.keys.get(k).equals(keys.get(k)))
     54                                        return false;
     55                }
     56                return true;
     57        }
     58       
    2959        /**
    3060         * Osm primitives are equal, when their keys are equal.
     
    4979                return keys == null ? 0 : keys.hashCode();
    5080        }
    51        
    52        
    5381}
  • src/org/openstreetmap/josm/data/osm/Track.java

    r1 r7  
    22
    33import java.util.ArrayList;
     4import java.util.Collection;
    45import java.util.List;
    56
     
    1415         * All track segments in this track
    1516         */
    16         public List<LineSegment> segments = new ArrayList<LineSegment>();
     17        public final List<LineSegment> segments = new ArrayList<LineSegment>();
     18
     19        /**
     20         * Return a merge of getAllNodes - calls to the line segments.
     21         */
     22        @Override
     23        public Collection<Node> getAllNodes() {
     24                ArrayList<Node> nodes = new ArrayList<Node>();
     25                for (LineSegment ls : segments)
     26                        nodes.addAll(ls.getAllNodes());
     27                return nodes;
     28        }
     29
     30        /**
     31         * Tracks are equal, when all segments and the keys are equal
     32         */
     33        @Override
     34        public boolean equals(Object obj) {
     35                if (!(obj instanceof Track))
     36                        return false;
     37                if (!super.equals(obj))
     38                        return false;
     39                Track t = (Track)obj;
     40                int size = segments.size();
     41                if (size != t.segments.size())
     42                        return false;
     43                for (int i = 0; i < size; ++i)
     44                        if (!segments.get(i).equals(t.segments.get(i)))
     45                                return false;
     46                return true;
     47        }
     48
     49        @Override
     50        public int hashCode() {
     51                int hash = super.hashCode();
     52                for (LineSegment ls : segments)
     53                        hash += ls.hashCode();
     54                return hash;
     55        }
     56
     57        /**
     58         * Return the last node in the track. This is the node, which no line segment
     59         * has as start, but at least one has it as end. If there are not exact one
     60         * such nodes found, <code>null</code> is returned.
     61         *
     62         * TODO Currently does return just the end node in the list.
     63         *
     64         * @return The ending node, if there is one.
     65         */
     66        public Node getEndingNode() {
     67                if (segments.isEmpty())
     68                        return null;
     69                return segments.get(segments.size()-1).end;
     70        }
     71
     72        /**
     73         * Return the first node in the track. This is the node, which no line segment
     74         * has as end, but at least one as starting node. If there are not exact one
     75         * such nodes found, <code>null</code> is returned.
     76         *
     77         * TODO Currently does return just the first node in the list.
     78         *
     79         * @return The starting node, if there is one.
     80         */
     81        public Node getStartingNode() {
     82                if (segments.isEmpty())
     83                        return null;
     84                return segments.get(0).start;
     85        }
    1786}
  • src/org/openstreetmap/josm/data/projection/Projection.java

    r6 r7  
    8989         */
    9090        public void init(DataSet dataSet) {
    91                 for (Node w : dataSet.allNodes)
     91                for (Node w : dataSet.nodes)
    9292                        latlon2xy(w.coor);
    9393        }
  • src/org/openstreetmap/josm/gui/IconToggleButton.java

    r4 r7  
    11package org.openstreetmap.josm.gui;
     2
     3import java.beans.PropertyChangeEvent;
     4import java.beans.PropertyChangeListener;
    25
    36import javax.swing.Action;
     
    1114 * @author imi
    1215 */
    13 public class IconToggleButton extends JToggleButton {
     16public class IconToggleButton extends JToggleButton implements PropertyChangeListener {
    1417
    1518        /**
     
    1922                super(action);
    2023                setText(null);
     24               
     25                // Tooltip
     26                String toolTipText = "";
    2127                Object o = action.getValue(Action.LONG_DESCRIPTION);
    2228                if (o != null)
    23                         setToolTipText(o.toString());
     29                        toolTipText += o.toString();
     30                o = action.getValue(Action.ACCELERATOR_KEY);
     31                if (o != null) {
     32                        String ksName = o.toString();
     33                        if (ksName.startsWith("pressed "))
     34                                ksName = ksName.substring("pressed ".length());
     35                        else if (ksName.startsWith("released "))
     36                                ksName = ksName.substring("released ".length());
     37                        toolTipText += " Shortcut: "+ksName;
     38                }
     39                setToolTipText(toolTipText);
     40               
     41                action.addPropertyChangeListener(this);
     42        }
     43
     44        public void propertyChange(PropertyChangeEvent evt) {
     45                if (evt.getPropertyName() == "active")
     46                        setSelected((Boolean)evt.getNewValue());
    2447        }
    2548}
  • src/org/openstreetmap/josm/gui/Main.java

    r1 r7  
    6262                setExtendedState(MAXIMIZED_BOTH); // some platform are able to maximize
    6363               
     64                // creating actions
     65                OpenGpxAction openGpxAction = new OpenGpxAction();
     66                SaveGpxAction saveGpxAction = new SaveGpxAction();
     67                ExitAction exitAction = new ExitAction();
     68                PreferencesAction preferencesAction = new PreferencesAction();
     69
    6470                // creating menu
    6571                JMenuBar mainMenu = new JMenuBar();
     
    6874                JMenu fileMenu = new JMenu("Files");
    6975                fileMenu.setMnemonic('F');
    70                 fileMenu.add(new OpenGpxAction());
    71                 fileMenu.add(new SaveGpxAction());
     76                fileMenu.add(openGpxAction);
     77                fileMenu.add(saveGpxAction);
    7278                fileMenu.addSeparator();
    73                 fileMenu.add(new ExitAction());
     79                fileMenu.add(exitAction);
    7480                mainMenu.add(fileMenu);
    7581               
    7682                JMenu editMenu = new JMenu("Edit");
    7783                editMenu.setMnemonic('E');
    78                 editMenu.add(new PreferencesAction());
     84                editMenu.add(preferencesAction);
    7985                mainMenu.add(editMenu);
    8086
     
    8288                JToolBar toolBar = new JToolBar();
    8389                toolBar.setFloatable(false);
    84                 toolBar.add(new OpenGpxAction());
    85                 toolBar.add(new SaveGpxAction());
     90                toolBar.add(openGpxAction);
     91                toolBar.add(saveGpxAction);
    8692                toolBar.addSeparator();
    87                 toolBar.add(new PreferencesAction());
     93                toolBar.add(preferencesAction);
    8894               
    8995                getContentPane().add(toolBar, BorderLayout.NORTH);
     
    133139                this.name = name;
    134140                this.mapFrame = mapFrame;
     141                panel.setVisible(false);
    135142                panel.removeAll();
    136143                panel.add(mapFrame, BorderLayout.CENTER);
    137144                panel.add(mapFrame.getToolBarActions(), BorderLayout.WEST);
     145                panel.setVisible(true);
    138146        }
    139147        /**
  • src/org/openstreetmap/josm/gui/MapFrame.java

    r4 r7  
    2525import javax.swing.event.ChangeListener;
    2626
     27import org.openstreetmap.josm.actions.mapmode.AddLineSegmentAction;
     28import org.openstreetmap.josm.actions.mapmode.AddNodeAction;
     29import org.openstreetmap.josm.actions.mapmode.AddTrackAction;
     30import org.openstreetmap.josm.actions.mapmode.CombineAction;
    2731import org.openstreetmap.josm.actions.mapmode.DebugAction;
     32import org.openstreetmap.josm.actions.mapmode.DeleteAction;
    2833import org.openstreetmap.josm.actions.mapmode.MapMode;
     34import org.openstreetmap.josm.actions.mapmode.MoveAction;
    2935import org.openstreetmap.josm.actions.mapmode.SelectionAction;
    3036import org.openstreetmap.josm.actions.mapmode.ZoomAction;
     
    3945 * @author imi
    4046 */
    41 public class MapFrame extends JComponent {
     47public class MapFrame extends JPanel {
    4248
    4349        /**
     
    123129
    124130                add(mapView = new MapView(dataSet), BorderLayout.CENTER);
    125                
     131
     132                // toolbar
    126133                toolBarActions.setFloatable(false);
    127134                toolBarActions.add(new IconToggleButton(this, new ZoomAction(this)));
    128135                toolBarActions.add(new IconToggleButton(this, new SelectionAction(this)));
     136                toolBarActions.add(new IconToggleButton(this, new MoveAction(this)));
     137                toolBarActions.add(new IconToggleButton(this, new AddNodeAction(this)));
     138                toolBarActions.add(new IconToggleButton(this, new AddLineSegmentAction(this)));
     139                toolBarActions.add(new IconToggleButton(this, new AddTrackAction(this)));
     140                toolBarActions.add(new IconToggleButton(this, new CombineAction(this)));
     141                toolBarActions.add(new IconToggleButton(this, new DeleteAction(this)));
    129142                toolBarActions.add(new IconToggleButton(this, new DebugAction(this)));
    130143
     
    159172        public void selectMapMode(MapMode mapMode) {
    160173                if (this.mapMode != null)
    161                         this.mapMode.unregisterListener(mapView);
     174                        this.mapMode.unregisterListener();
    162175                this.mapMode = mapMode;
    163                 mapMode.registerListener(mapView);
     176                mapMode.registerListener();
    164177        }
    165178
  • src/org/openstreetmap/josm/gui/MapView.java

    r6 r7  
    2424import org.openstreetmap.josm.data.osm.LineSegment;
    2525import org.openstreetmap.josm.data.osm.Node;
     26import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2627import org.openstreetmap.josm.data.osm.Track;
    2728import org.openstreetmap.josm.data.projection.Projection;
     
    8182
    8283       
    83         // Event handling functions and data
    84        
    85         /**
    86          * The event list with all state chaned listener
    87          */
    88         List<ChangeListener> listener = new LinkedList<ChangeListener>();
    89         /**
    90          * Add an event listener to the state changed event queue. If passed
    91          * <code>null</code>, nothing happens.
    92          */
    93         public final void addChangeListener(ChangeListener l) {
    94                 if (l != null)
    95                         listener.add(l);
    96         }
    97         /**
    98          * Remove an event listener from the event queue. If passed
    99          * <code>null</code>, nothing happens.
    100          */
    101         public final void removeChangeListener(ChangeListener l) {
    102                 listener.remove(l);
    103         }
    104         /**
    105          * Fires an ChangeEvent. Occours, when an non-data value changed, as example
    106          * the autoScale - state or the center. Is not fired, dataSet internal things
    107          * changes.
    108          */
    109         public final void fireStateChanged() {
    110                 ChangeEvent e = null;
    111                 for(ChangeListener l : listener) {
    112                         if (e == null)
    113                                 e = new ChangeEvent(this);
    114                         l.stateChanged(e);
    115                 }
    116         }
    117        
    118        
    119        
    120        
    121        
    122         // other functions
    123        
    12484        /**
    12585         * Construct a MapView and attach it to a frame.
     
    178138                return new Point(toScreenX(p.x), toScreenY(p.y));
    179139        }
    180        
     140
     141        /**
     142         * Return the object, that is nearest to the given screen point.
     143         *
     144         * First, a node will be searched. If a node within 10 pixel is found, the
     145         * nearest node is returned.
     146         *
     147         * If no node is found, search for pending line segments.
     148         *
     149         * If no such line segment is found, and a non-pending line segment is
     150         * within 10 pixel to p, this segment is returned, except when
     151         * <code>wholeTrack</code> is <code>true</code>, in which case the
     152         * corresponding Track is returned.
     153         *
     154         * If no line segment is found and the point is within an area, return that
     155         * area.
     156         *
     157         * If no area is found, return <code>null</code>.
     158         *
     159         * @param p                             The point on screen.
     160         * @param wholeTrack    Whether the whole track or only the line segment
     161         *                                              should be returned.
     162         * @return      The primitive, that is nearest to the point p.
     163         */
     164        public OsmPrimitive getNearest(Point p, boolean wholeTrack) {
     165                double minDistanceSq = Double.MAX_VALUE;
     166                OsmPrimitive minPrimitive = null;
     167               
     168                // nodes
     169                for (Node n : dataSet.nodes) {
     170                        Point sp = getScreenPoint(n.coor);
     171                        double dist = p.distanceSq(sp);
     172                        if (minDistanceSq > dist && dist < 100) {
     173                                minDistanceSq = p.distanceSq(sp);
     174                                minPrimitive = n;
     175                        }
     176                }
     177                if (minPrimitive != null)
     178                        return minPrimitive;
     179               
     180                // pending line segments
     181                for (LineSegment ls : dataSet.pendingLineSegments) {
     182                        Point A = getScreenPoint(ls.start.coor);
     183                        Point B = getScreenPoint(ls.end.coor);
     184                        double c = A.distanceSq(B);
     185                        double a = p.distanceSq(B);
     186                        double b = p.distanceSq(A);
     187                        double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
     188                        if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
     189                                minDistanceSq = perDist;
     190                                minPrimitive = ls;
     191                        }
     192                }
     193
     194                // tracks & line segments
     195                minDistanceSq = Double.MAX_VALUE;
     196                for (Track t : dataSet.tracks) {
     197                        for (LineSegment ls : t.segments) {
     198                                Point A = getScreenPoint(ls.start.coor);
     199                                Point B = getScreenPoint(ls.end.coor);
     200                                double c = A.distanceSq(B);
     201                                double a = p.distanceSq(B);
     202                                double b = p.distanceSq(A);
     203                                double perDist = a-(a-b+c)*(a-b+c)/4/c; // perpendicular distance squared
     204                                if (perDist < 100 && minDistanceSq > perDist && a < c+100 && b < c+100) {
     205                                        minDistanceSq = perDist;
     206                                        minPrimitive = wholeTrack ? t : ls;
     207                                }
     208                        }                       
     209                }
     210                if (minPrimitive != null)
     211                        return minPrimitive;
     212               
     213                // TODO areas
     214               
     215               
     216                return null; // nothing found
     217        }
     218
    181219        /**
    182220         * Zoom to the given coordinate.
     
    220258                                center = new GeoPoint(51.526447, -0.14746371);
    221259                                getProjection().latlon2xy(center);
    222                                 scale = 10000; // nice view from 1:10000, eh?
     260                                scale = 10;
    223261                        } else {
    224262                                center = bounds.centerXY();
     
    258296                                }
    259297
     298                // draw pending line segments
     299                for (LineSegment ls : dataSet.pendingLineSegments) {
     300                        g.setColor(ls.selected ? Color.WHITE : Color.LIGHT_GRAY);
     301                        g.drawLine(toScreenX(ls.start.coor.x), toScreenY(ls.start.coor.y),
     302                                        toScreenX(ls.end.coor.x), toScreenY(ls.end.coor.y));
     303                }
     304
    260305                // draw nodes
    261306                Set<Integer> alreadyDrawn = new HashSet<Integer>();
    262307                int width = getWidth();
    263                 for (Node w : dataSet.allNodes) {
     308                for (Node w : dataSet.nodes) {
    264309                        g.setColor(w.selected ? Color.WHITE : Color.RED);
    265310                        int x = toScreenX(w.coor.x);
     
    294339        }
    295340
    296         /**
    297          * Does nothing. Just to satisfy ComponentListener.
    298          */
    299         public void componentMoved(ComponentEvent e) {}
    300         /**
    301          * Does nothing. Just to satisfy ComponentListener.
    302          */
    303         public void componentShown(ComponentEvent e) {}
    304         /**
    305          * Does nothing. Just to satisfy ComponentListener.
    306          */
    307         public void componentHidden(ComponentEvent e) {}
    308 
     341
     342        // Event handling functions and data
     343       
     344        /**
     345         * The event list with all state chaned listener
     346         */
     347        List<ChangeListener> listener = new LinkedList<ChangeListener>();
     348        /**
     349         * Add an event listener to the state changed event queue. If passed
     350         * <code>null</code>, nothing happens.
     351         */
     352        public final void addChangeListener(ChangeListener l) {
     353                if (l != null)
     354                        listener.add(l);
     355        }
     356        /**
     357         * Remove an event listener from the event queue. If passed
     358         * <code>null</code>, nothing happens.
     359         */
     360        public final void removeChangeListener(ChangeListener l) {
     361                listener.remove(l);
     362        }
     363        /**
     364         * Fires an ChangeEvent. Occours, when an non-data value changed, as example
     365         * the autoScale - state or the center. Is not fired, dataSet internal things
     366         * changes.
     367         */
     368        public final void fireStateChanged() {
     369                ChangeEvent e = null;
     370                for(ChangeListener l : listener) {
     371                        if (e == null)
     372                                e = new ChangeEvent(this);
     373                        l.stateChanged(e);
     374                }
     375        }
     376       
    309377        /**
    310378         * Notify from the projection, that something has changed.
     
    363431                return center.clone();
    364432        }
     433
     434        /**
     435         * Does nothing. Just to satisfy ComponentListener.
     436         */
     437        public void componentMoved(ComponentEvent e) {}
     438        /**
     439         * Does nothing. Just to satisfy ComponentListener.
     440         */
     441        public void componentShown(ComponentEvent e) {}
     442        /**
     443         * Does nothing. Just to satisfy ComponentListener.
     444         */
     445        public void componentHidden(ComponentEvent e) {}
    365446}
  • src/org/openstreetmap/josm/gui/SelectionManager.java

    r4 r7  
    1010import java.awt.event.MouseListener;
    1111import java.awt.event.MouseMotionListener;
     12import java.beans.PropertyChangeEvent;
     13import java.beans.PropertyChangeListener;
     14import java.util.Collection;
     15import java.util.LinkedList;
     16
     17import org.openstreetmap.josm.data.osm.LineSegment;
     18import org.openstreetmap.josm.data.osm.Node;
     19import org.openstreetmap.josm.data.osm.OsmPrimitive;
     20import org.openstreetmap.josm.data.osm.Track;
    1221
    1322/**
     
    3645 * @author imi
    3746 */
    38 public class SelectionManager implements MouseListener, MouseMotionListener {
     47public class SelectionManager implements MouseListener, MouseMotionListener, PropertyChangeListener {
    3948
    4049        /**
     
    4756                 * Called, when the left mouse button was released.
    4857                 * @param r The rectangle, that is currently the selection.
    49                  * @param modifiers The modifiers returned from the MouseEvent when
    50                  *              the left mouse button was released.
     58                 * @param alt Whether the alt key was pressed
     59                 * @param shift Whether the shift key was pressed
     60                 * @param ctrl Whether the ctrl key was pressed
    5161                 * @see InputEvent#getModifiersEx()
    5262                 */
    53                 public void selectionEnded(Rectangle r, int modifiers);
     63                public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl);
     64                /**
     65                 * Called to register the selection manager for "active" property.
     66                 * @param listener The listener to register
     67                 */
     68                public void addPropertyChangeListener(PropertyChangeListener listener);
     69                /**
     70                 * Called to remove the selection manager from the listener list
     71                 * for "active" property.
     72                 * @param listener The listener to register
     73                 */
     74                public void removePropertyChangeListener(PropertyChangeListener listener);
    5475        }
    5576        /**
     
    6788        private Point mousePos;
    6889        /**
    69          * The component, the selection rectangle is drawn onto.
    70          */
    71         private final Component drawComponent;
     90         * The MapView, the selection rectangle is drawn onto.
     91         */
     92        private final MapView mv;
    7293        /**
    7394         * Whether the selection rectangle must obtain the aspect ratio of the
     
    83104         * @param aspectRatio If true, the selection window must obtain the aspect
    84105         *              ratio of the drawComponent.
    85          * @param drawComponent The component, the rectangle is drawn onto.
    86          */
    87         public SelectionManager(SelectionEnded selectionEndedListener, boolean aspectRatio, Component drawComponent) {
     106         * @param mapView The view, the rectangle is drawn onto.
     107         */
     108        public SelectionManager(SelectionEnded selectionEndedListener, boolean aspectRatio, MapView mapView) {
    88109                this.selectionEndedListener = selectionEndedListener;
    89110                this.aspectRatio = aspectRatio;
    90                 this.drawComponent = drawComponent;
     111                this.mv = mapView;
    91112        }
    92113       
     
    98119                eventSource.addMouseListener(this);
    99120                eventSource.addMouseMotionListener(this);
     121                selectionEndedListener.addPropertyChangeListener(this);
    100122        }
    101123        /**
     
    108130                eventSource.removeMouseListener(this);
    109131                eventSource.removeMouseMotionListener(this);
     132                selectionEndedListener.removePropertyChangeListener(this);
    110133        }
    111134
     
    158181                mousePosStart = null;
    159182                mousePos = null;
     183
     184                boolean shift = (e.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) != 0;
     185                boolean alt = (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0;
     186                boolean ctrl = (e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0;
    160187                if ((e.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) == 0)
    161                         selectionEndedListener.selectionEnded(r, e.getModifiersEx());
     188                        selectionEndedListener.selectionEnded(r, alt, shift, ctrl);
    162189        }
    163190
     
    168195         */
    169196        private void paintRect() {
    170                 Graphics g = drawComponent.getGraphics();
     197                Graphics g = mv.getGraphics();
    171198                g.setColor(Color.BLACK);
    172199                g.setXORMode(Color.WHITE);
     
    196223                if (aspectRatio) {
    197224                        // keep the aspect ration by shrinking the rectangle
    198                         double aspectRatio = (double)drawComponent.getWidth()/drawComponent.getHeight();
     225                        double aspectRatio = (double)mv.getWidth()/mv.getHeight();
    199226                        if ((double)w/h > aspectRatio) {
    200227                                int neww = (int)(h*aspectRatio);
     
    212239                return new Rectangle(x,y,w,h);
    213240        }
     241
     242        /**
     243         * If the action goes inactive, remove the selection rectangle from screen
     244         */
     245        public void propertyChange(PropertyChangeEvent evt) {
     246                if (evt.getPropertyName() == "active" && !(Boolean)evt.getNewValue() && mousePosStart != null) {
     247                        paintRect();
     248                        mousePosStart = null;
     249                        mousePos = null;
     250                }
     251        }
     252
     253        /**
     254         * Return a list of all objects in the rectangle, respecting the different
     255         * modifier.
     256         * @param alt Whether the alt key was pressed, which means select all objects
     257         *              that are touched, instead those which are completly covered. Also
     258         *              select whole tracks instead of line segments.
     259         */
     260        public Collection<OsmPrimitive> getObjectsInRectangle(Rectangle r, boolean alt) {
     261                Collection<OsmPrimitive> selection = new LinkedList<OsmPrimitive>();
     262
     263                // whether user only clicked, not dragged.
     264                boolean clicked = r.width <= 2 && r.height <= 2;
     265                Point center = new Point(r.x+r.width/2, r.y+r.height/2);
     266
     267                if (clicked) {
     268                        OsmPrimitive osm = mv.getNearest(center, alt);
     269                        if (osm != null)
     270                                selection.add(osm);
     271                } else {
     272                        // nodes
     273                        for (Node n : mv.dataSet.nodes) {
     274                                if (r.contains(mv.getScreenPoint(n.coor)))
     275                                        selection.add(n);
     276                        }
     277                       
     278                        // pending line segments
     279                        for (LineSegment ls : mv.dataSet.pendingLineSegments)
     280                                if (rectangleContainLineSegment(r, alt, ls))
     281                                        selection.add(ls);
     282
     283                        // tracks
     284                        for (Track t : mv.dataSet.tracks) {
     285                                boolean wholeTrackSelected = t.segments.size() > 0;
     286                                for (LineSegment ls : t.segments)
     287                                        if (rectangleContainLineSegment(r, alt, ls))
     288                                                selection.add(ls);
     289                                        else
     290                                                wholeTrackSelected = false;
     291                                if (wholeTrackSelected)
     292                                        selection.add(t);
     293                        }
     294                       
     295                        // TODO areas
     296                }
     297                return selection;
     298        }
     299
     300        /**
     301         * Decide whether the line segment is in the rectangle Return
     302         * <code>true</code>, if it is in or false if not.
     303         *
     304         * @param r                     The rectangle, in which the line segment has to be.
     305         * @param alt           Whether user pressed the Alt key
     306         * @param ls            The line segment.
     307         * @return <code>true</code>, if the LineSegment was added to the selection.
     308         */
     309        private boolean rectangleContainLineSegment(Rectangle r, boolean alt, LineSegment ls) {
     310                if (alt) {
     311                        Point p1 = mv.getScreenPoint(ls.start.coor);
     312                        Point p2 = mv.getScreenPoint(ls.end.coor);
     313                        if (r.intersectsLine(p1.x, p1.y, p2.x, p2.y))
     314                                return true;
     315                } else {
     316                        if (r.contains(mv.getScreenPoint(ls.start.coor))
     317                                        && r.contains(mv.getScreenPoint(ls.end.coor)))
     318                                return true;
     319                }
     320                return false;
     321        }
    214322       
     323       
    215324        /**
    216325         * Does nothing. Only to satisfy MouseListener
     
    229338         */
    230339        public void mouseMoved(MouseEvent e) {}
     340
    231341}
  • src/org/openstreetmap/josm/io/GpxReader.java

    r6 r7  
    44import java.io.Reader;
    55import java.util.ArrayList;
    6 import java.util.LinkedList;
    76
    87import org.jdom.Element;
     
    1211import org.openstreetmap.josm.data.GeoPoint;
    1312import org.openstreetmap.josm.data.osm.DataSet;
     13import org.openstreetmap.josm.data.osm.LineSegment;
    1414import org.openstreetmap.josm.data.osm.Node;
    1515import org.openstreetmap.josm.data.osm.Track;
    16 import org.openstreetmap.josm.data.osm.LineSegment;
    1716import org.openstreetmap.josm.gui.Main;
    1817
     
    6968                DataSet data = new DataSet();
    7069                // read waypoints not contained in tracks or areas
    71                 data.allNodes = new LinkedList<Node>();
    7270                for (Object o : e.getChildren("wpt", GPX))
    7371                        addNode(data, parseWaypoint((Element)o));
     
    109107        private Node addNode (DataSet data, Node node) {
    110108                if (Main.pref.mergeNodes)
    111                         for (Node n : data.allNodes)
     109                        for (Node n : data.nodes)
    112110                                if (node.equals(n))
    113111                                        return n;
    114                 data.allNodes.add(node);
     112                data.nodes.add(node);
    115113                return node;
    116114        }
Note: See TracChangeset for help on using the changeset viewer.