001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: package org.netbeans.api.project.libraries;
021:
022: import java.awt.BorderLayout;
023: import java.awt.Component;
024: import java.awt.Image;
025: import java.beans.PropertyChangeEvent;
026: import java.beans.PropertyChangeListener;
027: import java.beans.PropertyVetoException;
028: import java.io.IOException;
029: import java.text.Collator;
030: import java.util.ArrayList;
031: import java.util.Collection;
032: import java.util.Collections;
033: import java.util.Comparator;
034: import java.util.HashSet;
035: import java.util.List;
036: import java.util.Set;
037: import javax.swing.JButton;
038: import javax.swing.JPanel;
039: import javax.swing.border.EmptyBorder;
040: import org.openide.DialogDescriptor;
041: import org.openide.DialogDisplayer;
042: import org.openide.NotifyDescriptor;
043: import org.openide.explorer.ExplorerManager;
044: import org.openide.filesystems.Repository;
045: import org.openide.loaders.DataFolder;
046: import org.openide.nodes.AbstractNode;
047: import org.openide.nodes.Children;
048: import org.openide.nodes.Node;
049: import org.openide.nodes.NodeNotFoundException;
050: import org.openide.nodes.NodeOp;
051: import org.openide.util.Exceptions;
052: import org.openide.util.HelpCtx;
053: import org.openide.util.NbBundle;
054: import org.openide.util.lookup.Lookups;
055:
056: class LibraryChooserGUI extends JPanel implements
057: ExplorerManager.Provider, HelpCtx.Provider,
058: LibraryChooser.Panel {
059:
060: private final LibraryManager manager;
061: private final LibraryChooser.Filter filter;
062: private final ExplorerManager explorer;
063: private LibraryChooser.LibraryImportHandler importHandler;
064:
065: private LibraryChooserGUI(LibraryManager manager,
066: LibraryChooser.Filter filter,
067: LibraryChooser.LibraryImportHandler importHandler) {
068: if (manager == null) {
069: manager = LibraryManager.getDefault();
070: }
071: this .manager = manager;
072: this .filter = filter;
073: this .importHandler = importHandler;
074: explorer = new ExplorerManager();
075: initComponents();
076: tree.setDefaultActionAllowed(false);
077: }
078:
079: public static LibraryChooser.Panel createPanel(
080: LibraryManager manager, LibraryChooser.Filter filter) {
081: LibraryChooserGUI l = new LibraryChooserGUI(manager, filter,
082: null);
083: l.configureForEmbedded();
084: return l;
085: }
086:
087: public static Set<Library> showChooser(LibraryManager manager,
088: LibraryChooser.Filter filter,
089: LibraryChooser.LibraryImportHandler handler,
090: boolean addOperation) {
091: LibraryChooserGUI l = new LibraryChooserGUI(manager, filter,
092: handler);
093: return l.showDialog(addOperation);
094: }
095:
096: private Set<Library> showDialog(boolean addOperatation) {
097: // show manage button only in embedded panel:
098: manageLibrariesButton.setVisible(false);
099: // import enabled only for non-global library manager
100: importButton.setVisible(manager.getLocation() != null
101: && importHandler != null);
102: JPanel inset = new JPanel(new BorderLayout());
103: inset.setBorder(new EmptyBorder(12, 12, 0, 12));
104: inset.add(this );
105: String title;
106: String buttonLabel;
107: String buttonA11YName;
108: String buttonA11YDesc;
109: if (addOperatation) {
110: title = NbBundle.getMessage(LibraryChooserGUI.class,
111: "LibraryChooserGUI.add.title");
112: buttonLabel = NbBundle.getMessage(LibraryChooserGUI.class,
113: "LibraryChooserGUI.add.button");
114: buttonA11YName = NbBundle.getMessage(
115: LibraryChooserGUI.class,
116: "LibraryChooserGUI.add.button");
117: buttonA11YDesc = NbBundle.getMessage(
118: LibraryChooserGUI.class,
119: "LibraryChooserGUI.add.button.a11y.desc");
120: } else {
121: title = NbBundle.getMessage(LibraryChooserGUI.class,
122: "LibraryChooserGUI.import.title");
123: buttonLabel = NbBundle.getMessage(LibraryChooserGUI.class,
124: "LibraryChooserGUI.import.button");
125: buttonA11YName = NbBundle.getMessage(
126: LibraryChooserGUI.class,
127: "LibraryChooserGUI.import.button");
128: buttonA11YDesc = NbBundle.getMessage(
129: LibraryChooserGUI.class,
130: "LibraryChooserGUI.import.button.a11y.desc");
131: createButton.setVisible(false);
132: }
133: DialogDescriptor dd = new DialogDescriptor(inset, title);
134: dd.setModal(true);
135: final JButton add = new JButton(buttonLabel);
136: add.setEnabled(false);
137: add.setDefaultCapable(true);
138: add.getAccessibleContext().setAccessibleName(buttonA11YName);
139: add.getAccessibleContext().setAccessibleDescription(
140: buttonA11YDesc);
141: explorer
142: .addPropertyChangeListener(new PropertyChangeListener() {
143: public void propertyChange(PropertyChangeEvent evt) {
144: add.setEnabled(!getSelectedLibraries()
145: .isEmpty());
146: }
147: });
148: dd.setOptions(new Object[] { add,
149: NotifyDescriptor.CANCEL_OPTION });
150: dd.setClosingOptions(new Object[] { add,
151: NotifyDescriptor.CANCEL_OPTION });
152: if (DialogDisplayer.getDefault().notify(dd) == add) {
153: Set<Library> selection = getSelectedLibraries();
154: assert !selection.isEmpty();
155: return selection;
156: } else {
157: return null;
158: }
159: }
160:
161: private void configureForEmbedded() {
162: explorer
163: .addPropertyChangeListener(new PropertyChangeListener() {
164: public void propertyChange(PropertyChangeEvent evt) {
165: firePropertyChange(PROP_SELECTED_LIBRARIES,
166: null, null);
167: }
168: });
169: createButton.setVisible(false);
170: importButton.setVisible(false);
171: }
172:
173: public Set<Library> getSelectedLibraries() {
174: Set<Library> s = new HashSet<Library>();
175: for (Node n : explorer.getSelectedNodes()) {
176: Library l = n.getLookup().lookup(Library.class);
177: if (l != null) {
178: s.add(l);
179: } else {
180: return Collections.emptySet();
181: }
182: }
183: return s;
184: }
185:
186: public Component getVisualComponent() {
187: return this ;
188: }
189:
190: public ExplorerManager getExplorerManager() {
191: return explorer;
192: }
193:
194: public HelpCtx getHelpCtx() {
195: return new HelpCtx(LibraryChooserGUI.class);
196: }
197:
198: private void setRootNode() {
199: explorer.setRootContext(new AbstractNode(
200: new LibraryManagerChildren()));
201: tree.expandAll();
202: try {
203: if (explorer.getRootContext().getChildren().getNodes(true).length > 0) {
204: explorer
205: .setSelectedNodes(new Node[] { explorer
206: .getRootContext().getChildren()
207: .getNodes(true)[0] });
208: }
209: } catch (PropertyVetoException x) {
210: Exceptions.printStackTrace(x);
211: }
212: /* XXX Nothing seems to work to scroll to top; how is it done?
213: tree.getViewport().setViewPosition(new Point());
214: tree.getViewport().scrollRectToVisible(new Rectangle(0, 0, 1, 1));
215: */
216: tree.requestFocus();
217: }
218:
219: @Override
220: public void addNotify() {
221: super .addNotify();
222: setRootNode();
223: }
224:
225: private class LibraryManagerChildren extends
226: Children.Keys<LibraryManager> {
227:
228: @Override
229: protected void addNotify() {
230: super .addNotify();
231: if (manager != null) {
232: setKeys(Collections.singleton(manager));
233: }
234: }
235:
236: protected Node[] createNodes(LibraryManager mgr) {
237: List<Library> libs = new ArrayList<Library>();
238: for (Library lib : mgr.getLibraries()) {
239: if (filter == null || filter.accept(lib)) {
240: libs.add(lib);
241: }
242: }
243: if (libs.isEmpty()) {
244: return new Node[0];
245: } else {
246: Collections.sort(libs, new Comparator<Library>() {
247: Collator COLL = Collator.getInstance();
248:
249: public int compare(Library lib1, Library lib2) {
250: return COLL.compare(lib1.getDisplayName(), lib2
251: .getDisplayName());
252: }
253: });
254: Node n = new AbstractNode(new LibraryChildren(libs)) {
255: Node iconDelegate = DataFolder.findFolder(
256: Repository.getDefault()
257: .getDefaultFileSystem().getRoot())
258: .getNodeDelegate();
259:
260: public Image getIcon(int type) {
261: return iconDelegate.getIcon(type);
262: }
263:
264: public Image getOpenedIcon(int type) {
265: return iconDelegate.getOpenedIcon(type);
266: }
267: };
268: n.setName(mgr.getDisplayName());
269: n.setDisplayName(mgr.getDisplayName());
270: return new Node[] { n };
271: }
272: }
273:
274: }
275:
276: private class LibraryChildren extends Children.Keys<Library> {
277:
278: LibraryChildren(List<Library> libs) {
279: setKeys(libs);
280: }
281:
282: protected Node[] createNodes(Library lib) {
283: AbstractNode n = new AbstractNode(Children.LEAF, Lookups
284: .singleton(lib));
285: n.setName(lib.getName());
286: n.setDisplayName(lib.getDisplayName());
287: n.setShortDescription(lib.getDescription());
288: n
289: .setIconBaseWithExtension("org/netbeans/modules/project/libraries/resources/libraries.gif"); // NOI18N
290: return new Node[] { n };
291: }
292:
293: }
294:
295: // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
296: private void initComponents() {
297:
298: librariesLabel = new javax.swing.JLabel();
299: tree = new org.openide.explorer.view.BeanTreeView();
300: createButton = new javax.swing.JButton();
301: importButton = new javax.swing.JButton();
302: manageLibrariesButton = new javax.swing.JButton();
303:
304: librariesLabel.setLabelFor(tree);
305: org.openide.awt.Mnemonics.setLocalizedText(librariesLabel,
306: org.openide.util.NbBundle.getMessage(
307: LibraryChooserGUI.class,
308: "LibraryChooserGUI.librariesLabel")); // NOI18N
309:
310: tree.setBorder(javax.swing.BorderFactory.createEtchedBorder());
311: tree.setPopupAllowed(false);
312: tree.setRootVisible(false);
313:
314: org.openide.awt.Mnemonics.setLocalizedText(createButton,
315: org.openide.util.NbBundle.getMessage(
316: LibraryChooserGUI.class,
317: "LibraryChooserGUI.createButton.text")); // NOI18N
318: createButton
319: .addActionListener(new java.awt.event.ActionListener() {
320: public void actionPerformed(
321: java.awt.event.ActionEvent evt) {
322: createButtonActionPerformed(evt);
323: }
324: });
325:
326: org.openide.awt.Mnemonics.setLocalizedText(importButton,
327: org.openide.util.NbBundle.getMessage(
328: LibraryChooserGUI.class,
329: "LibraryChooserGUI.importButton.text")); // NOI18N
330: importButton
331: .addActionListener(new java.awt.event.ActionListener() {
332: public void actionPerformed(
333: java.awt.event.ActionEvent evt) {
334: importButtonActionPerformed(evt);
335: }
336: });
337:
338: org.openide.awt.Mnemonics
339: .setLocalizedText(
340: manageLibrariesButton,
341: org.openide.util.NbBundle
342: .getMessage(LibraryChooserGUI.class,
343: "LibraryChooserGUI.manageLibrariesButton.text")); // NOI18N
344: manageLibrariesButton
345: .addActionListener(new java.awt.event.ActionListener() {
346: public void actionPerformed(
347: java.awt.event.ActionEvent evt) {
348: manageLibrariesButtonActionPerformed(evt);
349: }
350: });
351:
352: org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(
353: this );
354: this .setLayout(layout);
355: layout
356: .setHorizontalGroup(layout
357: .createParallelGroup(
358: org.jdesktop.layout.GroupLayout.LEADING)
359: .add(librariesLabel)
360: .add(
361: org.jdesktop.layout.GroupLayout.TRAILING,
362: layout
363: .createSequentialGroup()
364: .add(
365: tree,
366: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
367: 249, Short.MAX_VALUE)
368: .addPreferredGap(
369: org.jdesktop.layout.LayoutStyle.RELATED)
370: .add(
371: layout
372: .createParallelGroup(
373: org.jdesktop.layout.GroupLayout.TRAILING)
374: .add(
375: createButton)
376: .add(
377: importButton)))
378: .add(
379: layout.createSequentialGroup().add(
380: manageLibrariesButton)
381: .addContainerGap()));
382: layout
383: .setVerticalGroup(layout
384: .createParallelGroup(
385: org.jdesktop.layout.GroupLayout.LEADING)
386: .add(
387: layout
388: .createSequentialGroup()
389: .add(librariesLabel)
390: .addPreferredGap(
391: org.jdesktop.layout.LayoutStyle.RELATED)
392: .add(
393: layout
394: .createParallelGroup(
395: org.jdesktop.layout.GroupLayout.LEADING)
396: .add(
397: layout
398: .createSequentialGroup()
399: .add(
400: createButton)
401: .addPreferredGap(
402: org.jdesktop.layout.LayoutStyle.RELATED)
403: .add(
404: importButton))
405: .add(
406: tree,
407: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
408: 284,
409: Short.MAX_VALUE))
410: .addPreferredGap(
411: org.jdesktop.layout.LayoutStyle.RELATED)
412: .add(manageLibrariesButton)));
413:
414: librariesLabel.getAccessibleContext().setAccessibleDescription(
415: org.openide.util.NbBundle.getMessage(
416: LibraryChooserGUI.class,
417: "ACSD_AvailableLibraries")); // NOI18N
418: tree.getAccessibleContext().setAccessibleDescription(
419: org.openide.util.NbBundle.getMessage(
420: LibraryChooserGUI.class,
421: "ACSD_AvailableLibrariesTree")); // NOI18N
422: createButton.getAccessibleContext().setAccessibleName(
423: org.openide.util.NbBundle.getMessage(
424: LibraryChooserGUI.class,
425: "LibraryChooserGUI.create.a11y.name")); // NOI18N
426: createButton.getAccessibleContext().setAccessibleDescription(
427: org.openide.util.NbBundle.getMessage(
428: LibraryChooserGUI.class,
429: "LibraryChooserGUI.create.a11y.desc")); // NOI18N
430: importButton.getAccessibleContext().setAccessibleName(
431: org.openide.util.NbBundle.getMessage(
432: LibraryChooserGUI.class,
433: "LibraryChooserGUI.import.a11y.name")); // NOI18N
434: importButton.getAccessibleContext().setAccessibleDescription(
435: org.openide.util.NbBundle.getMessage(
436: LibraryChooserGUI.class,
437: "LibraryChooserGUI.import.a11y.desc")); // NOI18N
438: manageLibrariesButton.getAccessibleContext()
439: .setAccessibleDescription(
440: org.openide.util.NbBundle.getMessage(
441: LibraryChooserGUI.class,
442: "ACSD_ManageLibraries")); // NOI18N
443:
444: getAccessibleContext()
445: .setAccessibleName(
446: org.openide.util.NbBundle
447: .getMessage(LibraryChooserGUI.class,
448: "LibraryChooserGUI.AccessibleContext.accessibleName")); // NOI18N
449: getAccessibleContext().setAccessibleDescription(
450: org.openide.util.NbBundle.getMessage(
451: LibraryChooserGUI.class,
452: "LibraryChooserGUI.accessibleDescription")); // NOI18N
453: }// </editor-fold>//GEN-END:initComponents
454:
455: private void manageLibrariesButtonActionPerformed(
456: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manageLibrariesButtonActionPerformed
457: if (LibrariesCustomizer.showCustomizer(null, manager)) {
458: setRootNode();
459: }
460: }//GEN-LAST:event_manageLibrariesButtonActionPerformed
461:
462: private void createButtonActionPerformed(
463: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createButtonActionPerformed
464: Library l = LibrariesCustomizer
465: .showCreateNewLibraryCustomizer(manager);
466: if (l != null) {
467: setRootNode();
468: selectLibrary(Collections.singleton(l));
469: }
470: }//GEN-LAST:event_createButtonActionPerformed
471:
472: private void selectLibrary(Collection<Library> libraries) {
473: Node root = explorer.getRootContext();
474: List<Node> selection = new ArrayList<Node>();
475: for (Library lib : libraries) {
476: String[] path = { lib.getManager().getDisplayName(),
477: lib.getName() };
478: try {
479: Node node = NodeOp.findPath(root, path);
480: if (node != null) {
481: selection.add(node);
482: }
483: } catch (NodeNotFoundException e) {
484: //Ignore it
485: }
486: }
487: try {
488: explorer.setSelectedNodes(selection
489: .toArray(new Node[selection.size()]));
490: } catch (PropertyVetoException e) {
491: //Ignore it
492: }
493: }
494:
495: private void importButtonActionPerformed(
496: java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importButtonActionPerformed
497: Set<Library> libs = showChooser(LibraryManager.getDefault(),
498: new IgnoreAlreadyImportedLibrariesFilter(), null, false);
499: if (libs != null) {
500: Set<Library> importedLibs = new HashSet<Library>();
501: try {
502: for (Library lib : libs) {
503: importedLibs.add(importHandler.importLibrary(lib));
504: }
505: } catch (IOException ex) {
506: Exceptions.printStackTrace(ex);
507: }
508: setRootNode();
509: selectLibrary(importedLibs);
510: }
511: }//GEN-LAST:event_importButtonActionPerformed
512:
513: private class IgnoreAlreadyImportedLibrariesFilter implements
514: LibraryChooser.Filter {
515: public boolean accept(Library library) {
516: return manager.getLibrary(library.getName()) == null;
517: }
518: }
519:
520: // Variables declaration - do not modify//GEN-BEGIN:variables
521: private javax.swing.JButton createButton;
522: private javax.swing.JButton importButton;
523: private javax.swing.JLabel librariesLabel;
524: private javax.swing.JButton manageLibrariesButton;
525: private org.openide.explorer.view.BeanTreeView tree;
526: // End of variables declaration//GEN-END:variables
527:
528: }
|