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