package ql.gui.widget.input;
import java.awt.Color;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
import ql.Value;
import ql.gui.DefaultComponent;
import ql.gui.widget.InputWidget;
public abstract class Spinbox<T extends Value> extends DefaultComponent implements InputWidget<T>, ChangeListener {
private JPanel panel;
private JSpinner spinbox;
private JLabel errorLabel;
private SpinnerNumberModel model;
public Spinbox(SpinnerNumberModel model) {
this.model = model;
spinbox = new JSpinner(model);
spinbox.setSize(100, 40);
spinbox.addChangeListener(this);
errorLabel = new JLabel();
errorLabel.setFont(new Font("Serif", Font.BOLD, 20));
errorLabel.setVisible(true);
panel = new JPanel(new MigLayout());
panel.add(spinbox);
panel.add(errorLabel, "wrap");
}
/**
* Exposes the internal JPanel for adjustements
* by extending classes. It cannot be overriden
* and is marked 'final'.
*
* @return The internal panel.
*/
protected final JPanel panel() {
return panel;
}
/**
* Exposes the internal JSpinner for adjustements
* by extending classes. It cannot be overriden
* and is marked 'final'.
*
* @return The internal spinbox.
*/
protected final JSpinner spinbox() {
return spinbox;
}
/**
* Exposes the internal JLabel for adjustements
* by extending classes. It cannot be overriden
* and is marked 'final'.
*
* The label is used to present errors by default.
*
* @return The internal label.
*/
protected final JLabel label() {
return errorLabel;
}
/**
* Exposes the internal SpinnerNumberModel for adjustements
* by extending classes. It cannot be overriden and is marked
* 'final'.
*
* @return The internal SpinnerNumberModel.
*/
protected final SpinnerNumberModel model() {
return model;
}
protected void setError(String text) {
spinbox.setBorder(BorderFactory.createLineBorder(Color.RED));
errorLabel.setText(text);
}
protected void removeError() {
spinbox.setBorder(BorderFactory.createLineBorder(Color.BLACK));
errorLabel.setText("");
}
@Override
public void disable() {
spinbox.setEnabled(false);
}
@Override
public abstract T getValue();
/**
* This method is overriden to cast the given value
* that is a numeric to the wanted type. Either
* integer or float.
*
* @param value - The value to convert.
* @return The converted value wrapped in the proper
* value object.
*/
public abstract Number convertValue(Value value);
@Override
public void setValue(Value value) {
spinbox.setValue(convertValue(value));
}
@Override
public void updateComponent() {
spinbox.repaint();
}
@Override
public JComponent getComponent() {
return spinbox;
}
@Override
public void stateChanged(ChangeEvent e) {
handleChange(getValue(), this);
}
}