001: /*
002: * Copyright (c) 2003-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.validation.tutorial.formatted;
032:
033: import java.text.DateFormat;
034: import java.text.Format;
035: import java.util.Date;
036: import java.util.GregorianCalendar;
037: import java.util.LinkedList;
038: import java.util.List;
039:
040: import javax.swing.*;
041: import javax.swing.text.DateFormatter;
042: import javax.swing.text.DefaultFormatter;
043: import javax.swing.text.DefaultFormatterFactory;
044:
045: import com.jgoodies.binding.value.ValueHolder;
046: import com.jgoodies.binding.value.ValueModel;
047: import com.jgoodies.forms.builder.DefaultFormBuilder;
048: import com.jgoodies.forms.layout.FormLayout;
049: import com.jgoodies.validation.formatter.EmptyDateFormatter;
050: import com.jgoodies.validation.formatter.RelativeDateFormatter;
051: import com.jgoodies.validation.tutorial.formatted.format.DisplayFormat;
052: import com.jgoodies.validation.tutorial.formatted.format.RelativeDateFormat;
053: import com.jgoodies.validation.tutorial.util.ExampleComponentFactory;
054: import com.jgoodies.validation.tutorial.util.MyFocusTraversalPolicy;
055: import com.jgoodies.validation.tutorial.util.TutorialUtils;
056:
057: /**
058: * Demonstrates different configurations of <code>JFormattedTextField</code>
059: * to display and edit numbers. Shows <ul>
060: * <li>how to use a custom DateFormat
061: * <li>how to use a custom DateFormatter
062: * <li>how to use a custom FormatterFactory
063: * <li>how to reset a date to <code>null</code>
064: * <li>how to map the empty string to a special date
065: * <li>how to commit values on valid texts
066: * </ul><p>
067: *
068: * To look under the hood of this component, this class exposes
069: * the bound properties <em>text</em>, <em>value</em> and <em>editValid</em>.
070: *
071: * @author Karsten Lentzsch
072: * @version $Revision: 1.17 $
073: *
074: * @see JFormattedTextField
075: * @see JFormattedTextField.AbstractFormatter
076: */
077: public final class DateExample {
078:
079: public static void main(String[] args) {
080: try {
081: UIManager
082: .setLookAndFeel("com.jgoodies.looks.plastic.PlasticXPLookAndFeel");
083: } catch (Exception e) {
084: // Likely Plastic is not in the classpath; ignore it.
085: }
086: JFrame frame = new JFrame();
087: frame.setTitle("Formatted :: Dates");
088: frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
089: JComponent panel = new DateExample().buildPanel();
090: frame.getContentPane().add(panel);
091: frame.pack();
092: TutorialUtils.locateOnOpticalScreenCenter(frame);
093: frame.setVisible(true);
094: }
095:
096: /**
097: * Builds and returns a panel with a header row and the sample rows.
098: *
099: * @return the example panel with a header and the sample rows
100: */
101: public JComponent buildPanel() {
102: FormLayout layout = new FormLayout(
103: "r:max(80dlu;pref), 4dlu, 45dlu, 1dlu, pref, 4dlu, pref, 0:grow");
104:
105: DefaultFormBuilder builder = new DefaultFormBuilder(layout);
106: builder.setDefaultDialogBorder();
107: builder.getPanel().setFocusTraversalPolicy(
108: MyFocusTraversalPolicy.INSTANCE);
109:
110: Utils.appendTitleRow(builder, "Description");
111: List<JFormattedTextField> fields = appendDemoRows(builder);
112:
113: String validText = DateFormat.getDateInstance().format(
114: new GregorianCalendar(67, 11, 5).getTime());
115: String invalidText = "aa" + validText;
116: Utils.appendButtonBar(builder, fields, validText, invalidText);
117: return builder.getPanel();
118: }
119:
120: /**
121: * Appends the demo rows to the given builder and returns the List of
122: * formatted text fields.
123: *
124: * @param builder the builder used to add components to
125: * @return the List of formatted text fields
126: */
127: private List<JFormattedTextField> appendDemoRows(
128: DefaultFormBuilder builder) {
129: // The Formatter is chosen by the initial value.
130: JFormattedTextField defaultDateField = new JFormattedTextField(
131: new Date());
132:
133: // The Formatter is chosen by the given Format.
134: JFormattedTextField noInitialValueField = new JFormattedTextField(
135: DateFormat.getDateInstance());
136:
137: // Uses a custom DateFormat.
138: DateFormat customFormat = DateFormat
139: .getDateInstance(DateFormat.SHORT);
140: JFormattedTextField customFormatField = new JFormattedTextField(
141: new DateFormatter(customFormat));
142:
143: // Uses a RelativeDateFormat.
144: DateFormat relativeFormat = new RelativeDateFormat();
145: JFormattedTextField relativeFormatField = new JFormattedTextField(
146: new DateFormatter(relativeFormat));
147:
148: // Uses a custom DateFormatter that allows relative input and
149: // prints natural language strings.
150: JFormattedTextField relativeFormatterField = new JFormattedTextField(
151: new RelativeDateFormatter());
152:
153: // Uses a custom FormatterFactory that used different formatters
154: // for the display and while editing.
155: DefaultFormatterFactory formatterFactory = new DefaultFormatterFactory(
156: new RelativeDateFormatter(false, true),
157: new RelativeDateFormatter(true, true));
158: JFormattedTextField relativeFactoryField = new JFormattedTextField(
159: formatterFactory);
160:
161: // Wraps a DateFormatter to map empty strings to null and vice versa.
162: JFormattedTextField numberOrNullField = new JFormattedTextField(
163: new EmptyDateFormatter());
164:
165: // Wraps a DateFormatter to map empty strings to -1 and vice versa.
166: Date epoch = new Date(0); // January 1, 1970
167: JFormattedTextField numberOrEmptyValueField = new JFormattedTextField(
168: new EmptyDateFormatter(epoch));
169: numberOrEmptyValueField.setValue(epoch);
170:
171: // Commits value on valid edit text
172: DefaultFormatter formatter = new RelativeDateFormatter();
173: formatter.setCommitsOnValidEdit(true);
174: JFormattedTextField commitOnValidEditField = new JFormattedTextField(
175: formatter);
176:
177: // A date field as created by the BasicComponentFactory:
178: // Uses relative date input, and maps empty strings to null.
179: ValueModel dateHolder = new ValueHolder();
180: JFormattedTextField componentFactoryField = ExampleComponentFactory
181: .createDateField(dateHolder);
182:
183: Format displayFormat = new DisplayFormat(DateFormat
184: .getDateInstance());
185: List<JFormattedTextField> fields = new LinkedList<JFormattedTextField>();
186: fields.add(Utils.appendRow(builder, "Default",
187: defaultDateField, displayFormat));
188: fields.add(Utils.appendRow(builder, "No initial value",
189: noInitialValueField, displayFormat));
190: fields.add(Utils.appendRow(builder, "Empty <-> null",
191: numberOrNullField, displayFormat));
192: fields.add(Utils.appendRow(builder, "Empty <-> epoch",
193: numberOrEmptyValueField, displayFormat));
194: fields.add(Utils.appendRow(builder, "Short format",
195: customFormatField, displayFormat));
196: fields.add(Utils.appendRow(builder, "Relative format",
197: relativeFormatField, displayFormat));
198: fields.add(Utils.appendRow(builder, "Relative formatter",
199: relativeFormatterField, displayFormat));
200: fields.add(Utils.appendRow(builder, "Relative factory",
201: relativeFactoryField, displayFormat));
202: fields.add(Utils.appendRow(builder, "Commits on valid edit",
203: commitOnValidEditField, displayFormat));
204: fields.add(Utils.appendRow(builder, "Relative, maps null",
205: componentFactoryField, displayFormat));
206:
207: return fields;
208: }
209:
210: }
|