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.beaninfo;
043:
044: import java.awt.Component;
045: import java.beans.PropertyChangeEvent;
046: import java.beans.PropertyChangeListener;
047: import java.beans.PropertyEditor;
048: import java.net.MalformedURLException;
049: import java.net.URL;
050: import java.util.logging.Level;
051: import java.util.logging.Logger;
052: import javax.accessibility.AccessibleContext;
053: import javax.swing.DefaultListModel;
054: import javax.swing.Icon;
055: import javax.swing.ImageIcon;
056: import javax.swing.JLabel;
057: import javax.swing.JList;
058: import javax.swing.ListCellRenderer;
059: import javax.swing.ListSelectionModel;
060: import org.netbeans.core.ActionsPoolNode;
061: import org.openide.awt.Actions;
062: import org.openide.cookies.InstanceCookie;
063: import org.openide.explorer.ExplorerManager;
064: import org.openide.explorer.propertysheet.PropertyEnv;
065: import org.openide.nodes.Node;
066: import org.openide.util.NbBundle;
067: import org.openide.util.actions.SystemAction;
068:
069: /** Custom editor for data loader actions list.
070: *
071: * @author Jesse Glick
072: */
073: public class LoaderActionsPanel extends javax.swing.JPanel implements
074: PropertyChangeListener, ListCellRenderer {
075:
076: private DefaultListModel model;
077: private ExplorerManager mgr;
078: private PropertyEditor editor;
079:
080: /** Creates new form LoaderActionsPanel */
081: public LoaderActionsPanel(PropertyEditor pe, PropertyEnv env) {
082: env.setState(PropertyEnv.STATE_NEEDS_VALIDATION);
083: env.addPropertyChangeListener(this );
084: this .editor = pe;
085:
086: initComponents();
087: model = new DefaultListModel();
088: SystemAction[] actions = (SystemAction[]) pe.getValue();
089: if (actions == null)
090: actions = new SystemAction[] {};
091: for (int i = 0; i < actions.length; i++)
092: model.addElement(actions[i]);
093: list.setModel(model);
094: mgr = explorerPanel.getExplorerManager();
095: mgr.setRootContext(new ActionsPoolNode());
096: mgr.addPropertyChangeListener(new PropertyChangeListener() {
097: public void propertyChange(PropertyChangeEvent ev) {
098: if (ExplorerManager.PROP_SELECTED_NODES.equals(ev
099: .getPropertyName())) {
100: SystemAction action = findAction(mgr
101: .getSelectedNodes());
102: addButton.setEnabled(action != null);
103: }
104: }
105: });
106: // bugfix #39369: remove help button in Action dialog property editor
107: //HelpCtx.setHelpIDString (this, LoaderActionsPanel.class.getName ());
108:
109: // Form Editor does not permit you to set this, because
110: // it has both int and double params:
111: splitPane.setDividerLocation(300);
112:
113: java.util.ResourceBundle bundle = NbBundle
114: .getBundle(LoaderActionsPanel.class);
115:
116: AccessibleContext ac = beanTreeView2.getAccessibleContext();
117: ac.setAccessibleName(bundle
118: .getString("ACS_LoaderActionsPanel.beanTreeView"));
119: ac.setAccessibleDescription(bundle
120: .getString("ACSD_LoaderActionsPanel.beanTreeView"));
121: ac = list.getAccessibleContext();
122: ac.setAccessibleName(bundle
123: .getString("ACS_LoaderActionsPanel.list"));
124: ac.setAccessibleDescription(bundle
125: .getString("ACSD_LoaderActionsPanel.list"));
126: getAccessibleContext().setAccessibleDescription(
127: bundle.getString("ACSD_LoaderActionsPanel"));
128: }
129:
130: /** This method is called from within the constructor to
131: * initialize the form.
132: * WARNING: Do NOT modify this code. The content of this method is
133: * always regenerated by the FormEditor.
134: */
135: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
136: private void initComponents() {
137: java.awt.GridBagConstraints gridBagConstraints;
138:
139: splitPane = new javax.swing.JSplitPane();
140: explorerPanel = new org.netbeans.beaninfo.ExplorerPanel();
141: beanTreeView2 = new org.openide.explorer.view.BeanTreeView();
142: jScrollPane1 = new javax.swing.JScrollPane();
143: list = new javax.swing.JList();
144: jPanel2 = new javax.swing.JPanel();
145: jPanel1 = new javax.swing.JPanel();
146: addButton = new javax.swing.JButton();
147: separatorButton = new javax.swing.JButton();
148: removeButton = new javax.swing.JButton();
149: upButton = new javax.swing.JButton();
150: downButton = new javax.swing.JButton();
151:
152: setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12,
153: 0, 11));
154: setPreferredSize(new java.awt.Dimension(600, 500));
155: setLayout(new java.awt.BorderLayout(11, 0));
156:
157: splitPane.setLastDividerLocation(300);
158:
159: explorerPanel.setLayout(new java.awt.BorderLayout());
160:
161: beanTreeView2.setDefaultActionAllowed(false);
162: beanTreeView2.setPopupAllowed(false);
163: explorerPanel.add(beanTreeView2, java.awt.BorderLayout.CENTER);
164:
165: splitPane.setLeftComponent(explorerPanel);
166:
167: list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
168: list.setCellRenderer(this );
169: list.addFocusListener(new java.awt.event.FocusAdapter() {
170: public void focusGained(java.awt.event.FocusEvent evt) {
171: listFocusGained(evt);
172: }
173: });
174: list
175: .addListSelectionListener(new javax.swing.event.ListSelectionListener() {
176: public void valueChanged(
177: javax.swing.event.ListSelectionEvent evt) {
178: listValueChanged(evt);
179: }
180: });
181: jScrollPane1.setViewportView(list);
182:
183: splitPane.setRightComponent(jScrollPane1);
184:
185: add(splitPane, java.awt.BorderLayout.CENTER);
186:
187: jPanel2.setLayout(new java.awt.FlowLayout(
188: java.awt.FlowLayout.CENTER, 0, 0));
189:
190: jPanel1.setLayout(new java.awt.GridBagLayout());
191:
192: java.util.ResourceBundle bundle = java.util.ResourceBundle
193: .getBundle("org/netbeans/beaninfo/Bundle"); // NOI18N
194: org.openide.awt.Mnemonics.setLocalizedText(addButton, bundle
195: .getString("LoaderActionsPanel.jButton1.text")); // NOI18N
196: addButton.setToolTipText(bundle
197: .getString("LoaderActionsPanel.jButton1.toolTipText")); // NOI18N
198: addButton.setEnabled(false);
199: addButton
200: .addActionListener(new java.awt.event.ActionListener() {
201: public void actionPerformed(
202: java.awt.event.ActionEvent evt) {
203: addButtonActionPerformed(evt);
204: }
205: });
206: gridBagConstraints = new java.awt.GridBagConstraints();
207: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
208: gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
209: jPanel1.add(addButton, gridBagConstraints);
210:
211: org.openide.awt.Mnemonics.setLocalizedText(separatorButton,
212: bundle.getString("LoaderActionsPanel.jButton2.text")); // NOI18N
213: separatorButton.setToolTipText(bundle
214: .getString("LoaderActionsPanel.jButton2.toolTipText")); // NOI18N
215: separatorButton
216: .addActionListener(new java.awt.event.ActionListener() {
217: public void actionPerformed(
218: java.awt.event.ActionEvent evt) {
219: separatorButtonActionPerformed(evt);
220: }
221: });
222: gridBagConstraints = new java.awt.GridBagConstraints();
223: gridBagConstraints.gridx = 0;
224: gridBagConstraints.gridy = 1;
225: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
226: gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
227: jPanel1.add(separatorButton, gridBagConstraints);
228:
229: org.openide.awt.Mnemonics.setLocalizedText(removeButton, bundle
230: .getString("LoaderActionsPanel.jButton3.text")); // NOI18N
231: removeButton.setToolTipText(bundle
232: .getString("LoaderActionsPanel.jButton3.toolTipText")); // NOI18N
233: removeButton.setEnabled(false);
234: removeButton
235: .addActionListener(new java.awt.event.ActionListener() {
236: public void actionPerformed(
237: java.awt.event.ActionEvent evt) {
238: removeButtonActionPerformed(evt);
239: }
240: });
241: gridBagConstraints = new java.awt.GridBagConstraints();
242: gridBagConstraints.gridx = 0;
243: gridBagConstraints.gridy = 2;
244: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
245: gridBagConstraints.insets = new java.awt.Insets(0, 0, 11, 0);
246: jPanel1.add(removeButton, gridBagConstraints);
247:
248: org.openide.awt.Mnemonics.setLocalizedText(upButton, bundle
249: .getString("LoaderActionsPanel.jButton4.text")); // NOI18N
250: upButton.setToolTipText(bundle
251: .getString("LoaderActionsPanel.jButton4.toolTipText")); // NOI18N
252: upButton.setEnabled(false);
253: upButton.addActionListener(new java.awt.event.ActionListener() {
254: public void actionPerformed(java.awt.event.ActionEvent evt) {
255: upButtonActionPerformed(evt);
256: }
257: });
258: gridBagConstraints = new java.awt.GridBagConstraints();
259: gridBagConstraints.gridx = 0;
260: gridBagConstraints.gridy = 3;
261: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
262: gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
263: jPanel1.add(upButton, gridBagConstraints);
264:
265: org.openide.awt.Mnemonics.setLocalizedText(downButton, bundle
266: .getString("LoaderActionsPanel.jButton5.text")); // NOI18N
267: downButton.setToolTipText(bundle
268: .getString("LoaderActionsPanel.jButton5.toolTipText")); // NOI18N
269: downButton.setEnabled(false);
270: downButton
271: .addActionListener(new java.awt.event.ActionListener() {
272: public void actionPerformed(
273: java.awt.event.ActionEvent evt) {
274: downButtonActionPerformed(evt);
275: }
276: });
277: gridBagConstraints = new java.awt.GridBagConstraints();
278: gridBagConstraints.gridx = 0;
279: gridBagConstraints.gridy = 4;
280: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
281: jPanel1.add(downButton, gridBagConstraints);
282:
283: jPanel2.add(jPanel1);
284:
285: add(jPanel2, java.awt.BorderLayout.EAST);
286: }// </editor-fold>//GEN-END:initComponents
287:
288: private void listFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_listFocusGained
289: // Add your handling code here:
290: if (list.getSelectedIndex() == -1
291: && list.getModel().getSize() > 0) {
292: list.setSelectedIndex(0);
293: }
294: }//GEN-LAST:event_listFocusGained
295:
296: private void listValueChanged(
297: javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_listValueChanged
298: int index = list.getSelectedIndex();
299: if (index == -1) {
300: downButton.setEnabled(false);
301: upButton.setEnabled(false);
302: removeButton.setEnabled(false);
303: } else {
304: // [PENDING] remove button enabled after removing last action
305: // but it is harmless to press it
306: removeButton.setEnabled(true);
307: downButton.setEnabled(index != model.getSize() - 1);
308: upButton.setEnabled(index != 0);
309: }
310: }//GEN-LAST:event_listValueChanged
311:
312: private void downButtonActionPerformed(
313: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downButtonActionPerformed
314: int index = list.getSelectedIndex();
315: if (index == -1 || index == model.getSize() - 1)
316: return;
317: Object temp = model.elementAt(index);
318: model.setElementAt(model.elementAt(index + 1), index);
319: model.setElementAt(temp, index + 1);
320: list.setSelectedIndex(index + 1);
321: }//GEN-LAST:event_downButtonActionPerformed
322:
323: private void upButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_upButtonActionPerformed
324: int index = list.getSelectedIndex();
325: if (index == -1 || index == 0)
326: return;
327: Object temp = model.elementAt(index);
328: model.setElementAt(model.elementAt(index - 1), index);
329: model.setElementAt(temp, index - 1);
330: list.setSelectedIndex(index - 1);
331: }//GEN-LAST:event_upButtonActionPerformed
332:
333: private void removeButtonActionPerformed(
334: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
335: int index = list.getSelectedIndex();
336: if (index == -1)
337: return;
338: model.remove(index);
339: if (model.getSize() == 0)
340: list.setSelectedIndices(new int[] {});
341: else
342: list.setSelectedIndex(Math.min(index, model.getSize() - 1));
343: }//GEN-LAST:event_removeButtonActionPerformed
344:
345: private void separatorButtonActionPerformed(
346: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_separatorButtonActionPerformed
347: model.addElement(null);
348: list.setSelectedIndex(model.getSize() - 1);
349: }//GEN-LAST:event_separatorButtonActionPerformed
350:
351: private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
352: Node[] nodes = mgr.getSelectedNodes();
353: SystemAction action = findAction(nodes);
354: if (action != null)
355: model.addElement(action);
356: list.setSelectedIndex(model.getSize() - 1);
357: }//GEN-LAST:event_addButtonActionPerformed
358:
359: // Variables declaration - do not modify//GEN-BEGIN:variables
360: private javax.swing.JButton addButton;
361: private org.openide.explorer.view.BeanTreeView beanTreeView2;
362: private javax.swing.JButton downButton;
363: private org.netbeans.beaninfo.ExplorerPanel explorerPanel;
364: private javax.swing.JPanel jPanel1;
365: private javax.swing.JPanel jPanel2;
366: private javax.swing.JScrollPane jScrollPane1;
367: private javax.swing.JList list;
368: private javax.swing.JButton removeButton;
369: private javax.swing.JButton separatorButton;
370: private javax.swing.JSplitPane splitPane;
371: private javax.swing.JButton upButton;
372:
373: // End of variables declaration//GEN-END:variables
374:
375: /** Try to find a system action instance among a set of nodes. */
376: static SystemAction findAction(Node[] nodes) {
377: if (nodes == null || nodes.length == 0 || nodes.length > 1)
378: return null;
379: InstanceCookie inst = (InstanceCookie) nodes[0]
380: .getCookie(InstanceCookie.class);
381: if (inst == null)
382: return null;
383: try {
384: Class clazz = inst.instanceClass();
385: if (!SystemAction.class.isAssignableFrom(clazz))
386: return null;
387: return (SystemAction) inst.instanceCreate();
388: } catch (Exception e) {
389: Logger.getLogger(LoaderActionsPanel.class.getName()).log(
390: Level.WARNING, null, e);
391: return null;
392: }
393: }
394:
395: /** Get the customized property value.
396: * @return the property value
397: * @exception InvalidStateException when the custom property editor does not contain a valid property value
398: * (and thus it should not be set)
399: */
400: private Object getPropertyValue() throws IllegalStateException {
401: SystemAction[] actions = new SystemAction[model.getSize()];
402: model.copyInto(actions);
403: return actions;
404: }
405:
406: public void propertyChange(PropertyChangeEvent evt) {
407: if (PropertyEnv.PROP_STATE.equals(evt.getPropertyName())
408: && evt.getNewValue() == PropertyEnv.STATE_VALID) {
409: editor.setValue(getPropertyValue());
410: }
411: }
412:
413: /** Return a component that has been configured to display the specified
414: * value. That component's <code>paint</code> method is then called to
415: * "render" the cell. If it is necessary to compute the dimensions
416: * of a list because the list cells do not have a fixed size, this method
417: * is called to generate a component on which <code>getPreferredSize</code>
418: * can be invoked.
419: *
420: * @param list The JList we're painting.
421: * @param value The value returned by list.getModel().getElementAt(index).
422: * @param index The cells index.
423: * @param isSelected True if the specified cell was selected.
424: * @param cellHasFocus True if the specified cell has the focus.
425: * @return A component whose paint() method will render the specified value.
426: *
427: * @see JList
428: * @see ListSelectionModel
429: * @see ListModel
430: */
431: public Component getListCellRendererComponent(JList list,
432: Object value, int index, boolean isSelected,
433: boolean cellHasFocus) {
434: JLabel label = new JLabel();
435: if (value != null) {
436: SystemAction action = (SystemAction) value;
437: try {
438: String name = action.getName();
439: if (name == null)
440: name = NbBundle.getBundle(LoaderActionsPanel.class)
441: .getString("LBL_no_system_action_name");
442: label.setText(Actions.cutAmpersand(name));
443: Icon icon = action.getIcon();
444: if (icon != null)
445: label.setIcon(icon);
446: } catch (RuntimeException re) {
447: // May happen if actions are misconfigured, bogus icons, etc.
448: // So best to recover semigracefully.
449: Logger.getLogger(LoaderActionsPanel.class.getName())
450: .log(Level.WARNING, null, re);
451: }
452: } else {
453: label.setText(NbBundle.getBundle(LoaderActionsPanel.class)
454: .getString("LBL_separator_rather_than_action"));
455: // For alignment:
456: try {
457: // For alignment:
458: label
459: .setIcon(new ImageIcon(
460: new URL(
461: "nbresloc:/org/openide/resources/actions/empty.gif"))); // NOI18N
462: } catch (MalformedURLException ex) {
463: assert false : ex;
464: }
465: }
466: if (isSelected) {
467: label.setBackground(list.getSelectionBackground());
468: label.setForeground(list.getSelectionForeground());
469: } else {
470: label.setBackground(list.getBackground());
471: label.setForeground(list.getForeground());
472: }
473: label.setEnabled(list.isEnabled());
474: label.setFont(list.getFont());
475: label.setOpaque(true);
476: return label;
477: }
478: }
|