1
package org.pushingpixels.substance.internal.contrib.xoetrope.editor.color;
4
import java.awt.event.*;
5
import java.awt.font.TextAttribute;
6
import java.awt.geom.*;
7
import java.awt.image.BufferedImage;
8
import java.text.AttributedString;
12
import javax.swing.colorchooser.AbstractColorChooserPanel;
13
import javax.swing.event.*;
16
* A color wheel showing a Red, Yellow, Blue color model traditionally used by
17
* graphic artists. $Revision: 2254 $
19
public class ColorWheelPanel extends AbstractColorChooserPanel implements
20
ActionListener, MouseListener, MouseMotionListener, MouseWheelListener,
22
public static final int MONOCHROMATIC_SCHEME = 0;
23
public static final int CONTRASTING_SCHEME = 1;
24
public static final int SOFT_CONTRAST_SCHEME = 2;
25
public static final int DOUBLE_CONTRAST_SCHEME = 3;
26
public static final int ANALOGIC_SCHEME = 4;
28
public static final int CTRL_ADJUST = 0;
29
public static final int ALWAYS_ADJUST = 1;
30
public static final int NEVER_ADJUST = 2;
32
protected JTextField hueEdit, satEdit, brightEdit, baseColorEdit;
33
protected BufferedImage pickerImage;
34
protected ColorWheel imagePicker;
35
protected JPanel fixedPanel;
36
protected JButton resetBtn;
37
protected JSlider brightnessSlider, saturationSlider;
38
protected JLabel baseColorLabel;
39
protected Ellipse2D innerCircle, outerCircle, borderCircle;
40
protected JCheckBox useWebColors, decimalRGB;
41
protected Font font9pt;
43
protected ModelColor chooserColor;
44
protected ModelColor[] selectedIttenColours;
46
private float values[] = new float[3];
47
private double h, s, b;
49
private int colorScheme = 0;
51
private boolean busy = false;
52
private boolean displayScheme = false;
53
private boolean hasChooser = false;
55
private ArrayList<ChangeListener> changeListeners;
56
private static double[] arcDelta = { -7.5, -7.5, -7.5, -7.5, -7.5, -1.0,
59
private double ringThickness;
60
private GeneralPath[] paths;
61
private static ResourceBundle labelBundle;
63
// Rollover related variables
64
private GeneralPath rolloverPath, selectedPath;
65
private boolean showRollovers;
66
private Color rolloverColor, selectedColor;
67
private Color systemColor;
69
private String fontFamily;
71
private int adjustWheel;
72
private boolean adjustRollover;
73
private boolean ctrlKeyDown;
74
private double saturationMultipler, brightnessMultipler;
77
* Creates a new instance of ColorWheelPanel
79
public ColorWheelPanel() {
80
saturationMultipler = brightnessMultipler = 1.0;
81
changeListeners = new ArrayList<ChangeListener>();
82
adjustWheel = CTRL_ADJUST;
83
adjustRollover = true;
86
font9pt = UIManager.getFont("ColorChooser.smallFont");
88
font9pt = new Font("Arial", 0, 9);
90
fontFamily = font9pt.getFamily();
93
innerCircle = new Ellipse2D.Double(96, 96, 36, 36);
94
outerCircle = new Ellipse2D.Double(6, 6, 214, 214);
95
borderCircle = new Ellipse2D.Double(0, 0, 227, 227);
97
fixedPanel = new JPanel();
98
fixedPanel.setLayout(null);
99
fixedPanel.setOpaque(false);
100
// fixedPanel.setBackground( Color.white );
101
fixedPanel.setBounds(0, 0, 255, 328);
102
fixedPanel.setPreferredSize(new Dimension(255, 328));
104
setLayout(new LayoutManager() {
106
public void addLayoutComponent(String name, Component comp) {
110
public void removeLayoutComponent(Component comp) {
114
public void layoutContainer(Container parent) {
115
Dimension fpp = fixedPanel.getPreferredSize();
116
int dx = (parent.getWidth() - fpp.width) / 2;
117
int dy = (parent.getHeight() - fpp.height) / 2;
118
fixedPanel.setBounds(dx, dy, fpp.width, fpp.height);
122
public Dimension minimumLayoutSize(Container parent) {
123
return preferredLayoutSize(parent);
127
public Dimension preferredLayoutSize(Container parent) {
128
return fixedPanel.getPreferredSize();
132
imagePicker = new ColorWheel();
133
imagePicker.setBounds(0, 0, 228, 228);
134
imagePicker.addMouseListener(this);
135
imagePicker.addMouseMotionListener(this);
136
imagePicker.setOpaque(false);
137
imagePicker.addMouseWheelListener(this);
138
fixedPanel.add(imagePicker);
140
brightnessSlider = new JSlider(JSlider.VERTICAL);
141
brightnessSlider.setBounds(230, 0, 25, 108);
142
brightnessSlider.setMinimum(0);
143
brightnessSlider.setMaximum(100);
144
brightnessSlider.setValue(100);
145
brightnessSlider.setOpaque(false);
146
// brightnessSlider.setBackground( Color.white );
147
brightnessSlider.setPaintLabels(true);
148
brightnessSlider.addChangeListener(this);
149
brightnessSlider.addMouseWheelListener(this);
150
brightnessSlider.addMouseMotionListener(this);
151
brightnessSlider.setToolTipText(getLabel("Xoetrope.ctrlDrag",
152
"CTRL+drag to adjust the color wheel"));
153
fixedPanel.add(brightnessSlider);
155
resetBtn = new JButton();
156
resetBtn.setBounds(237, 109, 10, 10);
157
resetBtn.setBackground(getBackground());
158
resetBtn.addActionListener(this);
159
resetBtn.setToolTipText(getLabel("Xoetrope.reset",
160
"Reset the color wheel sauturation and brightness"));
161
fixedPanel.add(resetBtn);
163
saturationSlider = new JSlider(JSlider.VERTICAL);
164
saturationSlider.setBounds(230, 120, 25, 110);
165
saturationSlider.setMinimum(0);
166
saturationSlider.setMaximum(100);
167
saturationSlider.setValue(100);
168
saturationSlider.setOpaque(false);
169
// saturationSlider.setBackground( Color.white );
170
saturationSlider.setInverted(true);
171
saturationSlider.setPaintLabels(true);
172
saturationSlider.addChangeListener(this);
173
saturationSlider.addMouseWheelListener(this);
174
saturationSlider.addMouseMotionListener(this);
175
saturationSlider.setToolTipText(getLabel("Xoetrope.ctrlDrag",
176
"CTRL+drag to adjust the color wheel"));
177
fixedPanel.add(saturationSlider);
179
useWebColors = new JCheckBox(getLabel("Xoetrope.webSafeColors",
180
"Use web safe colors"));
181
useWebColors.setBounds(8, 248, 160, 18);
182
useWebColors.addActionListener(this);
183
useWebColors.setOpaque(false);
184
useWebColors.setFont(font9pt);
185
fixedPanel.add(useWebColors);
187
decimalRGB = new JCheckBox(getLabel("Xoetrope.decimalRGB",
189
decimalRGB.setBounds(173, 248, 88, 18);
190
decimalRGB.addActionListener(this);
191
decimalRGB.setOpaque(false);
192
decimalRGB.setFont(font9pt);
193
fixedPanel.add(decimalRGB);
195
baseColorLabel = new JLabel();
196
baseColorLabel.setBounds(10, 268, 160, 18);
197
baseColorLabel.setBackground(Color.red);
198
baseColorLabel.setOpaque(true);
199
baseColorLabel.setToolTipText(getLabel("Xoetrope.systemColorsTooltip",
200
"Right click for system colours"));
201
fixedPanel.add(baseColorLabel);
202
baseColorLabel.addMouseListener(new MouseAdapter() {
204
public void mouseClicked(MouseEvent me) {
205
showSystemColorList(me.getPoint());
209
baseColorEdit = new JTextField();
210
baseColorEdit.setBounds(180, 268, 75, 18);
211
baseColorEdit.setOpaque(true);
212
fixedPanel.add(baseColorEdit);
213
baseColorEdit.addActionListener(this);
215
hueEdit = new JTextField();
216
hueEdit.setBounds(10, 288, 75, 20);
217
fixedPanel.add(hueEdit);
218
hueEdit.setText("0");
219
hueEdit.getDocument().addDocumentListener(
220
new ColorDocumentListener(hueEdit));
222
JLabel hueLabel = new JLabel(getLabel("Xoetrope.hue", "Hue")
224
hueLabel.setBounds(10, 308, 75, 20);
225
hueLabel.setFont(font9pt);
226
fixedPanel.add(hueLabel);
228
satEdit = new JTextField();
229
satEdit.setBounds(95, 288, 75, 20);
230
fixedPanel.add(satEdit);
231
satEdit.setText("0");
232
satEdit.getDocument().addDocumentListener(
233
new ColorDocumentListener(satEdit));
235
JLabel satLabel = new JLabel(getLabel("Xoetrope.saturation",
238
satLabel.setBounds(95, 308, 75, 20);
239
satLabel.setFont(font9pt);
240
fixedPanel.add(satLabel);
242
brightEdit = new JTextField();
243
brightEdit.setBounds(180, 288, 75, 20);
244
fixedPanel.add(brightEdit);
245
brightEdit.setText("0");
246
brightEdit.getDocument().addDocumentListener(
247
new ColorDocumentListener(brightEdit));
249
JLabel brightLabel = new JLabel(getLabel("Xoetrope.brightness",
252
brightLabel.setBounds(180, 308, 75, 20);
253
brightLabel.setFont(font9pt);
254
fixedPanel.add(brightLabel);
260
* Set the reference to the selected colours for the colour scheme
265
public void setSelectedColors(ModelColor[] clrs) {
266
selectedIttenColours = clrs;
270
* Add a listener for changes in the selected color
273
* the change listener to add
275
public void addChangeListener(ChangeListener l) {
276
changeListeners.add(l);
280
* Remove a change listener
283
* the change listener to remove
285
public void removeChangeListener(ChangeListener l) {
286
changeListeners.remove(l);
290
* Has the user selected the use decimal rgb checkbox?
292
* @return true if decimal rgb values are to be shown
294
public boolean useDecimalRGB() {
295
return decimalRGB.isSelected();
299
* Has the user selected the use web safe colors checkbox?
301
* @return true if only web safe colors are to be shown
303
public boolean useWebColors() {
304
return useWebColors.isSelected();
308
* Set the display of the color scheme markers.
311
* true to display the color scheme markers.
313
public void setDisplayScheme(boolean disp) {
314
displayScheme = disp;
318
* Get the selected colors hue
320
* @return the selected hue in the range 0-255
322
public int getHue() {
324
return Integer.parseInt(hueEdit.getText());
325
} catch (NumberFormatException e) {
332
* Set the selected hue
335
* the selected hue in the range 0-255
337
public void setHue(int h) {
342
int selHue = Math.max(0, Math.min(h, 360));
343
hueEdit.setText(Integer.toString(selHue));
345
} catch (NumberFormatException e) {
350
* Get the selected colors saturation
352
* @return the selected saturation in the range 0-255
354
public int getSaturation() {
356
return Integer.parseInt(satEdit.getText());
357
} catch (NumberFormatException e) {
364
* Get the selected colors brightness
366
* @return the selected brightness in the range 0-255
368
public int getBrightness() {
370
return Integer.parseInt(brightEdit.getText());
371
} catch (NumberFormatException e) {
378
* Set the Itten color scheme to use
382
* <li>-1 for no scheme display</li>
383
* <li>0 for a monchromatic color scheme: MONOCHROMATIC_SCHEME</li>
384
* <li>1 for a contrasting color scheme: CONTRASTING_SCHEME</li>
385
* <li>2 for a soft-contrasting color scheme:
386
* SOFT_CONTRAST_SCHEME</li>
387
* <li>3 for a double contrasting color scheme:
388
* DOUBLE_CONTRAST_SCHEME</li>
389
* <li>4 for a analogical color scheme: ANALOGIC_SCHEME</li>
392
public void setColorScheme(int scheme) {
393
colorScheme = scheme;
397
* Change the hue to match the angle identified by the point (in the inner
401
* the point within the inner circle
403
boolean moveHue(Point pt) {
404
if ((borderCircle.contains(pt) && !outerCircle.contains(pt))
405
|| innerCircle.contains(pt)) {
406
int h = getAngle(pt);
407
hueEdit.setText(Integer.toString(h));
415
private int getAngle(Point pt) {
416
int eX = (pt.x > 0) ? pt.x : 96;
417
int eY = (pt.y > 0) ? pt.y : 96;
421
.round(((Math.atan2(-x, y) * 180.0 / Math.PI) + 180.0) % 360.0));
424
public void setColor(Color c) {
429
int g = c.getGreen();
431
if (useWebColors.isSelected()) {
432
r = Math.round(r / 51) * 51;
433
g = Math.round(g / 51) * 51;
434
b = Math.round(b / 51) * 51;
436
chooserColor = new ModelColor(r, g, b);
439
c = new Color(chooserColor.R, chooserColor.G, chooserColor.B);
441
float[] oldValues = values;
442
values = c.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), values);
443
if (values[1] == 0.0F) {
446
} else if (values[2] == 0.0F) {
453
h = Math.min(Math.max(h, 0.0), 1.0);
454
s = Math.min(Math.max(s, 0.0), 1.0);
455
b = Math.min(Math.max(b, 0.0), 1.0);
457
if (values[1] != 0.0F) {
458
if (values[1] != 0.0F)
465
brightnessSlider.setValue(Integer.parseInt(brightEdit.getText()));
466
saturationSlider.setValue(Integer.parseInt(satEdit.getText()));
469
baseColorLabel.setBackground(new Color(chooserColor.R, chooserColor.G,
472
if ((0.5 * c.getRed() + c.getGreen() + 0.3 * c.getBlue()) < 220.0)
473
baseColorLabel.setForeground(Color.white);
475
baseColorLabel.setForeground(Color.black);
478
if (decimalRGB.isSelected()) {
479
// Output decimal values
480
colorStr = " " + Integer.toString(c.getRed()) + "."
481
+ Integer.toString(c.getGreen()) + "."
482
+ Integer.toString(c.getBlue());
485
colorStr = " " + ModelColor.toHexString(c.getRed())
486
+ ModelColor.toHexString(c.getGreen())
487
+ ModelColor.toHexString(c.getBlue());
489
baseColorLabel.setText(colorStr);
490
baseColorEdit.setText(colorStr);
492
ChangeEvent evt = new ChangeEvent(this);
493
int numListeners = changeListeners.size();
494
for (int i = 0; i < numListeners; i++) {
495
ChangeListener l = changeListeners.get(i);
500
getColorSelectionModel().setSelectedColor(c);
504
* Get the selected color
508
public Color getColor() {
509
return new Color(chooserColor.R, chooserColor.G, chooserColor.B);
513
* Get the chooser color
518
public ModelColor getChooserColour() {
523
* Set the value of the hue edit to match the current color
525
private void setHue() {
526
hueEdit.setText(Integer.toString(chooserColor.getHue()));
530
* Set the value of the saturartion edit to match the current color
532
private void setSaturation() {
533
satEdit.setText(Integer.toString((int) (100.0 * chooserColor.S)));
537
* Set the value of the brightness edit to match the current color
539
private void setBrightness() {
540
brightEdit.setText(Integer.toString((int) (100.0 * chooserColor.V)));
544
* Respond to action events for the edit fields
547
public void actionPerformed(ActionEvent e) {
548
Object source = e.getSource();
549
if (source == resetBtn)
551
else if (source instanceof JMenuItem) {
552
// A popup menu item has been selected
553
Color sysColor = getSystemColor(((JMenuItem) source).getText());
554
if (sysColor != null)
558
systemColor = sysColor;
561
getColorSelectionModel().setSelectedColor(systemColor);
565
} else if (source == useWebColors) {
566
boolean snap = useWebColors.isSelected();
567
chooserColor.setWebSnap(snap);
571
// Drop through to the next block to reset the internal color values
572
source = baseColorEdit;
574
} else if (source == baseColorEdit) {
575
String hex = baseColorEdit.getText().trim();
576
if (hex.length() == 0)
578
else if (decimalRGB.isSelected()) {
584
int pos2 = hex.indexOf('.', pos);
586
r = Integer.parseInt(hex.substring(pos, pos2));
588
pos2 = hex.indexOf('.', pos);
590
g = Integer.parseInt(hex.substring(pos, pos2));
592
if (pos2 < hex.length())
593
b = Integer.parseInt(hex.substring(pos));
596
setColor(new Color(r, g, b));
597
} catch (NumberFormatException nfe) {
599
baseColorEdit.setText("255.0.0");
602
for (int i = hex.length(); i < 6; i++)
605
setColor(new Color(ModelColor.hex2dec(hex.substring(0, 2)),
606
ModelColor.hex2dec(hex.substring(2, 4)), ModelColor
607
.hex2dec(hex.substring(4, 6))));
608
} catch (NumberFormatException nfe) {
610
baseColorEdit.setText("FF0000");
618
* Reset the displayed color to the color specified by the edit fields
620
private void resetColor() {
621
if (chooserColor != null) {
626
h = Integer.parseInt(hueEdit.getText());
628
} catch (NumberFormatException nfe) {
629
hueEdit.setText("0");
633
hueEdit.setText(Integer.toString(h));
636
h = (int) ((h + (Math.floor(-h / 360) + 1) * 360) % 360);
637
hueEdit.setText(Integer.toString(h));
642
s = Integer.parseInt(satEdit.getText()) / 100.0;
643
} catch (NumberFormatException nfe) {
644
satEdit.setText("100");
646
if (s > 1 || s < 0) {
648
satEdit.setText(Integer.toString((int) (s * 100.0)));
653
v = Integer.parseInt(brightEdit.getText()) / 100.0;
654
} catch (NumberFormatException nfe) {
655
brightEdit.setText("100");
658
if (v > 1 || v < 0) {
660
brightEdit.setText(Integer.toString((int) (v * 100.0)));
663
if (shouldAdjustWheel()) {
664
saturationMultipler = s;
665
brightnessMultipler = v;
668
if (selectedIttenColours != null)
669
selectedIttenColours[0].setHSV(h, s, v);
670
chooserColor.setHSV(h, s, v);
678
* Invoked when the mouse button has been clicked (pressed and released) on
682
public void mouseClicked(MouseEvent e) {
683
Object src = e.getSource();
684
if (src == imagePicker) {
685
Point pt = e.getPoint();
687
if (borderCircle.contains(pt)) {
688
selectedColor = rolloverColor;
689
selectedPath = rolloverPath;
691
if (outerCircle.contains(pt)) {
692
int width = imagePicker.getWidth();
693
int center = width / 2;
694
int dx = Math.abs(pt.x - center);
695
int dy = Math.abs(pt.y - center);
696
double dr = Math.pow((dx * dx + dy * dy), 0.5);
697
dr -= ringThickness * 1.5;
698
int bandIdx = (int) (dr / ringThickness);
701
int bandOffset = bandIdx * ModelColor.NUM_SEGMENTS;
702
for (int i = 0; i < ModelColor.NUM_SEGMENTS; i++) {
703
if (paths[bandOffset + i].contains(pt))
707
int hueInc = (hue / 15) % 2;
709
ModelColor mc = new ModelColor(hue,
710
ModelColor.SATURATION_BANDS[bandIdx],
711
ModelColor.BRIGHTNESS_BANDS[bandIdx + 1
713
mc = new ModelColor(mc.H, saturationMultipler * mc.S,
714
brightnessMultipler * mc.V);
715
Color pixelColor = new Color(mc.getRed(),
716
mc.getGreen(), mc.getBlue());
717
if (!pixelColor.equals(Color.white))
718
setColor(pixelColor);
723
// repaint for synchronizing the hue marker
725
imagePicker.repaint();
729
* Invoked when a mouse button has been pressed on a component.
732
public void mousePressed(MouseEvent e) {
733
imagePicker.repaint();
737
* Invoked when a mouse button has been released on a component.
740
public void mouseReleased(MouseEvent e) {
744
* Invoked when the mouse enters a component.
747
public void mouseEntered(MouseEvent e) {
751
* Invoked when the mouse exits a component.
754
public void mouseExited(MouseEvent e) {
760
* Invoked when the mouse exits a component.
763
public void mouseMoved(MouseEvent e) {
764
GeneralPath oldPath = rolloverPath;
766
if (e.getSource() == imagePicker) {
767
Point pt = e.getPoint();
769
int numPaths = paths.length;
770
for (int i = 0; i < numPaths; i++) {
771
if (paths[i].contains(pt.x, pt.y)) {
772
rolloverPath = paths[i];
773
ModelColor[][] baseColors = ModelColor.getBaseColors();
774
int ring = i / ModelColor.NUM_SEGMENTS;
775
ModelColor modelColor = baseColors[i
776
% ModelColor.NUM_SEGMENTS][ring];
778
modelColor = new ModelColor(modelColor.H,
779
saturationMultipler * modelColor.S,
780
brightnessMultipler * modelColor.V);
782
rolloverColor = new Color(modelColor.getRed(),
783
modelColor.getGreen(), modelColor.getBlue());
785
rolloverColor = rolloverColor.darker();
787
rolloverColor = rolloverColor.brighter().brighter();
794
if (rolloverPath != oldPath)
799
* Move the sliders in rsponse to the mouse wheel
802
public void mouseWheelMoved(MouseWheelEvent e) {
803
Object src = e.getSource();
804
ctrlKeyDown = e.isControlDown();
805
int notches = e.getWheelRotation();
807
if (src == brightnessSlider) {
809
.setValue(brightnessSlider.getValue() - 2 * notches);
810
} else if (src == saturationSlider) {
812
.setValue(saturationSlider.getValue() + 2 * notches);
813
} else if (src == imagePicker) {
814
setHue(getHue() + 2 * notches);
821
* Invoked when the mouse exits a component.
824
public void mouseDragged(MouseEvent e) {
825
ctrlKeyDown = e.isControlDown();
829
* Invoked when the target of the listener has changed its state.
832
* a ChangeEvent object
835
public void stateChanged(ChangeEvent e) {
836
Object source = e.getSource();
837
if (source == saturationSlider) {
838
satEdit.setText(Integer.toString(saturationSlider.getValue()));
840
} else if (source == brightnessSlider) {
841
brightEdit.setText(Integer.toString(brightnessSlider.getValue()));
846
getColorSelectionModel().setSelectedColor(
847
new Color(chooserColor.getRed(), chooserColor.getGreen(),
848
chooserColor.getBlue()));
855
protected void buildChooser() {
859
public String getDisplayName() {
860
return "Xoetrope Color Wheel";
864
public Icon getLargeDisplayIcon() {
865
return UIManager.getIcon("ColorChooser.colorWheelIcon");
869
public Icon getSmallDisplayIcon() {
870
return getLargeDisplayIcon();
874
public Dimension getPreferredSize() {
875
return new Dimension(255, 328);
879
public void updateChooser() {
881
Color selected = getColorFromModel();
882
if (selected == null) {
883
setSelectedColors(new ModelColor[0]);
886
ModelColor selectedModelColor = new ModelColor(selected.getRed(),
887
selected.getGreen(), selected.getBlue());
888
setSelectedColors(new ModelColor[] { selectedModelColor });
895
public void installChooserPanel(JColorChooser enclosingChooser) {
896
hasChooser = (enclosingChooser != null);
898
super.installChooserPanel(enclosingChooser);
899
// if runs in the color chooser, set the hue marker
900
this.setDisplayScheme(true);
904
// class------------------------------------------------------
906
* A class that wraps the image of the color wheel and draws markers for the
907
* selected color scheme
909
class ColorWheel extends JLabel {
910
public ColorWheel() {
914
* Draw markers for the selected color scheme
917
public void paintComponent(Graphics g) {
918
super.paintComponent(g);
920
paintWheel((Graphics2D) g);
925
int selIdx = colorScheme;// > 0 ? 1 : 0;
926
int numColours = Math.min(selIdx + 1, 4);
927
for (int i = 0; i < numColours; i++) {
928
double r = (selectedIttenColours[i].H - 90.0) / 360.0 * 2.0
930
x = Math.round(111.0 + 110.0 * Math.cos(r));
931
y = Math.round(111.0 + 110.0 * Math.sin(r));
932
g.setColor(Color.gray);
933
g.fillOval((int) x, (int) y, 4, 4);
934
g.setColor(Color.darkGray);
935
g.drawOval((int) x, (int) y, 4, 4);
940
public void paintWheel(Graphics2D g2d) {
941
// Store the paths for detecting the area with the mouse click.
943
paths = new GeneralPath[ModelColor.NUM_COLOR_RINGS
944
* ModelColor.NUM_SEGMENTS];
946
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
947
RenderingHints.VALUE_ANTIALIAS_ON);
948
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
949
RenderingHints.VALUE_RENDER_QUALITY);
951
ModelColor[][] baseColors = ModelColor.getBaseColors();
953
double width = getWidth() - 1;
954
double center = width / 2.0;
955
ringThickness = width / ((ModelColor.NUM_COLOR_RINGS + 2) * 2);
956
double fontHeight = ringThickness / 2.0;
957
double inset = ringThickness / 2.0;
959
// Paint the outer band
960
g2d.setColor(new Color(228, 228, 228));
961
Arc2D.Double innerArc = new Arc2D.Double(inset, inset, width
962
- inset - inset, width - inset - inset, 0.0, 360.0,
964
Arc2D.Double outerArc = new Arc2D.Double(0.0, 0.0, width, width,
965
360.0, -360.0, Arc2D.OPEN);
966
GeneralPath gp = new GeneralPath();
967
gp.append(innerArc, true);
968
gp.append(outerArc, true);
972
g2d.setColor(Color.black);
973
g2d.setStroke(new BasicStroke(0.3F));
976
// Paint the inner yellow arc
977
g2d.setColor(new Color(255, 253, 220));
978
innerArc = new Arc2D.Double(center - ringThickness / 2.0, center
979
- ringThickness / 2.0, ringThickness, ringThickness, -30.0,
981
outerArc = new Arc2D.Double(center - ringThickness, center
982
- ringThickness, ringThickness * 2, ringThickness * 2,
983
150.0, -180.0, Arc2D.OPEN);
984
gp = new GeneralPath();
985
gp.append(innerArc, true);
986
gp.append(outerArc, true);
990
// Paint the inner blue arc
991
g2d.setColor(new Color(202, 230, 252));
992
innerArc = new Arc2D.Double(center - ringThickness / 2.0, center
993
- ringThickness / 2.0, ringThickness, ringThickness, 150.0,
995
outerArc = new Arc2D.Double(center - ringThickness, center
996
- ringThickness, ringThickness * 2, ringThickness * 2,
997
330.0, -180.0, Arc2D.OPEN);
998
gp = new GeneralPath();
999
gp.append(innerArc, true);
1000
gp.append(outerArc, true);
1005
g2d.setColor(Color.black);
1006
AffineTransform identityTransform = g2d.getTransform();
1007
AffineTransform at = ((AffineTransform) identityTransform.clone());
1008
at.translate(center, center);
1009
at.rotate(Math.PI / 6.0);
1010
g2d.setTransform(at);
1012
gp = new GeneralPath();
1013
gp.moveTo((float) (-ringThickness / 2.0), 0.0F);
1014
gp.lineTo((float) (-ringThickness * 1.2), 0.0F);
1015
gp.lineTo((float) (-ringThickness * 1.2), (float) (-fontHeight));
1016
gp.lineTo((float) (-ringThickness * 1.4),
1017
(float) (-fontHeight + ringThickness * 0.2));
1018
gp.moveTo((float) (-ringThickness * 1.2), (float) (-fontHeight));
1019
gp.lineTo((float) (-ringThickness),
1020
(float) (-fontHeight + ringThickness * 0.2));
1023
gp = new GeneralPath();
1024
gp.moveTo((float) (ringThickness / 2.0), 0.0F);
1025
gp.lineTo((float) (ringThickness * 1.2), 0.0F);
1026
gp.lineTo((float) (ringThickness * 1.2), (float) (fontHeight));
1027
gp.lineTo((float) (ringThickness * 1.4),
1028
(float) (fontHeight - ringThickness * 0.2));
1029
gp.moveTo((float) (ringThickness * 1.2), (float) (fontHeight));
1030
gp.lineTo((float) (ringThickness),
1031
(float) (fontHeight - ringThickness * 0.2));
1034
// Draw the tick marks
1036
double r2 = r1 - fontHeight;
1037
double r3 = r1 - ringThickness / 2.3;
1038
double r4 = r1 + ringThickness / 2.7;
1040
// The angles for cos and sin are in radians
1041
double inc = Math.PI / 12.0;
1042
// double fullArc = Math.PI * 2.0;
1043
g2d.setColor(Color.black);
1044
for (int i = 0; i < ModelColor.NUM_SEGMENTS; i++) {
1045
double angle = i * inc;
1046
double sin = Math.sin(angle);
1047
double cos = Math.cos(angle);
1048
gp = new GeneralPath();
1049
if ((width > 200) && (i % 2 == 0)) {
1050
AttributedString as = new AttributedString(""
1051
+ (((i * 15) + 90) % 360) + "ļæ½");
1052
as.addAttribute(TextAttribute.FAMILY, fontFamily);
1053
as.addAttribute(TextAttribute.SIZE, (float) (fontHeight));
1054
as.addAttribute(TextAttribute.FOREGROUND, Color.black);
1055
at = ((AffineTransform) identityTransform.clone());
1056
at.translate((center + fontHeight / 5.0 + r3 * cos),
1057
(center + r3 * sin));
1058
at.rotate(angle + Math.PI / 2.0);
1059
g2d.setTransform(at);
1060
g2d.drawString(as.getIterator(), 0.0F, 0.0F);
1062
g2d.setTransform(identityTransform);
1063
gp.moveTo((float) (center + r1 * cos), (float) (center + r1
1065
gp.lineTo((float) (center + r2 * cos), (float) (center + r2
1071
// Paint the rings / star
1073
for (int i = 0; i < ModelColor.NUM_COLOR_RINGS; i++) {
1074
double outerX = inset + (ModelColor.NUM_COLOR_RINGS - (i + 1))
1076
double outerW = width - outerX - outerX;
1077
double innerX = outerX + ringThickness;
1078
double innerW = outerW - 2 * ringThickness;
1079
for (int j = 0; j < ModelColor.NUM_SEGMENTS; j++) {
1080
ModelColor modelColor = baseColors[j][i];
1081
modelColor = new ModelColor(modelColor.H,
1082
saturationMultipler * modelColor.S,
1083
brightnessMultipler * modelColor.V);
1084
Color c = new Color(modelColor.getRed(), modelColor
1085
.getGreen(), modelColor.getBlue());
1087
double startAngle = ((82.5 - (j * 15.0)) + 360) % 360.0;
1089
double delta1 = j % 2 == 0 ? arcDelta[i] : -arcDelta[i];
1090
double delta2 = j % 2 == 0 ? arcDelta[i + 1]
1092
innerArc = new Arc2D.Double(innerX, innerX, innerW, innerW,
1093
startAngle + delta1, 15.0 - 2.0 * delta1,
1095
outerArc = new Arc2D.Double(outerX, outerX, outerW, outerW,
1096
startAngle + 15.0 - delta2, -15.0 + 2.0 * delta2,
1098
gp = new GeneralPath();
1099
gp.append(innerArc, true);
1100
gp.append(outerArc, true);
1109
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
1110
RenderingHints.VALUE_ANTIALIAS_OFF);
1111
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
1112
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
1114
double angle = (Math.PI / 6.0) - (Math.PI / 2.0);
1115
double angle2 = angle - 0.055;
1116
double sin = Math.sin(angle2);
1117
double cos = Math.cos(angle2);
1119
AttributedString as = new AttributedString(getLabel(
1120
"Xoetrope.warm", "WARM"));
1121
as.addAttribute(TextAttribute.FAMILY, fontFamily);
1122
as.addAttribute(TextAttribute.SIZE,
1123
(float) (ringThickness / 1.5));
1124
as.addAttribute(TextAttribute.FOREGROUND, new Color(92, 0, 0));
1125
at = ((AffineTransform) identityTransform.clone());
1126
at.translate((center + fontHeight / 5.0 + r4 * cos),
1127
(center + r4 * sin));
1128
at.rotate(angle + Math.PI / 2.0 + 0.05);
1129
g2d.setTransform(at);
1130
g2d.drawString(as.getIterator(), 0.0F, 0.0F);
1133
sin = Math.sin(angle);
1134
cos = Math.cos(angle);
1135
as = new AttributedString(getLabel("Xoetrope.cold", "COLD"));
1136
as.addAttribute(TextAttribute.FAMILY, fontFamily);
1137
as.addAttribute(TextAttribute.SIZE,
1138
(float) (ringThickness / 1.5));
1139
as.addAttribute(TextAttribute.FOREGROUND, new Color(0, 0, 92));
1140
at = ((AffineTransform) identityTransform.clone());
1141
at.translate((center + fontHeight / 5.0 + r4 * cos),
1142
(center + r4 * sin));
1143
at.rotate(angle + Math.PI / 2.0 + 0.05);
1144
g2d.setTransform(at);
1145
g2d.drawString(as.getIterator(), 0.0F, 0.0F);
1148
sin = Math.sin(angle);
1149
cos = Math.cos(angle);
1150
as = new AttributedString(getLabel("Xoetrope.saturation",
1152
as.addAttribute(TextAttribute.FAMILY, fontFamily);
1153
as.addAttribute(TextAttribute.SIZE,
1154
(float) (ringThickness / 1.3));
1155
as.addAttribute(TextAttribute.FOREGROUND, UIManager
1156
.getColor("Label.foreground"));
1157
at = ((AffineTransform) identityTransform.clone());
1158
at.translate((width - fontHeight), (width));
1159
at.rotate(angle + Math.PI / 2.0);
1160
g2d.setTransform(at);
1161
g2d.drawString(as.getIterator(), 0.0F, 0.0F);
1163
String brightnessText = getLabel("Xoetrope.brightness",
1165
as = new AttributedString(brightnessText);
1166
as.addAttribute(TextAttribute.FAMILY, fontFamily);
1167
as.addAttribute(TextAttribute.SIZE,
1168
(float) (ringThickness / 1.3));
1169
as.addAttribute(TextAttribute.FOREGROUND, UIManager
1170
.getColor("Label.foreground"));
1171
at = ((AffineTransform) identityTransform.clone());
1172
at.translate((width - fontHeight), (ringThickness
1173
* brightnessText.length() / 2.3));
1174
at.rotate(angle + Math.PI / 2.0);
1175
g2d.setTransform(at);
1176
g2d.drawString(as.getIterator(), 0.0F, 0.0F);
1178
g2d.setTransform(identityTransform);
1180
if (showRollovers) {
1181
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
1182
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
1183
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
1184
RenderingHints.VALUE_ANTIALIAS_ON);
1185
if (rolloverPath != null) {
1186
g2d.setColor(rolloverColor);
1187
g2d.setStroke(new BasicStroke(1.5F));
1188
g2d.draw(rolloverPath);
1190
if (selectedPath != null) {
1191
g2d.setColor(selectedColor);
1192
g2d.setStroke(new BasicStroke(1.0F));
1193
g2d.draw(selectedPath);
1199
// End ColorWheel inner class
1200
// ------------------------------------------------
1202
// ----------------------------------------------------------------------------
1203
private class ColorDocumentListener implements DocumentListener {
1204
private JTextField originator;
1206
private static final String MARKER = "Xoetrope.XUI.ColorWheel.DocumentEvent";
1208
public ColorDocumentListener(JTextField originator) {
1209
this.originator = originator;
1213
* This method is called after an insert into the document
1216
public void insertUpdate(DocumentEvent evt) {
1221
* This method is called after a removal from the document
1224
public void removeUpdate(DocumentEvent evt) {
1229
* This method is called after one or more attributes have changed. This
1230
* method is not called when characters are inserted with attributes.
1233
public void changedUpdate(DocumentEvent evt) {
1237
public void synchronize(DocumentEvent evt) {
1238
boolean _hasAllValues = true;
1239
if (hueEdit.getText().length() == 0)
1240
_hasAllValues = false;
1241
if (brightEdit.getText().length() == 0)
1242
_hasAllValues = false;
1243
if (satEdit.getText().length() == 0)
1244
_hasAllValues = false;
1246
final boolean hasAllValues = _hasAllValues;
1247
SwingUtilities.invokeLater(new Runnable() {
1250
useWebColors.setEnabled(hasAllValues);
1251
decimalRGB.setEnabled(hasAllValues);
1255
SwingUtilities.invokeLater(new Runnable() {
1258
// the below use of client property is to prevent
1259
// infinite event loop (resetColor evetually changes
1261
if (hasAllValues && originator.hasFocus()) {
1262
if (Boolean.TRUE.equals(originator
1263
.getClientProperty(MARKER))) {
1264
originator.putClientProperty(MARKER, null);
1266
originator.putClientProperty(MARKER, Boolean.TRUE);
1270
// repaint for synchronizing the hue marker
1272
imagePicker.repaint();
1278
// ----------------------------------------------------------------------------
1279
public static void setLabelBundle(ResourceBundle labelBundle) {
1280
ColorWheelPanel.labelBundle = labelBundle;
1283
private static String getLabel(String labelName, String defaultValue) {
1284
if (ColorWheelPanel.labelBundle == null)
1285
return defaultValue;
1288
return ColorWheelPanel.labelBundle.getString(labelName);
1289
} catch (MissingResourceException mre) {
1290
return defaultValue;
1295
* Show a popup menu with the list of system colors
1298
* the location to display the popup
1300
private void showSystemColorList(Point p) {
1301
JPopupMenu popupMenu = new JPopupMenu();
1302
String[] systemColors = { "activeCaption", "desktop",
1303
"activeCaptionText", "activeCaptionBorder", "inactiveCaption",
1304
"inactiveCaptionText", "inactiveCaptionBorder", "window",
1305
"windowBorder", "windowText", "menu", "menuText", "text",
1306
"textText", "textHighlight", "textHighlightText",
1307
"textInactiveText", "control", "controlText",
1308
"controlHighlight", "controlLtHighlight", "controlShadow",
1309
"controlDkShadow", "scrollbar", "info", "infoText", "white",
1310
"lightGray", "gray", "darkGray", "black", "red", "pink",
1311
"orange", "yellow", "green", "magenta", "cyan", "blue" };
1313
for (int i = 0; i < systemColors.length; i++) {
1314
if (systemColors[i].equals("white")) {
1315
popupMenu.addSeparator();
1319
JMenuItem mi = new JMenuItem(systemColors[i]);
1320
mi.addActionListener(this);
1322
BufferedImage image = new BufferedImage(8, 8,
1323
BufferedImage.TYPE_INT_RGB);
1324
Graphics g = image.getGraphics();
1325
g.setColor(getSystemColor(systemColors[i]));
1326
g.fillRect(0, 0, 8, 8);
1327
g.setColor(SystemColor.windowBorder);
1328
g.drawRect(0, 0, 7, 7);
1330
Icon icon = new ImageIcon(image);
1335
popupMenu.show(this, p.x, p.y);
1339
* Get the named system color
1343
* @return the color value or null if the name is not recognized
1345
public Color getSystemColor(String temp) {
1347
if (temp.equals("activeCaption"))
1348
clr = SystemColor.activeCaption;
1349
else if (temp.equals("desktop"))
1350
clr = SystemColor.desktop;
1351
else if (temp.equals("activeCaptionText"))
1352
clr = SystemColor.activeCaptionText;
1353
else if (temp.equals("activeCaptionBorder"))
1354
clr = SystemColor.activeCaptionBorder;
1355
else if (temp.equals("inactiveCaption"))
1356
clr = SystemColor.inactiveCaption;
1357
else if (temp.equals("inactiveCaptionText"))
1358
clr = SystemColor.inactiveCaptionText;
1359
else if (temp.equals("inactiveCaptionBorder"))
1360
clr = SystemColor.inactiveCaptionBorder;
1361
else if (temp.equals("window"))
1362
clr = SystemColor.window;
1363
else if (temp.equals("windowBorder"))
1364
clr = SystemColor.windowBorder;
1365
else if (temp.equals("windowText"))
1366
clr = SystemColor.windowText;
1367
else if (temp.equals("menu"))
1368
clr = SystemColor.menu;
1369
else if (temp.equals("menuText"))
1370
clr = SystemColor.menuText;
1371
else if (temp.equals("text"))
1372
clr = SystemColor.text;
1373
else if (temp.equals("textText"))
1374
clr = SystemColor.textText;
1375
else if (temp.equals("textHighlight"))
1376
clr = SystemColor.textHighlight;
1377
else if (temp.equals("textHighlightText"))
1378
clr = SystemColor.textHighlightText;
1379
else if (temp.equals("textInactiveText"))
1380
clr = SystemColor.textInactiveText;
1381
else if (temp.equals("control"))
1382
clr = SystemColor.control;
1383
else if (temp.equals("controlText"))
1384
clr = SystemColor.controlText;
1385
else if (temp.equals("controlHighlight"))
1386
clr = SystemColor.controlHighlight;
1387
else if (temp.equals("controlLtHighlight"))
1388
clr = SystemColor.controlLtHighlight;
1389
else if (temp.equals("controlShadow"))
1390
clr = SystemColor.controlShadow;
1391
else if (temp.equals("controlDkShadow"))
1392
clr = SystemColor.controlDkShadow;
1393
else if (temp.equals("scrollbar"))
1394
clr = SystemColor.scrollbar;
1395
else if (temp.equals("info"))
1396
clr = SystemColor.info;
1397
else if (temp.equals("infoText"))
1398
clr = SystemColor.infoText;
1400
else if (temp.equals("white"))
1402
else if (temp.equals("lightGray"))
1403
clr = Color.lightGray;
1404
else if (temp.equals("gray"))
1406
else if (temp.equals("darkGray"))
1407
clr = Color.darkGray;
1408
else if (temp.equals("black"))
1410
else if (temp.equals("red"))
1412
else if (temp.equals("pink"))
1414
else if (temp.equals("orange"))
1416
else if (temp.equals("yellow"))
1418
else if (temp.equals("green"))
1420
else if (temp.equals("magenta"))
1421
clr = Color.magenta;
1422
else if (temp.equals("cyan"))
1424
else if (temp.equals("blue"))
1431
* Should the color wheeel's colors be adjusted
1433
* @return true if the colors should change to match the brightness and
1436
private boolean shouldAdjustWheel() {
1437
if (adjustWheel == NEVER_ADJUST)
1439
else if (adjustWheel == ALWAYS_ADJUST)
1441
else if (ctrlKeyDown)
1448
* Get the adjust color wheel flag.
1450
* @return the adjustment mode
1452
public int getAdjustWheel() {
1457
* Set the adjust color wheel flag.
1460
* the color wheel's new adjustment mode ( CTRL_ADJUST |
1461
* ALWAYS_ADJUST | NEVER_ADJUST );
1463
public void setAdjustWheel(int state) {
1464
adjustWheel = state;
1468
* Get the adjust rollover color flag.
1470
* @return the adjustment mode
1472
public boolean getRollover() {
1473
return adjustRollover;
1477
* Set the adjust rollover color flag.
1480
* the rollover's new adjustment mode ( true | false );
1482
public void setRollover(boolean state) {
1483
adjustRollover = state;
1487
* Reset the brightness and saturation multipliers for the ColorWheel.
1489
public void resetColorWheel() {
1490
saturationMultipler = brightnessMultipler = 1.0;
b'\\ No newline at end of file'