Changeset 10874 in josm for trunk/src


Ignore:
Timestamp:
2016-08-22T20:44:34+02:00 (8 years ago)
Author:
Don-vip
Message:

fix #13412 - Clean up DrawAction, add StrokeProperty (patch by michael2402) - gsoc-core

Location:
trunk/src/org/openstreetmap/josm
Files:
1 added
6 edited

Legend:

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

    r7937 r10874  
    77import org.openstreetmap.josm.data.Preferences;
    88import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
     9import org.openstreetmap.josm.data.preferences.BooleanProperty;
    910
    1011public class PreferenceToggleAction extends JosmAction implements PreferenceChangedListener {
    1112
    1213    private final JCheckBoxMenuItem checkbox;
    13     private final String prefKey;
    14     private final boolean prefDefault;
     14    private final BooleanProperty pref;
    1515
    1616    public PreferenceToggleAction(String name, String tooltip, String prefKey, boolean prefDefault) {
    1717        super(name, null, tooltip, null, false);
    1818        putValue("toolbar", "toggle-" + prefKey);
    19         this.prefKey = prefKey;
    20         this.prefDefault = prefDefault;
    21         this.checkbox = new JCheckBoxMenuItem(this);
    22         this.checkbox.setSelected(Main.pref.getBoolean(prefKey, prefDefault));
    23         Main.pref.addPreferenceChangeListener(this);
     19        this.pref = new BooleanProperty(prefKey, prefDefault);
     20        checkbox = new JCheckBoxMenuItem(this);
     21        checkbox.setSelected(pref.get());
     22        Main.pref.addWeakKeyPreferenceChangeListener(prefKey, this);
    2423    }
    2524
    2625    @Override
    2726    public void actionPerformed(ActionEvent e) {
    28         Main.pref.put(prefKey, checkbox.isSelected());
     27        pref.put(checkbox.isSelected());
    2928    }
    3029
     30    /**
     31     * Get the checkbox that can be used for this action. It can only be used at one place.
     32     * @return The checkbox.
     33     */
    3134    public JCheckBoxMenuItem getCheckbox() {
    3235        return checkbox;
     
    3538    @Override
    3639    public void preferenceChanged(Preferences.PreferenceChangeEvent e) {
    37         if (prefKey.equals(e.getKey())) {
    38             checkbox.setSelected(Main.pref.getBoolean(prefKey, prefDefault));
    39         }
     40        checkbox.setSelected(pref.get());
    4041    }
    4142}
  • trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java

    r10873 r10874  
    1212import java.awt.Graphics2D;
    1313import java.awt.Point;
    14 import java.awt.Stroke;
    1514import java.awt.event.ActionEvent;
    1615import java.awt.event.KeyEvent;
     
    2120import java.util.Collection;
    2221import java.util.Collections;
     22import java.util.Comparator;
    2323import java.util.HashMap;
    2424import java.util.HashSet;
     
    2828import java.util.Map;
    2929import java.util.Set;
     30import java.util.stream.DoubleStream;
    3031
    3132import javax.swing.AbstractAction;
     
    5354import org.openstreetmap.josm.data.osm.visitor.paint.MapPath2D;
    5455import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
     56import org.openstreetmap.josm.data.preferences.AbstractToStringProperty;
     57import org.openstreetmap.josm.data.preferences.BooleanProperty;
     58import org.openstreetmap.josm.data.preferences.CachingProperty;
    5559import org.openstreetmap.josm.data.preferences.ColorProperty;
     60import org.openstreetmap.josm.data.preferences.DoubleProperty;
     61import org.openstreetmap.josm.data.preferences.StrokeProperty;
    5662import org.openstreetmap.josm.gui.MainMenu;
    5763import org.openstreetmap.josm.gui.MapFrame;
    5864import org.openstreetmap.josm.gui.MapView;
     65import org.openstreetmap.josm.gui.MapViewState;
    5966import org.openstreetmap.josm.gui.MapViewState.MapViewPoint;
    6067import org.openstreetmap.josm.gui.NavigatableComponent;
     
    6269import org.openstreetmap.josm.gui.layer.MapViewPaintable;
    6370import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    64 import org.openstreetmap.josm.gui.util.GuiHelper;
    6571import org.openstreetmap.josm.gui.util.KeyPressReleaseListener;
    6672import org.openstreetmap.josm.gui.util.ModifierListener;
     
    8086
    8187    private static final ArrowPaintHelper START_WAY_INDICATOR = new ArrowPaintHelper(Math.toRadians(90), 8);
     88
     89    private static final CachingProperty<Boolean> USE_REPEATED_SHORTCUT
     90            = new BooleanProperty("draw.anglesnap.toggleOnRepeatedA", true).cached();
     91    private static final CachingProperty<BasicStroke> RUBBER_LINE_STROKE
     92            = new StrokeProperty("draw.stroke.helper-line", "3").cached();
     93
     94    private static final CachingProperty<BasicStroke> HIGHLIGHT_STROKE
     95            = new StrokeProperty("draw.anglesnap.stroke.highlight", "10").cached();
     96    private static final CachingProperty<BasicStroke> HELPER_STROKE
     97            = new StrokeProperty("draw.anglesnap.stroke.helper", "1 4").cached();
     98
     99    private static final CachingProperty<Double> SNAP_ANGLE_TOLERANCE
     100            = new DoubleProperty("draw.anglesnap.tolerance", 5.0).cached();
     101    private static final CachingProperty<Boolean> DRAW_CONSTRUCTION_GEOMETRY
     102            = new BooleanProperty("draw.anglesnap.drawConstructionGeometry", true).cached();
     103    private static final CachingProperty<Boolean> SHOW_PROJECTED_POINT
     104            = new BooleanProperty("draw.anglesnap.drawProjectedPoint", true).cached();
     105    private static final CachingProperty<Boolean> SNAP_TO_PROJECTIONS
     106            = new BooleanProperty("draw.anglesnap.projectionsnap", true).cached();
     107
     108    private static final CachingProperty<Boolean> SHOW_ANGLE
     109            = new BooleanProperty("draw.anglesnap.showAngle", true).cached();
     110
     111    private static final CachingProperty<Color> SNAP_HELPER_COLOR
     112            = new ColorProperty(marktr("draw angle snap"), Color.ORANGE).cached();
     113
     114    private static final CachingProperty<Color> HIGHLIGHT_COLOR
     115            = new ColorProperty(marktr("draw angle snap highlight"), ORANGE_TRANSPARENT).cached();
     116
     117    private static final AbstractToStringProperty<Color> RUBBER_LINE_COLOR
     118            = PaintColors.SELECTED.getProperty().getChildColor(marktr("helper line"));
     119
     120    private static final CachingProperty<Boolean> DRAW_HELPER_LINE
     121            = new BooleanProperty("draw.helper-line", true).cached();
     122    private static final CachingProperty<Boolean> DRAW_TARGET_HIGHLIGHT
     123            = new BooleanProperty("draw.target-highlight", true).cached();
     124    private static final CachingProperty<Double> SNAP_TO_INTERSECTION_THRESHOLD
     125            = new DoubleProperty("edit.snap-intersection-threshold", 10).cached();
    82126
    83127    private final Cursor cursorJoinNode;
     
    97141    // repaint if there are changes.
    98142    private transient Set<OsmPrimitive> newHighlights = new HashSet<>();
    99     private boolean drawHelperLine;
    100143    private boolean wayIsFinished;
    101     private boolean drawTargetHighlight;
    102144    private Point mousePos;
    103145    private Point oldMousePos;
    104     private Color rubberLineColor;
    105146
    106147    private transient Node currentBaseNode;
     
    117158    private final SnapChangeAction snapChangeAction;
    118159    private final JCheckBoxMenuItem snapCheckboxMenuItem;
    119     private boolean useRepeatedShortcut;
    120     private transient Stroke rubberLineStroke;
    121160    private static final BasicStroke BASIC_STROKE = new BasicStroke(1);
    122161
    123     private static int snapToIntersectionThreshold;
     162    private Point rightClickPressPos;
    124163
    125164    /**
     
    143182        cursorJoinWay = ImageProvider.getCursor("crosshair", "joinway");
    144183
    145         readPreferences();
    146184        snapHelper.init();
    147         readPreferences();
    148185    }
    149186
     
    166203        updateStatusLine();
    167204        // repaint required if the helper line is active.
    168         boolean needsRepaint = drawHelperLine && !wayIsFinished;
    169         if (drawTargetHighlight) {
     205        boolean needsRepaint = DRAW_HELPER_LINE.get() && !wayIsFinished;
     206        if (DRAW_TARGET_HIGHLIGHT.get()) {
    170207            // move newHighlights to oldHighlights; only update changed primitives
    171208            for (OsmPrimitive x : newHighlights) {
     
    185222        oldHighlights = newHighlights;
    186223
    187         if (!needsRepaint && !drawTargetHighlight)
     224        if (!needsRepaint && !DRAW_TARGET_HIGHLIGHT.get())
    188225            return false;
    189226
     
    246283
    247284    @Override
    248     protected void readPreferences() {
    249         rubberLineColor = new ColorProperty(marktr("helper line"), (Color) null).get();
    250         if (rubberLineColor == null)
    251             rubberLineColor = PaintColors.SELECTED.get();
    252 
    253         rubberLineStroke = GuiHelper.getCustomizedStroke(Main.pref.get("draw.stroke.helper-line", "3"));
    254         drawHelperLine = Main.pref.getBoolean("draw.helper-line", true);
    255         drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true);
    256         snapToIntersectionThreshold = Main.pref.getInteger("edit.snap-intersection-threshold", 10);
    257     }
    258 
    259     @Override
    260285    public void exitMode() {
    261286        super.exitMode();
     
    298323    @Override
    299324    public void doKeyPressed(KeyEvent e) {
    300         if (!snappingShortcut.isEvent(e) && !(useRepeatedShortcut && getShortcut().isEvent(e)))
     325        if (!snappingShortcut.isEvent(e) && !(USE_REPEATED_SHORTCUT.get() && getShortcut().isEvent(e)))
    301326            return;
    302327        snapHelper.setFixedMode();
     
    307332    @Override
    308333    public void doKeyReleased(KeyEvent e) {
    309         if (!snappingShortcut.isEvent(e) && !(useRepeatedShortcut && getShortcut().isEvent(e)))
     334        if (!snappingShortcut.isEvent(e) && !(USE_REPEATED_SHORTCUT.get() && getShortcut().isEvent(e)))
    310335            return;
    311336        if (ignoreNextKeyRelease) {
     
    352377        removeHighlighting();
    353378    }
    354 
    355     private Point rightClickPressPos;
    356379
    357380    @Override
     
    591614            }
    592615        }
    593 
     616        if (!extendedWay && !newNode) {
     617            return; // We didn't do anything.
     618        }
     619
     620        String title = getTitle(newNode, n, newSelection, reuseWays, extendedWay);
     621
     622        Command c = new SequenceCommand(title, cmds);
     623
     624        Main.main.undoRedo.add(c);
     625        if (!wayIsFinished) {
     626            lastUsedNode = n;
     627        }
     628
     629        ds.setSelected(newSelection);
     630
     631        // "viewport following" mode for tracing long features
     632        // from aerial imagery or GPS tracks.
     633        if (Main.map.mapView.viewportFollowing) {
     634            Main.map.mapView.smoothScrollTo(n.getEastNorth());
     635        }
     636        computeHelperLine();
     637        removeHighlighting();
     638    }
     639
     640    private String getTitle(boolean newNode, Node n, Collection<OsmPrimitive> newSelection, List<Way> reuseWays,
     641            boolean extendedWay) {
    594642        String title;
    595643        if (!extendedWay) {
    596             if (!newNode)
    597                 return; // We didn't do anything.
    598             else if (reuseWays.isEmpty()) {
     644            if (reuseWays.isEmpty()) {
    599645                title = tr("Add node");
    600646            } else {
     
    613659            title = tr("Add node into way and connect");
    614660        }
    615 
    616         Command c = new SequenceCommand(title, cmds);
    617 
    618         Main.main.undoRedo.add(c);
    619         if (!wayIsFinished) {
    620             lastUsedNode = n;
    621         }
    622 
    623         ds.setSelected(newSelection);
    624 
    625         // "viewport following" mode for tracing long features
    626         // from aerial imagery or GPS tracks.
    627         if (n != null && Main.map.mapView.viewportFollowing) {
    628             Main.map.mapView.smoothScrollTo(n.getEastNorth());
    629         }
    630         computeHelperLine();
    631         removeHighlighting();
     661        return title;
    632662    }
    633663
     
    10331063            // fall through to default action.
    10341064            // (for semi-parallel lines, intersection might be miles away!)
    1035             if (Main.map.mapView.getPoint2D(n).distance(Main.map.mapView.getPoint2D(intersection)) < snapToIntersectionThreshold) {
     1065            if (Main.map.mapView.getPoint2D(n).distance(Main.map.mapView.getPoint2D(intersection)) < SNAP_TO_INTERSECTION_THRESHOLD.get()) {
    10361066                n.setEastNorth(intersection);
    10371067                return;
     
    11351165
    11361166        Graphics2D g2 = g;
    1137         snapHelper.drawIfNeeded(g2, mv);
    1138         if (!drawHelperLine || wayIsFinished || shift)
    1139             return;
    1140 
    1141         if (!snapHelper.isActive()) { // else use color and stoke from  snapHelper.draw
    1142             g2.setColor(rubberLineColor);
    1143             g2.setStroke(rubberLineStroke);
    1144         } else if (!snapHelper.drawConstructionGeometry)
    1145             return;
     1167        snapHelper.drawIfNeeded(g2, mv.getState());
     1168        if (!DRAW_HELPER_LINE.get() || wayIsFinished || shift)
     1169            return;
     1170
     1171        if (!snapHelper.isActive()) {
     1172            g2.setColor(RUBBER_LINE_COLOR.get());
     1173            g2.setStroke(RUBBER_LINE_STROKE.get());
     1174            paintConstructionGeometry(mv, g2);
     1175        } else if (DRAW_CONSTRUCTION_GEOMETRY.get()) {
     1176            // else use color and stoke from  snapHelper.draw
     1177            paintConstructionGeometry(mv, g2);
     1178        }
     1179    }
     1180
     1181    private void paintConstructionGeometry(MapView mv, Graphics2D g2) {
    11461182        MapPath2D b = new MapPath2D();
    11471183        MapViewPoint p1 = mv.getState().getPointFor(getCurrentBaseNode());
     
    13051341
    13061342    private class SnapHelper {
     1343        private static final String DRAW_ANGLESNAP_ANGLES = "draw.anglesnap.angles";
     1344
    13071345        private final class AnglePopupMenu extends JPopupMenu {
    13081346
     
    13121350                public void actionPerformed(ActionEvent e) {
    13131351                    boolean sel = ((JCheckBoxMenuItem) e.getSource()).getState();
    1314                     Main.pref.put("draw.anglesnap.toggleOnRepeatedA", sel);
    1315                     init();
     1352                    USE_REPEATED_SHORTCUT.put(sel);
    13161353                }
    13171354            });
     
    13221359                public void actionPerformed(ActionEvent e) {
    13231360                    boolean sel = ((JCheckBoxMenuItem) e.getSource()).getState();
    1324                     Main.pref.put("draw.anglesnap.drawConstructionGeometry", sel);
    1325                     Main.pref.put("draw.anglesnap.drawProjectedPoint", sel);
    1326                     Main.pref.put("draw.anglesnap.showAngle", sel);
    1327                     init();
     1361                    DRAW_CONSTRUCTION_GEOMETRY.put(sel);
     1362                    SHOW_PROJECTED_POINT.put(sel);
     1363                    SHOW_ANGLE.put(sel);
    13281364                    enableSnapping();
    13291365                }
     
    13351371                public void actionPerformed(ActionEvent e) {
    13361372                    boolean sel = ((JCheckBoxMenuItem) e.getSource()).getState();
    1337                     Main.pref.put("draw.anglesnap.projectionsnap", sel);
    1338                     init();
     1373                    SNAP_TO_PROJECTIONS.put(sel);
    13391374                    enableSnapping();
    13401375                }
     
    13421377
    13431378            private AnglePopupMenu() {
    1344                 helperCb.setState(Main.pref.getBoolean("draw.anglesnap.drawConstructionGeometry", true));
    1345                 projectionCb.setState(Main.pref.getBoolean("draw.anglesnap.projectionsnapgvff", true));
    1346                 repeatedCb.setState(Main.pref.getBoolean("draw.anglesnap.toggleOnRepeatedA", true));
     1379                helperCb.setState(DRAW_CONSTRUCTION_GEOMETRY.get());
     1380                projectionCb.setState(SNAP_TO_PROJECTIONS.get());
     1381                repeatedCb.setState(USE_REPEATED_SHORTCUT.get());
    13471382                add(repeatedCb);
    13481383                add(helperCb);
     
    13851420        private boolean absoluteFix; // snap angle is absolute
    13861421
    1387         private boolean drawConstructionGeometry;
    1388         private boolean showProjectedPoint;
    1389         private boolean showAngle;
    1390 
    1391         private boolean snapToProjections;
    1392 
    13931422        private EastNorth dir2;
    13941423        private EastNorth projected;
     
    14021431
    14031432        private double[] snapAngles;
    1404         private double snapAngleTolerance;
    14051433
    14061434        private double pe, pn; // (pe, pn) - direction of snapping line
     
    14081436
    14091437        private final String fixFmt = "%d "+tr("FIX");
    1410         private Color snapHelperColor;
    1411         private Color highlightColor;
    1412 
    1413         private Stroke normalStroke;
    1414         private Stroke helperStroke;
    1415         private Stroke highlightStroke;
    14161438
    14171439        private JCheckBoxMenuItem checkBox;
     
    14281450        };
    14291451
     1452        /**
     1453         * Set the initial state
     1454         */
    14301455        public void init() {
    14311456            snapOn = false;
     
    14341459            absoluteFix = false;
    14351460
    1436             Collection<String> angles = Main.pref.getCollection("draw.anglesnap.angles",
    1437                     Arrays.asList("0", "30", "45", "60", "90", "120", "135", "150", "180"));
    1438 
    1439             snapAngles = new double[2*angles.size()];
    1440             int i = 0;
    1441             for (String s: angles) {
    1442                 try {
    1443                     snapAngles[i] = Double.parseDouble(s); i++;
    1444                     snapAngles[i] = 360-Double.parseDouble(s); i++;
    1445                 } catch (NumberFormatException e) {
    1446                     Main.warn("Incorrect number in draw.anglesnap.angles preferences: "+s);
    1447                     snapAngles[i] = 0; i++;
    1448                     snapAngles[i] = 0; i++;
    1449                 }
    1450             }
    1451             snapAngleTolerance = Main.pref.getDouble("draw.anglesnap.tolerance", 5.0);
    1452             drawConstructionGeometry = Main.pref.getBoolean("draw.anglesnap.drawConstructionGeometry", true);
    1453             showProjectedPoint = Main.pref.getBoolean("draw.anglesnap.drawProjectedPoint", true);
    1454             snapToProjections = Main.pref.getBoolean("draw.anglesnap.projectionsnap", true);
    1455 
    1456             showAngle = Main.pref.getBoolean("draw.anglesnap.showAngle", true);
    1457             useRepeatedShortcut = Main.pref.getBoolean("draw.anglesnap.toggleOnRepeatedA", true);
    1458 
    1459             normalStroke = rubberLineStroke;
    1460             snapHelperColor = new ColorProperty(marktr("draw angle snap"), Color.ORANGE).get();
    1461 
    1462             highlightColor = new ColorProperty(marktr("draw angle snap highlight"), ORANGE_TRANSPARENT).get();
    1463             highlightStroke = GuiHelper.getCustomizedStroke(Main.pref.get("draw.anglesnap.stroke.highlight", "10"));
    1464             helperStroke = GuiHelper.getCustomizedStroke(Main.pref.get("draw.anglesnap.stroke.helper", "1 4"));
    1465         }
    1466 
     1461            computeSnapAngles();
     1462            Main.pref.addWeakKeyPreferenceChangeListener(DRAW_ANGLESNAP_ANGLES, e -> this.computeSnapAngles());
     1463        }
     1464
     1465        private void computeSnapAngles() {
     1466            snapAngles = Main.pref.getCollection(DRAW_ANGLESNAP_ANGLES,
     1467                    Arrays.asList("0", "30", "45", "60", "90", "120", "135", "150", "180"))
     1468                    .stream()
     1469                    .mapToDouble(this::parseSnapAngle)
     1470                    .flatMap(s -> DoubleStream.of(s, 360-s))
     1471                    .toArray();
     1472        }
     1473
     1474        private double parseSnapAngle(String string) {
     1475            try {
     1476                return Double.parseDouble(string);
     1477            } catch (NumberFormatException e) {
     1478                Main.warn("Incorrect number in draw.anglesnap.angles preferences: {0}", string);
     1479                return 0;
     1480            }
     1481        }
     1482
     1483        /**
     1484         * Save the snap angles
     1485         * @param angles The angles
     1486         */
    14671487        public void saveAngles(String ... angles) {
    1468             Main.pref.putCollection("draw.anglesnap.angles", Arrays.asList(angles));
     1488            Main.pref.putCollection(DRAW_ANGLESNAP_ANGLES, Arrays.asList(angles));
    14691489        }
    14701490
     
    14731493        }
    14741494
    1475         public void drawIfNeeded(Graphics2D g2, MapView mv) {
     1495        /**
     1496         * Draw the snap hint line.
     1497         * @param g2 graphics
     1498         * @param mv MapView state
     1499         * @since 10874
     1500         */
     1501        public void drawIfNeeded(Graphics2D g2, MapViewState mv) {
    14761502            if (!snapOn || !active)
    14771503                return;
    1478             MapViewPoint p1 = mv.getState().getPointFor(getCurrentBaseNode());
    1479             MapViewPoint p2 = mv.getState().getPointFor(dir2);
    1480             MapViewPoint p3 = mv.getState().getPointFor(projected);
    1481             if (drawConstructionGeometry) {
    1482                 g2.setColor(snapHelperColor);
    1483                 g2.setStroke(helperStroke);
     1504            MapViewPoint p1 = mv.getPointFor(getCurrentBaseNode());
     1505            MapViewPoint p2 = mv.getPointFor(dir2);
     1506            MapViewPoint p3 = mv.getPointFor(projected);
     1507            if (DRAW_CONSTRUCTION_GEOMETRY.get()) {
     1508                g2.setColor(SNAP_HELPER_COLOR.get());
     1509                g2.setStroke(HELPER_STROKE.get());
    14841510
    14851511                MapPath2D b = new MapPath2D();
    14861512                b.moveTo(p2);
    14871513                if (absoluteFix) {
    1488                     b.lineTo(2d*p1.getInViewX()-p2.getInViewX(), 2d*p1.getInViewY()-p2.getInViewY()); // bi-directional line
     1514                    b.lineTo(p2.interpolate(p1, 2)); // bi-directional line
    14891515                } else {
    14901516                    b.lineTo(p3);
     
    14931519            }
    14941520            if (projectionSource != null) {
    1495                 g2.setColor(snapHelperColor);
    1496                 g2.setStroke(helperStroke);
     1521                g2.setColor(SNAP_HELPER_COLOR.get());
     1522                g2.setStroke(HELPER_STROKE.get());
    14971523                MapPath2D b = new MapPath2D();
    14981524                b.moveTo(p3);
    1499                 b.lineTo(mv.getState().getPointFor(projectionSource));
     1525                b.lineTo(mv.getPointFor(projectionSource));
    15001526                g2.draw(b);
    15011527            }
    15021528
    15031529            if (customBaseHeading >= 0) {
    1504                 g2.setColor(highlightColor);
    1505                 g2.setStroke(highlightStroke);
     1530                g2.setColor(HIGHLIGHT_COLOR.get());
     1531                g2.setStroke(HIGHLIGHT_STROKE.get());
    15061532                MapPath2D b = new MapPath2D();
    1507                 b.moveTo(mv.getState().getPointFor(segmentPoint1));
    1508                 b.lineTo(mv.getState().getPointFor(segmentPoint2));
     1533                b.moveTo(mv.getPointFor(segmentPoint1));
     1534                b.lineTo(mv.getPointFor(segmentPoint2));
    15091535                g2.draw(b);
    15101536            }
    15111537
    1512             g2.setColor(rubberLineColor);
    1513             g2.setStroke(normalStroke);
     1538            g2.setColor(RUBBER_LINE_COLOR.get());
     1539            g2.setStroke(RUBBER_LINE_STROKE.get());
    15141540            MapPath2D b = new MapPath2D();
    15151541            b.moveTo(p1);
     
    15181544
    15191545            g2.drawString(labelText, (int) p3.getInViewX()-5, (int) p3.getInViewY()+20);
    1520             if (showProjectedPoint) {
    1521                 g2.setStroke(normalStroke);
     1546            if (SHOW_PROJECTED_POINT.get()) {
     1547                g2.setStroke(RUBBER_LINE_STROKE.get());
    15221548                g2.drawOval((int) p3.getInViewX()-5, (int) p3.getInViewY()-5, 10, 10); // projected point
    15231549            }
    15241550
    1525             g2.setColor(snapHelperColor);
    1526             g2.setStroke(helperStroke);
    1527         }
    1528 
    1529         /* If mouse position is close to line at 15-30-45-... angle, remembers this direction
     1551            g2.setColor(SNAP_HELPER_COLOR.get());
     1552            g2.setStroke(HELPER_STROKE.get());
     1553        }
     1554
     1555        /**
     1556         *  If mouse position is close to line at 15-30-45-... angle, remembers this direction
     1557         * @param currentEN Current position
     1558         * @param baseHeading The heading
     1559         * @param curHeading The current mouse heading
    15301560         */
    15311561        public void checkAngleSnapping(EastNorth currentEN, double baseHeading, double curHeading) {
     
    15511581                } else {
    15521582                    nearestAngle = getNearestAngle(angle);
    1553                     if (getAngleDelta(nearestAngle, angle) < snapAngleTolerance) {
     1583                    if (getAngleDelta(nearestAngle, angle) < SNAP_ANGLE_TOLERANCE.get()) {
    15541584                        active = customBaseHeading >= 0 || Math.abs(nearestAngle - 180) > 1e-3;
    15551585                        // if angle is to previous segment, exclude 180 degrees
     
    15971627
    15981628        private void buildLabelText(double nearestAngle) {
    1599             if (showAngle) {
     1629            if (SHOW_ANGLE.get()) {
    16001630                if (fixed) {
    16011631                    if (absoluteFix) {
     
    16201650        }
    16211651
     1652        /**
     1653         * Gets a snap point close to p. Stores the result for display.
     1654         * @param p The point
     1655         * @return The snap point close to p.
     1656         */
    16221657        public EastNorth getSnapPoint(EastNorth p) {
    16231658            if (!active)
     
    16331668
    16341669            projectionSource = null;
    1635             if (snapToProjections) {
     1670            if (SNAP_TO_PROJECTIONS.get()) {
    16361671                DataSet ds = getLayerManager().getEditDataSet();
    16371672                Collection<Way> selectedWays = ds.getSelectedWays();
     
    16681703        }
    16691704
     1705        /**
     1706         * Disables snapping
     1707         */
    16701708        public void noSnapNow() {
    16711709            active = false;
     
    16911729        }
    16921730
     1731        /**
     1732         * Enable snapping.
     1733         */
    16931734        private void enableSnapping() {
    16941735            snapOn = true;
     
    17271768
    17281769        private double getNearestAngle(double angle) {
    1729             double delta, minDelta = 1e5, bestAngle = 0.0;
    1730             for (double snapAngle : snapAngles) {
    1731                 delta = getAngleDelta(angle, snapAngle);
    1732                 if (delta < minDelta) {
    1733                     minDelta = delta;
    1734                     bestAngle = snapAngle;
    1735                 }
    1736             }
     1770            double bestAngle = DoubleStream.of(snapAngles).boxed()
     1771                    .min(Comparator.comparing(snapAngle -> getAngleDelta(angle, snapAngle))).orElse(0.0);
    17371772            if (Math.abs(bestAngle-360) < 1e-3) {
    17381773                bestAngle = 0;
  • trunk/src/org/openstreetmap/josm/actions/mapmode/ParallelWayAction.java

    r10869 r10874  
    66import static org.openstreetmap.josm.tools.I18n.tr;
    77
     8import java.awt.BasicStroke;
    89import java.awt.Color;
    910import java.awt.Cursor;
    1011import java.awt.Graphics2D;
    1112import java.awt.Point;
    12 import java.awt.Stroke;
    1313import java.awt.event.KeyEvent;
    1414import java.awt.event.MouseEvent;
     
    4141import org.openstreetmap.josm.data.preferences.DoubleProperty;
    4242import org.openstreetmap.josm.data.preferences.IntegerProperty;
    43 import org.openstreetmap.josm.data.preferences.StringProperty;
     43import org.openstreetmap.josm.data.preferences.StrokeProperty;
    4444import org.openstreetmap.josm.gui.MapFrame;
    4545import org.openstreetmap.josm.gui.MapView;
     
    4848import org.openstreetmap.josm.gui.layer.MapViewPaintable;
    4949import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    50 import org.openstreetmap.josm.gui.util.GuiHelper;
    5150import org.openstreetmap.josm.gui.util.ModifierListener;
    5251import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    9493public class ParallelWayAction extends MapMode implements ModifierListener, MapViewPaintable {
    9594
    96     private static final StringProperty HELPER_LINE_STROKE = new StringProperty(prefKey("stroke.hepler-line"), "1");
    97     private static final StringProperty REF_LINE_STROKE = new StringProperty(prefKey("stroke.ref-line"), "1 2 2");
     95    private static final CachingProperty<BasicStroke> HELPER_LINE_STROKE = new StrokeProperty(prefKey("stroke.hepler-line"), "1").cached();
     96    private static final CachingProperty<BasicStroke> REF_LINE_STROKE = new StrokeProperty(prefKey("stroke.ref-line"), "2 2 3").cached();
    9897
    9998    // @formatter:off
     
    147146    private EastNorth helperLineEnd;
    148147
    149     private transient Stroke helpLineStroke;
    150     private transient Stroke refLineStroke;
    151 
    152148    /**
    153149     * Constructs a new {@code ParallelWayAction}.
     
    174170        mv.addMouseMotionListener(this);
    175171        mv.addTemporaryLayer(this);
    176 
    177         helpLineStroke = GuiHelper.getCustomizedStroke(HELPER_LINE_STROKE.get());
    178         refLineStroke = GuiHelper.getCustomizedStroke(REF_LINE_STROKE.get());
    179172
    180173        //// Needed to update the mouse cursor if modifiers are changed when the mouse is motionless
     
    473466
    474467            // FIXME: should clip the line (gets insanely slow when zoomed in on a very long line
    475             g.setStroke(refLineStroke);
     468            g.setStroke(REF_LINE_STROKE.get());
    476469            g.setColor(mainColor);
    477470            MapPath2D line = new MapPath2D();
     
    480473            g.draw(line);
    481474
    482             g.setStroke(helpLineStroke);
     475            g.setStroke(HELPER_LINE_STROKE.get());
    483476            g.setColor(mainColor);
    484477            line = new MapPath2D();
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/PaintColors.java

    r10869 r10874  
    3434    private final String name;
    3535    private final Color defaultColor;
     36    private final ColorProperty baseProperty;
    3637    private final CachingProperty<Color> property;
    3738
     
    5657
    5758    PaintColors(String name, Color defaultColor) {
    58         property = new ColorProperty(name, defaultColor).cached();
     59        baseProperty = new ColorProperty(name, defaultColor);
     60        property = baseProperty.cached();
    5961        this.name = name;
    6062        this.defaultColor = defaultColor;
     
    9698        }
    9799    }
     100
     101    /**
     102     * Get the color property
     103     * @return The property that is used to access the color.
     104     * @since 10874
     105     */
     106    public ColorProperty getProperty() {
     107        return baseProperty;
     108    }
    98109}
  • trunk/src/org/openstreetmap/josm/gui/MapViewState.java

    r10867 r10874  
    523523            return Math.sqrt(distanceToInViewSq(p2));
    524524        }
     525
     526        /**
     527         * Do a linear interpolation to the other point
     528         * @param p1 The other point
     529         * @param i The interpolation factor. 0 is at the current point, 1 at the other point.
     530         * @return The new point
     531         * @since 10874
     532         */
     533        public MapViewPoint interpolate(MapViewPoint p1, int i) {
     534            return new MapViewViewPoint((1 - i) * getInViewX() + i * p1.getInViewX(), (1 - i) * getInViewY() + i * p1.getInViewY());
     535        }
    525536    }
    526537
  • trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java

    r10712 r10874  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.awt.BasicStroke;
    76import java.awt.Color;
    87import java.awt.Component;
     
    5049
    5150import org.openstreetmap.josm.Main;
     51import org.openstreetmap.josm.data.preferences.StrokeProperty;
    5252import org.openstreetmap.josm.gui.ExtendedDialog;
    5353import org.openstreetmap.josm.gui.widgets.HtmlPanel;
     
    300300     * @param code = 3.5 -&gt; thickness=3.5px; 3.5 10 5 -&gt; thickness=3.5px, dashed: 10px filled + 5px empty
    301301     * @return stroke for drawing
     302     * @see StrokeProperty
    302303     */
    303304    public static Stroke getCustomizedStroke(String code) {
    304         String[] s = code.trim().split("[^\\.0-9]+");
    305 
    306         if (s.length == 0) return new BasicStroke();
    307         float w;
    308         try {
    309             w = Float.parseFloat(s[0]);
    310         } catch (NumberFormatException ex) {
    311             w = 1.0f;
    312         }
    313         if (s.length > 1) {
    314             float[] dash = new float[s.length-1];
    315             float sumAbs = 0;
    316             try {
    317                 for (int i = 0; i < s.length-1; i++) {
    318                    dash[i] = Float.parseFloat(s[i+1]);
    319                    sumAbs += Math.abs(dash[i]);
    320                 }
    321             } catch (NumberFormatException ex) {
    322                 Main.error("Error in stroke preference format: "+code);
    323                 dash = new float[]{5.0f};
    324             }
    325             if (sumAbs < 1e-1) {
    326                 Main.error("Error in stroke dash format (all zeros): "+code);
    327                 return new BasicStroke(w);
    328             }
    329             // dashed stroke
    330             return new BasicStroke(w, BasicStroke.CAP_BUTT,
    331                     BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f);
    332         } else {
    333             if (w > 1) {
    334                 // thick stroke
    335                 return new BasicStroke(w, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
    336             } else {
    337                 // thin stroke
    338                 return new BasicStroke(w);
    339             }
    340         }
     305        return StrokeProperty.getFromString(code);
    341306    }
    342307
Note: See TracChangeset for help on using the changeset viewer.