Changeset 5418 in josm


Ignore:
Timestamp:
2012-08-10T21:01:12+02:00 (7 years ago)
Author:
akks
Message:

fix #7082 (?) - CTRL-drag in selection mode problem, see #7888: SelectAction and MoveCommand rework

Location:
trunk/src/org/openstreetmap/josm
Files:
2 edited

Legend:

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

    r5394 r5418  
    120120    private Point startingDraggingPos;
    121121    /**
     122     * point where user pressed the mouse to start movement
     123     */
     124    EastNorth startEN;
     125    /**
    122126     * The last known position of the mouse.
    123127     */
     
    198202    }
    199203
     204    int previousModifiers;
     205   
    200206     /**
    201207     * This is called whenever the keyboard modifier status changes
     
    206212        // We don't have a mouse event, so we pass the old mouse event but the
    207213        // new modifiers.
     214        int modif = ((InputEvent) e).getModifiers();
     215        if (previousModifiers == modif)
     216            return;
     217        previousModifiers = modif;
    208218        if(giveUserFeedback(oldEvent, ((InputEvent) e).getModifiers())) {
    209219            mv.repaint();
     
    397407        mouseDownTime = System.currentTimeMillis();
    398408        lastMousePos = e.getPoint();
     409        startEN = mv.getEastNorth(lastMousePos.x,lastMousePos.y);
    399410
    400411        // primitives under cursor are stored in c collection
     
    424435            }
    425436            selectPrims(cycleManager.cycleSetup(nearestPrimitive, e.getPoint()), false, false);
     437            useLastMoveCommandIfPossible();
    426438            break;
    427439        case select:
     
    509521
    510522        if (!initialMoveThresholdExceeded) {
    511             int dxp = lastMousePos.x - e.getX();
    512             int dyp = lastMousePos.y - e.getY();
    513             int dp = (int) Math.sqrt(dxp * dxp + dyp * dyp);
     523            int dp = (int) lastMousePos.distance(e.getX(), e.getY());
    514524            if (dp < initialMoveThreshold)
    515525                return;
     
    518528
    519529        EastNorth currentEN = mv.getEastNorth(e.getX(), e.getY());
    520         EastNorth lastEN = mv.getEastNorth(lastMousePos.x, lastMousePos.y);
    521         //EastNorth startEN = mv.getEastNorth(startingDraggingPos.x, startingDraggingPos.y);
    522         double dx = currentEN.east() - lastEN.east();
    523         double dy = currentEN.north() - lastEN.north();
    524         if (dx == 0 && dy == 0)
    525             return;
    526 
     530        if (e.getPoint().equals(lastMousePos))
     531            return;
     532       
    527533        if (virtualManager.hasVirtualWays()) {
    528             virtualManager.processVirtualNodeMovements(dx, dy);
     534            virtualManager.processVirtualNodeMovements(currentEN);
    529535        } else {
    530             if (!updateCommandWhileDragging(dx, dy, currentEN)) return;
     536            if (!updateCommandWhileDragging(currentEN)) return;
    531537        }
    532538
     
    561567
    562568            // Select Draw Tool if no selection has been made
    563             if (getCurrentDataSet().getSelected().size() == 0 && !cancelDrawMode) {
     569            if (getCurrentDataSet().getSelected().isEmpty() && !cancelDrawMode) {
    564570                Main.map.selectDrawTool(true);
    565571                return;
     
    646652     * Create or update data modfication command whle dragging mouse - implementation of
    647653     * continuous moving, scaling and rotation
    648      * @param dx, @param dy - mouse displacement
    649      * @param currentEN -
     654     * @param currentEN - mouse position
    650655     * @return
    651656     */
    652     private boolean updateCommandWhileDragging(double dx, double dy, EastNorth currentEN) {
     657    private boolean updateCommandWhileDragging(EastNorth currentEN) {
    653658        // Currently we support only transformations which do not affect relations.
    654659        // So don't add them in the first place to make handling easier
     
    659664            return false;
    660665        }
    661         Command c = !Main.main.undoRedo.commands.isEmpty()
    662                 ? Main.main.undoRedo.commands.getLast() : null;
    663         if (c instanceof SequenceCommand) {
    664             c = ((SequenceCommand) c).getLastCommand();
    665         }
     666        Command c = getLastCommand();
    666667        if (mode == Mode.move) {
    667668            getCurrentDataSet().beginUpdate();
    668669            if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {
    669                 ((MoveCommand) c).moveAgain(dx, dy);
     670                ((MoveCommand) c).saveCheckpoint();
     671                ((MoveCommand) c).applyVectorTo(currentEN);
    670672            } else {
    671673                Main.main.undoRedo.add(
    672                         c = new MoveCommand(selection, dx, dy));
    673             }
    674             getCurrentDataSet().endUpdate();
     674                        c = new MoveCommand(selection, startEN, currentEN));
     675            }
    675676            for (Node n : affectedNodes) {
    676677                if (n.getCoor().isOutSideWorld()) {
    677678                    // Revert move
    678                     ((MoveCommand) c).moveAgain(-dx, -dy);
     679                    ((MoveCommand) c).resetToCheckpoint();
    679680                    JOptionPane.showMessageDialog(
    680681                            Main.parent,
     
    686687                }
    687688            }
     689            getCurrentDataSet().endUpdate();
    688690        } else if (mode == Mode.rotate) {
    689691            getCurrentDataSet().beginUpdate();
     
    704706        }
    705707        return true;
     708    }
     709   
     710    /**
     711     * Adapt last move command (if it is suitabble) to work with next drag, startedd at point startEN
     712     */
     713    private void useLastMoveCommandIfPossible() {
     714        Command c = getLastCommand();
     715        Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(getCurrentDataSet().getSelected());
     716        if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {
     717            // old command was created with different base point of movement, we need to recalculate it
     718            ((MoveCommand) c).changeStartPoint(startEN);
     719        }
     720    }
     721       
     722    /**
     723     * Obtain command in undoRedo stack to "continue" when dragging
     724     */
     725    private Command getLastCommand() {
     726        Command c = !Main.main.undoRedo.commands.isEmpty()
     727                ? Main.main.undoRedo.commands.getLast() : null;
     728        if (c instanceof SequenceCommand) {
     729            c = ((SequenceCommand) c).getLastCommand();
     730        }
     731        return c;
    706732    }
    707733   
     
    10361062        }
    10371063
    1038         private void processVirtualNodeMovements(double dx, double dy) {
     1064        private void processVirtualNodeMovements(EastNorth currentEN) {
    10391065            Collection<Command> virtualCmds = new LinkedList<Command>();
    10401066            virtualCmds.add(new AddCommand(virtualNode));
     
    10451071                virtualCmds.add(new ChangeCommand(w, wnew));
    10461072            }
    1047             virtualCmds.add(new MoveCommand(virtualNode, dx, dy));
     1073            virtualCmds.add(new MoveCommand(virtualNode, startEN, currentEN));
    10481074            String text = trn("Add and move a virtual new node to way",
    10491075                    "Add and move a virtual new node to {0} ways", virtualWays.size(),
  • trunk/src/org/openstreetmap/josm/command/MoveCommand.java

    r4918 r5418  
    3333    private Collection<Node> nodes = new LinkedList<Node>();
    3434    /**
     35     * Starting position, base command point, current (mouse-drag) position = startEN + (x,y) =
     36     */
     37    private EastNorth startEN;
     38
     39    /**
    3540     * x difference movement. Coordinates are in northern/eastern
    3641     */
     
    4045     */
    4146    private double y;
     47
     48    private double backupX;
     49    private double backupY;
    4250
    4351    /**
     
    4755    public static class OldState {
    4856        LatLon latlon;
     57        EastNorth en; // cached EastNorth to be used for applying exact displacenment
    4958        boolean modified;
    5059    }
     
    6675        this(objects, offset.getX(), offset.getY());
    6776    }
    68 
     77   
    6978    /**
    7079     * Create a MoveCommand and assign the initial object set and movement vector.
     
    7281    public MoveCommand(Collection<OsmPrimitive> objects, double x, double y) {
    7382        super();
     83        startEN = null;
     84        saveCheckpoint(); // (0,0) displacement will be saved
    7485        this.x = x;
    7586        this.y = y;
     
    7889            OldState os = new OldState();
    7990            os.latlon = new LatLon(n.getCoor());
     91            os.en = n.getEastNorth();
    8092            os.modified = n.isModified();
    8193            oldState.add(os);
     
    8395    }
    8496
     97     public MoveCommand(Collection<OsmPrimitive> objects, EastNorth start, EastNorth end) {
     98         this(objects, end.getX()-start.getX(), end.getY()-start.getY());
     99         startEN =  start;
     100     }
     101
     102     public MoveCommand(OsmPrimitive p, EastNorth start, EastNorth end) {
     103         this(Collections.singleton(p), end.getX()-start.getX(), end.getY()-start.getY());
     104         startEN =  start;
     105     }
     106     
    85107    /**
    86108     * Move the same set of objects again by the specified vector. The vectors
     
    102124        moveAgain(x - this.x, y - this.y);
    103125    }
     126   
     127    /**
     128     * Change the displacement vector to have endpoint @param currentEN
     129     * starting point is  startEN
     130     */
     131    public void applyVectorTo(EastNorth currentEN) {
     132        if (startEN == null)
     133            return;
     134        x = currentEN.getX() - startEN.getX();
     135        y = currentEN.getY() - startEN.getY();
     136        updateCoordinates();
     137    }
     138
     139     /**
     140     * Changes base point of movement
     141     * @param newDraggedStartPoint - new starting point after movement (where user clicks to start new drag)
     142     */
     143    public void changeStartPoint(EastNorth newDraggedStartPoint) {
     144        startEN = new EastNorth(newDraggedStartPoint.getX()-x, newDraggedStartPoint.getY()-y);
     145     }
     146
     147    /**
     148     * Save curent displacement to restore in case of some problems
     149     */
     150    public void saveCheckpoint() {
     151        backupX = x;
     152        backupY = y;
     153    }
     154
     155    /**
     156     * Restore old displacement in case of some problems
     157     */
     158    public void resetToCheckpoint() {
     159        x = backupX;
     160        y = backupY;
     161        updateCoordinates();
     162    }
     163
     164    private void updateCoordinates() {
     165        Iterator<OldState> it = oldState.iterator();
     166        for (Node n : nodes) {
     167            OldState os = it.next();
     168            n.setEastNorth(os.en.add(x, y));
     169        }
     170    }
    104171
    105172    @Override public boolean executeCommand() {
Note: See TracChangeset for help on using the changeset viewer.