001 /*
002 * $Id: JXGradientChooser.java 3360 2009-06-14 20:29:45Z kschaefe $
003 *
004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020 */
021
022 package org.jdesktop.swingx;
023
024 import java.awt.BorderLayout;
025 import java.awt.Color;
026 import java.awt.Component;
027 import java.awt.Dimension;
028 import java.awt.GridBagConstraints;
029 import java.awt.GridBagLayout;
030 import java.awt.GridLayout;
031 import java.awt.MultipleGradientPaint;
032 import java.awt.RadialGradientPaint;
033 import java.awt.event.ActionEvent;
034 import java.awt.event.ActionListener;
035 import java.awt.event.ItemEvent;
036 import java.awt.event.ItemListener;
037 import java.awt.event.MouseEvent;
038 import java.beans.PropertyChangeEvent;
039 import java.beans.PropertyChangeListener;
040 import java.util.logging.Logger;
041
042 import javax.swing.ActionMap;
043 import javax.swing.ButtonGroup;
044 import javax.swing.DefaultComboBoxModel;
045 import javax.swing.JButton;
046 import javax.swing.JCheckBox;
047 import javax.swing.JComboBox;
048 import javax.swing.JDialog;
049 import javax.swing.JFrame;
050 import javax.swing.JLabel;
051 import javax.swing.JPanel;
052 import javax.swing.JRadioButton;
053 import javax.swing.JSlider;
054 import javax.swing.JSpinner;
055 import javax.swing.JTextField;
056 import javax.swing.SpinnerNumberModel;
057 import javax.swing.SwingUtilities;
058 import javax.swing.event.ChangeEvent;
059 import javax.swing.event.ChangeListener;
060
061 import org.jdesktop.swingx.action.AbstractActionExt;
062 import org.jdesktop.swingx.color.ColorUtil;
063 import org.jdesktop.swingx.color.GradientPreviewPanel;
064 import org.jdesktop.swingx.color.GradientThumbRenderer;
065 import org.jdesktop.swingx.color.GradientTrackRenderer;
066 import org.jdesktop.swingx.multislider.Thumb;
067 import org.jdesktop.swingx.multislider.ThumbListener;
068
069 /**
070 * <p>A specialized JXPanel that allows the user to construct and choose a Gradient.
071 * The returned values will be one of: LinearGradientPaint or RadialGradientPaint.</p>
072 *
073 * <p><b>Dependency</b>: Because this class relies on LinearGradientPaint and
074 * RadialGradientPaint, it requires the optional MultipleGradientPaint.jar</p>
075 *
076 * @author joshy
077 */
078 public class JXGradientChooser extends JXPanel {
079 private enum GradientStyle { Linear, Radial }
080
081 /**
082 * The multi-thumb slider to use for the gradient stops
083 */
084 private JXMultiThumbSlider<Color> slider;
085 private JButton deleteThumbButton;
086 private JButton addThumbButton;
087
088 private JTextField colorField;
089 private JXColorSelectionButton changeColorButton;
090 private JSpinner colorLocationSpinner;
091 private JSpinner alphaSpinner;
092 private JSlider alphaSlider;
093
094 private JComboBox styleCombo;
095 private GradientPreviewPanel gradientPreview;
096
097 private JRadioButton noCycleRadio;
098 private JRadioButton reflectedRadio;
099 private JRadioButton repeatedRadio;
100 private JCheckBox reversedCheck;
101 private MultipleGradientPaint gradient;
102
103 /**
104 * Creates new JXGradientChooser
105 */
106 public JXGradientChooser() {
107 initComponents2();
108 }
109
110 /**
111 * Returns the MultipleGradientPaint currently choosen by the user.
112 * @return the currently selected gradient
113 */
114 public MultipleGradientPaint getGradient() {
115 return gradient;
116 }
117
118 private boolean thumbsMoving = false;
119 private Logger log = Logger.getLogger(JXGradientChooser.class.getName());
120
121 /**
122 * Sets the gradient within this panel to the new gradient. This will delete
123 * the old gradient all of it's settings, resetting the slider, gradient
124 * type selection, and other gradient configuration options to match the
125 * new gradient.
126 *
127 * @param mgrad The desired gradient.
128 */
129 public void setGradient(MultipleGradientPaint mgrad) {
130 if(gradient == mgrad) {
131 return;
132 }
133 float[] fracts = mgrad.getFractions();
134 Color[] colors = mgrad.getColors();
135
136 if(!thumbsMoving) {
137 // update the slider properly
138 if(slider.getModel().getThumbCount() !=
139 mgrad.getColors().length) {
140 // removing all thumbs;
141 while(slider.getModel().getThumbCount() > 0) {
142 slider.getModel().removeThumb(0);
143 }
144 // add them back
145 for(int i=0; i<fracts.length; i++) {
146 slider.getModel().addThumb(fracts[i],colors[i]);
147 }
148 } else {
149 for(int i=0; i<fracts.length; i++) {
150 slider.getModel().getThumbAt(i).setObject(colors[i]);
151 slider.getModel().getThumbAt(i).setPosition(fracts[i]);
152 }
153 }
154 } else {
155 log.fine("not updating because it's moving");
156 }
157 if(mgrad instanceof RadialGradientPaint) {
158 if(styleCombo.getSelectedItem() != GradientStyle.Radial) {
159 styleCombo.setSelectedItem(GradientStyle.Radial);
160 }
161 } else {
162 if(styleCombo.getSelectedItem() != GradientStyle.Linear) {
163 styleCombo.setSelectedItem(GradientStyle.Linear);
164 }
165 }
166
167 if(mgrad.getCycleMethod() == MultipleGradientPaint.CycleMethod.REFLECT) {
168 this.reflectedRadio.setSelected(true);
169 gradientPreview.setReflected(true);
170 }
171 if(mgrad.getCycleMethod() == MultipleGradientPaint.CycleMethod.REPEAT) {
172 this.repeatedRadio.setSelected(true);
173 gradientPreview.setRepeated(true);
174 }
175 gradientPreview.setGradient(mgrad);
176 //reflectedRadio.setSelected()
177 MultipleGradientPaint old = this.getGradient();
178 gradient = mgrad;
179 firePropertyChange("gradient",old,getGradient());
180 repaint();
181 }
182
183 private void recalcGradientFromStops() {
184 setGradient(gradientPreview.getGradient());
185 }
186
187 private void updateFromStop(Thumb<Color> thumb) {
188 if(thumb == null) {
189 updateFromStop(-1,-1,Color.black);
190 } else {
191 updateFromStop(1,thumb.getPosition(),thumb.getObject());
192 }
193 }
194
195 private void updateFromStop(int thumb, float position, Color color) {
196 log.fine("updating: " + thumb + " " + position + " " + color);
197 if(thumb == -1) {
198 colorLocationSpinner.setEnabled(false);
199 alphaSpinner.setEnabled(false);
200 alphaSlider.setEnabled(false);
201 colorField.setEnabled(false);
202 changeColorButton.setEnabled(false);
203 changeColorButton.setBackground(Color.black);
204 deleteThumbButton.setEnabled(false);
205 } else {
206 colorLocationSpinner.setEnabled(true);
207 alphaSpinner.setEnabled(true);
208 alphaSlider.setEnabled(true);
209 colorField.setEnabled(true);
210 changeColorButton.setEnabled(true);
211 colorLocationSpinner.setValue((int)(100*position));
212 colorField.setText(Integer.toHexString(color.getRGB()).substring(2));
213 alphaSpinner.setValue(color.getAlpha()*100/255);
214 alphaSlider.setValue(color.getAlpha()*100/255);
215 changeColorButton.setBackground(color);
216 deleteThumbButton.setEnabled(true);
217 }
218 updateDeleteButtons();
219 recalcGradientFromStops();
220 }
221
222 private void updateDeleteButtons() {
223 if(slider.getModel().getThumbCount() <= 2) {
224 deleteThumbButton.setEnabled(false);
225 }
226 }
227
228 private void updateGradientProperty() {
229 firePropertyChange("gradient",null,getGradient());
230 gradientPreview.repaint();
231 }
232
233
234 /** This method is called from within the constructor to
235 * initialize the form.
236 */
237
238 private JPanel topPanel, previewPanel;
239 private void initComponents() {
240 // declarations for anonymous components
241 JPanel jPanel1, jPanel2, jPanel3, jPanel4;
242 JLabel jLabel1, jLabel5, jLabel2, jLabel6, jLabel4, jLabel7, jLabel8, jLabel9;
243 ButtonGroup typeGroup;
244 // pre-init stuff
245 slider = new JXMultiThumbSlider<Color>();
246 gradientPreview = new GradientPreviewPanel();
247 gradientPreview.setMultiThumbModel(slider.getModel());
248
249 java.awt.GridBagConstraints gridBagConstraints;
250
251 typeGroup = new javax.swing.ButtonGroup();
252 jPanel1 = new javax.swing.JPanel();
253 topPanel = new javax.swing.JPanel();
254 jPanel2 = new javax.swing.JPanel();
255 jLabel1 = new javax.swing.JLabel();
256 jLabel5 = new javax.swing.JLabel();
257 colorField = new javax.swing.JTextField();
258 jLabel2 = new javax.swing.JLabel();
259 jLabel6 = new javax.swing.JLabel();
260 colorLocationSpinner = new javax.swing.JSpinner();
261 jLabel4 = new javax.swing.JLabel();
262 jLabel7 = new javax.swing.JLabel();
263 alphaSpinner = new javax.swing.JSpinner();
264 changeColorButton = new JXColorSelectionButton();
265 alphaSlider = new javax.swing.JSlider();
266 //slider = new javax.swing.JSlider();
267 jPanel4 = new javax.swing.JPanel();
268 addThumbButton = new javax.swing.JButton();
269 deleteThumbButton = new javax.swing.JButton();
270 previewPanel = new javax.swing.JPanel();
271 jPanel3 = new javax.swing.JPanel();
272 jLabel8 = new javax.swing.JLabel();
273 styleCombo = new javax.swing.JComboBox();
274 jLabel9 = new javax.swing.JLabel();
275 noCycleRadio = new javax.swing.JRadioButton();
276 reflectedRadio = new javax.swing.JRadioButton();
277 repeatedRadio = new javax.swing.JRadioButton();
278 reversedCheck = new javax.swing.JCheckBox();
279 //gradientPreview = new javax.swing.JPanel();
280
281 //setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
282 jPanel1.setLayout(new java.awt.GridBagLayout());
283
284 topPanel.setLayout(new java.awt.GridBagLayout());
285
286 topPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Gradient"));
287 jPanel2.setLayout(new java.awt.GridBagLayout());
288
289 jLabel1.setText("Color:");
290 gridBagConstraints = new java.awt.GridBagConstraints();
291 gridBagConstraints.gridx = 0;
292 gridBagConstraints.gridy = 0;
293 gridBagConstraints.ipadx = 2;
294 gridBagConstraints.ipady = 2;
295 gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
296 gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
297 jPanel2.add(jLabel1, gridBagConstraints);
298
299 jLabel5.setText("#");
300 gridBagConstraints = new java.awt.GridBagConstraints();
301 gridBagConstraints.gridx = 1;
302 gridBagConstraints.gridy = 0;
303 gridBagConstraints.insets = new java.awt.Insets(4, 0, 4, 4);
304 jPanel2.add(jLabel5, gridBagConstraints);
305
306 colorField.setColumns(6);
307 colorField.setEnabled(false);
308 colorField.setPreferredSize(null);
309 gridBagConstraints = new java.awt.GridBagConstraints();
310 gridBagConstraints.gridy = 0;
311 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
312 jPanel2.add(colorField, gridBagConstraints);
313
314 jLabel2.setText("Location:");
315 gridBagConstraints = new java.awt.GridBagConstraints();
316 gridBagConstraints.gridy = 1;
317 gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
318 gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
319 jPanel2.add(jLabel2, gridBagConstraints);
320
321 jLabel6.setText("%");
322 gridBagConstraints = new java.awt.GridBagConstraints();
323 gridBagConstraints.gridy = 1;
324 jPanel2.add(jLabel6, gridBagConstraints);
325
326 colorLocationSpinner.setEnabled(false);
327 colorLocationSpinner.setPreferredSize(null);
328 gridBagConstraints = new java.awt.GridBagConstraints();
329 gridBagConstraints.gridy = 1;
330 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
331 jPanel2.add(colorLocationSpinner, gridBagConstraints);
332
333 jLabel4.setText("Opacity:");
334 gridBagConstraints = new java.awt.GridBagConstraints();
335 gridBagConstraints.gridy = 2;
336 gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
337 gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
338 jPanel2.add(jLabel4, gridBagConstraints);
339
340 jLabel7.setText("%");
341 gridBagConstraints = new java.awt.GridBagConstraints();
342 gridBagConstraints.gridy = 2;
343 jPanel2.add(jLabel7, gridBagConstraints);
344
345 alphaSpinner.setEnabled(false);
346 alphaSpinner.setPreferredSize(null);
347 gridBagConstraints = new java.awt.GridBagConstraints();
348 gridBagConstraints.gridy = 2;
349 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
350 jPanel2.add(alphaSpinner, gridBagConstraints);
351
352 changeColorButton.setText("00");
353 changeColorButton.setEnabled(false);
354 gridBagConstraints = new java.awt.GridBagConstraints();
355 gridBagConstraints.fill = java.awt.GridBagConstraints.NONE;
356 gridBagConstraints.weightx = 1.0;
357 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
358 gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
359 jPanel2.add(changeColorButton, gridBagConstraints);
360
361 alphaSlider.setEnabled(false);
362 alphaSlider.setPreferredSize(new java.awt.Dimension(20, 25));
363 gridBagConstraints = new java.awt.GridBagConstraints();
364 gridBagConstraints.gridy = 2;
365 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
366 gridBagConstraints.weightx = 1.0;
367 jPanel2.add(alphaSlider, gridBagConstraints);
368
369 gridBagConstraints = new java.awt.GridBagConstraints();
370 gridBagConstraints.gridx = 0;
371 gridBagConstraints.gridy = 2;
372 gridBagConstraints.gridwidth = 2;
373 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
374 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
375 gridBagConstraints.weightx = 1.0;
376 gridBagConstraints.weighty = 1.0;
377 gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
378 topPanel.add(jPanel2, gridBagConstraints);
379
380 gridBagConstraints = new java.awt.GridBagConstraints();
381 gridBagConstraints.gridy = 0;
382 gridBagConstraints.gridwidth = 2;
383 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
384 topPanel.add(slider, gridBagConstraints);
385
386 jPanel4.setLayout(new java.awt.GridLayout(1, 0, 2, 0));
387
388 addThumbButton.setText("Add");
389 jPanel4.add(addThumbButton);
390
391 deleteThumbButton.setText("Delete");
392 jPanel4.add(deleteThumbButton);
393
394 gridBagConstraints = new java.awt.GridBagConstraints();
395 gridBagConstraints.gridy = 1;
396 gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
397 gridBagConstraints.weightx = 1.0;
398 gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
399 topPanel.add(jPanel4, gridBagConstraints);
400
401 gridBagConstraints = new java.awt.GridBagConstraints();
402 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
403 gridBagConstraints.weightx = 1.0;
404 jPanel1.add(topPanel, gridBagConstraints);
405
406 previewPanel.setLayout(new java.awt.GridBagLayout());
407
408 previewPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Preview"));
409 jPanel3.setLayout(new java.awt.GridBagLayout());
410
411 jLabel8.setText("Style:");
412 gridBagConstraints = new java.awt.GridBagConstraints();
413 gridBagConstraints.gridy = 0;
414 gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
415 gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
416 jPanel3.add(jLabel8, gridBagConstraints);
417
418 styleCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Linear", "Radial" }));
419 gridBagConstraints = new java.awt.GridBagConstraints();
420 gridBagConstraints.gridy = 0;
421 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
422 gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
423 jPanel3.add(styleCombo, gridBagConstraints);
424
425 jLabel9.setText("Type:");
426 gridBagConstraints = new java.awt.GridBagConstraints();
427 gridBagConstraints.gridy = 1;
428 gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
429 gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
430 jPanel3.add(jLabel9, gridBagConstraints);
431
432 typeGroup.add(noCycleRadio);
433 noCycleRadio.setSelected(true);
434 noCycleRadio.setText("None");
435 noCycleRadio.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
436 noCycleRadio.setMargin(new java.awt.Insets(0, 0, 0, 0));
437 gridBagConstraints = new java.awt.GridBagConstraints();
438 gridBagConstraints.gridy = 1;
439 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
440 gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
441 jPanel3.add(noCycleRadio, gridBagConstraints);
442
443 typeGroup.add(reflectedRadio);
444 reflectedRadio.setText("Reflect");
445 reflectedRadio.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
446 reflectedRadio.setMargin(new java.awt.Insets(0, 0, 0, 0));
447 gridBagConstraints = new java.awt.GridBagConstraints();
448 gridBagConstraints.gridx = 1;
449 gridBagConstraints.gridy = 2;
450 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
451 gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
452 jPanel3.add(reflectedRadio, gridBagConstraints);
453
454 typeGroup.add(repeatedRadio);
455 repeatedRadio.setText("Repeat");
456 repeatedRadio.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
457 repeatedRadio.setMargin(new java.awt.Insets(0, 0, 0, 0));
458 gridBagConstraints = new java.awt.GridBagConstraints();
459 gridBagConstraints.gridx = 1;
460 gridBagConstraints.gridy = 3;
461 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
462 gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
463 jPanel3.add(repeatedRadio, gridBagConstraints);
464
465 reversedCheck.setText("Reverse");
466 reversedCheck.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
467 reversedCheck.setMargin(new java.awt.Insets(0, 0, 0, 0));
468 gridBagConstraints = new java.awt.GridBagConstraints();
469 gridBagConstraints.gridx = 1;
470 gridBagConstraints.gridy = 4;
471 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
472 gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
473 jPanel3.add(reversedCheck, gridBagConstraints);
474
475 gridBagConstraints = new java.awt.GridBagConstraints();
476 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
477 previewPanel.add(jPanel3, gridBagConstraints);
478
479 gradientPreview.setBorder(javax.swing.BorderFactory.createEtchedBorder());
480 gradientPreview.setPreferredSize(new java.awt.Dimension(130, 130));
481 gridBagConstraints = new java.awt.GridBagConstraints();
482 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
483 gridBagConstraints.weightx = 10.0;
484 gridBagConstraints.weighty = 10.0;
485 previewPanel.add(gradientPreview, gridBagConstraints);
486
487 gridBagConstraints = new java.awt.GridBagConstraints();
488 gridBagConstraints.gridy = 1;
489 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
490 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
491 gridBagConstraints.weightx = 1.0;
492 gridBagConstraints.weighty = 1.0;
493 jPanel1.add(previewPanel, gridBagConstraints);
494
495 }// </editor-fold>
496 private void initComponents2() {
497 this.initComponents();
498 setLayout(new BorderLayout());
499 add(topPanel, BorderLayout.NORTH);
500 add(previewPanel, BorderLayout.CENTER);
501
502
503 // do event handling stuff
504 //create the actions and load them in the action map
505 AddThumbAction addThumbAction = new AddThumbAction();
506 DeleteThumbAction deleteThumbAction = new DeleteThumbAction();
507 deleteThumbAction.setEnabled(false); //disabled to begin with
508 //TODO Add to the action map with proper keys, etc
509 ActionMap actions = getActionMap();
510 actions.put("add-thumb", addThumbAction);
511 actions.put("delete-thumb", deleteThumbAction);
512 //actions.put("change-color", changeColorAction);
513 addThumbButton.setAction(addThumbAction);
514 deleteThumbButton.setAction(deleteThumbAction);
515 changeColorButton.addPropertyChangeListener("background", new PropertyChangeListener() {
516 public void propertyChange(PropertyChangeEvent evt) {
517 selectColorForThumb();
518 updateGradientProperty();
519 }
520 });
521 colorLocationSpinner.addChangeListener(new ChangeLocationListener());
522 ChangeAlphaListener changeAlphaListener = new ChangeAlphaListener();
523 alphaSpinner.addChangeListener(changeAlphaListener);
524 alphaSlider.addChangeListener(changeAlphaListener);
525 RepaintOnEventListener repaintListener = new RepaintOnEventListener();
526 styleCombo.addItemListener(repaintListener);
527 styleCombo.setModel(new DefaultComboBoxModel(GradientStyle.values()));
528 noCycleRadio.addActionListener(repaintListener);
529 reflectedRadio.addActionListener(repaintListener);
530 repeatedRadio.addActionListener(repaintListener);
531 reversedCheck.addActionListener(repaintListener);
532 gradientPreview.picker = this; //wow, nasty
533
534
535 ///To still refactor below::
536 SpinnerNumberModel alpha_model = new SpinnerNumberModel(100,0,100,1);
537 alphaSpinner.setModel(alpha_model);
538 SpinnerNumberModel location_model = new SpinnerNumberModel(100,0,100,1);
539 colorLocationSpinner.setModel(location_model);
540
541 slider.setOpaque(false);
542 slider.setPreferredSize(new Dimension(100,35));
543 slider.getModel().setMinimumValue(0f);
544 slider.getModel().setMaximumValue(1.0f);
545
546 slider.getModel().addThumb(0,Color.black);
547 slider.getModel().addThumb(0.5f,Color.red);
548 slider.getModel().addThumb(1.0f,Color.white);
549
550 slider.setThumbRenderer(new GradientThumbRenderer());
551 slider.setTrackRenderer(new GradientTrackRenderer());
552 slider.addMultiThumbListener(new StopListener());
553
554 // called when the gradient property of the preview pane changes
555 gradientPreview.addPropertyChangeListener("gradient", new PropertyChangeListener() {
556 public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
557 recalcGradientFromStops();
558 }
559 });
560
561 recalcGradientFromStops();
562
563 }
564
565 // called whenever the color location spinner is changed
566 private final class ChangeLocationListener implements ChangeListener {
567 public void stateChanged(ChangeEvent evt) {
568 if(slider.getSelectedIndex() >= 0) {
569 Thumb<Color> thumb = slider.getModel().getThumbAt(slider.getSelectedIndex());
570 thumb.setPosition((Integer)colorLocationSpinner.getValue()/100f);
571 updateFromStop(thumb);
572 updateGradientProperty();
573 }
574 }
575 }
576
577 // called when the alpha slider moves
578 private final class ChangeAlphaListener implements ChangeListener {
579 public void stateChanged(ChangeEvent changeEvent) {
580 if(slider.getSelectedIndex() >= 0 && !thumbsMoving) {
581 // get the selected thumb
582 Thumb<Color> thumb = slider.getModel().getThumbAt(slider.getSelectedIndex());
583 // get the new alpha value
584 int alpha = changeEvent.getSource() == alphaSpinner ?
585 (Integer)alphaSpinner.getValue()
586 : alphaSlider.getValue();
587
588
589 // calc new color and set it on thumb
590 Color col = thumb.getObject();
591 col = ColorUtil.setAlpha(col, alpha*255/100);
592 thumb.setObject(col);
593
594 // set the new alpha value on the other alpha control
595 if (changeEvent.getSource() == alphaSpinner) {
596 alphaSlider.setValue(alpha);
597 } else {
598 alphaSpinner.setValue(alpha);
599 }
600
601 recalcGradientFromStops();
602 }
603 }
604 }
605
606
607 private final class AddThumbAction extends AbstractActionExt {
608 public AddThumbAction() {
609 super("Add");
610 }
611
612 public void actionPerformed(ActionEvent actionEvent) {
613 float pos = 0.2f;
614 Color color = Color.black;
615 int num = slider.getModel().addThumb(pos,color);
616 log.fine("new number = " + num);
617 /*
618 for (int i = 0; i < slider.getModel().getThumbCount(); i++) {
619 float pos2 = slider.getModel().getThumbAt(i).getPosition();
620 if (pos2 < pos) {
621 continue;
622 }
623 slider.getModel().insertThumb(pos, color, i);
624 updateFromStop(i,pos,color);
625 break;
626 }
627 */
628
629 }
630 }
631
632 private final class DeleteThumbAction extends AbstractActionExt {
633 public DeleteThumbAction() {
634 super("Delete");
635 }
636
637 public void actionPerformed(ActionEvent actionEvent) {
638 int index = slider.getSelectedIndex();
639 if (index >= 0) {
640 slider.getModel().removeThumb(index);
641 updateFromStop(-1,-1,null);
642 }
643 }
644 }
645
646 private class StopListener implements ThumbListener {
647
648 public StopListener() {
649 super();
650 }
651
652 public void thumbMoved(int thumb, float pos) {
653 log.fine("moved: " + thumb + " " + pos);
654 Color color = slider.getModel().getThumbAt(thumb).getObject();
655 thumbsMoving = true;
656 updateFromStop(thumb,pos,color);
657 updateDeleteButtons();
658 thumbsMoving = false;
659
660 }
661
662 public void thumbSelected(int thumb) {
663
664 if(thumb == -1) {
665 updateFromStop(-1,-1,Color.black);
666 return;
667 }
668 thumbsMoving = true;
669 float pos = slider.getModel().getThumbAt(thumb).getPosition();
670 Color color = slider.getModel().getThumbAt(thumb).getObject();
671 log.fine("selected = " + thumb + " " + pos + " " + color);
672 updateFromStop(thumb,pos,color);
673 updateDeleteButtons();
674 slider.repaint();
675 thumbsMoving = false;
676
677 }
678
679 public void mousePressed(MouseEvent e) {
680 if(e.getClickCount() > 1) {
681 selectColorForThumb();
682 }
683 }
684 }
685
686 private final class RepaintOnEventListener implements ActionListener, ItemListener {
687 public void actionPerformed(ActionEvent e) {
688 gradientPreview.setReflected(reflectedRadio.isSelected());
689 gradientPreview.setReversed(reversedCheck.isSelected());
690 gradientPreview.setRepeated(repeatedRadio.isSelected());
691 //updateGradientProperty();
692 recalcGradientFromStops();
693 gradientPreview.repaint();
694 }
695
696 public void itemStateChanged(ItemEvent e) {
697 if(styleCombo.getSelectedItem() == GradientStyle.Radial) {
698 gradientPreview.setRadial(true);
699 } else {
700 gradientPreview.setRadial(false);
701 }
702 recalcGradientFromStops();
703 }
704 }
705
706 private void selectColorForThumb() {
707 int index = slider.getSelectedIndex();
708 if (index >= 0) {
709 Color color = changeColorButton.getBackground();
710 slider.getModel().getThumbAt(index).setObject(color);
711 updateFromStop(index, slider.getModel().getThumbAt(index).getPosition(), color);
712 }
713 }
714
715 /**
716 * This static utility method <b>cannot</b> be called from the
717 * ETD, or your application will lock up. Call it from a separate
718 * thread or create a new Thread with a Runnable.
719 * @param comp The component to use when finding a top level window or frame for
720 * the dialog.
721 * @param title The desired title of the gradient chooser dialog.
722 * @param mgrad The gradient to initialize the chooser too.
723 * @return The gradient the user chose.
724 */
725 public static MultipleGradientPaint showDialog(Component comp, String title, MultipleGradientPaint mgrad) {
726 Component root = SwingUtilities.getRoot(comp);
727 final JDialog dialog = new JDialog((JFrame)root,title,true);
728 final JXGradientChooser picker = new JXGradientChooser();
729 if(mgrad != null) {
730 picker.setGradient(mgrad);
731 }
732 dialog.add(picker);
733
734
735 JPanel panel = new JPanel();
736 JButton cancel = new JButton("Cancel");
737 cancel.addActionListener(new ActionListener() {
738 public void actionPerformed(ActionEvent actionEvent) {
739 dialog.setVisible(false);
740 }
741 });
742 JButton okay = new JButton("Ok");
743 okay.addActionListener(new ActionListener() {
744 public void actionPerformed(ActionEvent actionEvent) {
745 dialog.setVisible(false);
746 }
747 });
748 okay.setDefaultCapable(true);
749
750
751 GridLayout gl = new GridLayout();
752 gl.setHgap(2);
753 panel.setLayout(gl);
754 panel.add(cancel);
755 panel.add(okay);
756
757 JPanel p2 = new JPanel();
758 p2.setLayout(new GridBagLayout());
759 GridBagConstraints gbc = new GridBagConstraints();
760 gbc.anchor = GridBagConstraints.EAST;
761 gbc.weightx = 1.0;
762 p2.add(panel,gbc);
763 dialog.add(p2,"South");
764
765 dialog.getRootPane().setDefaultButton(okay);
766 dialog.pack();
767 dialog.setResizable(false);
768 dialog.setVisible(true);
769
770 return picker.getGradient();
771 }
772
773 /**
774 * Creates a string representation of a {@code MultipleGradientPaint}. This
775 * string is used for debugging purposes. Its contents cannot be guaranteed
776 * between releases.
777 *
778 * @param paint
779 * the {@code paint} to create a string for
780 * @return a string representing the supplied {@code paint}
781 */
782 public static String toString(MultipleGradientPaint paint) {
783 StringBuffer buffer = new StringBuffer();
784 buffer.append(paint.getClass().getName());
785 Color[] colors = paint.getColors();
786 float[] values = paint.getFractions();
787 buffer.append("[");
788 for(int i=0; i<colors.length; i++) {
789 buffer.append("#").append(Integer.toHexString(colors[i].getRGB()));
790 buffer.append(":");
791 buffer.append(values[i]);
792 buffer.append(", ");
793 }
794 buffer.append("]");
795 return buffer.toString();
796 }
797
798 }
799
800