Ticket #24695: 24695.patch

File 24695.patch, 7.4 KB (added by GerdP, 44 hours ago)

change code to handle repeated scale or rotation, add check that warns when there is at least one download area and one or more modified nodes are outside

  • src/org/openstreetmap/josm/actions/mapmode/SelectAction.java

     
    792792            return ds.update(() -> {
    793793                if (mode == Mode.ROTATE) {
    794794                    if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand) c).getTransformedNodes())) {
    795                         ((RotateCommand) c).handleEvent(currentEN);
     795                        if (didMouseDrag) {
     796                            ((RotateCommand) c).handleEvent(currentEN);
     797                        } else {
     798                            ((RotateCommand) c).handleUpdate(currentEN);
     799                        }
    796800                    } else {
    797801                        UndoRedoHandler.getInstance().add(new RotateCommand(selection, currentEN));
    798802                    }
    799803                } else if (mode == Mode.SCALE) {
    800804                    if (c instanceof ScaleCommand && affectedNodes.equals(((ScaleCommand) c).getTransformedNodes())) {
    801                         ((ScaleCommand) c).handleEvent(currentEN);
     805                        if (didMouseDrag) {
     806                            ((ScaleCommand) c).handleEvent(currentEN);
     807                        } else {
     808                            ((ScaleCommand) c).handleUpdate(currentEN);
     809                        }
    802810                    } else {
    803811                        UndoRedoHandler.getInstance().add(new ScaleCommand(selection, currentEN));
    804812                    }
     
    821829        }
    822830    }
    823831
     832    private boolean movesOutside() {
     833        DataSet ds = getLayerManager().getEditDataSet();
     834        if (ds.getDataSourceBounds().isEmpty())
     835            return false;
     836        final Collection<Node> elementsToTest = new HashSet<>(ds.getSelectedNodes());
     837        for (Way osm : ds.getSelectedWays()) {
     838            elementsToTest.addAll(osm.getNodes());
     839        }
     840        for (Node n : elementsToTest) {
     841            if (n.isOutsideDownloadArea())
     842                return true;
     843        }
     844        return false;
     845    }
     846
    824847    private static boolean doesImpactStatusLine(Collection<Node> affectedNodes, Collection<Way> selectedWays) {
    825848        return selectedWays.stream()
    826849                .flatMap(w -> w.getNodes().stream())
     
    870893     * @param e the mouse event causing the action (mouse released)
    871894     */
    872895    private void confirmOrUndoMovement(MouseEvent e) {
     896        final Command lastCommand = UndoRedoHandler.getInstance().getLastCommand();
     897        if (lastCommand == null) {
     898            Logging.warn("No command found in undo/redo history, skipping confirmOrUndoMovement");
     899            return;
     900        }
     901
    873902        if (movesHiddenWay()) {
    874903            final ConfirmMoveDialog ed = new ConfirmMoveDialog();
    875904            ed.setContent(tr("Are you sure that you want to move elements with attached ways that are hidden by filters?"));
     
    876905            ed.toggleEnable("movedHiddenElements");
    877906            showConfirmMoveDialog(ed);
    878907        }
     908        // check if move was cancelled
     909        if (UndoRedoHandler.getInstance().getLastCommand() != lastCommand)
     910            return;
    879911
    880         final Command lastCommand = UndoRedoHandler.getInstance().getLastCommand();
    881         if (lastCommand == null) {
    882             Logging.warn("No command found in undo/redo history, skipping confirmOrUndoMovement");
     912        if (movesOutside()) {
     913            final ConfirmMoveDialog ed = new ConfirmMoveDialog();
     914            ed.setContent(tr("Are you sure that you want to move nodes outside the downloaded area?"));
     915            ed.toggleEnable("movedOutsideNodes");
     916            showConfirmMoveDialog(ed);
     917        }
     918        // check if move was cancelled
     919        if (UndoRedoHandler.getInstance().getLastCommand() != lastCommand)
    883920            return;
    884         }
    885921
    886922        SelectAction.checkCommandForLargeDistance(lastCommand);
    887923
  • src/org/openstreetmap/josm/command/RotateCommand.java

     
    2525    /**
    2626     * angle of rotation starting click to pivot
    2727     */
    28     private final double startAngle;
     28    private double startAngle;
    2929
    3030    /**
    3131     * computed rotation angle between starting click and current mouse pos
     
    3232     */
    3333    private double rotationAngle;
    3434
     35    private double deltaAngle;
     36
    3537    /**
    3638     * Creates a RotateCommand.
    3739     * Assign the initial object set, compute pivot point and initial rotation angle.
     
    6567    @Override
    6668    public final void handleEvent(EastNorth currentEN) {
    6769        double currentAngle = getAngle(currentEN);
    68         rotationAngle = currentAngle - startAngle;
     70        rotationAngle = currentAngle - startAngle + deltaAngle;
    6971        transformNodes();
    7072    }
    7173
    7274    /**
     75     * Handle a repeated rotation action where the mouse was moved to a different position
     76     * see #24695
     77     * @param startEN start cursor position of a repeated rotation
     78     */
     79    public void handleUpdate(EastNorth startEN) {
     80        deltaAngle = rotationAngle;
     81        startAngle = getAngle(startEN);
     82    }
     83
     84    /**
    7385     * Set the rotation angle.
    7486     * @param rotationAngle The rotate angle
    7587     */
  • src/org/openstreetmap/josm/command/ScaleCommand.java

     
    2626    private double scalingFactor;
    2727
    2828    /**
     29     * scaling factor applied previously
     30     */
     31    private double deltaScalingFactor;
     32
     33    /**
    2934     * World position of the mouse when the user started the command.
    3035     */
    31     private final EastNorth startEN;
     36    private EastNorth startEN;
    3237
    3338    /**
    3439     * Creates a ScaleCommand.
     
    5762     */
    5863    @Override
    5964    public final void handleEvent(EastNorth currentEN) {
    60         double startAngle = Math.atan2(startEN.east()-pivot.east(), startEN.north()-pivot.north());
    61         double endAngle = Math.atan2(currentEN.east()-pivot.east(), currentEN.north()-pivot.north());
     65        setScalingFactor(deltaScalingFactor + calcScalingFactor(currentEN));
     66        transformNodes();
     67    }
     68
     69    /**
     70     * Handle a repeated scaling action where the mouse was moved to a different position
     71     * see #24695
     72     * @param newStartEN start cursor position of a repeated scaling
     73     */
     74    public void handleUpdate(EastNorth newStartEN) {
     75        startEN = newStartEN;
     76        deltaScalingFactor = scalingFactor - calcScalingFactor(newStartEN);
     77    }
     78
     79    private double calcScalingFactor(EastNorth currentEN) {
     80        double startAngle = Math.atan2(startEN.east() - pivot.east(), startEN.north() - pivot.north());
     81        double endAngle = Math.atan2(currentEN.east() - pivot.east(), currentEN.north() - pivot.north());
    6282        double startDistance = pivot.distance(startEN);
    6383        double currentDistance = pivot.distance(currentEN);
    64         setScalingFactor(Math.cos(startAngle-endAngle) * currentDistance / startDistance);
    65         transformNodes();
     84        return Math.cos(startAngle - endAngle) * currentDistance / startDistance;
    6685    }
    6786
    6887    /**