Ignore:
Timestamp:
2012-09-08T15:08:25+02:00 (12 years ago)
Author:
bastiK
Message:

applied #7990 extruder: different curser icons for non-rectangled variants or different preview (patch by AlfonZ)

File:
1 edited

Legend:

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

    r4982 r5506  
    33
    44import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
     5import static org.openstreetmap.josm.tools.I18n.marktr;
    56import static org.openstreetmap.josm.tools.I18n.tr;
    67
     
    6364     */
    6465    private boolean alwaysCreateNodes = false;
     66
    6567    private long mouseDownTime = 0;
    6668    private WaySegment selectedSegment = null;
     
    6870
    6971    /**
     72     * drawing settings for helper lines
     73     */
     74    private Color helperColor;
     75    private BasicStroke helperStrokeDash;
     76    private BasicStroke helperStrokeRA;
     77
     78    /**
    7079     * Possible directions to move to.
    7180     */
    72     private List<EastNorth> possibleMoveDirections;
     81    private List<ReferenceSegment> possibleMoveDirections;
    7382
    7483    /**
    7584     * The direction that is currently active.
    7685     */
    77     private EastNorth activeMoveDirection;
     86    private ReferenceSegment activeMoveDirection;
    7887
    7988    /**
     
    104113    /** The cursor for the 'create_new' mode. */
    105114    private final Cursor cursorCreateNew;
     115
     116    /** The cursor for the 'translate' mode. */
     117    private final Cursor cursorTranslate;
     118
     119    /** The cursor for the 'alwaysCreateNodes' submode. */
     120    private final Cursor cursorCreateNodes;
     121
     122    private class ReferenceSegment {
     123        public final EastNorth en;
     124        public final WaySegment ws;
     125        public final boolean perpendicular;
     126
     127        public ReferenceSegment(EastNorth en, WaySegment ws, boolean perpendicular) {
     128            this.en = en;
     129            this.ws = ws;
     130            this.perpendicular = perpendicular;
     131        }
     132    }
    106133
    107134    /**
     
    115142            InputEvent ie = (InputEvent) e;
    116143            boolean alt = (ie.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
    117             if(mode == Mode.select) {
    118                 Main.map.mapView.setNewCursor(alt ? cursorCreateNew : cursor, this);
     144            boolean ctrl = (ie.getModifiers() & (ActionEvent.CTRL_MASK)) != 0;
     145            boolean shift = (ie.getModifiers() & (ActionEvent.SHIFT_MASK)) != 0;
     146            if (mode == Mode.select) {
     147                Main.map.mapView.setNewCursor(ctrl ? cursorTranslate : alt ? cursorCreateNew : shift ? cursorCreateNodes : cursor, this);
    119148            }
    120149        }
     
    134163        selectedColor = PaintColors.SELECTED.get();
    135164        cursorCreateNew = ImageProvider.getCursor("normal", "rectangle_plus");
     165        cursorTranslate = ImageProvider.getCursor("normal", "rectangle_move");
     166        cursorCreateNodes = ImageProvider.getCursor("normal", "rectangle_plussmall");
     167        helperColor = Main.pref.getColor(marktr("Extrude: helper line"), Color.ORANGE);
     168        float dash1[] = { 4.0f };
     169        helperStrokeDash = new BasicStroke(1.0f, BasicStroke.CAP_BUTT,
     170                BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f);
     171        helperStrokeRA = new BasicStroke(1);
    136172    }
    137173
     
    212248
    213249            //gather possible move directions - perpendicular to the selected segment and parallel to neighbor segments
    214             possibleMoveDirections = new ArrayList<EastNorth>();
    215             possibleMoveDirections.add(new EastNorth(
     250            possibleMoveDirections = new ArrayList<ReferenceSegment>();
     251            possibleMoveDirections.add(new ReferenceSegment(new EastNorth(
    216252                    initialN1en.getY() - initialN2en.getY(),
    217                     initialN2en.getX() - initialN1en.getX()));
     253                    initialN2en.getX() - initialN1en.getX()
     254                    ), selectedSegment, true));
    218255
    219256            //add directions parallel to neighbor segments
     
    222259            if (prevNode != null) {
    223260                EastNorth en = prevNode.getEastNorth();
    224                 possibleMoveDirections.add(new EastNorth(
     261                possibleMoveDirections.add(new ReferenceSegment(new EastNorth(
    225262                        initialN1en.getX() - en.getX(),
    226                         initialN1en.getY() - en.getY()));
     263                        initialN1en.getY() - en.getY()
     264                        ), new WaySegment(selectedSegment.way, getPreviousNodeIndex(selectedSegment.lowerIndex)), false));
    227265            }
    228266
     
    230268            if (nextNode != null) {
    231269                EastNorth en = nextNode.getEastNorth();
    232                 possibleMoveDirections.add(new EastNorth(
     270                possibleMoveDirections.add(new ReferenceSegment(new EastNorth(
    233271                        initialN2en.getX() - en.getX(),
    234                         initialN2en.getY() - en.getY()));
     272                        initialN2en.getY() - en.getY()
     273                        ), new WaySegment(selectedSegment.way, getPreviousNodeIndex(getNextNodeIndex(getNextNodeIndex(selectedSegment.lowerIndex)))), false));
    235274            }
    236275
     
    278317
    279318            //find the best movement direction and vector
    280             for (EastNorth direction: possibleMoveDirections) {
    281                 EastNorth movement = calculateSegmentOffset(initialN1en, initialN2en, direction , mouseEn);
     319            for (ReferenceSegment direction : possibleMoveDirections) {
     320                EastNorth movement = calculateSegmentOffset(initialN1en, initialN2en, direction.en, mouseEn);
    282321                if (movement == null) {
    283322                    //if direction parallel to segment.
     
    429468
    430469            boolean alt = (e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
     470            boolean ctrl = (e.getModifiers() & (ActionEvent.CTRL_MASK)) != 0;
     471            boolean shift = (e.getModifiers() & (ActionEvent.SHIFT_MASK)) != 0;
    431472            // Switch back into select mode
    432             Main.map.mapView.setNewCursor(alt ? cursorCreateNew : cursor, this);
     473            Main.map.mapView.setNewCursor(ctrl ? cursorTranslate : alt ? cursorCreateNew : shift ? cursorCreateNodes : cursor, this);
    433474            Main.map.mapView.removeTemporaryLayer(this);
    434475            selectedSegment = null;
     
    475516    }
    476517
     518    /**
     519     * Gets a node from selected way before given index.
     520     * @param index  index of current node
     521     * @return index of previous node or -1 if there are no nodes there.
     522     */
     523    private int getPreviousNodeIndex(int index) {
     524        if (index > 0)
     525            return index - 1;
     526        else if (selectedSegment.way.isClosed())
     527            return selectedSegment.way.getNodesCount() - 2;
     528        else
     529            return -1;
     530    }
    477531
    478532    /**
     
    482536     */
    483537    private Node getPreviousNode(int index) {
    484         if (index > 0)
    485             return selectedSegment.way.getNode(index - 1);
    486         else if (selectedSegment.way.isClosed())
    487             return selectedSegment.way.getNode(selectedSegment.way.getNodesCount() - 2);
     538        int indexPrev = getPreviousNodeIndex(index);
     539        if (indexPrev >= 0)
     540            return selectedSegment.way.getNode(indexPrev);
    488541        else
    489542            return null;
    490543    }
    491544
    492     /**
    493      * Gets a node from selected way before given index.
     545
     546    /**
     547     * Gets a node from selected way after given index.
     548     * @param index index of current node
     549     * @return index of next node or -1 if there are no nodes there.
     550     */
     551    private int getNextNodeIndex(int index) {
     552        int count = selectedSegment.way.getNodesCount();
     553        if (index <  count - 1)
     554            return index + 1;
     555        else if (selectedSegment.way.isClosed())
     556            return 1;
     557        else
     558            return -1;
     559    }
     560
     561    /**
     562     * Gets a node from selected way after given index.
    494563     * @param index index of current node
    495564     * @return next node or null if there are no nodes there.
    496565     */
    497566    private Node getNextNode(int index) {
    498         int count = selectedSegment.way.getNodesCount();
    499         if (index <  count - 1)
    500             return selectedSegment.way.getNode(index + 1);
    501         else if (selectedSegment.way.isClosed())
    502             return selectedSegment.way.getNode(1);
     567        int indexNext = getNextNodeIndex(index);
     568        if (indexNext >= 0)
     569            return selectedSegment.way.getNode(indexNext);
    503570        else
    504571            return null;
     
    519586                Point p4 = mv.getPoint(newN2en);
    520587
     588                double fac = 1.0 / activeMoveDirection.en.distance(0,0);
     589                // mult by factor to get unit vector.
     590                EastNorth normalUnitVector = new EastNorth(activeMoveDirection.en.getX() * fac, activeMoveDirection.en.getY() * fac);
     591
     592                // Check to see if our new N1 is in a positive direction with respect to the normalUnitVector.
     593                // Even if the x component is zero, we should still be able to discern using +0.0 and -0.0
     594                if (newN1en != null && ((newN1en.getX() > initialN1en.getX()) != (normalUnitVector.getX() > -0.0))) {
     595                    // If not, use a sign-flipped version of the normalUnitVector.
     596                    normalUnitVector = new EastNorth(-normalUnitVector.getX(), -normalUnitVector.getY());
     597                }
     598
     599                //HACK: swap Y, because the target pixels are top down, but EastNorth is bottom-up.
     600                //This is normally done by MapView.getPoint, but it does not work on vectors.
     601                normalUnitVector.setLocation(normalUnitVector.getX(), -normalUnitVector.getY());
     602
    521603                if (mode == Mode.extrude || mode == Mode.create_new) {
    522604                    // Draw rectangle around new area.
     
    526608                    b.lineTo(p1.x, p1.y);
    527609                    g2.draw(b);
    528                     g2.setStroke(new BasicStroke(1));
     610
     611                    if (activeMoveDirection != null) {
     612                        // Draw reference way
     613                        Point pr1 = mv.getPoint(activeMoveDirection.ws.getFirstNode().getEastNorth());
     614                        Point pr2 = mv.getPoint(activeMoveDirection.ws.getSecondNode().getEastNorth());
     615                        b = new GeneralPath();
     616                        b.moveTo(pr1.x, pr1.y);
     617                        b.lineTo(pr2.x, pr2.y);
     618                        g2.setColor(helperColor);
     619                        g2.setStroke(helperStrokeDash);
     620                        g2.draw(b);
     621
     622                        // Draw right angle marker on first node position, only when moving at right angle
     623                        if (activeMoveDirection.perpendicular) {
     624                            // mirror RightAngle marker, so it is inside the extrude
     625                            double headingRefWS = activeMoveDirection.ws.getFirstNode().getEastNorth().heading(activeMoveDirection.ws.getSecondNode().getEastNorth());
     626                            double headingMoveDir = Math.atan2(normalUnitVector.getY(), normalUnitVector.getX());
     627                            double headingDiff = headingRefWS - headingMoveDir;
     628                            if (headingDiff < 0) headingDiff += 2 * Math.PI;
     629                            boolean mirrorRA = Math.abs(headingDiff - Math.PI) > 1e-5;
     630
     631                            // EastNorth units per pixel
     632                            double factor = 1.0/g2.getTransform().getScaleX();
     633                            double raoffsetx = 8.0*factor*normalUnitVector.getX();
     634                            double raoffsety = 8.0*factor*normalUnitVector.getY();
     635
     636                            Point2D ra1 = new Point2D.Double(pr1.x + raoffsetx, pr1.y+raoffsety);
     637                            Point2D ra3 = new Point2D.Double(pr1.x - raoffsety*(mirrorRA ? -1 : 1), pr1.y + raoffsetx*(mirrorRA ? -1 : 1));
     638                            Point2D ra2 = new Point2D.Double(ra1.getX() - raoffsety*(mirrorRA ? -1 : 1), ra1.getY() + raoffsetx*(mirrorRA ? -1 : 1));
     639                            GeneralPath ra = new GeneralPath();
     640                            ra.moveTo((float)ra1.getX(), (float)ra1.getY());
     641                            ra.lineTo((float)ra2.getX(), (float)ra2.getY());
     642                            ra.lineTo((float)ra3.getX(), (float)ra3.getY());
     643                            g2.setStroke(helperStrokeRA);
     644                            g2.draw(ra);
     645                        }
     646                    }
    529647                } else if (mode == Mode.translate) {
    530648                    // Highlight the new and old segments.
     
    537655                    if (activeMoveDirection != null) {
    538656
    539                         double fac = 1.0 / activeMoveDirection.distance(0,0);
    540                         // mult by factor to get unit vector.
    541                         EastNorth normalUnitVector = new EastNorth(activeMoveDirection.getX() * fac, activeMoveDirection.getY() * fac);
    542 
    543                         // Check to see if our new N1 is in a positive direction with respect to the normalUnitVector.
    544                         // Even if the x component is zero, we should still be able to discern using +0.0 and -0.0
    545                         if (newN1en != null && (newN1en.getX() > initialN1en.getX() != normalUnitVector.getX() > -0.0)) {
    546                             // If not, use a sign-flipped version of the normalUnitVector.
    547                             normalUnitVector = new EastNorth(-normalUnitVector.getX(), -normalUnitVector.getY());
    548                         }
    549 
    550                         //HACK: swap Y, because the target pixels are top down, but EastNorth is bottom-up.
    551                         //This is normally done by MapView.getPoint, but it does not work on vectors.
    552                         normalUnitVector.setLocation(normalUnitVector.getX(), -normalUnitVector.getY());
    553 
    554657                        // Draw a guideline along the normal.
    555658                        Line2D normline;
     
    559662
    560663                        // Draw right angle marker on initial position, only when moving at right angle
    561                         if (activeMoveDirection == possibleMoveDirections.get(0)) {
     664                        if (activeMoveDirection.perpendicular) {
    562665                            // EastNorth units per pixel
    563666                            double factor = 1.0/g2.getTransform().getScaleX();
Note: See TracChangeset for help on using the changeset viewer.