1 /* 2 * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.swing.colorchooser; 27 28 import java.awt.Color; 29 import java.awt.ContainerOrderFocusTraversalPolicy; 30 import java.awt.GridBagConstraints; 31 import java.awt.GridBagLayout; 32 import java.awt.Insets; 33 import java.awt.event.ItemEvent; 34 import java.awt.event.ItemListener; 35 import javax.swing.ButtonGroup; 36 import javax.swing.DefaultButtonModel; 37 import javax.swing.JLabel; 38 import javax.swing.JPanel; 39 import javax.swing.JRadioButton; 40 import javax.swing.border.EmptyBorder; 41 import javax.swing.JSpinner.DefaultEditor; 42 43 @SuppressWarnings("serial") // Superclass is not serializable across versions 44 final class ColorPanel extends JPanel implements ItemListener { 45 46 private final SlidingSpinner[] spinners = new SlidingSpinner[5]; 47 private final float[] values = new float[this.spinners.length]; 48 49 private final ColorModel model; 50 private Color color; 51 private int x = 1; 52 private int y = 2; 53 private int z; 54 55 ColorPanel(ColorModel model) { 56 super(new GridBagLayout()); 57 58 GridBagConstraints gbc = new GridBagConstraints(); 59 gbc.fill = GridBagConstraints.HORIZONTAL; 60 61 gbc.gridx = 1; 62 ButtonGroup group = new ButtonGroup(); 63 EmptyBorder border = null; 64 for (int i = 0; i < this.spinners.length; i++) { 65 if (i < 3) { 66 JRadioButton button = new JRadioButton(); 67 if (i == 0) { 68 Insets insets = button.getInsets(); 69 insets.left = button.getPreferredSize().width; 70 border = new EmptyBorder(insets); 71 button.setSelected(true); 72 gbc.insets.top = 5; 73 } 74 add(button, gbc); 75 group.add(button); 76 button.setActionCommand(Integer.toString(i)); 77 button.getModel().addItemListener(this); 78 this.spinners[i] = new SlidingSpinner(this, button); 79 } 80 else { 81 JLabel label = new JLabel(); 82 add(label, gbc); 83 label.setBorder(border); 84 label.setFocusable(false); 85 this.spinners[i] = new SlidingSpinner(this, label); 86 } 87 } 88 gbc.gridx = 2; 89 gbc.weightx = 1.0; 90 gbc.insets.top = 0; 91 gbc.insets.left = 5; 92 for (SlidingSpinner spinner : this.spinners) { 93 add(spinner.getSlider(), gbc); 94 gbc.insets.top = 5; 95 } 96 gbc.gridx = 3; 97 gbc.weightx = 0.0; 98 gbc.insets.top = 0; 99 for (SlidingSpinner spinner : this.spinners) { 100 add(spinner.getSpinner(), gbc); 101 gbc.insets.top = 5; 102 } 103 setFocusTraversalPolicy(new ContainerOrderFocusTraversalPolicy()); 104 setFocusTraversalPolicyProvider(true); 105 setFocusable(false); 106 107 this.model = model; 108 } 109 110 @Override 111 public void itemStateChanged(ItemEvent e) { 112 if(e.getStateChange() == ItemEvent.SELECTED) { 113 if (e.getSource() instanceof DefaultButtonModel) { 114 DefaultButtonModel model = (DefaultButtonModel) e.getSource(); 115 try { 116 this.z = Integer.parseInt(model.getActionCommand()); 117 this.y = (this.z != 2) ? 2 : 1; 118 this.x = (this.z != 0) ? 0 : 1; 119 getParent().repaint(); 120 } 121 catch (NumberFormatException exception) { 122 } 123 } 124 } 125 } 126 127 void buildPanel() { 128 int count = this.model.getCount(); 129 this.spinners[4].setVisible(count > 4); 130 for (int i = 0; i < count; i++) { 131 String text = this.model.getLabel(this, i); 132 Object object = this.spinners[i].getLabel(); 133 if (object instanceof JRadioButton) { 134 JRadioButton button = (JRadioButton) object; 135 button.setText(text); 136 button.getAccessibleContext().setAccessibleDescription(text); 137 } 138 else if (object instanceof JLabel) { 139 JLabel label = (JLabel) object; 140 label.setText(text); 141 } 142 this.spinners[i].setRange(this.model.getMinimum(i), this.model.getMaximum(i)); 143 this.spinners[i].setValue(this.values[i]); 144 this.spinners[i].getSlider().getAccessibleContext().setAccessibleName(text); 145 this.spinners[i].getSpinner().getAccessibleContext().setAccessibleName(text); 146 DefaultEditor editor = (DefaultEditor) this.spinners[i].getSpinner().getEditor(); 147 editor.getTextField().getAccessibleContext().setAccessibleName(text); 148 this.spinners[i].getSlider().getAccessibleContext().setAccessibleDescription(text); 149 this.spinners[i].getSpinner().getAccessibleContext().setAccessibleDescription(text); 150 editor.getTextField().getAccessibleContext().setAccessibleDescription(text); 151 } 152 } 153 154 void colorChanged() { 155 this.color = new Color(getColor(0), isColorTransparencySelectionEnabled()); 156 Object parent = getParent(); 157 if (parent instanceof ColorChooserPanel) { 158 ColorChooserPanel chooser = (ColorChooserPanel) parent; 159 chooser.setSelectedColor(this.color); 160 chooser.repaint(); 161 } 162 } 163 164 float getValueX() { 165 return this.spinners[this.x].getValue(); 166 } 167 168 float getValueY() { 169 return 1.0f - this.spinners[this.y].getValue(); 170 } 171 172 float getValueZ() { 173 return 1.0f - this.spinners[this.z].getValue(); 174 } 175 176 void setValue(float z) { 177 this.spinners[this.z].setValue(1.0f - z); 178 colorChanged(); 179 } 180 181 void setValue(float x, float y) { 182 this.spinners[this.x].setValue(x); 183 this.spinners[this.y].setValue(1.0f - y); 184 colorChanged(); 185 } 186 187 int getColor(float z) { 188 setDefaultValue(this.x); 189 setDefaultValue(this.y); 190 this.values[this.z] = 1.0f - z; 191 return getColor(3); 192 } 193 194 int getColor(float x, float y) { 195 this.values[this.x] = x; 196 this.values[this.y] = 1.0f - y; 197 setValue(this.z); 198 return getColor(3); 199 } 200 201 void setColor(Color color) { 202 if (!color.equals(this.color)) { 203 this.color = color; 204 this.model.setColor(color.getRGB(), this.values); 205 for (int i = 0; i < this.model.getCount(); i++) { 206 this.spinners[i].setValue(this.values[i]); 207 } 208 } 209 } 210 211 private int getColor(int index) { 212 while (index < this.model.getCount()) { 213 setValue(index++); 214 } 215 return this.model.getColor(this.values); 216 } 217 218 void setColorTransparencySelectionEnabled(boolean b) { 219 if (spinners[model.getCount() - 1].isVisible() != b) { 220 spinners[model.getCount() - 1].setVisible(b); 221 colorChanged(); 222 } 223 } 224 225 boolean isColorTransparencySelectionEnabled() { 226 return spinners[model.getCount() - 1].isVisible(); 227 } 228 229 private void setValue(int index) { 230 this.values[index] = this.spinners[index].getValue(); 231 } 232 233 private void setDefaultValue(int index) { 234 float value = this.model.getDefault(index); 235 this.values[index] = (value < 0.0f) 236 ? this.spinners[index].getValue() 237 : value; 238 } 239 }