Skip to content

Commit 24463c8

Browse files
committed
Add SwingColorAlphaWidget
* this makes it possible to use parameters of type ColorRGBA
1 parent ac3cbb1 commit 24463c8

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*
2+
* #%L
3+
* SciJava UI components for Java Swing.
4+
* %%
5+
* Copyright (C) 2010 - 2017 Board of Regents of the University of
6+
* Wisconsin-Madison.
7+
* %%
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
13+
* 2. Redistributions in binary form must reproduce the above copyright notice,
14+
* this list of conditions and the following disclaimer in the documentation
15+
* and/or other materials provided with the distribution.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
21+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
* #L%
29+
*/
30+
31+
package org.scijava.ui.swing.widget;
32+
33+
import org.scijava.plugin.Plugin;
34+
import org.scijava.ui.awt.AWTColors;
35+
import org.scijava.util.ColorRGBA;
36+
import org.scijava.widget.InputWidget;
37+
import org.scijava.widget.WidgetModel;
38+
39+
import javax.swing.*;
40+
import javax.swing.colorchooser.AbstractColorChooserPanel;
41+
import java.awt.*;
42+
import java.awt.event.ActionEvent;
43+
import java.awt.event.ActionListener;
44+
import java.awt.image.BufferedImage;
45+
import java.util.Arrays;
46+
import java.util.Comparator;
47+
48+
/**
49+
* Swing implementation of color chooser widget including alpha.
50+
*
51+
* @author Curtis Rueden
52+
*/
53+
@Plugin(type = InputWidget.class)
54+
public class SwingColorAlphaWidget extends SwingInputWidget<ColorRGBA> implements
55+
ActionListener, InputWidget<ColorRGBA, JPanel>
56+
{
57+
58+
private static final int SWATCH_WIDTH = 64, SWATCH_HEIGHT = 16;
59+
60+
private static final String HSB_CLASS_NAME =
61+
"javax.swing.colorchooser.DefaultHSBChooserPanel";
62+
63+
protected static final String RGB_CLASS_NAME =
64+
"javax.swing.colorchooser.DefaultRGBChooserPanel";
65+
66+
protected static final String SWATCHES_CLASS_NAME =
67+
"javax.swing.colorchooser.DefaultSwatchChooserPanel";
68+
69+
private JButton choose;
70+
private Color color;
71+
72+
// -- ActionListener methods --
73+
74+
@Override
75+
public void actionPerformed(final ActionEvent e) {
76+
final Color choice = showColorDialog(choose, "Select a color", color);
77+
if (choice == null) return;
78+
color = choice;
79+
updateModel();
80+
refreshWidget();
81+
}
82+
83+
// -- InputWidget methods --
84+
85+
@Override
86+
public ColorRGBA getValue() {
87+
return AWTColors.getColorRGBA(color);
88+
}
89+
90+
// -- WrapperPlugin methods --
91+
92+
@Override
93+
public void set(final WidgetModel model) {
94+
super.set(model);
95+
96+
getComponent().setLayout(new BoxLayout(getComponent(), BoxLayout.X_AXIS));
97+
98+
choose = new JButton() {
99+
100+
@Override
101+
public Dimension getMaximumSize() {
102+
return getPreferredSize();
103+
}
104+
};
105+
setToolTip(choose);
106+
getComponent().add(choose);
107+
choose.addActionListener(this);
108+
109+
refreshWidget();
110+
}
111+
112+
// -- Typed methods --
113+
114+
@Override
115+
public boolean supports(final WidgetModel model) {
116+
return super.supports(model) && model.isType(ColorRGBA.class);
117+
}
118+
119+
// -- Utility methods --
120+
121+
/**
122+
* This method is identical to
123+
* {@link JColorChooser#showDialog(Component, String, Color)} except that it
124+
* reorders the panels of the color chooser to be more desirable. It uses
125+
* (HSB, RGB, Swatches) rather than the default of (Swatches, HSB, RGB).
126+
*/
127+
public static Color showColorDialog(final Component component,
128+
final String title, final Color initialColor) throws HeadlessException
129+
{
130+
final JColorChooser pane = createColorChooser(initialColor);
131+
132+
class ColorTracker implements ActionListener {
133+
134+
private final JColorChooser chooser;
135+
private Color color;
136+
137+
public ColorTracker(final JColorChooser c) {
138+
chooser = c;
139+
}
140+
141+
@Override
142+
public void actionPerformed(final ActionEvent e) {
143+
color = chooser.getColor();
144+
}
145+
146+
public Color getColor() {
147+
return color;
148+
}
149+
}
150+
final ColorTracker ok = new ColorTracker(pane);
151+
152+
final JDialog dialog =
153+
JColorChooser.createDialog(component, title, true, pane, ok, null);
154+
155+
dialog.setVisible(true);
156+
157+
return ok.getColor();
158+
}
159+
160+
// -- Helper methods --
161+
162+
/**
163+
* Creates a new {@link JColorChooser} with panels in a desirable order.
164+
* <p>
165+
* All of this code exists solely to reorder the panels from (Swatches, HSB,
166+
* RGB) to (HSB, RGB, Swatches) since we believe the HSB tab is the most
167+
* commonly useful.
168+
* </p>
169+
*/
170+
private static JColorChooser createColorChooser(final Color initialColor) {
171+
final JColorChooser chooser =
172+
new JColorChooser(initialColor != null ? initialColor : Color.white);
173+
174+
// get the list of panels
175+
final AbstractColorChooserPanel[] panels =
176+
chooser.getChooserPanels().clone();
177+
178+
// sort panels into the desired order
179+
Arrays.sort(panels, new Comparator<Object>() {
180+
181+
@Override
182+
public int compare(final Object o1, final Object o2) {
183+
return value(o1) - value(o2);
184+
}
185+
186+
private int value(final Object o) {
187+
final String className = o.getClass().getName();
188+
if (className.equals(HSB_CLASS_NAME)) return 1;
189+
if (className.equals(RGB_CLASS_NAME)) return 2;
190+
if (className.equals(SWATCHES_CLASS_NAME)) return 3;
191+
return 4;
192+
}
193+
});
194+
195+
// reset the panels to match the sorted list
196+
chooser.setChooserPanels(panels);
197+
198+
return chooser;
199+
}
200+
201+
// -- AbstractUIInputWidget methods ---
202+
203+
@Override
204+
public void doRefresh() {
205+
final ColorRGBA value = (ColorRGBA) get().getValue();
206+
color = AWTColors.getColor(value);
207+
208+
final BufferedImage image =
209+
new BufferedImage(SWATCH_WIDTH, SWATCH_HEIGHT, BufferedImage.TYPE_INT_RGB);
210+
final Graphics g = image.getGraphics();
211+
g.setColor(color);
212+
g.fillRect(0, 0, image.getWidth(), image.getHeight());
213+
g.dispose();
214+
final ImageIcon icon = new ImageIcon(image);
215+
choose.setIcon(icon);
216+
}
217+
}

0 commit comments

Comments
 (0)