package com.baselet.control.util; import java.awt.BasicStroke; import java.awt.RenderingHints; import java.awt.Stroke; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Vector; import com.baselet.control.basics.geom.Point; import com.baselet.control.constants.Constants; import com.baselet.control.constants.FacetConstants; import com.baselet.control.enums.LineType; import com.baselet.diagram.draw.DoubleStroke; public abstract class Utils { private Utils() {} // private constructor to avoid instantiation public static Point normalize(Point p, int pixels) { Point ret = new Point(); double d = Math.sqrt(p.x * p.x + p.y * p.y); ret.x = (int) (p.x / d * pixels); ret.y = (int) (p.y / d * pixels); return ret; } public static Vector<String> decomposeStringsIncludingEmptyStrings(String s, String delimiter) { return decomposeStringsWFilter(s, delimiter, false, false); } public static Vector<String> decomposeStringsWithEmptyLines(String s) { return Utils.decomposeStringsWFilter(s, Constants.NEWLINE, true, false); } public static Vector<String> decomposeStringsWithComments(String s) { return Utils.decomposeStringsWFilter(s, Constants.NEWLINE, false, true); } public static Vector<String> decomposeStrings(String s, String delimiter) { return Utils.decomposeStringsWFilter(s, delimiter, true, true); } public static Vector<String> decomposeStrings(String s) { return decomposeStrings(s, Constants.NEWLINE); } // TODO: Decomposing should be moved to Properties.class. At the moment OldGridElement uses this method and NewGridElement the one in Properties.class private static Vector<String> decomposeStringsWFilter(String fullString, String delimiter, boolean filterComments, boolean filterNewLines) { Vector<String> returnVector = new Vector<String>(); String compatibleFullString = fullString.replaceAll("\r\n", delimiter); // compatibility to windows \r\n for (String line : compatibleFullString.split("\\" + delimiter)) { if (filterComments && line.matches("((//)|(fg=)|(bg=)|(autoresize=)|(layer=)|(group=)).*")) { continue; } else if (filterNewLines && line.isEmpty()) { continue; } else { returnVector.add(line); } } return returnVector; } public static String composeStrings(Vector<String> v, String delimiter) { String ret = null; if (v != null) { for (int i = 0; i < v.size(); i++) { if (ret == null) { ret = v.elementAt(i); } else { ret = ret + delimiter + v.elementAt(i); } } } if (ret == null) { ret = ""; } return ret; } public static Stroke getStroke(LineType lineType, float lineThickness) { // If the lineThickness is not supported, the default type is used if (lineThickness < 0) { lineThickness = (float) FacetConstants.LINE_WIDTH_DEFAULT; } Stroke stroke = null; if (lineType == LineType.SOLID) { stroke = new BasicStroke(lineThickness); } else if (lineType == LineType.DASHED) { stroke = new BasicStroke(lineThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 5.0f, new float[] { 8.0f, 5.0f }, 0.0f); } else if (lineType == LineType.DOTTED) { stroke = new BasicStroke(lineThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 5.0f, new float[] { 1.0f, 2.0f }, 0.0f); } else if (lineType == LineType.DOUBLE) { stroke = new DoubleStroke(lineThickness, 4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 5.0f, null, 0.0f); } else if (lineType == LineType.DOUBLE_DASHED) { stroke = new DoubleStroke(lineThickness, 4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 5.0f, new float[] { 8.0f, 5.0f }, 0.0f); } else if (lineType == LineType.DOUBLE_DOTTED) { stroke = new DoubleStroke(lineThickness, 3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 5.0f, new float[] { 1.0f, 2.0f }, 0.0f); } return stroke; } public static Map<RenderingHints.Key, Object> getUxRenderingQualityHigh(boolean subpixelRendering) { HashMap<RenderingHints.Key, Object> renderingHints = new HashMap<RenderingHints.Key, Object>(); renderingHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); renderingHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); renderingHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); if (subpixelRendering) { renderingHints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); } else { renderingHints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF); } renderingHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); return renderingHints; } /** * Calculates and returns the angle of the line defined by the coordinates */ public static double getAngle(double x1, double y1, double x2, double y2) { double res; double x = x2 - x1; double y = y2 - y1; res = Math.atan(y / x); if (x >= 0.0 && y >= 0.0) { res += 0.0; } else if (x < 0.0 && y >= 0.0) { res += Math.PI; } else if (x < 0.0 && y < 0.0) { res += Math.PI; } else if (x >= 0.0 && y < 0.0) { res += 2.0 * Math.PI; } return res; } /** * eg: createDoubleArrayFromTo(5, 6, 0.1) = [5, 5.1, 5.2, ..., 5.9, 6] <br/> * eg: createDoubleArrayFromTo(10, 20, 3) = [10, 13, 16, 19, 22] <br/> * * @param min first value of the result array * @param max if this value is reached (or passed if it's not dividable through "step") the array is finished * @param step the stepsize of the array */ public static Double[] createDoubleArrayFromTo(Double min, Double max, Double step) { if (min > max) { return null; } int range = (int) Math.ceil((max - min) / step + 1); Double[] returnArray = new Double[range]; for (int i = 0; i < range; i++) { returnArray[i] = min + i * step; } return returnArray; } public static Double[] createDoubleArrayFromTo(Double min, Double max) { return createDoubleArrayFromTo(min, max, 1D); } public static class BuildInfo { public String version; public String buildtime; } /** * Read build info from the BuildInfo.propreties file at the root of the classpath */ public static BuildInfo readBuildInfo() { InputStream stream = Utils.class.getResourceAsStream("/BuildInfo.properties"); if (stream == null) { throw new RuntimeException("Cannot load BuildInfo.properties"); } else { Properties prop = new Properties(); try { prop.load(stream); BuildInfo result = new BuildInfo(); result.version = prop.getProperty("version"); result.buildtime = prop.getProperty("buildtime"); return result; } catch (IOException e) { throw new RuntimeException("Cannot load properties from file BuildInfo.properties", e); } finally { try { stream.close(); } catch (IOException e) {/* nothing to do */} } } } }