1
28 package demo.view.mindmap;
29
30 import y.view.BendList;
31 import y.view.EdgeRealizer;
32 import y.view.GenericEdgeRealizer;
33 import y.view.NodeRealizer;
34
35 import java.awt.Color;
36 import java.awt.Graphics2D;
37 import java.awt.geom.GeneralPath;
38 import java.awt.geom.PathIterator;
39
40
45 class GradientEdgePainter implements GenericEdgeRealizer.Painter {
46
47
55 public void paintSloppy(final EdgeRealizer context, final BendList bends, final GeneralPath path,
56 final Graphics2D gfx, final boolean selected) {
57 paintImpl(context, path, gfx, 2);
58 }
59
60
70 public void paint(final EdgeRealizer context, final BendList bends, final GeneralPath path, final Graphics2D gfx,
71 final boolean selected) {
72 paintImpl(context, path, gfx, 30);
73 }
74
75 private void paintImpl(final EdgeRealizer context, final GeneralPath path, final Graphics2D gfx, final int totalParts) {
76 final boolean isRoot = ViewModel.instance.isRoot(context.getSourceRealizer().getNode());
77
78 Color currentColor;
80 NodeRealizer nodeRealizer = context.getTargetRealizer();
81 final Color endColor = nodeRealizer.getFillColor();
82 final double endLineWidth = nodeRealizer.getLineType().getLineWidth();
83 double currentLineWidth;
84 if (!isRoot) {
85 nodeRealizer = context.getSourceRealizer();
86 currentColor = nodeRealizer.getFillColor();
87 currentLineWidth = nodeRealizer.getLineType().getLineWidth();
88 } else {
89 currentColor = endColor;
90 currentLineWidth = 15.0;
91 }
92
93 gfx.setColor(currentColor);
94
95 double dist = 0; double[] seg = new double[6];
98 int count = 0;
99 PathIterator pi = path.getPathIterator(null);
100 pi.currentSegment(seg);
101 pi.next();
102 for (; !pi.isDone(); pi.next()) {
103 final double oldX = seg[0];
104 final double oldY = seg[1];
105 pi.currentSegment(seg);
106 dist += calcDist(oldX,oldY,seg[0],seg[1]);
107 count++;
108 }
109 final double maxDist = dist / totalParts;
113 final int greenStep = (endColor.getGreen() - currentColor.getGreen()) / count;
115 final int redStep = (endColor.getRed() - currentColor.getRed()) / count;
116 final int blueStep = (endColor.getBlue() - currentColor.getBlue()) / count;
117 final double lineWidthStep = (currentLineWidth - endLineWidth) / count;
118 double angle = 0;
122 boolean first = true;
123 double[] start = new double[6];
124 double[] end = new double[2];
125 pi = path.getPathIterator(null);
126 pi.currentSegment(start);
127 pi.next();
128 final GeneralPath gp = new GeneralPath();
129 for (; !pi.isDone(); pi.next()) {
130 pi.currentSegment(seg);
132 double xdiff = seg[0] - start[0];
133 double ydiff = seg[1] - start[1];
134 dist = calcDist(seg[0],seg[1], start[0],start[1]);
135 double oldAngle = angle;
136 angle = Math.atan2(ydiff, xdiff);
137 double midAngle = (oldAngle+angle) / 2;
138 double xpos = (Math.sin(angle) * currentLineWidth * 0.5);
139 double ypos = (Math.cos(angle) * currentLineWidth * 0.5);
140 if (dist > maxDist) {
142 if (first && isRoot) {
146 gfx.setColor(currentColor);
147 end[0] = start[0] - (xdiff/dist) * currentLineWidth;
148 end[1] = start[1] - (ydiff/dist) * currentLineWidth;
149 gfx.fill(calcLineSegment(start, end, xpos, ypos, 0, 0, 0, gp));
150 }
151 final int parts = (int) Math.ceil(dist / maxDist) + 1;
153 xdiff /= parts;
155 ydiff /= parts;
156 if (!first) {
157 double midXPos = (Math.sin(midAngle) * currentLineWidth * 0.5);
159 double midYPos = (Math.cos(midAngle) * currentLineWidth * 0.5);
160 gfx.fill(calcLineSegment(start, start, midXPos, midYPos, xdiff, ydiff, 0.5, gp));
161 gfx.setColor(currentColor);
162 }
163 for (int i = 1; i <= parts; i++) {
164 gfx.fill(calcLineSegment(start, start, xpos, ypos, xdiff, ydiff, i, gp));
166 currentColor = getNewColor(currentColor, greenStep, redStep, blueStep, parts);
168 gfx.setColor(currentColor);
169 currentLineWidth = Math.max(currentLineWidth - (lineWidthStep / parts), endLineWidth);
170 xpos = (Math.sin(angle) * currentLineWidth * 0.5);
172 ypos = (Math.cos(angle) * currentLineWidth * 0.5);
173 }
174 } else {
175 gfx.setColor(currentColor);
176 if (!first) {
177 double midXPos = (Math.sin(midAngle) * currentLineWidth * 0.5);
179 double midYPos = (Math.cos(midAngle) * currentLineWidth * 0.5);
180 gfx.fill(calcLineSegment(start, start, midXPos, midYPos, xdiff, ydiff, 0.5, gp));
181 } else if (isRoot) {
182 end[0] = start[0] - (xdiff/dist) * currentLineWidth;
186 end[1] = start[1] - (ydiff/dist) * currentLineWidth;
187 gfx.fill(calcLineSegment(start, end, xpos, ypos, 0, 0, 0, gp));
188 }
189 gfx.fill(calcLineSegment(start, seg, xpos, ypos, 0, 0, 0, gp));
191 currentColor = getNewColor(currentColor, greenStep, redStep, blueStep, 1);
193 currentLineWidth = Math.max(currentLineWidth - lineWidthStep, endLineWidth);
194 }
195 start[0] = seg[0];
197 start[1] = seg[1];
198 first = false;
199 }
200 }
201
209 private double calcDist(final double x1,final double y1,final double x2,final double y2) {
210 final double dx = x1 - x2;
211 final double dy = y1 - y2;
212 return Math.sqrt(dx * dx + dy * dy);
213 }
214
215
227 private GeneralPath calcLineSegment(final double[] start, final double[] end, final double xpos, final double ypos,
228 final double xstep, final double ystep, final double i, final GeneralPath gp) {
229 gp.reset();
230 gp.moveTo((float) ((start[0] + (i - 1) * xstep) - xpos), (float) ((start[1] + (i - 1) * ystep) + ypos));
231 gp.lineTo((float) ((start[0] + (i - 1) * xstep) + xpos), (float) ((start[1] + (i - 1) * ystep) - ypos));
232 gp.lineTo((float) ((end[0] + (i + 0.5) * xstep) + xpos), (float) ((end[1] + (i + 0.5) * ystep) - ypos));
233 gp.lineTo((float) ((end[0] + (i + 0.5) * xstep) - xpos), (float) ((end[1] + (i + 0.5) * ystep) + ypos));
234 return gp;
235 }
236
237
246 private Color getNewColor(final Color startColor, final int greenStep, final int redStep, final int blueStep,
247 final int parts) {
248 return new Color(
249 Math.max(0, Math.min(255, startColor.getRed() + (redStep / parts))),
250 Math.max(0, Math.min(255, startColor.getGreen() + (greenStep / parts))),
251 Math.max(0, Math.min(255, startColor.getBlue() + (blueStep / parts))));
252 }
253 }
254