Changeset 1115 in josm


Ignore:
Timestamp:
Dec 12, 2008 12:13:30 AM (4 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.