package com.revolsys.swing.map.layer.record.style;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.measure.Measure;
import javax.measure.quantity.Length;
import javax.measure.unit.NonSI;
import javax.measure.unit.Unit;
import com.revolsys.awt.WebColors;
import com.revolsys.geometry.model.LineCap;
import com.revolsys.geometry.model.LineJoin;
import com.revolsys.swing.map.Viewport2D;
import com.revolsys.util.MathUtil;
import com.revolsys.util.Property;
public class GeometryStyle extends MarkerStyle {
private static int colorIndex = -1;
public static final List<Color> COLORS = Arrays.asList(WebColors.Maroon, WebColors.Olive,
WebColors.Green, WebColors.Teal, WebColors.Navy, WebColors.Purple, WebColors.Red,
WebColors.Yellow, WebColors.Lime, WebColors.Aqua, WebColors.Blue, WebColors.Fuchsia);
static {
// addStyleProperty("backgroundColor", Color.class);
// addStyleProperty("backgroundImage", String.class);
// addStyleProperty("base", String.class);
// addStyleProperty("bufferSize", Double.class);
// addStyleProperty("buildingFill", Color.class);
// addStyleProperty("buildingFillOpacity", String.class);
// addStyleProperty("buildingHeight", Double.class);
// addStyleProperty("compOp", String.class);
// addStyleProperty("fontDirectory", String.class);
// addStyleProperty("imageFilters", String.class);
addStyleProperty("lineCap", LineCap.ROUND);
addStyleProperty("lineClip", true);
addStyleProperty("lineColor", new Color(128, 128, 128));
addStyleProperty("lineCompOp", CompositionOperation.src_over);
addStyleProperty("lineDashOffset", 0);
addStyleProperty("lineDashArray", Collections.emptyList());
addStyleProperty("lineGamma", 1.0);
addStyleProperty("lineGammaMethod", GammaMethod.power);
addStyleProperty("lineJoin", LineJoin.ROUND);
addStyleProperty("lineMiterlimit", 4f);
// addStyleProperty("lineOffset", String.class);
addStyleProperty("lineOpacity", 255);
// addStyleProperty("linePattern", String.class);
// addStyleProperty("linePatternClip", String.class);
// addStyleProperty("linePatternCompOp", String.class);
// addStyleProperty("linePatternFile", String.class);
// addStyleProperty("linePatternSmooth", String.class);
// addStyleProperty("lineRasterizer", String.class);
addStyleProperty("lineSmooth", 0.0);
addStyleProperty("lineWidth", ONE_PIXEL);
// addStyleProperty("opacity", String.class);
// addStyleProperty("point", String.class);
// addStyleProperty("pointAllowOverlap", String.class);
// addStyleProperty("pointCompOp", String.class);
// addStyleProperty("pointFile", String.class);
// addStyleProperty("pointIgnorePlacement", String.class);
// addStyleProperty("pointOpacity", String.class);
// addStyleProperty("pointPlacement", String.class);
// addStyleProperty("pointTransform", String.class);
// addStyleProperty("polygon", String.class);
addStyleProperty("polygonClip", true);
addStyleProperty("polygonCompOp", CompositionOperation.src_over);
addStyleProperty("polygonFill", new Color(128, 128, 128));
addStyleProperty("polygonFillOpacity", 255);
addStyleProperty("polygonGamma", 1.0);
addStyleProperty("polygonGammaMethod", GammaMethod.power);
// addStyleProperty("polygonPattern", String.class);
// addStyleProperty("polygonPatternAlignment", String.class);
// addStyleProperty("polygonPatternClip", String.class);
// addStyleProperty("polygonPatternCompOp", String.class);
// addStyleProperty("polygonPatternFile", String.class);
// addStyleProperty("polygonPatternGamma", String.class);
// addStyleProperty("polygonPatternOpacity", String.class);
// addStyleProperty("polygonPatternSmooth", String.class);
addStyleProperty("polygonSmooth", 0.0);
// addStyleProperty("raster", String.class);
// addStyleProperty("rasterCompOp", String.class);
// addStyleProperty("rasterFilterFactor", String.class);
// addStyleProperty("rasterMeshSize", Double.class);
// addStyleProperty("rasterOpacity", String.class);
// addStyleProperty("rasterScaling", String.class);
// addStyleProperty("shield", String.class);
// addStyleProperty("shieldAllowOverlap", String.class);
// addStyleProperty("shieldAvoidEdges", String.class);
// addStyleProperty("shieldCharacterSpacing", String.class);
// addStyleProperty("shieldClip", String.class);
// addStyleProperty("shieldCompOp", String.class);
// addStyleProperty("shieldDx", Double.class);
// addStyleProperty("shieldDy", Double.class);
// addStyleProperty("shieldFaceName", String.class);
// addStyleProperty("shieldFile", String.class);
// addStyleProperty("shieldFill", Color.class);
// addStyleProperty("shieldHaloFill", Color.class);
// addStyleProperty("shieldHaloRadius", String.class);
// addStyleProperty("shieldHorizontalAlignment", String.class);
// addStyleProperty("shieldJustifyAlignment", String.class);
// addStyleProperty("shieldLineSpacing", String.class);
// addStyleProperty("shieldMinDistance", String.class);
// addStyleProperty("shieldMinPadding", String.class);
// addStyleProperty("shieldName", String.class);
// addStyleProperty("shieldOpacity", String.class);
// addStyleProperty("shieldPlacement", String.class);
// addStyleProperty("shieldSize", Double.class);
// addStyleProperty("shieldSpacing", String.class);
// addStyleProperty("shieldTextDx", Double.class);
// addStyleProperty("shieldTextDy", Double.class);
// addStyleProperty("shieldTextOpacity", String.class);
// addStyleProperty("shieldTextTransform", String.class);
// addStyleProperty("shieldverticalAlignment", String.class);
// addStyleProperty("shieldWrapBefore", String.class);
// addStyleProperty("shieldWrapCharacter", String.class);
// addStyleProperty("shieldWrapWidth", Double.class);
// addStyleProperty("srs", String.class);
}
public static final List<Double> DOT = newDash(2.0);
public static final List<Double> DASH_5 = newDash(5.0);
public static final List<Double> DASH_10 = newDash(10.0);
public static final List<Double> DASH_15 = newDash(10.0);
public static final List<Double> DASH_DOT_DOT = newDash(8.0, 3.0, 3.0, 3.0, 3.0, 3.0);
public static final List<Double> DASH_DOT = newDash(8.0, 3.0, 3.0, 3.0);
public static GeometryStyle line(final Color color) {
final GeometryStyle style = new GeometryStyle();
style.setLineColor(color);
return style;
}
public static GeometryStyle line(final Color color, final double lineWidth) {
final GeometryStyle style = new GeometryStyle();
style.setLineColor(color);
style.setLineWidth(Measure.valueOf(lineWidth, NonSI.PIXEL));
return style;
}
public static List<Double> newDash(final Double... dashArray) {
return Arrays.asList(dashArray);
}
public static GeometryStyle newStyle() {
final GeometryStyle style = new GeometryStyle();
Color color;
synchronized (COLORS) {
colorIndex = (colorIndex + 1) % COLORS.size();
color = COLORS.get(colorIndex);
}
style.setLineColor(color);
style.setPolygonFill(WebColors.newAlpha(color, 127));
return style;
}
public static GeometryStyle polygon(final Color lineColor, final Color fillColor) {
final GeometryStyle style = new GeometryStyle();
style.setLineColor(lineColor);
style.setPolygonFill(fillColor);
return style;
}
public static GeometryStyle polygon(final Color lineColor, final int lineWidth,
final Color fillColor) {
final GeometryStyle style = new GeometryStyle();
style.setLineColor(lineColor);
style.setLineWidth(Measure.valueOf(lineWidth, NonSI.PIXEL));
style.setPolygonFill(fillColor);
return style;
}
private LineCap lineCap = LineCap.ROUND;
private boolean lineClip = true;
private Color lineColor = new Color(128, 128, 128, 255);
private CompositionOperation lineCompOp = CompositionOperation.src_over;
private List<Double> lineDashArray = Collections.emptyList();
private double lineDashOffset = 0;
private double lineGamma = 1.0;
private GammaMethod lineGammaMethod = GammaMethod.power;
private LineJoin lineJoin = LineJoin.ROUND;
private float lineMiterlimit = 4;
private int lineOpacity = 255;
private double lineSmooth;
private Measure<Length> lineWidth = ONE_PIXEL;
private boolean polygonClip = true;
private CompositionOperation polygonCompOp = CompositionOperation.src_over;
private Color polygonFill = new Color(128, 128, 128, 255);
private int polygonFillOpacity = 255;
private double polygonGamma = 1.0;
private GammaMethod polygonGammaMethod = GammaMethod.power;
private double polygonSmooth;
public GeometryStyle() {
}
public GeometryStyle(final Map<String, Object> style) {
setProperties(style);
}
@Override
public GeometryStyle clone() {
return (GeometryStyle)super.clone();
}
public LineCap getLineCap() {
return this.lineCap;
}
public Color getLineColor() {
return this.lineColor;
}
public CompositionOperation getLineCompOp() {
return this.lineCompOp;
}
public List<Double> getLineDashArray() {
return this.lineDashArray;
}
public double getLineDashOffset() {
return this.lineDashOffset;
}
public double getLineGamma() {
return this.lineGamma;
}
public GammaMethod getLineGammaMethod() {
return this.lineGammaMethod;
}
public LineJoin getLineJoin() {
return this.lineJoin;
}
public float getLineMiterlimit() {
return this.lineMiterlimit;
}
public int getLineOpacity() {
return this.lineOpacity;
}
public double getLineSmooth() {
return this.lineSmooth;
}
public Measure<Length> getLineWidth() {
return this.lineWidth;
}
public CompositionOperation getPolygonCompOp() {
return this.polygonCompOp;
}
public Color getPolygonFill() {
return this.polygonFill;
}
public int getPolygonFillOpacity() {
return this.polygonFillOpacity;
}
public double getPolygonGamma() {
return this.polygonGamma;
}
public GammaMethod getPolygonGammaMethod() {
return this.polygonGammaMethod;
}
public double getPolygonSmooth() {
return this.polygonSmooth;
}
public boolean isLineClip() {
return this.lineClip;
}
public boolean isPolygonClip() {
return this.polygonClip;
}
public void setFill(final Color fill) {
setPolygonFill(fill);
setMarkerFill(fill);
}
public void setFillStyle(final Viewport2D viewport, final Graphics2D graphics) {
graphics.setPaint(this.polygonFill);
// final Graphic fillPattern = fill.getPattern();
// if (fillPattern != null) {
// TODO fillPattern
// double width = fillPattern.getWidth();
// double height = fillPattern.getHeight();
// Rectangle2D.Double patternRect;
// // TODO units
// // if (isUseModelUnits()) {
// // patternRect = new Rectangle2D.Double(0, 0, width
// // * viewport.getModelUnitsPerViewUnit(), height
// // * viewport.getModelUnitsPerViewUnit());
// // } else {
// patternRect = new Rectangle2D.Double(0, 0, width, height);
// // }
// graphics.setPaint(new TexturePaint(fillPattern, patternRect));
// }
}
public void setLineCap(final LineCap lineCap) {
final Object oldValue = this.lineCap;
this.lineCap = lineCap;
firePropertyChange("lineCap", oldValue, this.lineCap);
}
public void setLineClip(final boolean lineClip) {
final Object oldValue = this.lineClip;
this.lineClip = lineClip;
firePropertyChange("lineClip", oldValue, this.lineClip);
}
public void setLineColor(final Color lineColor) {
final Object oldLineColor = this.lineColor;
final Object oldLineOpacity = this.lineOpacity;
if (lineColor == null) {
this.lineColor = new Color(128, 128, 128, this.lineOpacity);
} else {
this.lineColor = lineColor;
this.lineOpacity = lineColor.getAlpha();
}
firePropertyChange("lineColor", oldLineColor, this.lineColor);
firePropertyChange("lineOpacity", oldLineOpacity, this.lineOpacity);
}
public void setLineCompOp(final CompositionOperation lineCompOp) {
final Object oldValue = this.lineCompOp;
this.lineCompOp = getWithDefault(lineCompOp, CompositionOperation.src_over);
firePropertyChange("lineCompOp", oldValue, this.lineCompOp);
}
public void setLineDashArray(final List<?> lineDashArray) {
final Object oldValue = this.lineDashArray;
final List<Double> dashArray = new ArrayList<>();
if (lineDashArray != null) {
for (final Object dashObject : lineDashArray) {
if (Property.hasValue(dashObject)) {
String dashString = dashObject.toString();
dashString = dashString.replaceAll(" \\[pnt\\]", "");
final Double dash = MathUtil.toDouble(dashString);
dashArray.add(dash);
}
}
}
this.lineDashArray = Collections.unmodifiableList(dashArray);
firePropertyChange("lineDashArray", oldValue, this.lineDashArray);
}
public void setLineDashOffset(final double lineDashOffset) {
final Object oldValue = this.lineDashOffset;
this.lineDashOffset = lineDashOffset;
firePropertyChange("lineDashOffset", oldValue, this.lineDashOffset);
}
public void setLineGamma(final double gamma) {
final Object oldValue = this.lineGamma;
this.lineGamma = gamma;
firePropertyChange("lineGamma", oldValue, this.lineGamma);
}
public void setLineGammaMethod(final GammaMethod gammaMethod) {
final Object oldValue = this.lineGammaMethod;
this.lineGammaMethod = getWithDefault(gammaMethod, GammaMethod.power);
firePropertyChange("lineGammaMethod", oldValue, this.lineGammaMethod);
}
public void setLineJoin(final LineJoin lineJoin) {
final Object oldValue = this.lineJoin;
this.lineJoin = lineJoin;
firePropertyChange("lineJoin", oldValue, this.lineJoin);
}
public void setLineMiterlimit(final float lineMiterlimit) {
final Object oldValue = this.lineMiterlimit;
this.lineMiterlimit = lineMiterlimit;
firePropertyChange("lineMiterlimit", oldValue, this.lineMiterlimit);
}
public void setLineOpacity(final double lineOpacity) {
if (lineOpacity < 0 || lineOpacity > 1) {
throw new IllegalArgumentException("Line opacity must be between 0.0 - 1.0");
} else {
setLineOpacity((int)(255 * lineOpacity));
}
}
public void setLineOpacity(final int lineOpacity) {
if (lineOpacity < 0 || lineOpacity > 255) {
throw new IllegalArgumentException("Line opacity must be between 0 - 255");
} else {
final Object oldLineOpacity = this.lineOpacity;
final Object oldLineColor = this.lineColor;
this.lineOpacity = lineOpacity;
this.lineColor = WebColors.newAlpha(this.lineColor, this.lineOpacity);
firePropertyChange("lineOpacity", oldLineOpacity, this.lineOpacity);
firePropertyChange("lineColor", oldLineColor, this.lineColor);
}
}
public void setLineSmooth(final double smooth) {
final Object oldValue = this.lineSmooth;
this.lineSmooth = smooth;
firePropertyChange("lineSmooth", oldValue, this.lineSmooth);
}
public void setLineStyle(final Viewport2D viewport, final Graphics2D graphics) {
final Color color = getLineColor();
graphics.setColor(color);
final Unit<Length> unit = this.lineWidth.getUnit();
final float width = (float)Viewport2D.toModelValue(viewport, this.lineWidth);
final float dashOffset = (float)Viewport2D.toModelValue(viewport,
Measure.valueOf(this.lineDashOffset, unit));
final float[] dashArray;
final int dashArraySize = this.lineDashArray.size();
if (dashArraySize == 0) {
dashArray = null;
} else {
dashArray = new float[dashArraySize];
for (int i = 0; i < dashArray.length; i++) {
final Double dashDouble = this.lineDashArray.get(i);
final float dashFloat = (float)Viewport2D.toModelValue(viewport,
Measure.valueOf(dashDouble, unit));
dashArray[i] = dashFloat;
}
}
final int lineCap = this.lineCap.getAwtValue();
final int lineJoin = this.lineJoin.getAwtValue();
final BasicStroke basicStroke = new BasicStroke(width, lineCap, lineJoin, this.lineMiterlimit,
dashArray, dashOffset);
graphics.setStroke(basicStroke);
}
public void setLineWidth(final Measure<Length> lineWidth) {
final Object oldValue = this.lineWidth;
this.lineWidth = getWithDefault(lineWidth, ZERO_PIXEL);
firePropertyChange("lineWidth", oldValue, this.lineWidth);
}
public void setPolygonClip(final boolean polygonClip) {
final Object oldValue = this.polygonClip;
this.polygonClip = polygonClip;
firePropertyChange("polygonClip", oldValue, this.polygonClip);
}
public void setPolygonCompOp(final CompositionOperation polygonCompOp) {
final Object oldValue = this.polygonCompOp;
this.polygonCompOp = getWithDefault(polygonCompOp, CompositionOperation.src_over);
firePropertyChange("polygonCompOp", oldValue, this.polygonCompOp);
}
public void setPolygonFill(final Color fill) {
final Object oldPolygonFill = this.polygonFill;
final Object oldPolygonFillOpacity = this.polygonFillOpacity;
if (fill == null) {
this.polygonFill = new Color(128, 128, 128, this.polygonFillOpacity);
} else {
this.polygonFill = fill;
this.polygonFillOpacity = fill.getAlpha();
}
firePropertyChange("polygonFill", oldPolygonFill, this.polygonFill);
firePropertyChange("polygonFillOpacity", oldPolygonFillOpacity, this.polygonFillOpacity);
}
public void setPolygonFillOpacity(final double polygonFillOpacity) {
if (polygonFillOpacity < 0 || polygonFillOpacity > 1) {
throw new IllegalArgumentException("Polygon fill opacity must be between 0.0 - 1.0");
} else {
setPolygonFillOpacity((int)(255 * polygonFillOpacity));
}
}
public void setPolygonFillOpacity(final int polygonFillOpacity) {
final Object oldPolygonFill = this.polygonFill;
final Object oldPolygonFillOpacity = this.polygonFillOpacity;
if (polygonFillOpacity < 0 || polygonFillOpacity > 255) {
throw new IllegalArgumentException("Fill opacity must be between 0 - 255");
} else {
this.polygonFillOpacity = polygonFillOpacity;
this.polygonFill = WebColors.newAlpha(this.polygonFill, this.polygonFillOpacity);
}
firePropertyChange("polygonFill", oldPolygonFill, this.polygonFill);
firePropertyChange("polygonFillOpacity", oldPolygonFillOpacity, this.polygonFillOpacity);
}
public void setPolygonGamma(final double polygonGamma) {
final Object oldValue = this.polygonGamma;
this.polygonGamma = polygonGamma;
firePropertyChange("polygonGamma", oldValue, this.polygonGamma);
}
public void setPolygonGammaMethod(final GammaMethod polygonGammaMethod) {
final Object oldValue = this.polygonGammaMethod;
this.polygonGammaMethod = getWithDefault(polygonGammaMethod, GammaMethod.power);
firePropertyChange("polygonGammaMethod", oldValue, this.polygonGammaMethod);
}
public void setPolygonSmooth(final double polygonSmooth) {
final Object oldValue = this.polygonSmooth;
this.polygonSmooth = polygonSmooth;
firePropertyChange("polygonSmooth", oldValue, this.polygonSmooth);
}
}