package misc; import java.awt.Dimension; import java.awt.GridBagLayout; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Locale; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener; import misc.Util; import static misc.Util.GBC; import static misc.Util.GBCNL; /** Spinner and Slider */ @SuppressWarnings ("serial") public class SpinnerSlider extends JPanel implements ChangeListener { static public int MaxPrecision = 10000; static public NumberFormat numberFormat; static { numberFormat = NumberFormat.getInstance (Locale.FRENCH); //numberFormat = new DecimalFormat ("#,##0.###,#"); numberFormat.setGroupingUsed (true); numberFormat.setMinimumFractionDigits (0); numberFormat.setMaximumFractionDigits (12); } // ======================================== public interface Accessor { /** current */ public void set (double value); /** minValue, maxValue, current */ public double [] get (); }; Accessor accessor; // ======================================== public double minValue, maxValue; public SpinnerNumberModel snm = new SpinnerNumberModel (0., 0., 0., 1.) { public Object getPreviousValue () { Number value = (Number) super.getPreviousValue (); return SpinnerSlider.this.getPreviousValue (value); } public Object getNextValue () { Number value = (Number) super.getNextValue (); return SpinnerSlider.this.getNextValue (value); } }; public JSpinner spinner = new JSpinner (snm); public JLabel label = new JLabel ("/0"); private JSlider slider = new JSlider (0, MaxPrecision, 1); // ======================================== public SpinnerSlider (Accessor accessor, int textLength, float slideWidthCoef) { super (null); this.accessor = accessor; snm.addChangeListener (this); slider.addChangeListener (this); ((JSpinner.DefaultEditor) spinner.getEditor ()).getTextField ().setColumns (textLength); JSpinner.NumberEditor editor = (JSpinner.NumberEditor) spinner.getEditor (); DecimalFormat format = editor.getFormat (); format.setDecimalSeparatorAlwaysShown (true); format.setMinimumFractionDigits (0); format.setMaximumFractionDigits (12); setLayout (new GridBagLayout ()); Util.addComponent (spinner, this, GBC); Util.addComponent (label, this, GBC); Util.addComponent (slider, this, GBCNL); Dimension d = slider.getPreferredSize (); d.width = (int)(slideWidthCoef*d.width); slider.setPreferredSize (d); slider.setMinimumSize (d); } // ======================================== public void stateChanged (ChangeEvent e) { try { if (e.getSource () == slider) accessor.set (((double)slider.getValue ()/MaxPrecision)*(maxValue - minValue)+minValue); else if (e.getSource () == snm) accessor.set (((Number)snm.getValue ()).doubleValue ()); } catch (Exception e2) { e2.printStackTrace (); } } // ======================================== public void update () { double [] doubleValues = accessor.get (); minValue = doubleValues [0]; maxValue = doubleValues [1]; slider.removeChangeListener (this); snm.removeChangeListener (this); snm.setMinimum (doubleValues [0]); snm.setMaximum (doubleValues [1]); // XXX ? snm.setValue (doubleValues [2]); //snm.setStepSize ((maxValue-minValue)/MaxPrecision); slider.setValue ((int)((doubleValues [2]-minValue)/(maxValue-minValue)*MaxPrecision)); label.setText ("/"+numberFormat.format ((float)doubleValues [1])); snm.addChangeListener (this); slider.addChangeListener (this); } // ======================================== public Number getPreviousValue (Number value) { return value; } public Number getNextValue (Number value) { return value; } // ======================================== }