Skip to content

Commit

Permalink
Improve dialog
Browse files Browse the repository at this point in the history
* Focus on row spinner upon opening of the settings dialog.
* Select the content of the spinner fields when they gain focues.
* Update preview when field contents change

Fixes #6.
  • Loading branch information
jdhoek committed Dec 23, 2019
1 parent d59415e commit 74b5402
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 9 deletions.
9 changes: 7 additions & 2 deletions src/nl/jeroenhoek/josm/gridify/ui/GridSizePanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public GridSizePanel(ChangeCallback changeCallback, int rows, int columns) {
this.columns = columns;
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

spinnerRows = new PositiveSpinner(rows);
spinnerColumns = new PositiveSpinner(columns);
spinnerRows = new PositiveSpinner(rows, this::setRowCount);
spinnerColumns = new PositiveSpinner(columns, this::setColumnCount);
JLabel xLabel = new JLabel("×");
xLabel.setFont(new Font("Monospaced", Font.PLAIN, 18));

Expand Down Expand Up @@ -70,6 +70,11 @@ void nudgeColumnCount(Nudge direction) {
}
}

@Override
public boolean requestFocusInWindow() {
return this.spinnerRows.requestFocusInWindow();
}

public int getRowCount() {
return this.rows;
}
Expand Down
2 changes: 2 additions & 0 deletions src/nl/jeroenhoek/josm/gridify/ui/GridifySettingsDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ public void setupDialog() {
setDefaultButton(1);

super.setupDialog();

gridSizePanel.requestFocusInWindow();
}

@Override
Expand Down
101 changes: 94 additions & 7 deletions src/nl/jeroenhoek/josm/gridify/ui/PositiveSpinner.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
// License: GPL. For details, see LICENSE file.
package nl.jeroenhoek.josm.gridify.ui;

import javax.swing.JFormattedTextField;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.text.ParseException;
import java.util.Objects;

/**
* A {@link JSpinner} limited to a range of 1 to 1000. This class also adds a mouse wheel listener allowing users to
* scroll the value up or down.
*/
public class PositiveSpinner extends JSpinner {
public PositiveSpinner(int defaultValue) {

private final JFormattedTextField field;
private final ValueChanged changeCallback;
private Integer lastValue;

public PositiveSpinner(int defaultValue, ValueChanged changeCallback) {
super(new SpinnerNumberModel(defaultValue, 1, 1000, 1));
JFormattedTextField field = ((DefaultEditor) getEditor()).getTextField();
this.changeCallback = changeCallback;
DefaultEditor editor = (DefaultEditor) getEditor();
field = editor.getTextField();
field.setColumns(3);
field.setFont(new Font("Monospaced", Font.PLAIN, 18));

Expand All @@ -40,10 +49,88 @@ public PositiveSpinner(int defaultValue) {
setValue(newValue);
}
});

// Select the input for easy editing when the field receives focus.
field.addFocusListener(new FocusListener());

// Let our parent know when the field value changes for live updates.
field.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
callbackIfChanged();
}

@Override
public void removeUpdate(DocumentEvent e) {
callbackIfChanged();
}

@Override
public void changedUpdate(DocumentEvent e) {
callbackIfChanged();
}
});

this.lastValue = (Integer) getValue();
}

void callbackIfChanged() {
Integer newValue;
try {
newValue = Integer.parseInt(field.getText());
} catch (NumberFormatException e) {
// Ignore.
return;
}

if (!Objects.equals(newValue, lastValue)) {
SwingUtilities.invokeLater(() -> {
this.lastValue = newValue;
changeCallback.onChange(newValue);
});
}
}

@Override
public Dimension getMaximumSize() {
return getPreferredSize();
}

@Override
public boolean requestFocusInWindow() {
return this.field.requestFocusInWindow();
}

/**
* This should work on most platforms.
*/
static class FocusListener implements java.awt.event.FocusListener {
// Thanks to mKorbel (https://stackoverflow.com/users/714968/mkorbel) for this instructive snippet:
// https://stackoverflow.com/questions/20971050/jspinner-autoselect-onfocus/20971713#20971713

@Override
public void focusGained(FocusEvent e) {
focus(e);
}

@Override
public void focusLost(FocusEvent e) {
focus(e);
}

private void focus(FocusEvent e) {
final Component component = e.getComponent();
if (component instanceof JFormattedTextField) {
JFormattedTextField field = (JFormattedTextField) component;
SwingUtilities.invokeLater(() -> {
field.setText(field.getText());
field.selectAll();
});
}
}
}

interface ValueChanged {
void onChange(int value);
}
}

0 comments on commit 74b5402

Please sign in to comment.