1 /* 2 * 3 * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * - Neither the name of Oracle nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package java2d.demos.Arcs_Curves; 33 34 35 import static java.awt.Color.BLUE; 36 import static java.awt.Color.GRAY; 37 import static java.awt.Color.GREEN; 38 import static java.awt.Color.RED; 39 import static java.awt.Color.WHITE; 40 import static java.awt.Color.YELLOW; 41 import java.awt.BasicStroke; 42 import java.awt.Color; 43 import java.awt.Component; 44 import java.awt.Dimension; 45 import java.awt.Font; 46 import java.awt.GradientPaint; 47 import java.awt.Graphics; 48 import java.awt.Graphics2D; 49 import java.awt.Paint; 50 import java.awt.Rectangle; 51 import java.awt.TexturePaint; 52 import java.awt.event.ActionEvent; 53 import java.awt.event.ActionListener; 54 import java.awt.geom.GeneralPath; 55 import java.awt.geom.Path2D; 56 import java.awt.image.BufferedImage; 57 import java2d.AnimatingControlsSurface; 58 import java2d.CustomControls; 59 import javax.swing.Icon; 60 import javax.swing.JMenu; 61 import javax.swing.JMenuBar; 62 import javax.swing.JMenuItem; 63 64 65 /** 66 * Animated Bezier Curve with controls for different draw & fill paints. 67 */ 68 @SuppressWarnings("serial") 69 public class BezierAnim extends AnimatingControlsSurface { 70 71 private static final int NUMPTS = 6; 72 protected BasicStroke solid = new BasicStroke(10.0f, 73 BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND); 74 protected BasicStroke dashed = new BasicStroke(10.0f, 75 BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 10, new float[] { 5 }, 76 0); 77 private float[] animpts = new float[NUMPTS * 2]; 78 private float[] deltas = new float[NUMPTS * 2]; 79 protected Paint fillPaint, drawPaint; 80 protected boolean doFill = true; 81 protected boolean doDraw = true; 82 protected GradientPaint gradient; 83 protected BasicStroke stroke; 84 85 public BezierAnim() { 86 setBackground(WHITE); 87 gradient = new GradientPaint(0, 0, RED, 200, 200, YELLOW); 88 fillPaint = gradient; 89 drawPaint = BLUE; 90 stroke = solid; 91 setControls(new Component[] { new DemoControls(this) }); 92 } 93 94 public void animate(float[] pts, float[] deltas, int index, int limit) { 95 float newpt = pts[index] + deltas[index]; 96 if (newpt <= 0) { 97 newpt = -newpt; 98 deltas[index] = (float) (Math.random() * 4.0 + 2.0); 99 } else if (newpt >= limit) { 100 newpt = 2.0f * limit - newpt; 101 deltas[index] = -(float) (Math.random() * 4.0 + 2.0); 102 } 103 pts[index] = newpt; 104 } 105 106 @Override 107 public void reset(int w, int h) { 108 for (int i = 0; i < animpts.length; i += 2) { 109 animpts[i + 0] = (float) (Math.random() * w); 110 animpts[i + 1] = (float) (Math.random() * h); 111 deltas[i + 0] = (float) (Math.random() * 6.0 + 4.0); 112 deltas[i + 1] = (float) (Math.random() * 6.0 + 4.0); 113 if (animpts[i + 0] > w / 2.0f) { 114 deltas[i + 0] = -deltas[i + 0]; 115 } 116 if (animpts[i + 1] > h / 2.0f) { 117 deltas[i + 1] = -deltas[i + 1]; 118 } 119 } 120 gradient = new GradientPaint(0, 0, RED, w * .7f, h * .7f, YELLOW); 121 } 122 123 @Override 124 public void step(int w, int h) { 125 for (int i = 0; i < animpts.length; i += 2) { 126 animate(animpts, deltas, i + 0, w); 127 animate(animpts, deltas, i + 1, h); 128 } 129 } 130 131 @Override 132 public void render(int w, int h, Graphics2D g2) { 133 float[] ctrlpts = animpts; 134 int len = ctrlpts.length; 135 float prevx = ctrlpts[len - 2]; 136 float prevy = ctrlpts[len - 1]; 137 float curx = ctrlpts[0]; 138 float cury = ctrlpts[1]; 139 float midx = (curx + prevx) / 2.0f; 140 float midy = (cury + prevy) / 2.0f; 141 GeneralPath gp = new GeneralPath(Path2D.WIND_NON_ZERO); 142 gp.moveTo(midx, midy); 143 for (int i = 2; i <= ctrlpts.length; i += 2) { 144 float x1 = (midx + curx) / 2.0f; 145 float y1 = (midy + cury) / 2.0f; 146 prevx = curx; 147 prevy = cury; 148 if (i < ctrlpts.length) { 149 curx = ctrlpts[i + 0]; 150 cury = ctrlpts[i + 1]; 151 } else { 152 curx = ctrlpts[0]; 153 cury = ctrlpts[1]; 154 } 155 midx = (curx + prevx) / 2.0f; 156 midy = (cury + prevy) / 2.0f; 157 float x2 = (prevx + midx) / 2.0f; 158 float y2 = (prevy + midy) / 2.0f; 159 gp.curveTo(x1, y1, x2, y2, midx, midy); 160 } 161 gp.closePath(); 162 if (doDraw) { 163 g2.setPaint(drawPaint); 164 g2.setStroke(stroke); 165 g2.draw(gp); 166 } 167 if (doFill) { 168 if (fillPaint instanceof GradientPaint) { 169 fillPaint = gradient; 170 } 171 g2.setPaint(fillPaint); 172 g2.fill(gp); 173 } 174 } 175 176 public static void main(String[] argv) { 177 createDemoFrame(new BezierAnim()); 178 } 179 180 181 static class DemoControls extends CustomControls implements ActionListener { 182 183 static final TexturePaint tp1, tp2; 184 185 static { 186 BufferedImage bi = new BufferedImage(2, 1, 187 BufferedImage.TYPE_INT_RGB); 188 bi.setRGB(0, 0, 0xff00ff00); 189 bi.setRGB(1, 0, 0xffff0000); 190 tp1 = new TexturePaint(bi, new Rectangle(0, 0, 2, 1)); 191 bi = new BufferedImage(2, 1, BufferedImage.TYPE_INT_RGB); 192 bi.setRGB(0, 0, 0xff0000ff); 193 bi.setRGB(1, 0, 0xffff0000); 194 tp2 = new TexturePaint(bi, new Rectangle(0, 0, 2, 1)); 195 } 196 BezierAnim demo; 197 static Paint[] drawPaints = { new Color(0, 0, 0, 0), BLUE, new Color(0, 198 0, 255, 126), 199 BLUE, tp2 }; 200 static String[] drawName = { "No Draw", "Blue", "Blue w/ Alpha", 201 "Blue Dash", "Texture" }; 202 static Paint[] fillPaints = { new Color(0, 0, 0, 0), GREEN, new Color(0, 203 255, 0, 126), 204 tp1, new GradientPaint(0, 0, RED, 30, 30, YELLOW) }; 205 String[] fillName = { "No Fill", "Green", "Green w/ Alpha", "Texture", 206 "Gradient" }; 207 JMenu fillMenu, drawMenu; 208 JMenuItem[] fillMI = new JMenuItem[fillPaints.length]; 209 JMenuItem[] drawMI = new JMenuItem[drawPaints.length]; 210 PaintedIcon[] fillIcons = new PaintedIcon[fillPaints.length]; 211 PaintedIcon[] drawIcons = new PaintedIcon[drawPaints.length]; 212 Font font = new Font(Font.SERIF, Font.PLAIN, 10); 213 214 @SuppressWarnings("LeakingThisInConstructor") 215 public DemoControls(BezierAnim demo) { 216 super(demo.name); 217 this.demo = demo; 218 219 JMenuBar drawMenuBar = new JMenuBar(); 220 add(drawMenuBar); 221 222 JMenuBar fillMenuBar = new JMenuBar(); 223 add(fillMenuBar); 224 225 drawMenu = drawMenuBar.add(new JMenu("Draw Choice")); 226 drawMenu.setFont(font); 227 228 for (int i = 0; i < drawPaints.length; i++) { 229 drawIcons[i] = new PaintedIcon(drawPaints[i]); 230 drawMI[i] = drawMenu.add(new JMenuItem(drawName[i])); 231 drawMI[i].setFont(font); 232 drawMI[i].setIcon(drawIcons[i]); 233 drawMI[i].addActionListener(this); 234 } 235 drawMenu.setIcon(drawIcons[1]); 236 237 fillMenu = fillMenuBar.add(new JMenu("Fill Choice")); 238 fillMenu.setFont(font); 239 for (int i = 0; i < fillPaints.length; i++) { 240 fillIcons[i] = new PaintedIcon(fillPaints[i]); 241 fillMI[i] = fillMenu.add(new JMenuItem(fillName[i])); 242 fillMI[i].setFont(font); 243 fillMI[i].setIcon(fillIcons[i]); 244 fillMI[i].addActionListener(this); 245 } 246 fillMenu.setIcon(fillIcons[fillPaints.length - 1]); 247 } 248 249 @Override 250 public void actionPerformed(ActionEvent e) { 251 Object obj = e.getSource(); 252 for (int i = 0; i < fillPaints.length; i++) { 253 if (obj.equals(fillMI[i])) { 254 demo.doFill = true; 255 demo.fillPaint = fillPaints[i]; 256 fillMenu.setIcon(fillIcons[i]); 257 break; 258 } 259 } 260 for (int i = 0; i < drawPaints.length; i++) { 261 if (obj.equals(drawMI[i])) { 262 demo.doDraw = true; 263 demo.drawPaint = drawPaints[i]; 264 if (((JMenuItem) obj).getText().endsWith("Dash")) { 265 demo.stroke = demo.dashed; 266 } else { 267 demo.stroke = demo.solid; 268 } 269 drawMenu.setIcon(drawIcons[i]); 270 break; 271 } 272 } 273 if (obj.equals(fillMI[0])) { 274 demo.doFill = false; 275 } else if (obj.equals(drawMI[0])) { 276 demo.doDraw = false; 277 } 278 if (!demo.animating.running()) { 279 demo.repaint(); 280 } 281 } 282 283 @Override 284 public Dimension getPreferredSize() { 285 return new Dimension(200, 36); 286 } 287 288 @Override 289 @SuppressWarnings("SleepWhileHoldingLock") 290 public void run() { 291 Thread me = Thread.currentThread(); 292 while (thread == me) { 293 for (JMenuItem dmi : drawMI) { 294 dmi.doClick(); 295 for (JMenuItem fmi : fillMI) { 296 fmi.doClick(); 297 try { 298 Thread.sleep(3000 + (long) (Math.random() * 3000)); 299 } catch (InterruptedException e) { 300 break; 301 } 302 } 303 } 304 } 305 thread = null; 306 } 307 308 309 static class PaintedIcon implements Icon { 310 311 Paint paint; 312 313 public PaintedIcon(Paint p) { 314 this.paint = p; 315 } 316 317 @Override 318 public void paintIcon(Component c, Graphics g, int x, int y) { 319 Graphics2D g2 = (Graphics2D) g; 320 g2.setPaint(paint); 321 g2.fillRect(x, y, getIconWidth(), getIconHeight()); 322 g2.setColor(GRAY); 323 g2.draw3DRect(x, y, getIconWidth() - 1, getIconHeight() - 1, 324 true); 325 } 326 327 @Override 328 public int getIconWidth() { 329 return 12; 330 } 331 332 @Override 333 public int getIconHeight() { 334 return 12; 335 } 336 } // End PaintedIcon class 337 } // End DemoControls class 338 } // End BezierAnim class 339