001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.visualweb.propertyeditors.binding;
042:
043: import java.beans.PropertyDescriptor;
044: import java.util.ArrayList;
045: import java.util.Enumeration;
046: import java.util.HashMap;
047: import java.util.List;
048: import java.util.Map;
049: import java.util.Vector;
050: import java.awt.event.ActionListener;
051: import javax.swing.Icon;
052: import javax.swing.JComponent;
053: import javax.swing.tree.DefaultTreeModel;
054: import javax.swing.tree.TreeNode;
055: import com.sun.rave.designtime.DesignBean;
056: import org.netbeans.modules.visualweb.propertyeditors.binding.nodes.PropertyTargetNode;
057: import org.netbeans.modules.visualweb.propertyeditors.util.Bundle;
058:
059: public abstract class BindingTargetNode implements TreeNode {
060:
061: private static final Bundle bundle = Bundle
062: .getBundle(BindingTargetNode.class);
063:
064: //------------------------------------------------------------------------------- STATIC METHODS
065:
066: private static List factoryList = new ArrayList();
067:
068: public static void _registerBindingTargetNodeFactory(
069: BindingTargetNodeFactory btnf) {
070: factoryList.add(0, btnf);
071: }
072:
073: public static BindingTargetNode _createTargetNode(
074: BindingTargetNode parent, DesignBean bean,
075: PropertyDescriptor[] propPath, Object propInstance) {
076:
077: if (bean == null)
078: return null;
079: Class targetClass = propInstance != null ? propInstance
080: .getClass() : null;
081: if (targetClass == null && propPath != null
082: && propPath.length > 0) {
083: Object o = PropertyBindingHelper.getPropInstance(bean,
084: propPath);
085: if (o != null) {
086: propInstance = o;
087: targetClass = o.getClass();
088: } else {
089: targetClass = propPath[propPath.length - 1]
090: .getPropertyType();
091: }
092: }
093: if (targetClass == null) {
094: Object o = bean.getInstance();
095: if (o != null) {
096: propInstance = o;
097: targetClass = o.getClass();
098: } else {
099: targetClass = bean.getBeanInfo().getBeanDescriptor()
100: .getBeanClass();
101: }
102: }
103: for (int i = 0; i < factoryList.size(); i++) {
104: BindingTargetNodeFactory tnf = (BindingTargetNodeFactory) factoryList
105: .get(i);
106: if (tnf.supportsTargetClass(targetClass)) {
107: BindingTargetNode btn = tnf.createTargetNode(parent,
108: bean, propPath, propInstance);
109: if (btn != null) {
110: return btn;
111: }
112: }
113: }
114: return new PropertyTargetNode(parent, bean, propPath,
115: propInstance);
116: }
117:
118: //----------------------------------------------------------------------------- abstract methods
119:
120: public abstract boolean lazyLoad();
121:
122: public abstract boolean isValidBindingTarget();
123:
124: public abstract String getBindingExpressionPart();
125:
126: public abstract Class getTargetTypeClass();
127:
128: public abstract String getDisplayText(boolean enabled);
129:
130: public BindingTargetNode(BindingTargetNode parent) {
131: this .parent = parent;
132: }
133:
134: protected HashMap userDataHash = new HashMap();
135:
136: public Map getUserDataMap() {
137: return userDataHash;
138: }
139:
140: public boolean hasDisplayIcon() {
141: return false;
142: }
143:
144: public Icon getDisplayIcon(boolean enabled) {
145: // subclasses can put their custom icon here - only called if hasCustomDisplayIcon() returns true
146: return null;
147: }
148:
149: public JComponent getCustomDisplayPanel(
150: ActionListener updateCallback) {
151: return null;
152: }
153:
154: public String getTargetTypeDisplayName() {
155: Class c = getTargetTypeClass();
156: if (c != null) {
157: return PropertyBindingHelper.getPrettyTypeName(c.getName());
158: }
159: return ""; //NOI18N
160: }
161:
162: protected BindingTargetNode parent;
163: protected Vector children = new Vector();
164: protected boolean loaded = false;
165:
166: //------------------------------------------------------------------------ Tree Building Methods
167:
168: public DefaultTreeModel getTreeModel() {
169: TreeNode p = getParent();
170: while (p != null) {
171: if (p instanceof BindingTargetNode.Root) {
172: return ((BindingTargetNode.Root) p).getTreeModel();
173: }
174: p = p.getParent();
175: }
176: return null;
177: }
178:
179: public void add(BindingTargetNode child) {
180: if (child instanceof BindingTargetNode) {
181: children.add(child);
182: child.setParent(this );
183: }
184: }
185:
186: public void add(int index, BindingTargetNode child) {
187: if (child instanceof BindingTargetNode) {
188: children.add(index, child);
189: child.setParent(this );
190: }
191: }
192:
193: public void remove(BindingTargetNode child) {
194: children.remove(child);
195: }
196:
197: public void removeAll() {
198: children.clear();
199: loaded = false;
200: }
201:
202: public void setParent(BindingTargetNode parent) {
203: if (parent instanceof BindingTargetNode) {
204: this .parent = parent;
205: }
206: }
207:
208: //------------------------------------------------------------------------------------- TreeNode
209:
210: public TreeNode getChildAt(int childIndex) {
211: if (!loaded) {
212: loaded = lazyLoad();
213: }
214: if (children.size() > childIndex) {
215: return (TreeNode) children.get(childIndex);
216: }
217: return null;
218: }
219:
220: public int getChildCount() {
221: if (!loaded) {
222: loaded = lazyLoad();
223: }
224: return children.size();
225: }
226:
227: public TreeNode getParent() {
228: return parent;
229: }
230:
231: public int getIndex(TreeNode node) {
232: if (!loaded) {
233: loaded = lazyLoad();
234: }
235: return children.indexOf(node);
236: }
237:
238: public boolean getAllowsChildren() {
239: return true;
240: }
241:
242: public boolean isLeaf() {
243: if (!loaded) {
244: loaded = lazyLoad();
245: }
246: return children.size() == 0;
247: }
248:
249: public Enumeration children() {
250: if (!loaded) {
251: loaded = lazyLoad();
252: }
253: return children.elements();
254: }
255:
256: //----------------------------------------------------------------------- BindingTargetNode.Root
257:
258: public static class Root extends BindingTargetNode {
259: public Root() {
260: super (null);
261: }
262:
263: protected DefaultTreeModel treeModel;
264:
265: protected void setTreeModel(DefaultTreeModel treeModel) {
266: this .treeModel = treeModel;
267: }
268:
269: public DefaultTreeModel getTreeModel() {
270: return treeModel;
271: }
272:
273: public boolean lazyLoad() {
274: return true;
275: }
276:
277: public String getDisplayText(boolean enableNode) {
278: return null;
279: }
280:
281: public boolean isValidBindingTarget() {
282: return false;
283: }
284:
285: public String getBindingExpressionPart() {
286: return null;
287: }
288:
289: public Class getTargetTypeClass() {
290: return null;
291: }
292: }
293:
294: //----------------------------------------------------------------------- BindingTargetNode.Null
295:
296: public static class Null extends BindingTargetNode {
297: public Null(BindingTargetNode parent) {
298: super (parent);
299: this .displayText = "<html><b>"
300: + bundle.getMessage("propertyNotBound")
301: + "</b></html>"; //NOI18N
302: }
303:
304: public boolean lazyLoad() {
305: return true;
306: }
307:
308: protected String displayText;
309:
310: public String getDisplayText(boolean enableNode) {
311: return displayText;
312: }
313:
314: public boolean isValidBindingTarget() {
315: return true;
316: }
317:
318: public String getBindingExpressionPart() {
319: return null;
320: }
321:
322: public Class getTargetTypeClass() {
323: return null;
324: }
325: }
326: }
|