001: /*
002: * Copyright (C) 2005 Jeff Tassin
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package com.jeta.swingbuilder.gui.properties;
020:
021: import java.awt.Color;
022: import java.awt.Component;
023: import java.awt.Dimension;
024: import java.awt.Font;
025: import java.beans.BeanDescriptor;
026: import java.beans.PropertyEditor;
027: import java.beans.PropertyEditorManager;
028: import java.util.ArrayList;
029: import java.util.Collection;
030: import java.util.Hashtable;
031: import java.util.Iterator;
032: import java.util.LinkedList;
033: import java.util.ListIterator;
034:
035: import javax.swing.Icon;
036: import javax.swing.table.AbstractTableModel;
037:
038: import com.jeta.forms.gui.beans.DynamicBeanInfo;
039: import com.jeta.forms.gui.beans.JETABean;
040: import com.jeta.forms.gui.beans.JETAPropertyDescriptor;
041: import com.jeta.forms.gui.form.FormComponent;
042: import com.jeta.forms.logger.FormsLogger;
043: import com.jeta.swingbuilder.gui.commands.CommandUtils;
044: import com.jeta.swingbuilder.gui.commands.SetPropertyCommand;
045: import com.jeta.swingbuilder.gui.editor.FormEditor;
046: import com.jeta.swingbuilder.gui.properties.editors.UnknownEditor;
047:
048: /**
049: * TableModel for managing properties for a given bean.
050: *
051: * @author Jeff Tassin
052: */
053: public class PropertyTableModel extends AbstractTableModel {
054: private JETAPropertyDescriptor[] m_descriptors;
055:
056: private BeanDescriptor m_beandescriptor;
057:
058: private DynamicBeanInfo m_beaninfo;
059:
060: private JETABean m_bean;
061:
062: // Cached property editors.
063: private static Hashtable m_prop_editors;
064:
065: // Shared instance of a comparator
066: private static DescriptorComparator comparator = new DescriptorComparator();
067:
068: private UnknownEditor m_unknown_editor = new UnknownEditor();
069:
070: private static final int NUM_COLUMNS = 2;
071:
072: public static final int COL_NAME = 0;
073:
074: public static final int COL_VALUE = 1;
075:
076: // Filter options
077: public static final int VIEW_ALL = 0;
078:
079: public static final int VIEW_PREFERRED = 7;
080:
081: private int currentFilter = VIEW_PREFERRED;
082:
083: /**
084: * A list of PropertyEditorListeners that want to receive
085: * PropertyEditorEvents
086: */
087: private LinkedList m_listeners = new LinkedList();
088:
089: public PropertyTableModel() {
090:
091: if (m_prop_editors == null) {
092: m_prop_editors = new Hashtable();
093: registerPropertyEditors();
094: }
095: setFilter(VIEW_ALL);
096: }
097:
098: public PropertyTableModel(JETABean jbean) {
099: this ();
100: setBean(jbean);
101: }
102:
103: public void addPropertyListener(PropertyEditorListener listener) {
104: m_listeners.add(listener);
105: }
106:
107: /**
108: * Filters the table to display only properties with specific attributes.
109: * Will sort the table after the data has been filtered.
110: *
111: * @param view
112: * The properties to display.
113: */
114: public void filterTable(int view) {
115: if (m_beaninfo == null)
116: return;
117:
118: Collection descriptors = m_beaninfo.getPropertyDescriptors();
119:
120: // Use collections to filter out unwanted properties
121: ArrayList list = new ArrayList();
122: list.addAll(descriptors);
123:
124: ListIterator iterator = list.listIterator();
125: JETAPropertyDescriptor desc;
126: while (iterator.hasNext()) {
127: desc = (JETAPropertyDescriptor) iterator.next();
128:
129: switch (view) {
130: case VIEW_ALL:
131: if (desc.isHidden()) {
132: iterator.remove();
133: }
134: break;
135:
136: case VIEW_PREFERRED:
137: if (!desc.isPreferred() || desc.isHidden()) {
138: iterator.remove();
139: }
140: // System.out.println( "PropertyTableModel.filterProps: desc: "
141: // +
142: // desc.getName() + " pref: " + desc.isPreferred() );
143: break;
144: }
145: }
146: m_descriptors = (JETAPropertyDescriptor[]) list
147: .toArray(new JETAPropertyDescriptor[list.size()]);
148: fireTableDataChanged();
149: }
150:
151: public void firePropertyEditorEvent(PropertyEditorEvent evt) {
152: Iterator iter = m_listeners.iterator();
153: while (iter.hasNext()) {
154: PropertyEditorListener listener = (PropertyEditorListener) iter
155: .next();
156: listener.propertyChanged(evt);
157: }
158: }
159:
160: /**
161: * Sets the current filter of the Properties.
162: *
163: * @param filter
164: * one of VIEW_ constants
165: */
166: public void setFilter(int filter) {
167: this .currentFilter = filter;
168: filterTable(currentFilter);
169: }
170:
171: /**
172: * Returns the current filter type
173: */
174: public int getFilter() {
175: return currentFilter;
176: }
177:
178: /**
179: * Return the current object that is represented by this model.
180: */
181: public JETABean getBean() {
182: return m_bean;
183: }
184:
185: /**
186: * Get row count (total number of properties shown)
187: */
188: public int getRowCount() {
189: if (m_descriptors == null) {
190: return 0;
191: }
192: return m_descriptors.length;
193: }
194:
195: /**
196: * Get column count (2: name, value)
197: */
198: public int getColumnCount() {
199: return NUM_COLUMNS;
200: }
201:
202: /**
203: * Check if given cell is editable
204: *
205: * @param row
206: * table row
207: * @param col
208: * table column
209: */
210: public boolean isCellEditable(int row, int col) {
211: if (col == COL_VALUE) {
212: Class type = getPropertyType(row);
213: if (type != null) {
214: PropertyEditor editor = (PropertyEditor) m_prop_editors
215: .get(type);
216: if (editor == null)
217: return false;
218: }
219:
220: JETAPropertyDescriptor pd = getPropertyDescriptor(row);
221: JETAPropertyDescriptor dpd = (JETAPropertyDescriptor) pd;
222: return dpd.isWritable();
223: // return ( pd.getWriteMethod() == null) ? false : true;
224: } else {
225: return false;
226: }
227: }
228:
229: /**
230: * Get text value for cell of table
231: *
232: * @param row
233: * table row
234: * @param col
235: * table column
236: */
237: public Object getValueAt(int row, int col) {
238: Object value = null;
239:
240: if (col == COL_NAME) {
241: value = m_descriptors[row].getDisplayName();
242: } else {
243: try {
244: // COL_VALUE is handled
245: JETAPropertyDescriptor dpd = getPropertyDescriptor(row);
246: value = dpd.getPropertyValue(m_bean);
247: } catch (Exception e) {
248: e.printStackTrace();
249: }
250: }
251: return value;
252: }
253:
254: /**
255: * Returns the Java type info for the property at the given row.
256: */
257: public Class getPropertyType(int row) {
258: return m_descriptors[row].getPropertyType();
259: }
260:
261: /**
262: * Returns the PropertyDescriptor for the row.
263: */
264: public JETAPropertyDescriptor getPropertyDescriptor(int row) {
265: return (JETAPropertyDescriptor) m_descriptors[row];
266: }
267:
268: /**
269: * Returns a new instance of the property editor for a given class. If an
270: * editor is not specified in the property descriptor then it is looked up
271: * in the PropertyEditorManager.
272: */
273: public PropertyEditor getPropertyEditor(int row) {
274: Class cls = m_descriptors[row].getPropertyEditorClass();
275: PropertyEditor editor = null;
276:
277: if (cls != null) {
278:
279: try {
280: editor = (PropertyEditor) cls.newInstance();
281: } catch (Exception ex) {
282: // XXX - debug
283: System.out
284: .println("PropertyTableModel: Instantiation exception creating PropertyEditor");
285: }
286: } else {
287:
288: // Look for a registered editor for this type.
289: Class type = getPropertyType(row);
290: if (type != null) {
291: editor = (PropertyEditor) m_prop_editors.get(type);
292: if (editor == null) {
293: // Load a shared instance of the property editor.
294: editor = PropertyEditorManager.findEditor(type);
295: /**
296: * The property editor manager will return default editors
297: * for the Java primitives. Everything else is up to the
298: * application.
299: */
300:
301: if (editor != null)
302: m_prop_editors.put(type, editor);
303: }
304:
305: if (editor == null) {
306: // Use the editor for Object.class
307: editor = (PropertyEditor) m_prop_editors
308: .get(Object.class);
309: if (editor == null) {
310: editor = PropertyEditorManager
311: .findEditor(Object.class);
312: if (editor != null)
313: m_prop_editors.put(Object.class, editor);
314: }
315:
316: }
317:
318: if (editor == null) {
319: editor = m_unknown_editor;
320: }
321:
322: // System.out.println( "PropertyEditorManager returned: " +
323: // editor +
324: // " for type: " + type );
325:
326: }
327: }
328: return editor;
329: }
330:
331: /**
332: * Returns a flag indicating if the encapsulated object has a customizer.
333: */
334: public boolean hasCustomizer() {
335: if (m_beandescriptor != null) {
336: Class cls = m_beandescriptor.getCustomizerClass();
337: return (cls != null);
338: }
339:
340: return false;
341: }
342:
343: /**
344: * Gets the customizer for the current object.
345: *
346: * @return New instance of the customizer or null if there isn't a
347: * customizer.
348: */
349: public Component getCustomizer() {
350: Component customizer = null;
351:
352: if (m_beandescriptor != null) {
353: Class cls = m_beandescriptor.getCustomizerClass();
354:
355: if (cls != null) {
356: try {
357: customizer = (Component) cls.newInstance();
358: } catch (Exception ex) {
359: // XXX - debug
360: System.out
361: .println("PropertyTableModel: Instantiation exception creating Customizer");
362: }
363: }
364: }
365:
366: return customizer;
367: }
368:
369: /**
370: * Method which registers property editors for types.
371: */
372: private static void registerPropertyEditors() {
373: PropertyEditorManager
374: .registerEditor(
375: Font.class,
376: com.jeta.swingbuilder.gui.properties.editors.FontEditor.class);
377: PropertyEditorManager
378: .registerEditor(
379: Color.class,
380: com.jeta.swingbuilder.gui.properties.editors.ColorEditor.class);
381: PropertyEditorManager
382: .registerEditor(
383: Boolean.class,
384: com.jeta.swingbuilder.gui.properties.editors.BooleanEditor.class);
385: PropertyEditorManager
386: .registerEditor(
387: boolean.class,
388: com.jeta.swingbuilder.gui.properties.editors.BooleanEditor.class);
389: PropertyEditorManager
390: .registerEditor(
391: String.class,
392: com.jeta.swingbuilder.gui.properties.editors.StringEditor.class);
393: PropertyEditorManager
394: .registerEditor(
395: Dimension.class,
396: com.jeta.swingbuilder.gui.properties.editors.DimensionEditor.class);
397: PropertyEditorManager
398: .registerEditor(
399: Icon.class,
400: com.jeta.swingbuilder.gui.properties.editors.IconEditor.class);
401:
402: PropertyEditorManager
403: .registerEditor(
404: byte.class,
405: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.ByteEditor.class);
406:
407: PropertyEditorManager
408: .registerEditor(
409: short.class,
410: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.ShortEditor.class);
411: PropertyEditorManager
412: .registerEditor(
413: Short.class,
414: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.ShortEditor.class);
415:
416: PropertyEditorManager
417: .registerEditor(
418: int.class,
419: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.IntegerEditor.class);
420: PropertyEditorManager
421: .registerEditor(
422: Integer.class,
423: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.IntegerEditor.class);
424:
425: PropertyEditorManager
426: .registerEditor(
427: long.class,
428: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.LongEditor.class);
429: PropertyEditorManager
430: .registerEditor(
431: Long.class,
432: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.LongEditor.class);
433:
434: PropertyEditorManager
435: .registerEditor(
436: float.class,
437: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.FloatEditor.class);
438: PropertyEditorManager
439: .registerEditor(
440: Float.class,
441: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.FloatEditor.class);
442:
443: PropertyEditorManager
444: .registerEditor(
445: double.class,
446: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.DoubleEditor.class);
447: PropertyEditorManager
448: .registerEditor(
449: Double.class,
450: com.jeta.swingbuilder.gui.properties.editors.NumericEditor.DoubleEditor.class);
451:
452: PropertyEditorManager
453: .registerEditor(
454: com.jeta.forms.store.properties.ButtonGroupProperty.class,
455: com.jeta.swingbuilder.gui.properties.editors.ButtonGroupEditor.class);
456: PropertyEditorManager
457: .registerEditor(
458: com.jeta.forms.store.properties.ItemsProperty.class,
459: com.jeta.swingbuilder.gui.properties.editors.ItemsEditor.class);
460: PropertyEditorManager
461: .registerEditor(
462: com.jeta.forms.store.properties.TransformOptionsProperty.class,
463: com.jeta.swingbuilder.gui.properties.editors.ComboEditor.class);
464: PropertyEditorManager
465: .registerEditor(
466: com.jeta.forms.store.properties.CompoundBorderProperty.class,
467: com.jeta.swingbuilder.gui.properties.editors.BorderEditor.class);
468: PropertyEditorManager
469: .registerEditor(
470: com.jeta.forms.store.properties.CompoundLineProperty.class,
471: com.jeta.swingbuilder.gui.properties.editors.LineEditor.class);
472: PropertyEditorManager
473: .registerEditor(
474: com.jeta.forms.store.properties.effects.PaintProperty.class,
475: com.jeta.swingbuilder.gui.properties.editors.FillEditor.class);
476: PropertyEditorManager
477: .registerEditor(
478: com.jeta.forms.store.properties.ScrollBarsProperty.class,
479: com.jeta.swingbuilder.gui.properties.editors.ScrollBarsEditor.class);
480:
481: PropertyEditorManager
482: .registerEditor(
483: com.jeta.forms.store.properties.TabbedPaneProperties.class,
484: com.jeta.swingbuilder.gui.properties.editors.TabbedPaneEditor.class);
485:
486: }
487:
488: /**
489: * Set the table model to represents the properties of the object.
490: */
491: public void setBean(JETABean bean) {
492: if (bean == m_bean) {
493: fireTableDataChanged();
494: return;
495: }
496:
497: m_bean = bean;
498:
499: if (m_bean == null || m_bean.getDelegate() == null) {
500: if (m_descriptors != null && m_descriptors.length > 0) {
501: m_descriptors = new JETAPropertyDescriptor[0];
502: m_beaninfo = null;
503: fireTableDataChanged();
504: }
505: return;
506: }
507:
508: try {
509: m_beaninfo = bean.getBeanInfo();
510: } catch (Exception ex) {
511: FormsLogger.severe(ex);
512: }
513:
514: if (m_beaninfo != null) {
515: m_beandescriptor = m_beaninfo.getBeanDescriptor();
516: filterTable(getFilter());
517: }
518: }
519:
520: /**
521: * Set the value of the Values column.
522: */
523: public void setValueAt(Object value, int row, int column) {
524: if (column != COL_VALUE || m_descriptors == null
525: || row > m_descriptors.length) {
526: return;
527: }
528:
529: try {
530: Object old_value = getValueAt(row, column);
531:
532: if (old_value == null && value == null)
533: return;
534:
535: if (old_value == value)
536: return;
537:
538: if (value != null && value.equals(old_value))
539: return;
540:
541: if (old_value != null && old_value.equals(value))
542: return;
543:
544: // System.out.println( "setValueAt new_value: " + value + " " +
545: // value.hashCode() + " old_value: " + old_value + " " +
546: // old_value.hashCode() );
547:
548: JETAPropertyDescriptor dpd = getPropertyDescriptor(row);
549: SetPropertyCommand cmd = new SetPropertyCommand(dpd,
550: m_bean, value, old_value, FormComponent
551: .getParentForm(m_bean));
552: CommandUtils.invoke(cmd, FormEditor.getEditor(m_bean));
553: fireTableRowsUpdated(row, row);
554: firePropertyEditorEvent(new PropertyEditorEvent(
555: PropertyEditorEvent.BEAN_PROPERTY_CHANGED, m_bean));
556: } catch (Exception e) {
557: FormsLogger.severe(e);
558: }
559: }
560:
561: }
|