001: /*
002: * GradientPicker.java
003: *
004: * Created on January 13, 2006, 3:17 PM
005: */
006:
007: package org.jdesktop.swingx;
008:
009: import java.awt.BorderLayout;
010: import java.awt.Color;
011: import java.awt.Component;
012: import java.awt.Dimension;
013: import java.awt.GridBagConstraints;
014: import java.awt.GridBagLayout;
015: import java.awt.GridLayout;
016: import java.awt.Insets;
017: import java.awt.Paint;
018: import java.awt.Toolkit;
019: import java.awt.event.ActionEvent;
020: import java.awt.event.ActionListener;
021: import java.awt.event.ItemEvent;
022: import java.awt.event.ItemListener;
023: import java.awt.event.MouseEvent;
024: import java.awt.geom.Point2D;
025: import java.beans.PropertyChangeEvent;
026: import java.beans.PropertyChangeListener;
027: import java.util.List;
028: import javax.swing.ActionMap;
029: import javax.swing.BorderFactory;
030: import javax.swing.BoxLayout;
031: import javax.swing.ButtonGroup;
032: import javax.swing.DefaultComboBoxModel;
033: import javax.swing.JButton;
034: import javax.swing.JCheckBox;
035: import javax.swing.JColorChooser;
036: import javax.swing.JComboBox;
037: import javax.swing.JDialog;
038: import javax.swing.JFrame;
039: import javax.swing.JLabel;
040: import javax.swing.JPanel;
041: import javax.swing.JRadioButton;
042: import javax.swing.JSlider;
043: import javax.swing.JSpinner;
044: import javax.swing.JTextField;
045: import javax.swing.SpinnerNumberModel;
046: import javax.swing.SwingConstants;
047: import javax.swing.SwingUtilities;
048: import javax.swing.UIManager;
049: import javax.swing.event.ChangeEvent;
050: import javax.swing.event.ChangeListener;
051: import org.apache.batik.ext.awt.LinearGradientPaint;
052: import org.apache.batik.ext.awt.MultipleGradientPaint;
053: import org.apache.batik.ext.awt.RadialGradientPaint;
054: import org.jdesktop.swingx.action.AbstractActionExt;
055: import org.jdesktop.swingx.color.*;
056: import org.jdesktop.swingx.multislider.Thumb;
057: import org.jdesktop.swingx.multislider.ThumbListener;
058: import org.jdesktop.swingx.painter.gradient.RadialGradientPainter;
059:
060: /**
061: * A specialized JXPanel that allows the user to construct and choose a Gradient.
062: * The returned values will be one of: GradientPaint, LinearGradientPaint, RadialGradientPaint.
063: *
064: * @author jm158417
065: */
066: public class JXGradientChooser extends JXPanel {
067: public enum GradientStyle {
068: Linear, Radial
069: };
070:
071: /**
072: * The multi-thumb slider to use for the gradient stops
073: */
074: private JXMultiThumbSlider<Color> slider;
075: public JButton deleteThumbButton;
076: public JButton addThumbButton;
077:
078: public JTextField colorField;
079: public JXColorSelectionButton changeColorButton;
080: public JSpinner colorLocationSpinner;
081: public JSpinner alphaSpinner;
082: public JSlider alphaSlider;
083:
084: public JComboBox styleCombo;
085: public GradientPreviewPanel gradientPreview;
086:
087: public JRadioButton noCycleRadio;
088: public JRadioButton reflectedRadio;
089: public JRadioButton repeatedRadio;
090: public JCheckBox reversedCheck;
091:
092: Paint checker_texture = null;
093:
094: /** Creates new form GradientPicker */
095: public JXGradientChooser() {
096: initComponents2();
097: }
098:
099: public MultipleGradientPaint getGradient() {
100: return gradientPreview.getGradient();
101: }
102:
103: public MultipleGradientPaint getFlatGradient() {
104: // get the list of colors
105: List<Thumb<Color>> stops = slider.getModel().getSortedThumbs();
106: int len = stops.size();
107:
108: // set up the data for the gradient
109: float[] fractions = new float[len];
110: Color[] colors = new Color[len];
111: int i = 0;
112: for (Thumb<Color> thumb : stops) {
113: colors[i] = (Color) thumb.getObject();
114: fractions[i] = thumb.getPosition();
115: i++;
116: }
117: // fill in the gradient
118: Point2D start = new Point2D.Float(0, 0);
119: Point2D end = new Point2D.Float(getWidth(), 0);
120: MultipleGradientPaint paint = new org.apache.batik.ext.awt.LinearGradientPaint(
121: (float) start.getX(), (float) start.getY(), (float) end
122: .getX(), (float) end.getY(), fractions, colors);
123: return paint;
124: }
125:
126: public void setGradient(MultipleGradientPaint mgrad) {
127: // removing all thumbs;
128: while (slider.getModel().getThumbCount() > 0) {
129: slider.getModel().removeThumb(0);
130: }
131: float[] fracts = mgrad.getFractions();
132: Color[] colors = mgrad.getColors();
133: for (int i = 0; i < fracts.length; i++) {
134: slider.getModel().addThumb(fracts[i], colors[i]);
135: }
136:
137: if (mgrad instanceof RadialGradientPaint) {
138: styleCombo.setSelectedItem(GradientStyle.Radial);
139: gradientPreview.setGradient(mgrad);
140: } else {
141: styleCombo.setSelectedItem(GradientStyle.Linear);
142: gradientPreview.setGradient(mgrad);
143: }
144:
145: repaint();
146: }
147:
148: private void updateFromStop(Thumb<Color> thumb) {
149: if (thumb == null) {
150: updateFromStop(-1, -1, Color.black);
151: } else {
152: updateFromStop(1, thumb.getPosition(), thumb.getObject());
153: }
154: }
155:
156: private void updateFromStop(int thumb, float position, Color color) {
157: if (thumb == -1) {
158: colorLocationSpinner.setEnabled(false);
159: alphaSpinner.setEnabled(false);
160: alphaSlider.setEnabled(false);
161: colorField.setEnabled(false);
162: changeColorButton.setEnabled(false);
163: changeColorButton.setBackground(Color.black);
164: deleteThumbButton.setEnabled(false);
165: } else {
166: colorLocationSpinner.setEnabled(true);
167: alphaSpinner.setEnabled(true);
168: alphaSlider.setEnabled(true);
169: colorField.setEnabled(true);
170: changeColorButton.setEnabled(true);
171: colorLocationSpinner.setValue((int) (100 * position));
172: colorField.setText(Integer.toHexString(color.getRGB())
173: .substring(2));
174: alphaSpinner.setValue((int) (color.getAlpha() * 100 / 255));
175: alphaSlider.setValue(color.getAlpha() * 100 / 255);
176: changeColorButton.setBackground(color);
177: deleteThumbButton.setEnabled(true);
178: }
179: updateDeleteButtons();
180: ((GradientPreviewPanel) gradientPreview).repaint();
181: }
182:
183: private void updateDeleteButtons() {
184: if (slider.getModel().getThumbCount() <= 2) {
185: deleteThumbButton.setEnabled(false);
186: }
187: }
188:
189: public JXMultiThumbSlider<Color> getSlider() {
190: return slider;
191: }
192:
193: private void updateGradientProperty() {
194: firePropertyChange("gradient", null, getGradient());
195: gradientPreview.repaint();
196: }
197:
198: /** This method is called from within the constructor to
199: * initialize the form.
200: */
201:
202: private JPanel topPanel, previewPanel;
203:
204: private void initComponents() {
205: // declarations for anonymous components
206: JPanel jPanel1, jPanel2, jPanel3, jPanel4;
207: JLabel jLabel1, jLabel5, jLabel2, jLabel6, jLabel4, jLabel7, jLabel8, jLabel9;
208: ButtonGroup typeGroup;
209: // pre-init stuff
210: slider = new JXMultiThumbSlider<Color>();
211: gradientPreview = new GradientPreviewPanel();
212:
213: java.awt.GridBagConstraints gridBagConstraints;
214:
215: typeGroup = new javax.swing.ButtonGroup();
216: jPanel1 = new javax.swing.JPanel();
217: topPanel = new javax.swing.JPanel();
218: jPanel2 = new javax.swing.JPanel();
219: jLabel1 = new javax.swing.JLabel();
220: jLabel5 = new javax.swing.JLabel();
221: colorField = new javax.swing.JTextField();
222: jLabel2 = new javax.swing.JLabel();
223: jLabel6 = new javax.swing.JLabel();
224: colorLocationSpinner = new javax.swing.JSpinner();
225: jLabel4 = new javax.swing.JLabel();
226: jLabel7 = new javax.swing.JLabel();
227: alphaSpinner = new javax.swing.JSpinner();
228: changeColorButton = new JXColorSelectionButton();
229: alphaSlider = new javax.swing.JSlider();
230: //slider = new javax.swing.JSlider();
231: jPanel4 = new javax.swing.JPanel();
232: addThumbButton = new javax.swing.JButton();
233: deleteThumbButton = new javax.swing.JButton();
234: previewPanel = new javax.swing.JPanel();
235: jPanel3 = new javax.swing.JPanel();
236: jLabel8 = new javax.swing.JLabel();
237: styleCombo = new javax.swing.JComboBox();
238: jLabel9 = new javax.swing.JLabel();
239: noCycleRadio = new javax.swing.JRadioButton();
240: reflectedRadio = new javax.swing.JRadioButton();
241: repeatedRadio = new javax.swing.JRadioButton();
242: reversedCheck = new javax.swing.JCheckBox();
243: //gradientPreview = new javax.swing.JPanel();
244:
245: //setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
246: jPanel1.setLayout(new java.awt.GridBagLayout());
247:
248: topPanel.setLayout(new java.awt.GridBagLayout());
249:
250: topPanel.setBorder(javax.swing.BorderFactory
251: .createTitledBorder("Gradient"));
252: jPanel2.setLayout(new java.awt.GridBagLayout());
253:
254: jLabel1.setText("Color:");
255: gridBagConstraints = new java.awt.GridBagConstraints();
256: gridBagConstraints.gridx = 0;
257: gridBagConstraints.gridy = 0;
258: gridBagConstraints.ipadx = 2;
259: gridBagConstraints.ipady = 2;
260: gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
261: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
262: jPanel2.add(jLabel1, gridBagConstraints);
263:
264: jLabel5.setText("#");
265: gridBagConstraints = new java.awt.GridBagConstraints();
266: gridBagConstraints.gridx = 1;
267: gridBagConstraints.gridy = 0;
268: gridBagConstraints.insets = new java.awt.Insets(4, 0, 4, 4);
269: jPanel2.add(jLabel5, gridBagConstraints);
270:
271: colorField.setColumns(6);
272: colorField.setEnabled(false);
273: colorField.setPreferredSize(null);
274: gridBagConstraints = new java.awt.GridBagConstraints();
275: gridBagConstraints.gridy = 0;
276: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
277: jPanel2.add(colorField, gridBagConstraints);
278:
279: jLabel2.setText("Location:");
280: gridBagConstraints = new java.awt.GridBagConstraints();
281: gridBagConstraints.gridy = 1;
282: gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
283: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
284: jPanel2.add(jLabel2, gridBagConstraints);
285:
286: jLabel6.setText("%");
287: gridBagConstraints = new java.awt.GridBagConstraints();
288: gridBagConstraints.gridy = 1;
289: jPanel2.add(jLabel6, gridBagConstraints);
290:
291: colorLocationSpinner.setEnabled(false);
292: colorLocationSpinner.setPreferredSize(null);
293: gridBagConstraints = new java.awt.GridBagConstraints();
294: gridBagConstraints.gridy = 1;
295: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
296: jPanel2.add(colorLocationSpinner, gridBagConstraints);
297:
298: jLabel4.setText("Opacity:");
299: gridBagConstraints = new java.awt.GridBagConstraints();
300: gridBagConstraints.gridy = 2;
301: gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
302: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
303: jPanel2.add(jLabel4, gridBagConstraints);
304:
305: jLabel7.setText("%");
306: gridBagConstraints = new java.awt.GridBagConstraints();
307: gridBagConstraints.gridy = 2;
308: jPanel2.add(jLabel7, gridBagConstraints);
309:
310: alphaSpinner.setEnabled(false);
311: alphaSpinner.setPreferredSize(null);
312: gridBagConstraints = new java.awt.GridBagConstraints();
313: gridBagConstraints.gridy = 2;
314: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
315: jPanel2.add(alphaSpinner, gridBagConstraints);
316:
317: changeColorButton.setText("00");
318: changeColorButton.setEnabled(false);
319: gridBagConstraints = new java.awt.GridBagConstraints();
320: gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
321: gridBagConstraints.weightx = 1.0;
322: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
323: gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
324: jPanel2.add(changeColorButton, gridBagConstraints);
325:
326: alphaSlider.setEnabled(false);
327: alphaSlider.setPreferredSize(new java.awt.Dimension(20, 25));
328: gridBagConstraints = new java.awt.GridBagConstraints();
329: gridBagConstraints.gridy = 2;
330: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
331: gridBagConstraints.weightx = 1.0;
332: jPanel2.add(alphaSlider, gridBagConstraints);
333:
334: gridBagConstraints = new java.awt.GridBagConstraints();
335: gridBagConstraints.gridx = 0;
336: gridBagConstraints.gridy = 2;
337: gridBagConstraints.gridwidth = 2;
338: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
339: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
340: gridBagConstraints.weightx = 1.0;
341: gridBagConstraints.weighty = 1.0;
342: gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
343: topPanel.add(jPanel2, gridBagConstraints);
344:
345: gridBagConstraints = new java.awt.GridBagConstraints();
346: gridBagConstraints.gridy = 0;
347: gridBagConstraints.gridwidth = 2;
348: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
349: topPanel.add(slider, gridBagConstraints);
350:
351: jPanel4.setLayout(new java.awt.GridLayout(1, 0, 2, 0));
352:
353: addThumbButton.setText("Add");
354: jPanel4.add(addThumbButton);
355:
356: deleteThumbButton.setText("Delete");
357: jPanel4.add(deleteThumbButton);
358:
359: gridBagConstraints = new java.awt.GridBagConstraints();
360: gridBagConstraints.gridy = 1;
361: gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
362: gridBagConstraints.weightx = 1.0;
363: gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
364: topPanel.add(jPanel4, gridBagConstraints);
365:
366: gridBagConstraints = new java.awt.GridBagConstraints();
367: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
368: gridBagConstraints.weightx = 1.0;
369: jPanel1.add(topPanel, gridBagConstraints);
370:
371: previewPanel.setLayout(new java.awt.GridBagLayout());
372:
373: previewPanel.setBorder(javax.swing.BorderFactory
374: .createTitledBorder("Preview"));
375: jPanel3.setLayout(new java.awt.GridBagLayout());
376:
377: jLabel8.setText("Style:");
378: gridBagConstraints = new java.awt.GridBagConstraints();
379: gridBagConstraints.gridy = 0;
380: gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
381: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
382: jPanel3.add(jLabel8, gridBagConstraints);
383:
384: styleCombo.setModel(new javax.swing.DefaultComboBoxModel(
385: new String[] { "Linear", "Radial" }));
386: gridBagConstraints = new java.awt.GridBagConstraints();
387: gridBagConstraints.gridy = 0;
388: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
389: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
390: jPanel3.add(styleCombo, gridBagConstraints);
391:
392: jLabel9.setText("Type:");
393: gridBagConstraints = new java.awt.GridBagConstraints();
394: gridBagConstraints.gridy = 1;
395: gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
396: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
397: jPanel3.add(jLabel9, gridBagConstraints);
398:
399: typeGroup.add(noCycleRadio);
400: noCycleRadio.setSelected(true);
401: noCycleRadio.setText("None");
402: noCycleRadio.setBorder(javax.swing.BorderFactory
403: .createEmptyBorder(0, 0, 0, 0));
404: noCycleRadio.setMargin(new java.awt.Insets(0, 0, 0, 0));
405: gridBagConstraints = new java.awt.GridBagConstraints();
406: gridBagConstraints.gridy = 1;
407: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
408: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
409: jPanel3.add(noCycleRadio, gridBagConstraints);
410:
411: typeGroup.add(reflectedRadio);
412: reflectedRadio.setText("Reflect");
413: reflectedRadio.setBorder(javax.swing.BorderFactory
414: .createEmptyBorder(0, 0, 0, 0));
415: reflectedRadio.setMargin(new java.awt.Insets(0, 0, 0, 0));
416: gridBagConstraints = new java.awt.GridBagConstraints();
417: gridBagConstraints.gridx = 1;
418: gridBagConstraints.gridy = 2;
419: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
420: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
421: jPanel3.add(reflectedRadio, gridBagConstraints);
422:
423: typeGroup.add(repeatedRadio);
424: repeatedRadio.setText("Repeat");
425: repeatedRadio.setBorder(javax.swing.BorderFactory
426: .createEmptyBorder(0, 0, 0, 0));
427: repeatedRadio.setMargin(new java.awt.Insets(0, 0, 0, 0));
428: gridBagConstraints = new java.awt.GridBagConstraints();
429: gridBagConstraints.gridx = 1;
430: gridBagConstraints.gridy = 3;
431: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
432: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
433: jPanel3.add(repeatedRadio, gridBagConstraints);
434:
435: reversedCheck.setText("Reverse");
436: reversedCheck.setBorder(javax.swing.BorderFactory
437: .createEmptyBorder(0, 0, 0, 0));
438: reversedCheck.setMargin(new java.awt.Insets(0, 0, 0, 0));
439: gridBagConstraints = new java.awt.GridBagConstraints();
440: gridBagConstraints.gridx = 1;
441: gridBagConstraints.gridy = 4;
442: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
443: gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
444: jPanel3.add(reversedCheck, gridBagConstraints);
445:
446: gridBagConstraints = new java.awt.GridBagConstraints();
447: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
448: previewPanel.add(jPanel3, gridBagConstraints);
449:
450: gradientPreview.setBorder(javax.swing.BorderFactory
451: .createEtchedBorder());
452: gradientPreview.setPreferredSize(new java.awt.Dimension(130,
453: 130));
454: /*
455: org.jdesktop.layout.GroupLayout gradientPreviewLayout = new org.jdesktop.layout.GroupLayout(gradientPreview);
456: gradientPreview.setLayout(gradientPreviewLayout);
457: gradientPreviewLayout.setHorizontalGroup(
458: gradientPreviewLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
459: .add(0, 132, Short.MAX_VALUE)
460: );
461: gradientPreviewLayout.setVerticalGroup(
462: gradientPreviewLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
463: .add(0, 118, Short.MAX_VALUE)
464: );
465: */
466: gridBagConstraints = new java.awt.GridBagConstraints();
467: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
468: gridBagConstraints.weightx = 10.0;
469: gridBagConstraints.weighty = 10.0;
470: previewPanel.add(gradientPreview, gridBagConstraints);
471:
472: gridBagConstraints = new java.awt.GridBagConstraints();
473: gridBagConstraints.gridy = 1;
474: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
475: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
476: gridBagConstraints.weightx = 1.0;
477: gridBagConstraints.weighty = 1.0;
478: jPanel1.add(previewPanel, gridBagConstraints);
479:
480: /*
481: org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
482: getContentPane().setLayout(layout);
483: layout.setHorizontalGroup(
484: layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
485: .add(layout.createSequentialGroup()
486: .addContainerGap()
487: .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 253, Short.MAX_VALUE)
488: .addContainerGap())
489: );
490: layout.setVerticalGroup(
491: layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
492: .add(layout.createSequentialGroup()
493: .addContainerGap()
494: .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 321, Short.MAX_VALUE)
495: .addContainerGap())
496: );
497: pack();
498: */
499: }// </editor-fold>
500:
501: private void initComponents2() {
502: this .initComponents();
503: setLayout(new BorderLayout());
504: add(topPanel, BorderLayout.NORTH);
505: add(previewPanel, BorderLayout.CENTER);
506:
507: // do event handling stuff
508: //create the actions and load them in the action map
509: AddThumbAction addThumbAction = new AddThumbAction();
510: DeleteThumbAction deleteThumbAction = new DeleteThumbAction();
511: deleteThumbAction.setEnabled(false); //disabled to begin with
512: //TODO Add to the action map with proper keys, etc
513: ActionMap actions = getActionMap();
514: actions.put("add-thumb", addThumbAction);
515: actions.put("delete-thumb", deleteThumbAction);
516: //actions.put("change-color", changeColorAction);
517: addThumbButton.setAction(addThumbAction);
518: deleteThumbButton.setAction(deleteThumbAction);
519: changeColorButton.addPropertyChangeListener("background",
520: new PropertyChangeListener() {
521: public void propertyChange(PropertyChangeEvent evt) {
522: selectColorForThumb();
523: updateGradientProperty();
524: }
525: });
526: colorLocationSpinner
527: .addChangeListener(new ChangeLocationListener());
528: ChangeAlphaListener changeAlphaListener = new ChangeAlphaListener();
529: alphaSpinner.addChangeListener(changeAlphaListener);
530: alphaSlider.addChangeListener(changeAlphaListener);
531: RepaintOnEventListener repaintListener = new RepaintOnEventListener();
532: styleCombo.addItemListener(repaintListener);
533: styleCombo.setModel(new DefaultComboBoxModel(GradientStyle
534: .values()));
535: noCycleRadio.addActionListener(repaintListener);
536: reflectedRadio.addActionListener(repaintListener);
537: repeatedRadio.addActionListener(repaintListener);
538: reversedCheck.addActionListener(repaintListener);
539: gradientPreview.picker = this ; //wow, nasty
540:
541: /*
542: //configure the panel
543: JXPanel topPanel = new JXPanel(new GridBagLayout());
544: topPanel.setBorder(BorderFactory.createTitledBorder("Gradient"));
545:
546: ///////////////// Build and Configure the slider panel/////////////////
547: JXPanel sliderPanel = new JXPanel(new GridBagLayout());
548: slider = new JXMultiThumbSlider<Color>();
549: addThumbButton = new JButton(addThumbAction);
550: deleteThumbButton = new JButton(deleteThumbAction);
551:
552: Insets stdInsets = new Insets(3,3,3,3);
553: sliderPanel.add(slider, new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 5, 0), 0, 0));
554: sliderPanel.add(addThumbButton, new GridBagConstraints(0, 1, 1, 1, .5, 0.0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(0, 0, 0, 3), 0, 0));
555: sliderPanel.add(deleteThumbButton, new GridBagConstraints(1, 1, 1, 1, .5, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 3, 0, 0), 0, 0));
556:
557: topPanel.add(sliderPanel, new GridBagConstraints(0, 0, 3, 1, 1.0, 1.0, GridBagConstraints.PAGE_START, GridBagConstraints.HORIZONTAL, new Insets(7, 7, 12, 7), 0, 0));
558: ///////////////////////////////////////////////////////////////////////
559:
560: //////////////// Build and Configure the top panel ////////////////////
561: JLabel label = new JLabel("Color: #");
562: label.setHorizontalAlignment(SwingConstants.TRAILING);
563: colorField = new JTextField();
564: colorField.setText("000");
565: colorField.setEnabled(false);
566: label.setLabelFor(colorField);
567: changeColorButton = new JXColorSelectionButton();
568: changeColorButton.setText("");
569: changeColorButton.addPropertyChangeListener("background", new PropertyChangeListener() {
570: public void propertyChange(PropertyChangeEvent evt) {
571: System.out.println("color bg changed");
572: selectColorForThumb();
573: }
574: });
575: topPanel.add(label, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0));
576: topPanel.add(colorField, new GridBagConstraints(1, 1, 1, 1, .5, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
577: topPanel.add(changeColorButton, new GridBagConstraints(2, 1, 1, 1, .5, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
578:
579: label = new JLabel("Location: %");
580: label.setHorizontalAlignment(SwingConstants.TRAILING);
581: colorLocationSpinner = new JSpinner();
582: colorLocationSpinner.setEnabled(false);
583: colorLocationSpinner.addChangeListener(new ChangeLocationListener());
584: label.setLabelFor(colorLocationSpinner);
585: topPanel.add(label, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
586: topPanel.add(colorLocationSpinner, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
587:
588: ChangeAlphaListener changeAlphaListener = new ChangeAlphaListener();
589: label = new JLabel("Opacity: %");
590: label.setHorizontalAlignment(SwingConstants.TRAILING);
591: alphaSpinner = new JSpinner();
592: alphaSpinner.setEnabled(false);
593: ChangeAlphaListener changeAlphaListener = new ChangeAlphaListener();
594: alphaSpinner.addChangeListener(changeAlphaListener);
595: label.setLabelFor(alphaSpinner);
596: alphaSlider = new JSlider();
597: alphaSlider.setEnabled(false);
598: alphaSlider.addChangeListener(changeAlphaListener);
599: topPanel.add(label, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
600: topPanel.add(alphaSpinner, new GridBagConstraints(1, 3, 1, 1, .5, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
601: topPanel.add(alphaSlider, new GridBagConstraints(2, 3, 1, 1, .5, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
602:
603: add(topPanel, BorderLayout.NORTH);
604: /////////////////////////////////////////////////////////////////////
605:
606:
607: JXPanel previewPanel = new JXPanel(new GridBagLayout());
608: previewPanel.setBorder(BorderFactory.createTitledBorder("Preview"));
609:
610: label = new JLabel("Style:");
611: styleCombo = new JComboBox();
612: RepaintOnEventListener repaintListener = new RepaintOnEventListener();
613: styleCombo.addItemListener(repaintListener);
614: styleCombo.setModel(new DefaultComboBoxModel(GradientStyle.values()));
615: label.setLabelFor(styleCombo);
616: previewPanel.add(label, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
617: previewPanel.add(styleCombo, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
618:
619: label = new JLabel("Type");
620: previewPanel.add(label, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
621:
622: ButtonGroup typeGroup = new ButtonGroup();
623: noCycleRadio = new JRadioButton("None");
624: noCycleRadio.setSelected(true);
625: noCycleRadio.addActionListener(repaintListener);
626: typeGroup.add(noCycleRadio);
627: previewPanel.add(noCycleRadio, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
628:
629: reflectedRadio = new JRadioButton("Reflect");
630: reflectedRadio.addActionListener(repaintListener);
631: typeGroup.add(reflectedRadio);
632: previewPanel.add(reflectedRadio, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
633:
634: repeatedRadio = new JRadioButton("Repeat");
635: repeatedRadio.addActionListener(repaintListener);
636: typeGroup.add(repeatedRadio);
637: previewPanel.add(repeatedRadio, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
638:
639: reversedCheck = new JCheckBox("Reverse");
640: reversedCheck.addActionListener(repaintListener);
641: previewPanel.add(reversedCheck, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.FIRST_LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
642:
643: gradientPreview = new GradientPreviewPanel();
644: gradientPreview.picker = this; //wow, nasty
645: previewPanel.add(gradientPreview, new GridBagConstraints(2, 0, 1, 5, 1.0, 1.0, GridBagConstraints.FIRST_LINE_START, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
646:
647: add(previewPanel);
648: */
649:
650: ///To still refactor below::
651: SpinnerNumberModel alpha_model = new SpinnerNumberModel(100, 0,
652: 100, 1);
653: alphaSpinner.setModel(alpha_model);
654: SpinnerNumberModel location_model = new SpinnerNumberModel(100,
655: 0, 100, 1);
656: colorLocationSpinner.setModel(location_model);
657:
658: checker_texture = ColorUtil.getCheckerPaint();
659:
660: slider.setOpaque(false);
661: slider.setPreferredSize(new Dimension(100, 35));
662: slider.getModel().setMinimumValue(0f);
663: slider.getModel().setMaximumValue(1.0f);
664:
665: slider.getModel().addThumb(0, Color.black);
666: slider.getModel().addThumb(0.5f, Color.red);
667: slider.getModel().addThumb(1.0f, Color.white);
668:
669: slider
670: .setThumbRenderer(new GradientThumbRenderer(this ,
671: slider));
672: slider.setTrackRenderer(new GradientTrackRenderer(this ));
673: slider.addMultiThumbListener(new StopListener(slider));
674: //// gradient_selector.add(slider, "Center");
675:
676: gradientPreview.addPropertyChangeListener("gradient",
677: new PropertyChangeListener() {
678: public void propertyChange(
679: PropertyChangeEvent propertyChangeEvent) {
680: updateGradientProperty();
681: }
682: });
683:
684: }
685:
686: private final class ChangeLocationListener implements
687: ChangeListener {
688: public void stateChanged(ChangeEvent evt) {
689: if (slider.getSelectedIndex() >= 0) {
690: Thumb thumb = slider.getModel().getThumbAt(
691: slider.getSelectedIndex());
692: thumb
693: .setPosition((float) ((Integer) colorLocationSpinner
694: .getValue()) / 100);
695: slider.repaint();
696: updateFromStop(thumb);
697: updateGradientProperty();
698: }
699: }
700: }
701:
702: private final class ChangeAlphaListener implements ChangeListener {
703: public void stateChanged(ChangeEvent changeEvent) {
704: if (slider.getSelectedIndex() >= 0) {
705: Thumb<Color> thumb = slider.getModel().getThumbAt(
706: slider.getSelectedIndex());
707: int alpha = changeEvent.getSource() == alphaSpinner ? (Integer) alphaSpinner
708: .getValue()
709: : alphaSlider.getValue();
710:
711: Color col = (Color) thumb.getObject();
712: col = ColorUtil.setAlpha(col, alpha * 255 / 100);
713: thumb.setObject(col);
714:
715: if (changeEvent.getSource() == alphaSpinner) {
716: alphaSlider.setValue(alpha);
717: } else {
718: alphaSpinner.setValue(alpha);
719: }
720: slider.repaint();
721: updateGradientProperty();
722: }
723: }
724: }
725:
726: private final class AddThumbAction extends AbstractActionExt {
727: public AddThumbAction() {
728: super ("Add");
729: }
730:
731: public void actionPerformed(ActionEvent actionEvent) {
732: float pos = 0.2f;
733: Color color = Color.black;
734: for (int i = 0; i < slider.getModel().getThumbCount(); i++) {
735: float pos2 = slider.getModel().getThumbAt(i)
736: .getPosition();
737: if (pos2 < pos) {
738: continue;
739: }
740: slider.getModel().insertThumb(pos, color, i);
741: updateFromStop(i, pos, color);
742: break;
743: }
744:
745: }
746: }
747:
748: private final class DeleteThumbAction extends AbstractActionExt {
749: public DeleteThumbAction() {
750: super ("Delete");
751: }
752:
753: public void actionPerformed(ActionEvent actionEvent) {
754: int index = slider.getSelectedIndex();
755: if (index >= 0) {
756: slider.getModel().removeThumb(index);
757: updateFromStop(-1, -1, null);
758: }
759: }
760: }
761:
762: private class StopListener implements ThumbListener {
763:
764: private JXMultiThumbSlider slider;
765:
766: public StopListener(JXMultiThumbSlider slider) {
767: super ();
768: this .slider = slider;
769: }
770:
771: public void thumbMoved(int thumb, float pos) {
772: Color color = (Color) slider.getModel().getThumbAt(thumb)
773: .getObject();
774: updateFromStop(thumb, pos, color);
775: updateDeleteButtons();
776: }
777:
778: public void thumbSelected(int thumb) {
779: if (thumb == -1) {
780: updateFromStop(-1, -1, Color.black);
781: return;
782: }
783: float pos = slider.getModel().getThumbAt(thumb)
784: .getPosition();
785: Color color = (Color) slider.getModel().getThumbAt(thumb)
786: .getObject();
787: updateFromStop(thumb, pos, color);
788: updateDeleteButtons();
789: }
790:
791: public void mousePressed(MouseEvent e) {
792: if (e.getClickCount() > 1) {
793: selectColorForThumb();
794: }
795: }
796: }
797:
798: private final class RepaintOnEventListener implements
799: ActionListener, ItemListener {
800: public void actionPerformed(ActionEvent e) {
801: updateGradientProperty();
802: }
803:
804: public void itemStateChanged(ItemEvent e) {
805: updateGradientProperty();
806: }
807: }
808:
809: private void selectColorForThumb() {
810: int index = slider.getSelectedIndex();
811: if (index >= 0) {
812: Color color = (Color) slider.getModel().getThumbAt(index)
813: .getObject();
814: color = changeColorButton.getBackground();
815: slider.getModel().getThumbAt(index).setObject(color);
816: updateFromStop(index, slider.getModel().getThumbAt(index)
817: .getPosition(), color);
818: slider.repaint();
819: ((GradientPreviewPanel) gradientPreview).repaint();
820: }
821: }
822:
823: /**
824: * This static utility method <b>cannot</b> be called from the
825: * ETD, or your application will lock up. Call it from a separate
826: * thread or create a new Thread with a Runnable.
827: */
828: public static MultipleGradientPaint showDialog(Component comp,
829: String title, MultipleGradientPaint mgrad) {
830: Component root = SwingUtilities.getRoot(comp);
831: final JDialog dialog = new JDialog((JFrame) root, title, true);
832: final JXGradientChooser picker = new JXGradientChooser();
833: if (mgrad != null) {
834: picker.setGradient(mgrad);
835: }
836: dialog.add(picker);
837:
838: JPanel panel = new JPanel();
839: JButton cancel = new JButton("Cancel");
840: cancel.addActionListener(new ActionListener() {
841: public void actionPerformed(ActionEvent actionEvent) {
842: dialog.setVisible(false);
843: }
844: });
845: JButton okay = new JButton("Ok");
846: okay.addActionListener(new ActionListener() {
847: public void actionPerformed(ActionEvent actionEvent) {
848: dialog.setVisible(false);
849: }
850: });
851: okay.setDefaultCapable(true);
852:
853: GridLayout gl = new GridLayout();
854: gl.setHgap(2);
855: panel.setLayout(gl);
856: panel.add(cancel);
857: panel.add(okay);
858:
859: JPanel p2 = new JPanel();
860: p2.setLayout(new GridBagLayout());
861: GridBagConstraints gbc = new GridBagConstraints();
862: gbc.anchor = gbc.EAST;
863: gbc.weightx = 1.0;
864: p2.add(panel, gbc);
865: dialog.add(p2, "South");
866:
867: dialog.getRootPane().setDefaultButton(okay);
868: dialog.pack();
869: dialog.setResizable(false);
870: dialog.setVisible(true);
871:
872: return picker.getGradient();
873: }
874:
875: public static void main(String[] args) throws Exception {
876: UIManager.setLookAndFeel(UIManager
877: .getSystemLookAndFeelClassName());
878: Toolkit.getDefaultToolkit().setDynamicLayout(true);
879: final JFrame frame = new JFrame("Gradient Picker");
880: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
881: frame.getContentPane()
882: .setLayout(
883: new BoxLayout(frame.getContentPane(),
884: BoxLayout.Y_AXIS));
885:
886: JButton button = new JButton("Select Gradient");
887: button.addActionListener(new ActionListener() {
888: public void actionPerformed(ActionEvent e) {
889: Color[] colors = { Color.blue, Color.black };
890: float[] vals = { 0.0f, 1.0f };
891: LinearGradientPaint paint = new LinearGradientPaint(0f,
892: 0f, 10f, 0f, vals, colors);
893: MultipleGradientPaint grad = JXGradientChooser
894: .showDialog(frame, "Pick a Gradient", paint);
895: System.out.println("got: "
896: + JXGradientChooser.toString(grad));
897: }
898: });
899: frame.add(button);
900: frame.pack();
901: frame.setVisible(true);
902: }
903:
904: public static String toString(MultipleGradientPaint paint) {
905: StringBuffer buffer = new StringBuffer();
906: buffer.append(paint.getClass().getName());
907: Color[] colors = paint.getColors();
908: float[] values = paint.getFractions();
909: buffer.append("[");
910: for (int i = 0; i < colors.length; i++) {
911: buffer
912: .append("#"
913: + Integer.toHexString(colors[i].getRGB()));
914: buffer.append(":");
915: buffer.append(values[i]);
916: buffer.append(", ");
917: }
918: buffer.append("]");
919: return buffer.toString();
920: }
921:
922: }
|