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.core.execution.beaninfo.editors;
043:
044: import java.beans.PropertyEditor;
045: import java.io.File;
046: import java.io.IOException;
047: import java.util.Collections;
048: import java.util.List;
049: import java.util.StringTokenizer;
050: import javax.swing.DefaultListModel;
051: import javax.swing.JFileChooser;
052: import javax.swing.filechooser.FileFilter;
053: import org.netbeans.beaninfo.editors.FileEditor;
054: import org.openide.execution.NbClassPath;
055: import org.openide.util.HelpCtx;
056: import org.openide.util.NbBundle;
057: import org.openide.util.NbCollections;
058: import org.openide.windows.WindowManager;
059:
060: /**
061: * Panel for editing entries in the classpath.
062: * @author David Strupl
063: */
064: class NbClassPathCustomEditor extends javax.swing.JPanel {
065:
066: /** Remember last folder, which was explored in FileChooser.*/
067: private static File lastDirFolder = null;
068: /** Remember last folder, which was explored in FileChooser.*/
069: private static File lastJarFolder = null;
070: /** Property editor associated with. */
071: private PropertyEditor editor;
072: /** Model of list of class path items. */
073: private DefaultListModel listModel = new DefaultListModel();
074: private boolean editable = true;
075:
076: /** Creates new form NbClassPathCustomEditor */
077: public NbClassPathCustomEditor() {
078: initComponents();
079: pathList.setModel(listModel);
080: pathScrollPane.setViewportView(pathList);
081:
082: setMinimumSize(new java.awt.Dimension(400, 200));
083: setPreferredSize(new java.awt.Dimension(400, 200));
084:
085: pathList.getAccessibleContext().setAccessibleDescription(
086: getString("ACSD_PathList"));
087: addDirButton.getAccessibleContext().setAccessibleDescription(
088: getString("ACSD_AddDirectory"));
089: addJarButton.getAccessibleContext().setAccessibleDescription(
090: getString("ACSD_AddJAR"));
091: upButton.getAccessibleContext().setAccessibleDescription(
092: getString("ACSD_MoveUp"));
093: downButton.getAccessibleContext().setAccessibleDescription(
094: getString("ACSD_MoveDown"));
095: removeButton.getAccessibleContext().setAccessibleDescription(
096: getString("ACSD_Remove"));
097:
098: getAccessibleContext().setAccessibleDescription(
099: getString("ACSD_CustomNbClassPathEditor"));
100: }
101:
102: NbClassPathCustomEditor(PropertyEditor propEd) {
103: this ();
104: editor = propEd;
105: Object value = propEd.getValue();
106: if (value instanceof NbClassPath) {
107: setClassPath(((NbClassPath) value).getClassPath());
108: }
109: if (editor instanceof NbClassPathEditor)
110: if (!((NbClassPathEditor) editor).isEditable()) {
111: editable = false;
112: addDirButton.setEnabled(false);
113: addJarButton.setEnabled(false);
114: }
115: }
116:
117: /** This method is called from within the constructor to
118: * initialize the form.
119: * WARNING: Do NOT modify this code. The content of this method is
120: * always regenerated by the FormEditor.
121: */
122: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
123: private void initComponents() {
124: java.awt.GridBagConstraints gridBagConstraints;
125:
126: innerPanel = new javax.swing.JPanel();
127: addDirButton = new javax.swing.JButton();
128: addJarButton = new javax.swing.JButton();
129: upButton = new javax.swing.JButton();
130: downButton = new javax.swing.JButton();
131: removeButton = new javax.swing.JButton();
132: pathScrollPane = new javax.swing.JScrollPane();
133: pathList = new javax.swing.JList();
134:
135: setLayout(new java.awt.BorderLayout());
136:
137: innerPanel.setLayout(new java.awt.GridBagLayout());
138:
139: org.openide.awt.Mnemonics.setLocalizedText(addDirButton,
140: getString("CTL_AddDirectory")); // NOI18N
141: addDirButton
142: .addActionListener(new java.awt.event.ActionListener() {
143: public void actionPerformed(
144: java.awt.event.ActionEvent evt) {
145: addDirButtonActionPerformed(evt);
146: }
147: });
148: gridBagConstraints = new java.awt.GridBagConstraints();
149: gridBagConstraints.gridx = 1;
150: gridBagConstraints.gridy = 0;
151: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
152: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
153: gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
154: innerPanel.add(addDirButton, gridBagConstraints);
155:
156: org.openide.awt.Mnemonics.setLocalizedText(addJarButton,
157: getString("CTL_AddJAR")); // NOI18N
158: addJarButton
159: .addActionListener(new java.awt.event.ActionListener() {
160: public void actionPerformed(
161: java.awt.event.ActionEvent evt) {
162: addJarButtonActionPerformed(evt);
163: }
164: });
165: gridBagConstraints = new java.awt.GridBagConstraints();
166: gridBagConstraints.gridx = 1;
167: gridBagConstraints.gridy = 1;
168: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
169: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
170: gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
171: innerPanel.add(addJarButton, gridBagConstraints);
172:
173: org.openide.awt.Mnemonics.setLocalizedText(upButton,
174: getString("CTL_MoveUp")); // NOI18N
175: upButton.setEnabled(false);
176: upButton.addActionListener(new java.awt.event.ActionListener() {
177: public void actionPerformed(java.awt.event.ActionEvent evt) {
178: upButtonActionPerformed(evt);
179: }
180: });
181: gridBagConstraints = new java.awt.GridBagConstraints();
182: gridBagConstraints.gridx = 1;
183: gridBagConstraints.gridy = 3;
184: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
185: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
186: gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
187: innerPanel.add(upButton, gridBagConstraints);
188:
189: org.openide.awt.Mnemonics.setLocalizedText(downButton,
190: getString("CTL_MoveDown")); // NOI18N
191: downButton.setEnabled(false);
192: downButton
193: .addActionListener(new java.awt.event.ActionListener() {
194: public void actionPerformed(
195: java.awt.event.ActionEvent evt) {
196: downButtonActionPerformed(evt);
197: }
198: });
199: gridBagConstraints = new java.awt.GridBagConstraints();
200: gridBagConstraints.gridx = 1;
201: gridBagConstraints.gridy = 4;
202: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
203: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
204: innerPanel.add(downButton, gridBagConstraints);
205:
206: org.openide.awt.Mnemonics.setLocalizedText(removeButton,
207: getString("CTL_Remove")); // NOI18N
208: removeButton.setEnabled(false);
209: removeButton
210: .addActionListener(new java.awt.event.ActionListener() {
211: public void actionPerformed(
212: java.awt.event.ActionEvent evt) {
213: removeButtonActionPerformed(evt);
214: }
215: });
216: gridBagConstraints = new java.awt.GridBagConstraints();
217: gridBagConstraints.gridx = 1;
218: gridBagConstraints.gridy = 2;
219: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
220: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
221: gridBagConstraints.insets = new java.awt.Insets(0, 0, 11, 0);
222: innerPanel.add(removeButton, gridBagConstraints);
223:
224: pathList
225: .addListSelectionListener(new javax.swing.event.ListSelectionListener() {
226: public void valueChanged(
227: javax.swing.event.ListSelectionEvent evt) {
228: pathListValueChanged(evt);
229: }
230: });
231: pathList.addMouseListener(new java.awt.event.MouseAdapter() {
232: public void mouseClicked(java.awt.event.MouseEvent evt) {
233: pathListMouseClicked(evt);
234: }
235: });
236: pathScrollPane.setViewportView(pathList);
237:
238: gridBagConstraints = new java.awt.GridBagConstraints();
239: gridBagConstraints.gridx = 0;
240: gridBagConstraints.gridy = 0;
241: gridBagConstraints.gridheight = 5;
242: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
243: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
244: gridBagConstraints.weightx = 1.0;
245: gridBagConstraints.weighty = 1.0;
246: gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 11);
247: innerPanel.add(pathScrollPane, gridBagConstraints);
248:
249: add(innerPanel, java.awt.BorderLayout.CENTER);
250: }// </editor-fold>//GEN-END:initComponents
251:
252: private void pathListMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_pathListMouseClicked
253: if (evt.getClickCount() != 2) {
254: // trigger the action on double-click
255: return;
256: }
257: triggerEdit(pathList.getSelectedIndex());
258: }//GEN-LAST:event_pathListMouseClicked
259:
260: private void pathListValueChanged(
261: javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_pathListValueChanged
262: enableButtons();
263: }//GEN-LAST:event_pathListValueChanged
264:
265: private void removeButtonActionPerformed(
266: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
267: int index = pathList.getSelectedIndex();
268:
269: Object[] selectedValues = pathList.getSelectedValues();
270: for (int i = 0; i < selectedValues.length; i++) {
271: listModel.removeElement(selectedValues[i]);
272: fireValueChanged();
273: }
274:
275: // Select some of remaining item.
276: int size = listModel.getSize();
277:
278: if (index >= 0 && size > 0) {
279: if (size == index) {
280: pathList.setSelectedIndex(index - 1);
281: } else if (size > index) {
282: pathList.setSelectedIndex(index);
283: } else {
284: pathList.setSelectedIndex(0);
285: }
286: }
287:
288: // If empty disable up, down, remve buttons.
289: enableButtons();
290: }//GEN-LAST:event_removeButtonActionPerformed
291:
292: private void downButtonActionPerformed(
293: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downButtonActionPerformed
294: int i = pathList.getSelectedIndex();
295: swap(i);
296: pathList.setSelectedIndex(i + 1);
297: }//GEN-LAST:event_downButtonActionPerformed
298:
299: private void upButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_upButtonActionPerformed
300: int i = pathList.getSelectedIndex();
301: swap(i - 1);
302: pathList.setSelectedIndex(i - 1);
303: }//GEN-LAST:event_upButtonActionPerformed
304:
305: private void addJarButtonActionPerformed(
306: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addJarButtonActionPerformed
307:
308: JFileChooser chooser = FileEditor.createHackedFileChooser();
309: setHelpToChooser(chooser);
310:
311: chooser.setFileFilter(new FileFilter() {
312: public boolean accept(File f) {
313: return (f.isDirectory() || f.getName().endsWith(".jar") || f
314: .getName().endsWith(".zip")); // NOI18N
315: }
316:
317: public String getDescription() {
318: return getString("CTL_JarArchivesMask");
319: }
320: });
321:
322: if (lastJarFolder != null) {
323: chooser.setCurrentDirectory(lastJarFolder);
324: }
325:
326: chooser
327: .setDialogTitle(getString("CTL_FileSystemPanel.Jar_Dialog_Title"));
328: chooser.setMultiSelectionEnabled(true);
329: if (chooser
330: .showDialog(WindowManager.getDefault().getMainWindow(),
331: getString("CTL_Approve_Button_Title")) == JFileChooser.APPROVE_OPTION) {
332: File[] files = chooser.getSelectedFiles();
333: boolean found = false;
334: for (int i = 0; i < files.length; i++) {
335: if ((files[i] != null) && (files[i].isFile())) {
336: found = true;
337: String path = files[i].getAbsolutePath();
338: if (!listModel.contains(path)) {
339: listModel.addElement(path);
340: }
341: }
342: }
343: if (found) {
344: lastJarFolder = chooser.getCurrentDirectory();
345: fireValueChanged();
346: }
347: pathList.setSelectedIndex(listModel.size() - 1);
348: }
349: }//GEN-LAST:event_addJarButtonActionPerformed
350:
351: private void addDirButtonActionPerformed(
352: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addDirButtonActionPerformed
353: JFileChooser chooser = FileEditor.createHackedFileChooser();
354: setHelpToChooser(chooser);
355: chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
356: chooser
357: .setDialogTitle(getString("CTL_FileSystemPanel.Local_Dialog_Title"));
358:
359: if (lastDirFolder != null) {
360: chooser.setCurrentDirectory(lastDirFolder);
361: }
362:
363: if (chooser
364: .showDialog(WindowManager.getDefault().getMainWindow(),
365: getString("CTL_Approve_Button_Title")) == JFileChooser.APPROVE_OPTION) {
366: File f = chooser.getSelectedFile();
367: if ((f != null) && (f.isDirectory())) {
368: lastDirFolder = f.getParentFile();
369:
370: String path = f.getAbsolutePath();
371: if (!listModel.contains(path)) {
372: listModel.addElement(path);
373: }
374: fireValueChanged();
375:
376: pathList.setSelectedIndex(listModel.size() - 1);
377: }
378: }
379: }//GEN-LAST:event_addDirButtonActionPerformed
380:
381: // Variables declaration - do not modify//GEN-BEGIN:variables
382: private javax.swing.JButton addDirButton;
383: private javax.swing.JButton addJarButton;
384: private javax.swing.JButton downButton;
385: private javax.swing.JPanel innerPanel;
386: private javax.swing.JList pathList;
387: private javax.swing.JScrollPane pathScrollPane;
388: private javax.swing.JButton removeButton;
389: private javax.swing.JButton upButton;
390:
391: // End of variables declaration//GEN-END:variables
392:
393: /** Sets value to property editor if exists.
394: * @see #editor */
395: private void fireValueChanged() {
396: if (editor != null) {
397: editor.setValue(getPropertyValue());
398: }
399: }
400:
401: /** Allows the user to edit the selected item. */
402: private void triggerEdit(int index) {
403: if (index < 0) {
404: return;
405: }
406: String selectedItem = (String) listModel.elementAt(index);
407: File selectedF = new File(selectedItem);
408: if (selectedF.isDirectory()) {
409:
410: JFileChooser chooser = FileEditor.createHackedFileChooser();
411: setHelpToChooser(chooser);
412: chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
413: chooser
414: .setDialogTitle(getString("CTL_Edit_Local_Dialog_Title"));
415:
416: if (selectedF.getParentFile() != null) {
417: chooser.setCurrentDirectory(selectedF.getParentFile());
418: chooser.setSelectedFile(selectedF);
419: }
420:
421: if (chooser.showDialog(WindowManager.getDefault()
422: .getMainWindow(),
423: getString("CTL_Approve_Button_Title")) == JFileChooser.APPROVE_OPTION) {
424: File f = chooser.getSelectedFile();
425: if ((f != null) && (f.isDirectory())) {
426: lastDirFolder = chooser.getCurrentDirectory();
427: try {
428: f = f.getCanonicalFile();
429: } catch (IOException ioe) {
430: // ignore
431: }
432:
433: listModel.set(index, f.getAbsolutePath());
434: fireValueChanged();
435: }
436: }
437: } else if (selectedF.isFile()) {
438: JFileChooser chooser = FileEditor.createHackedFileChooser();
439: setHelpToChooser(chooser);
440:
441: chooser.setFileFilter(new FileFilter() {
442: public boolean accept(File f) {
443: return (f.isDirectory()
444: || f.getName().endsWith(".jar") || f
445: .getName().endsWith(".zip")); // NOI18N
446: }
447:
448: public String getDescription() {
449: return getString("CTL_JarArchivesMask");
450: }
451: });
452:
453: chooser.setCurrentDirectory(selectedF.getParentFile());
454: chooser.setSelectedFile(selectedF);
455:
456: chooser
457: .setDialogTitle(getString("CTL_Edit_Jar_Dialog_Title"));
458: if (chooser.showDialog(WindowManager.getDefault()
459: .getMainWindow(),
460: getString("CTL_Approve_Button_Title")) == JFileChooser.APPROVE_OPTION) {
461: File f = chooser.getSelectedFile();
462: if ((f != null) && (f.isFile())) {
463: lastJarFolder = chooser.getCurrentDirectory();
464: listModel.set(index, f.getAbsolutePath());
465: fireValueChanged();
466: }
467: }
468: }
469: }
470:
471: /** Swaps item on the the position index with item on the position index+1. */
472: private void swap(int index) {
473: if ((index < 0) || (index >= listModel.size() - 1)) {
474: return;
475: }
476: Object value = listModel.elementAt(index);
477: listModel.removeElement(value);
478: listModel.add(index + 1, value);
479: fireValueChanged();
480: }
481:
482: /** Enables buttons according to the state of the list.*/
483: private void enableButtons() {
484: if (!editable)
485: return;
486: removeButton
487: .setEnabled(pathList.getSelectedIndices().length > 0);
488: if (pathList.getSelectedIndices().length == 1) {
489: downButton
490: .setEnabled(pathList.getSelectedIndices()[0] < pathList
491: .getModel().getSize() - 1);
492: upButton.setEnabled(pathList.getSelectedIndices()[0] > 0);
493: } else {
494: downButton.setEnabled(false);
495: upButton.setEnabled(false);
496: }
497: }
498:
499: /** This method parses given classPath and adds the elements to
500: * the listModel.
501: */
502: private void setClassPath(String classPath) {
503: StringTokenizer tok = new StringTokenizer(classPath,
504: File.pathSeparator);
505: while (tok.hasMoreTokens()) {
506: String s = tok.nextToken();
507: if (s.startsWith("\"")) { // NOI18N
508: s = s.substring(1);
509: }
510: if (s.endsWith("\"")) { // NOI18N
511: s = s.substring(0, s.length() - 1);
512: }
513: if (!listModel.contains(s)) {
514: listModel.addElement(s);
515: }
516: }
517:
518: }
519:
520: /** Get the customized property value. Implements <code>EnhancedCustomPropertyEditor</code>.
521: * @return the property value
522: * @exception InvalidStateException when the custom property editor does not contain a valid property value
523: * (and thus it should not be set)
524: */
525: public Object getPropertyValue() throws IllegalStateException {
526: List<String> list = Collections.list(NbCollections
527: .checkedEnumerationByFilter(listModel.elements(),
528: String.class, true));
529: String[] arr = list.toArray(new String[list.size()]);
530: return new NbClassPath(arr);
531: }
532:
533: /** Gets localized string. Helper method. */
534: private static final String getString(String s) {
535: return NbBundle.getMessage(NbClassPathCustomEditor.class, s);
536: }
537:
538: private void setHelpToChooser(JFileChooser chooser) {
539: HelpCtx help = HelpCtx.findHelp(this);
540: if (help != null)
541: HelpCtx.setHelpIDString(chooser, help.getHelpID());
542: }
543: }
|