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.nodes;
042:
043: import org.netbeans.modules.visualweb.propertyeditors.binding.PropertyBindingPanel;
044: import java.beans.BeanInfo;
045: import java.beans.Introspector;
046: import java.beans.PropertyDescriptor;
047: import javax.faces.model.SelectItem;
048: import java.awt.Component;
049: import java.awt.GridBagConstraints;
050: import java.awt.GridBagLayout;
051: import java.awt.Insets;
052: import java.awt.event.ActionEvent;
053: import java.awt.event.ActionListener;
054: import javax.swing.DefaultListCellRenderer;
055: import javax.swing.JComboBox;
056: import javax.swing.JComponent;
057: import javax.swing.JLabel;
058: import javax.swing.JList;
059: import javax.swing.JPanel;
060: import com.sun.data.provider.DataProvider;
061: import com.sun.data.provider.FieldKey;
062: import com.sun.rave.designtime.DesignBean;
063: import org.netbeans.modules.visualweb.propertyeditors.binding.BindingTargetNode;
064: import org.netbeans.modules.visualweb.propertyeditors.binding.BindingTargetNodeFactory;
065: import org.netbeans.modules.visualweb.propertyeditors.binding.PropertyBindingHelper;
066: import org.netbeans.modules.visualweb.propertyeditors.util.Bundle;
067: import javax.swing.SwingUtilities;
068: import org.openide.ErrorManager;
069:
070: public class DataProviderTargetNodeFactory implements
071: BindingTargetNodeFactory {
072:
073: private static final Bundle bundle = Bundle
074: .getBundle(DataProviderTargetNodeFactory.class);
075:
076: public boolean supportsTargetClass(Class targetClass) {
077: return DataProvider.class.isAssignableFrom(targetClass);
078: }
079:
080: public BindingTargetNode createTargetNode(BindingTargetNode parent,
081: DesignBean bean, PropertyDescriptor[] propPath,
082: Object propInstance) {
083: return new DataProviderTargetNode(parent, bean, propPath,
084: propInstance);
085: }
086:
087: public class DataProviderTargetNode extends PropertyTargetNode {
088: public DataProviderTargetNode(BindingTargetNode parent,
089: DesignBean bean, PropertyDescriptor[] propPath,
090: Object propInstance) {
091: super (parent, bean, propPath, propInstance);
092: }
093:
094: public void lazyLoadCustomTargetNodes() {
095: if (propInstance == null) {
096: propInstance = PropertyBindingHelper.getPropInstance(
097: bean, propPath);
098: }
099:
100: if (propInstance instanceof DataProvider) {
101: Thread dataProvideNodeThread = new Thread(
102: new Runnable() {
103: public void run() {
104: final DataProvider dp = (DataProvider) propInstance;
105: try {
106: final FieldKey[] keys = dp
107: .getFieldKeys();
108: SwingUtilities
109: .invokeLater(new Runnable() {
110: public void run() {
111: for (int i = 0; keys != null
112: && i < keys.length; i++) {
113: DataProviderTargetNode.super
114: .add(new FieldKeyNode(
115: DataProviderTargetNode.this ,
116: bean,
117: propPath,
118: dp,
119: keys[i]));
120: }
121: DataProviderTargetNode.super
122: .add(new OptionsNode(
123: DataProviderTargetNode.this ,
124: dp,
125: keys));
126: DataProviderTargetNode.super
127: .add(new SelectItemsNode(
128: DataProviderTargetNode.this ,
129: dp,
130: keys));
131: }
132: });
133: } catch (Exception exc) {
134: ErrorManager.getDefault().notify(
135: exc);
136: }
137: }
138: });
139: dataProvideNodeThread.setPriority(Thread.MIN_PRIORITY);
140: dataProvideNodeThread.start();
141: }
142: }
143:
144: public class FieldKeyNode extends BindingTargetNode {
145: protected DesignBean bean;
146: protected PropertyDescriptor[] propPath;
147: protected DataProvider provider;
148: protected FieldKey key;
149:
150: public FieldKeyNode(BindingTargetNode parent,
151: DesignBean bean, PropertyDescriptor[] propPath,
152: DataProvider provider, FieldKey key) {
153: super (parent);
154: this .bean = bean;
155: this .propPath = propPath;
156: this .provider = provider;
157: this .key = key;
158: }
159:
160: public boolean lazyLoad() {
161: try {
162: BeanInfo bi = Introspector
163: .getBeanInfo(getTargetTypeClass());
164: PropertyDescriptor[] pds = bi
165: .getPropertyDescriptors();
166: for (int i = 0; pds != null && i < pds.length; i++) {
167: if (pds[i].getReadMethod() != null) {
168: PropertyDescriptor[] newPath = new PropertyDescriptor[propPath.length + 1];
169: System.arraycopy(propPath, 0, newPath, 0,
170: propPath.length);
171: newPath[newPath.length - 1] = pds[i];
172: super .add(_createTargetNode(this , bean,
173: newPath, null));
174: }
175: }
176: } catch (Exception x) {
177: // x.printStackTrace();
178: }
179: return true;
180: }
181:
182: public boolean isValidBindingTarget() {
183: return true;
184: }
185:
186: public String getBindingExpressionPart() {
187: return "value['" + key.getFieldId() + "']"; //NOI18N
188: }
189:
190: public Class getTargetTypeClass() {
191: return provider.getType(key);
192: }
193:
194: public String getDisplayText(boolean enableNode) {
195: String tn = getTargetTypeDisplayName();
196: StringBuffer sb = new StringBuffer();
197: sb.append("<html>"); //NOI18N
198: if (!enableNode) {
199: sb.append("<font color=\"gray\">"); //NOI18N
200: }
201: sb.append(bundle.getMessage("key")); //NOI18N
202: sb.append(" "); //NOI18N
203: if (enableNode) {
204: sb.append("<b>"); //NOI18N
205: }
206: sb.append(key.getDisplayName());
207: if (enableNode) {
208: sb.append("</b>"); //NOI18N
209: }
210: sb.append(" <font size=\"-1\"><i>"); //NOI18N
211: sb.append(tn);
212: sb.append("</i></font>"); //NOI18N
213: if (!enableNode) {
214: sb.append("</font>"); //NOI18N
215: }
216: sb.append("</html>"); //NOI18N
217: return sb.toString();
218: }
219: }
220:
221: public class OptionsNode extends SelectItemsNode {
222: public OptionsNode(BindingTargetNode parent,
223: DataProvider provider, FieldKey[] cols) {
224: super (parent, provider, cols);
225: }
226:
227: public String getNodeDisplayName() {
228: return bundle.getMessage("options"); // NOI18N
229: }
230:
231: public String getBindingExpressionPart() {
232: return "options['" + getColumnPicks() + "']"; //NOI18N
233: }
234: }
235:
236: public class SelectItemsNode extends BindingTargetNode {
237: protected DataProvider provider;
238: FieldKey[] cols;
239:
240: public SelectItemsNode(BindingTargetNode parent,
241: DataProvider provider, FieldKey[] cols) {
242: super (parent);
243: this .provider = provider;
244: this .cols = cols;
245: initCustomPanel();
246: displayTextEnabled = getDisplayText(true);
247: displayTextDisabled = getDisplayText(false);
248: }
249:
250: public String getNodeDisplayName() {
251: return bundle.getMessage("selectItems"); // NOI18N
252: }
253:
254: protected String displayTextEnabled = null;
255: protected String displayTextDisabled = null;
256:
257: public String getDisplayText(boolean enableNode) {
258: if (enableNode && displayTextEnabled != null) {
259: return displayTextEnabled;
260: } else if (!enableNode && displayTextDisabled != null) {
261: return displayTextDisabled;
262: }
263: StringBuffer sb = new StringBuffer();
264: sb.append("<html>"); //NOI18N
265: if (!enableNode) {
266: sb.append("<font color=\"gray\">"); //NOI18N
267: }
268: if (enableNode) {
269: sb.append("<b>"); //NOI18N
270: }
271: sb.append(getNodeDisplayName());
272: if (enableNode) {
273: sb.append("</b>"); //NOI18N
274: }
275: sb.append(" <font size=\"-1\"><i>"); //NOI18N
276: sb.append(bundle.getMessage("parenItemsForListBoxOr")); //NOI18N
277: sb.append("</i></font>"); //NOI18N
278: if (!enableNode) {
279: sb.append("</font>"); //NOI18N
280: }
281: sb.append("</html>"); //NOI18N
282: return sb.toString();
283: }
284:
285: public int getChildCount() {
286: return 0;
287: }
288:
289: public boolean lazyLoad() {
290: return true;
291: }
292:
293: public Class getTargetTypeClass() {
294: return SelectItem[].class;
295: }
296:
297: public boolean isValidBindingTarget() {
298: return true;
299: }
300:
301: public String getBindingExpressionPart() {
302: return "selectItems['" + getColumnPicks() + "']"; //NOI18N
303: }
304:
305: String getColumnPicks() {
306: StringBuffer sb = new StringBuffer();
307: Object o = valueCombo.getSelectedItem();
308: if (o instanceof ComboDisplayColumn) {
309: sb.append(((ComboDisplayColumn) o).fieldKey
310: .getFieldId());
311: }
312: o = labelCombo.getSelectedItem();
313: if (o instanceof ComboDisplayColumn) {
314: sb.append(","); //NOI18N
315: sb.append(((ComboDisplayColumn) o).fieldKey
316: .getFieldId());
317: }
318: o = descrCombo.getSelectedItem();
319: if (o instanceof ComboDisplayColumn) {
320: sb.append(","); //NOI18N
321: sb.append(((ComboDisplayColumn) o).fieldKey
322: .getFieldId());
323: }
324: return sb.toString();
325: }
326:
327: JPanel pickerPanel = new JPanel();
328: JLabel valueLabel = new JLabel(bundle
329: .getMessage("valueField")); //NOI18N
330: JLabel labelLabel = new JLabel(bundle
331: .getMessage("displayField")); //NOI18N
332: JLabel descrLabel = new JLabel(bundle
333: .getMessage("tooltipField")); //NOI18N
334: JComboBox valueCombo = new JComboBox();
335: JComboBox labelCombo = new JComboBox();
336: JComboBox descrCombo = new JComboBox();
337:
338: void initCustomPanel() {
339: ComboDisplayColumnRenderer cdcr = new ComboDisplayColumnRenderer();
340: valueCombo.setRenderer(cdcr);
341: labelCombo.setRenderer(cdcr);
342: descrCombo.setRenderer(cdcr);
343: labelCombo.addItem(bundle.getMessage("noneBrackets")); //NOI18N
344: descrCombo.addItem(bundle.getMessage("noneBrackets")); //NOI18N
345:
346: // Don't get the FieldKey again, it is a slow process
347: //FieldKey[] cols = provider.getFieldKey();
348: if (cols != null && cols.length > 0) {
349: for (int i = 0; i < cols.length; i++) {
350: ComboDisplayColumn col = new ComboDisplayColumn(
351: cols[i], provider.getType(cols[i]));
352: valueCombo.addItem(col);
353: labelCombo.addItem(col);
354: descrCombo.addItem(col);
355: }
356: }
357:
358: pickerPanel.setLayout(new GridBagLayout());
359: pickerPanel.add(valueLabel, new GridBagConstraints(0,
360: 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
361: GridBagConstraints.HORIZONTAL, new Insets(0, 0,
362: 2, 4), 0, 0));
363: pickerPanel.add(labelLabel, new GridBagConstraints(1,
364: 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
365: GridBagConstraints.HORIZONTAL, new Insets(0, 0,
366: 2, 4), 0, 0));
367: pickerPanel.add(descrLabel, new GridBagConstraints(2,
368: 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
369: GridBagConstraints.HORIZONTAL, new Insets(0, 0,
370: 2, 0), 0, 0));
371: pickerPanel.add(valueCombo, new GridBagConstraints(0,
372: 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
373: GridBagConstraints.HORIZONTAL, new Insets(0, 0,
374: 0, 4), 0, 0));
375: pickerPanel.add(labelCombo, new GridBagConstraints(1,
376: 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
377: GridBagConstraints.HORIZONTAL, new Insets(0, 0,
378: 0, 4), 0, 0));
379: pickerPanel.add(descrCombo, new GridBagConstraints(2,
380: 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
381: GridBagConstraints.HORIZONTAL, new Insets(0, 0,
382: 0, 0), 0, 0));
383: valueCombo.addActionListener(updateAdapter);
384: labelCombo.addActionListener(updateAdapter);
385: descrCombo.addActionListener(updateAdapter);
386: }
387:
388: public JComponent getCustomDisplayPanel(
389: ActionListener updateCallback) {
390: this .updateCallback = updateCallback;
391: return pickerPanel;
392: }
393:
394: ActionListener updateCallback = null;
395: ActionListener updateAdapter = new ActionListener() {
396: public void actionPerformed(ActionEvent e) {
397: if (updateCallback != null) {
398: updateCallback.actionPerformed(e);
399: }
400: }
401: };
402: }
403:
404: public class ComboDisplayColumn {
405: public FieldKey fieldKey;
406: public Class fieldType;
407:
408: public ComboDisplayColumn(FieldKey fieldKey, Class fieldType) {
409: this .fieldKey = fieldKey;
410: this .fieldType = fieldType;
411: }
412: }
413:
414: public class ComboDisplayColumnRenderer extends
415: DefaultListCellRenderer {
416: public Component getListCellRendererComponent(JList list,
417: Object value, int index, boolean isSelected,
418: boolean cellHasFocus) {
419: super .getListCellRendererComponent(list, value, index,
420: isSelected, cellHasFocus);
421: if (value instanceof ComboDisplayColumn) {
422: ComboDisplayColumn cdc = (ComboDisplayColumn) value;
423: String tn = cdc.fieldType != null ? cdc.fieldType
424: .getName() : "";
425: StringBuffer sb = new StringBuffer();
426: sb.append("<html><b>"); //NOI18N
427: sb.append(cdc.fieldKey.getDisplayName());
428: sb.append("</b> <font size=\"-1\"><i>"); //NOI18N
429: sb.append(tn);
430: sb.append("</i></font></html>"); //NOI18N
431: this .setText(sb.toString());
432: } else {
433: this .setText(bundle.getMessage("noneBrackets")); //NOI18N
434: }
435: return this;
436: }
437: }
438: }
439: }
|