001: /*
002: * SSpinner.java
003: *
004: * Created on 31. August 2006, 09:21
005: *
006: * To change this template, choose Tools | Template Manager
007: * and open the template in the editor.
008: */
009:
010: package org.wings;
011:
012: import java.text.DecimalFormat;
013: import java.text.DateFormat;
014: import java.text.SimpleDateFormat;
015:
016: import javax.swing.SpinnerModel;
017: import javax.swing.SpinnerDateModel;
018: import javax.swing.SpinnerNumberModel;
019: import javax.swing.SpinnerListModel;
020:
021: import javax.swing.event.ChangeListener;
022: import javax.swing.event.ChangeEvent;
023:
024: import org.wings.text.SDefaultFormatter;
025: import org.wings.text.SNumberFormatter;
026: import org.wings.text.SDateFormatter;
027: import org.wings.text.SDefaultFormatterFactory;
028:
029: /**
030: * A single line input field that lets the user select a number or an object value from an ordered sequence.
031: * @author erik
032: */
033: public class SSpinner extends SComponent implements
034: LowLevelEventListener {
035:
036: private SpinnerModel model;
037: private DefaultEditor editor;
038:
039: private ChangeListener modelChangeListener = null;
040:
041: /**
042: * @see LowLevelEventListener#isEpochCheckEnabled()
043: */
044: protected boolean epochCheckEnabled = true;
045:
046: /** Creates a new instance of SSpinner */
047: public SSpinner() {
048: this (new SpinnerNumberModel(new Integer(0), null, null,
049: new Integer(1)));
050: }
051:
052: /**
053: * Creates a new instance of SSpinner
054: * @param model the model for this Component
055: */
056: public SSpinner(SpinnerModel model) {
057: this .model = model;
058: this .editor = createEditor(model);
059: }
060:
061: protected DefaultEditor createEditor(SpinnerModel model) {
062: DefaultEditor defaultEditor = null;
063:
064: if (model instanceof SpinnerNumberModel) {
065: defaultEditor = new NumberEditor(this );
066: } else if (model instanceof SpinnerDateModel) {
067: defaultEditor = new DateEditor(this );
068: } else if (model instanceof SpinnerListModel) {
069: defaultEditor = new ListEditor(this );
070: } else {
071: defaultEditor = new DefaultEditor(this );
072: }
073:
074: return defaultEditor;
075: }
076:
077: /**
078: * Returns the model of this Component.
079: * @return the model of this Component
080: */
081: public SpinnerModel getModel() {
082: return model;
083: }
084:
085: /**
086: * Sets the model for this Component.
087: * @param model the model for this Component
088: */
089: public void setModel(SpinnerModel model) {
090: if (!model.equals(this .model)) {
091: this .model = model;
092: if (modelChangeListener != null) {
093: this .model.addChangeListener(modelChangeListener);
094: }
095: }
096: }
097:
098: /**
099: * Returns the currrent value of this Component.
100: * @return the current value of this Component
101: */
102: public Object getValue() {
103: return getModel().getValue();
104: }
105:
106: /**
107: * Sets the current value for this Component.
108: * @param value the new current value for this Component
109: */
110: public void setValue(Object value) {
111: if (value instanceof Long) {
112: if (this .getValue() instanceof Integer) {
113: value = new Integer(((Long) value).intValue());
114: } else if (this .getValue() instanceof Double) {
115: value = new Double(((Long) value).doubleValue());
116: }
117: }
118: getModel().setValue(value);
119: }
120:
121: /**
122: * Returns the next value in the sequence.
123: * @return the next value in the sequence
124: */
125: public Object getNextValue() {
126: return getModel().getNextValue();
127: }
128:
129: /**
130: * Returns the current editor.
131: * As long as wings donesn't support incremental updates for all components
132: * we have to return a DefaultEditor instead of SComponent.
133: * @return DefaultEditor
134: */
135: public DefaultEditor getEditor() {
136: return editor;
137: }
138:
139: /**
140: * Sets the editor for this Component.
141: * @param editor the editor for this Component
142: */
143: public void setEditor(DefaultEditor editor) {
144: if (editor != null && !editor.equals(this .editor)) {
145: this .editor.dismiss(this );
146: this .editor = editor;
147: }
148: }
149:
150: public void addChangeListener(ChangeListener changeListener) {
151: addEventListener(ChangeListener.class, changeListener);
152:
153: if (modelChangeListener == null) {
154: modelChangeListener = new ChangeListener() {
155: public void stateChanged(javax.swing.event.ChangeEvent e) {
156: fireChangeEvents();
157: }
158: };
159: getModel().addChangeListener(modelChangeListener);
160: }
161: }
162:
163: private void fireChangeEvents() {
164: ChangeListener[] listeners = getChangeListeners();
165: for (int x = 0, y = listeners.length; x < y; x++) {
166: ChangeListener listener = listeners[x];
167: listener.stateChanged(new ChangeEvent(this ));
168: }
169: }
170:
171: public void removeChangeListener(ChangeListener changeListener) {
172: removeEventListener(ChangeListener.class, changeListener);
173: }
174:
175: public ChangeListener[] getChangeListeners() {
176: return (ChangeListener[]) getListeners(ChangeListener.class);
177: }
178:
179: public static class DefaultEditor extends SPanel implements
180: ChangeListener {
181:
182: private SFormattedTextField ftf = null;
183: private SSpinner spinner = null;
184:
185: public DefaultEditor(SSpinner spinner) {
186: super (null);
187:
188: this .spinner = spinner;
189: putClientProperty("drm:realParentComponent", spinner);
190:
191: ftf = new SFormattedTextField(spinner.getValue()) {
192: public void processLowLevelEvent(String action,
193: String[] values) {
194: String text = getText();
195: super .processLowLevelEvent(action, values);
196: SSpinner spinner = getSpinner();
197: if (isEditable() && isEnabled() && spinner != null) {
198: if (text == null || !text.equals(values[0])) {
199:
200: Object lastValue = spinner.getValue();
201: try {
202: spinner.setValue(getTextField()
203: .getValue());
204: } catch (IllegalArgumentException iae) {
205: try {
206: getTextField().setValue(lastValue);
207: } catch (IllegalArgumentException iae2) {
208: }
209: }
210:
211: }
212: }
213:
214: }
215: };
216: ftf.setStyle("SFormattedTextField");
217: ftf.setHorizontalAlignment(SConstants.RIGHT);
218:
219: spinner.addChangeListener(this );
220:
221: String toolTipText = spinner.getToolTipText();
222: if (toolTipText != null) {
223: ftf.setToolTipText(toolTipText);
224: }
225:
226: add(ftf);
227:
228: }
229:
230: public void dismiss(SSpinner s) {
231: spinner = null;
232: s.removeChangeListener(this );
233: }
234:
235: /**
236: * Returns the SFormattedTextField of this editor
237: * @return the SFormattedTextField of this editor
238: */
239: public SFormattedTextField getTextField() {
240: return ftf;
241: }
242:
243: /**
244: * Returns the Spinner of this editor.
245: * @return the Spinner of this editor
246: */
247: public SSpinner getSpinner() {
248: return this .spinner;
249: }
250:
251: public void stateChanged(ChangeEvent event) {
252: Object source = event.getSource();
253: if (source instanceof SSpinner) {
254: getTextField().setValue(((SSpinner) source).getValue());
255: }
256: }
257:
258: }
259:
260: public static class NumberEditor extends DefaultEditor {
261:
262: public NumberEditor(SSpinner spinner) {
263: this (spinner, getPattern());
264: }
265:
266: public NumberEditor(SSpinner spinner,
267: String decimalFormatPattern) {
268: this (spinner, new DecimalFormat(decimalFormatPattern));
269: }
270:
271: private NumberEditor(SSpinner spinner, DecimalFormat format) {
272: super (spinner);
273: if (!(spinner.getModel() instanceof SpinnerNumberModel)) {
274: throw new IllegalArgumentException(
275: "model not a SpinnerNumberModel");
276: }
277:
278: SDefaultFormatterFactory factory = new SDefaultFormatterFactory(
279: new SNumberFormatter(format));
280:
281: SFormattedTextField ftf = getTextField();
282: ftf.setFormatterFactory(factory);
283: }
284:
285: private static String getPattern() {
286: DecimalFormat decimalFormat = new DecimalFormat();
287: String pattern = decimalFormat.toPattern() + ";-"
288: + decimalFormat.toPattern();
289: return pattern;
290: }
291: }
292:
293: public static class DateEditor extends DefaultEditor {
294:
295: public DateEditor(SSpinner spinner) {
296: this (spinner, getPattern());
297: }
298:
299: public DateEditor(SSpinner spinner, String dateFormatPattern) {
300: this (spinner, new SimpleDateFormat(dateFormatPattern,
301: spinner.getSession().getLocale()));
302: }
303:
304: private DateEditor(SSpinner spinner, DateFormat format) {
305: super (spinner);
306: if (!(spinner.getModel() instanceof SpinnerDateModel)) {
307: throw new IllegalArgumentException(
308: "model not a SpinnerDateModel");
309: }
310:
311: SDefaultFormatterFactory factory = new SDefaultFormatterFactory(
312: new SDateFormatter(format));
313:
314: SFormattedTextField ftf = getTextField();
315: ftf.setFormatterFactory(factory);
316:
317: }
318:
319: private static String getPattern() {
320: SimpleDateFormat sdf = new SimpleDateFormat();
321: return sdf.toPattern();
322: }
323:
324: public SimpleDateFormat getFormat() {
325: return (SimpleDateFormat) ((SDateFormatter) (getTextField()
326: .getFormatter())).getFormat();
327: }
328:
329: /**
330: * Returns the SpinnerDateModel of this editor.
331: * @return the SpinnerDateModel of this editor
332: */
333: public SpinnerDateModel getModel() {
334: return (SpinnerDateModel) (getSpinner().getModel());
335: }
336: }
337:
338: public static class ListEditor extends DefaultEditor {
339:
340: public ListEditor(SSpinner spinner) {
341: super (spinner);
342: if (!(spinner.getModel() instanceof SpinnerListModel)) {
343: throw new IllegalArgumentException(
344: "model not a SpinnerListModel");
345: }
346:
347: SDefaultFormatterFactory factory = new SDefaultFormatterFactory(
348: new SDefaultFormatter());
349:
350: SFormattedTextField ftf = getTextField();
351: ftf.setFormatterFactory(factory);
352: }
353:
354: /**
355: * Returns the SpinnerListModel of this editor.
356: * @return the SpinnerListModel of this editor
357: */
358: public SpinnerListModel getModel() {
359: return (SpinnerListModel) (getSpinner().getModel());
360: }
361:
362: }
363:
364: protected void setParentFrame(SFrame f) {
365: super .setParentFrame(f);
366: getEditor().setParentFrame(f);
367: }
368:
369: /**
370: * @see LowLevelEventListener#isEpochCheckEnabled()
371: */
372: public boolean isEpochCheckEnabled() {
373: return epochCheckEnabled;
374: }
375:
376: /**
377: * @see LowLevelEventListener#setEpochCheckEnabled()
378: */
379: public void setEpochCheckEnabled(boolean epochCheckEnabled) {
380: this .epochCheckEnabled = epochCheckEnabled;
381: }
382:
383: /**
384: * @see LowLevelEventListener#fireIntermediateEvents()
385: */
386: public void fireIntermediateEvents() {
387: }
388:
389: /**
390: * @see LowLevelEventListener#processLowLevelEvent(String action, String[] values)
391: */
392: public void processLowLevelEvent(String action, String[] values) {
393: processKeyEvents(values);
394: if (action.endsWith("_keystroke"))
395: return;
396:
397: int type = Integer.parseInt(values[0]);
398:
399: Object value = null;
400: if (type == 0) {
401: value = getModel().getNextValue();
402: } else {
403: value = getModel().getPreviousValue();
404: }
405: try {
406: getModel().setValue(value);
407: } catch (IllegalArgumentException iae) {
408: }
409:
410: }
411:
412: }
|