Skip to content

Commit ff1fa86

Browse files
committed
Add focus listener to JSpinner text
This (mostly) ensures the text of a JSpinner is selected on focus. On OSX it seems to always work with tabs, and mostly work with mouse clicking. However there does seem to be a race condition where the text selection can be lost, presumably from the JSPinner firing a validation event after the text field's selection has been processed. See #12 for future work.
1 parent 97e63cf commit ff1fa86

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/main/java/org/scijava/ui/swing/widget/SwingNumberWidget.java

+49
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@
3131
package org.scijava.ui.swing.widget;
3232

3333
import java.awt.Adjustable;
34+
import java.awt.Component;
3435
import java.awt.Dimension;
3536
import java.awt.event.AdjustmentEvent;
3637
import java.awt.event.AdjustmentListener;
38+
import java.awt.event.FocusEvent;
39+
import java.awt.event.FocusListener;
3740
import java.math.BigDecimal;
3841
import java.math.BigInteger;
3942
import java.text.DecimalFormat;
@@ -44,11 +47,14 @@
4447
import javax.swing.JScrollBar;
4548
import javax.swing.JSlider;
4649
import javax.swing.JSpinner;
50+
import javax.swing.JTextField;
4751
import javax.swing.SpinnerNumberModel;
4852
import javax.swing.event.ChangeEvent;
4953
import javax.swing.event.ChangeListener;
5054

55+
import org.scijava.plugin.Parameter;
5156
import org.scijava.plugin.Plugin;
57+
import org.scijava.thread.ThreadService;
5258
import org.scijava.util.NumberUtils;
5359
import org.scijava.widget.InputWidget;
5460
import org.scijava.widget.NumberWidget;
@@ -64,6 +70,9 @@ public class SwingNumberWidget extends SwingInputWidget<Number> implements
6470
NumberWidget<JPanel>, AdjustmentListener, ChangeListener
6571
{
6672

73+
@Parameter
74+
private ThreadService threadService;
75+
6776
private JScrollBar scrollBar;
6877
private JSlider slider;
6978
private JSpinner spinner;
@@ -121,6 +130,9 @@ else if (model.isStyle(NumberWidget.SLIDER_STYLE)) {
121130
final SpinnerNumberModel spinnerModel =
122131
new SpinnerNumberModelFactory().createModel(value, min, max, stepSize);
123132
spinner = new JSpinner(spinnerModel);
133+
134+
fixSpinnerFocus();
135+
124136
fixSpinner(type);
125137
setToolTip(spinner);
126138
getComponent().add(spinner);
@@ -200,6 +212,43 @@ private void fixSpinner(final Class<?> type) {
200212
}
201213
}
202214

215+
/**
216+
* Adapted from <a href=
217+
* "http://stackoverflow.com/q/20971050/1027800"
218+
* >this SO post</a>.
219+
*
220+
* Tries to ensure that the text of a {@link JSpinner} is selected when it
221+
* has focus.
222+
*/
223+
private void fixSpinnerFocus() {
224+
for (final Component c : spinner.getEditor().getComponents()) {
225+
if (JTextField.class.isAssignableFrom(c.getClass())) {
226+
c.addFocusListener(new FocusListener() {
227+
228+
@Override
229+
public void focusGained(final FocusEvent e) {
230+
queueSelection();
231+
}
232+
233+
@Override
234+
public void focusLost(final FocusEvent e) {
235+
queueSelection();
236+
}
237+
238+
private void queueSelection() {
239+
threadService.queue(new Runnable() {
240+
@Override
241+
public void run() {
242+
((JTextField) c).selectAll();
243+
}
244+
});
245+
}
246+
247+
});
248+
}
249+
}
250+
}
251+
203252
/** Sets slider values to match the spinner. */
204253
private void syncSliders() {
205254
if (slider != null) {

0 commit comments

Comments
 (0)