blob: bf75da8bbb67fd31bf2b5511aed97d4690a0a680 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 6296064 6521533
27 * @summary A simple manual test for visual verification of GradientPaint
28 * LinearGradientPaint, and RadialGradientPaint.
29 * @run main/manual MultiGradientTest
30 * @author campbelc
31 */
32
33import java.awt.BorderLayout;
34import java.awt.Color;
35import java.awt.Dimension;
36import java.awt.GradientPaint;
37import java.awt.Graphics;
38import java.awt.Graphics2D;
39import java.awt.LinearGradientPaint;
40import java.awt.MultipleGradientPaint.ColorSpaceType;
41import java.awt.MultipleGradientPaint.CycleMethod;
42import java.awt.Paint;
43import java.awt.Polygon;
44import java.awt.RadialGradientPaint;
45import java.awt.Rectangle;
46import java.awt.RenderingHints;
47import java.awt.geom.AffineTransform;
48import java.awt.geom.NoninvertibleTransformException;
49import java.awt.geom.Point2D;
50import java.awt.event.ActionEvent;
51import java.awt.event.ActionListener;
52import java.awt.event.MouseAdapter;
53import java.awt.event.MouseEvent;
54import java.awt.event.WindowAdapter;
55import java.awt.event.WindowEvent;
56import java.util.Arrays;
57import java.util.ArrayList;
58import java.util.EnumSet;
59import java.util.List;
60import javax.swing.AbstractListModel;
61import javax.swing.BoxLayout;
62import javax.swing.ComboBoxModel;
63import javax.swing.JCheckBox;
64import javax.swing.JComboBox;
65import javax.swing.JFrame;
66import javax.swing.JLabel;
67import javax.swing.JPanel;
68import javax.swing.JSpinner;
69import javax.swing.SpinnerNumberModel;
70import javax.swing.event.ChangeEvent;
71import javax.swing.event.ChangeListener;
72
73public class MultiGradientTest extends JPanel {
74
75 private static final Color[] COLORS = {
76 new Color(0, 0, 0),
77 new Color(128, 128, 128),
78 new Color(255, 0, 0),
79 new Color(255, 255, 0),
80 new Color(0, 255, 0),
81 new Color(0, 255, 255),
82 new Color(128, 0, 255),
83 new Color(128, 128, 128),
84 };
85
86 private static enum PaintType {BASIC, LINEAR, RADIAL};
87 private static enum ShapeType {RECT, ELLIPSE, MULTIPLE};
88 private static enum XformType {IDENTITY, TRANSLATE, SCALE, SHEAR, ROTATE};
89
90 private PaintType paintType = PaintType.LINEAR;
91 private ShapeType shapeType = ShapeType.RECT;
92 private XformType xformType = XformType.IDENTITY;
93 private CycleMethod cycleMethod = CycleMethod.NO_CYCLE;
94 private ColorSpaceType colorSpace = ColorSpaceType.SRGB;
95 private Object antialiasHint = RenderingHints.VALUE_ANTIALIAS_OFF;
96 private Object renderHint = RenderingHints.VALUE_RENDER_SPEED;
97 private AffineTransform transform = new AffineTransform();
98
99 private int numColors;
100
101 private GradientPanel gradientPanel;
102 private ControlsPanel controlsPanel;
103
104 private MultiGradientTest() {
105 numColors = COLORS.length;
106
107 setLayout(new BorderLayout());
108 gradientPanel = new GradientPanel();
109 add(gradientPanel, BorderLayout.CENTER);
110 controlsPanel = new ControlsPanel();
111 add(controlsPanel, BorderLayout.SOUTH);
112 }
113
114 private class GradientPanel extends JPanel {
115 private int startX, startY, endX, endY;
116 private int ctrX, ctrY, focusX, focusY;
117 private float radius;
118 private Paint paint;
119
120 private GradientPanel() {
121 startX = 20;
122 startY = 20;
123 endX = 100;
124 endY = 100;
125 ctrX = 100;
126 ctrY = 100;
127 focusX = 100;
128 focusY = 100;
129 radius = 100.0f;
130
131 makeNewPaint();
132
133 MouseAdapter l = new MyMouseAdapter();
134 addMouseListener(l);
135 addMouseMotionListener(l);
136 }
137
138 public void paintComponent(Graphics g) {
139 Graphics2D g2d = (Graphics2D)g.create();
140
141 int w = getWidth();
142 int h = getHeight();
143 g2d.setColor(Color.black);
144 g2d.fillRect(0, 0, w, h);
145
146 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
147 antialiasHint);
148 g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
149 renderHint);
150
151 g2d.transform(transform);
152 g2d.setPaint(paint);
153
154 switch (shapeType) {
155 default:
156 case RECT:
157 g2d.fillRect(0, 0, w, h);
158 break;
159
160 case ELLIPSE:
161 g2d.fillOval(0, 0, w, h);
162 break;
163
164 case MULTIPLE:
165 g2d.fillRect(0, 0, w/2, h/2);
166 g2d.fillOval(w/2, 0, w/2, h/2);
167 g2d.drawOval(0, h/2, w/2, h/2);
168 g2d.drawLine(0, h/2, w/2, h);
169 g2d.drawLine(0, h, w/2, h/2);
170 Polygon p = new Polygon();
171 p.addPoint(w/2, h);
172 p.addPoint(w, h);
173 p.addPoint(3*w/4, h/2);
174 g2d.fillPolygon(p);
175 break;
176 }
177
178 switch (paintType) {
179 default:
180 case BASIC:
181 case LINEAR:
182 g2d.setColor(Color.white);
183 g2d.fillRect(startX-1, startY-1, 2, 2);
184 g2d.drawString("1", startX, startY + 12);
185 g2d.fillRect(endX-1, endY-1, 2, 2);
186 g2d.drawString("2", endX, endY + 12);
187 break;
188
189 case RADIAL:
190 g2d.setColor(Color.white);
191 g2d.fillRect(ctrX-1, ctrY-1, 2, 2);
192 g2d.drawString("C", ctrX, ctrY + 12);
193 g2d.fillRect(focusX-1, focusY-1, 2, 2);
194 g2d.drawString("F", focusX, focusY + 12);
195 break;
196 }
197
198 g2d.dispose();
199 }
200
201 private void updatePoints(int x, int y) {
202 Point2D inv = new Point2D.Double(x, y);
203
204 try {
205 inv = transform.inverseTransform(inv, null);
206 } catch (NoninvertibleTransformException e) {
207 e.printStackTrace();
208 }
209
210 x = (int)inv.getX();
211 y = (int)inv.getY();
212
213 switch (paintType) {
214 default:
215 case BASIC:
216 case LINEAR:
217 // pick the closest point to move
218 if (inv.distance(startX, startY) < inv.distance(endX, endY)) {
219 startX = x;
220 startY = y;
221 } else {
222 endX = x;
223 endY = y;
224 }
225 break;
226
227 case RADIAL:
228 // pick the closest point to move
229 if (inv.distance(ctrX, ctrY) < inv.distance(focusX, focusY)) {
230 ctrX = x;
231 ctrY = y;
232 } else {
233 focusX = x;
234 focusY = y;
235 }
236 break;
237 }
238
239 updatePaint();
240 }
241
242 private void makeNewPaint() {
243 Color[] colors = Arrays.copyOf(COLORS, numColors);
244 float[] fractions = new float[colors.length];
245 for (int i = 0; i < fractions.length; i++) {
246 fractions[i] = ((float)i) / (fractions.length-1);
247 }
248
249 switch (paintType) {
250 case BASIC:
251 boolean cyclic = (cycleMethod != CycleMethod.NO_CYCLE);
252 paint = new GradientPaint(startX, startY, Color.RED,
253 endX, endY, Color.BLUE, cyclic);
254 break;
255
256 default:
257 case LINEAR:
258 paint =
259 new LinearGradientPaint(new Point2D.Float(startX, startY),
260 new Point2D.Float(endX, endY),
261 fractions, colors,
262 cycleMethod, colorSpace,
263 new AffineTransform());
264 break;
265
266 case RADIAL:
267 paint =
268 new RadialGradientPaint(new Point2D.Float(ctrX, ctrY),
269 radius,
270 new Point2D.Float(focusX, focusY),
271 fractions, colors,
272 cycleMethod, colorSpace,
273 new AffineTransform());
274 break;
275 }
276
277 switch (xformType) {
278 default:
279 case IDENTITY:
280 transform = new AffineTransform();
281 break;
282 case TRANSLATE:
283 transform = AffineTransform.getTranslateInstance(2, 2);
284 break;
285 case SCALE:
286 transform = AffineTransform.getScaleInstance(1.2, 1.4);
287 break;
288 case SHEAR:
289 transform = AffineTransform.getShearInstance(0.1, 0.1);
290 break;
291 case ROTATE:
292 transform = AffineTransform.getRotateInstance(Math.PI / 4,
293 getWidth()/2,
294 getHeight()/2);
295 break;
296 }
297 }
298
299 public void updatePaint() {
300 makeNewPaint();
301 repaint();
302 }
303
304 private class MyMouseAdapter extends MouseAdapter {
305 @Override
306 public void mouseClicked(MouseEvent e) {
307 updatePoints(e.getX(), e.getY());
308 }
309
310 @Override
311 public void mouseDragged(MouseEvent e) {
312 updatePoints(e.getX(), e.getY());
313 }
314 }
315
316 public Dimension getPreferredSize() {
317 return new Dimension(400, 400);
318 }
319 }
320
321 private class ControlsPanel extends JPanel implements ActionListener {
322 private JComboBox cmbPaint, cmbCycle, cmbSpace, cmbShape, cmbXform;
323 private JCheckBox cbAntialias, cbRender;
324 private JSpinner spinNumColors;
325
326 private ControlsPanel() {
327 cmbPaint = createCombo(this, paintType);
328 cmbPaint.setSelectedIndex(1);
329 cmbCycle = createCombo(this, cycleMethod);
330 cmbSpace = createCombo(this, colorSpace);
331 cmbShape = createCombo(this, shapeType);
332 cmbXform = createCombo(this, xformType);
333
334 int max = COLORS.length;
335 SpinnerNumberModel model = new SpinnerNumberModel(max, 2, max, 1);
336 spinNumColors = new JSpinner(model);
337 spinNumColors.addChangeListener(new ChangeListener() {
338 public void stateChanged(ChangeEvent e) {
339 numColors = ((Integer)spinNumColors.getValue()).intValue();
340 gradientPanel.updatePaint();
341 }
342 });
343 add(spinNumColors);
344
345 cbAntialias = createCheck(this, "Antialiasing");
346 cbRender = createCheck(this, "Render Quality");
347 }
348
349 private JComboBox createCombo(JPanel panel, Enum e) {
350 JComboBox cmb = new JComboBox();
351 cmb.setModel(new EnumComboBoxModel(e.getClass()));
352 cmb.addActionListener(this);
353 panel.add(cmb);
354 return cmb;
355 }
356
357 private JCheckBox createCheck(JPanel panel, String name) {
358 JCheckBox cb = new JCheckBox(name);
359 cb.addActionListener(this);
360 panel.add(cb);
361 return cb;
362 }
363
364 public void actionPerformed(ActionEvent e) {
365 Object source = e.getSource();
366
367 if (source == cmbPaint) {
368 paintType = (PaintType)cmbPaint.getSelectedItem();
369 } else if (source == cmbCycle) {
370 cycleMethod = (CycleMethod)cmbCycle.getSelectedItem();
371 } else if (source == cmbSpace) {
372 colorSpace = (ColorSpaceType)cmbSpace.getSelectedItem();
373 } else if (source == cmbShape) {
374 shapeType = (ShapeType)cmbShape.getSelectedItem();
375 } else if (source == cmbXform) {
376 xformType = (XformType)cmbXform.getSelectedItem();
377 } else if (source == cbAntialias) {
378 antialiasHint = cbAntialias.isSelected() ?
379 RenderingHints.VALUE_ANTIALIAS_ON :
380 RenderingHints.VALUE_ANTIALIAS_OFF;
381 } else if (source == cbRender) {
382 renderHint = cbRender.isSelected() ?
383 RenderingHints.VALUE_RENDER_QUALITY :
384 RenderingHints.VALUE_RENDER_SPEED;
385 }
386
387 gradientPanel.updatePaint();
388 }
389 }
390
391 private static class EnumComboBoxModel<E extends Enum<E>>
392 extends AbstractListModel
393 implements ComboBoxModel
394 {
395 private E selected = null;
396 private List<E> list;
397
398 public EnumComboBoxModel(Class<E> en) {
399 EnumSet<E> ens = EnumSet.allOf(en);
400 list = new ArrayList<E>(ens);
401 selected = list.get(0);
402 }
403
404 public int getSize() {
405 return list.size();
406 }
407
408 public E getElementAt(int index) {
409 return list.get(index);
410 }
411
412 public void setSelectedItem(Object anItem) {
413 selected = (E)anItem;
414 this.fireContentsChanged(this, 0, getSize());
415 }
416
417 public E getSelectedItem() {
418 return selected;
419 }
420 }
421
422 public static void main(String[] args) {
423 final JFrame frame = new JFrame("Multistop Gradient Demo");
424 frame.addWindowListener(new WindowAdapter() {
425 public void windowClosing(WindowEvent e) {
426 frame.dispose();
427 }
428 });
429 frame.add(new MultiGradientTest());
430 frame.pack();
431 frame.setLocationRelativeTo(null);
432 frame.setVisible(true);
433 }
434}