// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.data.preferences; import java.awt.BasicStroke; import java.util.Collections; import java.util.List; import java.util.regex.Pattern; import java.util.stream.Collectors; import org.openstreetmap.josm.Main; /** * A property that stores a {@link BasicStroke}. * @author Michael Zangl * @since 10874 */ public class StrokeProperty extends AbstractToStringProperty<BasicStroke> { /** * Create a new stroke property from a string. * @param key The key to use * @param defaultValue The default stroke as string */ public StrokeProperty(String key, String defaultValue) { super(key, getFromString(defaultValue)); } /** * Create a new stroke property from a stroke object. * @param key The key * @param defaultStroke The default stroke. */ public StrokeProperty(String key, BasicStroke defaultStroke) { super(key, defaultStroke); } @Override protected BasicStroke fromString(String string) { return getFromString(string); } @Override protected String toString(BasicStroke t) { StringBuilder string = new StringBuilder(); string.append(t.getLineWidth()); float[] dashes = t.getDashArray(); if (dashes != null) { for (float d : dashes) { string.append(' ').append(d); } } return string.toString(); } /** * Return s new BasicStroke object with given thickness and style * @param code = 3.5 -> thickness=3.5px; 3.5 10 5 -> thickness=3.5px, dashed: 10px filled + 5px empty * @return stroke for drawing */ public static BasicStroke getFromString(String code) { Pattern floatPattern = Pattern.compile("(\\.\\d+|\\d+(\\.\\d+)?)"); List<Double> captures = Pattern.compile("[^\\d.]+").splitAsStream(code) .filter(s -> floatPattern.matcher(s).matches()) .map(Double::valueOf).collect(Collectors.toList()); double w = 1; List<Double> dashes = Collections.emptyList(); if (!captures.isEmpty()) { w = captures.get(0); dashes = captures.subList(1, captures.size()); } if (!dashes.isEmpty()) { double sumAbs = dashes.stream().mapToDouble(Math::abs).sum(); if (sumAbs < 1e-1) { Main.error("Error in stroke dash format (all zeros): " + code); dashes = Collections.emptyList(); } } int cap; int join; if (w > 1) { // thick stroke cap = BasicStroke.CAP_ROUND; join = BasicStroke.JOIN_ROUND; } else { // thin stroke cap = BasicStroke.CAP_BUTT; join = BasicStroke.JOIN_MITER; } return new BasicStroke((float) w, cap, join, 10.0f, toDashArray(dashes), 0.0f); } private static float[] toDashArray(List<Double> dashes) { if (dashes.isEmpty()) { return null; } else { float[] array = new float[dashes.size()]; for (int i = 0; i < array.length; i++) { array[i] = (float) (double) dashes.get(i); } return array; } } }