Use internal SNAPSHOT couplings again
[trakem2.git] / TrakEM2_ / src / main / java / ini / trakem2 / utils / OptionPanel.java
blob15bd175fe7dc11d38ace1f129e2ba69054f7f2ea
1 package ini.trakem2.utils;
3 import java.awt.Color;
4 import java.awt.Component;
5 import java.awt.GridBagConstraints;
6 import java.awt.GridBagLayout;
7 import java.awt.event.ActionEvent;
8 import java.awt.event.ActionListener;
9 import java.awt.event.KeyAdapter;
10 import java.awt.event.KeyEvent;
11 import java.awt.event.KeyListener;
12 import java.awt.event.MouseWheelEvent;
13 import java.awt.event.MouseWheelListener;
14 import java.lang.reflect.Field;
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
19 import javax.swing.JCheckBox;
20 import javax.swing.JComboBox;
21 import javax.swing.JLabel;
22 import javax.swing.JPanel;
23 import javax.swing.JTextField;
24 import javax.swing.text.JTextComponent;
26 public class OptionPanel extends JPanel {
28 private static final long serialVersionUID = 1L;
29 private GridBagLayout bl = new GridBagLayout();
30 private GridBagConstraints c = new GridBagConstraints();
32 private ActionListener tl = new ActionListener() {
33 public void actionPerformed(ActionEvent ae) {
34 Component source = (Component) ae.getSource();
35 try {
36 Setter s = setters.get(source);
37 if (null != s) s.setFrom(source);
38 } catch (Exception e) {
39 Utils.log2("Invalid value!");
44 private KeyListener kl = new KeyAdapter() {
45 public void keyReleased(KeyEvent ke) {
46 Component source = (Component) ke.getSource();
47 try {
48 Setter s = setters.get(source);
49 if (null != s) s.setFrom(source);
50 } catch (Throwable t) {
51 Utils.logAll("Invalid value " + ((JTextField)source).getText());
56 private MouseWheelListener mwl = new MouseWheelListener() {
57 @Override
58 public void mouseWheelMoved(MouseWheelEvent mwe) {
59 Component source = (Component) mwe.getSource();
60 try {
61 Setter s = setters.get(source);
62 if (s instanceof NumericalSetter) {
63 if (null != s) {
64 // Update the value of the field and also of the JTextField
65 ((JTextField)source).setText(((NumericalSetter)s).setFrom(source, mwe.getWheelRotation()).toString());
68 } catch (Throwable t) {
69 Utils.logAll("Invalid value " + ((JTextField)source).getText());
74 public OptionPanel() {
75 super();
76 setLayout(bl);
77 c.ipady = 10;
80 private List<JTextField> numeric_fields = new ArrayList<JTextField>();
81 private List<JCheckBox> checkboxes = new ArrayList<JCheckBox>();
82 private List<JComboBox> choices = new ArrayList<JComboBox>();
83 private List<Component> all = new ArrayList<Component>();
84 private HashMap<Component,Setter> setters = new HashMap<Component,Setter>();
86 private int rows = 0;
88 public void addMessage(String text) {
89 JLabel label = new JLabel(text);
90 c.gridy = rows++;
91 c.gridx = 0;
92 c.anchor = GridBagConstraints.NORTHWEST;
93 c.weightx = 1;
94 c.weighty = 0;
95 c.gridwidth = 2;
96 c.fill = GridBagConstraints.NONE;
97 bl.setConstraints(label, c);
98 add(label);
101 public void bottomPadding() {
102 c.gridy = rows++;
103 c.gridx = 0;
104 c.anchor = GridBagConstraints.NORTHWEST;
105 c.fill = GridBagConstraints.BOTH;
106 c.weightx = 1;
107 c.weighty = 1;
108 JPanel space = new JPanel();
109 bl.setConstraints(space, c);
110 add(space);
113 /** The left-side label of a field. */
114 private void addLabel(String label) {
115 c.gridy = rows++;
116 c.gridx = 0;
117 JLabel l = new JLabel(label);
118 c.anchor = GridBagConstraints.NORTHEAST;
119 c.weightx = 1;
120 c.weighty = 0;
121 c.ipadx = 10;
122 c.gridwidth = 1;
123 c.fill = GridBagConstraints.NONE;
124 bl.setConstraints(l, c);
125 add(l);
128 /** The right-side field of a label. */
129 private void addField(Component comp, Setter setter) {
130 c.gridx = 1;
131 c.weightx = 0;
132 c.anchor = GridBagConstraints.NORTHWEST;
133 c.ipadx = 0;
134 c.gridwidth = 1;
135 c.fill = GridBagConstraints.HORIZONTAL;
136 bl.setConstraints(comp, c);
137 add(comp);
138 setters.put(comp, setter);
141 public JTextField addNumericField(String label, double value, int digits) {
142 return addNumericField(label, value, digits, null);
145 public JTextField addNumericField(String label, double value, int digits, Setter setter) {
146 return addNumericField(label, Utils.cutNumber(value, digits), setter);
149 public JTextField addNumericField(String label, int value) {
150 return addNumericField(label, value, null);
153 public JTextField addNumericField(String label, int value, Setter setter) {
154 return addNumericField(label, Integer.toString(value), setter);
157 private JTextField addNumericField(String label, String value, Setter setter) {
158 addLabel(label);
159 JTextField tval = new JTextField(value, 7);
160 numeric_fields.add(tval);
161 addField(tval, setter);
162 tval.addKeyListener(kl);
163 tval.addMouseWheelListener(mwl);
164 return tval;
167 public JCheckBox addCheckbox(String label, boolean selected) {
168 return addCheckbox(label, selected, null);
171 public JCheckBox addCheckbox(String label, boolean selected, Setter setter) {
172 addLabel(label);
173 JCheckBox cb = new JCheckBox();
174 cb.setSelected(selected);
175 checkboxes.add(cb);
176 all.add(cb);
177 addField(cb, setter);
178 cb.addActionListener(tl);
179 return cb;
182 public JComboBox addChoice(String label, String[] items, int selected) {
183 return addChoice(label, items, selected, null);
186 public JComboBox addChoice(String label, String[] items, int selected, Setter setter) {
187 addLabel(label);
188 JComboBox choice = new JComboBox(items);
189 choice.setBackground(Color.white);
190 choice.setSelectedIndex(selected);
191 choice.addActionListener(tl);
192 all.add(choice);
193 addField(choice, setter);
194 return choice;
199 public List<JTextField> getNumericFields() {
200 return new ArrayList<JTextField>(numeric_fields);
203 /** May throw IllegalArgumentException or NumberFormatException */
204 public double getNumber(int index) throws Exception {
205 check(numeric_fields, index);
206 return Double.parseDouble(numeric_fields.get(index).getText());
209 public List<JCheckBox> getCheckBoxes() {
210 return new ArrayList<JCheckBox>(checkboxes);
213 /** May throw IllegalArgumentException */
214 public boolean getCheckbox(int index) throws Exception {
215 check(checkboxes, index);
216 return checkboxes.get(index).isSelected();
219 public List<JComboBox> getChoices() {
220 return new ArrayList<JComboBox>(choices);
223 public int getChoiceIndex(int index) throws Exception {
224 check(choices, index);
225 return choices.get(index).getSelectedIndex();
228 public String getChoiceString(int index) throws Exception {
229 return getChoiceObject(index).toString();
232 public Object getChoiceObject(int index) throws Exception {
233 check(choices, index);
234 return choices.get(index).getSelectedItem();
238 private void check(List<?> list, int index) throws Exception {
239 if (index < 0 || index > list.size() -1) throw new IllegalArgumentException("Index out of bounds: " + index);
242 static abstract public class Setter {
243 protected final Object ob;
244 protected final String field;
245 protected Runnable reaction;
246 public Setter(Object ob, String field) {
247 this.ob = ob;
248 this.field = field;
250 public Setter(Object ob, String field, Runnable reaction) {
251 this(ob, field);
252 this.reaction = reaction;
254 /** Will set the field if no exception is thrown when reading it. */
255 public void setFrom(Component source) throws Exception {
256 Field f = ob.getClass().getDeclaredField(field);
257 f.setAccessible(true);
258 f.set(ob, getValue(source));
260 //Utils.log2("set value of " + field + " to " + f.get(ob));
262 if (null != reaction) reaction.run();
264 abstract public Object getValue(Component source);
267 static abstract public class NumericalSetter extends Setter {
268 protected int min = Integer.MIN_VALUE,
269 max = Integer.MAX_VALUE;
270 public NumericalSetter(Object ob, String field) {
271 super(ob, field);
273 public NumericalSetter(Object ob, String field, Runnable reaction) {
274 super(ob, field, reaction);
276 public NumericalSetter(Object ob, String field, Runnable reaction, int min, int max) {
277 super(ob, field, reaction);
278 this.min = min;
279 this.max = max;
281 public Object setFrom(Component source, int inc) throws Exception {
282 Field f = ob.getClass().getDeclaredField(field);
283 f.setAccessible(true);
284 Object val = getValue(source, inc);
285 f.set(ob, val);
287 Utils.log2("set value of " + field + " to " + f.get(ob));
289 if (null != reaction) reaction.run();
291 return val;
293 abstract protected Object getValue(Component source, int inc);
296 static public class IntSetter extends NumericalSetter {
297 public IntSetter(Object ob, String field) {
298 super(ob, field);
300 public IntSetter(Object ob, String field, Runnable reaction) {
301 super(ob, field, reaction);
303 public IntSetter(Object ob, String field, Runnable reaction, int min, int max) {
304 super(ob, field, reaction, min, max);
306 public Object getValue(Component source) {
307 return (int) Double.parseDouble(((JTextField)source).getText());
309 protected Object getValue(Component source, int inc) {
310 int val = ((int) Double.parseDouble(((JTextField)source).getText())) + inc;
311 if (val < this.min) return this.min;
312 if (val > this.max) return this.max;
313 return val;
317 static public class DoubleSetter extends NumericalSetter {
318 public DoubleSetter(Object ob, String field) {
319 super(ob, field);
321 public DoubleSetter(Object ob, String field, Runnable reaction) {
322 super(ob, field, reaction);
324 public DoubleSetter(Object ob, String field, Runnable reaction, int min, int max) {
325 super(ob, field, reaction, min, max);
327 public Object getValue(Component source) {
328 return Double.parseDouble(((JTextField)source).getText());
330 protected Object getValue(Component source, int inc) {
331 double val = Double.parseDouble(((JTextField)source).getText()) + inc;
332 if (val < this.min) return (double)this.min;
333 if (val > this.max) return (double)this.max;
334 return val;
338 static public class FloatSetter extends NumericalSetter {
339 public FloatSetter(Object ob, String field) {
340 super(ob, field);
342 public FloatSetter(Object ob, String field, Runnable reaction) {
343 super(ob, field, reaction);
345 public FloatSetter(Object ob, String field, Runnable reaction, int min, int max) {
346 super(ob, field, reaction, min, max);
348 public Object getValue(Component source) {
349 return Float.parseFloat(((JTextField)source).getText());
351 public Object getValue(Component source, int inc) {
352 float val = Float.parseFloat(((JTextField)source).getText()) + inc;
353 if (val < this.min) return (float)this.min;
354 if (val > this.max) return (float)this.max;
355 return val;
359 static public class BooleanSetter extends Setter {
360 public BooleanSetter(Object ob, String field) {
361 super(ob, field);
363 public BooleanSetter(Object ob, String field, Runnable reaction) {
364 super(ob, field, reaction);
366 public Object getValue(Component source) {
367 return ((JCheckBox)source).isSelected();
371 static public class StringSetter extends Setter {
372 public StringSetter(Object ob, String field) {
373 super(ob, field);
375 public StringSetter(Object ob, String field, Runnable reaction) {
376 super(ob, field, reaction);
378 public Object getValue(Component source) {
379 return ((JTextComponent)source).getText();
383 static public class ChoiceIntSetter extends Setter {
384 public ChoiceIntSetter(Object ob, String field) {
385 super(ob, field);
387 public ChoiceIntSetter(Object ob, String field, Runnable reaction) {
388 super(ob, field, reaction);
390 public Object getValue(Component source) {
391 return ((JComboBox)source).getSelectedIndex();
395 static public class ChoiceStringSetter extends Setter {
396 public ChoiceStringSetter(Object ob, String field) {
397 super(ob, field);
399 public ChoiceStringSetter(Object ob, String field, Runnable reaction) {
400 super(ob, field, reaction);
402 public Object getValue(Component source) {
403 return ((JComboBox)source).getSelectedItem().toString();
407 static public class ChoiceObjectSetter extends Setter {
408 public ChoiceObjectSetter(Object ob, String field) {
409 super(ob, field);
411 public ChoiceObjectSetter(Object ob, String field, Runnable reaction) {
412 super(ob, field, reaction);
414 public Object getValue(Component source) {
415 return ((JComboBox)source).getSelectedItem();