Changeset 1115 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2008-12-12T00:13:30+01:00 (16 years ago)
Author:
framm
Message:
  • update coordinates in selected list after moving. patch by <robome@…>. fixes #1788.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java

    r1084 r1115  
    2525import org.openstreetmap.josm.command.SequenceCommand;
    2626import org.openstreetmap.josm.data.coor.EastNorth;
     27import org.openstreetmap.josm.data.osm.DataSet;
    2728import org.openstreetmap.josm.data.osm.Node;
    2829import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    5051public class SelectAction extends MapMode implements SelectionEnded {
    5152
    52         enum Mode { move, rotate, select }
    53         private Mode mode = null;
    54         private long mouseDownTime = 0;
    55         private boolean didMove = false;
    56         Node virtualNode = null;
    57         WaySegment virtualWay = null;
    58         SequenceCommand virtualCmds = null;
    59 
    60         /**
    61         * The old cursor before the user pressed the mouse button.
    62         */
    63         private Cursor oldCursor;
    64         /**
    65         * The position of the mouse before the user moves a node.
    66         */
    67         private Point mousePos;
    68         private SelectionManager selectionManager;
    69 
    70         /**
    71         * The time which needs to pass between click and release before something
    72         * counts as a move, in milliseconds
    73         */
    74         private int initialMoveDelay = 200;
    75 
    76         /**
    77         * The screen distance which needs to be travelled before something
    78         * counts as a move, in pixels
    79         */
    80         private int initialMoveThreshold = 15;
    81         private boolean initialMoveThresholdExceeded = false;
    82         /**
    83         * Create a new SelectAction
    84         * @param mapFrame The MapFrame this action belongs to.
    85         */
    86         public SelectAction(MapFrame mapFrame) {
    87                 super(tr("Select"), "move/move", tr("Select, move and rotate objects"),
    88                         Shortcut.registerShortcut("mapmode:select", tr("Mode: {0}", tr("Select")), KeyEvent.VK_S, Shortcut.GROUP_EDIT),
    89                         mapFrame,
    90                         getCursor("normal", "selection", Cursor.DEFAULT_CURSOR));
    91                 putValue("help", "Action/Move/Move");
    92                 selectionManager = new SelectionManager(this, false, mapFrame.mapView);
    93                 try { initialMoveDelay = Integer.parseInt(Main.pref.get("edit.initial-move-delay","200")); } catch (NumberFormatException x) {}
    94                 try { initialMoveThreshold = Integer.parseInt(Main.pref.get("edit.initial-move-threshold","5")); } catch (NumberFormatException x) {}
    95 
    96         }
    97 
    98         private static Cursor getCursor(String name, String mod, int def) {
    99                 try {
    100                 return ImageProvider.getCursor(name, mod);
     53    enum Mode { move, rotate, select }
     54    private Mode mode = null;
     55    private long mouseDownTime = 0;
     56    private boolean didMove = false;
     57    Node virtualNode = null;
     58    WaySegment virtualWay = null;
     59    SequenceCommand virtualCmds = null;
     60
     61    /**
     62    * The old cursor before the user pressed the mouse button.
     63    */
     64    private Cursor oldCursor;
     65    /**
     66    * The position of the mouse before the user moves a node.
     67    */
     68    private Point mousePos;
     69    private SelectionManager selectionManager;
     70
     71    /**
     72    * The time which needs to pass between click and release before something
     73    * counts as a move, in milliseconds
     74    */
     75    private int initialMoveDelay = 200;
     76
     77    /**
     78    * The screen distance which needs to be travelled before something
     79    * counts as a move, in pixels
     80    */
     81    private int initialMoveThreshold = 15;
     82    private boolean initialMoveThresholdExceeded = false;
     83    /**
     84    * Create a new SelectAction
     85    * @param mapFrame The MapFrame this action belongs to.
     86    */
     87    public SelectAction(MapFrame mapFrame) {
     88        super(tr("Select"), "move/move", tr("Select, move and rotate objects"),
     89            Shortcut.registerShortcut("mapmode:select", tr("Mode: {0}", tr("Select")), KeyEvent.VK_S, Shortcut.GROUP_EDIT),
     90            mapFrame,
     91            getCursor("normal", "selection", Cursor.DEFAULT_CURSOR));
     92        putValue("help", "Action/Move/Move");
     93        selectionManager = new SelectionManager(this, false, mapFrame.mapView);
     94        try { initialMoveDelay = Integer.parseInt(Main.pref.get("edit.initial-move-delay","200")); } catch (NumberFormatException x) {}
     95        try { initialMoveThreshold = Integer.parseInt(Main.pref.get("edit.initial-move-threshold","5")); } catch (NumberFormatException x) {}
     96
     97    }
     98
     99    private static Cursor getCursor(String name, String mod, int def) {
     100        try {
     101            return ImageProvider.getCursor(name, mod);
    101102        } catch (Exception e) {
    102103        }
    103             return Cursor.getPredefinedCursor(def);
    104     }
    105 
    106         private void setCursor(Cursor c) {
    107                 if (oldCursor == null) {
    108                         oldCursor = Main.map.mapView.getCursor();
    109                         Main.map.mapView.setCursor(c);
    110                 }
    111         }
    112 
    113         private void restoreCursor() {
    114                 if (oldCursor != null) {
    115                         Main.map.mapView.setCursor(oldCursor);
    116                         oldCursor = null;
    117                 }
    118         }
    119 
    120         @Override public void enterMode() {
    121                 super.enterMode();
    122                 Main.map.mapView.addMouseListener(this);
    123                 Main.map.mapView.addMouseMotionListener(this);
    124                 Main.map.mapView.enableVirtualNodes(
    125                 Main.pref.getInteger("mappaint.node.virtual-size", 8) != 0);
    126         }
    127 
    128         @Override public void exitMode() {
    129                 super.exitMode();
    130                 selectionManager.unregister(Main.map.mapView);
    131                 Main.map.mapView.removeMouseListener(this);
    132                 Main.map.mapView.removeMouseMotionListener(this);
    133                 Main.map.mapView.enableVirtualNodes(false);
    134         }
    135 
    136         /**
    137          * If the left mouse button is pressed, move all currently selected
    138          * objects (if one of them is under the mouse) or the current one under the
    139          * mouse (which will become selected).
    140          */
    141         @Override public void mouseDragged(MouseEvent e) {
    142                 if (mode == Mode.select) return;
    143 
    144                 // do not count anything as a move if it lasts less than 100 milliseconds.
    145                 if ((mode == Mode.move) && (System.currentTimeMillis() - mouseDownTime < initialMoveDelay)) return;
    146 
    147                 if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
    148                         return;
    149 
    150                 if (mode == Mode.move) {
    151                         setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
    152                 }
    153 
    154                 if (mousePos == null) {
    155                         mousePos = e.getPoint();
    156                         return;
    157                 }
    158 
    159                 if (!initialMoveThresholdExceeded) {
    160                         int dxp = mousePos.x - e.getX();
    161                         int dyp = mousePos.y - e.getY();
    162                         int dp = (int) Math.sqrt(dxp*dxp+dyp*dyp);
    163                         if (dp < initialMoveThreshold) return;
    164                         initialMoveThresholdExceeded = true;
    165                 }
    166 
    167                 EastNorth mouseEN = Main.map.mapView.getEastNorth(e.getX(), e.getY());
    168                 EastNorth mouseStartEN = Main.map.mapView.getEastNorth(mousePos.x, mousePos.y);
    169                 double dx = mouseEN.east() - mouseStartEN.east();
    170                 double dy = mouseEN.north() - mouseStartEN.north();
    171                 if (dx == 0 && dy == 0)
    172                         return;
    173 
    174                 if (virtualWay != null) {
    175                         Collection<Command> virtualCmds = new LinkedList<Command>();
    176                         virtualCmds.add(new AddCommand(virtualNode));
    177                         Way w = virtualWay.way;
    178                         Way wnew = new Way(w);
    179                         wnew.nodes.add(virtualWay.lowerIndex+1, virtualNode);
    180                         virtualCmds.add(new ChangeCommand(w, wnew));
    181                         virtualCmds.add(new MoveCommand(virtualNode, dx, dy));
    182                         Main.main.undoRedo.add(new SequenceCommand(tr("Add and move a virtual new node to way"), virtualCmds));
    183                         selectPrims(Collections.singleton((OsmPrimitive)virtualNode), false, false);
    184                         virtualWay = null;
    185                         virtualNode = null;
    186                 } else {
    187                         Collection<OsmPrimitive> selection = Main.ds.getSelected();
    188                         Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
    189 
    190                         // when rotating, having only one node makes no sense - quit silently
    191                         if (mode == Mode.rotate && affectedNodes.size() < 2)
    192                                 return;
    193 
    194                         Command c = !Main.main.undoRedo.commands.isEmpty()
    195                                 ? Main.main.undoRedo.commands.getLast() : null;
    196                         if (c instanceof SequenceCommand)
    197                                 c = ((SequenceCommand)c).getLastCommand();
    198 
    199                         if (mode == Mode.move) {
    200                                 if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand)c).objects))
    201                                         ((MoveCommand)c).moveAgain(dx,dy);
    202                                 else
    203                                         Main.main.undoRedo.add(
    204                                                 c = new MoveCommand(selection, dx, dy));
    205 
    206                                 for (Node n : affectedNodes) {
    207                                         if (n.coor.isOutSideWorld()) {
    208                                                 // Revert move
    209                                                 ((MoveCommand) c).moveAgain(-dx, -dy);
    210 
    211                                                 JOptionPane.showMessageDialog(Main.parent,
    212                                                         tr("Cannot move objects outside of the world."));
    213                                                 return;
    214                                         }
    215                                 }
    216                         } else if (mode == Mode.rotate) {
    217                                 if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand)c).objects))
    218                                         ((RotateCommand)c).rotateAgain(mouseStartEN, mouseEN);
    219                                 else
    220                                         Main.main.undoRedo.add(new RotateCommand(selection, mouseStartEN, mouseEN));
    221                         }
    222                 }
    223 
    224                 Main.map.mapView.repaint();
    225                 mousePos = e.getPoint();
    226 
    227                 didMove = true;
    228         }
    229 
    230         private Collection<OsmPrimitive> getNearestCollectionVirtual(Point p) {
    231                 MapView c = Main.map.mapView;
    232                 int snapDistance = Main.pref.getInteger("mappaint.node.virtual-snap-distance", 8);
    233                 snapDistance *= snapDistance;
    234                 OsmPrimitive osm = c.getNearestNode(p);
    235                 virtualWay = null;
    236                 virtualNode = null;
    237 
    238                 if (osm == null)
    239                 {
    240                         WaySegment nearestWaySeg = c.getNearestWaySegment(p);
    241                         if (nearestWaySeg != null)
    242                         {
    243                                 osm = nearestWaySeg.way;
    244                                 if(Main.pref.getInteger("mappaint.node.virtual-size", 8) > 0)
    245                                 {
    246                                         Way w = (Way)osm;
    247                                         Point p1 = c.getPoint(w.nodes.get(nearestWaySeg.lowerIndex).eastNorth);
    248                                         Point p2 = c.getPoint(w.nodes.get(nearestWaySeg.lowerIndex+1).eastNorth);
    249                                         if(SimplePaintVisitor.isLargeSegment(p1, p2, Main.pref.getInteger("mappaint.node.virtual-space", 70)))
    250                                         {
    251                                                 Point pc = new Point((p1.x+p2.x)/2, (p1.y+p2.y)/2);
    252                                                 if (p.distanceSq(pc) < snapDistance)
    253                                                 {
    254                                                         virtualWay = nearestWaySeg;
    255                                                         virtualNode = new Node(Main.map.mapView.getLatLon(pc.x, pc.y));
    256                                                         osm = w;
    257                                                 }
    258                                         }
    259                                 }
    260                         }
    261                 }
    262                 if (osm == null)
    263                         return Collections.emptySet();
    264                 return Collections.singleton(osm);
    265         }
    266 
    267         /**
    268          * Look, whether any object is selected. If not, select the nearest node.
    269          * If there are no nodes in the dataset, do nothing.
    270          *
    271          * If the user did not press the left mouse button, do nothing.
    272          *
    273          * Also remember the starting position of the movement and change the mouse
    274          * cursor to movement.
    275          */
    276         @Override public void mousePressed(MouseEvent e) {
    277                 if (! (Boolean)this.getValue("active")) return;
    278                 if (e.getButton() != MouseEvent.BUTTON1)
    279                         return;
    280                 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
    281                 // boolean alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0;
    282                 boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
    283 
    284                 mouseDownTime = System.currentTimeMillis();
    285                 didMove = false;
    286                 initialMoveThresholdExceeded = false;
    287 
    288                 Collection<OsmPrimitive> osmColl = getNearestCollectionVirtual(e.getPoint());
    289 
    290                 if (ctrl && shift) {
    291                         if (Main.ds.getSelected().isEmpty()) selectPrims(osmColl, true, false);
    292                         mode = Mode.rotate;
    293                         setCursor(ImageProvider.getCursor("rotate", null));
    294                 } else if (!osmColl.isEmpty()) {
    295                         // Don't replace the selection now if the user clicked on a
    296                         // selected object (this would break moving of selected groups).
    297                         // We'll do that later in mouseReleased if the user didn't try to
    298                         // move.
    299                         selectPrims(osmColl,
    300                                 shift || Main.ds.getSelected().containsAll(osmColl),
    301                                 ctrl);
    302                         mode = Mode.move;
    303                 } else {
    304                         mode = Mode.select;
    305                         oldCursor = Main.map.mapView.getCursor();
    306                         selectionManager.register(Main.map.mapView);
    307                         selectionManager.mousePressed(e);
    308                 }
    309                 if(mode != Mode.move || shift || ctrl)
    310                 {
    311                         virtualNode = null;
    312                         virtualWay = null;
    313                 }
    314 
    315                 updateStatusLine();
    316                 Main.map.mapView.repaint();
    317 
    318                 mousePos = e.getPoint();
    319         }
    320 
    321         /**
    322          * Restore the old mouse cursor.
    323          */
    324         @Override public void mouseReleased(MouseEvent e) {
    325                 if (mode == Mode.select) {
    326                         selectionManager.unregister(Main.map.mapView);
    327                 }
    328                 restoreCursor();
    329 
    330                 if (mode == Mode.move) {
    331                         boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
    332                         boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
    333                         if (!didMove) {
    334                                 selectPrims(
    335                                         Main.map.mapView.getNearestCollection(e.getPoint()),
    336                                         shift, ctrl);
    337                         } else if (ctrl) {
    338                                 Collection<OsmPrimitive> selection = Main.ds.getSelected();
    339                                 Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
    340                                 Collection<Node> nn = Main.map.mapView.getNearestNodes(e.getPoint(), affectedNodes);
    341                                 if (nn != null) {
    342                                         Node n = nn.iterator().next();
    343                                     LinkedList<Node> selNodes = new LinkedList<Node>();
    344                                     for (OsmPrimitive osm : selection)
    345                                                 if (osm instanceof Node)
    346                                                         selNodes.add((Node)osm);
    347                                         if (selNodes.size() > 0) {
    348                                                 selNodes.add(n);
    349                                                 MergeNodesAction.mergeNodes(selNodes, n);
    350                                         }
    351                                 }
    352                         }
    353                 }
    354 
    355                 updateStatusLine();
    356                 mode = null;
    357                 updateStatusLine();
    358         }
    359 
    360         public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
    361                 selectPrims(selectionManager.getObjectsInRectangle(r, alt), shift, ctrl);
    362         }
    363 
    364         public void selectPrims(Collection<OsmPrimitive> selectionList, boolean shift, boolean ctrl) {
    365                 if (shift && ctrl)
    366                         return; // not allowed together
    367 
    368                 Collection<OsmPrimitive> curSel;
    369                 if (!ctrl && !shift)
    370                         curSel = new LinkedList<OsmPrimitive>(); // new selection will replace the old.
    371                 else
    372                         curSel = Main.ds.getSelected();
    373 
    374                 for (OsmPrimitive osm : selectionList)
    375                         if (ctrl)
    376                                 curSel.remove(osm);
    377                         else
    378                                 curSel.add(osm);
    379                 Main.ds.setSelected(curSel);
    380                 Main.map.mapView.repaint();
    381         }
    382 
    383         @Override public String getModeHelpText() {
    384                 if (mode == Mode.select) {
    385                         return tr("Release the mouse button to select the objects in the rectangle.");
    386                 } else if (mode == Mode.move) {
    387                         return tr("Release the mouse button to stop moving. Ctrl to merge with nearest node.");
    388                 } else if (mode == Mode.rotate) {
    389                         return tr("Release the mouse button to stop rotating.");
    390                 } else {
    391                         return tr("Move objects by dragging; Shift to add to selection (Ctrl to remove); Shift-Ctrl to rotate selected; or change selection");
    392                 }
    393         }
     104        return Cursor.getPredefinedCursor(def);
     105    }
     106
     107    private void setCursor(Cursor c) {
     108        if (oldCursor == null) {
     109            oldCursor = Main.map.mapView.getCursor();
     110            Main.map.mapView.setCursor(c);
     111        }
     112    }
     113
     114    private void restoreCursor() {
     115        if (oldCursor != null) {
     116            Main.map.mapView.setCursor(oldCursor);
     117            oldCursor = null;
     118        }
     119    }
     120
     121    @Override public void enterMode() {
     122        super.enterMode();
     123        Main.map.mapView.addMouseListener(this);
     124        Main.map.mapView.addMouseMotionListener(this);
     125        Main.map.mapView.enableVirtualNodes(
     126        Main.pref.getInteger("mappaint.node.virtual-size", 8) != 0);
     127    }
     128
     129    @Override public void exitMode() {
     130        super.exitMode();
     131        selectionManager.unregister(Main.map.mapView);
     132        Main.map.mapView.removeMouseListener(this);
     133        Main.map.mapView.removeMouseMotionListener(this);
     134        Main.map.mapView.enableVirtualNodes(false);
     135    }
     136
     137    /**
     138     * If the left mouse button is pressed, move all currently selected
     139     * objects (if one of them is under the mouse) or the current one under the
     140     * mouse (which will become selected).
     141     */
     142    @Override public void mouseDragged(MouseEvent e) {
     143        if (mode == Mode.select) return;
     144
     145        // do not count anything as a move if it lasts less than 100 milliseconds.
     146        if ((mode == Mode.move) && (System.currentTimeMillis() - mouseDownTime < initialMoveDelay)) return;
     147
     148        if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
     149            return;
     150
     151        if (mode == Mode.move) {
     152            setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
     153        }
     154
     155        if (mousePos == null) {
     156            mousePos = e.getPoint();
     157            return;
     158        }
     159
     160        if (!initialMoveThresholdExceeded) {
     161            int dxp = mousePos.x - e.getX();
     162            int dyp = mousePos.y - e.getY();
     163            int dp = (int) Math.sqrt(dxp*dxp+dyp*dyp);
     164            if (dp < initialMoveThreshold) return;
     165            initialMoveThresholdExceeded = true;
     166        }
     167
     168        EastNorth mouseEN = Main.map.mapView.getEastNorth(e.getX(), e.getY());
     169        EastNorth mouseStartEN = Main.map.mapView.getEastNorth(mousePos.x, mousePos.y);
     170        double dx = mouseEN.east() - mouseStartEN.east();
     171        double dy = mouseEN.north() - mouseStartEN.north();
     172        if (dx == 0 && dy == 0)
     173            return;
     174
     175        if (virtualWay != null)    {
     176            Collection<Command> virtualCmds = new LinkedList<Command>();
     177            virtualCmds.add(new AddCommand(virtualNode));
     178            Way w = virtualWay.way;
     179            Way wnew = new Way(w);
     180            wnew.nodes.add(virtualWay.lowerIndex+1, virtualNode);
     181            virtualCmds.add(new ChangeCommand(w, wnew));
     182            virtualCmds.add(new MoveCommand(virtualNode, dx, dy));
     183            Main.main.undoRedo.add(new SequenceCommand(tr("Add and move a virtual new node to way"), virtualCmds));
     184            selectPrims(Collections.singleton((OsmPrimitive)virtualNode), false, false);
     185            virtualWay = null;
     186            virtualNode = null;
     187        } else {
     188            Collection<OsmPrimitive> selection = Main.ds.getSelected();
     189            Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
     190
     191            // when rotating, having only one node makes no sense - quit silently
     192            if (mode == Mode.rotate && affectedNodes.size() < 2)
     193                return;
     194
     195            Command c = !Main.main.undoRedo.commands.isEmpty()
     196                ? Main.main.undoRedo.commands.getLast() : null;
     197            if (c instanceof SequenceCommand)
     198                c = ((SequenceCommand)c).getLastCommand();
     199
     200            if (mode == Mode.move) {
     201                if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand)c).objects))
     202                    ((MoveCommand)c).moveAgain(dx,dy);
     203                else
     204                    Main.main.undoRedo.add(
     205                        c = new MoveCommand(selection, dx, dy));
     206
     207                for (Node n : affectedNodes) {
     208                    if (n.coor.isOutSideWorld()) {
     209                        // Revert move
     210                        ((MoveCommand) c).moveAgain(-dx, -dy);
     211
     212                        JOptionPane.showMessageDialog(Main.parent,
     213                            tr("Cannot move objects outside of the world."));
     214                        return;
     215                    }
     216                }
     217            } else if (mode == Mode.rotate) {
     218                if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand)c).objects))
     219                    ((RotateCommand)c).rotateAgain(mouseStartEN, mouseEN);
     220                else
     221                    Main.main.undoRedo.add(new RotateCommand(selection, mouseStartEN, mouseEN));
     222            }
     223        }
     224
     225        Main.map.mapView.repaint();
     226        mousePos = e.getPoint();
     227
     228        didMove = true;
     229    }
     230
     231    private Collection<OsmPrimitive> getNearestCollectionVirtual(Point p) {
     232        MapView c = Main.map.mapView;
     233        int snapDistance = Main.pref.getInteger("mappaint.node.virtual-snap-distance", 8);
     234        snapDistance *= snapDistance;
     235        OsmPrimitive osm = c.getNearestNode(p);
     236        virtualWay = null;
     237        virtualNode = null;
     238
     239        if (osm == null)
     240        {
     241            WaySegment nearestWaySeg = c.getNearestWaySegment(p);
     242            if (nearestWaySeg != null)
     243            {
     244                osm = nearestWaySeg.way;
     245                if(Main.pref.getInteger("mappaint.node.virtual-size", 8) > 0)
     246                {
     247                    Way w = (Way)osm;
     248                    Point p1 = c.getPoint(w.nodes.get(nearestWaySeg.lowerIndex).eastNorth);
     249                    Point p2 = c.getPoint(w.nodes.get(nearestWaySeg.lowerIndex+1).eastNorth);
     250                    if(SimplePaintVisitor.isLargeSegment(p1, p2, Main.pref.getInteger("mappaint.node.virtual-space", 70)))
     251                    {
     252                        Point pc = new Point((p1.x+p2.x)/2, (p1.y+p2.y)/2);
     253                        if (p.distanceSq(pc) < snapDistance)
     254                        {
     255                            virtualWay = nearestWaySeg;
     256                            virtualNode = new Node(Main.map.mapView.getLatLon(pc.x, pc.y));
     257                            osm = w;
     258                        }
     259                    }
     260                }
     261            }
     262        }
     263        if (osm == null)
     264            return Collections.emptySet();
     265        return Collections.singleton(osm);
     266    }
     267
     268    /**
     269     * Look, whether any object is selected. If not, select the nearest node.
     270     * If there are no nodes in the dataset, do nothing.
     271     *
     272     * If the user did not press the left mouse button, do nothing.
     273     *
     274     * Also remember the starting position of the movement and change the mouse
     275     * cursor to movement.
     276     */
     277    @Override public void mousePressed(MouseEvent e) {
     278        if (! (Boolean)this.getValue("active")) return;
     279        if (e.getButton() != MouseEvent.BUTTON1)
     280            return;
     281        boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
     282        // boolean alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0;
     283        boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
     284
     285        mouseDownTime = System.currentTimeMillis();
     286        didMove = false;
     287        initialMoveThresholdExceeded = false;
     288
     289        Collection<OsmPrimitive> osmColl = getNearestCollectionVirtual(e.getPoint());
     290
     291        if (ctrl && shift) {
     292            if (Main.ds.getSelected().isEmpty()) selectPrims(osmColl, true, false);
     293            mode = Mode.rotate;
     294            setCursor(ImageProvider.getCursor("rotate", null));
     295        } else if (!osmColl.isEmpty()) {
     296            // Don't replace the selection now if the user clicked on a
     297            // selected object (this would break moving of selected groups).
     298            // We'll do that later in mouseReleased if the user didn't try to
     299            // move.
     300            selectPrims(osmColl,
     301                shift || Main.ds.getSelected().containsAll(osmColl),
     302                ctrl);
     303            mode = Mode.move;
     304        } else {
     305            mode = Mode.select;
     306            oldCursor = Main.map.mapView.getCursor();
     307            selectionManager.register(Main.map.mapView);
     308            selectionManager.mousePressed(e);
     309        }
     310        if(mode != Mode.move || shift || ctrl)
     311        {
     312            virtualNode = null;
     313            virtualWay = null;
     314        }
     315
     316        updateStatusLine();
     317        Main.map.mapView.repaint();
     318
     319        mousePos = e.getPoint();
     320    }
     321
     322    /**
     323     * Restore the old mouse cursor.
     324     */
     325    @Override public void mouseReleased(MouseEvent e) {
     326        if (mode == Mode.select) {
     327            selectionManager.unregister(Main.map.mapView);
     328        }
     329        restoreCursor();
     330
     331        if (mode == Mode.move) {
     332            boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
     333            boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
     334            if (!didMove) {
     335                selectPrims(
     336                    Main.map.mapView.getNearestCollection(e.getPoint()),
     337                    shift, ctrl);
     338            } else {
     339                Collection<OsmPrimitive> selection = Main.ds.getSelected();
     340                if (ctrl) {
     341                    Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection);
     342                    Collection<Node> nn = Main.map.mapView.getNearestNodes(e.getPoint(), affectedNodes);
     343                    if (nn != null) {
     344                        Node n = nn.iterator().next();
     345                        LinkedList<Node> selNodes = new LinkedList<Node>();
     346                        for (OsmPrimitive osm : selection)
     347                            if (osm instanceof Node)
     348                                selNodes.add((Node)osm);
     349                        if (selNodes.size() > 0) {
     350                            selNodes.add(n);
     351                            MergeNodesAction.mergeNodes(selNodes, n);
     352                        }
     353                    }
     354                }
     355                DataSet.fireSelectionChanged(selection);
     356            }
     357        }
     358
     359        updateStatusLine();
     360        mode = null;
     361        updateStatusLine();
     362    }
     363
     364    public void selectionEnded(Rectangle r, boolean alt, boolean shift, boolean ctrl) {
     365        selectPrims(selectionManager.getObjectsInRectangle(r, alt), shift, ctrl);
     366    }
     367
     368    public void selectPrims(Collection<OsmPrimitive> selectionList, boolean shift, boolean ctrl) {
     369        if (shift && ctrl)
     370            return; // not allowed together
     371
     372        Collection<OsmPrimitive> curSel;
     373        if (!ctrl && !shift)
     374            curSel = new LinkedList<OsmPrimitive>(); // new selection will replace the old.
     375        else
     376            curSel = Main.ds.getSelected();
     377
     378        for (OsmPrimitive osm : selectionList)
     379            if (ctrl)
     380                curSel.remove(osm);
     381            else
     382                curSel.add(osm);
     383        Main.ds.setSelected(curSel);
     384        Main.map.mapView.repaint();
     385    }
     386
     387    @Override public String getModeHelpText() {
     388        if (mode == Mode.select) {
     389            return tr("Release the mouse button to select the objects in the rectangle.");
     390        } else if (mode == Mode.move) {
     391            return tr("Release the mouse button to stop moving. Ctrl to merge with nearest node.");
     392        } else if (mode == Mode.rotate) {
     393            return tr("Release the mouse button to stop rotating.");
     394        } else {
     395            return tr("Move objects by dragging; Shift to add to selection (Ctrl to remove); Shift-Ctrl to rotate selected; or change selection");
     396        }
     397    }
    394398}
Note: See TracChangeset for help on using the changeset viewer.