001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2008 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-2008 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.ruby.rubyproject.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 org.openide.WizardDescriptor;
051: import org.openide.WizardValidationException;
052: import org.openide.filesystems.FileObject;
053: import org.openide.filesystems.FileUtil;
054: import org.openide.util.NbBundle;
055: import org.netbeans.api.project.ProjectManager;
056: import org.netbeans.modules.ruby.rubyproject.ui.FoldersListSettings;
057: import org.netbeans.spi.project.ui.support.ProjectChooser;
058:
059: /**
060: * Sets up source and test folders for new Java project from existing sources.
061: * @author Tomas Zezula et al.
062: */
063: public class PanelProjectLocationExtSrc extends SettingsPanel {
064:
065: private final PanelConfigureProject firer;
066: private WizardDescriptor wizardDescriptor;
067: private boolean calculatePF;
068:
069: public PanelProjectLocationExtSrc(PanelConfigureProject panel) {
070: this .firer = panel;
071: initComponents();
072: this .projectName.getDocument().addDocumentListener(
073: new DocumentListener() {
074: public void changedUpdate(DocumentEvent e) {
075: calculateProjectFolder();
076: dataChanged();
077: }
078:
079: public void insertUpdate(DocumentEvent e) {
080: calculateProjectFolder();
081: dataChanged();
082: }
083:
084: public void removeUpdate(DocumentEvent e) {
085: calculateProjectFolder();
086: dataChanged();
087: }
088: });
089: this .projectLocation.getDocument().addDocumentListener(
090: new DocumentListener() {
091: public void changedUpdate(DocumentEvent e) {
092: setCalculateProjectFolder(false);
093: dataChanged();
094: }
095:
096: public void insertUpdate(DocumentEvent e) {
097: setCalculateProjectFolder(false);
098: dataChanged();
099: }
100:
101: public void removeUpdate(DocumentEvent e) {
102: setCalculateProjectFolder(false);
103: dataChanged();
104: }
105: });
106: }
107:
108: private synchronized void calculateProjectFolder() {
109: if (this .calculatePF) {
110: File f = ProjectChooser.getProjectsFolder();
111: this .projectLocation.setText(f.getAbsolutePath()
112: + File.separator + this .projectName.getText());
113: this .calculatePF = true;
114: }
115: }
116:
117: private synchronized void setCalculateProjectFolder(boolean value) {
118: this .calculatePF = value;
119: }
120:
121: private void dataChanged() {
122: this .firer.fireChangeEvent();
123: }
124:
125: void read(WizardDescriptor settings) {
126: this .wizardDescriptor = settings;
127: String projectName = null;
128: File projectLocation = (File) settings.getProperty("projdir"); //NOI18N
129: if (projectLocation == null) {
130: projectLocation = ProjectChooser.getProjectsFolder();
131: int index = FoldersListSettings.getDefault()
132: .getNewProjectCount();
133: String formater = NbBundle
134: .getMessage(PanelProjectLocationExtSrc.class,
135: "TXT_JavaProject");
136: File file;
137: do {
138: index++;
139: projectName = MessageFormat.format(formater, index);
140: file = new File(projectLocation, projectName);
141: } while (file.exists());
142: settings
143: .putProperty(
144: NewRubyProjectWizardIterator.PROP_NAME_INDEX,
145: index);
146: this .projectLocation.setText(projectLocation
147: .getAbsolutePath());
148: this .setCalculateProjectFolder(true);
149: } else {
150: projectName = (String) settings.getProperty("name"); //NOI18N
151: boolean tmpFlag = this .calculatePF;
152: this .projectLocation.setText(projectLocation
153: .getAbsolutePath());
154: this .setCalculateProjectFolder(tmpFlag);
155: }
156: this .projectName.setText(projectName);
157: this .projectName.selectAll();
158: }
159:
160: void store(WizardDescriptor settings) {
161: settings.putProperty("name", this .projectName.getText()); // NOI18N
162: File projectsDir = new File(this .projectLocation.getText());
163: settings.putProperty("projdir", projectsDir); // NOI18N
164: }
165:
166: boolean valid(WizardDescriptor settings) {
167: String result = checkValidity(this .projectName.getText(),
168: this .projectLocation.getText());
169: if (result == null) {
170: wizardDescriptor
171: .putProperty("WizardPanel_errorMessage", ""); //NOI18N
172:
173: // 103648: make sure users don't accidentally create Ruby projects from Rails sources
174: // Like ZenTest, check for "config/environment.rb" to see if this looks like it
175: // might be a Rails project
176: File environment = new File(this .projectLocation.getText(),
177: "config" + File.separator + "environment.rb");
178: if (environment.exists()) {
179: String message = NbBundle.getMessage(
180: PanelProjectLocationExtSrc.class,
181: "ProbablyRails");
182: wizardDescriptor.putProperty(
183: "WizardPanel_errorMessage", message); //NOI18N
184: }
185: return true;
186: } else {
187: wizardDescriptor.putProperty("WizardPanel_errorMessage",
188: result); //NOI18N
189: return false;
190: }
191: }
192:
193: static String checkValidity(final String projectName,
194: final String projectLocation) {
195: if (projectName.length() == 0 || projectName.indexOf('/') > 0 //NOI18N
196: || projectName.indexOf('\\') > 0 //NOI18N
197: || projectName.indexOf(':') > 0) { //NOI18N
198: // Display name not specified
199: return NbBundle.getMessage(
200: PanelProjectLocationExtSrc.class,
201: "MSG_IllegalProjectName");
202: }
203:
204: File projLoc = new File(projectLocation).getAbsoluteFile();
205:
206: if (PanelProjectLocationVisual.getCanonicalFile(projLoc) == null) {
207: return NbBundle.getMessage(
208: PanelProjectLocationExtSrc.class,
209: "MSG_IllegalProjectLocation");
210: }
211:
212: while (projLoc != null && !projLoc.exists()) {
213: projLoc = projLoc.getParentFile();
214: }
215: if (projLoc == null || !projLoc.canWrite()) {
216: return NbBundle.getMessage(
217: PanelProjectLocationExtSrc.class,
218: "MSG_ProjectFolderReadOnly");
219: }
220:
221: File destFolder = FileUtil.normalizeFile(new File(
222: projectLocation));
223: File[] kids = destFolder.listFiles();
224: if (destFolder.exists() && kids != null && kids.length > 0) {
225: String file = null;
226: for (int i = 0; i < kids.length; i++) {
227: String childName = kids[i].getName();
228: if ("nbproject".equals(childName)) { //NOI18N
229: file = NbBundle.getMessage(
230: PanelProjectLocationExtSrc.class,
231: "TXT_NetBeansProject");
232: }
233: if (file != null) {
234: String format = NbBundle.getMessage(
235: PanelProjectLocationExtSrc.class,
236: "MSG_ProjectFolderInvalid");
237: return MessageFormat.format(format,
238: new Object[] { file });
239: }
240: }
241: }
242:
243: // #47611: if there is a live project still residing here, forbid project creation.
244: if (destFolder.isDirectory()) {
245: FileObject destFO = FileUtil.toFileObject(destFolder);
246: assert destFO != null : "No FileObject for " + destFolder;
247: boolean clear = false;
248: try {
249: clear = ProjectManager.getDefault().findProject(destFO) == null;
250: } catch (IOException e) {
251: // need not report here; clear remains false -> error
252: }
253: if (!clear) {
254: return NbBundle.getMessage(
255: PanelProjectLocationExtSrc.class,
256: "MSG_ProjectFolderHasDeletedProject");
257: }
258: }
259: return null;
260: }
261:
262: void validate(WizardDescriptor settings)
263: throws WizardValidationException {
264: }
265:
266: /** This method is called from within the constructor to
267: * initialize the form.
268: * WARNING: Do NOT modify this code. The content of this method is
269: * always regenerated by the Form Editor.
270: */
271: // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
272: private void initComponents() {
273: java.awt.GridBagConstraints gridBagConstraints;
274:
275: projectInfoPanel = new javax.swing.JPanel();
276: description = new javax.swing.JLabel();
277: projectNameLabel = new javax.swing.JLabel();
278: projectName = new javax.swing.JTextField();
279: projectLocationLabel = new javax.swing.JLabel();
280: projectLocation = new javax.swing.JTextField();
281: browseButton = new javax.swing.JButton();
282:
283: setLayout(new java.awt.GridBagLayout());
284:
285: projectInfoPanel.setLayout(new java.awt.GridBagLayout());
286:
287: description.setLabelFor(projectInfoPanel);
288: org.openide.awt.Mnemonics.setLocalizedText(description,
289: org.openide.util.NbBundle.getMessage(
290: PanelProjectLocationExtSrc.class,
291: "LBL_ProjectNameAndLocationLabel")); // NOI18N
292: gridBagConstraints = new java.awt.GridBagConstraints();
293: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
294: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
295: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
296: gridBagConstraints.weightx = 1.0;
297: projectInfoPanel.add(description, gridBagConstraints);
298: description.getAccessibleContext().setAccessibleName(
299: org.openide.util.NbBundle.getMessage(
300: PanelProjectLocationExtSrc.class,
301: "ACSN_jLabel4")); // NOI18N
302: description.getAccessibleContext().setAccessibleDescription(
303: org.openide.util.NbBundle.getMessage(
304: PanelProjectLocationExtSrc.class,
305: "ACSD_jLabel4")); // NOI18N
306:
307: projectNameLabel.setLabelFor(projectName);
308: org.openide.awt.Mnemonics.setLocalizedText(projectNameLabel,
309: org.openide.util.NbBundle.getMessage(
310: PanelProjectLocationExtSrc.class,
311: "LBL_NWP1_ProjectName_Label")); // NOI18N
312: gridBagConstraints = new java.awt.GridBagConstraints();
313: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
314: gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 0);
315: projectInfoPanel.add(projectNameLabel, gridBagConstraints);
316: projectNameLabel.getAccessibleContext().setAccessibleName(
317: org.openide.util.NbBundle.getMessage(
318: PanelProjectLocationExtSrc.class,
319: "ACSN_projectNameLabel")); // NOI18N
320: projectNameLabel.getAccessibleContext()
321: .setAccessibleDescription(
322: org.openide.util.NbBundle.getMessage(
323: PanelProjectLocationExtSrc.class,
324: "ACSD_projectNameLabel")); // NOI18N
325:
326: gridBagConstraints = new java.awt.GridBagConstraints();
327: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
328: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
329: gridBagConstraints.weightx = 1.0;
330: gridBagConstraints.insets = new java.awt.Insets(12, 6, 0, 0);
331: projectInfoPanel.add(projectName, gridBagConstraints);
332:
333: projectLocationLabel.setLabelFor(projectLocation);
334: org.openide.awt.Mnemonics
335: .setLocalizedText(projectLocationLabel,
336: org.openide.util.NbBundle.getMessage(
337: PanelProjectLocationExtSrc.class,
338: "LBL_NWP1_CreatedProjectFolder_Lablel")); // NOI18N
339: gridBagConstraints = new java.awt.GridBagConstraints();
340: gridBagConstraints.gridx = 0;
341: gridBagConstraints.gridy = 2;
342: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
343: gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 0);
344: projectInfoPanel.add(projectLocationLabel, gridBagConstraints);
345: projectLocationLabel.getAccessibleContext().setAccessibleName(
346: org.openide.util.NbBundle.getMessage(
347: PanelProjectLocationExtSrc.class,
348: "ACSN_projectLocationLabel")); // NOI18N
349: projectLocationLabel.getAccessibleContext()
350: .setAccessibleDescription(
351: org.openide.util.NbBundle.getMessage(
352: PanelProjectLocationExtSrc.class,
353: "ACSD_projectLocationLabel")); // NOI18N
354:
355: gridBagConstraints = new java.awt.GridBagConstraints();
356: gridBagConstraints.gridy = 2;
357: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
358: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
359: gridBagConstraints.weightx = 1.0;
360: gridBagConstraints.insets = new java.awt.Insets(12, 6, 0, 0);
361: projectInfoPanel.add(projectLocation, gridBagConstraints);
362:
363: org.openide.awt.Mnemonics.setLocalizedText(browseButton,
364: org.openide.util.NbBundle.getMessage(
365: PanelProjectLocationExtSrc.class,
366: "LBL_NWP1_BrowseLocation_Button3")); // NOI18N
367: browseButton
368: .addActionListener(new java.awt.event.ActionListener() {
369: public void actionPerformed(
370: java.awt.event.ActionEvent evt) {
371: browseProjectLocation(evt);
372: }
373: });
374: gridBagConstraints = new java.awt.GridBagConstraints();
375: gridBagConstraints.gridy = 2;
376: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
377: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
378: gridBagConstraints.insets = new java.awt.Insets(12, 6, 0, 0);
379: projectInfoPanel.add(browseButton, gridBagConstraints);
380: browseButton.getAccessibleContext().setAccessibleName(
381: org.openide.util.NbBundle.getMessage(
382: PanelProjectLocationExtSrc.class,
383: "ACSN_browseButton")); // NOI18N
384: browseButton.getAccessibleContext().setAccessibleDescription(
385: org.openide.util.NbBundle.getMessage(
386: PanelProjectLocationExtSrc.class,
387: "ACSD_browseButton")); // NOI18N
388:
389: gridBagConstraints = new java.awt.GridBagConstraints();
390: gridBagConstraints.gridx = 0;
391: gridBagConstraints.gridy = 0;
392: gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
393: gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
394: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
395: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
396: gridBagConstraints.weightx = 1.0;
397: gridBagConstraints.weighty = 1.0;
398: add(projectInfoPanel, gridBagConstraints);
399:
400: getAccessibleContext().setAccessibleName(
401: org.openide.util.NbBundle.getMessage(
402: PanelProjectLocationExtSrc.class,
403: "ACSN_PanelSourceFolders")); // NOI18N
404: getAccessibleContext().setAccessibleDescription(
405: org.openide.util.NbBundle.getMessage(
406: PanelProjectLocationExtSrc.class,
407: "ACSD_PanelSourceFolders")); // NOI18N
408: }// </editor-fold>//GEN-END:initComponents
409:
410: private void browseProjectLocation(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseProjectLocation
411: // TODO add your handling code here:
412: JFileChooser chooser = new JFileChooser();
413: FileUtil.preventFileChooserSymlinkTraversal(chooser, null);
414: chooser.setDialogTitle(NbBundle.getMessage(
415: PanelProjectLocationExtSrc.class,
416: "LBL_NWP1_SelectProjectLocation"));
417: chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
418: String path = this .projectLocation.getText();
419: if (path.length() > 0) {
420: File f = new File(path);
421: if (f.exists()) {
422: chooser.setSelectedFile(f);
423: }
424: }
425: if (chooser.showOpenDialog(this ) == JFileChooser.APPROVE_OPTION) {
426: File file = chooser.getSelectedFile();
427: if (file != null) {
428: this .projectLocation.setText(FileUtil.normalizeFile(
429: file).getAbsolutePath());
430: }
431: }
432: }//GEN-LAST:event_browseProjectLocation
433:
434: // Variables declaration - do not modify//GEN-BEGIN:variables
435: private javax.swing.JButton browseButton;
436: private javax.swing.JLabel description;
437: private javax.swing.JPanel projectInfoPanel;
438: private javax.swing.JTextField projectLocation;
439: private javax.swing.JLabel projectLocationLabel;
440: private javax.swing.JTextField projectName;
441: private javax.swing.JLabel projectNameLabel;
442: // End of variables declaration//GEN-END:variables
443:
444: }
|