1 package ini
.trakem2
.utils
;
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();
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();
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() {
58 public void mouseWheelMoved(MouseWheelEvent mwe
) {
59 Component source
= (Component
) mwe
.getSource();
61 Setter s
= setters
.get(source
);
62 if (s
instanceof NumericalSetter
) {
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() {
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
>();
88 public void addMessage(String text
) {
89 JLabel label
= new JLabel(text
);
92 c
.anchor
= GridBagConstraints
.NORTHWEST
;
96 c
.fill
= GridBagConstraints
.NONE
;
97 bl
.setConstraints(label
, c
);
101 public void bottomPadding() {
104 c
.anchor
= GridBagConstraints
.NORTHWEST
;
105 c
.fill
= GridBagConstraints
.BOTH
;
108 JPanel space
= new JPanel();
109 bl
.setConstraints(space
, c
);
113 /** The left-side label of a field. */
114 private void addLabel(String label
) {
117 JLabel l
= new JLabel(label
);
118 c
.anchor
= GridBagConstraints
.NORTHEAST
;
123 c
.fill
= GridBagConstraints
.NONE
;
124 bl
.setConstraints(l
, c
);
128 /** The right-side field of a label. */
129 private void addField(Component comp
, Setter setter
) {
132 c
.anchor
= GridBagConstraints
.NORTHWEST
;
135 c
.fill
= GridBagConstraints
.HORIZONTAL
;
136 bl
.setConstraints(comp
, c
);
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
) {
159 JTextField tval
= new JTextField(value
, 7);
160 numeric_fields
.add(tval
);
161 addField(tval
, setter
);
162 tval
.addKeyListener(kl
);
163 tval
.addMouseWheelListener(mwl
);
167 public JCheckBox
addCheckbox(String label
, boolean selected
) {
168 return addCheckbox(label
, selected
, null);
171 public JCheckBox
addCheckbox(String label
, boolean selected
, Setter setter
) {
173 JCheckBox cb
= new JCheckBox();
174 cb
.setSelected(selected
);
177 addField(cb
, setter
);
178 cb
.addActionListener(tl
);
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
) {
188 JComboBox choice
= new JComboBox(items
);
189 choice
.setBackground(Color
.white
);
190 choice
.setSelectedIndex(selected
);
191 choice
.addActionListener(tl
);
193 addField(choice
, setter
);
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
) {
250 public Setter(Object ob
, String field
, Runnable reaction
) {
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
) {
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
);
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
);
287 Utils
.log2("set value of " + field
+ " to " + f
.get(ob
));
289 if (null != reaction
) reaction
.run();
293 abstract protected Object
getValue(Component source
, int inc
);
296 static public class IntSetter
extends NumericalSetter
{
297 public IntSetter(Object ob
, String 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
;
317 static public class DoubleSetter
extends NumericalSetter
{
318 public DoubleSetter(Object ob
, String 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
;
338 static public class FloatSetter
extends NumericalSetter
{
339 public FloatSetter(Object ob
, String 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
;
359 static public class BooleanSetter
extends Setter
{
360 public BooleanSetter(Object ob
, String 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
) {
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
) {
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
) {
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
) {
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();