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.BeanInfo;
044: import java.beans.PropertyDescriptor;
045: import java.util.ArrayList;
046: import java.util.HashMap;
047: import javax.faces.component.UIComponent;
048: import java.awt.Component;
049: import java.awt.FlowLayout;
050: import java.awt.Graphics;
051: import java.awt.GridBagConstraints;
052: import java.awt.GridBagLayout;
053: import java.awt.Image;
054: import java.awt.Insets;
055: import java.awt.event.ActionEvent;
056: import java.awt.event.ActionListener;
057: import java.awt.event.ItemEvent;
058: import java.awt.event.ItemListener;
059: import javax.swing.ButtonGroup;
060: import javax.swing.DefaultComboBoxModel;
061: import javax.swing.DefaultListCellRenderer;
062: import javax.swing.DefaultListModel;
063: import javax.swing.Icon;
064: import javax.swing.ImageIcon;
065: import javax.swing.JComboBox;
066: import javax.swing.JLabel;
067: import javax.swing.JList;
068: import javax.swing.JPanel;
069: import javax.swing.JRadioButton;
070: import javax.swing.JScrollPane;
071: import javax.swing.JTextPane;
072: import javax.swing.ListSelectionModel;
073: import javax.swing.UIManager;
074: import javax.swing.event.ListSelectionEvent;
075: import javax.swing.event.ListSelectionListener;
076: import com.sun.rave.designtime.CategoryDescriptor;
077: import com.sun.rave.designtime.Constants;
078: import com.sun.rave.designtime.DesignBean;
079: import com.sun.rave.designtime.DesignContext;
080: import com.sun.rave.designtime.DesignProperty;
081: import com.sun.rave.designtime.markup.AttributeDescriptor;
082: import org.netbeans.modules.visualweb.propertyeditors.util.Bundle;
083:
084: public class BindingSourcePanel extends JPanel {
085:
086: private static final Bundle bundle = Bundle
087: .getBundle(BindingSourcePanel.class);
088:
089: JComboBox compCombo = new JComboBox();
090: JLabel compLabel = new JLabel();
091: DefaultComboBoxModel compComboModel = new DefaultComboBoxModel();
092: DefaultListModel propListModel = new DefaultListModel();
093: JLabel propLabel = new JLabel();
094: JScrollPane propScroll = new JScrollPane();
095: JList propList = new JList();
096: JRadioButton showDefault = new JRadioButton();
097: JRadioButton showAdvanced = new JRadioButton();
098: JRadioButton showAll = new JRadioButton();
099: JPanel radioPanel = new JPanel();
100: FlowLayout flowLayout1 = new FlowLayout();
101: GridBagLayout gridBagLayout1 = new GridBagLayout();
102: ButtonGroup showGroup = new ButtonGroup();
103: JTextPane noneText = new JTextPane();
104:
105: public BindingSourcePanel() {
106: try {
107: jbInit();
108: } catch (Exception ex) {
109: // ex.printStackTrace();
110: }
111: propList.getAccessibleContext().setAccessibleName(
112: bundle.getMessage("SOURCE_PROP_LIST_ACCESS_NAME"));
113: propList.getAccessibleContext().setAccessibleDescription(
114: bundle.getMessage("SOURCE_PROP_LIST_ACCESS_DESC"));
115: propLabel.setLabelFor(propList);
116: showDefault.getAccessibleContext().setAccessibleName(
117: bundle.getMessage("SHOW_DEFAULT_ACCESS_NAME"));
118: showDefault.getAccessibleContext().setAccessibleDescription(
119: bundle.getMessage("SHOW_DEFAULT_ACCESS_DESC"));
120: showAdvanced.getAccessibleContext().setAccessibleName(
121: bundle.getMessage("SHOW_ADVANCED_ACCESS_NAME"));
122: showAdvanced.getAccessibleContext().setAccessibleDescription(
123: bundle.getMessage("SHOW_ADVANCED_ACCESS_DESC"));
124: showAll.getAccessibleContext().setAccessibleName(
125: bundle.getMessage("SHOW_ALL_ACCESS_NAME"));
126: showAll.getAccessibleContext().setAccessibleDescription(
127: bundle.getMessage("SHOW_ALL_ACCESS_DESC"));
128: showDefault.setMnemonic(bundle.getMessage(
129: "SHOW_DEFAULT_MNEMONIC").charAt(0));
130: showAdvanced.setMnemonic(bundle.getMessage(
131: "SHOW_ADVANCED_MNEMONIC").charAt(0));
132: showAll.setMnemonic(bundle.getMessage("SHOW_ALL_MNEMONIC")
133: .charAt(0));
134: }
135:
136: protected PropertyBindingPanel bindingPanel;
137:
138: public BindingSourcePanel(PropertyBindingPanel bindingPanel) {
139: this ();
140: this .bindingPanel = bindingPanel;
141: }
142:
143: protected DesignContext showingContext = null;
144:
145: public void sourceContextChanged(DesignContext context) {
146: if (showingContext != null && showingContext == context)
147: return;
148: showingContext = context;
149: compComboModel.removeAllElements();
150: if (context != null) {
151: DesignBean root = context.getRootContainer();
152: fillCombo(root.getChildBeans());
153: }
154: }
155:
156: protected DesignBean showingBean = null;
157:
158: public void sourceBeanChanged(DesignBean bean) {
159: if (showingBean == bean)
160: return;
161: showingBean = bean;
162: if (bean != null) {
163: compCombo.setSelectedItem(bean);
164: enumProps();
165: } else {
166: propListModel.removeAllElements();
167: }
168: }
169:
170: protected DesignProperty showingProp = null;
171:
172: public void sourcePropertyChanged(DesignProperty prop) {
173: if (showingProp == prop)
174: return;
175: showingProp = prop;
176: if (prop != null) {
177: propList.setSelectedValue(prop, true);
178: } else {
179: propList.clearSelection();
180: }
181: }
182:
183: protected void fillCombo(DesignBean[] beans) {
184: for (int i = 0; i < beans.length; i++) {
185: if (beans[i].getInstance() instanceof UIComponent) {
186: compComboModel.addElement(beans[i]);
187: }
188: if (beans[i].isContainer()) {
189: fillCombo(beans[i].getChildBeans());
190: }
191: }
192: }
193:
194: protected void enumProps() {
195: DesignProperty[] props = bindingPanel.getSourceBean()
196: .getProperties();
197: propListModel.removeAllElements();
198: ArrayList pa = new ArrayList();
199: for (int i = 0; i < props.length; i++) {
200: // no read-only properties
201: if (props[i].getPropertyDescriptor().getWriteMethod() == null) {
202: continue;
203: }
204: // remove non-bindable properties
205: AttributeDescriptor ad = (AttributeDescriptor) props[i]
206: .getPropertyDescriptor()
207: .getValue(
208: Constants.PropertyDescriptor.ATTRIBUTE_DESCRIPTOR);
209: if (ad == null || !ad.isBindable()) {
210: continue;
211: }
212: // remove hidden/expert props
213: if (showDefault.isSelected()) {
214: CategoryDescriptor pcd = (CategoryDescriptor) props[i]
215: .getPropertyDescriptor().getValue(
216: Constants.PropertyDescriptor.CATEGORY);
217: if (props[i].getPropertyDescriptor().isHidden()
218: || props[i].getPropertyDescriptor().isExpert()
219: || (pcd != null && pcd.getName().equals(
220: "Advanced"))) { // JOE! HACK!
221: continue;
222: }
223: }
224: // remove hidden props
225: else if (showAdvanced.isSelected()) {
226: if (props[i].getPropertyDescriptor().isHidden()) {
227: continue;
228: }
229: }
230: pa.add(props[i]);
231: }
232: ArrayList mods = new ArrayList();
233: ArrayList rest = new ArrayList();
234: for (int i = 0; i < pa.size(); i++) {
235: DesignProperty p = (DesignProperty) pa.get(i);
236: if (p.isModified()) {
237: String vx = p.getValueSource();
238: if (vx != null && vx.startsWith("#{")
239: && vx.endsWith("}")) { //NOI18N
240: mods.add(p);
241: continue;
242: }
243: }
244: rest.add(p);
245: }
246: for (int i = 0; i < mods.size(); i++) {
247: propListModel.addElement(mods.get(i));
248: }
249: for (int i = 0; i < rest.size(); i++) {
250: propListModel.addElement(rest.get(i));
251: }
252: if (propListModel.getSize() > 0) {
253: this .remove(noneText);
254: this .add(propScroll, propScrollConstraints);
255: if (mods.size() > 0) {
256: propList.setSelectedIndex(0);
257: } else {
258: boolean foundValue = false;
259: for (int i = 0; i < rest.size(); i++) {
260: if (((DesignProperty) rest.get(i))
261: .getPropertyDescriptor().getName() == "value") { //NOI18N
262: propList.setSelectedValue(rest.get(i), true);
263: foundValue = true;
264: break;
265: }
266: }
267: if (!foundValue) {
268: for (int i = 0; i < rest.size(); i++) {
269: if (((DesignProperty) rest.get(i))
270: .getPropertyDescriptor().getName() == "text") { //NOI18N
271: propList
272: .setSelectedValue(rest.get(i), true);
273: break;
274: }
275: }
276: }
277: }
278: if (propList.getSelectedValue() == null) {
279: propList.setSelectedIndex(0);
280: }
281: } else {
282: this .remove(propScroll);
283: this .add(noneText, propScrollConstraints);
284: }
285: this .validate();
286: this .doLayout();
287: this .repaint(100);
288: }
289:
290: GridBagConstraints propScrollConstraints = new GridBagConstraints(
291: 0, 3, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER,
292: GridBagConstraints.BOTH, new Insets(0, 8, 0, 0), 0, 0);
293:
294: void jbInit() throws Exception {
295: this .setLayout(gridBagLayout1);
296:
297: noneText.setEditable(false);
298: noneText.setFont(propLabel.getFont());
299: noneText.setBorder(UIManager.getBorder("TextField.border")); //NOI18N
300: noneText.setText(bundle.getMessage("noBindableProps")); //NOI18N
301:
302: compLabel.setText(bundle.getMessage("selectComponent")); //NOI18N
303: compCombo.setModel(compComboModel);
304: compCombo.setRenderer(new CompComboRenderer());
305: compCombo.setEditable(false);
306: compCombo.addActionListener(new ActionListener() {
307: public void actionPerformed(ActionEvent e) {
308: compCombo_actionPerformed(e);
309: }
310: });
311: propLabel.setText(bundle.getMessage("selectBindableProp")); //NOI18N
312: propLabel.setDisplayedMnemonic(bundle.getMessage(
313: "selectBindablePropDisplayedMnemonic").charAt(0)); //NOI18N
314:
315: propList.setModel(propListModel);
316: propList.setCellRenderer(new PropListRenderer());
317: propList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
318: propList.getSelectionModel().addListSelectionListener(
319: new ListSelectionListener() {
320: public void valueChanged(ListSelectionEvent e) {
321: propList_valueChanged(e);
322: }
323: });
324: showDefault.setText(bundle.getMessage("default")); //NOI18N
325: showDefault.setSelected(true);
326: showDefault.addItemListener(new ItemListener() {
327: public void itemStateChanged(ItemEvent e) {
328: show_itemStateChanged(e);
329: }
330: });
331: showAdvanced.setText(bundle.getMessage("advanced")); //NOI18N
332: showAdvanced.addItemListener(new ItemListener() {
333: public void itemStateChanged(ItemEvent e) {
334: show_itemStateChanged(e);
335: }
336: });
337: showAll.setText(bundle.getMessage("all")); //NOI18N
338: showAll.addItemListener(new ItemListener() {
339: public void itemStateChanged(ItemEvent e) {
340: show_itemStateChanged(e);
341: }
342: });
343: radioPanel.setLayout(flowLayout1);
344: flowLayout1.setAlignment(FlowLayout.LEFT);
345: flowLayout1.setHgap(5);
346: flowLayout1.setVgap(0);
347: // this.add(compCombo, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER,
348: // GridBagConstraints.HORIZONTAL, new Insets(0, 8, 0, 0), 0, 0));
349: // this.add(compLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
350: // GridBagConstraints.HORIZONTAL, new Insets(8, 8, 2, 0), 0, 0));
351: this .add(propLabel, new GridBagConstraints(0, 2, 1, 1, 0.0,
352: 0.0, GridBagConstraints.WEST,
353: GridBagConstraints.HORIZONTAL, new Insets(8, 8, 2, 0),
354: 0, 0));
355: this .add(propScroll, propScrollConstraints);
356: this .add(radioPanel, new GridBagConstraints(0, 4, 1, 1, 1.0,
357: 0.0, GridBagConstraints.CENTER,
358: GridBagConstraints.HORIZONTAL, new Insets(0, 0, 8, 0),
359: 0, 0));
360: radioPanel.add(showDefault, null);
361: radioPanel.add(showAdvanced, null);
362: radioPanel.add(showAll, null);
363: propScroll.getViewport().add(propList, null);
364: showGroup.add(showDefault);
365: showGroup.add(showAdvanced);
366: showGroup.add(showAll);
367: }
368:
369: class CompComboRenderer extends DefaultListCellRenderer {
370: public Component getListCellRendererComponent(JList list,
371: Object value, int index, boolean isSelected,
372: boolean cellHasFocus) {
373: super .getListCellRendererComponent(list, value, index,
374: isSelected, cellHasFocus);
375:
376: if (value instanceof DesignBean) {
377: DesignBean b = (DesignBean) value;
378:
379: String prefix = ""; //NOI18N
380: DesignBean p = b.getBeanParent();
381: while (p != null
382: && p != b.getDesignContext().getRootContainer()) {
383: prefix += " "; //NOI18N
384: p = p.getBeanParent();
385: }
386:
387: this .setText(prefix + b.getInstanceName());
388: BeanInfo bi = b.getBeanInfo();
389: Image img = bi.getIcon(BeanInfo.ICON_COLOR_16x16);
390: if (img != null) {
391: this .setIcon(new ImageIcon(img));
392: } else {
393: this .setIcon(BEAN_ICON);
394: }
395: }
396:
397: return this ;
398: }
399: }
400:
401: protected static Icon BLANK_ICON = new Icon() {
402: public void paintIcon(Component c, Graphics g, int x, int y) {
403: g.setColor(c.getBackground());
404: g.fillRect(x, y, 16, 16);
405: }
406:
407: public int getIconWidth() {
408: return 16;
409: }
410:
411: public int getIconHeight() {
412: return 16;
413: }
414: };
415:
416: public static Icon BEAN_ICON = new ImageIcon(
417: BindingSourcePanel.class.getResource("img/bean.gif")); //NOI18N
418:
419: class PropListRenderer extends DefaultListCellRenderer {
420: public Component getListCellRendererComponent(JList list,
421: Object value, int index, boolean isSelected,
422: boolean cellHasFocus) {
423: super .getListCellRendererComponent(list, value, index,
424: isSelected, cellHasFocus);
425:
426: if (value instanceof DesignProperty) {
427: DesignProperty p = (DesignProperty) value;
428:
429: PropertyDescriptor pd = p.getPropertyDescriptor();
430: String cn = pd.getPropertyType().getName();
431: if (cn.startsWith("[")) { //NOI18N
432: cn = decodeTypeName(cn);
433: }
434: if (cn.indexOf(".") > -1) { //NOI18N
435: cn = cn.substring(cn.lastIndexOf(".") + 1); //NOI18N
436: }
437:
438: boolean bold = false;
439: if (p.isModified()) {
440: String vx = p.getValueSource();
441: if (vx == null) {
442: vx = "";
443: }
444: bold = vx.startsWith("#{") && vx.endsWith("}"); //NOI18N
445: }
446:
447: StringBuffer sb = new StringBuffer();
448: sb.append("<html>"); //NOI18N
449: if (bold) {
450: sb.append("<b>"); //NOI18N
451: }
452: sb.append(pd.getName());
453: if (bold) {
454: sb.append("</b>"); //NOI18N
455: }
456: sb.append(" <font><i>"); //NOI18N
457: sb.append(cn);
458: sb.append("</i></font></html>"); //NOI18N
459: this .setText(sb.toString());
460: this .setIcon(UIManager.getIcon("Tree.leafIcon")); //NOI18N
461: }
462:
463: return this ;
464: }
465: }
466:
467: void show_itemStateChanged(ItemEvent e) {
468: Object o = propList.getSelectedValue();
469: enumProps();
470: propList.setSelectedValue(o, false);
471: }
472:
473: void compCombo_actionPerformed(ActionEvent e) {
474: DesignBean b = (DesignBean) compCombo.getSelectedItem();
475: bindingPanel.setSourceBean(b);
476: }
477:
478: void propList_valueChanged(ListSelectionEvent e) {
479: DesignProperty p = (DesignProperty) propList.getSelectedValue();
480: bindingPanel.setSourceProperty(p);
481: }
482:
483: static HashMap arrayTypeKeyHash = new HashMap();
484: static {
485: arrayTypeKeyHash.put("B", "byte"); //NOI18N
486: arrayTypeKeyHash.put("C", "char"); //NOI18N
487: arrayTypeKeyHash.put("D", "double"); //NOI18N
488: arrayTypeKeyHash.put("F", "float"); //NOI18N
489: arrayTypeKeyHash.put("I", "int"); //NOI18N
490: arrayTypeKeyHash.put("J", "long"); //NOI18N
491: arrayTypeKeyHash.put("S", "short"); //NOI18N
492: arrayTypeKeyHash.put("Z", "boolean"); //NOI18N
493: arrayTypeKeyHash.put("V", "void"); //NOI18N
494: }
495:
496: String decodeTypeName(String tn) {
497: if (tn.startsWith("[")) { //NOI18N
498: int depth = 0;
499: while (tn.startsWith("[")) { //NOI18N
500: tn = tn.substring(1);
501: depth++;
502: }
503: if (tn.startsWith("L")) { //NOI18N
504: tn = tn.substring(1);
505: tn = tn.substring(0, tn.length() - 1);
506: } else {
507: char typeKey = tn.charAt(0);
508: tn = (String) arrayTypeKeyHash.get("" + typeKey); //NOI18N
509: }
510: for (int i = 0; i < depth; i++) {
511: tn += "[]"; //NOI18N
512: }
513: }
514: return tn;
515: }
516: }
|