KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdesktop > swing > form > ComponentMap


1 /*
2  * $Id: ComponentMap.java,v 1.5 2005/03/01 13:27:11 kleopatra Exp $
3  *
4  * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
5  * Santa Clara, California 95054, U.S.A. All rights reserved.
6  */

7
8 package org.jdesktop.swing.form;
9
10 import java.awt.Cursor JavaDoc;
11 import java.awt.Image JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.Calendar JavaDoc;
14 import java.util.Date JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import javax.swing.Icon JavaDoc;
21 import javax.swing.JCheckBox JavaDoc;
22 import javax.swing.JComboBox JavaDoc;
23 import javax.swing.JComponent JavaDoc;
24 import javax.swing.JLabel JavaDoc;
25 import javax.swing.JList JavaDoc;
26 import javax.swing.JScrollPane JavaDoc;
27 import javax.swing.JSpinner JavaDoc;
28 import javax.swing.JTextArea JavaDoc;
29 import javax.swing.JTextField JavaDoc;
30 import javax.swing.ListModel JavaDoc;
31 import javax.swing.SpinnerModel JavaDoc;
32 import javax.swing.SpinnerNumberModel JavaDoc;
33
34 import org.jdesktop.swing.JXDatePicker;
35 import org.jdesktop.swing.JXImagePanel;
36 import org.jdesktop.swing.JXListPanel;
37 import org.jdesktop.swing.JXRadioGroup;
38 import org.jdesktop.swing.JXTable;
39 import org.jdesktop.swing.LinkHandler;
40 import org.jdesktop.swing.data.DataModel;
41 import org.jdesktop.swing.data.DefaultTableModelExt;
42 import org.jdesktop.swing.data.EnumeratedMetaData;
43 import org.jdesktop.swing.data.Link;
44 import org.jdesktop.swing.data.MetaData;
45 import org.jdesktop.swing.data.NumberMetaData;
46 import org.jdesktop.swing.data.StringMetaData;
47 import org.jdesktop.swing.data.TabularDataModel;
48 import org.jdesktop.swing.data.TabularMetaData;
49
50 /**
51  * Choosing strategy for creating components.
52  * <p>
53  *
54  * Extracted from DefaultFormFactory to have a "pluggable" place for creating
55  * custom components. The usage of a ComponentCreator should be viewed as an
56  * implementation detail, they don't do much.
57  * <p>
58  *
59  * The created components have their name property set to metaData.name. This
60  * will enable searching for them in a container and facilitates testing.
61  * <p>
62  *
63  * PENDING: should be factored into an interface and a default implementation.
64  * <p>
65  *
66  * PENDING: think about task distribution - only visual aspects of the metaData
67  * should be handled here.
68  *
69  * @author Jeanette Winzenburg
70  */

71 public class ComponentMap {
72     private Map JavaDoc creatorMap;
73
74     private ComponentCreator fallBackCreator;
75
76     private List JavaDoc assignables;
77
78     private static ComponentMap instance = new ComponentMap();
79
80     public static ComponentMap getInstance() {
81         return instance;
82     }
83
84     public static void setInstance(ComponentMap map) {
85         instance = map;
86     }
87     /**
88      * creates and returns a component based on the given MetaData.
89      *
90      * @param metaData
91      * @return
92      */

93     public JComponent JavaDoc createComponent(MetaData metaData) {
94         ComponentCreator creator = getComponentCreator(metaData);
95         return creator.createComponent(metaData);
96     }
97
98     /**
99      * Encapsulates lookup-strategy to find a fitting ComponentCreator.
100      * <p>
101      * Here:
102      * <ol>
103      * <li>look-up by metaData.class, if nothing found
104      * <li>look-up by metaData.elementClass, if nothing found
105      * <li>fallback component
106      * </ol>
107      *
108      * @param metaData
109      * @return
110      * @throws NullPointerException
111      * if metaData == null
112      */

113     protected ComponentCreator getComponentCreator(MetaData metaData) {
114         ComponentCreator creator = findByClass(metaData.getClass());
115         if (creator == null) {
116             creator = findByElementClass(metaData.getElementClass());
117         }
118         if (creator == null) {
119             creator = getFallBackComponentCreator();
120         }
121         return creator;
122     }
123
124     protected ComponentCreator findByElementClass(Class JavaDoc elementClass) {
125         elementClass = checkForArray(elementClass);
126         List JavaDoc classes = getAssignableClasses();
127         for (Iterator JavaDoc iter = classes.iterator(); iter.hasNext();) {
128             Class JavaDoc clazz = (Class JavaDoc) iter.next();
129             if (clazz.isAssignableFrom(elementClass)) {
130                 return findByClass(clazz);
131             }
132         }
133         return findByClass(elementClass);
134     }
135
136     protected Class JavaDoc checkForArray(Class JavaDoc elementClass) {
137         // dirty hack...
138
return elementClass.isArray() ? Object JavaDoc[].class : elementClass;
139     }
140
141     protected ComponentCreator findByClass(Class JavaDoc elementClass) {
142         Object JavaDoc mappedObject = getCreatorMap().get(elementClass);
143         return (ComponentCreator) mappedObject;
144     }
145
146     protected ComponentCreator getFallBackComponentCreator() {
147         if (fallBackCreator == null) {
148             fallBackCreator = new LabelCreator();
149         }
150         return fallBackCreator;
151     }
152
153     protected void initCreators(Map JavaDoc map) {
154         map.put(TabularMetaData.class, new TableCreator());
155         map.put(EnumeratedMetaData.class, new EnumerationCreator());
156         map.put(NumberMetaData.class, new NumberCreator());
157         ComponentCreator textCreator = new TextCreator();
158         map.put(StringMetaData.class, textCreator);
159         map.put(String JavaDoc.class, textCreator);
160         ComponentCreator booleanCreator = new BooleanCreator();
161         map.put(Boolean JavaDoc.class, booleanCreator);
162         map.put(boolean.class, booleanCreator);
163         map.put(DataModel.class, new FormCreator());
164         map.put(DefaultTableModelExt.class, new TableCreator());
165         ComponentCreator listCreator = new ListCreator();
166         // map.put(XListModel.class, listCreator);
167
map.put(ListModel JavaDoc.class, listCreator);
168         ComponentCreator listPanelCreator = new ListPanelCreator();
169         map.put(List JavaDoc.class, listPanelCreator);
170         map.put(Object JavaDoc[].class, listPanelCreator);
171         map.put(Link.class, new LinkLabelCreator());
172         ImagePanelCreator imagePanelCreator = new ImagePanelCreator();
173         map.put(Image JavaDoc.class, imagePanelCreator);
174         map.put(Icon JavaDoc.class, imagePanelCreator);
175         DatePickerCreator datePickerCreator = new DatePickerCreator();
176         map.put(Date JavaDoc.class, datePickerCreator);
177         map.put(Calendar JavaDoc.class, datePickerCreator);
178     }
179
180     protected void initAssignablesClasses(List JavaDoc assignables) {
181         assignables.add(DataModel.class);
182         assignables.add(DefaultTableModelExt.class);
183         assignables.add(List JavaDoc.class);
184         // assignables.add(Image.class);
185
// assignables.add(Icon.class);
186
// assignables.add(XListModel.class);
187
}
188
189     // --------------------- lazy access
190
private List JavaDoc getAssignableClasses() {
191         if (assignables == null) {
192             assignables = new ArrayList JavaDoc();
193             initAssignablesClasses(assignables);
194         }
195         return assignables;
196     }
197
198     private Map JavaDoc getCreatorMap() {
199         if (creatorMap == null) {
200             creatorMap = new HashMap JavaDoc();
201             initCreators(creatorMap);
202         }
203         return creatorMap;
204     }
205
206     // ----------------------------- default creators
207

208     /**
209      */

210     public static class ListPanelCreator implements ComponentCreator {
211
212         /**
213          * creates and returns a JXListPanel.
214          */

215         public JComponent JavaDoc createComponent(MetaData metaData) {
216             JXListPanel list = new JXListPanel();
217             list.setName(metaData.getName());
218             list.getList().setName(metaData.getName());
219             return list;
220         }
221
222         // private void configureList(JList list, MetaData metaData) {
223
// list.setName(metaData.getName());
224
// setListRenderer(list, metaData);
225
// installMetaDataListener(list, metaData);
226
// }
227
//
228
// /**
229
// * PENDING: no possibility to remove the listener if
230
// * MetaData is removed from model
231
// */
232
// private void installMetaDataListener(final JList list, final MetaData
233
// metaData) {
234
// PropertyChangeListener l = new PropertyChangeListener() {
235
//
236
// public void propertyChange(PropertyChangeEvent evt) {
237
// if (DataConstants.RENDER_PROPERTY_NAME.equals(evt.getPropertyName()))
238
// {
239
// setListRenderer(list, metaData);
240
// }
241
//
242
// }
243
//
244
// };
245
// metaData.addPropertyChangeListener(l);
246
//
247
// }
248
//
249
// private void setListRenderer(JList list, MetaData metaData) {
250
// Object renderProperty =
251
// metaData.getCustomProperty(DataConstants.RENDER_PROPERTY_NAME);
252
// // can't do - coupling to JGoodies ValueModel
253
// // working for Beans only.
254
// // if (renderProperty != null) {
255
// // ValueCellRenderer renderer = new ValueCellRenderer();
256
// // renderer.setPropertyName(String.valueOf(renderProperty));
257
// // list.setCellRenderer(renderer);
258
// // }
259
// }
260
}
261
262     /**
263      */

264     public static class ListCreator implements ComponentCreator {
265
266         /**
267          * creates and returns a JScrollPane containing a JList.
268          */

269         public JComponent JavaDoc createComponent(MetaData metaData) {
270             JList JavaDoc list = new JList JavaDoc();
271
272             // list.setPreferredSize(new Dimension(100, 100));
273
JScrollPane JavaDoc pane = new JScrollPane JavaDoc(list);
274             pane.setName(metaData.getName());
275             list.setName(metaData.getName());
276             return pane;
277         }
278     }
279
280     public static class TableCreator implements ComponentCreator {
281
282         /**
283          * creates and returns a JScrollPane containing a JXTable.
284          */

285         public JComponent JavaDoc createComponent(MetaData metaData) {
286             JXTable table = new JXTable();
287             JScrollPane JavaDoc pane = new JScrollPane JavaDoc(table);
288             table.setName(metaData.getName());
289             pane.setName(metaData.getName());
290             return pane;
291         }
292     }
293
294     /**
295      *
296      */

297     public static class FormCreator implements ComponentCreator {
298         
299         /**
300          * creates and returns a JForm.
301          * PENDING: need to wrap into a JScrollPane by default?
302          */

303         public JComponent JavaDoc createComponent(MetaData metaData) {
304             JForm form = new JForm();
305             form.setName(metaData.getName());
306             // visual debugging...
307
// form.setBorder(BorderFactory.createLineBorder(Color.BLUE));
308
return form;
309         }
310     }
311
312     /**
313      */

314     public static class BooleanCreator implements ComponentCreator {
315         
316         /**
317          * creates and returns a JCheckBox.
318          */

319         public JComponent JavaDoc createComponent(MetaData metaData) {
320             JCheckBox JavaDoc box = new JCheckBox JavaDoc();
321             box.setName(metaData.getName());
322             // JW: logic state - move to Binding
323
box.setEnabled(!metaData.isReadOnly());
324             return box;
325         }
326     }
327
328     /**
329      * creates JSpinner if metaData is NumberMetaData, the map's fallback
330      * component otherwise.
331      *
332      */

333     public class NumberCreator implements ComponentCreator {
334
335         public JComponent JavaDoc createComponent(MetaData metaData) {
336             if (!(metaData instanceof NumberMetaData)) {
337                 // Hack: prevents making static... where else to put?
338
return getFallBackComponentCreator().createComponent(metaData);
339             }
340             JComponent JavaDoc comp = createComponent((NumberMetaData) metaData);
341             comp.setName(metaData.getName());
342             return comp;
343         }
344
345         public JComponent JavaDoc createComponent(NumberMetaData numberMetaData) {
346             Class JavaDoc fieldClass = numberMetaData.getElementClass();
347             Number JavaDoc min = numberMetaData.getMinimum();
348             Number JavaDoc max = numberMetaData.getMaximum();
349             // JW: edit constraint - move to SpinnerBinding
350
if ((min != null) && (max != null)) {
351                 SpinnerModel JavaDoc spinnerModel = null;
352                 if ((fieldClass == Integer JavaDoc.class) || (fieldClass == Long JavaDoc.class)
353                         || (fieldClass == Short JavaDoc.class)
354                         || (fieldClass == int.class)) {
355                     spinnerModel = new SpinnerNumberModel JavaDoc(min.intValue(), min
356                             .intValue(), max.intValue(), 1);
357                 } else if ((fieldClass == Float JavaDoc.class)
358                         || (fieldClass == Double JavaDoc.class)
359                         || (fieldClass == float.class)
360                         || (fieldClass == double.class)) {
361
362                     // **@todo aim: need to add precision to NumberMetaData */
363
spinnerModel = new SpinnerNumberModel JavaDoc(min.doubleValue(),
364                             min.doubleValue(), max.doubleValue(), .01);
365                 }
366                 if (spinnerModel != null) {
367                     return new JSpinner JavaDoc(spinnerModel);
368                 }
369             }
370             // Hack: prevents making static... where else to put?
371
return getFallBackComponentCreator()
372                     .createComponent(numberMetaData);
373         }
374     }
375
376     /**
377      */

378     public static class TextCreator implements ComponentCreator {
379         /**
380          * creates and returns a JTextComponent.
381          */

382
383         public JComponent JavaDoc createComponent(MetaData metaData) {
384             if (metaData instanceof StringMetaData) {
385                 return createComponent((StringMetaData) metaData);
386             }
387             int fieldLength = metaData.getDisplayWidth();
388             JTextField JavaDoc field = new JTextField JavaDoc((fieldLength > 0) ? fieldLength
389                     : 24);
390             field.setName(metaData.getName());
391             return field;
392         }
393
394         public JComponent JavaDoc createComponent(StringMetaData stringMetaData) {
395             if (stringMetaData.isMultiLine()) {
396                 int columns = stringMetaData.getDisplayWidth();
397                 int rows = Math.min(stringMetaData.getMaxLength() / columns, 5);
398                 JTextArea JavaDoc area = new JTextArea JavaDoc(rows, columns);
399                 JScrollPane JavaDoc pane = new JScrollPane JavaDoc(area);
400                 area.setName(stringMetaData.getName());
401                 pane.setName(stringMetaData.getName());
402                 return pane;
403             }
404             int fieldLength = Math.min(stringMetaData.getDisplayWidth(),
405                     stringMetaData.getMaxLength());
406             JTextField JavaDoc field = new JTextField JavaDoc(fieldLength);
407             field.setName(stringMetaData.getName());
408             return field;
409         }
410     }
411
412     /**
413      */

414     public static class EnumerationCreator implements ComponentCreator {
415
416         public JComponent JavaDoc createComponent(MetaData metaData) {
417             JComponent JavaDoc box = null;
418             if (metaData instanceof EnumeratedMetaData) {
419                 box = createComponent((EnumeratedMetaData) metaData);
420             } else {
421                 box = new JComboBox JavaDoc();
422             }
423             box.setName(metaData.getName());
424             return box;
425         }
426
427         public JComponent JavaDoc createComponent(EnumeratedMetaData enumMetaData) {
428             Object JavaDoc values[] = enumMetaData.getEnumeration();
429             if (values.length > 3) {
430                 return new JComboBox JavaDoc();
431             }
432             // JW: constraint... move to RadioGroupBinding
433
return new JXRadioGroup(values);
434         }
435     }
436
437     /**
438      *
439      */

440     public static class LabelCreator implements ComponentCreator {
441
442         public JComponent JavaDoc createComponent(MetaData metaData) {
443             JLabel JavaDoc label = new JLabel JavaDoc();
444             label.setName(metaData.getName());
445             return label;
446         }
447     }
448
449     /**
450      */

451     public static class LinkLabelCreator implements ComponentCreator {
452
453         public JComponent JavaDoc createComponent(MetaData metaData) {
454             JLabel JavaDoc label = new JLabel JavaDoc();
455             label.setName(metaData.getName());
456             label.addMouseListener(new LinkHandler());
457             label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
458             return label;
459         }
460     }
461
462     /**
463      *
464      */

465     public static class ImagePanelCreator implements ComponentCreator {
466
467         public JComponent JavaDoc createComponent(MetaData metaData) {
468             JXImagePanel label = new JXImagePanel();
469             label.setName(metaData.getName());
470             return label;
471         }
472     }
473
474     /**
475      */

476     public static class DatePickerCreator implements ComponentCreator {
477
478         public JComponent JavaDoc createComponent(MetaData metaData) {
479             JXDatePicker label = new JXDatePicker();
480             label.setName(metaData.getName());
481             return label;
482         }
483     }
484 }
485
Popular Tags