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.java.j2seproject.ui.wizards;
043:
044: import java.io.File;
045: import java.io.IOException;
046: import java.text.MessageFormat;
047: import javax.swing.JFileChooser;
048: import javax.swing.event.DocumentEvent;
049: import javax.swing.event.DocumentListener;
050: import javax.swing.text.Document;
051: import org.netbeans.modules.java.j2seproject.ui.FoldersListSettings;
052: import org.netbeans.spi.project.ui.support.ProjectChooser;
053: import org.openide.WizardDescriptor;
054: import org.openide.WizardValidationException;
055: import org.openide.filesystems.FileUtil;
056: import org.openide.util.NbBundle;
057: import org.openide.util.Utilities;
058:
059: /**
060: *
061: * @author Petr Hrebejk
062: */
063:
064: public class PanelProjectLocationVisual extends SettingsPanel implements
065: DocumentListener {
066:
067: public static final String PROP_PROJECT_NAME = "projectName"; //NOI18N
068: public static final String PROP_PROJECT_LOCATION = "projectLocation"; //NOI18N
069:
070: private PanelConfigureProject panel;
071: private NewJ2SEProjectWizardIterator.WizardType type;
072:
073: public PanelProjectLocationVisual(PanelConfigureProject panel,
074: NewJ2SEProjectWizardIterator.WizardType type) {
075: initComponents();
076: this .panel = panel;
077: this .type = type;
078: // Register listener on the textFields to make the automatic updates
079: projectNameTextField.getDocument().addDocumentListener(this );
080: projectLocationTextField.getDocument()
081: .addDocumentListener(this );
082: }
083:
084: public String getProjectName() {
085: return this .projectNameTextField.getText();
086: }
087:
088: /** This method is called from within the constructor to
089: * initialize the form.
090: * WARNING: Do NOT modify this code. The content of this method is
091: * always regenerated by the Form Editor.
092: */
093: private void initComponents() {//GEN-BEGIN:initComponents
094: java.awt.GridBagConstraints gridBagConstraints;
095:
096: projectNameLabel = new javax.swing.JLabel();
097: projectNameTextField = new javax.swing.JTextField();
098: projectLocationLabel = new javax.swing.JLabel();
099: projectLocationTextField = new javax.swing.JTextField();
100: browseButton = new javax.swing.JButton();
101: createdFolderLabel = new javax.swing.JLabel();
102: createdFolderTextField = new javax.swing.JTextField();
103:
104: setLayout(new java.awt.GridBagLayout());
105:
106: getAccessibleContext().setAccessibleName(
107: org.openide.util.NbBundle.getMessage(
108: PanelProjectLocationVisual.class,
109: "ACSN_PanelProjectLocationVisual"));
110: getAccessibleContext().setAccessibleDescription(
111: org.openide.util.NbBundle.getMessage(
112: PanelProjectLocationVisual.class,
113: "ACSD_PanelProjectLocationVisual"));
114: projectNameLabel.setLabelFor(projectNameTextField);
115: org.openide.awt.Mnemonics.setLocalizedText(projectNameLabel,
116: org.openide.util.NbBundle.getMessage(
117: PanelProjectLocationVisual.class,
118: "LBL_NWP1_ProjectName_Label"));
119: gridBagConstraints = new java.awt.GridBagConstraints();
120: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
121: gridBagConstraints.insets = new java.awt.Insets(0, 0, 12, 0);
122: add(projectNameLabel, gridBagConstraints);
123: projectNameLabel.getAccessibleContext().setAccessibleName(
124: org.openide.util.NbBundle.getBundle(
125: PanelProjectLocationVisual.class).getString(
126: "ACSN_projectNameLabel"));
127: projectNameLabel.getAccessibleContext()
128: .setAccessibleDescription(
129: org.openide.util.NbBundle.getBundle(
130: PanelProjectLocationVisual.class)
131: .getString("ACSD_projectNameLabel"));
132:
133: gridBagConstraints = new java.awt.GridBagConstraints();
134: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
135: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
136: gridBagConstraints.weightx = 1.0;
137: gridBagConstraints.insets = new java.awt.Insets(0, 12, 12, 0);
138: add(projectNameTextField, gridBagConstraints);
139:
140: projectLocationLabel.setLabelFor(projectLocationTextField);
141: org.openide.awt.Mnemonics.setLocalizedText(
142: projectLocationLabel, org.openide.util.NbBundle
143: .getMessage(PanelProjectLocationVisual.class,
144: "LBL_NWP1_ProjectLocation_Label"));
145: gridBagConstraints = new java.awt.GridBagConstraints();
146: gridBagConstraints.gridy = 1;
147: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
148: gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
149: add(projectLocationLabel, gridBagConstraints);
150: projectLocationLabel.getAccessibleContext().setAccessibleName(
151: org.openide.util.NbBundle.getBundle(
152: PanelProjectLocationVisual.class).getString(
153: "ACSN_projectLocationLabel"));
154: projectLocationLabel
155: .getAccessibleContext()
156: .setAccessibleDescription(
157: org.openide.util.NbBundle.getBundle(
158: PanelProjectLocationVisual.class)
159: .getString("ACSD_projectLocationLabel"));
160:
161: gridBagConstraints = new java.awt.GridBagConstraints();
162: gridBagConstraints.gridy = 1;
163: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
164: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
165: gridBagConstraints.weightx = 1.0;
166: gridBagConstraints.insets = new java.awt.Insets(0, 12, 5, 0);
167: add(projectLocationTextField, gridBagConstraints);
168:
169: org.openide.awt.Mnemonics.setLocalizedText(browseButton,
170: org.openide.util.NbBundle.getMessage(
171: PanelProjectLocationVisual.class,
172: "LBL_NWP1_BrowseLocation_Button"));
173: browseButton.setActionCommand("BROWSE");
174: browseButton
175: .addActionListener(new java.awt.event.ActionListener() {
176: public void actionPerformed(
177: java.awt.event.ActionEvent evt) {
178: browseLocationAction(evt);
179: }
180: });
181:
182: gridBagConstraints = new java.awt.GridBagConstraints();
183: gridBagConstraints.gridy = 1;
184: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
185: gridBagConstraints.insets = new java.awt.Insets(0, 6, 5, 0);
186: add(browseButton, gridBagConstraints);
187: browseButton.getAccessibleContext().setAccessibleName(
188: org.openide.util.NbBundle.getBundle(
189: PanelProjectLocationVisual.class).getString(
190: "ACSN_browseButton"));
191: browseButton.getAccessibleContext().setAccessibleDescription(
192: org.openide.util.NbBundle.getBundle(
193: PanelProjectLocationVisual.class).getString(
194: "ACSD_browseButton"));
195:
196: createdFolderLabel.setLabelFor(createdFolderTextField);
197: org.openide.awt.Mnemonics.setLocalizedText(createdFolderLabel,
198: org.openide.util.NbBundle.getMessage(
199: PanelProjectLocationVisual.class,
200: "LBL_NWP1_CreatedProjectFolder_Lablel"));
201: gridBagConstraints = new java.awt.GridBagConstraints();
202: gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
203: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
204: add(createdFolderLabel, gridBagConstraints);
205: createdFolderLabel.getAccessibleContext().setAccessibleName(
206: org.openide.util.NbBundle.getBundle(
207: PanelProjectLocationVisual.class).getString(
208: "ACSN_createdFolderLabel"));
209: createdFolderLabel.getAccessibleContext()
210: .setAccessibleDescription(
211: org.openide.util.NbBundle.getBundle(
212: PanelProjectLocationVisual.class)
213: .getString("ACSD_createdFolderLabel"));
214:
215: createdFolderTextField.setEditable(false);
216: gridBagConstraints = new java.awt.GridBagConstraints();
217: gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
218: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
219: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
220: gridBagConstraints.weightx = 1.0;
221: gridBagConstraints.weighty = 1.0;
222: gridBagConstraints.insets = new java.awt.Insets(0, 12, 0, 0);
223: add(createdFolderTextField, gridBagConstraints);
224:
225: }//GEN-END:initComponents
226:
227: private void browseLocationAction(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseLocationAction
228: String command = evt.getActionCommand();
229: if ("BROWSE".equals(command)) { // NOI18N
230: JFileChooser chooser = new JFileChooser();
231: FileUtil.preventFileChooserSymlinkTraversal(chooser, null);
232: chooser.setDialogTitle(NbBundle.getMessage(
233: PanelSourceFolders.class,
234: "LBL_NWP1_SelectProjectLocation"));
235: chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
236: String path = this .projectLocationTextField.getText();
237: if (path.length() > 0) {
238: File f = new File(path);
239: if (f.exists()) {
240: chooser.setSelectedFile(f);
241: }
242: }
243: if (JFileChooser.APPROVE_OPTION == chooser
244: .showOpenDialog(this )) { //NOI18N
245: File projectDir = chooser.getSelectedFile();
246: projectLocationTextField.setText(FileUtil
247: .normalizeFile(projectDir).getAbsolutePath());
248: }
249: panel.fireChangeEvent();
250: }
251: }//GEN-LAST:event_browseLocationAction
252:
253: public void addNotify() {
254: super .addNotify();
255: //same problem as in 31086, initial focus on Cancel button
256: projectNameTextField.requestFocus();
257: }
258:
259: boolean valid(WizardDescriptor wizardDescriptor) {
260:
261: if (projectNameTextField.getText().length() == 0
262: || projectNameTextField.getText().indexOf('/') > 0 //NOI18N
263: || projectNameTextField.getText().indexOf('\\') > 0 //NOI18N
264: || projectNameTextField.getText().indexOf(':') > 0) { //NOI18N
265: wizardDescriptor.putProperty("WizardPanel_errorMessage", // NOI18N
266: NbBundle.getMessage(
267: PanelProjectLocationVisual.class,
268: "MSG_IllegalProjectName"));
269: return false; // Display name not specified
270: }
271: File f = new File(projectLocationTextField.getText())
272: .getAbsoluteFile();
273: if (getCanonicalFile(f) == null) {
274: String message = NbBundle.getMessage(
275: PanelProjectLocationVisual.class,
276: "MSG_IllegalProjectLocation");
277: wizardDescriptor.putProperty("WizardPanel_errorMessage",
278: message);
279: return false;
280: }
281: // not allow to create project on unix root folder, see #82339
282: File cfl = getCanonicalFile(new File(createdFolderTextField
283: .getText()));
284: if (Utilities.isUnix() && cfl != null
285: && cfl.getParentFile().getParent() == null) {
286: String message = NbBundle.getMessage(
287: PanelProjectLocationVisual.class,
288: "MSG_ProjectInRootNotSupported");
289: wizardDescriptor.putProperty("WizardPanel_errorMessage",
290: message);
291: return false;
292: }
293:
294: final File destFolder = new File(createdFolderTextField
295: .getText()).getAbsoluteFile();
296: if (getCanonicalFile(destFolder) == null) {
297: String message = NbBundle.getMessage(
298: PanelProjectLocationVisual.class,
299: "MSG_IllegalProjectLocation");
300: wizardDescriptor.putProperty("WizardPanel_errorMessage",
301: message);
302: return false;
303: }
304:
305: File projLoc = FileUtil.normalizeFile(destFolder);
306: while (projLoc != null && !projLoc.exists()) {
307: projLoc = projLoc.getParentFile();
308: }
309: if (projLoc == null || !projLoc.canWrite()) {
310: wizardDescriptor.putProperty("WizardPanel_errorMessage", // NOI18N
311: NbBundle.getMessage(
312: PanelProjectLocationVisual.class,
313: "MSG_ProjectFolderReadOnly"));
314: return false;
315: }
316:
317: if (FileUtil.toFileObject(projLoc) == null) {
318: String message = NbBundle.getMessage(
319: PanelProjectLocationVisual.class,
320: "MSG_IllegalProjectLocation");
321: wizardDescriptor.putProperty("WizardPanel_errorMessage",
322: message);
323: return false;
324: }
325:
326: File[] kids = destFolder.listFiles();
327: if (destFolder.exists() && kids != null && kids.length > 0) {
328: // Folder exists and is not empty
329: wizardDescriptor.putProperty("WizardPanel_errorMessage", // NOI18N
330: NbBundle.getMessage(
331: PanelProjectLocationVisual.class,
332: "MSG_ProjectFolderExists"));
333: return false;
334: }
335: return true;
336: }
337:
338: void store(WizardDescriptor d) {
339:
340: String name = projectNameTextField.getText().trim();
341: String location = projectLocationTextField.getText().trim();
342: String folder = createdFolderTextField.getText().trim();
343:
344: d.putProperty( /*XXX Define somewhere */"projdir", new File(
345: folder)); // NOI18N
346: d.putProperty( /*XXX Define somewhere */"name", name); // NOI18N
347: }
348:
349: void read(WizardDescriptor settings) {
350: File projectLocation = (File) settings.getProperty("projdir"); //NOI18N
351: if (projectLocation == null
352: || projectLocation.getParentFile() == null
353: || !projectLocation.getParentFile().isDirectory()) {
354: projectLocation = ProjectChooser.getProjectsFolder();
355: } else {
356: projectLocation = projectLocation.getParentFile();
357: }
358: this .projectLocationTextField.setText(projectLocation
359: .getAbsolutePath());
360:
361: String projectName = (String) settings.getProperty("name"); //NOI18N
362: if (projectName == null) {
363: switch (type) {
364: case APP:
365: int baseCount = FoldersListSettings.getDefault()
366: .getNewApplicationCount() + 1;
367: String formatter = NbBundle
368: .getMessage(PanelSourceFolders.class,
369: "TXT_JavaApplication");
370: while ((projectName = validFreeProjectName(
371: projectLocation, formatter, baseCount)) == null)
372: baseCount++;
373: settings.putProperty(
374: NewJ2SEProjectWizardIterator.PROP_NAME_INDEX,
375: new Integer(baseCount));
376: break;
377: default:
378: baseCount = FoldersListSettings.getDefault()
379: .getNewLibraryCount() + 1;
380: formatter = NbBundle.getMessage(
381: PanelSourceFolders.class, "TXT_JavaLibrary");
382: while ((projectName = validFreeProjectName(
383: projectLocation, formatter, baseCount)) == null)
384: baseCount++;
385: settings.putProperty(
386: NewJ2SEProjectWizardIterator.PROP_NAME_INDEX,
387: new Integer(baseCount));
388: }
389: }
390: this .projectNameTextField.setText(projectName);
391: this .projectNameTextField.selectAll();
392: }
393:
394: void validate(WizardDescriptor d) throws WizardValidationException {
395: // nothing to validate
396: }
397:
398: // Variables declaration - do not modify//GEN-BEGIN:variables
399: private javax.swing.JButton browseButton;
400: private javax.swing.JLabel createdFolderLabel;
401: private javax.swing.JTextField createdFolderTextField;
402: private javax.swing.JLabel projectLocationLabel;
403: private javax.swing.JTextField projectLocationTextField;
404: private javax.swing.JLabel projectNameLabel;
405: private javax.swing.JTextField projectNameTextField;
406:
407: // End of variables declaration//GEN-END:variables
408:
409: // Private methods ---------------------------------------------------------
410:
411: private static JFileChooser createChooser() {
412: JFileChooser chooser = new JFileChooser();
413: FileUtil.preventFileChooserSymlinkTraversal(chooser, null);
414: chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
415: chooser.setAcceptAllFileFilterUsed(false);
416: chooser.setName("Select Project Directory"); // XXX // NOI18N
417: return chooser;
418: }
419:
420: private String validFreeProjectName(final File parentFolder,
421: final String formater, final int index) {
422: String name = MessageFormat.format(formater,
423: new Object[] { new Integer(index) });
424: File file = new File(parentFolder, name);
425: return file.exists() ? null : name;
426: }
427:
428: // Implementation of DocumentListener --------------------------------------
429:
430: public void changedUpdate(DocumentEvent e) {
431: updateTexts(e);
432: if (this .projectNameTextField.getDocument() == e.getDocument()) {
433: firePropertyChange(PROP_PROJECT_NAME, null,
434: this .projectNameTextField.getText());
435: }
436: if (this .projectLocationTextField.getDocument() == e
437: .getDocument()) {
438: firePropertyChange(PROP_PROJECT_LOCATION, null,
439: this .projectLocationTextField.getText());
440: }
441: }
442:
443: public void insertUpdate(DocumentEvent e) {
444: updateTexts(e);
445: if (this .projectNameTextField.getDocument() == e.getDocument()) {
446: firePropertyChange(PROP_PROJECT_NAME, null,
447: this .projectNameTextField.getText());
448: }
449: if (this .projectLocationTextField.getDocument() == e
450: .getDocument()) {
451: firePropertyChange(PROP_PROJECT_LOCATION, null,
452: this .projectLocationTextField.getText());
453: }
454: }
455:
456: public void removeUpdate(DocumentEvent e) {
457: updateTexts(e);
458: if (this .projectNameTextField.getDocument() == e.getDocument()) {
459: firePropertyChange(PROP_PROJECT_NAME, null,
460: this .projectNameTextField.getText());
461: }
462: if (this .projectLocationTextField.getDocument() == e
463: .getDocument()) {
464: firePropertyChange(PROP_PROJECT_LOCATION, null,
465: this .projectLocationTextField.getText());
466: }
467: }
468:
469: /** Handles changes in the Project name and project directory
470: */
471: private void updateTexts(DocumentEvent e) {
472: Document doc = e.getDocument();
473: if (doc == projectNameTextField.getDocument()
474: || doc == projectLocationTextField.getDocument()) {
475: // Change in the project name
476: String projectName = projectNameTextField.getText();
477: String projectFolder = projectLocationTextField.getText();
478: String projFolderPath = FileUtil.normalizeFile(
479: new File(projectFolder)).getAbsolutePath();
480: if (projFolderPath.endsWith(File.separator)) {
481: createdFolderTextField.setText(projFolderPath
482: + projectName);
483: } else {
484: createdFolderTextField.setText(projFolderPath
485: + File.separator + projectName);
486: }
487: }
488: panel.fireChangeEvent(); // Notify that the panel changed
489: }
490:
491: static File getCanonicalFile(File file) {
492: try {
493: return file.getCanonicalFile();
494: } catch (IOException e) {
495: return null;
496: }
497: }
498:
499: }
|