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: /*
042: * ImportComplibPanel.java
043: *
044: * Created on May 31, 2006, 3:42 PM
045: */
046:
047: package org.netbeans.modules.visualweb.complib.ui;
048:
049: import java.awt.Dialog;
050: import java.io.File;
051: import java.util.List;
052:
053: import javax.swing.Icon;
054: import javax.swing.JFileChooser;
055: import javax.swing.JLabel;
056: import javax.swing.JPanel;
057: import javax.swing.JProgressBar;
058: import javax.swing.event.DocumentEvent;
059: import javax.swing.event.DocumentListener;
060: import javax.swing.filechooser.FileFilter;
061: import javax.swing.tree.DefaultMutableTreeNode;
062: import javax.swing.tree.DefaultTreeCellRenderer;
063: import javax.swing.tree.DefaultTreeModel;
064:
065: import org.openide.DialogDescriptor;
066: import org.openide.DialogDisplayer;
067: import org.openide.NotifyDescriptor;
068: import org.openide.util.HelpCtx;
069: import org.openide.util.NbBundle;
070: import org.openide.util.RequestProcessor;
071:
072: import org.netbeans.modules.visualweb.complib.Complib;
073: import org.netbeans.modules.visualweb.complib.ComplibPackage;
074: import org.netbeans.modules.visualweb.complib.ComplibServiceProvider;
075: import org.netbeans.modules.visualweb.complib.ExtensionComplib;
076: import org.netbeans.modules.visualweb.complib.IdeUtil;
077: import org.netbeans.modules.visualweb.complib.Complib.InitialPaletteFolder;
078:
079: /**
080: * Import complib panel dialog. NetBeans Matisse generated code is at the
081: * beginning of this file and user added code appears after.
082: *
083: * @author Edwin Goei
084: */
085: public class ImportComplibPanel extends javax.swing.JPanel {
086: private static final long serialVersionUID = 1L;
087:
088: /** Creates new form ImportComplibPanel */
089: public ImportComplibPanel() {
090: // Init in showDialog()
091: // initComponents();
092: }
093:
094: /**
095: * This method is called from within the constructor to initialize the form.
096: * WARNING: Do NOT modify this code. The content of this method is always
097: * regenerated by the Form Editor.
098: */
099: // <editor-fold defaultstate="collapsed" desc=" Generated Code
100: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
101: private void initComponents() {
102: packageLabel = new javax.swing.JLabel();
103: packageTextField = new javax.swing.JTextField();
104: browseButton = new javax.swing.JButton();
105: previewLabel = new javax.swing.JLabel();
106: previewScrollPane = new javax.swing.JScrollPane();
107: previewTree = new javax.swing.JTree();
108: errorLabel = new javax.swing.JLabel();
109:
110: packageLabel.setLabelFor(packageTextField);
111: org.openide.awt.Mnemonics.setLocalizedText(packageLabel,
112: org.openide.util.NbBundle.getBundle(
113: ImportComplibPanel.class).getString(
114: "import.packageLabel"));
115: packageLabel.getAccessibleContext().setAccessibleName(
116: org.openide.util.NbBundle.getMessage(
117: ImportComplibPanel.class,
118: "ACSN_import.packageLabel"));
119: packageLabel.getAccessibleContext().setAccessibleDescription(
120: org.openide.util.NbBundle.getMessage(
121: ImportComplibPanel.class,
122: "ACSD_import.packageLabel"));
123:
124: packageTextField.getAccessibleContext().setAccessibleName(
125: org.openide.util.NbBundle.getMessage(
126: ImportComplibPanel.class,
127: "ACSN_import.packageLabel"));
128: packageTextField.getAccessibleContext()
129: .setAccessibleDescription(
130: org.openide.util.NbBundle.getMessage(
131: ImportComplibPanel.class,
132: "ACSD_import.packageLabel"));
133:
134: org.openide.awt.Mnemonics.setLocalizedText(browseButton,
135: org.openide.util.NbBundle
136: .getMessage(ImportComplibPanel.class,
137: "import.browseButton"));
138: browseButton
139: .addActionListener(new java.awt.event.ActionListener() {
140: public void actionPerformed(
141: java.awt.event.ActionEvent evt) {
142: browseButtonActionPerformed(evt);
143: }
144: });
145:
146: browseButton.getAccessibleContext().setAccessibleName(
147: org.openide.util.NbBundle.getMessage(
148: ImportComplibPanel.class,
149: "ACSN_import.browseButton"));
150: browseButton.getAccessibleContext().setAccessibleDescription(
151: org.openide.util.NbBundle.getMessage(
152: ImportComplibPanel.class,
153: "ACSD_import.browseButton"));
154:
155: previewLabel.setLabelFor(previewTree);
156: previewLabel.setText(org.openide.util.NbBundle.getMessage(
157: ImportComplibPanel.class, "import.previewLabel"));
158: previewLabel.getAccessibleContext().setAccessibleDescription(
159: previewLabel.getText());
160:
161: previewTree.setRootVisible(false);
162: previewTree.setSelectionModel(null);
163: previewScrollPane.setViewportView(previewTree);
164:
165: errorLabel.setForeground(java.awt.Color.red);
166: errorLabel.setText("Error");
167:
168: org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(
169: this );
170: this .setLayout(layout);
171: layout
172: .setHorizontalGroup(layout
173: .createParallelGroup(
174: org.jdesktop.layout.GroupLayout.LEADING)
175: .add(
176: org.jdesktop.layout.GroupLayout.TRAILING,
177: layout
178: .createSequentialGroup()
179: .addContainerGap()
180: .add(
181: layout
182: .createParallelGroup(
183: org.jdesktop.layout.GroupLayout.TRAILING)
184: .add(
185: org.jdesktop.layout.GroupLayout.LEADING,
186: previewScrollPane,
187: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
188: 401,
189: Short.MAX_VALUE)
190: .add(
191: layout
192: .createSequentialGroup()
193: .add(
194: packageTextField,
195: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
196: 316,
197: Short.MAX_VALUE)
198: .addPreferredGap(
199: org.jdesktop.layout.LayoutStyle.RELATED)
200: .add(
201: browseButton))
202: .add(
203: org.jdesktop.layout.GroupLayout.LEADING,
204: previewLabel)
205: .add(
206: org.jdesktop.layout.GroupLayout.LEADING,
207: packageLabel)
208: .add(
209: org.jdesktop.layout.GroupLayout.LEADING,
210: errorLabel))
211: .addContainerGap()));
212: layout
213: .setVerticalGroup(layout
214: .createParallelGroup(
215: org.jdesktop.layout.GroupLayout.LEADING)
216: .add(
217: org.jdesktop.layout.GroupLayout.TRAILING,
218: layout
219: .createSequentialGroup()
220: .addContainerGap()
221: .add(packageLabel)
222: .addPreferredGap(
223: org.jdesktop.layout.LayoutStyle.RELATED)
224: .add(
225: layout
226: .createParallelGroup(
227: org.jdesktop.layout.GroupLayout.BASELINE)
228: .add(
229: browseButton)
230: .add(
231: packageTextField,
232: org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
233: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
234: org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
235: .addPreferredGap(
236: org.jdesktop.layout.LayoutStyle.RELATED)
237: .add(previewLabel)
238: .addPreferredGap(
239: org.jdesktop.layout.LayoutStyle.RELATED)
240: .add(
241: previewScrollPane,
242: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
243: 117, Short.MAX_VALUE)
244: .addPreferredGap(
245: org.jdesktop.layout.LayoutStyle.RELATED)
246: .add(
247: errorLabel,
248: org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
249: 14,
250: org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)));
251: }// </editor-fold>//GEN-END:initComponents
252:
253: // Variables declaration - do not modify//GEN-BEGIN:variables
254: private javax.swing.JButton browseButton;
255: private javax.swing.JLabel errorLabel;
256: private javax.swing.JLabel packageLabel;
257: private javax.swing.JTextField packageTextField;
258: private javax.swing.JLabel previewLabel;
259: private javax.swing.JScrollPane previewScrollPane;
260: private javax.swing.JTree previewTree;
261: // End of variables declaration//GEN-END:variables
262:
263: /**
264: * Beginning of non-generated code
265: */
266:
267: private static File savedCurDir = ComplibOptionsPanel
268: .getImportStartDir();
269:
270: private static DefaultTreeModel EMPTY_TREE_MODEL = new DefaultTreeModel(
271: new DefaultMutableTreeNode("/emptyPaletteRoot"));
272:
273: private DialogDescriptor descriptor;
274:
275: private ComplibPackage complibPackage;
276:
277: /**
278: * Filter file selection so only files with complibExtention are shown
279: */
280: private static class CompLibFileFilter extends FileFilter {
281:
282: public final static String compLibExtension = "complib"; // NOI18N
283:
284: /**
285: * Allow directories
286: */
287: public boolean accept(File f) {
288: if (f.isDirectory()) {
289: return true;
290: }
291:
292: String extension = getExtension(f);
293: if (extension != null) {
294: return extension.equals(compLibExtension);
295: }
296: return false;
297: }
298:
299: public String getExtension(File f) {
300: String ext = null;
301: String s = f.getName();
302: int i = s.lastIndexOf('.');
303:
304: if (i > 0 && i < s.length() - 1) {
305: ext = s.substring(i + 1).toLowerCase();
306: }
307: return ext;
308: }
309:
310: /** The description of this filter */
311: public String getDescription() {
312: return NbBundle.getMessage(CompLibFileFilter.class,
313: "import.compLibFileFilter"); // NOI18N
314: }
315: }
316:
317: private void browseButtonActionPerformed(
318: java.awt.event.ActionEvent evt) {
319: JFileChooser fcd = org.netbeans.modules.visualweb.extension.openide.awt.JFileChooser_RAVE
320: .getJFileChooser();
321: CompLibFileFilter compLibFileFilter = new CompLibFileFilter();
322: fcd.setFileFilter(compLibFileFilter);
323: fcd.setCurrentDirectory(savedCurDir);
324:
325: if (fcd.showOpenDialog(this ) == JFileChooser.APPROVE_OPTION) {
326: File packageFile = fcd.getSelectedFile();
327:
328: // Save the directory containing the chosen file for future dialogs
329: if (packageFile != null) {
330: File curDir = packageFile.getParentFile();
331: if (curDir != null) {
332: savedCurDir = curDir;
333: }
334: }
335:
336: // This causes DocumentListener events to be fired
337: packageTextField.setText(packageFile.getAbsolutePath());
338: }
339: }
340:
341: /**
342: * This method is the main entry point for this dialog panel
343: *
344: * @param compLibManagerPanel
345: * Component Library Manager
346: */
347: public void showDialog(final CompLibManagerPanel compLibManagerPanel) {
348: initComponents();
349:
350: packageTextField.getDocument().addDocumentListener(
351: new DocumentListener() {
352: public void changedUpdate(DocumentEvent e) {
353: }
354:
355: public void insertUpdate(DocumentEvent e) {
356: packageFileChanged();
357: }
358:
359: public void removeUpdate(DocumentEvent e) {
360: packageFileChanged();
361: }
362: });
363:
364: // Init predefined categories to empty list
365: previewTree.setModel(EMPTY_TREE_MODEL);
366:
367: // Override the leaf icon to be the same as a closed branch icon
368: previewTree.setCellRenderer(new DefaultTreeCellRenderer() {
369: private static final long serialVersionUID = 1L;
370:
371: public Icon getLeafIcon() {
372: return getClosedIcon();
373: }
374: });
375:
376: clearErrorMessage();
377: setValid(false);
378:
379: // TODO Change the label on the OK button to "Import". Note we can't use
380: // the following code because the setValid() method does not work.
381: if (false) {
382: String importButton = NbBundle.getMessage(
383: ImportComplibPanel.class, "import.importButton"); // NOI18N
384: String cancelButton = NbBundle.getMessage(
385: ImportComplibPanel.class, "global.cancelButton"); // NOI18N
386: String helpButton = NbBundle.getMessage(
387: ImportComplibPanel.class, "global.helpButton"); // NOI18N
388: Object[] options = new Object[] { importButton,
389: cancelButton };
390: }
391:
392: String title = NbBundle.getMessage(ImportComplibPanel.class,
393: "import.dialogTitle"); // NOI18N
394: HelpCtx helpCtx = new HelpCtx(
395: "projrave_ui_elements_dialogs_import_components_db"); // NOI18N
396: descriptor = new DialogDescriptor(this , title, true,
397: DialogDescriptor.OK_CANCEL_OPTION,
398: DialogDescriptor.OK_OPTION,
399: DialogDescriptor.DEFAULT_ALIGN, helpCtx, null);
400: Dialog dialog = DialogDisplayer.getDefault().createDialog(
401: descriptor);
402: dialog
403: .getAccessibleContext()
404: .setAccessibleName(
405: java.util.ResourceBundle
406: .getBundle(
407: "org/netbeans/modules/visualweb/complib/ui/Bundle")
408: .getString("ACSN_import.dialog"));
409: dialog
410: .getAccessibleContext()
411: .setAccessibleDescription(
412: java.util.ResourceBundle
413: .getBundle(
414: "org/netbeans/modules/visualweb/complib/ui/Bundle")
415: .getString("ACSD_import.dialog"));
416:
417: descriptor.setValid(false);
418:
419: dialog.setVisible(true);
420: if (!descriptor.getValue().equals(DialogDescriptor.OK_OPTION)) {
421: // Cancel, or Esc: do nothing
422: return;
423: }
424:
425: final Dialog progressDialog = showProgressBar("import.progressImport");
426:
427: RequestProcessor.getDefault().post(new Runnable() { // separate thread
428: public void run() {
429: Complib newComplib = null;
430: try {
431: newComplib = doImportLibrary();
432: } catch (Exception e) {
433: // Log the exception
434: IdeUtil.logError(e);
435:
436: // Notify user to check ide.log for more info
437: String msg = NbBundle.getMessage(
438: ImportComplibPanel.class,
439: "import.importFailed"); // NOI18N
440: NotifyDescriptor nd = new NotifyDescriptor.Message(
441: msg, NotifyDescriptor.ERROR_MESSAGE);
442: DialogDisplayer.getDefault().notify(nd);
443: }
444:
445: progressDialog.dispose();
446: compLibManagerPanel
447: .notifyImportComplete(newComplib);
448: }
449: });
450: }
451:
452: private Dialog showProgressBar(String resourceKey) {
453: String msg = NbBundle.getMessage(ImportComplibPanel.class,
454: resourceKey);
455: String title = NbBundle.getMessage(ImportComplibPanel.class,
456: "global.progressTitle");
457:
458: JPanel panel = new JPanel();
459: java.awt.GridBagConstraints gridBagConstraints;
460: JLabel jLabel1 = new javax.swing.JLabel();
461: JProgressBar jProgressBar1 = new javax.swing.JProgressBar();
462: jProgressBar1.setIndeterminate(true);
463: jProgressBar1.setStringPainted(false);
464: panel.setLayout(new java.awt.GridBagLayout());
465:
466: jLabel1.setText(msg);
467: gridBagConstraints = new java.awt.GridBagConstraints();
468: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
469: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
470: gridBagConstraints.insets = new java.awt.Insets(12, 12, 0, 11);
471: panel.add(jLabel1, gridBagConstraints);
472:
473: gridBagConstraints = new java.awt.GridBagConstraints();
474: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
475: gridBagConstraints.weightx = 1.0;
476: gridBagConstraints.insets = new java.awt.Insets(0, 12, 11, 11);
477: panel.add(jProgressBar1, gridBagConstraints);
478:
479: // Create dialog with a single "close" button
480: String close = NbBundle.getMessage(ImportComplibPanel.class,
481: "global.labelClose"); // NOI18N
482: Object[] options = new Object[] { close };
483: DialogDescriptor dlg = new DialogDescriptor(panel, title,
484: false, options, close, DialogDescriptor.DEFAULT_ALIGN,
485: null, null);
486: Dialog progressDialog = DialogDisplayer.getDefault()
487: .createDialog(dlg);
488: progressDialog.setVisible(true);
489: return progressDialog;
490: }
491:
492: /**
493: * @return new complib iff a new complib was actually imported
494: * @throws Exception
495: */
496: private ExtensionComplib doImportLibrary() throws Exception {
497: assert descriptor.isValid();
498:
499: ComplibServiceProvider compManager = ComplibServiceProvider
500: .getInstance();
501:
502: if (compManager.isInstalled(complibPackage)) {
503: String message = NbBundle.getMessage(
504: ImportComplibPanel.class, "import.libraryExists"); // NOI18N
505: NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
506: message, NotifyDescriptor.YES_NO_OPTION);
507: Object result = DialogDisplayer.getDefault().notify(nd);
508: if (NotifyDescriptor.YES_OPTION != result) {
509: return null;
510: }
511: // Continue which will overwrite the old library
512: }
513:
514: return compManager.installComplibPackage(complibPackage);
515: }
516:
517: private void clearErrorMessage() {
518: // not empty - that will shrink the height to 0
519: errorLabel.setText(" ");
520: }
521:
522: private void setValid(boolean state) {
523: if (descriptor != null) {
524: descriptor.setValid(state);
525: }
526: }
527:
528: /**
529: * Validate the package file field and return corresponding ComplibPackage
530: * iff valid. If it returns null, then error message and valid state has
531: * been set.
532: *
533: * @return ExtensionComplib iff package file field is valid
534: */
535: private ComplibPackage validatePackageFile() {
536: File packageFile = validatePackageName();
537: if (packageFile == null) {
538: // Invalid package message and valid state has already been set
539: return null;
540: }
541:
542: ComplibPackage inputPackage;
543: try {
544: inputPackage = new ComplibPackage(packageFile);
545: } catch (Exception e) {
546: // Log the exception
547: IdeUtil.logError(e);
548:
549: setErrorMessage("import.notReadable"); // NOI18N
550: return null;
551: }
552:
553: return inputPackage;
554: }
555:
556: /**
557: * Validate the package file
558: */
559: private void packageFileChanged() {
560: complibPackage = validatePackageFile();
561: if (complibPackage == null) {
562: // Invalid package
563: // Error message and valid state has already been set.
564:
565: // Clear preview model
566: previewTree.setModel(EMPTY_TREE_MODEL);
567: return;
568: }
569:
570: // If we get here then the package file is valid.
571: updatePreviewTreeModel();
572: clearErrorMessage();
573: setValid(true);
574: }
575:
576: private void updatePreviewTreeModel() {
577: DefaultMutableTreeNode root = new DefaultMutableTreeNode(
578: "/paletteRoot");
579:
580: List<InitialPaletteFolder> topFolders = complibPackage
581: .getInitialPaletteFolders();
582: if (topFolders.isEmpty()) {
583: // No initial palette folders defined so use title
584: root.add(new DefaultMutableTreeNode(complibPackage
585: .getTitle()));
586: } else {
587: for (InitialPaletteFolder folder : topFolders) {
588: DefaultMutableTreeNode n = new DefaultMutableTreeNode(
589: folder.getName());
590: root.add(n);
591: }
592: }
593:
594: DefaultTreeModel treeModel = new DefaultTreeModel(root);
595: previewTree.setModel(treeModel);
596: }
597:
598: /**
599: * Validate Package file name field
600: *
601: * @return null iff not a *.complib file and sets error message and state
602: */
603: private File validatePackageName() {
604: // Perform validation
605: String text = packageTextField.getText().trim();
606:
607: // Convert to absolute and check that it's a non-directory
608: File f = validateFileName(text);
609: if (f == null) {
610: return null;
611: }
612:
613: // Check that it is a complib file
614: if (new CompLibFileFilter().accept(f)) {
615: return f;
616: }
617:
618: setErrorMessage("import.notCompLib"); // NOI18N
619: return null;
620: }
621:
622: private void setErrorMessage(String key) {
623: errorLabel.setText(NbBundle.getMessage(
624: ImportComplibPanel.class, key)); // NOI18N
625: setValid(false);
626: }
627:
628: /**
629: * Validate that "name" is a non-directory file and return it as an absolute
630: * File using the saved current directory if it is relative.
631: *
632: * @param fileName
633: * @return File object representing fileName or null if not valid
634: */
635: private File validateFileName(String fileName) {
636: File f = new File(fileName);
637: if (!f.isAbsolute()) {
638: f = new File(savedCurDir, fileName);
639: }
640:
641: if (f.exists()) {
642: if (f.isDirectory()) {
643: setErrorMessage("import.isDirectory"); // NOI18N
644: return null;
645: }
646: return f;
647: }
648:
649: setErrorMessage("import.noSuchFile"); // NOI18N
650: return null;
651: }
652: }
|