Source code: com/arranger/jarl/stroke/base/Precision.java
1 package com.arranger.jarl.stroke.base;
2
3 import com.arranger.jarl.base.IContext;
4 import com.arranger.jarl.base.IJarlObjectInfo;
5 import com.arranger.jarl.stroke.BaseSegmentStroke;
6 import com.arranger.jarl.util.*;
7 import com.arranger.jarl.widget.IWidget;
8 import org.w3c.dom.Element;
9
10 import java.awt.*;
11 import java.awt.geom.Point2D;
12 import java.util.ArrayList;
13
14 /**
15 * Precision will draw the shape with various preciseness.
16 * It can make rectangles our of circles for instance...
17 *
18 * @strokeAttribute start ## xs:string ## the starting precision should be between 0 & 100% for instance (50%)
19 * @strokeAttribute end ## xs:string ## the ending precision should be between 0 & 100% for instance (50%)
20 */
21 public class Precision extends BaseSegmentStroke {
22
23 protected double m_start = Double.NEGATIVE_INFINITY;
24 protected double m_end = Double.NEGATIVE_INFINITY;
25
26 /**
27 * This will perform custom drawing of the shape
28 * onto the graphics on behalf of the widget
29 *
30 * NB: this will need to interpolate points in between points
31 *
32 * @param widget
33 * @param context
34 * @param graphics2D
35 * @param shape
36 */
37 public Shape processShape(IWidget widget,
38 IContext context,
39 Graphics2D graphics2D,
40 Shape shape) {
41
42 Point2D[] points = WidgetUtil.getPoints(shape);
43 double numPoints = points.length / 2;
44 double startPrec;
45 double endPrec;
46 double currentPct;
47
48 //need to determine the starting and ending precision and what are current pct is between the two
49 if (m_start != Double.NEGATIVE_INFINITY && m_end != Double.NEGATIVE_INFINITY) {
50 startPrec = m_start;
51 endPrec = m_end;
52 currentPct = InterpolateUtil.interpolate(widget, context.getTime());
53 } else {
54 PrecisionConfigSegment precisionConfigSegment = (PrecisionConfigSegment) getCurrentSegment(widget, context);
55 currentPct = getCurrentSegmentTimePct(widget, context, precisionConfigSegment);
56 startPrec = precisionConfigSegment.getStart();
57 endPrec = precisionConfigSegment.getEnd();
58 }
59
60 //need to 'normalize' the start and end precision and then interpolate
61 double precision = InterpolateUtil.interpolate(
62 0,
63 1,
64 startPrec,
65 endPrec,
66 currentPct);
67
68 precision = (1 - precision) * numPoints;
69 if (precision <= 0) {
70 precision = 1;
71 }
72
73 //step through all the points skipping at 'precision' amount, generating a new array of points
74 boolean gotLastPoint = false;
75 java.util.List pointList = new ArrayList();
76 for (int index = 0; index < points.length - 1; index += precision) {
77 pointList.add(points[index]);
78 if (index == points.length - 1) {
79 gotLastPoint = true;
80 }
81 }
82
83 //get last point
84 if (!gotLastPoint) {
85 pointList.add(points[points.length - 1]);
86 }
87 points = new Point2D[pointList.size()];
88 points = (Point2D[]) pointList.toArray(points);
89
90 //generate a shape with those points
91 return WidgetUtil.pointsToShape(points, true);
92 }
93
94 /**
95 * Always remember some attrs might not be there
96 * @param context
97 */
98 protected void initAttributes(IContext context) {
99 super.initAttributes(context);
100
101 ObjectUtil.initializeField("start", m_configElement, this, ObjectUtil.NORMALIZING_CONVERSION);
102 ObjectUtil.initializeField("end", m_configElement, this, ObjectUtil.NORMALIZING_CONVERSION);
103 }
104
105 /**
106 * Override this, and for every field that you're using, call {@link #populateInfo}
107 * for example:
108 * <code>
109 * populateInfo(jarlObjectInfo, "zOrder", "Z-Order", JarlInfoUtil.PRIMITIVE_DISPLAY);
110 * </code>
111 *
112 * @param jarlObjectInfo
113 *
114 * @see JarlInfoUtil#PRIMITIVE_DISPLAY
115 * @see #populateInfo
116 * @see ObjectUtil#initializeField
117 */
118 protected void addJarlObjectInfo(IJarlObjectInfo jarlObjectInfo) {
119 super.addJarlObjectInfo(jarlObjectInfo);
120 populateInfo(jarlObjectInfo, "start", "Start", JarlInfoUtil.PCT_DISPLAY);
121 populateInfo(jarlObjectInfo, "end", "End", JarlInfoUtil.PCT_DISPLAY);
122 }
123
124 /**
125 * Create a concrete {@link WidgetConfigSegment} based on this element
126 * @param element
127 * @return a specific {@link WidgetConfigSegment}
128 */
129 public WidgetConfigSegment createSegment(Element element) {
130 return new PrecisionConfigSegment(element);
131 }
132
133 protected static class PrecisionConfigSegment extends WidgetConfigSegment {
134
135 protected double m_start;
136 protected double m_end;
137
138 public PrecisionConfigSegment(Element element) {
139 super(element);
140
141 ObjectUtil.initializeFieldStrict("start", element, this, ObjectUtil.NORMALIZING_CONVERSION);
142 ObjectUtil.initializeFieldStrict("end", element, this, ObjectUtil.NORMALIZING_CONVERSION);
143 }
144
145 protected void addJarlObjectInfo(IJarlObjectInfo jarlObjectInfo) {
146 super.addJarlObjectInfo(jarlObjectInfo);
147 populateInfo(jarlObjectInfo, "start", "Start", JarlInfoUtil.PCT_DISPLAY);
148 populateInfo(jarlObjectInfo, "end", "End", JarlInfoUtil.PCT_DISPLAY);
149 }
150
151 public double getStart() {
152 return m_start;
153 }
154
155 public double getEnd() {
156 return m_end;
157 }
158 }
159 }