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-2006 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:
042: package org.netbeans.modules.form;
043:
044: import java.beans.*;
045: import java.util.*;
046:
047: import org.openide.awt.Mnemonics;
048:
049: /** The PropertyPicker is a form which allows user to choose from property set
050: * of specified required class.
051: *
052: * @author Ian Formanek
053: */
054: public class PropertyPicker extends javax.swing.JPanel {
055:
056: public static final int CANCEL = 0;
057: public static final int OK = 1;
058:
059: static final long serialVersionUID = 5689122601606238081L;
060:
061: /**
062: * Initializes the Form.
063: *
064: * @param formModel form model.
065: * @param componentToSelect component whose property should be selected.
066: * @param requiredType required type of the property.
067: */
068: public PropertyPicker(FormModel formModel,
069: RADComponent componentToSelect, Class requiredType) {
070: this .requiredType = requiredType;
071: initComponents();
072:
073: java.util.List<RADComponent> componentsList = formModel
074: .getComponentList();
075: Collections.sort(componentsList,
076: new ParametersPicker.ComponentComparator());
077: components = new RADComponent[componentsList.size()];
078: componentsList.toArray(components);
079:
080: int selIndex = -1;
081: for (Iterator<RADComponent> it = componentsList.iterator(); it
082: .hasNext();) {
083: RADComponent radComp = it.next();
084: if (componentToSelect != null
085: && componentToSelect == radComp)
086: selIndex = componentsCombo.getItemCount();
087: if (radComp == formModel.getTopRADComponent())
088: componentsCombo.addItem(FormUtils
089: .getBundleString("CTL_FormTopContainerName")); // NOI18N
090: else
091: componentsCombo.addItem(radComp.getName());
092: }
093: if (selIndex >= 0)
094: componentsCombo.setSelectedIndex(selIndex);
095:
096: propertyList
097: .setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
098: updatePropertyList();
099:
100: // localize components
101: Mnemonics.setLocalizedText(componentLabel, FormUtils
102: .getBundleString("CTL_CW_Component")); // NOI18N
103: Mnemonics.setLocalizedText(listLabel, FormUtils
104: .getBundleString("CTL_CW_PropertyList")); // NOI18N
105:
106: componentsCombo
107: .getAccessibleContext()
108: .setAccessibleDescription(
109: FormUtils
110: .getBundleString("ACSD_CTL_CW_Component")); // NOI18N
111: propertyList.getAccessibleContext().setAccessibleDescription(
112: FormUtils.getBundleString("ACSD_CTL_CW_PropertyList")); // NOI18N
113: getAccessibleContext().setAccessibleDescription(
114: FormUtils.getBundleString("ACSD_PropertyPicker")); // NOI18N
115:
116: // HelpCtx.setHelpIDString(this, "gui.connecting.code"); // NOI18N
117: }
118:
119: public boolean isPickerValid() {
120: return pickerValid;
121: }
122:
123: private void setPickerValid(boolean v) {
124: boolean old = pickerValid;
125: pickerValid = v;
126: firePropertyChange("pickerValid", old, pickerValid); // NOI18N
127: }
128:
129: RADComponent getSelectedComponent() {
130: return selectedComponent;
131: }
132:
133: void setSelectedComponent(RADComponent selectedComponent) {
134: if (selectedComponent != null)
135: componentsCombo
136: .setSelectedItem(selectedComponent.getName());
137: }
138:
139: PropertyPickerItem getSelectedProperty() {
140: if ((selectedComponent == null)
141: || (propertyList.getSelectedIndex() == -1))
142: return null;
143: return items[propertyList.getSelectedIndex()];
144: }
145:
146: void setSelectedProperty(PropertyDescriptor selectedProperty) {
147: if (selectedProperty == null) {
148: propertyList.setSelectedIndex(-1);
149: } else {
150: propertyList.setSelectedValue(selectedProperty.getName(),
151: true);
152: }
153: }
154:
155: // ----------------------------------------------------------------------------
156: // private methods
157:
158: private void updatePropertyList() {
159: RADComponent sel = getSelectedComponent();
160: if (sel == null) {
161: propertyList.setListData(new Object[0]);
162: propertyList.revalidate();
163: propertyList.repaint();
164: } else {
165: PropertyDescriptor[] descs = sel.getBeanInfo()
166: .getPropertyDescriptors();
167: Map<String, PropertyPickerItem> filtered = new HashMap<String, PropertyPickerItem>();
168: for (int i = 0; i < descs.length; i++) {
169: if ((descs[i].getReadMethod() != null) && // filter out non-readable properties
170: (descs[i].getPropertyType() != null) && // indexed properties return null from getPropertyType
171: requiredType.isAssignableFrom(descs[i]
172: .getPropertyType())) {
173: PropertyPickerItem item = createItem(descs[i]);
174: filtered.put(item.getPropertyName(), item);
175: }
176: }
177:
178: if (sel == sel.getFormModel().getTopRADComponent()) {
179: String[] names = FormEditor.getFormJavaSource(
180: sel.getFormModel()).getPropertyReadMethodNames(
181: requiredType);
182: for (int i = 0; i < names.length; i++) {
183: PropertyPickerItem item = createItem(names[i]);
184: if (!filtered.keySet().contains(
185: item.getPropertyName())) {
186: filtered.put(item.getPropertyName(), item);
187: }
188: }
189: }
190:
191: items = new PropertyPickerItem[filtered.size()];
192: filtered.values().toArray(items);
193:
194: // sort the properties by name
195: Arrays.sort(items, new Comparator<PropertyPickerItem>() {
196: public int compare(PropertyPickerItem o1,
197: PropertyPickerItem o2) {
198: return o1.getPropertyName().compareTo(
199: o2.getPropertyName());
200: }
201: });
202:
203: String[] listItems = new String[items.length];
204: for (int i = 0; i < listItems.length; i++)
205: listItems[i] = items[i].getPropertyName();
206:
207: propertyList.setListData(listItems);
208: propertyList.revalidate();
209: propertyList.repaint();
210: }
211: }
212:
213: private PropertyPickerItem createItem(final PropertyDescriptor desc) {
214: return new PropertyPickerItem() {
215: public String getPropertyName() {
216: return desc.getName();
217: }
218:
219: public String getReadMethodName() {
220: return desc.getReadMethod().getName();
221: }
222:
223: public boolean providesPropertyDescriptor() {
224: return true;
225: }
226:
227: public PropertyDescriptor getPropertyDescriptor() {
228: return desc;
229: }
230: };
231: }
232:
233: private PropertyPickerItem createItem(final String name) {
234: return new PropertyPickerItem() {
235: public String getPropertyName() {
236: return FormJavaSource.extractPropertyName(name);
237: }
238:
239: public String getReadMethodName() {
240: return FormUtils.getMethodName(name, NO_PARAMETERS);
241: }
242:
243: public boolean providesPropertyDescriptor() {
244: return false;
245: }
246:
247: public PropertyDescriptor getPropertyDescriptor() {
248: return null;
249: }
250: };
251: }
252:
253: private void updateState() {
254: setPickerValid((getSelectedComponent() != null)
255: && (getSelectedProperty() != null));
256: }
257:
258: /** This method is called from within the constructor to
259: * initialize the form.
260: * WARNING: Do NOT modify this code. The content of this method is
261: * always regenerated by the FormEditor.
262: */
263: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
264: private void initComponents() {
265: java.awt.GridBagConstraints gridBagConstraints;
266:
267: componentsCombo = new javax.swing.JComboBox();
268: propertiesScrollPane = new javax.swing.JScrollPane();
269: propertyList = new javax.swing.JList();
270: componentLabel = new javax.swing.JLabel();
271: listLabel = new javax.swing.JLabel();
272:
273: setLayout(new java.awt.GridBagLayout());
274:
275: setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12,
276: 0, 11));
277: componentsCombo
278: .addItemListener(new java.awt.event.ItemListener() {
279: public void itemStateChanged(
280: java.awt.event.ItemEvent evt) {
281: componentsComboItemStateChanged(evt);
282: }
283: });
284:
285: gridBagConstraints = new java.awt.GridBagConstraints();
286: gridBagConstraints.gridx = 1;
287: gridBagConstraints.gridy = 0;
288: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
289: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
290: gridBagConstraints.weightx = 1.0;
291: gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
292: add(componentsCombo, gridBagConstraints);
293:
294: propertyList
295: .addListSelectionListener(new javax.swing.event.ListSelectionListener() {
296: public void valueChanged(
297: javax.swing.event.ListSelectionEvent evt) {
298: propertyListValueChanged(evt);
299: }
300: });
301:
302: propertiesScrollPane.setViewportView(propertyList);
303:
304: gridBagConstraints = new java.awt.GridBagConstraints();
305: gridBagConstraints.gridx = 0;
306: gridBagConstraints.gridy = 2;
307: gridBagConstraints.gridwidth = 2;
308: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
309: gridBagConstraints.weightx = 1.0;
310: gridBagConstraints.weighty = 1.0;
311: add(propertiesScrollPane, gridBagConstraints);
312:
313: componentLabel.setLabelFor(componentsCombo);
314: componentLabel.setText("Component:");
315: gridBagConstraints = new java.awt.GridBagConstraints();
316: gridBagConstraints.gridx = 0;
317: gridBagConstraints.gridy = 0;
318: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
319: gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 6);
320: add(componentLabel, gridBagConstraints);
321:
322: listLabel.setLabelFor(propertyList);
323: listLabel.setText("Properties");
324: gridBagConstraints = new java.awt.GridBagConstraints();
325: gridBagConstraints.gridx = 0;
326: gridBagConstraints.gridy = 1;
327: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
328: gridBagConstraints.insets = new java.awt.Insets(0, 0, 2, 0);
329: add(listLabel, gridBagConstraints);
330:
331: }// </editor-fold>//GEN-END:initComponents
332:
333: private void propertyListValueChanged(
334: javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_propertyListValueChanged
335: updateState();
336: }//GEN-LAST:event_propertyListValueChanged
337:
338: private void componentsComboItemStateChanged(
339: java.awt.event.ItemEvent evt) {//GEN-FIRST:event_componentsComboItemStateChanged
340: if (componentsCombo.getSelectedIndex() == -1)
341: selectedComponent = null;
342: else
343: selectedComponent = components[componentsCombo
344: .getSelectedIndex()];
345: updatePropertyList();
346: }//GEN-LAST:event_componentsComboItemStateChanged
347:
348: // Variables declaration - do not modify//GEN-BEGIN:variables
349: private javax.swing.JLabel componentLabel;
350: private javax.swing.JComboBox componentsCombo;
351: private javax.swing.JLabel listLabel;
352: private javax.swing.JScrollPane propertiesScrollPane;
353: private javax.swing.JList propertyList;
354: // End of variables declaration//GEN-END:variables
355:
356: private boolean pickerValid = false;
357:
358: private RADComponent[] components;
359: private Class<?> requiredType;
360: private PropertyPickerItem[] items;
361: private RADComponent selectedComponent;
362: private static Class[] NO_PARAMETERS = new Class[0];
363:
364: interface PropertyPickerItem {
365: public String getPropertyName();
366:
367: public String getReadMethodName();
368:
369: public PropertyDescriptor getPropertyDescriptor();
370: }
371:
372: }
|