001: /*
002: * Copyright (c) 2002-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.binding.adapter;
032:
033: import java.awt.Color;
034: import java.text.DateFormat;
035: import java.text.Format;
036: import java.text.NumberFormat;
037: import java.text.ParseException;
038:
039: import javax.swing.*;
040: import javax.swing.text.DefaultFormatterFactory;
041: import javax.swing.text.MaskFormatter;
042: import javax.swing.text.NumberFormatter;
043:
044: import com.jgoodies.binding.formatter.EmptyDateFormatter;
045: import com.jgoodies.binding.formatter.EmptyNumberFormatter;
046: import com.jgoodies.binding.list.SelectionInList;
047: import com.jgoodies.binding.value.ComponentValueModel;
048: import com.jgoodies.binding.value.ConverterFactory;
049: import com.jgoodies.binding.value.ValueModel;
050:
051: /**
052: * Consists only of static methods that create and vend frequently used
053: * Swing components that are then bound to a given ValueModel.
054: * This class is one of two helper classes that help you establish a binding:
055: * 1) the Bindings class binds components that have been created before;
056: * it wraps ValueModels with the adapters from package
057: * <code>com.jgoodies.binding.adapter</code>.
058: * 2) this BasicComponentFactory creates Swing components that are then
059: * tied to ValueModels using the the different <code>#bind</code> methods
060: * in the Bindings class.<p>
061: *
062: * If you have an existing factory that vends Swing components, you can use
063: * Bindings to bind them to ValueModels. If you don't have such a factory, you
064: * can use this BasicComponentFactory to create and bind Swing components.<p>
065: *
066: * This class is intended to be used or extended by custom ComponentFactory
067: * classes. Such a factory can create a broader variety of component types,
068: * may use different default configurations, and can use your favorite
069: * Formatters, FormatterFactories, etc.
070: *
071: * @author Karsten Lentzsch
072: * @version $Revision: 1.14 $
073: *
074: * @see com.jgoodies.binding.value.ValueModel
075: * @see com.jgoodies.binding.adapter.Bindings
076: */
077: public class BasicComponentFactory {
078:
079: protected BasicComponentFactory() {
080: // Reduce the visibility of the default constructor.
081: }
082:
083: // Factory Methods ********************************************************
084:
085: /**
086: * Creates and returns a check box with the specified text label
087: * that is bound to the given ValueModel. The check box is selected
088: * if and only if the model's value equals <code>Boolean.TRUE</code>.<p>
089: *
090: * The model is converted to the required ToggleButtonModel
091: * using a ToggleButtonAdapter.
092: *
093: * @param valueModel the model that provides a Boolean value
094: * @param text the check boxes' text label
095: * @return a check box with the specified text bound to the given model,
096: * selected if the model's value equals Boolean.TRUE
097: *
098: * @throws NullPointerException if the valueModel is <code>null</code>
099: */
100: public static JCheckBox createCheckBox(ValueModel valueModel,
101: String text) {
102: JCheckBox checkBox = new JCheckBox(text);
103: Bindings.bind(checkBox, valueModel);
104: return checkBox;
105: }
106:
107: /**
108: * Creates and returns a JColorChooser that has the color selection bound
109: * to the given ValueModel. The ValueModel must be of type Color and must
110: * allow read-access to its value, and the initial value must not be
111: * <code>null</code>.<p>
112: *
113: * It is strongly recommended (though not required)
114: * that the underlying ValueModel provides only non-null values.
115: * This is so because the ColorSelectionModel behavior is undefined
116: * for <code>null</code> values and it may have unpredictable results.
117: * To avoid these problems, you may create the ColorChooser with
118: * a default color using {@link #createColorChooser(ValueModel, Color)}.
119: *
120: * @param valueModel a Color-typed ValueModel
121: * @return a color chooser with the selected color bound to the given model
122: *
123: * @throws NullPointerException if the valueModel is <code>null</code>,
124: * or if its initial value is <code>null</code>
125: *
126: * @see #createColorChooser(ValueModel, Color)
127: *
128: * @since 1.0.3
129: */
130: public static JColorChooser createColorChooser(ValueModel valueModel) {
131: if (valueModel.getValue() == null)
132: throw new NullPointerException(
133: "The initial value must not be null.");
134:
135: JColorChooser colorChooser = new JColorChooser(
136: new ColorSelectionAdapter(valueModel));
137: // Due to a bug in Java 1.4.2, Java 5 and Java 6, we don't use
138: // the Bindings class, but provide a ColorSelectionModel at
139: // instance creation time. The bug is in BasicColorChooserUI
140: // that doesn't listen to color selection model changes.
141: // This is required to update the color preview panel.
142: // But the BasicColorChooserUI registers a preview listener
143: // with the initial color selection model.
144: //Bindings.bind(colorChooser, valueModel);
145: return colorChooser;
146: }
147:
148: /**
149: * Creates and returns a JColorChooser that has the color selection bound
150: * to the given ValueModel. The ValueModel must be of type Color and must
151: * allow read-access to its value. If the valueModel returns
152: * <code>null</code>, the given default color is used instead.
153: * This avoids problems with the ColorSelectionModel that may have
154: * unpredictable result for <code>null</code> values.
155: *
156: * @param valueModel a Color-typed ValueModel
157: * @param defaultColor the color used if the valueModel returns null
158: * @return a color chooser with the selected color bound to the given model
159: *
160: * @throws NullPointerException if the valueModel or the default color
161: * is <code>null</code>,
162: *
163: * @since 1.1
164: */
165: public static JColorChooser createColorChooser(
166: ValueModel valueModel, Color defaultColor) {
167: if (defaultColor == null)
168: throw new NullPointerException(
169: "The default color must not be null.");
170:
171: JColorChooser colorChooser = new JColorChooser(
172: new ColorSelectionAdapter(valueModel, defaultColor));
173: // Due to a bug in Java 1.4.2, Java 5 and Java 6, we don't use
174: // the Bindings class, but provide a ColorSelectionModel at
175: // instance creation time. The bug is in BasicColorChooserUI
176: // that doesn't listen to color selection model changes.
177: // This is required to update the color preview panel.
178: // But the BasicColorChooserUI registers a preview listener
179: // with the initial color selection model.
180: //Bindings.bind(colorChooser, valueModel);
181: return colorChooser;
182: }
183:
184: /**
185: * Creates and returns a non-editable JComboBox that is bound
186: * to the given SelectionInList. The SelectionInList's ListModel
187: * is the list data provider and the selection index holder
188: * is used for the combo box model's selected item.<p>
189: *
190: * If the selectionInList's selection holder is a {@link ComponentValueModel}
191: * it is synchronized with the visible and enabled state of the returned
192: * combo box.<p>
193: *
194: * There are a couple of other possibilities to bind a JComboBox.
195: * See the constructors and the class comment of the
196: * {@link ComboBoxAdapter}.
197: *
198: * @param selectionInList provides the list and selection
199: * @param <E> the type of the combo box items and the selection
200: *
201: * @return a non-editable JComboBox that is bound to the SelectionInList
202: *
203: * @throws NullPointerException if the selectionInList
204: * is <code>null</code>
205: *
206: * @see ComboBoxAdapter
207: *
208: * @since 1.0.1
209: */
210: public static <E> JComboBox createComboBox(
211: SelectionInList<E> selectionInList) {
212: return createComboBox(selectionInList, null);
213: }
214:
215: /**
216: * Creates and returns a non-editable JComboBox that is bound
217: * to the given SelectionInList using the given cell renderer.
218: * The SelectionInList provides the list data and the selection
219: * index holder is used for the combo box model's selected item.<p>
220: *
221: * If the selectionInList's selection holder is a {@link ComponentValueModel}
222: * it is synchronized with the visible and enabled state of the returned
223: * combo box.<p>
224: *
225: * There are a couple of other possibilities to bind a JComboBox.
226: * See the constructors and the class comment of the
227: * {@link ComboBoxAdapter}.
228: *
229: * @param selectionInList provides the list and selection
230: * @param cellRenderer an optional ListCellRenderer,
231: * can be <code>null</code>
232: * @param <E> the type of the combo box items and the selection
233: *
234: * @return a non-editable JComboBox that is bound to the SelectionInList
235: * and uses the given renderer - if non-<code>null</code>
236: *
237: * @throws NullPointerException if the selectionInList
238: * is <code>null</code>
239: *
240: * @see ComboBoxAdapter
241: *
242: * @since 1.0.1
243: */
244: public static <E> JComboBox createComboBox(
245: SelectionInList<E> selectionInList,
246: ListCellRenderer cellRenderer) {
247: JComboBox comboBox = new JComboBox();
248: Bindings.bind(comboBox, selectionInList);
249: if (cellRenderer != null) {
250: comboBox.setRenderer(cellRenderer);
251: }
252: return comboBox;
253: }
254:
255: /**
256: * Creates and returns a formatted text field that is bound
257: * to the Date value of the given ValueModel.
258: * The JFormattedTextField is configured with an AbstractFormatter
259: * that uses two different DateFormats to edit and display the Date.
260: * A <code>SHORT</code> DateFormat with strict checking is used to edit
261: * (parse) a date; the DateFormatter's default DateFormat is used to
262: * display (format) a date. In both cases <code>null</code> Dates are
263: * mapped to the empty String.
264: *
265: * @param valueModel the model that holds the value to be edited
266: * @return a formatted text field for Date instances that is bound
267: * to the given value model
268: *
269: * @throws NullPointerException if the valueModel is <code>null</code>
270: */
271: public static JFormattedTextField createDateField(
272: ValueModel valueModel) {
273: DateFormat shortFormat = DateFormat
274: .getDateInstance(DateFormat.SHORT);
275: shortFormat.setLenient(false);
276:
277: JFormattedTextField.AbstractFormatter defaultFormatter = new EmptyDateFormatter(
278: shortFormat);
279: JFormattedTextField.AbstractFormatter displayFormatter = new EmptyDateFormatter();
280: DefaultFormatterFactory formatterFactory = new DefaultFormatterFactory(
281: defaultFormatter, displayFormatter);
282:
283: return createFormattedTextField(valueModel, formatterFactory);
284: }
285:
286: /**
287: * Creates and returns a formatted text field that binds its value
288: * to the given model and converts Strings to values using
289: * the given Format.
290: *
291: * @param valueModel the model that provides the value
292: * @param format the <code>Format</code> used to convert values
293: * into a text representation and vice versa via <code>#format</code>
294: * and <code>#parse</code>
295: * @return a formatted text field that is bound to the given value model
296: *
297: * @throws NullPointerException if the valueModel is <code>null</code>
298: */
299: public static JFormattedTextField createFormattedTextField(
300: ValueModel valueModel, Format format) {
301: JFormattedTextField textField = new JFormattedTextField(format);
302: Bindings.bind(textField, valueModel);
303: return textField;
304: }
305:
306: /**
307: * Creates and returns a formatted text field that binds its value
308: * to the given model and converts Strings to values using
309: * the given Formatter.
310: *
311: * @param valueModel the model that provides the value
312: * @param formatter the Formatter used to convert values to
313: * a text representation and vice versa via <code>#valueToString</code>
314: * and <code>#stringToValue</code>
315: * @return a formatted text field that is bound to the given value model
316: *
317: * @throws NullPointerException if the valueModel is <code>null</code>
318: */
319: public static JFormattedTextField createFormattedTextField(
320: ValueModel valueModel,
321: JFormattedTextField.AbstractFormatter formatter) {
322: JFormattedTextField textField = new JFormattedTextField(
323: formatter);
324: Bindings.bind(textField, valueModel);
325: return textField;
326: }
327:
328: /**
329: * Creates and returns a formatted text field that binds its value
330: * to the given model and converts Strings to values using
331: * Formatters provided by the given AbstractFormatterFactory.
332: *
333: * @param valueModel the model that provides the value
334: * @param formatterFactory provides formatters for different field states
335: * that in turn are used to convert values to a text representation and
336: * vice versa via <code>#valueToString</code>
337: * and <code>#stringToValue</code>
338: * @return a formatted text field that is bound to the given value model
339: *
340: * @throws NullPointerException if the valueModel is <code>null</code>
341: */
342: public static JFormattedTextField createFormattedTextField(
343: ValueModel valueModel,
344: JFormattedTextField.AbstractFormatterFactory formatterFactory) {
345: JFormattedTextField textField = new JFormattedTextField(
346: formatterFactory);
347: Bindings.bind(textField, valueModel);
348: return textField;
349: }
350:
351: /**
352: * Creates and returns a formatted text field that binds its value
353: * to the given model and converts Strings to values using
354: * a MaskFormatter that is based on the given mask.
355: *
356: * @param valueModel the model that provides the value
357: * @param mask the mask pattern used to create an instance of
358: * <code>MaskFormatter</code> that in turn converts values to Strings
359: * and vice versa
360: * @return a bound formatted text field using a MaskFormatter
361: *
362: * @throws NullPointerException if the valueModel is <code>null</code>
363: * @throws IllegalArgumentException if the mask is invalid
364: */
365: public static JFormattedTextField createFormattedTextField(
366: ValueModel valueModel, String mask) {
367: MaskFormatter formatter = null;
368: try {
369: formatter = new MaskFormatter(mask);
370: } catch (ParseException e) {
371: throw new IllegalArgumentException("Invalid mask '" + mask
372: + "'.");
373: }
374: JFormattedTextField textField = new JFormattedTextField(
375: formatter);
376: Bindings.bind(textField, valueModel);
377: return textField;
378: }
379:
380: // Integer Fields *********************************************************
381:
382: /**
383: * Creates and returns a formatted text field that is bound
384: * to the Integer value of the given ValueModel.
385: * Empty strings are converted to <code>null</code> and vice versa.<p>
386: *
387: * The Format used to convert numbers to strings and vice versa
388: * is <code>NumberFormat.getIntegerInstance()</code>.
389: *
390: * @param valueModel the model that holds the value to be edited
391: * @return a formatted text field for Integer instances that is bound
392: * to the specified valueModel
393: *
394: * @throws NullPointerException if the valueModel is <code>null</code>
395: */
396: public static JFormattedTextField createIntegerField(
397: ValueModel valueModel) {
398: return createIntegerField(valueModel, NumberFormat
399: .getIntegerInstance(), null);
400: }
401:
402: /**
403: * Creates and returns a formatted text field that is bound
404: * to the Integer value of the given ValueModel.
405: * Empty strings are converted to the specified empty number.<p>
406: *
407: * The Format used to convert numbers to strings and vice versa
408: * is <code>NumberFormat.getIntegerInstance()</code>.
409: *
410: * @param valueModel the model that holds the value to be edited
411: * @param emptyNumber an Integer that represents the empty string
412: * @return a formatted text field for Integer instances that is bound
413: * to the specified valueModel
414: *
415: * @throws NullPointerException if the valueModel is <code>null</code>
416: */
417: public static JFormattedTextField createIntegerField(
418: ValueModel valueModel, int emptyNumber) {
419: return createIntegerField(valueModel, NumberFormat
420: .getIntegerInstance(), emptyNumber);
421: }
422:
423: /**
424: * Creates and returns a formatted text field that is bound
425: * to the Integer value of the given ValueModel.
426: * Empty strings are converted to <code>null</code> and vice versa.
427: *
428: * @param valueModel the model that holds the value to be edited
429: * @param numberFormat used to convert numbers to strings and vice versa
430: * @return a formatted text field for Integer instances that is bound
431: * to the specified valueModel
432: *
433: * @throws NullPointerException if the valueModel is <code>null</code>
434: */
435: public static JFormattedTextField createIntegerField(
436: ValueModel valueModel, NumberFormat numberFormat) {
437: return createIntegerField(valueModel, numberFormat, null);
438: }
439:
440: /**
441: * Creates and returns a formatted text field that is bound
442: * to the Integer value of the given ValueModel.
443: * Empty strings are converted to the specified empty number.
444: *
445: * @param valueModel the model that holds the value to be edited
446: * @param numberFormat used to convert numbers to strings and vice versa
447: * @param emptyNumber an Integer that represents the empty string
448: * @return a formatted text field for Integer instances that is bound
449: * to the specified valueModel
450: *
451: * @throws NullPointerException if the valueModel is <code>null</code>
452: */
453: public static JFormattedTextField createIntegerField(
454: ValueModel valueModel, NumberFormat numberFormat,
455: int emptyNumber) {
456: return createIntegerField(valueModel, numberFormat, Integer
457: .valueOf(emptyNumber));
458: }
459:
460: /**
461: * Creates and returns a formatted text field that is bound
462: * to the Integer value of the given ValueModel.
463: * Empty strings are converted to the specified empty number.
464: *
465: * @param valueModel the model that holds the value to be edited
466: * @param numberFormat used to convert numbers to strings and vice versa
467: * @param emptyNumber an Integer that represents the empty string
468: * @return a formatted text field for Integer instances that is bound
469: * to the specified valueModel
470: *
471: * @throws NullPointerException if the valueModel is <code>null</code>
472: */
473: public static JFormattedTextField createIntegerField(
474: ValueModel valueModel, NumberFormat numberFormat,
475: Integer emptyNumber) {
476: NumberFormatter numberFormatter = new EmptyNumberFormatter(
477: numberFormat, emptyNumber);
478: numberFormatter.setValueClass(Integer.class);
479:
480: return createFormattedTextField(valueModel, numberFormatter);
481: }
482:
483: // Long Fields ************************************************************
484:
485: /**
486: * Creates and returns a formatted text field that is bound
487: * to the Long value of the given ValueModel.
488: * Empty strings are converted to <code>null</code> and vice versa.<p>
489: *
490: * The Format used to convert numbers to strings and vice versa is
491: * <code>NumberFormat.getIntegerInstance()</code>.
492: *
493: * @param valueModel the model that holds the value to be edited
494: * @return a formatted text field for Long instances that is bound to the
495: * specified valueModel
496: *
497: * @throws NullPointerException if the model is <code>null</code>
498: */
499: public static JFormattedTextField createLongField(
500: ValueModel valueModel) {
501: return createLongField(valueModel, NumberFormat
502: .getIntegerInstance(), null);
503: }
504:
505: /**
506: * Creates and returns a formatted text field that is bound to the
507: * Long value of the given ValueModel. Empty strings are converted
508: * to the specified empty number.<p>
509: *
510: * The Format used to convert numbers to strings and vice versa is
511: * <code>NumberFormat.getIntegerInstance()</code>.
512: *
513: * @param valueModel the model that holds the value to be edited
514: * @param emptyNumber a Long that represents the empty string
515: * @return a formatted text field for Long instances that is bound to the
516: * specified valueModel
517: *
518: * @throws NullPointerException if the model is <code>null</code>
519: */
520: public static JFormattedTextField createLongField(
521: ValueModel valueModel, long emptyNumber) {
522: return createLongField(valueModel, NumberFormat
523: .getIntegerInstance(), emptyNumber);
524: }
525:
526: /**
527: * Creates and returns a formatted text field that is bound to the
528: * Long value of the given ValueModel. Empty strings are converted
529: * to <code>null</code> and vice versa.
530: *
531: * @param valueModel the model that holds the value to be edited
532: * @param numberFormat used to convert numbers to strings and vice versa
533: * @return a formatted text field for Long instances that is bound to the
534: * specified valueModel
535: *
536: * @throws NullPointerException if the model is <code>null</code>
537: */
538: public static JFormattedTextField createLongField(
539: ValueModel valueModel, NumberFormat numberFormat) {
540: return createLongField(valueModel, numberFormat, null);
541: }
542:
543: /**
544: * Creates and returns a formatted text field that is bound to the
545: * Long value of the given ValueModel. Empty strings are converted
546: * to the specified empty number.
547: *
548: * @param valueModel the model that holds the value to be edited
549: * @param numberFormat used to convert numbers to strings and vice versa
550: * @param emptyNumber a Long that represents the empty string
551: * @return a formatted text field for Long instances that is bound to the
552: * specified valueModel
553: *
554: * @throws NullPointerException if the model is <code>null</code>
555: */
556: public static JFormattedTextField createLongField(
557: ValueModel valueModel, NumberFormat numberFormat,
558: long emptyNumber) {
559: return createLongField(valueModel, numberFormat, Long
560: .valueOf(emptyNumber));
561: }
562:
563: /**
564: * Creates and returns a formatted text field that is bound to the
565: * Long value of the given ValueModel. Empty strings are converted
566: * to the specified empty number.
567: *
568: * @param valueModel the model that holds the value to be edited
569: * @param numberFormat used to convert numbers to strings and vice versa
570: * @param emptyNumber a Long that represents the empty string
571: * @return a formatted text field for Long instances that is bound to the
572: * specified valueModel
573: *
574: * @throws NullPointerException if the model is <code>null</code>
575: */
576: public static JFormattedTextField createLongField(
577: ValueModel valueModel, NumberFormat numberFormat,
578: Long emptyNumber) {
579: NumberFormatter numberFormatter = new EmptyNumberFormatter(
580: numberFormat, emptyNumber);
581: numberFormatter.setValueClass(Long.class);
582:
583: return createFormattedTextField(valueModel, numberFormatter);
584: }
585:
586: // ************************************************************************
587:
588: /**
589: * Creates and returns a text label that is bound to the given ValueModel.
590: *
591: * @param valueModel the model that provides the value
592: * @return a text label that is bound to the given value model
593: *
594: * @throws NullPointerException if the valueModel is <code>null</code>
595: */
596: public static JLabel createLabel(ValueModel valueModel) {
597: JLabel label = new JLabel();
598: Bindings.bind(label, valueModel);
599: return label;
600: }
601:
602: /**
603: * Creates and returns a text label that is bound to the
604: * given ValueModel that is wrapped by a <code>StringConverter</code>.
605: * The conversion to Strings uses the specified Format.
606: *
607: * @param valueModel the model that provides the value
608: * @param format the format used to create the StringConverter
609: * @return a text label that is bound to the given value model
610: *
611: * @throws NullPointerException if the valueModel is <code>null</code>
612: *
613: * @see ConverterFactory
614: */
615: public static JLabel createLabel(ValueModel valueModel,
616: Format format) {
617: return createLabel(ConverterFactory.createStringConverter(
618: valueModel, format));
619: }
620:
621: /**
622: * Creates and returns a JList for the given SelectionInList.<p>
623: *
624: * If the selectionInList's selection holder is a {@link ComponentValueModel}
625: * it is synchronized with the visible and enabled state of the returned
626: * list.
627: *
628: * @param selectionInList provides the list and selection
629: * @param <E> the type of the list items and the selection
630: * @return a JList bound to the given SelectionInList
631: *
632: * @throws NullPointerException if selectionInList is <code>null</code>
633: */
634: public static <E> JList createList(
635: SelectionInList<E> selectionInList) {
636: return createList(selectionInList, null);
637: }
638:
639: /**
640: * Creates and returns a JList for the given SelectionInList using
641: * the specified optional ListCellRenderer to render cells.<p>
642: *
643: * If the selectionInList's selection holder is a {@link ComponentValueModel}
644: * it is synchronized with the visible and enabled state of the returned
645: * list.
646: *
647: * @param selectionInList provides the list and selection
648: * @param cellRenderer an optional ListCellRenderer,
649: * can be <code>null</code>
650: * @param <E> the type of the list items and the selection
651: * @return a JList bound to the given SelectionInList
652: *
653: * @throws NullPointerException if selectionInList is <code>null</code>
654: */
655: public static <E> JList createList(
656: SelectionInList<E> selectionInList,
657: ListCellRenderer cellRenderer) {
658: JList list = new JList();
659: Bindings.bind(list, selectionInList);
660: if (cellRenderer != null) {
661: list.setCellRenderer(cellRenderer);
662: }
663: return list;
664: }
665:
666: /**
667: * Creates and returns a JPasswordField with the content bound
668: * to the given ValueModel. Text changes are committed to the model
669: * on focus lost.<p>
670: *
671: * <strong>Security Note: </strong> The binding created by this method
672: * uses Strings as values of the given ValueModel. The String-typed
673: * passwords could potentially be observed in a security fraud.
674: * For stronger security it is recommended to request a character array
675: * from the JPasswordField and clear the array after use by setting
676: * each character to zero. Method {@link JPasswordField#getPassword()}
677: * return's the field's password as a character array.
678: *
679: * @param valueModel the model that provides the value
680: * @return a text field that is bound to the given value model
681: *
682: * @throws NullPointerException if the valueModel is <code>null</code>
683: *
684: * @see #createPasswordField(ValueModel, boolean)
685: * @see JPasswordField#getPassword()
686: */
687: public static JPasswordField createPasswordField(
688: ValueModel valueModel) {
689: return createPasswordField(valueModel, true);
690: }
691:
692: /**
693: * Creates and returns a JPasswordField with the content bound
694: * to the given ValueModel. Text changes can be committed to the model
695: * on focus lost or on every character typed.<p>
696: *
697: * <strong>Security Note: </strong> The binding created by this method
698: * uses Strings as values of the given ValueModel. The String-typed
699: * passwords could potentially be observed in a security fraud.
700: * For stronger security it is recommended to request a character array
701: * from the JPasswordField and clear the array after use by setting
702: * each character to zero. Method {@link JPasswordField#getPassword()}
703: * return's the field's password as a character array.
704: *
705: * @param valueModel the model that provides the value
706: * @param commitOnFocusLost true to commit text changes on focus lost,
707: * false to commit text changes on every character typed
708: * @return a text field that is bound to the given value model
709: *
710: * @throws NullPointerException if the valueModel is <code>null</code>
711: *
712: * @see #createPasswordField(ValueModel)
713: * @see JPasswordField#getPassword()
714: */
715: public static JPasswordField createPasswordField(
716: ValueModel valueModel, boolean commitOnFocusLost) {
717: JPasswordField textField = new JPasswordField();
718: Bindings.bind(textField, valueModel, commitOnFocusLost);
719: return textField;
720: }
721:
722: /**
723: * Creates and returns a radio button with the specified text label
724: * that is bound to the given ValueModel. The radio button is selected
725: * if and only if the model's value equals the specified choice.<p>
726: *
727: * The model is converted to the required ToggleButton
728: * using a RadioButtonAdapter.
729: *
730: * @param model the model that provides the current choice
731: * @param choice this button's value
732: * @param text the radio buttons' text label
733: * @return a radio button with the specified text bound to the given model,
734: * selected if the model's value equals the specified choice
735: *
736: * @throws NullPointerException if the valueModel is <code>null</code>
737: */
738: public static JRadioButton createRadioButton(ValueModel model,
739: Object choice, String text) {
740: JRadioButton radioButton = new JRadioButton(text);
741: Bindings.bind(radioButton, model, choice);
742: return radioButton;
743: }
744:
745: /**
746: * Creates and returns a text area with the content bound to the given
747: * ValueModel. Text changes are committed to the model on focus lost.
748: *
749: * @param valueModel the model that provides the value
750: * @return a text area that is bound to the given value model
751: *
752: * @throws NullPointerException if the valueModel is <code>null</code>
753: *
754: * @see #createTextArea(ValueModel, boolean)
755: */
756: public static JTextArea createTextArea(ValueModel valueModel) {
757: return createTextArea(valueModel, true);
758: }
759:
760: /**
761: * Creates and returns a text area with the content bound to the given
762: * ValueModel. Text changes can be committed to the model on focus lost
763: * or on every character typed.
764: *
765: * @param valueModel the model that provides the text value
766: * @param commitOnFocusLost true to commit text changes on focus lost,
767: * false to commit text changes on every character typed
768: * @return a text area that is bound to the given value model
769: *
770: * @throws NullPointerException if the valueModel is <code>null</code>
771: *
772: * @see #createTextArea(ValueModel)
773: */
774: public static JTextArea createTextArea(ValueModel valueModel,
775: boolean commitOnFocusLost) {
776: JTextArea textArea = new JTextArea();
777: Bindings.bind(textArea, valueModel, commitOnFocusLost);
778: return textArea;
779: }
780:
781: /**
782: * Creates and returns a text field with the content bound
783: * to the given ValueModel. Text changes are committed to the model
784: * on focus lost.
785: *
786: * @param valueModel the model that provides the value
787: * @return a text field that is bound to the given value model
788: *
789: * @throws NullPointerException if the valueModel is <code>null</code>
790: *
791: * @see #createTextField(ValueModel, boolean)
792: */
793: public static JTextField createTextField(ValueModel valueModel) {
794: return createTextField(valueModel, true);
795: }
796:
797: /**
798: * Creates and returns a text field with the content bound
799: * to the given ValueModel. Text changes can be committed to the model
800: * on focus lost or on every character typed.
801: *
802: * @param valueModel the model that provides the text value
803: * @param commitOnFocusLost true to commit text changes on focus lost,
804: * false to commit text changes on every character typed
805: * @return a text field that is bound to the given value model
806: *
807: * @throws NullPointerException if the valueModel is <code>null</code>
808: *
809: * @see #createTextField(ValueModel)
810: */
811: public static JTextField createTextField(ValueModel valueModel,
812: boolean commitOnFocusLost) {
813: JTextField textField = new JTextField();
814: Bindings.bind(textField, valueModel, commitOnFocusLost);
815: return textField;
816: }
817:
818: }
|