2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
41 import java.awt.Component;
42 import java.awt.Container;
43 import java.awt.Dimension;
44 import java.awt.LayoutManager;
45 import java.beans.PropertyChangeEvent;
46 import java.beans.PropertyChangeListener;
47 import java.text.DecimalFormat;
48 import java.text.ParseException;
50 import javax.swing.border.EtchedBorder;
51 import javax.swing.event.ChangeEvent;
52 import javax.swing.event.ChangeListener;
53 import javax.swing.plaf.SpinnerUI;
57 * A JSpinner is a component which typically contains a numeric value and a
58 * way to manipulate the value.
60 * @author Ka-Hing Cheung
64 public class JSpinner extends JComponent
69 public static class StubEditor extends JLabel implements ChangeListener
81 private JSpinner spinner;
84 * Creates a new StubEditor object.
86 * @param spinner DOCUMENT ME!
88 public StubEditor(JSpinner spinner)
90 this.spinner = spinner;
91 setBorder(new EtchedBorder());
92 setHorizontalAlignment(SwingConstants.TRAILING);
93 stateChanged(null); /* fill in the label */
99 * @param evt DOCUMENT ME!
101 public void stateChanged(ChangeEvent evt)
103 setText(String.valueOf(spinner.getValue()));
110 public static class DefaultEditor extends JPanel implements ChangeListener,
111 PropertyChangeListener,
114 private JSpinner spinner;
117 * For compatability with Sun's JDK 1.4.2 rev. 5
119 private static final long serialVersionUID = -5317788736173368172L;
122 * Creates a new <code>DefaultEditor</code> object.
124 * @param spinner the <code>JSpinner</code> associated with this editor
126 public DefaultEditor(JSpinner spinner)
128 this.spinner = spinner;
130 spinner.addChangeListener(this);
134 * Returns the <code>JSpinner</code> object for this editor.
136 public JSpinner getSpinner()
144 public void commitEdit()
145 throws ParseException
152 * @param spinner DOCUMENT ME!
154 public void dismiss(JSpinner spinner)
156 spinner.removeChangeListener(this);
162 * @return DOCUMENT ME!
164 public JFormattedTextField getTextField()
172 * @param parent DOCUMENT ME!
174 public void layoutContainer(Container parent)
181 * @param parent DOCUMENT ME!
183 * @return DOCUMENT ME!
185 public Dimension minimumLayoutSize(Container parent)
193 * @param parent DOCUMENT ME!
195 * @return DOCUMENT ME!
197 public Dimension preferredLayoutSize(Container parent)
205 * @param event DOCUMENT ME!
207 public void propertyChange(PropertyChangeEvent event)
214 * @param event DOCUMENT ME!
216 public void stateChanged(ChangeEvent event)
221 public void removeLayoutComponent(Component child)
228 * @param name DOCUMENT ME!
229 * @param child DOCUMENT ME!
231 public void addLayoutComponent(String name, Component child)
239 public static class NumberEditor extends DefaultEditor
242 * For compatability with Sun's JDK
244 private static final long serialVersionUID = 3791956183098282942L;
247 * Creates a new NumberEditor object.
249 * @param spinner DOCUMENT ME!
251 public NumberEditor(JSpinner spinner)
257 * Creates a new NumberEditor object.
259 * @param spinner DOCUMENT ME!
261 public NumberEditor(JSpinner spinner, String decimalFormatPattern)
269 * @return DOCUMENT ME!
271 public DecimalFormat getFormat()
276 public SpinnerNumberModel getModel()
278 return (SpinnerNumberModel) getSpinner().getModel();
283 private SpinnerModel model;
286 private JComponent editor;
289 private ChangeListener listener = new ChangeListener()
291 public void stateChanged(ChangeEvent evt)
298 * Creates a JSpinner with <code>SpinnerNumberModel</code>
300 * @see javax.swing.SpinnerNumberModel
304 this(new SpinnerNumberModel());
308 * Creates a JSpinner with the specific model and sets the default editor
310 * @param model DOCUMENT ME!
312 public JSpinner(SpinnerModel model)
315 model.addChangeListener(listener);
316 setEditor(createEditor(model));
321 * If the editor is <code>JSpinner.DefaultEditor</code>, then forwards the
322 * call to it, otherwise do nothing.
324 * @throws ParseException DOCUMENT ME!
326 public void commitEdit() throws ParseException
328 if (editor instanceof DefaultEditor)
329 ((DefaultEditor) editor).commitEdit();
333 * Gets the current editor
335 * @return the current editor
339 public JComponent getEditor()
345 * Changes the current editor to the new editor. This methods should remove
346 * the old listeners (if any) and adds the new listeners (if any).
348 * @param editor the new editor
350 * @throws IllegalArgumentException DOCUMENT ME!
354 public void setEditor(JComponent editor)
357 throw new IllegalArgumentException("editor may not be null");
359 if (this.editor instanceof DefaultEditor)
360 ((DefaultEditor) editor).dismiss(this);
361 else if (this.editor instanceof ChangeListener)
362 removeChangeListener((ChangeListener) this.editor);
364 if (editor instanceof ChangeListener)
365 addChangeListener((ChangeListener) editor);
367 this.editor = editor;
371 * Gets the underly model.
373 * @return the underly model
375 public SpinnerModel getModel()
381 * Sets a new underlying model.
383 * @param newModel the new model to set
385 * @exception IllegalArgumentException if newModel is <code>null</code>
387 public void setModel(SpinnerModel newModel)
389 if (newModel == null)
390 throw new IllegalArgumentException();
392 if (model == newModel)
395 SpinnerModel oldModel = model;
397 firePropertyChange("model", oldModel, newModel);
400 setEditor(createEditor(model));
404 * Gets the next value without changing the current value.
406 * @return the next value
408 * @see javax.swing.SpinnerModel#getNextValue
410 public Object getNextValue()
412 return model.getNextValue();
416 * Gets the previous value without changing the current value.
418 * @return the previous value
420 * @see javax.swing.SpinnerModel#getPreviousValue
422 public Object getPreviousValue()
424 return model.getPreviousValue();
428 * Gets the <code>SpinnerUI</code> that handles this spinner
430 * @return the <code>SpinnerUI</code>
432 public SpinnerUI getUI()
434 return (SpinnerUI) ui;
438 * Gets the current value of the spinner, according to the underly model,
441 * @return the current value
443 * @see javax.swing.SpinnerModel#getValue
445 public Object getValue()
447 return model.getValue();
453 * @param value DOCUMENT ME!
455 public void setValue(Object value)
457 model.setValue(value);
461 * This method returns a name to identify which look and feel class will be
462 * the UI delegate for this spinner.
464 * @return The UIClass identifier. "SpinnerUI"
466 public String getUIClassID()
472 * This method resets the spinner's UI delegate to the default UI for the
473 * current look and feel.
475 public void updateUI()
477 setUI((SpinnerUI) UIManager.getUI(this));
481 * This method sets the spinner's UI delegate.
483 * @param ui The spinner's UI delegate.
485 public void setUI(SpinnerUI ui)
491 * Adds a <code>ChangeListener</code>
493 * @param listener the listener to add
495 public void addChangeListener(ChangeListener listener)
497 listenerList.add(ChangeListener.class, listener);
501 * Remove a particular listener
503 * @param listener the listener to remove
505 public void removeChangeListener(ChangeListener listener)
507 listenerList.remove(ChangeListener.class, listener);
511 * Gets all the <code>ChangeListener</code>s
513 * @return all the <code>ChangeListener</code>s
515 public ChangeListener[] getChangeListeners()
517 return (ChangeListener[]) listenerList.getListeners(ChangeListener.class);
521 * Fires a <code>ChangeEvent</code> to all the <code>ChangeListener</code>s
522 * added to this <code>JSpinner</code>
524 protected void fireStateChanged()
526 ChangeEvent evt = new ChangeEvent(this);
527 ChangeListener[] listeners = getChangeListeners();
529 for (int i = 0; i < listeners.length; ++i)
530 listeners[i].stateChanged(evt);
534 * Creates an editor for this <code>JSpinner</code>. Really, it should be a
535 * <code>JSpinner.DefaultEditor</code>, but since that should be
536 * implemented by a JFormattedTextField, and one is not written, I am just
537 * using a dummy one backed by a JLabel.
539 * @param model DOCUMENT ME!
541 * @return the default editor
543 protected JComponent createEditor(SpinnerModel model)
545 return new StubEditor(this);