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