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.cnd.editor.filecreation;
043:
044: import java.awt.Component;
045: import java.io.File;
046: import java.io.IOException;
047: import java.lang.String;
048: import javax.swing.event.ChangeEvent;
049: import javax.swing.event.ChangeListener;
050: import org.netbeans.api.project.Project;
051: import org.netbeans.api.project.SourceGroup;
052: import org.netbeans.spi.project.ui.templates.support.Templates;
053: import org.openide.ErrorManager;
054: import org.openide.WizardDescriptor;
055: import org.openide.filesystems.FileObject;
056: import org.openide.filesystems.FileUtil;
057: import org.openide.util.ChangeSupport;
058: import org.openide.util.HelpCtx;
059: import org.openide.util.NbBundle;
060:
061: /**
062: * SimpleTargetChooserPanel extended with extension selector and logic
063: *
064: */
065: final class NewCndFileChooserPanel implements
066: WizardDescriptor.Panel<WizardDescriptor>, ChangeListener {
067:
068: private final ChangeSupport changeSupport = new ChangeSupport(this );
069: private NewCndFileChooserPanelGUI gui;
070:
071: private final Project project;
072: private final SourceGroup[] folders;
073: private final WizardDescriptor.Panel<WizardDescriptor> bottomPanel;
074: private WizardDescriptor wizard;
075: private final ExtensionsSettings es;
076:
077: NewCndFileChooserPanel(Project project, SourceGroup[] folders,
078: WizardDescriptor.Panel<WizardDescriptor> bottomPanel,
079: ExtensionsSettings es) {
080: this .es = es;
081: this .folders = folders;
082: this .project = project;
083: this .bottomPanel = bottomPanel;
084: if (bottomPanel != null) {
085: bottomPanel.addChangeListener(this );
086: }
087: this .gui = null;
088: }
089:
090: public Component getComponent() {
091: if (gui == null) {
092: gui = new NewCndFileChooserPanelGUI(project, folders,
093: bottomPanel == null ? null : bottomPanel
094: .getComponent(), es);
095: gui.addChangeListener(this );
096: }
097: return gui;
098: }
099:
100: public HelpCtx getHelp() {
101: if (bottomPanel != null) {
102: HelpCtx bottomHelp = bottomPanel.getHelp();
103: if (bottomHelp != null) {
104: return bottomHelp;
105: }
106: }
107:
108: //XXX
109: return null;
110: }
111:
112: public boolean isValid() {
113: boolean ok = (gui != null && gui.getTargetName() != null
114: && (bottomPanel == null || bottomPanel.isValid()) && gui
115: .getTargetExtension().length() > 0);
116:
117: if (!ok) {
118: wizard.putProperty("WizardPanel_errorMessage", ""); // NOI18N
119: return false;
120: }
121:
122: // check if the file name can be created
123: String errorMessage = canUseFileName(gui.getTargetGroup()
124: .getRootFolder(), gui.getTargetFolder(), gui
125: .getTargetName(), false);
126: wizard.putProperty("WizardPanel_errorMessage", errorMessage); // NOI18N
127:
128: if (!es.isKnownExtension(gui.getTargetExtension())) {
129: //MSG_new_extension_introduced
130: String msg = NbBundle.getMessage(
131: NewCndFileChooserPanel.class,
132: "MSG_new_extension_introduced", gui
133: .getTargetExtension()); // NOI18N
134: wizard.putProperty("WizardPanel_errorMessage", msg); // NOI18N
135: }
136:
137: return errorMessage == null;
138: }
139:
140: public void addChangeListener(ChangeListener l) {
141: changeSupport.addChangeListener(l);
142: }
143:
144: public void removeChangeListener(ChangeListener l) {
145: changeSupport.removeChangeListener(l);
146: }
147:
148: public void readSettings(WizardDescriptor settings) {
149:
150: wizard = settings;
151:
152: if (gui == null) {
153: getComponent();
154: }
155:
156: // Try to preselect a folder
157: FileObject preselectedTarget = Templates
158: .getTargetFolder(wizard);
159: // Try to preserve the already entered target name
160: String targetName = Templates.getTargetName(wizard);
161: // Init values
162: gui.initValues(Templates.getTemplate(wizard),
163: preselectedTarget, targetName);
164:
165: // XXX hack, TemplateWizard in final setTemplateImpl() forces new wizard's title
166: // this name is used in NewFileWizard to modify the title
167: Object substitute = gui
168: .getClientProperty("NewFileWizard_Title"); // NOI18N
169: if (substitute != null) {
170: wizard.putProperty("NewFileWizard_Title", substitute); // NOI18N
171: }
172:
173: wizard
174: .putProperty(
175: "WizardPanel_contentData",
176: new String[] { // NOI18N
177: NbBundle
178: .getBundle(
179: NewCndFileChooserPanel.class)
180: .getString(
181: "LBL_TemplatesPanel_Name"), // NOI18N
182: NbBundle
183: .getBundle(
184: NewCndFileChooserPanel.class)
185: .getString(
186: "LBL_SimpleTargetChooserPanel_Name") }); // NOI18N
187:
188: if (bottomPanel != null) {
189: bottomPanel.readSettings(settings);
190: }
191: }
192:
193: public void storeSettings(WizardDescriptor settings) {
194: if (WizardDescriptor.PREVIOUS_OPTION
195: .equals(settings.getValue())) {
196: return;
197: }
198: if (!settings.getValue().equals(WizardDescriptor.CANCEL_OPTION)
199: && isValid()) {
200: if (bottomPanel != null) {
201: bottomPanel.storeSettings(settings);
202: }
203:
204: String name = gui.getTargetName();
205: if (name.indexOf('/') > 0) { // NOI18N
206: name = name.substring(name.lastIndexOf('/') + 1);
207: }
208:
209: FileObject fo = getTargetFolderFromGUI();
210: try {
211: Templates.setTargetFolder(settings, fo);
212: } catch (IllegalArgumentException iae) {
213: ErrorManager.getDefault()
214: .annotate(
215: iae,
216: ErrorManager.EXCEPTION,
217: null,
218: NbBundle.getMessage(
219: NewCndFileChooserPanel.class,
220: "MSG_Cannot_Create_Folder", gui
221: .getTargetFolder()),
222: null, null);
223: throw iae;
224: }
225: Templates.setTargetName(settings, name);
226: es.setDefaultExtension(gui.getTargetExtension());
227: }
228: settings.putProperty("NewFileWizard_Title", null); // NOI18N
229: }
230:
231: public void stateChanged(ChangeEvent e) {
232: changeSupport.fireChange();
233: }
234:
235: private FileObject getTargetFolderFromGUI() {
236: FileObject rootFolder = gui.getTargetGroup().getRootFolder();
237: String folderName = gui.getTargetFolder();
238: String newObject = gui.getTargetName();
239:
240: if (newObject.indexOf('/') > 0) { // NOI18N
241: String path = newObject.substring(0, newObject
242: .lastIndexOf('/')); // NOI18N
243: folderName = folderName == null || "".equals(folderName) ? path
244: : folderName + '/' + path; // NOI18N
245: }
246:
247: FileObject targetFolder;
248: if (folderName == null) {
249: targetFolder = rootFolder;
250: } else {
251: targetFolder = rootFolder.getFileObject(folderName);
252: }
253:
254: if (targetFolder == null) {
255: // XXX add deletion of the file in uninitalize of the wizard
256: try {
257: targetFolder = FileUtil.createFolder(rootFolder,
258: folderName);
259: } catch (IOException ioe) {
260: // XXX
261: // Can't create the folder
262: }
263: }
264:
265: return targetFolder;
266: }
267:
268: // helper methods copied from project/ui/ProjectUtilities
269: /** Checks if the given file name can be created in the target folder.
270: *
271: * @param targetFolder target folder (e.g. source group)
272: * @param folderName name of the folder relative to target folder
273: * @param newObjectName name of created file
274: * @param extension extension of created file
275: * @return localized error message or null if all right
276: */
277: final public static String canUseFileName(FileObject targetFolder,
278: String folderName, String newObjectName,
279: boolean allowFileSeparator) {
280: String relFileName = folderName + "/" + newObjectName; // NOI18N
281:
282: boolean allowSlash = false;
283: boolean allowBackslash = false;
284: int errorVariant = 0;
285:
286: if (allowFileSeparator) {
287: if (File.separatorChar == '\\') {
288: errorVariant = 3;
289: allowSlash = allowBackslash = true;
290: } else {
291: errorVariant = 1;
292: allowSlash = true;
293: }
294: }
295:
296: if ((!allowSlash && newObjectName.indexOf('/') != -1)
297: || (!allowBackslash && newObjectName.indexOf('\\') != -1)) {
298: //if errorVariant == 3, the test above should never be true:
299: assert errorVariant == 0 || errorVariant == 1 : "Invalid error variant: "
300: + errorVariant;
301:
302: return NbBundle.getMessage(NewCndFileChooserPanel.class,
303: "MSG_not_valid_filename", newObjectName,
304: new Integer(errorVariant));
305: }
306:
307: // test whether the selected folder on selected filesystem already exists
308: if (targetFolder == null) {
309: return NbBundle.getMessage(NewCndFileChooserPanel.class,
310: "MSG_fs_or_folder_does_not_exist"); // NOI18N
311: }
312:
313: // target filesystem should be writable
314: if (!targetFolder.canWrite()) {
315: return NbBundle.getMessage(NewCndFileChooserPanel.class,
316: "MSG_fs_is_readonly"); // NOI18N
317: }
318:
319: if (existFileName(targetFolder, relFileName)) {
320: return NbBundle.getMessage(NewCndFileChooserPanel.class,
321: "MSG_file_already_exist", newObjectName); // NOI18N
322: }
323:
324: // all ok
325: return null;
326: }
327:
328: private static boolean existFileName(FileObject targetFolder,
329: String relFileName) {
330: boolean result = false;
331: File fileForTargetFolder = FileUtil.toFile(targetFolder);
332: if (fileForTargetFolder.exists()) {
333: result = new File(fileForTargetFolder, relFileName)
334: .exists();
335: } else {
336: result = targetFolder.getFileObject(relFileName) != null;
337: }
338:
339: return result;
340: }
341: }
|