HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

"JSpinner"
Volume: 4 Issue: 4, p. 40

Download files assoicated with this article

	

Listing 1.
 
public interface SpinModel 
{ 
  public int getFieldCount(); 
  public int getActiveField(); 
  public void setActiveField(int fieldID); 
  public void setNextField(); 
  public void setPrevField(); 
  public int[] getFieldIDs(); 
  public void setFieldIDs(int[] fields); 
  public void setRange(int fieldID, SpinRangeModel range); 
  public SpinRangeModel getRange(int fieldID); 
  public void addChangeListener(ChangeListener listener); 
  public void removeChangeListener(ChangeListener listener); 
} 

Listing 2.
 
public interface SpinRangeModel 
{ 
  public double getValue(); 
  public double getExtent(); 
  public double getMinimum(); 
  public double getMaximum(); 
  public boolean getWrap(); 
  public void setValue(double value); 
  public void setExtent(double extent); 
  public void setMinimum(double min); 
  public void setMaximum(double max); 
  public void setWrap(boolean wrap); 
  public void setValueIsAdjusting(boolean adusting); 
  public boolean getValueIsAdjusting(); 
  public void addChangeListener(ChangeListener listener); 
  public void removeChangeListener(ChangeListener listener); 
} 

Listing 3.
 
public interface SpinRenderer 
{ 
  public Component getSpinCellRendererComponent( 
    JSpinnerField spin, Object value, boolean hasFocus, 
    Format formatter, int selectedFieldID); 
} 

Listing 4.
 
public class DefaultSpinModel 
  implements SpinModel, ChangeListener 
{ 
  protected int activeField; 
  protected Vector fieldIDs = new Vector(); 
  protected Hashtable table = new Hashtable(); 
  protected Vector listeners = new Vector(); 

  public DefaultSpinModel() {} 

  public DefaultSpinModel(double value, 
    double extent, double min, double max, boolean wrap) 
  { 
    SpinRangeModel model = new DefaultSpinRangeModel( 
      value, extent, min, max, wrap); 
    setRange(NumberFormat.INTEGER_FIELD, model); 
    setActiveField(NumberFormat.INTEGER_FIELD); 
  } 

  public DefaultSpinModel( 
    double iValue, double iExtent, double iMin, double 
iMax, boolean iWrap, 
    double fValue, double fExtent, double fMin, double 
fMax, boolean fWrap) 
  { 
    SpinRangeModel iModel = new DefaultSpinRangeModel( 
      iValue, iExtent, iMin, iMax, iWrap); 
    setRange(NumberFormat.INTEGER_FIELD, iModel); 

    SpinRangeModel fModel = new DefaultSpinRangeModel( 
      fValue, fExtent, fMin, fMax, fWrap); 
    setRange(NumberFormat.FRACTION_FIELD, fModel); 

    setActiveField(NumberFormat.INTEGER_FIELD); 
  } 

  public int getFieldCount() 
  { 
    return fieldIDs.size(); 
  } 

  public int getActiveField() 
  { 
    return activeField; 
  } 

  public void setActiveField(int fieldID) 
  { 
    activeField = fieldID; 
    fireStateChanged(); 
  } 

  public void setNextField() 
  { 
    int[] array = getFieldIDs(); 
    for (int i = 0; i < array.length; i++) 
    { 
      if (array[i] == activeField)// && i != 
array.length 
- 1) 
      { 
        setActiveField(array[Math.min(i + 1, 
array.length - 1)]); 
        return; 
      } 
    } 
  } 

  public void setPrevField() 
  { 
    int[] array = getFieldIDs(); 
    for (int i = 0; i < array.length; i++) 
    { 
      if (array[i] == activeField) 
      { 
        setActiveField(array[Math.max(i - 1, 0)]); 
        return; 
      } 
    } 
  } 

  public void setRange(int id, SpinRangeModel range) 
  { 
    Integer key = new Integer(id); 
    if (!table.containsKey(key)) 
    { 
      fieldIDs.addElement(key); 
      range.addChangeListener(this); 
    } 
    table.put(key, range); 
  } 

  public SpinRangeModel getRange(int id) 
  { 
    Integer key = new Integer(id); 
    return (SpinRangeModel)table.get(key); 
  } 

  public int[] getFieldIDs() 
  { 
    int size = fieldIDs.size(); 
    int[] array = new int[size]; 
    for (int i = 0; i < size; i++) 
    { 
      array[i] = 
((Integer)fieldIDs.elementAt(i)).intValue(); 
    } 
    return array; 
  } 

  public void setFieldIDs(int[] fields) 
  { 
    fieldIDs.removeAllElements(); 
    for (int i = 0; i < fields.length; i++) 
    { 
      fieldIDs.addElement(new Integer(fields[i])); 
    } 
  } 

  public void stateChanged(ChangeEvent event) 
  { 
    fireStateChanged(); 
  } 

  public void addChangeListener(ChangeListener 
listener) 
  { 
    listeners.addElement(listener); 
  } 

  public void removeChangeListener(ChangeListener 
listener) 
  { 
    listeners.removeElement(listener); 
  } 

  public void fireStateChanged() 
  { 
    ChangeListener listener; 
    Vector list = (Vector)listeners.clone(); 
    ChangeEvent event = new ChangeEvent(this); 
    for (int i = 0; i < list.size(); i++) 
    { 
      listener = ((ChangeListener)list.elementAt(i)); 
      listener.stateChanged(event); 
    } 
  } 
} 

Listing 5.
 
public class DefaultSpinRangeModel 
  implements SpinRangeModel 
{ 
    protected Vector listeners = new Vector(); 

    private double value = 0; 
    private double extent = 1; 
    private double min = 0; 
    private double max = 100; 
    private boolean wrap = true; 
    private boolean isAdjusting = false; 

  public DefaultSpinRangeModel() {} 

  public DefaultSpinRangeModel(double value, 
double extent, 
    double min, double max, boolean wrap) 
  { 
    this.value = value; 
    this.extent = extent; 
    this.min = min; 
    this.max = max; 
  } 

  public double getValue() 
  { 
    return value; 
  } 

  public double getExtent() 
  { 
    return extent; 
  } 

  public double getMinimum() 
  { 
    return min; 
  } 

  public double getMaximum() 
  { 
    return max; 
  } 

  public boolean getWrap() 
  { 
    return wrap; 
  } 

  public void setValue(double value) 
  { 
    this.value = value; 
  } 

  public void setExtent(double extent) 
  { 
    this.extent = extent; 
  } 

  public void setMinimum(double min) 
  { 
    this.min = min; 
  } 

  public void setMaximum(double max) 
  { 
    this.max = max; 
  } 

  public void setWrap(boolean wrap) 
  { 
    this.wrap = wrap; 
  } 

  public void setValueIsAdjusting(boolean isAdusting) 
  { 
    this.isAdjusting = isAdjusting; 
    if (!isAdjusting) fireStateChanged(); 
  } 

  public boolean getValueIsAdjusting() 
  { 
    return isAdjusting; 
  } 

  public void addChangeListener(ChangeListener 
listener) 
  { 
    listeners.addElement(listener); 
  } 

  public void removeChangeListener(ChangeListener 
listener) 
  { 
    listeners.removeElement(listener); 
  } 

  public void fireStateChanged() 
  { 
    ChangeListener listener; 
    Vector list = (Vector)listeners.clone(); 
    ChangeEvent event = new ChangeEvent(this); 
    for (int i = 0; i < list.size(); i++) 
    { 
      listener = ((ChangeListener)list.elementAt(i)); 
      listener.stateChanged(event); 
    } 
  } 

  public String toString() 
  { 
    String modelString = 
      "value=" + getValue() + ", " + 
      "extent=" + getExtent() + ", " + 
      "min=" + getMinimum() + ", " + 
      "max=" + getMaximum() + ", " + 
      "adj=" + getValueIsAdjusting(); 
    return getClass().getName() + "[" + modelString + "]"; 
  } 
} 

Listing 6.
 
public class JSpinner extends JPanel 
  implements ActionListener, KeyListener, SwingConstants 
{ 
  protected Vector listeners = new Vector(); 
  protected BasicArrowButton north, south; 
  SpinModel model; 

  public JSpinner(SpinModel model) 
  { 
    this.model = model; 
    setLayout(new GridLayout(2, 1)); 
    setPreferredSize(new Dimension(16, 16)); 

    north = new BasicArrowButton(BasicArrowButton.NORTH); 
    north.addActionListener(this); 
    add(north); 

    south = new BasicArrowButton(BasicArrowButton.SOUTH); 
    south.addActionListener(this); 
    add(south); 
  } 

  public void actionPerformed(ActionEvent event) 
  { 
    if (event.getSource() == north) 
    { 
      increment(); 
    } 
    if (event.getSource() == south) 
    { 
      decrement(); 
    } 
  } 

  public void keyTyped(KeyEvent event) {} 
  public void keyReleased(KeyEvent event) {} 
  public void keyPressed(KeyEvent event) 
  { 
    int code = event.getKeyCode(); 
    if (code == KeyEvent.VK_UP) 
    { 
      increment(); 
    } 
    if (code == KeyEvent.VK_DOWN) 
    { 
      decrement(); 
    } 
    if (code == KeyEvent.VK_LEFT) 
    { 
      model.setPrevField(); 
    } 
    if (code == KeyEvent.VK_RIGHT) 
    { 
      model.setNextField(); 
    } 
  } 

  protected void increment() 
  { 
    int fieldID = model.getActiveField(); 
    SpinRangeModel range = model.getRange(fieldID); 
    range.setValueIsAdjusting(true); 
    double value = range.getValue() + range.getExtent(); 
    if (value > range.getMaximum()) 
      value = range.getWrap() ? 
        range.getMinimum() : range.getMaximum(); 
    range.setValue(value); 
    model.setRange(fieldID, range); 
    range.setValueIsAdjusting(false); 
  } 

  public void decrement() 
  { 
    int fieldID = model.getActiveField(); 
    SpinRangeModel range = model.getRange(fieldID); 
    range.setValueIsAdjusting(true); 
    double value = range.getValue() - range.getExtent(); 
    if (value < range.getMinimum()) 
      value = range.getWrap() ? 
        range.getMaximum() : range.getMinimum(); 
    range.setValue(value); 
    model.setRange(fieldID, range); 
    range.setValueIsAdjusting(false); 
  } 
} 

Listing 7.
 
public class JSpinnerField extends JPanel 
  implements ChangeListener, MouseListener, 
FocusListener 
{ 
  protected SpinModel model; 
  protected SpinField spinField; 
  protected SpinRenderer renderer; 
  protected Format formatter; 
  protected boolean wrap = true; 
  protected boolean hasFocus = false; 

  public JSpinnerField() {} 

  public JSpinnerField(int value, 
    int extent, int min, int max, boolean wrap) 
  { 
    init(new DefaultSpinModel(value, extent, min, 
max, wrap), 
      new DefaultSpinRenderer(), 
      NumberFormat.getInstance(), wrap); 
    refreshSpinView(); 
  } 

  public JSpinnerField(SpinModel model, 
    SpinRenderer renderer, Format formatter, 
    boolean wrap) 
  { 
    init(model, renderer, formatter, wrap); 
    refreshSpinView(); 
  } 

  protected void init(SpinModel model, 
    SpinRenderer renderer, Format formatter, 
    boolean wrap) 
  { 
    this.model = model; 
    this.renderer = renderer; 
    this.formatter = formatter; 
    this.wrap = wrap; 
    spinField = new SpinField(this); 
    setLayout(new BorderLayout()); 
    add(BorderLayout.CENTER, spinField); 
    setBorder(spinField.getBorder()); 
    spinField.setBorder(null); 
    JSpinner spinner = new JSpinner(model); 
    addKeyListener(spinner); 
    addMouseListener(this); 
    addFocusListener(this); 
    model.addChangeListener(this); 
    add(BorderLayout.EAST, spinner); 
  } 

  public void setLocale(Locale locale) 
  { 
    formatter = NumberFormat.getInstance(locale); 
    updateFieldOrder(); 
  } 

  public void updateFieldOrder() 
  { 
    if (spinField.getValue() == null) return; 
    int[] fieldIDs = model.getFieldIDs(); 
    LocaleUtil.sortFieldOrder(formatter, 
spinField.getValue(), fieldIDs); 
    model.setFieldIDs(fieldIDs); 
  } 

  public SpinRenderer getRenderer() 
  { 
    return renderer; 
  } 

  protected void refreshSpinView() 
  { 
    int fieldID = model.getActiveField(); 
    SpinRangeModel range = model.getRange(fieldID); 
    spinField.setValue(new Double(range.getValue())); 
  } 

  public void stateChanged(ChangeEvent event) 
  { 
    requestFocus(); 
    refreshSpinView(); 
    repaint(); 
  } 

  public void mouseClicked(MouseEvent event) 
  { 
    int fieldID = LocaleUtil.findMouseInField( 
      getGraphics().getFontMetrics(), event.getX(), 
      formatter, spinField.getValue(), 
model.getFieldIDs()); 
    model.setActiveField(fieldID); 
    requestFocus(); 
    refreshSpinView(); 
  } 
  public void mousePressed(MouseEvent event) {} 
  public void mouseReleased(MouseEvent event) {} 
  public void mouseEntered(MouseEvent event) {} 
  public void mouseExited(MouseEvent event) {} 

  public void focusGained(FocusEvent event) 
  { 
    hasFocus = true; 
    repaint(); 
  } 

  public void focusLost(FocusEvent event) 
  { 
    hasFocus = false; 
    repaint(); 
  } 

  public boolean isFocusTraversable() 
  { 
    return true; 
  } 
} 

Listing 8.
 
public class LocaleUtil 
{ 
  public static void sortFieldOrder( 
    Format formatter, Object obj, int[] fieldIDs) 
  { 
    int size = fieldIDs.length; 
    int[] order = new int[size]; 
    for (int i = 0; i < size; i++) 
    { 
      order[i] = getFieldPosition( 
        formatter, obj, fieldIDs[i]).getBeginIndex(); 
    } 
    sort(fieldIDs, order); 
  } 

  public static int findMouseInField(FontMetrics 
metrics, 
int x, 
    Format formatter, Object obj, int[] fieldIDs) 
  { 
    String text = formatter.format(obj); 
    int size = fieldIDs.length; 
    FieldPosition pos; 
    for (int i = 0; i < size; i++) 
    { 
      pos = getFieldPosition(formatter, obj, 
fieldIDs[i]); 
      int left = metrics.stringWidth( 
        text.substring(0, pos.getBeginIndex())); 
      int right = metrics.stringWidth( 
        text.substring(0, pos.getEndIndex())); 
      if (x >= left && x <= right) 
      { 
        return fieldIDs[i]; 
      } 
    } 
    return fieldIDs[0]; 
  } 

  public static FieldPosition getFieldPosition( 
    Format formatter, Object obj, int field) 
  { 
    FieldPosition pos = new FieldPosition(field); 
    StringBuffer buffer = new StringBuffer(); 
    formatter.format(obj, buffer, pos); 
    return pos; 
  } 

  private static void sort(int[] fieldIDs, int[] 
order) 
  { 
    sort(fieldIDs, order, 0, fieldIDs.length - 1); 
    } 

  private static void sort(int[] fieldIDs, int[] 
order, 
int first, int last) 
  { 
    if (first >= last) return; 
    int lo = first, hi = last; 
    int mid = order[(first + last) / 2]; 
    int tmp, temp; 
    do 
    { 
      while (mid > order[lo]) lo++; 
      while (mid < order[hi]) hi--; 
      if (lo <= hi) 
      { 
        tmp = order[lo]; 
        temp = fieldIDs[lo]; 
        order[lo] = order[hi]; 
        fieldIDs[lo] = fieldIDs[hi]; 
        lo++; 
        order[hi] = tmp; 
        fieldIDs[hi] = temp; 
        hi--; 
      } 
    } 
    while (lo <= hi) ; 
    sort(fieldIDs, order, first, hi); 
    sort(fieldIDs, order, lo, last); 
  } 

  public static void main(String[] args) 
  { 
    int[] order = {2, 8, 12, 6, 10, 4}; 
    int[] fieldIDs = {1, 4, 6, 3, 5, 2}; 
    sort(fieldIDs, order); 
    for (int i = 0; i < fieldIDs.length; i++) 
    { 
      System.out.print(fieldIDs[i] + "; "); 
    } 
  } 
} 

Listing 9.
 
public class SpinField extends JPanel 
{ 
  protected CellRendererPane pane; 
  protected JSpinnerField field; 
  protected Object value; 

  public SpinField(JSpinnerField field) 
  { 
    this.field = field; 
    setLayout(new BorderLayout()); 
    add(BorderLayout.CENTER, pane = new 
CellRendererPane()); 
    JComponent renderer = (JComponent) 
field.getRenderer(); 
    setBorder(renderer.getBorder()); 
    renderer.setBorder(null); 
  } 

  public void setValue(Object value) 
  { 
    this.value = value; 
    repaint(); 
  } 

  public Object getValue() 
  { 
    return value; 
  } 

  public void paintComponent(Graphics g) 
  { 
    int w = getSize().width; 
    int h = getSize().height; 
    Component comp = field.getRenderer(). 
      getSpinCellRendererComponent(field, value, 
        field.hasFocus, field.formatter, 
        field.model.getActiveField()); 
    pane.paintComponent(g, comp, this, 0, 0, w, h); 
  } 

  public Dimension getPreferredSize() 
  { 
    return ((JComponent)field.getRenderer()) 
.getPreferredSize(); 
  } 

  public Dimension getMinimumSize() 
  { 
    return ((JComponent)field.getRenderer()) 
.getMinimumSize(); 
  } 
} 

Listing 10.
 
public class DefaultSpinRenderer extends JTextField 
  implements SpinRenderer 
{ 
  private static Color focusColor = new Color(0, 0, 128); 

  public DefaultSpinRenderer() 
  { 
    setOpaque(true); 
    setEditable(false); 
  } 

  public Component getSpinCellRendererComponent( 
    JSpinnerField spin, Object value, boolean hasFocus, 
    Format formatter, int selectedFieldID) 
  { 
    String text = formatter.format(value); 
    setText(text); 
    FieldPosition pos = LocaleUtil.getFieldPosition( 
      formatter, value, selectedFieldID); 
    // Make non-selections expand to full selections 
    if (pos.getBeginIndex() == pos.getEndIndex()) 
    { 
      pos.setBeginIndex(0); 
      pos.setEndIndex(text.length()); 
    } 
    if (hasFocus) 
      select(pos.getBeginIndex(), pos.getEndIndex()); 
    else select(0, 0); 
    return this; 
  } 
} 

Listing 11.
 
public class ColorSpinRenderer extends JTextField 
  implements SpinRenderer 
{ 
  private static Color focusColor = Color.white; 
  private static Border focus = new 
LineBorder(focusColor, 1); 

  public ColorSpinRenderer() 
  { 
    setOpaque(true); 
    setEditable(false); 
  } 

  public Component getSpinCellRendererComponent( 
    JSpinnerField spin, Object value, boolean hasFocus, 
    Format formatter, int selectedFieldID) 
  { 
    if (value instanceof Color) 
    { 
      Color color = (Color)value; 
      setBackground(color); 
      if (hasFocus) setBorder(focus); 
      else setBorder(null); 
    } 
    return this; 
  } 
} 

Listing 12.
 
public class JSpinnerColor extends JSpinnerField 
{ 
  protected Vector list = new Vector(); 

  public JSpinnerColor(Color[] items, int index, 
boolean wrap) 
  { 
    super( 
      new DefaultSpinModel(index, 1, 0, items.length 
- 1, wrap), 
      new ColorSpinRenderer(), null, wrap); 
    for (int i = 0; i < items.length; i++) 
    { 
      list.addElement(items[i]); 
    } 
    refreshSpinView(); 
  } 

  protected void refreshSpinView() 
  { 
    if (list == null) return; 
    int fieldID = model.getActiveField(); 
    SpinRangeModel range = model.getRange(fieldID); 
    spinField.setValue(list.elementAt((int) 
range.getValue())); 
  } 

  public void updateFieldOrder() {} 
} 

Listing 13.
 
public class JSpinnerList extends JSpinnerField 
{ 
  public JSpinnerList(String[] items, int index, 
boolean wrap) 
  { 
    double[] limits = new double[items.length]; 
    for (int i = 0; i < items.length; i++) 
    { 
      limits[i] = i; 
    } 
    init(new DefaultSpinModel(index, 1, 0, 
items.length - 1, wrap), 
      new DefaultSpinRenderer(), 
      new ChoiceFormat(limits, items), wrap); 
    refreshSpinView(); 
  } 

  public void setLocale(Locale locale) {} 
} 

Listing 14.
 
public class JSpinnerPercent extends JSpinnerField 
{ 
  public JSpinnerPercent() 
  { 
    init(new DefaultSpinModel(0, 0.01, 0, 1, true), 
      new DefaultSpinRenderer(), 
      NumberFormat.getPercentInstance(), 
      true); 
    refreshSpinView(); 
  } 

  public void setLocale(Locale locale) 
  { 
    formatter = NumberFormat.getPercentInstance(locale); 
    updateFieldOrder(); 
  } 
} 

Listing 15.
 
public class JSpinnerCurrency extends JSpinnerField 
{ 
  public JSpinnerCurrency() 
  { 
    init(new DefaultSpinModel( 
        0, 1, 0, 10, true, 
        0, 0.01, 0, 1, true), 
      new DefaultSpinRenderer(), 
      NumberFormat.getCurrencyInstance(), 
      true); 
    refreshSpinView(); 
  } 

  public void setLocale(Locale locale) 
  { 
    formatter = NumberFormat.getCurrencyInstance(locale); 
    updateFieldOrder(); 
  } 

  protected void refreshSpinView() 
  { 
    double integer = model.getRange( 
      NumberFormat.INTEGER_FIELD).getValue(); 
    double fraction = model.getRange( 
      NumberFormat.FRACTION_FIELD).getValue(); 
    spinField.setValue(new Double(integer + fraction)); 
  } 
} 

Listing 16.
 
public class TimeSpinModel extends DefaultSpinModel 
{ 
  protected Calendar time = Calendar.getInstance(); 

  public TimeSpinModel() 
  { 
    setRange(DateFormat.HOUR1_FIELD, 
      new DefaultSpinRangeModel()); 
    setRange(DateFormat.MINUTE_FIELD, 
      new DefaultSpinRangeModel()); 
    setRange(DateFormat.AM_PM_FIELD, 
      new DefaultSpinRangeModel()); 
    setActiveField(DateFormat.HOUR1_FIELD); 
    setTime(time); 
  } 

  public void setRange(int fieldID, SpinRangeModel range) 
  { 
    super.setRange(fieldID, range); 
    if (fieldID == DateFormat.HOUR1_FIELD) 
    { 
      time.set(Calendar.HOUR, (int)range.getValue()); 
    } 
    if (fieldID == DateFormat.MINUTE_FIELD) 
    { 
      time.set(Calendar.MINUTE, (int)range.getValue()); 
    } 
    if (fieldID == DateFormat.AM_PM_FIELD) 
    { 
      time.set(Calendar.HOUR_OF_DAY, 
        time.get(Calendar.HOUR) + 12 * (int) 
range.getValue()); 
    } 
  } 

  public SpinRangeModel getRange(int fieldID) 
  { 
    SpinRangeModel range = super.getRange(fieldID); 
    if (fieldID == DateFormat.HOUR1_FIELD) 
    { 
      range.setExtent(1.0); 
      range.setValue(time.get(Calendar.HOUR)); 
      range.setMinimum(time.getActualMinimum 
(Calendar.HOUR)); 
      range.setMaximum(time.getActualMaximum 
(Calendar.HOUR)); 
    } 
    if (fieldID == DateFormat.MINUTE_FIELD) 
    { 
      range.setExtent(1.0); 
      range.setValue(time.get(Calendar.MINUTE)); 
      range.setMinimum(time.getActualMinimum 
(Calendar.MINUTE)); 
      range.setMaximum(time.getActualMaximum 
(Calendar.MINUTE)); 
    } 
    if (fieldID == DateFormat.AM_PM_FIELD) 
    { 
      range.setExtent(1.0); 
      range.setValue(time.get(Calendar.AM_PM)); 
      range.setMinimum(time.getActualMinimum 
(Calendar.AM_PM)); 
      range.setMaximum(time.getActualMaximum 
(Calendar.AM_PM)); 
    } 
    return range; 
  } 

  public void setTime(Calendar time) 
  { 
    this.time = time; 
    getRange(DateFormat.HOUR1_FIELD); 
    getRange(DateFormat.MINUTE_FIELD); 
    getRange(DateFormat.AM_PM_FIELD); 
    fireStateChanged(); 
  } 

  public Calendar getTime() 
  { 
    return time; 
  } 

  public static void main(String[] args) 
  { 
    TimeSpinModel model = new TimeSpinModel(); 
    int activeField = model.getActiveField(); 
    System.out.println(model.getRange(activeField)); 
    model.setNextField(); 
    activeField = model.getActiveField(); 
    System.out.println(model.getRange(activeField)); 
    model.setNextField(); 
    activeField = model.getActiveField(); 
    System.out.println(model.getRange(activeField)); 
    model.setNextField(); 
    activeField = model.getActiveField(); 
    System.out.println(model.getRange(activeField)); 
  } 
} 

Listing 17.
 
public class DateSpinModel extends DefaultSpinModel 
{ 
  protected Calendar date = Calendar.getInstance(); 

  public DateSpinModel() 
  { 
    setRange(DateFormat.MONTH_FIELD, 
      new DefaultSpinRangeModel()); 
    setRange(DateFormat.DATE_FIELD, 
      new DefaultSpinRangeModel()); 
    setRange(DateFormat.YEAR_FIELD, 
      new DefaultSpinRangeModel()); 
    setActiveField(DateFormat.MONTH_FIELD); 
  } 

  public void setRange(int fieldID, SpinRangeModel 
range) 
  { 
    super.setRange(fieldID, range); 
    if (fieldID == DateFormat.DATE_FIELD) 
    { 
      date.set(Calendar.DATE, (int)range.getValue()); 
    } 
    if (fieldID == DateFormat.MONTH_FIELD) 
    { 
      date.set(Calendar.MONTH, (int)range.getValue()); 
    } 
    if (fieldID == DateFormat.YEAR_FIELD) 
    { 
      date.set(Calendar.YEAR, (int)range.getValue()); 
    } 
  } 

  public SpinRangeModel getRange(int fieldID) 
  { 
    SpinRangeModel range = super.getRange(fieldID); 
    if (fieldID == DateFormat.DATE_FIELD) 
    { 
      range.setExtent(1); 
      range.setValue(date.get(Calendar.DAY_OF_MONTH)); 
      range.setMinimum(date.getActualMinimum 
(Calendar.DAY_OF_MONTH)); 
      range.setMaximum(date.getActualMaximum 
(Calendar.DAY_OF_MONTH)); 
    } 
    if (fieldID == DateFormat.MONTH_FIELD) 
    { 
      range.setExtent(1); 
      range.setValue(date.get(Calendar.MONTH)); 
      range.setMinimum(date.getActualMinimum 
(Calendar.MONTH)); 
      range.setMaximum(date.getActualMaximum 
(Calendar.MONTH)); 
    } 
    if (fieldID == DateFormat.YEAR_FIELD) 
    { 
      range.setExtent(1); 
      range.setValue(date.get(Calendar.YEAR)); 
      range.setMinimum(date.getActualMinimum(Calendar.YEAR)); 
      range.setMaximum(date.getActualMaximum(Calendar.YEAR)); 
    } 
    return range; 
  } 

  public void setDate(Calendar date) 
  { 
    this.date = date; 
    getRange(DateFormat.DATE_FIELD); 
    getRange(DateFormat.MONTH_FIELD); 
    getRange(DateFormat.YEAR_FIELD); 
  } 

  public Calendar getDate() 
  { 
    return date; 
  } 
} 

Listing 18.
 
public class JSpinnerTime extends JSpinnerField 
{ 
  public JSpinnerTime() 
  { 
    this(Calendar.getInstance()); 
  } 

  public JSpinnerTime(Calendar time) 
  { 
    super(new TimeSpinModel(), 
      new DefaultSpinRenderer(), 
      DateFormat.getTimeInstance(DateFormat.SHORT), 
      true); 
    getTimeModel().setTime(time); 
    refreshSpinView(); 
  } 

  public void setLocale(Locale locale) 
  { 
    formatter = DateFormat.getTimeInstance(DateFormat.SHORT, 
locale); 
    updateFieldOrder(); 
  } 

  private TimeSpinModel getTimeModel() 
  { 
    return (TimeSpinModel)model; 
  } 

  protected void refreshSpinView() 
  { 
    spinField.setValue(getTimeModel().getTime().getTime()); 
  } 
} 

Listing 19.
 
public class JSpinnerDate extends JSpinnerField 
{ 
  public JSpinnerDate() 
  { 
    this(Calendar.getInstance()); 
  } 

  public JSpinnerDate(Calendar date) 
  { 
    super(new DateSpinModel(), 
      new DefaultSpinRenderer(), 
      DateFormat.getDateInstance(DateFormat.MEDIUM), 
      true); 
    getDateModel().setDate(date); 
    refreshSpinView(); 
  } 

  public void setLocale(Locale locale) 
  { 
    formatter = DateFormat.getDateInstance(DateFormat.MEDIUM, 
locale); 
    updateFieldOrder(); 
  } 

  private DateSpinModel getDateModel() 
  { 
    return (DateSpinModel)model; 
  } 

  protected void refreshSpinView() 
  { 
    spinField.setValue(getDateModel().getDate().getTime()); 
  } 
} 

Listing 20.
 
public class JSpinnerTest extends JPanel 
  implements ActionListener 
{ 
  protected JComboBox localeChoice; 
  protected JSpinnerField date, time, 
    currency, percent, number, skip, list, color; 
  protected String[] localeNames = 
  { 
    "U.S.", "English", "French", "German" 
  }; 
  protected Locale[] localeTypes = 
  { 
    Locale.US, Locale.ENGLISH, Locale.FRENCH, Locale.GERMAN 
  }; 

  public JSpinnerTest() 
  { 
    setLayout(new FieldLayout(4, 4)); 
    add(new JLabel(" Locale: ")); 
    add(localeChoice = new JComboBox(localeNames)); 
    localeChoice.addActionListener(this); 
    add(new JLabel(" JSpinnerField (1-10/1): ")); 
    add(number = new JSpinnerField(1, 1, 1, 10, true)); 
    add(new JLabel(" JSpinnerField (0-8/2): ")); 
    add(skip = new JSpinnerField(0, 2, 0, 8, true)); 
    add(new JLabel(" JSpinnerDate (today): ")); 
    add(date = new JSpinnerDate()); 
    add(new JLabel(" JSpinnerTime (now): ")); 
    add(time = new JSpinnerTime()); 
    add(new JLabel(" JSpinnerPercent: ")); 
    add(percent = new JSpinnerPercent()); 
    add(new JLabel(" JSpinnerCurrency: ")); 
    add(currency = new JSpinnerCurrency()); 
    add(new JLabel(" JSpinnerList (a,b,c,d,e): ")); 
    add(list = new JSpinnerList(new String[] { 
      "alpha", "beta", "gamma", "delta", "epsilon"}, 0, true)); 
    add(new JLabel(" JSpinnerColor (r,g,b): ")); 
    add(color = new JSpinnerColor(new Color[] { 
      Color.red, Color.green, Color.blue}, 0, true)); 
  } 

  public void actionPerformed(ActionEvent event) 
  { 
    Locale locale = localeTypes 
[localeChoice.getSelectedIndex()]; 
    date.setLocale(locale); 
    time.setLocale(locale); 
    percent.setLocale(locale); 
    currency.setLocale(locale); 
    number.setLocale(locale); 
    skip.setLocale(locale); 
    list.setLocale(locale); 
    color.setLocale(locale); 
    repaint(); 
  } 

  public static void main(String[] args) 
  { 
    PLAF.setNativeLookAndFeel(true); 
    JFrame frame = new JFrame("JSpinner* Test"); 
    frame.getContentPane().add(new JSpinnerTest()); 
    frame.setBounds(100, 100, 250, 250); 
    frame.show(); 
  } 
} 
  

 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.