diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index 8946a75c053..227742d87bb 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,11 @@ +2004-08-18 Chris Wiebe + + added source/header file selection dialog + * src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCreationWizardPage.java + * src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java + * src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCreationWizardMessages.properties + * src/org/eclipse/cdt/internal/ui/wizards/classwizard/SourceFileSelectionDialog.java + 2004-08-16 Chris Wiebe better handling of source folders in class wizard diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java index 7ab30487c82..35ae153c3af 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCodeGenerator.java @@ -156,13 +156,25 @@ public class NewClassCodeGenerator { //TODO should use code templates StringBuffer text = new StringBuffer(); - int insertionPos = -1; + int appendFirstCharPos = -1; if (oldContents != null) { - insertionPos = getInsertionPos(oldContents); - if (insertionPos == -1) + int insertionPos = getInsertionPos(oldContents); + if (insertionPos == -1) { text.append(oldContents); - else - text.append(oldContents.substring(0, insertionPos)); + } else { + // skip over whitespace + int prependLastCharPos = insertionPos - 1; + while (prependLastCharPos >= 0 && Character.isWhitespace(oldContents.charAt(prependLastCharPos))) { + --prependLastCharPos; + } + if (prependLastCharPos >= 0) { + text.append(oldContents.substring(0, prependLastCharPos + 1)); + } + appendFirstCharPos = prependLastCharPos + 1; + } + text.append(fLineDelimiter); + + // insert a blank line before class definition text.append(fLineDelimiter); } @@ -202,9 +214,18 @@ public class NewClassCodeGenerator { endNamespace(text); } - if (oldContents != null && insertionPos != -1) { + if (oldContents != null && appendFirstCharPos != -1) { + // insert a blank line after class definition text.append(fLineDelimiter); - text.append(oldContents.substring(insertionPos)); + + // skip over any extra whitespace + int len = oldContents.length(); + while (appendFirstCharPos < len && Character.isWhitespace(oldContents.charAt(appendFirstCharPos))) { + ++appendFirstCharPos; + } + if (appendFirstCharPos < len) { + text.append(oldContents.substring(appendFirstCharPos)); + } } return text.toString(); @@ -440,7 +461,7 @@ public class NewClassCodeGenerator { } } - private IPath makeRelativePathToProjectIncludes(IPath fullPath, IProject project) { + public static IPath makeRelativePathToProjectIncludes(IPath fullPath, IProject project) { IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project); if (provider != null) { IScannerInfo info = provider.getScannerInformation(project); @@ -465,7 +486,7 @@ public class NewClassCodeGenerator { return null; } - private IPath makeRelativePath(IPath path, IPath relativeTo) { + public static IPath makeRelativePath(IPath path, IPath relativeTo) { int segments = relativeTo.matchingFirstSegments(path); if (segments > 0) { IPath prefix = relativeTo.removeFirstSegments(segments).removeLastSegments(1); @@ -479,7 +500,7 @@ public class NewClassCodeGenerator { return null; } - private String getIncludeString(String fileName, boolean isSystemInclude) { + private static String getIncludeString(String fileName, boolean isSystemInclude) { StringBuffer buf = new StringBuffer(); buf.append("#include "); //$NON-NLS-1$ if (isSystemInclude) diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCreationWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCreationWizardPage.java index 76c20a8f608..a3ca600da32 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCreationWizardPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCreationWizardPage.java @@ -184,14 +184,14 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { HeaderFileFieldAdapter headerFileAdapter = new HeaderFileFieldAdapter(); fHeaderFileDialogField = new StringButtonDialogField(headerFileAdapter); fHeaderFileDialogField.setDialogFieldListener(headerFileAdapter); - fHeaderFileDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.classDefinition.label")); //$NON-NLS-1$ - fHeaderFileDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.classDefinition.button")); //$NON-NLS-1$ + fHeaderFileDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.headerFile.label")); //$NON-NLS-1$ + fHeaderFileDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.headerFile.button")); //$NON-NLS-1$ SourceFileFieldAdapter sourceFileAdapter = new SourceFileFieldAdapter(); fSourceFileDialogField = new StringButtonDialogField(sourceFileAdapter); fSourceFileDialogField.setDialogFieldListener(sourceFileAdapter); - fSourceFileDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.classImplementation.label")); //$NON-NLS-1$ - fSourceFileDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.classImplementation.button")); //$NON-NLS-1$ + fSourceFileDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.sourceFile.label")); //$NON-NLS-1$ + fSourceFileDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.sourceFile.button")); //$NON-NLS-1$ fSourceFolderStatus = new StatusInfo(); fNamespaceStatus = new StatusInfo(); @@ -583,7 +583,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { private class SourceFolderFieldAdapter implements IStringButtonAdapter, IDialogFieldListener { public void changeControlPressed(DialogField field) { // take the current cproject as init element of the dialog - ICContainer folder = chooseSourceFolder(fCurrentSourceFolder); + ICElement folder = chooseSourceFolder(fCurrentSourceFolder); if (folder != null) { setSourceFolder(folder, true); prepareTypeCache(); @@ -593,6 +593,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { public void dialogFieldChanged(DialogField field) { fSourceFolderStatus = sourceFolderChanged(); // tell all others + updateEnableState(); handleFieldChanged(SOURCE_FOLDER); } } @@ -674,6 +675,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { } fClassNameStatus = classNameChanged(); // tell all others + updateEnableState(); handleFieldChanged(CLASSNAME); } } @@ -682,9 +684,10 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { public void customButtonPressed(ListDialogField field, int index) { if (index == 0) { chooseBaseClasses(); - fBaseClassesStatus = baseClassesChanged(); - handleFieldChanged(BASECLASSES); } + fBaseClassesStatus = baseClassesChanged(); + updateEnableState(); + handleFieldChanged(BASECLASSES); } public void selectionChanged(ListDialogField field) { @@ -708,32 +711,32 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { private class HeaderFileFieldAdapter implements IStringButtonAdapter, IDialogFieldListener { public void changeControlPressed(DialogField field) { - // take the current cproject as init element of the dialog - ITranslationUnit headerFile = chooseHeaderFile(fCurrentSourceFolder); - if (headerFile != null) { - setHeaderFile(headerFile.getPath(), true); + IPath filePath = chooseSourceFile(getHeaderFilePath(), NewClassWizardMessages.getString("NewClassCreationWizardPage.ChooseHeaderFileDialog.title")); //$NON-NLS-1$ + if (filePath != null) { + setHeaderFile(filePath, true); } } public void dialogFieldChanged(DialogField field) { fHeaderFileStatus = headerFileChanged(); // tell all others + updateEnableState(); handleFieldChanged(HEADERFILE); } } private class SourceFileFieldAdapter implements IStringButtonAdapter, IDialogFieldListener { public void changeControlPressed(DialogField field) { - // take the current cproject as init element of the dialog - ITranslationUnit sourceFile = chooseSourceFile(fCurrentSourceFolder); - if (sourceFile != null) { - setSourceFile(sourceFile.getPath(), true); + IPath filePath = chooseSourceFile(getSourceFilePath(), NewClassWizardMessages.getString("NewClassCreationWizardPage.ChooseSourceFileDialog.title")); //$NON-NLS-1$ + if (filePath != null) { + setSourceFile(filePath, true); } } public void dialogFieldChanged(DialogField field) { fSourceFileStatus = sourceFileChanged(); // tell all others + updateEnableState(); handleFieldChanged(SOURCEFILE); } } @@ -767,7 +770,6 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.NotAFolder", str)); //$NON-NLS-1$ return status; } - ICProject cproject = CoreModel.getDefault().create(proj); ICElement e = CoreModel.getDefault().create(res.getFullPath()); fCurrentSourceFolder = CModelUtil.getSourceFolder(e); if (fCurrentSourceFolder == null) { @@ -787,7 +789,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { return status; } } else { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.SourceFolderDoesNotExist", str)); //$NON-NLS-1$ + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.FolderDoesNotExist", str)); //$NON-NLS-1$ return status; } return status; @@ -914,6 +916,11 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnclosingClassNotExistsInProject")); //$NON-NLS-1$ return status; } +// ITypeReference ref = fCurrentEnclosingClass.getResolvedReference(); +// if (ref == null || enclosingProject.getFullPath().isPrefixOf(ref.getPath())) { +// status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnclosingClassNotExistsInProject")); //$NON-NLS-1$ +// return status; +// } } } return status; @@ -1091,7 +1098,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { // return status; // } // } else { -// status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.SourceFolderDoesNotExist", str)); //$NON-NLS-1$ +// status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.FolderDoesNotExist", str)); //$NON-NLS-1$ // return status; // } return status; @@ -1147,7 +1154,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { // return status; // } // } else { -// status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.SourceFolderDoesNotExist", str)); //$NON-NLS-1$ +// status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.FolderDoesNotExist", str)); //$NON-NLS-1$ // return status; // } return status; @@ -1265,6 +1272,19 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { return fHeaderFileDialogField.getText(); } + public IPath getHeaderFilePath() { + String name = getHeaderFileName(); + if (name.length() > 0) { + IPath headerPath = new Path(name); + if (headerPath.isAbsolute()) { + return headerPath; + } else if (fCurrentSourceFolder != null) { + return fCurrentSourceFolder.getPath().append(headerPath); + } + } + return null; + } + /** * Returns the type name entered into the type input field. * @@ -1274,6 +1294,19 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { return fSourceFileDialogField.getText(); } + public IPath getSourceFilePath() { + String name = getSourceFileName(); + if (name.length() > 0) { + IPath headerPath = new Path(name); + if (headerPath.isAbsolute()) { + return headerPath; + } else if (fCurrentSourceFolder != null) { + return fCurrentSourceFolder.getPath().append(headerPath); + } + } + return null; + } + public IProject getCurrentProject() { if (fCurrentSourceFolder != null) { return fCurrentSourceFolder.getCProject().getProject(); @@ -1406,8 +1439,12 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @param canBeModified if false the source folder field can * not be changed by the user. If true the field is editable */ - public void setSourceFolder(ICContainer folder, boolean canBeModified) { - fCurrentSourceFolder = folder; + public void setSourceFolder(ICElement folder, boolean canBeModified) { + if (folder instanceof ICContainer) { + fCurrentSourceFolder = (ICContainer)folder; + } else { + fCurrentSourceFolder = null; + } String str = (folder == null) ? "" : folder.getPath().makeRelative().toString(); //$NON-NLS-1$ fSourceFolderDialogField.setText(str); fSourceFolderDialogField.setEnabled(canBeModified); @@ -1474,9 +1511,12 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * not be changed by the user. If true the field is editable */ public void setHeaderFile(IPath headerPath, boolean canBeModified) { - fCurrentHeaderFile = headerPath; - if (fCurrentSourceFolder != null && fCurrentSourceFolder.getPath().isPrefixOf(headerPath)) { - headerPath = headerPath.removeFirstSegments(fCurrentSourceFolder.getPath().segmentCount()); + fCurrentHeaderFile = headerPath; + if (fCurrentSourceFolder != null) { + IPath sourcePath = fCurrentSourceFolder.getPath(); + IPath relPath = NewClassCodeGenerator.makeRelativePath(headerPath, sourcePath); + if (relPath != null) + headerPath = relPath; } String str = (headerPath == null) ? "" : headerPath.makeRelative().toString(); //$NON-NLS-1$ fHeaderFileDialogField.setText(str); @@ -1504,12 +1544,18 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * Updates the enable state of buttons related to the enclosing class selection checkbox. */ void updateEnableState() { + IProject project = getCurrentProject(); + boolean validProject = (project != null); + fBaseClassesDialogField.setEnabled(validProject); + fHeaderFileDialogField.setEnabled(validProject); + fSourceFileDialogField.setEnabled(validProject); + boolean enclosing = isEnclosingClassSelected(); - fNamespaceDialogField.setEnabled(fCanModifyNamespace && !enclosing); - fEnclosingClassDialogField.setEnabled(fCanModifyEnclosingClass && enclosing); + fNamespaceDialogField.setEnabled(validProject && fCanModifyNamespace && !enclosing); + fEnclosingClassDialogField.setEnabled(validProject && fCanModifyEnclosingClass && enclosing); } - ICContainer chooseSourceFolder(ICElement initElement) { + ICElement chooseSourceFolder(ICElement initElement) { Class[] acceptedClasses = new Class[] { ICContainer.class, ICProject.class }; TypedElementSelectionValidator validator = new TypedElementSelectionValidator(acceptedClasses, false) { public boolean isSelectedValid(Object element) { @@ -1546,14 +1592,17 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { dialog.setInitialSelection(initElement); if (dialog.open() == Window.OK) { - Object element = dialog.getFirstResult(); - if (element instanceof ICProject) { - ICProject cproject = (ICProject)element; - return cproject.findSourceRoot(cproject.getProject()); - } else if (element instanceof ICContainer) { - return (ICContainer)element; + Object result = dialog.getFirstResult(); + if (result instanceof ICElement) { + ICElement element = (ICElement)result; + if (element instanceof ICProject) { + ICProject cproject = (ICProject)element; + ISourceRoot folder = cproject.findSourceRoot(cproject.getProject()); + if (folder != null) + return folder; + } + return element; } - return null; } return null; } @@ -1705,32 +1754,8 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { } } - ITranslationUnit chooseHeaderFile(ICElement initElement) { - Class[] acceptedClasses = new Class[] { ITranslationUnit.class, ICContainer.class, ICProject.class }; - TypedElementSelectionValidator validator = new TypedElementSelectionValidator(acceptedClasses, false) { - public boolean isSelectedValid(Object element) { - return isValidHeaderFile(element); - } - }; - - acceptedClasses = new Class[] { ICModel.class, ICContainer.class, ICProject.class, ITranslationUnit.class }; - ViewerFilter filter = new TypedViewerFilter(acceptedClasses) { - public boolean select(Viewer viewer, Object parent, Object element) { - if (isValidHeaderFile(element)) { - return true; - } - return super.select(viewer, parent, element); - } - }; - - CElementContentProvider provider = new CElementContentProvider(); - ILabelProvider labelProvider = new CElementLabelProvider(CElementLabelProvider.SHOW_DEFAULT); - ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), labelProvider, provider); - dialog.setValidator(validator); - dialog.setSorter(new CElementSorter()); - dialog.setTitle(NewClassWizardMessages.getString("NewClassCreationWizardPage.ChooseHeaderFileDialog.title")); //$NON-NLS-1$ - dialog.setMessage(NewClassWizardMessages.getString("NewClassCreationWizardPage.ChooseHeaderFileDialog.description")); //$NON-NLS-1$ - dialog.addFilter(filter); + IPath chooseSourceFile(IPath filePath, String title) { + SourceFileSelectionDialog dialog = new SourceFileSelectionDialog(getShell()); ICElement input = CoreModel.create(fWorkspaceRoot); if (fCurrentSourceFolder != null) { ICProject cproject = fCurrentSourceFolder.getCProject(); @@ -1738,63 +1763,19 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { input = cproject; } dialog.setInput(input); - dialog.setInitialSelection(initElement); - + if (filePath != null) { + dialog.setInitialFields(filePath.removeLastSegments(1).toString(), filePath.lastSegment()); + } else if (fCurrentSourceFolder != null) { + dialog.setInitialFields(fCurrentSourceFolder.getPath().toString(), null); + } + if (dialog.open() == Window.OK) { - Object element = dialog.getFirstResult(); - if (element instanceof ITranslationUnit) { - return (ITranslationUnit)element; - } - return null; + return dialog.getFilePath(); } return null; } - ITranslationUnit chooseSourceFile(ICElement initElement) { - Class[] acceptedClasses = new Class[] { ITranslationUnit.class, ICContainer.class, ICProject.class }; - TypedElementSelectionValidator validator = new TypedElementSelectionValidator(acceptedClasses, false) { - public boolean isSelectedValid(Object element) { - return isValidSourceFile(element); - } - }; - - acceptedClasses = new Class[] { ICModel.class, ICContainer.class, ICProject.class, ITranslationUnit.class }; - ViewerFilter filter = new TypedViewerFilter(acceptedClasses) { - public boolean select(Viewer viewer, Object parent, Object element) { - if (isValidSourceFile(element)) { - return true; - } - return super.select(viewer, parent, element); - } - }; - CElementContentProvider provider = new CElementContentProvider(); - ILabelProvider labelProvider = new CElementLabelProvider(CElementLabelProvider.SHOW_DEFAULT); - ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), labelProvider, provider); - dialog.setValidator(validator); - dialog.setSorter(new CElementSorter()); - dialog.setTitle(NewClassWizardMessages.getString("NewClassCreationWizardPage.ChooseSourceFileDialog.title")); //$NON-NLS-1$ - dialog.setMessage(NewClassWizardMessages.getString("NewClassCreationWizardPage.ChooseSourceFileDialog.description")); //$NON-NLS-1$ - dialog.addFilter(filter); - ICElement input = CoreModel.create(fWorkspaceRoot); - if (fCurrentSourceFolder != null) { - ICProject cproject = fCurrentSourceFolder.getCProject(); - if (cproject != null) - input = cproject; - } - dialog.setInput(input); - dialog.setInitialSelection(initElement); - - if (dialog.open() == Window.OK) { - Object element = dialog.getFirstResult(); - if (element instanceof ITranslationUnit) { - return (ITranslationUnit)element; - } - return null; - } - return null; - } - // ---- creation ---------------- /** @@ -1805,13 +1786,9 @@ public class NewClassCreationWizardPage extends NewElementWizardPage { * @throws InterruptedException Thrown when the operation was cancelled. */ public void createClass(IProgressMonitor monitor) throws CoreException, InterruptedException { - IPath containerPath = fCurrentSourceFolder.getPath(); - IPath headerPath = containerPath.append(getHeaderFileName()); - IPath sourcePath = containerPath.append(getSourceFileName()); - fCodeGenerator = new NewClassCodeGenerator( - headerPath, - sourcePath, + getHeaderFilePath(), + getSourceFilePath(), getClassName(), getNamespace(), getBaseClasses(), diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.properties index 93ce43251ff..adfe3776ebf 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.properties @@ -27,11 +27,11 @@ NewClassCreationWizardPage.getClasses.noclasses.message=No classes available. NewClassCreationWizardPage.sourceFolder.label=Source &Folder: NewClassCreationWizardPage.sourceFolder.button=Br&owse... NewClassCreationWizardPage.ChooseSourceFolderDialog.title=Folder Selection -NewClassCreationWizardPage.ChooseSourceFolderDialog.description=&Choose a folder: -NewClassCreationWizardPage.error.EnterSourceFolderName=Folder name is empty. -NewClassCreationWizardPage.error.SourceFolderDoesNotExist=Folder ''{0}'' does not exist. -NewClassCreationWizardPage.error.NotAFolder=''{0}'' must be a project or folder. -NewClassCreationWizardPage.error.NotASourceFolder=''{0}'' is not a source folder. +NewClassCreationWizardPage.ChooseSourceFolderDialog.description=&Choose a source folder: +NewClassCreationWizardPage.error.EnterSourceFolderName=Source folder name is empty. +NewClassCreationWizardPage.error.FolderDoesNotExist=Folder ''{0}'' does not exist. +NewClassCreationWizardPage.error.NotAFolder=''{0}'' is not a project or folder. +NewClassCreationWizardPage.error.NotASourceFolder=Folder ''{0}'' is not a valid source folder. NewClassCreationWizardPage.error.ProjectClosed=Project ''{0}'' must be accessible. NewClassCreationWizardPage.warning.NotACProject=Folder is not a C/C++ project. NewClassCreationWizardPage.warning.NotInACProject=Folder is not in a C/C++ project. @@ -68,15 +68,13 @@ NewClassCreationWizardPage.error.BaseClassNotExistsInProject=Base class ''{0}'' NewClassCreationWizardPage.methodStubs.label=Method &Stubs: -NewClassCreationWizardPage.classDefinition.label=Class &Definition: -NewClassCreationWizardPage.classDefinition.button=Br&owse... -NewClassCreationWizardPage.ChooseHeaderFileDialog.title=File Selection -NewClassCreationWizardPage.ChooseHeaderFileDialog.description=&Choose a header file: +NewClassCreationWizardPage.headerFile.label=Class &Definition: +NewClassCreationWizardPage.headerFile.button=Br&owse... +NewClassCreationWizardPage.ChooseHeaderFileDialog.title=Header File Selection -NewClassCreationWizardPage.classImplementation.button=Br&owse... -NewClassCreationWizardPage.classImplementation.label=Class &Implementation: -NewClassCreationWizardPage.ChooseSourceFileDialog.title=File Selection -NewClassCreationWizardPage.ChooseSourceFileDialog.description=&Choose a source file: +NewClassCreationWizardPage.sourceFile.button=Br&owse... +NewClassCreationWizardPage.sourceFile.label=Class &Implementation: +NewClassCreationWizardPage.ChooseSourceFileDialog.title=Source File Selection # -----------BaseClassesListDialogField ------------- BaseClassesListDialogField.buttons.add=&Add... @@ -126,6 +124,22 @@ NewBaseClassSelectionDialog.getClasses.exception.message=Unexpected exception. S NewBaseClassSelectionDialog.getClasses.noclasses.title=Class Selection NewBaseClassSelectionDialog.getClasses.noclasses.message=No classes available. +# ------- SourceFileSelectionDialog ----- +SourceFileSelectionDialog.folderName.label=Folder Name: +SourceFileSelectionDialog.fileName.label=File Name: +SourceFileSelectionDialog.message.emptyList=No items. +SourceFileSelectionDialog.error.EnterFolderName=Folder name is empty. +SourceFileSelectionDialog.error.FolderDoesNotExist=Folder ''{0}'' does not exist. +SourceFileSelectionDialog.error.NotAFolder=''{0}'' must be a project or folder. +SourceFileSelectionDialog.error.NotASourceFolder=Folder ''{0}'' is not a valid source folder. +SourceFileSelectionDialog.error.ProjectClosed=Project ''{0}'' must be accessible. +SourceFileSelectionDialog.warning.NotACProject=Folder is not a C/C++ project. +SourceFileSelectionDialog.warning.NotInACProject=Folder is not in a C/C++ project. +SourceFileSelectionDialog.error.EnterFileName=File name is empty. +SourceFileSelectionDialog.error.NotAFile=''{0}'' is not a source file. +SourceFileSelectionDialog.error.NotASourceFile=''{0}'' is not a valid source file. +SourceFileSelectionDialog.warning.SourceFileExists=New class contents will be appended to existing file ''{0}''. + # -----------NewClassCodeGeneration ------------- NewClassCodeGeneration.createType.task=Creating type.... NewClassCodeGeneration.createFile.task=Creating diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/SourceFileSelectionDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/SourceFileSelectionDialog.java new file mode 100644 index 00000000000..178a6a7936d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/SourceFileSelectionDialog.java @@ -0,0 +1,566 @@ +/******************************************************************************* + * Copyright (c) 2004 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * QNX Software Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.wizards.classwizard; + +import java.util.ArrayList; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.model.ICContainer; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICElementVisitor; +import org.eclipse.cdt.core.model.ICModel; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.internal.corext.util.CModelUtil; +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.cdt.internal.ui.dialogs.StatusUtil; +import org.eclipse.cdt.internal.ui.wizards.TypedViewerFilter; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField; +import org.eclipse.cdt.ui.CElementContentProvider; +import org.eclipse.cdt.ui.CElementLabelProvider; +import org.eclipse.cdt.ui.CElementSorter; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.dialogs.SelectionStatusDialog; + +public class SourceFileSelectionDialog extends SelectionStatusDialog { + + private TreeViewer fViewer; + private final ITreeContentProvider fContentProvider = new CElementContentProvider(); + private final ILabelProvider fLabelProvider = new CElementLabelProvider(CElementLabelProvider.SHOW_DEFAULT); + private IStatus fCurrStatus = new StatusInfo(); + private IStatus fFolderNameStatus = new StatusInfo(); + private IStatus fFileNameStatus = new StatusInfo(); + private ICElement fInput; + private int fWidth = 60; + private int fHeight = 18; + private StringDialogField fFolderNameDialogField; + private StringDialogField fFileNameDialogField; + private IWorkspaceRoot fWorkspaceRoot; + private final FieldsAdapter fFieldsAdapter = new FieldsAdapter(); + + private ICElement fCurrentFolder = null; + private String fCurrentFileString = null; + private String fInitialFolderName = null; + private String fInitialFileName = null; + + + private final class FieldsAdapter extends SelectionAdapter + implements ISelectionChangedListener, IDoubleClickListener, IDialogFieldListener { + + // -- SelectionAdapter -- + public void widgetDefaultSelected(SelectionEvent e) { + doStatusUpdate(); + if (fCurrStatus.isOK()) + buttonPressed(IDialogConstants.OK_ID); + } + + // -- ISelectionChangedListener -- + public void selectionChanged(SelectionChangedEvent event) { + setResult(((IStructuredSelection) event.getSelection()).toList()); + ISelection sel = event.getSelection(); + if (sel instanceof IStructuredSelection) { + Object obj = ((IStructuredSelection) sel).getFirstElement(); + if (obj instanceof ICElement) { + ICElement elem = (ICElement) obj; + IPath path = elem.getPath(); + String fileName = fFileNameDialogField.getText(); + String folderName = fFolderNameDialogField.getText(); + if (elem instanceof ICContainer || elem instanceof ICProject) { + folderName = path.toString(); + } else { + folderName = path.removeLastSegments(1).toString(); + fileName = path.lastSegment(); + } + setPathFields(folderName, fileName); + } + } + doStatusUpdate(); + } + + // -- IDoubleClickListener -- + public void doubleClick(DoubleClickEvent event) { + doStatusUpdate(); + + ISelection selection = event.getSelection(); + if (selection instanceof IStructuredSelection) { + Object item = ((IStructuredSelection)selection).getFirstElement(); + if (fCurrStatus.getSeverity() != IStatus.ERROR) { + if (item instanceof ITranslationUnit) { + setResult(((IStructuredSelection)selection).toList()); + close(); + return; + } + } + if (fViewer.getExpandedState(item)) + fViewer.collapseToLevel(item, 1); + else + fViewer.expandToLevel(item, 1); + } + } + + // -- IDialogFieldListener -- + public void dialogFieldChanged(DialogField field) { + if (field == fFolderNameDialogField) { + fFolderNameStatus = folderNameChanged(); + fFileNameStatus = fileNameChanged(); + } else if (field == fFileNameDialogField) { + fFileNameStatus = fileNameChanged(); + } + doStatusUpdate(); + } + } + + private static final Class[] FILTER_TYPES = new Class[] { + ICModel.class, + ICProject.class, + ICContainer.class, + ITranslationUnit.class + }; + + private final class Filter extends TypedViewerFilter { + + private Filter() { + super(FILTER_TYPES); + } + + public boolean select(Viewer viewer, Object parent, Object obj) { + if (obj instanceof ICElement) { + ICElement elem = (ICElement)obj; + if (!(fInput instanceof ICModel)) { + return elem.getCProject().equals(fInput.getCProject()); + } + return true; + } + return super.select(viewer, parent, obj); + } + } + + /** + * Constructs an instance of ElementTreeSelectionDialog. + * + * @param parent + * The parent shell for the dialog + * @param labelProvider + * the label provider to render the entries + * @param contentProvider + * the content provider to evaluate the tree structure + */ + public SourceFileSelectionDialog(Shell parent) { + super(parent); + + fWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); + fInput = CoreModel.create(fWorkspaceRoot); + + fFolderNameDialogField = new StringDialogField(); + fFolderNameDialogField.setDialogFieldListener(fFieldsAdapter); + fFolderNameDialogField.setLabelText(NewClassWizardMessages.getString("SourceFileSelectionDialog.folderName.label")); //$NON-NLS-1$ + + fFileNameDialogField = new StringDialogField(); + fFileNameDialogField.setDialogFieldListener(fFieldsAdapter); + fFileNameDialogField.setLabelText(NewClassWizardMessages.getString("SourceFileSelectionDialog.fileName.label")); //$NON-NLS-1$ + + setResult(new ArrayList(0)); + setStatusLineAboveButtons(true); + + int shellStyle = getShellStyle(); + setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE); + } + + /** + * Sets the tree input. + * + * @param input + * the tree input. + */ + public void setInput(ICElement input) { + fInput = input; + } + + protected void doStatusUpdate() { + // status of all used components + IStatus[] status = new IStatus[] { + fFolderNameStatus, + fFileNameStatus + }; + + // the mode severe status will be displayed and the ok button enabled/disabled. + updateStatus(status); + } + + /** + * Updates the status line and the ok button according to the given status + * + * @param status status to apply + */ + protected void updateStatus(IStatus status) { + fCurrStatus = status; + super.updateStatus(status); + } + + /** + * Updates the status line and the ok button according to the status evaluate from + * an array of status. The most severe error is taken. In case that two status with + * the same severity exists, the status with lower index is taken. + * + * @param status the array of status + */ + protected void updateStatus(IStatus[] status) { + updateStatus(StatusUtil.getMostSevere(status)); + } + + private IStatus folderNameChanged() { + StatusInfo status = new StatusInfo(); + + fCurrentFolder = null; + String str = fFolderNameDialogField.getText(); + if (str.length() == 0) { + status.setError(NewClassWizardMessages.getString("SourceFileSelectionDialog.error.EnterFolderName")); //$NON-NLS-1$ + return status; + } + + IPath path = new Path(str); + IResource res = fWorkspaceRoot.findMember(path); + if (res != null && res.exists()) { + int resType = res.getType(); + if (resType == IResource.PROJECT || resType == IResource.FOLDER) { + IProject proj = res.getProject(); + if (!proj.isOpen()) { + status.setError(NewClassWizardMessages.getFormattedString("SourceFileSelectionDialog.error.NotAFolder", str)); //$NON-NLS-1$ + return status; + } + ICElement e = CoreModel.getDefault().create(res.getFullPath()); + fCurrentFolder = CModelUtil.getSourceFolder(e); + if (fCurrentFolder == null) { + status.setError(NewClassWizardMessages.getFormattedString("SourceFileSelectionDialog.error.NotASourceFolder", str)); //$NON-NLS-1$ + return status; + } + if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) { + if (resType == IResource.PROJECT) { + status.setError(NewClassWizardMessages.getString("SourceFileSelectionDialog.warning.NotACProject")); //$NON-NLS-1$ + return status; + } else { + status.setWarning(NewClassWizardMessages.getString("SourceFileSelectionDialog.warning.NotInACProject")); //$NON-NLS-1$ + } + } + } else { + status.setError(NewClassWizardMessages.getFormattedString("SourceFileSelectionDialog.error.NotAFolder", str)); //$NON-NLS-1$ + return status; + } + } else { + status.setError(NewClassWizardMessages.getFormattedString("SourceFileSelectionDialog.error.FolderDoesNotExist", str)); //$NON-NLS-1$ + return status; + } + return status; + } + + private IStatus fileNameChanged() { + StatusInfo status = new StatusInfo(); + + fCurrentFileString = null; + ICElement existingFile = null; + String str = fFileNameDialogField.getText(); + if (str.length() == 0) { + status.setError(NewClassWizardMessages.getString("SourceFileSelectionDialog.error.EnterFileName")); //$NON-NLS-1$ + return status; + } + + if (fCurrentFolder != null) { + IPath folderPath = fCurrentFolder.getPath(); + IPath path = new Path(str); + IResource res = fWorkspaceRoot.findMember(folderPath.append(path)); + if (res == null) + res = fWorkspaceRoot.findMember(path); + if (res != null && res.exists()) { + int resType = res.getType(); + if (resType == IResource.FILE) { + IProject proj = res.getProject(); + if (!proj.isOpen()) { + status.setError(NewClassWizardMessages.getFormattedString("SourceFileSelectionDialog.error.NotAFile", str)); //$NON-NLS-1$ + return status; + } + ICElement e = CoreModel.getDefault().create(res.getFullPath()); + if (e instanceof ITranslationUnit) { + existingFile = (ITranslationUnit) e; + } + if (existingFile == null) { + status.setError(NewClassWizardMessages.getFormattedString("SourceFileSelectionDialog.error.NotASourceFile", str)); //$NON-NLS-1$ + return status; + } + if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) { + status.setWarning(NewClassWizardMessages.getString("SourceFileSelectionDialog.warning.NotInACProject")); //$NON-NLS-1$ + } + } else { + status.setError(NewClassWizardMessages.getFormattedString("SourceFileSelectionDialog.error.NotAFile", str)); //$NON-NLS-1$ + return status; + } + } + } + if (existingFile != null) { + status.setWarning(NewClassWizardMessages.getFormattedString("SourceFileSelectionDialog.warning.SourceFileExists", str)); //$NON-NLS-1$ + } + fCurrentFileString = str; + return status; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.window.Window#open() + */ + public int open() { + super.open(); + return getReturnCode(); + } + + /** + * Handles cancel button pressed event. + */ + protected void cancelPressed() { + setResult(null); + super.cancelPressed(); + } + + /* + * @see SelectionStatusDialog#computeResult() + */ + protected void computeResult() { + setResult(((IStructuredSelection) fViewer.getSelection()).toList()); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.jface.window.Window#create() + */ + public void create() { + BusyIndicator.showWhile(null, new Runnable() { + public void run() { + superCreate(); + fViewer.setSelection(new StructuredSelection(getInitialElementSelections()), true); + setPathFields(fInitialFolderName, fInitialFileName); + fFileNameDialogField.setFocus(); + doStatusUpdate(); + } + }); + } + private void superCreate() { + super.create(); + } + + /* + * @see Dialog#createDialogArea(Composite) + */ + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + // Label messageLabel = createMessageArea(composite); + int nColumns = 4; + fFolderNameDialogField.doFillIntoGrid(composite, nColumns - 1); + DialogField.createEmptySpace(composite); + LayoutUtil.setWidthHint(fFolderNameDialogField.getTextControl(null), getMaxFieldWidth()); + + TreeViewer treeViewer = createTreeViewer(composite); + + GridData data = new GridData(GridData.FILL_BOTH); + data.widthHint = convertWidthInCharsToPixels(fWidth); + data.heightHint = convertHeightInCharsToPixels(fHeight); + + Tree treeWidget = treeViewer.getTree(); + treeWidget.setLayoutData(data); + treeWidget.setFont(parent.getFont()); + + fFileNameDialogField.doFillIntoGrid(composite, nColumns - 1); + DialogField.createEmptySpace(composite); + LayoutUtil.setWidthHint(fFileNameDialogField.getTextControl(null), getMaxFieldWidth()); + + return composite; + } + + /** + * Returns the recommended maximum width for text fields (in pixels). This + * method requires that createContent has been called before this method is + * call. Subclasses may override to change the maximum width for text + * fields. + * + * @return the recommended maximum width for text fields. + */ + protected int getMaxFieldWidth() { + return convertWidthInCharsToPixels(60); + } + + /** + * Creates the tree viewer. + * + * @param parent + * the parent composite + * @return the tree viewer + */ + protected TreeViewer createTreeViewer(Composite parent) { + int style = (SWT.BORDER | SWT.SINGLE); + + fViewer = new TreeViewer(new Tree(parent, style)); + fViewer.setContentProvider(fContentProvider); + fViewer.setLabelProvider(fLabelProvider); + fViewer.addSelectionChangedListener(fFieldsAdapter); + + fViewer.setSorter(new CElementSorter()); + fViewer.addFilter(new Filter()); + + Tree tree = fViewer.getTree(); + tree.addSelectionListener(fFieldsAdapter); + fViewer.addDoubleClickListener(fFieldsAdapter); + + fViewer.setInput(fInput.getCModel()); + + return fViewer; + } + + /** + * Returns the tree viewer. + * + * @return the tree viewer + */ + protected TreeViewer getTreeViewer() { + return fViewer; + } + + /** + * @see org.eclipse.jface.window.Window#handleShellCloseEvent() + */ + protected void handleShellCloseEvent() { + super.handleShellCloseEvent(); + + //Handle the closing of the shell by selecting the close icon + if (getReturnCode() == CANCEL) + setResult(null); + } + + public String getFolderName() { + if (fCurrentFolder != null) { + return fCurrentFolder.getPath().toString(); + } + return null; + } + + public String getFileName() { + return fCurrentFileString; + } + + public IPath getFilePath() { + IPath path = null; + if (fCurrentFolder != null) { + path = fCurrentFolder.getPath(); + if (fCurrentFileString != null) + path = path.append(fCurrentFileString); + } else if (fCurrentFileString != null) { + path = new Path(fCurrentFileString); + } + return path; + } + + private void setPathFields(String folderName, String fileName) { + fFolderNameDialogField.setTextWithoutUpdate(folderName != null ? folderName : ""); //$NON-NLS-1$ + fFileNameDialogField.setTextWithoutUpdate(fileName != null ? fileName : ""); //$NON-NLS-1$ + fFolderNameStatus = folderNameChanged(); + fFileNameStatus = fileNameChanged(); + } + + /** + * Sets the initial selection. Convenience method. + * + * @param selection + * the initial selection. + */ + public void setInitialFields(String folderName, String fileName) { + fInitialFolderName = folderName; + fInitialFileName = fileName; + + final IPath folderPath; + final IPath filePath; + if (folderName != null && folderName.length() > 0) { + folderPath = new Path(folderName); + } else { + folderPath = null; + } + if (folderPath != null && fileName != null && fileName.length() > 0) { + filePath = folderPath.append(fileName); + } else { + filePath = null; + } + + if (fInput != null && folderPath != null) { + final ICElement[] foundElem = {/*base_folder*/ null, /*exact_folder*/ null, /*exact_file*/ null}; + try { + fInput.accept(new ICElementVisitor() { + public boolean visit(ICElement elem) { + IPath path = elem.getPath(); + if (path.isPrefixOf(folderPath)) { + if (foundElem[0] == null || path.segmentCount() > foundElem[0].getPath().segmentCount()) { + foundElem[0] = elem; /*base_folder*/ + } + if (path.equals(folderPath)) { + foundElem[1] = elem; /*exact_folder*/ + if (filePath == null) + return false; // no need to search children + } else if (filePath != null && path.equals(filePath)) { + foundElem[2] = elem; /*exact_file*/ + return false; // no need to search children + } + return true; + } + return false; + } + }); + + ICElement selectedElement = foundElem[2]; /*exact_file*/ + if (selectedElement == null) + selectedElement = foundElem[1]; /*exact_folder*/ + if (selectedElement == null) + selectedElement = foundElem[0]; /*base_folder*/ + + if (selectedElement != null) { + setInitialSelections(new Object[] { selectedElement }); + } + } catch (CoreException e) { + } + } + } +}