/**
*
*/
package cz.cuni.mff.peckam.java.origamist.gui.common;
import java.awt.Font;
import java.util.Hashtable;
import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JSpinner.NumberEditor;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.FormLayout;
/**
* A slider with a textfield for entering a value.
*
* @author Martin Pecka
*/
public class JEditableSlider extends JPanel
{
/** */
private static final long serialVersionUID = -3461220059990284317L;
/** The slider this component uses. */
protected JSlider slider = null;
/** The spinner for entering the value. */
protected JSpinner spinner = null;
/** If <code>true</code>, the listeners know that they should just set the value and do no other actions. */
protected boolean setRawValue = false;
/** The value the slider takes as the initial maximum. */
protected int defaultSliderMax = 400;
/**
*
*/
public JEditableSlider()
{
this(null, null);
}
/**
* @param slider
* @param spinner
*/
public JEditableSlider(JSlider slider, JSpinner spinner)
{
setSlider(slider);
setSpinner(spinner);
createComponents();
buildLayout();
}
/**
* Create all components this component uses.
*/
protected void createComponents()
{
if (slider == null) {
JSlider sl = new JSlider(new DefaultBoundedRangeModel(100, 5, 25, defaultSliderMax));
Hashtable<Object, Object> labels = new Hashtable<Object, Object>();
Font labelFont = new JLabel().getFont().deriveFont(Font.PLAIN, 9f);
for (Integer i : new Integer[] { 25, 100, 200, defaultSliderMax }) {
JLabel label = new JLabel(i.toString());
label.setFont(labelFont);
labels.put(i, label);
}
sl.setLabelTable(labels);
sl.setPaintTicks(true);
sl.setMajorTickSpacing(75);
sl.setMinorTickSpacing(15);
sl.setPaintLabels(true);
setSlider(sl);
}
if (spinner == null) {
JSpinner sp = new JSpinner(new SpinnerNumberModel());
JSpinner.NumberEditor editor = (NumberEditor) sp.getEditor();
editor.getTextField().setColumns(3);
sp.setEditor(editor);
setSpinner(sp);
}
spinner.setValue(100);
slider.setValue(100);
updateSpinnerModel();
}
/**
* Add components to layout.
*/
protected void buildLayout()
{
DefaultFormBuilder builder = new DefaultFormBuilder(new FormLayout("default,$rgap,pref", ""), this);
builder.append(slider, spinner);
}
/**
* @return the slider
*/
public JSlider getSlider()
{
return slider;
}
/**
* @param slider the slider to set
*/
protected void setSlider(JSlider slider)
{
this.slider = slider;
if (slider == null)
return;
slider.getModel().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e)
{
if (JEditableSlider.this.slider.getModel().getValueIsAdjusting())
return;
updateSpinnerModel();
}
});
}
/**
* @return the spinner
*/
public JSpinner getSpinner()
{
return spinner;
}
/**
* @param spinner the spinner to set
*/
protected void setSpinner(JSpinner spinner)
{
this.spinner = spinner;
if (spinner == null)
return;
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e)
{
if (setRawValue)
return;
setRawValue = true;
Integer value = (Integer) JEditableSlider.this.spinner.getValue();
if (value > slider.getModel().getMaximum() || slider.getModel().getMaximum() > defaultSliderMax) {
slider.getModel().setMaximum(Math.max(value + 10, defaultSliderMax));
JTextField field = ((NumberEditor) JEditableSlider.this.spinner.getEditor()).getTextField();
field.setColumns((int) Math.ceil(Math.log10(value))); // TODO doesn't relayout the component
}
slider.setValue(value);
setRawValue = false;
}
});
}
/**
* Update the spinner's model to honor the min and max from the slider.
*/
protected void updateSpinnerModel()
{
if (slider != null) {
int min = slider.getMinimum();
spinner.setModel(new SpinnerNumberModel(slider.getValue(), min, null, 1));
}
}
@Override
public void setEnabled(boolean enabled)
{
super.setEnabled(enabled);
slider.setEnabled(enabled);
spinner.setEnabled(enabled);
}
/**
* @return The value of the slider.
*/
public int getValue()
{
return slider.getValue();
}
/**
* Set the value of this slider.
*
* @param value The new value.
*/
public void setValue(int value)
{
slider.setValue(value);
spinner.setValue(value);
}
/**
* @return The value the slider takes as the initial maximum.
*/
public int getDefaultSliderMax()
{
return defaultSliderMax;
}
/**
* @param defaultSliderMax The value the slider takes as the initial maximum.
*/
public void setDefaultSliderMax(int defaultSliderMax)
{
this.defaultSliderMax = defaultSliderMax;
}
/**
* @param l
* @see javax.swing.JSlider#addChangeListener(javax.swing.event.ChangeListener)
*/
public void addChangeListener(ChangeListener l)
{
slider.addChangeListener(l);
}
/**
* @param l
* @see javax.swing.JSlider#removeChangeListener(javax.swing.event.ChangeListener)
*/
public void removeChangeListener(ChangeListener l)
{
slider.removeChangeListener(l);
}
}