View Javadoc

1   package com.melloware.jukes.gui.view.component;
2   
3   import java.text.DateFormat;
4   
5   import javax.swing.AbstractAction;
6   import javax.swing.AbstractButton;
7   import javax.swing.JFormattedTextField;
8   import javax.swing.JToggleButton;
9   import javax.swing.filechooser.FileFilter;
10  import javax.swing.text.DefaultFormatter;
11  import javax.swing.text.DefaultFormatterFactory;
12  import javax.swing.text.JTextComponent;
13  
14  import com.jgoodies.binding.adapter.BasicComponentFactory;
15  import com.jgoodies.binding.adapter.Bindings;
16  import com.jgoodies.binding.value.ValueModel;
17  import com.jgoodies.uif.action.ActionManager;
18  import com.jgoodies.uif.component.ToolBarButton;
19  import com.jgoodies.validation.formatter.RelativeDateFormatter;
20  import com.melloware.jukes.gui.tool.Actions;
21  import com.melloware.jukes.gui.tool.Resources;
22  
23  /**
24   * Consists only of static methods that vend formatted text fields used
25   * to edit dates that are bound to an underlying ValueModel.
26   * Extends the Binding library's BasicComponentFactory to inherit
27   * all factory metods from that class.
28   * <p>
29   * Copyright (c) 1999-2007 Melloware, Inc. <http://www.melloware.com>
30   * @author Emil A. Lefkof III <info@melloware.com>
31   * @version 4.0
32   *
33   * @see com.jgoodies.binding.adapter.BasicComponentFactory
34   * @see com.jgoodies.binding.adapter.Bindings
35   */
36  public final class ComponentFactory
37      extends BasicComponentFactory {
38  
39      private ComponentFactory() {
40          // Suppresses default constructor, ensuring non-instantiability.
41      }
42  
43  
44  
45      /**
46       * Creates and returns a formatted text field that is bound
47       * to the Date value of the given <code>ValueModel</code>.<p>
48       *
49       * The JFormattedTextField is configured with an AbstractFormatter
50       * that uses two different DateFormats to edit and display the Date.
51       * A <code>SHORT</code> DateFormat with strict checking is used to edit
52       * (parse) a date; the DateFormatter's default DateFormat is used to
53       * display (format) a date. In both cases <code>null</code> Dates are
54       * mapped to the empty String.<p>
55       *
56       * In addition to formatted Dates, the parser accepts positive and
57       * negative integers and interprets them as Dates relative to today.
58       * For example -1 is yesterday, 1 is tomorrow, and 7 is "in a week".<p>
59       *
60       * Yesterday, today, and tomorrow are displayed as these Strings,
61       * not as formatted Dates.
62       *
63       * @param valueModel  the model that holds the value to be edited
64       * @return a formatted text field for Date instances that is bound
65       * @throws NullPointerException if the model is <code>null</code>
66       */
67      public static JFormattedTextField createDateField(ValueModel valueModel) {
68          return createDateField(valueModel, true);
69      }
70  
71      /**
72       * Creates and returns a formatted text field that is bound
73       * to the Date value of the given <code>ValueModel</code>.<p>
74       *
75       * The JFormattedTextField is configured with an AbstractFormatter
76       * that uses two different DateFormats to edit and display the Date.
77       * A <code>SHORT</code> DateFormat with strict checking is used to edit
78       * (parse) a date; the DateFormatter's default DateFormat is used to
79       * display (format) a date. In both cases <code>null</code> Dates are
80       * mapped to the empty String.<p>
81       *
82       * In addition to formatted Dates, the parser accepts positive and
83       * negative integers and interprets them as Dates relative to today.
84       * For example -1 is yesterday, 1 is tomorrow, and 7 is "in a week".<p>
85       *
86       * If <code>enableShortcuts</code> is set to <code>true</code>,
87       * yesterday, today, and tomorrow are displayed as these Strings,
88       * not as formatted Dates.
89       *
90       * @param valueModel  the model that holds the value to be edited
91       * @param enableShortcuts true to display yesterday, today, and tomorrow
92       *     with natural language strings
93       * @return a formatted text field for Date instances that is bound
94       * @throws NullPointerException if the model is <code>null</code>
95       */
96      public static JFormattedTextField createDateField(ValueModel valueModel, boolean enableShortcuts) {
97          return createDateField(valueModel, enableShortcuts, false);
98      }
99  
100     /**
101      * Creates and returns a formatted text field that is bound
102      * to the Date value of the given <code>ValueModel</code>.<p>
103      *
104      * The JFormattedTextField is configured with an AbstractFormatter
105      * that uses two different DateFormats to edit and display the Date.
106      * A <code>SHORT</code> DateFormat with strict checking is used to edit
107      * (parse) a date; the DateFormatter's default DateFormat is used to
108      * display (format) a date. In both cases <code>null</code> Dates are
109      * mapped to the empty String.<p>
110      *
111      * In addition to formatted Dates, the parser accepts positive and
112      * negative integers and interprets them as Dates relative to today.
113      * For example -1 is yesterday, 1 is tomorrow, and 7 is "in a week".<p>
114      *
115      * If <code>enableShortcuts</code> is set to <code>true</code>,
116      * yesterday, today, and tomorrow are displayed as these Strings,
117      * not as formatted Dates.
118      *
119      * @param valueModel  the model that holds the value to be edited
120      * @param enableShortcuts true to display yesterday, today, and tomorrow
121      *     with natural language strings
122      * @param commitsOnValidEdit   true to commit on valid edit,
123      *     false to commit on focus lost
124      * @return a formatted text field for Date instances that is bound
125      * @throws NullPointerException if the model is <code>null</code>
126      */
127     public static JFormattedTextField createDateField(ValueModel valueModel,
128                                                       boolean enableShortcuts,
129                                                       boolean commitsOnValidEdit) {
130         DateFormat shortFormat = DateFormat.getDateInstance(DateFormat.SHORT);
131         shortFormat.setLenient(false);
132 
133         DefaultFormatter defaultFormatter = new RelativeDateFormatter(shortFormat, false, true);
134         defaultFormatter.setCommitsOnValidEdit(commitsOnValidEdit);
135 
136         JFormattedTextField.AbstractFormatter displayFormatter = new RelativeDateFormatter(enableShortcuts, true);
137 
138         DefaultFormatterFactory formatterFactory = new DefaultFormatterFactory(defaultFormatter, displayFormatter);
139 
140         JFormattedTextField textField = new JFormattedTextField(formatterFactory);
141         Bindings.bind(textField, valueModel);
142         return textField;
143     }
144 
145     /**
146      * Create a new button that is a directory chooser button and associates
147      * it with a text component to put the selected directory in.
148      * <p>
149      * @param aTextComponent the text component to title case
150      * @return an Abstract button that is the title case button
151      */
152     public static AbstractButton createDirectoryChooserButton(JTextComponent aTextComponent) {
153         final AbstractAction action = (AbstractAction)ActionManager.get(Actions.DIRECTORY_ID);
154         AbstractButton button = new ToolBarButton(action);
155         button.putClientProperty(Resources.TEXT_COMPONENT, aTextComponent);
156         button.setOpaque(false);
157         button.setVerifyInputWhenFocusTarget(true);
158         return button;
159     }
160 
161     /**
162      * Create a new button that is a file chooser button and associates
163      * it with a text component to put the selected file in.
164      * <p>
165      * @param aTextComponent the text component to title case
166      * @param aTitle the title of the chooser dialog
167      * @param aFilter the file filter for the chooser
168      * @return an Abstract button that is the title case button
169      */
170     public static AbstractButton createFileChooserButton(JTextComponent aTextComponent,
171                                                          String aTitle,
172                                                          FileFilter aFilter) {
173         final AbstractAction action = (AbstractAction)ActionManager.get(Actions.FILE_CHOOSER_ID);
174         AbstractButton button = new ToolBarButton(action);
175         button.putClientProperty(Resources.TEXT_COMPONENT, aTextComponent);
176         button.putClientProperty(Resources.FILE_CHOOSER_FILTER, aFilter);
177         button.putClientProperty(Resources.FILE_CHOOSER_TITLE, aTitle);
178         button.setOpaque(false);
179         button.setVerifyInputWhenFocusTarget(true);
180         return button;
181     }
182 
183     /**
184      * Create a new button that is a title case button and associates it with a
185      * text component to actually perform the title casing on.
186      * <p>
187      * @param aTextComponent the text component to title case
188      * @return an Abstract button that is the title case button
189      */
190     public static AbstractButton createTitleCaseButton(JTextComponent aTextComponent) {
191         final AbstractAction action = (AbstractAction)ActionManager.get(Actions.TITLECASE_ID);
192         AbstractButton button = new ToolBarButton(action);
193         button.putClientProperty(Resources.TEXT_COMPONENT, aTextComponent);
194         button.setOpaque(false);
195         button.setVerifyInputWhenFocusTarget(true);
196         return button;
197     }
198 
199     /**
200      * Create a new tool bar button from an Action.
201      * <p>
202      * @param aActionId the actionId to create the button for
203      * @return an Abstract button that is the title case button
204      */
205     public static AbstractButton createToolBarButton(String aActionId) {
206         final AbstractAction action = (AbstractAction)ActionManager.get(aActionId);
207         AbstractButton button = new ToolBarButton(action);
208         button.setOpaque(false);
209         button.setVerifyInputWhenFocusTarget(true);
210         return button;
211     }
212 
213     /**
214      * Create a new tool bar toggle button from an Action.
215      * <p>
216      * @param aActionId the actionId to create the button for
217      * @return an Abstract button that is the title case button
218      */
219     public static AbstractButton createToolBarToggleButton(String aActionId) {
220         final AbstractAction action = (AbstractAction)ActionManager.get(aActionId);
221         AbstractButton button = new JToggleButton(action);
222         button.setText("");
223         button.setOpaque(false);
224         button.setVerifyInputWhenFocusTarget(true);
225         return button;
226     }
227 
228 }