KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > ui > IndexedPropertyChildren


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.java.ui;
21
22 import java.lang.reflect.InvocationTargetException JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Arrays JavaDoc;
25 import java.util.LinkedList JavaDoc;
26
27 import java.beans.PropertyChangeListener JavaDoc;
28 import java.beans.PropertyChangeEvent JavaDoc;
29
30 import org.openide.explorer.propertysheet.DefaultPropertyModel;
31 import org.openide.explorer.propertysheet.PropertyModel;
32 import org.openide.nodes.Index;
33
34
35 /**
36  * Serves as a base for Children, that present some indexed property's values.
37  * The Children object watches a specified (indexed) property on a Bean and updates
38  * accordingly. It also supports reorder-like manipulations on children, reflecting
39  * those changes to the underlying bean as set-operations on the indexed property.
40  */

41 public abstract class IndexedPropertyChildren extends Index.KeysChildren {
42     /** Property model for getting/settings the property.
43     */

44     private PropertyModel model;
45
46     /** Listener that updates the display from the underlying bean.
47     */

48     private PropertyChangeListener JavaDoc beanListener;
49
50     /** States that changes from the bean should be ignored. Used to prevent
51      * event loops between the bean and the children and unnecessary updates
52      */

53     boolean ignoreBeanChanges;
54
55     /**
56      * Initializes a new Children. It uses DefaultPropertyModel for communication
57      * with the bean.
58      */

59     public IndexedPropertyChildren(Object JavaDoc bean, String JavaDoc propertyName) {
60         this(new DefaultPropertyModel(bean, propertyName));
61     }
62
63     /**
64      * Initializes a new Children instance with the given property model.
65      */

66     public IndexedPropertyChildren(PropertyModel m) {
67         super(new LinkedList JavaDoc());
68         this.model = m;
69         
70         if (!m.getPropertyType().isArray()) {
71             throw new IllegalArgumentException JavaDoc("Property of array type expected."); //NOI18N
72
}
73     }
74
75     /** Called when the children are about to be displayed.
76         Attaches a listener to the target bean via property model and monitors its changes.
77     */

78     protected void addNotify() {
79         model.addPropertyChangeListener(getBeanListener());
80         refreshData();
81     }
82
83     /** Called after the children are removed from the display.
84         Currently only removes the property listener. The method could as well omitted,
85      * because it is called during node's finalize and the listener is Weak anyway.
86     */

87     protected void removeNotify() {
88         model.removePropertyChangeListener(getBeanListener());
89    }
90
91     protected final PropertyChangeListener JavaDoc getBeanListener() {
92         if (beanListener != null) {
93             return beanListener;
94         }
95         return beanListener = createBeanListener();
96     }
97
98     /**
99      * Creates a listener for the bean. This implementation creates a WeakListener
100      * that watches for the property changes on the property passed to the Children
101      * constructor and, if it arrives, invokes refresh()
102      */

103     protected PropertyChangeListener JavaDoc createBeanListener() {
104         return new SourceListener();
105     }
106
107     /** Updates the children list from the source.
108         This implementation obtains the current value from the property model and
109         calls update().
110     */

111     protected final void refreshData() {
112         Collection JavaDoc c;
113         try {
114             c = Arrays.asList((Object JavaDoc[])model.getValue());
115         } catch (InvocationTargetException JavaDoc e) {
116             // just ignore getter exceptions.
117
return;
118         }
119
120         this.list.clear();
121         this.list.addAll(c);
122         update();
123     }
124
125     /**
126      * Creates the array value from the given collection. The standard implementation
127      * uses reflection to construct the returned array instance. The type of array
128      * elements is extracted from the property model.
129      */

130     protected Object JavaDoc[] createValue(Collection JavaDoc value) {
131         Class JavaDoc compType = model.getPropertyType().getComponentType();
132         Object JavaDoc[] val = (Object JavaDoc[])java.lang.reflect.Array.newInstance(compType, value.size());
133         return value.toArray(val);
134     }
135
136     /** Performs a reorder on the indexed property.
137         This implementation reorders children's node list using superclass'
138         reorder() method, then tries to update the bean with the new property value.
139         If this fails, reorder updates the subnode list from the bean's current
140         property value.
141     */

142     protected void reorder(int []permutation) {
143         super.reorder(permutation);
144         try {
145             try {
146                 ignoreBeanChanges = true;
147                 Object JavaDoc[] value = createValue(list);
148                 model.setValue(value);
149             } finally {
150                 ignoreBeanChanges = false;
151             }
152         } catch (InvocationTargetException JavaDoc e) {
153             handleReorderException(e);
154         }
155     }
156
157     /**
158      * Reports a reorder error to the user. This (default) implementation does
159      * nothing, it simply refreshes the display from the current bean's data.
160      * @param InvocationTargetException thrown by the property model.
161      */

162     protected void handleReorderException(InvocationTargetException JavaDoc e) {
163         refreshData();
164     }
165
166     /*************************************************************************/
167     private class SourceListener implements PropertyChangeListener JavaDoc {
168         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
169             if (PropertyModel.PROP_VALUE.equals(evt.getPropertyName())) {
170 // IndexedPropertyChildren.this.refresh();
171
IndexedPropertyChildren.this.refreshData();
172             }
173         }
174     }
175 }
176
Popular Tags