From 6acaa7fee9fc8a67c3bb2b761889634fd1c74868 Mon Sep 17 00:00:00 2001 From: Chris Wiebe Date: Wed, 30 Mar 2005 00:17:45 +0000 Subject: [PATCH] 2005-03-29 Chris Wiebe fix PR#87328 by making class wizard page publicly accessible refactored wizard code and added comments * src/org/eclipse/cdt/internal/ui/wizards/AbstractMethodStub.java * src/org/eclipse/cdt/internal/ui/wizards/ConstructorMethodStub.java * src/org/eclipse/cdt/internal/ui/wizards/DestructorMethodStub.java * src/org/eclipse/cdt/internal/ui/wizards/IMethodStub.java * src/org/eclipse/cdt/internal/ui/wizards/NewBaseClassSelectionDialog.java * src/org/eclipse/cdt/internal/ui/wizards/NewClassCodeGenerator.java * src/org/eclipse/cdt/internal/ui/wizards/NewClassWizardMessages.properties * src/org/eclipse/cdt/internal/ui/wizards/DestructorMethodStub.java * src/org/eclipse/cdt/internal/ui/wizards/DestructorMethodStub.java * src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java * src/org/eclipse/cdt/internal/ui/wizards/NewClassCreationWizard.java * src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardPrefs.java * src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardUtil.java * plugin.xml removed: * src/org/eclipse/cdt/ui/wizards/NewClassCreationWizard.java * src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCreationWizardPage.java --- core/org.eclipse.cdt.ui/ChangeLog | 22 + core/org.eclipse.cdt.ui/plugin.properties | 2 +- core/org.eclipse.cdt.ui/plugin.xml | 2 +- .../ui/wizards/NewClassCreationWizard.java | 46 +- .../classwizard/AbstractMethodStub.java | 5 +- .../classwizard/ConstructorMethodStub.java | 9 +- .../classwizard/DestructorMethodStub.java | 11 +- .../ui/wizards/classwizard/IMethodStub.java | 5 +- .../NewBaseClassSelectionDialog.java | 79 +- .../classwizard/NewClassCodeGenerator.java | 78 +- .../NewClassCreationWizardPage.java | 2184 ----------------- .../NewClassWizardMessages.properties | 10 +- .../classwizard/NewClassWizardPrefs.java | 37 + .../classwizard/NewClassWizardUtil.java | 398 +++ .../filewizard/NewSourceFileGenerator.java | 3 +- .../wizards/NewClassCreationWizardPage.java | 1954 +++++++++++++++ 16 files changed, 2555 insertions(+), 2290 deletions(-) rename core/org.eclipse.cdt.ui/src/org/eclipse/cdt/{ => internal}/ui/wizards/NewClassCreationWizard.java (68%) delete mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCreationWizardPage.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardPrefs.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardUtil.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index d56f358efea..1bf9a5e9176 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,25 @@ +2005-03-29 Chris Wiebe + + fix PR#87328 by making class wizard page publicly accessible + refactored wizard code and added comments + * src/org/eclipse/cdt/internal/ui/wizards/AbstractMethodStub.java + * src/org/eclipse/cdt/internal/ui/wizards/ConstructorMethodStub.java + * src/org/eclipse/cdt/internal/ui/wizards/DestructorMethodStub.java + * src/org/eclipse/cdt/internal/ui/wizards/IMethodStub.java + * src/org/eclipse/cdt/internal/ui/wizards/NewBaseClassSelectionDialog.java + * src/org/eclipse/cdt/internal/ui/wizards/NewClassCodeGenerator.java + * src/org/eclipse/cdt/internal/ui/wizards/NewClassWizardMessages.properties + * src/org/eclipse/cdt/internal/ui/wizards/DestructorMethodStub.java + * src/org/eclipse/cdt/internal/ui/wizards/DestructorMethodStub.java + * src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java + * src/org/eclipse/cdt/internal/ui/wizards/NewClassCreationWizard.java + * src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardPrefs.java + * src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardUtil.java + * plugin.xml + removed: + * src/org/eclipse/cdt/ui/wizards/NewClassCreationWizard.java + * src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCreationWizardPage.java + 2005-03-29 Vladimir Hirsl Removing indexer problem markers when problem reporting is deselected. diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties index 7761e757f6a..3e32ddd02ef 100644 --- a/core/org.eclipse.cdt.ui/plugin.properties +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -109,7 +109,7 @@ CEditor.name=C/C++ Editor CPluginPreferencePage.name=C/C++ CPluginEditorPreferencePage.name=Editor -CPluginTemplatePreferencePage.name=Code Templates +CPluginTemplatePreferencePage.name=Templates CPluginBuildConsolePreferencePage.name=Build Console CPluginFileTypesPreferencePage.name=File Types CodeFormatterPreferencePage.name=Code Formatter diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index ebd36e5cc75..872cc689c2c 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -388,7 +388,7 @@ category="org.eclipse.cdt.ui.newCCWizards" finalPerspective="org.eclipse.cdt.ui.CPerspective" id="org.eclipse.cdt.ui.wizards.NewClassCreationWizard"> - + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/NewClassCreationWizard.java similarity index 68% rename from core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizard.java rename to core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/NewClassCreationWizard.java index f4038299044..f5a24bc0643 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizard.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/NewClassCreationWizard.java @@ -8,16 +8,13 @@ * Contributors: * QNX Software Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.cdt.ui.wizards; +package org.eclipse.cdt.internal.ui.wizards; -import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.internal.ui.CPluginImages; -import org.eclipse.cdt.internal.ui.wizards.NewElementWizard; -import org.eclipse.cdt.internal.ui.wizards.classwizard.NewClassCreationWizardPage; import org.eclipse.cdt.internal.ui.wizards.classwizard.NewClassWizardMessages; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.wizards.NewClassCreationWizardPage; import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -48,7 +45,7 @@ public class NewClassCreationWizard extends NewElementWizard { * @see org.eclipse.cdt.internal.ui.wizards.NewElementWizard#canRunForked() */ protected boolean canRunForked() { - return !fPage.isEnclosingTypeSelected(); + return !fPage.isNamespaceSelected(); } /* @@ -66,28 +63,21 @@ public class NewClassCreationWizard extends NewElementWizard { * @see org.eclipse.jface.wizard.IWizard#performFinish() */ public boolean performFinish() { - boolean res = super.performFinish(); - if (res) { - //TODO need prefs option for opening editor - boolean openInEditor = true; - - ITranslationUnit bodyTU = fPage.getCreatedSourceTU(); - if (bodyTU != null) { - IResource resource= bodyTU.getResource(); - selectAndReveal(resource); - if (openInEditor) { - openResource((IFile) resource); - } - } - ITranslationUnit headerTU = fPage.getCreatedHeaderTU(); - if (headerTU != null) { - IResource resource = headerTU.getResource(); - selectAndReveal(resource); - if (openInEditor) { - openResource((IFile) resource); - } - } + boolean finished = super.performFinish(); + if (finished) { + if (fPage.openClassInEditor()) { + IFile source = fPage.getCreatedSourceFile(); + if (source != null) { + selectAndReveal(source); + openResource(source); + } + IFile header = fPage.getCreatedHeaderFile(); + if (header != null) { + selectAndReveal(header); + openResource(header); + } + } } - return res; + return finished; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/AbstractMethodStub.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/AbstractMethodStub.java index 4692ae6ea02..74f2e714e18 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/AbstractMethodStub.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/AbstractMethodStub.java @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; -import org.eclipse.cdt.core.browser.IQualifiedTypeName; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; public abstract class AbstractMethodStub implements IMethodStub { @@ -79,7 +78,7 @@ public abstract class AbstractMethodStub implements IMethodStub { return false; } - public abstract String createMethodDeclaration(IQualifiedTypeName className, IBaseClassInfo[] baseClasses, String lineDelimiter); + public abstract String createMethodDeclaration(String className, IBaseClassInfo[] baseClasses, String lineDelimiter); - public abstract String createMethodImplementation(IQualifiedTypeName className, IBaseClassInfo[] baseClasses, String lineDelimiter); + public abstract String createMethodImplementation(String className, IBaseClassInfo[] baseClasses, String lineDelimiter); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/ConstructorMethodStub.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/ConstructorMethodStub.java index a1e3d3b4297..ff3259ab3fa 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/ConstructorMethodStub.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/ConstructorMethodStub.java @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; -import org.eclipse.cdt.core.browser.IQualifiedTypeName; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; @@ -26,10 +25,10 @@ public final class ConstructorMethodStub extends AbstractMethodStub { super(NAME, access, false, isInline); } - public String createMethodDeclaration(IQualifiedTypeName className, IBaseClassInfo[] baseClasses, String lineDelimiter) { + public String createMethodDeclaration(String className, IBaseClassInfo[] baseClasses, String lineDelimiter) { //TODO should use code templates StringBuffer buf = new StringBuffer(); - buf.append(className.toString()); + buf.append(className); buf.append("()"); //$NON-NLS-1$ if (fIsInline) { buf.append(" {}"); //$NON-NLS-1$ @@ -39,13 +38,13 @@ public final class ConstructorMethodStub extends AbstractMethodStub { return buf.toString(); } - public String createMethodImplementation(IQualifiedTypeName className, IBaseClassInfo[] baseClasses, String lineDelimiter) { + public String createMethodImplementation(String className, IBaseClassInfo[] baseClasses, String lineDelimiter) { //TODO should use code templates if (fIsInline) { return ""; //$NON-NLS-1$ } StringBuffer buf = new StringBuffer(); - buf.append(className.toString()); + buf.append(className); buf.append("::"); //$NON-NLS-1$ buf.append(className.toString()); buf.append("()"); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/DestructorMethodStub.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/DestructorMethodStub.java index 00e9a7451e5..4cf7179648f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/DestructorMethodStub.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/DestructorMethodStub.java @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; -import org.eclipse.cdt.core.browser.IQualifiedTypeName; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; @@ -26,14 +25,14 @@ public final class DestructorMethodStub extends AbstractMethodStub { super(NAME, access, isVirtual, isInline); } - public String createMethodDeclaration(IQualifiedTypeName className, IBaseClassInfo[] baseClasses, String lineDelimiter) { + public String createMethodDeclaration(String className, IBaseClassInfo[] baseClasses, String lineDelimiter) { //TODO should use code templates StringBuffer buf = new StringBuffer(); if (fIsVirtual){ buf.append("virtual "); //$NON-NLS-1$ } buf.append("~"); //$NON-NLS-1$ - buf.append(className.toString()); + buf.append(className); buf.append("()"); //$NON-NLS-1$ if (fIsInline) { buf.append(" {}"); //$NON-NLS-1$ @@ -43,15 +42,15 @@ public final class DestructorMethodStub extends AbstractMethodStub { return buf.toString(); } - public String createMethodImplementation(IQualifiedTypeName className, IBaseClassInfo[] baseClasses, String lineDelimiter) { + public String createMethodImplementation(String className, IBaseClassInfo[] baseClasses, String lineDelimiter) { //TODO should use code templates if (fIsInline) { return ""; //$NON-NLS-1$ } StringBuffer buf = new StringBuffer(); - buf.append(className.toString()); + buf.append(className); buf.append("::~"); //$NON-NLS-1$ - buf.append(className.toString()); + buf.append(className); buf.append("()"); //$NON-NLS-1$ buf.append(lineDelimiter); buf.append('{'); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/IMethodStub.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/IMethodStub.java index ca9e6c40ecb..2aa1d9b1035 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/IMethodStub.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/IMethodStub.java @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; -import org.eclipse.cdt.core.browser.IQualifiedTypeName; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; @@ -33,6 +32,6 @@ public interface IMethodStub { public boolean isConstructor(); public boolean isDestructor(); - public String createMethodDeclaration(IQualifiedTypeName className, IBaseClassInfo[] baseClasses, String lineDelimiter); - public String createMethodImplementation(IQualifiedTypeName className, IBaseClassInfo[] baseClasses, String lineDelimiter); + public String createMethodDeclaration(String className, IBaseClassInfo[] baseClasses, String lineDelimiter); + public String createMethodImplementation(String className, IBaseClassInfo[] baseClasses, String lineDelimiter); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewBaseClassSelectionDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewBaseClassSelectionDialog.java index f0ee9e3b5a0..96b9d7da37c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewBaseClassSelectionDialog.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewBaseClassSelectionDialog.java @@ -10,21 +10,16 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.wizards.classwizard; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.eclipse.cdt.core.browser.AllTypesCache; import org.eclipse.cdt.core.browser.ITypeInfo; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; -import org.eclipse.cdt.internal.ui.util.ExceptionHandler; import org.eclipse.cdt.ui.browser.typeinfo.TypeSelectionDialog; -import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; @@ -105,36 +100,47 @@ public class NewBaseClassSelectionDialog extends TypeSelectionDialog { private void addType(Object elem) { if (elem instanceof ITypeInfo) { ITypeInfo type = (ITypeInfo)elem; - if (!fTypeList.contains(type)) { + if (fTypeList.contains(type)) { + String qualifiedName = type.getQualifiedTypeName().getFullyQualifiedName(); + String message = NewClassWizardMessages.getFormattedString("NewBaseClassSelectionDialog.classalreadyadded.info", qualifiedName); //$NON-NLS-1$ + updateStatus(new StatusInfo(IStatus.INFO, message)); + } else { String qualifiedName = type.getQualifiedTypeName().getFullyQualifiedName(); String message = NewClassWizardMessages.getFormattedString("NewBaseClassSelectionDialog.addingclass.info", qualifiedName); //$NON-NLS-1$ updateStatus(new StatusInfo(IStatus.INFO, message)); - // resolve location of base class - if (type.getResolvedReference() == null) { - final ITypeInfo[] typesToResolve = new ITypeInfo[] { type }; - IRunnableWithProgress runnable = new IRunnableWithProgress() { - public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException { - AllTypesCache.resolveTypeLocation(typesToResolve[0], progressMonitor); - if (progressMonitor.isCanceled()) { - throw new InterruptedException(); - } - } - }; - - IProgressService service = PlatformUI.getWorkbench().getProgressService(); - try { - service.busyCursorWhile(runnable); - } catch (InvocationTargetException e) { - String title= NewClassWizardMessages.getString("NewBaseClassSelectionDialog.getClasses.exception.title"); //$NON-NLS-1$ - String errorMessage= NewClassWizardMessages.getString("NewBaseClassSelectionDialog.getClasses.exception.message"); //$NON-NLS-1$ - ExceptionHandler.handle(e, title, errorMessage); - } catch (InterruptedException e) { - // cancelled by user - } - } + boolean canAdd = true; + if (verifyBaseClasses()) { + IProgressService service = PlatformUI.getWorkbench().getProgressService(); + NewClassWizardUtil.resolveClassLocation(type, service); + canAdd = (type.getResolvedReference() != null); + } + +// // resolve location of base class +// if (type.getResolvedReference() == null) { +// final ITypeInfo[] typesToResolve = new ITypeInfo[] { type }; +// IRunnableWithProgress runnable = new IRunnableWithProgress() { +// public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException { +// AllTypesCache.resolveTypeLocation(typesToResolve[0], progressMonitor); +// if (progressMonitor.isCanceled()) { +// throw new InterruptedException(); +// } +// } +// }; +// +// IProgressService service = PlatformUI.getWorkbench().getProgressService(); +// try { +// service.busyCursorWhile(runnable); +// } catch (InvocationTargetException e) { +// String title= NewClassWizardMessages.getString("NewBaseClassSelectionDialog.getClasses.exception.title"); //$NON-NLS-1$ +// String errorMessage= NewClassWizardMessages.getString("NewBaseClassSelectionDialog.getClasses.exception.message"); //$NON-NLS-1$ +// ExceptionHandler.handle(e, title, errorMessage); +// } catch (InterruptedException e) { +// // cancelled by user +// } +// } - if (type.getResolvedReference() != null) { + if (canAdd) { fTypeList.add(type); message = NewClassWizardMessages.getFormattedString("NewBaseClassSelectionDialog.classadded.info", qualifiedName); //$NON-NLS-1$ @@ -145,13 +151,18 @@ public class NewBaseClassSelectionDialog extends TypeSelectionDialog { message = NewClassWizardMessages.getFormattedString("NewBaseClassSelectionDialog.error.classnotadded", qualifiedName); //$NON-NLS-1$ updateStatus(new StatusInfo(IStatus.ERROR, message)); } - } else { - String qualifiedName = type.getQualifiedTypeName().getFullyQualifiedName(); - String message = NewClassWizardMessages.getFormattedString("NewBaseClassSelectionDialog.classalreadyadded.info", qualifiedName); //$NON-NLS-1$ - updateStatus(new StatusInfo(IStatus.INFO, message)); } } } + + /** + * Checks if the base classes need to be verified (ie they must exist in the project) + * + * @return true if the base classes should be verified + */ + public boolean verifyBaseClasses() { + return NewClassWizardPrefs.verifyBaseClasses(); + } /* * @see AbstractElementListSelectionDialog#handleDefaultSelected() 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 08b72ebc5c0..638ea4af09e 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 @@ -18,6 +18,7 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.browser.IQualifiedTypeName; import org.eclipse.cdt.core.browser.ITypeReference; import org.eclipse.cdt.core.browser.PathUtil; +import org.eclipse.cdt.core.browser.QualifiedTypeName; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICContainer; @@ -32,20 +33,23 @@ import org.eclipse.cdt.core.parser.IScannerInfoProvider; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; import org.eclipse.cdt.internal.corext.util.CModelUtil; import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator; +import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; public class NewClassCodeGenerator { private IPath fHeaderPath = null; private IPath fSourcePath = null; - private IQualifiedTypeName fClassName = null; + private String fClassName = null; private IQualifiedTypeName fNamespace = null; private String fLineDelimiter; private IBaseClassInfo[] fBaseClasses = null; @@ -54,25 +58,30 @@ public class NewClassCodeGenerator { private ITranslationUnit fCreatedSourceTU = null; private ICElement fCreatedClass = null; - //TODO this should be a prefs option - private boolean fCreateIncludePaths = true; - - public static class CodeGeneratorException extends Exception { + public static class CodeGeneratorException extends CoreException { /** * Comment for serialVersionUID */ private static final long serialVersionUID = 1L; - public CodeGeneratorException(String message) { + + public CodeGeneratorException(String message) { + super(new Status(Status.ERROR, CUIPlugin.getPluginId(), IStatus.OK, message, null)); } + public CodeGeneratorException(Throwable e) { + super(new Status(Status.ERROR, CUIPlugin.getPluginId(), IStatus.OK, e.getMessage(), e)); } } - public NewClassCodeGenerator(IPath headerPath, IPath sourcePath, IQualifiedTypeName className, IQualifiedTypeName namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs) { + public NewClassCodeGenerator(IPath headerPath, IPath sourcePath, String className, String namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs) { fHeaderPath = headerPath; fSourcePath = sourcePath; - fClassName = className; - fNamespace = namespace; + if (className != null && className.length() > 0) { + fClassName = className; + } + if (namespace != null && namespace.length() > 0) { + fNamespace = new QualifiedTypeName(namespace); + } fBaseClasses = baseClasses; fMethodStubs = methodStubs; fLineDelimiter = NewSourceFileGenerator.getLineDelimiter(); @@ -85,11 +94,25 @@ public class NewClassCodeGenerator { public ITranslationUnit getCreatedHeaderTU() { return fCreatedHeaderTU; } + + public IFile getCreatedHeaderFile() { + if (fCreatedHeaderTU != null) { + return (IFile)fCreatedHeaderTU.getResource(); + } + return null; + } public ITranslationUnit getCreatedSourceTU() { return fCreatedSourceTU; } + public IFile getCreatedSourceFile() { + if (fCreatedSourceTU != null) { + return (IFile)fCreatedSourceTU.getResource(); + } + return null; + } + /** * Creates the new class. * @@ -393,10 +416,10 @@ public class NewClassCodeGenerator { IPath headerLocation = headerTU.getResource().getLocation(); List includePaths = getIncludePaths(headerTU); - List baseClassPaths = getBaseClassPaths(); + List baseClassPaths = getBaseClassPaths(verifyBaseClasses()); // add the missing include paths to the project - if (fCreateIncludePaths) { + if (createIncludePaths()) { List newIncludePaths = getMissingIncludePaths(projectLocation, includePaths, baseClassPaths); if (!newIncludePaths.isEmpty()) { addIncludePaths(cProject, newIncludePaths, monitor); @@ -449,6 +472,24 @@ public class NewClassCodeGenerator { monitor.done(); } + + /** + * Checks if the base classes need to be verified (ie they must exist in the project) + * + * @return true if the base classes should be verified + */ + private boolean verifyBaseClasses() { + return NewClassWizardPrefs.verifyBaseClasses(); + } + + /** + * Checks if include paths can be added to the project as needed. + * + * @return true if the include paths should be added + */ + private boolean createIncludePaths() { + return NewClassWizardPrefs.createIncludePaths(); + } private void addIncludePaths(ICProject cProject, List newIncludePaths, IProgressMonitor monitor) throws CodeGeneratorException { monitor.beginTask(NewClassWizardMessages.getString("NewClassCodeGeneration.createType.task.header.addIncludePaths"), 100); //$NON-NLS-1$ @@ -562,18 +603,23 @@ public class NewClassCodeGenerator { return null; } - private List getBaseClassPaths() throws CodeGeneratorException { + private List getBaseClassPaths(boolean verifyLocation) throws CodeGeneratorException { List list = new ArrayList(); for (int i = 0; i < fBaseClasses.length; ++i) { IBaseClassInfo baseClass = fBaseClasses[i]; ITypeReference ref = baseClass.getType().getResolvedReference(); IPath baseClassLocation = null; - if (ref != null) + if (ref != null) { baseClassLocation = ref.getLocation(); + } + if (baseClassLocation == null) { - throw new CodeGeneratorException("Could not find base class " + baseClass.toString()); //$NON-NLS-1$ - } - list.add(baseClassLocation); + if (verifyLocation) { + throw new CodeGeneratorException("Could not find base class " + baseClass.toString()); //$NON-NLS-1$ + } + } else { + list.add(baseClassLocation); + } } return list; } 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 deleted file mode 100644 index b958313fdbe..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassCreationWizardPage.java +++ /dev/null @@ -1,2184 +0,0 @@ -/******************************************************************************* - * 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.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.eclipse.cdt.core.CConventions; -import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.browser.AllTypesCache; -import org.eclipse.cdt.core.browser.IQualifiedTypeName; -import org.eclipse.cdt.core.browser.ITypeInfo; -import org.eclipse.cdt.core.browser.ITypeReference; -import org.eclipse.cdt.core.browser.ITypeSearchScope; -import org.eclipse.cdt.core.browser.PathUtil; -import org.eclipse.cdt.core.browser.QualifiedTypeName; -import org.eclipse.cdt.core.browser.TypeSearchScope; -import org.eclipse.cdt.core.browser.TypeUtil; -import org.eclipse.cdt.core.model.CModelException; -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.ICProject; -import org.eclipse.cdt.core.model.ISourceRoot; -import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.core.parser.IScannerInfo; -import org.eclipse.cdt.core.parser.IScannerInfoProvider; -import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; -import org.eclipse.cdt.internal.corext.util.CModelUtil; -import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; -import org.eclipse.cdt.internal.ui.editor.CEditor; -import org.eclipse.cdt.internal.ui.util.ExceptionHandler; -import org.eclipse.cdt.internal.ui.util.SWTUtil; -import org.eclipse.cdt.internal.ui.viewsupport.IViewPartInputProvider; -import org.eclipse.cdt.internal.ui.wizards.NewElementWizardPage; -import org.eclipse.cdt.internal.ui.wizards.SourceFolderSelectionDialog; -import org.eclipse.cdt.internal.ui.wizards.classwizard.NewBaseClassSelectionDialog.ITypeSelectionListener; -import org.eclipse.cdt.internal.ui.wizards.classwizard.NewClassCodeGenerator.CodeGeneratorException; -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.IListAdapter; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.IStringButtonAdapter; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.ListDialogField; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.Separator; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringButtonDialogField; -import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField; -import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator; -import org.eclipse.cdt.ui.CUIPlugin; -import org.eclipse.core.resources.IFile; -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.IAdaptable; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.operation.IRunnableWithProgress; -import org.eclipse.jface.text.ITextSelection; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionProvider; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.views.contentoutline.ContentOutline; - -public class NewClassCreationWizardPage extends NewElementWizardPage { - -// private static final int NAMESPACE_INDEX = 0; -// private static final int CLASS_INDEX = 1; - private final static String PAGE_NAME = "NewClassWizardPage"; //$NON-NLS-1$ - private static final int MAX_FIELD_CHARS = 50; - - private IWorkspaceRoot fWorkspaceRoot; - - // field IDs - private static final int SOURCE_FOLDER_ID = 1; - private static final int ENCLOSING_TYPE_ID = 2; - private static final int CLASS_NAME_ID = 4; - private static final int BASE_CLASSES_ID = 8; - private static final int METHOD_STUBS_ID = 16; - private static final int HEADER_FILE_ID = 32; - private static final int SOURCE_FILE_ID = 64; - private static final int ALL_FIELDS = SOURCE_FOLDER_ID | ENCLOSING_TYPE_ID - | CLASS_NAME_ID | BASE_CLASSES_ID | METHOD_STUBS_ID - | HEADER_FILE_ID | SOURCE_FILE_ID; - protected int fLastFocusedField = 0; - - private StringButtonDialogField fSourceFolderDialogField; - SelectionButtonDialogField fEnclosingTypeSelection; - StringButtonDialogField fEnclosingTypeDialogField; -// SelectionButtonDialogFieldGroup fEnclosingTypeButtons; -// SelectionButtonDialogFieldGroup fEnclosingClassAccessButtons; - StringDialogField fClassNameDialogField; - BaseClassesListDialogField fBaseClassesDialogField; - MethodStubsListDialogField fMethodStubsDialogField; - SelectionButtonDialogField fUseDefaultSelection; - StringButtonDialogField fHeaderFileDialogField; - StringButtonDialogField fSourceFileDialogField; - - protected IStatus fSourceFolderStatus; - protected IStatus fEnclosingTypeStatus; - protected IStatus fClassNameStatus; - protected IStatus fBaseClassesStatus; - protected IStatus fMethodStubsStatus; - protected IStatus fHeaderFileStatus; - protected IStatus fSourceFileStatus; - protected final IStatus STATUS_OK = new StatusInfo(); - - private NewClassCodeGenerator fCodeGenerator = null; - - //TODO this should be a prefs option - private boolean fErrorIfBaseClassNotInPath = true; - - public NewClassCreationWizardPage() { - super(PAGE_NAME); - - setDescription(NewClassWizardMessages.getString("NewClassCreationWizardPage.description")); //$NON-NLS-1$ - - fWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); - fCodeGenerator = null; - - SourceFolderFieldAdapter sourceFolderAdapter = new SourceFolderFieldAdapter(); - fSourceFolderDialogField = new StringButtonDialogField(sourceFolderAdapter); - fSourceFolderDialogField.setDialogFieldListener(sourceFolderAdapter); - fSourceFolderDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.sourceFolder.label")); //$NON-NLS-1$ - fSourceFolderDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.sourceFolder.button")); //$NON-NLS-1$ - - EnclosingTypeFieldAdapter enclosingTypeAdapter = new EnclosingTypeFieldAdapter(); - fEnclosingTypeSelection = new SelectionButtonDialogField(SWT.CHECK); - fEnclosingTypeSelection.setDialogFieldListener(enclosingTypeAdapter); - fEnclosingTypeSelection.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.enclosingType.label")); //$NON-NLS-1$ - -// String[] buttonNames = new String[] { -// /* NAMESPACE_INDEX */ NewClassWizardMessages.getString("NewClassCreationWizardPage.enclosingType.namespace"), //$NON-NLS-1$ -// /* CLASS_INDEX */ NewClassWizardMessages.getString("NewClassCreationWizardPage.enclosingType.class"), //$NON-NLS-1$ -// }; -// fEnclosingTypeButtons = new SelectionButtonDialogFieldGroup(SWT.RADIO, buttonNames, buttonNames.length); -// fEnclosingTypeButtons.setDialogFieldListener(enclosingTypeAdapter); -// fEnclosingTypeButtons.setSelection(NAMESPACE_INDEX, true); - -// String[] buttonNames2 = new String[] { -// NewClassWizardMessages.getString("NewClassCreationWizardPage.enclosingClassAccess.public"), //$NON-NLS-1$ -// NewClassWizardMessages.getString("NewClassCreationWizardPage.enclosingClassAccess.protected"), //$NON-NLS-1$ -// NewClassWizardMessages.getString("NewClassCreationWizardPage.enclosingClassAccess.private") //$NON-NLS-1$ -// }; -// fEnclosingClassAccessButtons = new SelectionButtonDialogFieldGroup(SWT.RADIO, buttonNames2, buttonNames2.length); -// fEnclosingClassAccessButtons.setDialogFieldListener(enclosingTypeAdapter); -// fEnclosingClassAccessButtons.setLabelText(NewClassWizardMessages.getString("NewClassWizardPage.baseclass.access.label")); //$NON-NLS-1$ -// fEnclosingClassAccessButtons.setSelection(0, true); - - fEnclosingTypeDialogField = new StringButtonDialogField(enclosingTypeAdapter); - fEnclosingTypeDialogField.setDialogFieldListener(enclosingTypeAdapter); - fEnclosingTypeDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.enclosingType.button")); //$NON-NLS-1$ - - ClassNameFieldAdapter classAdapter = new ClassNameFieldAdapter(); - fClassNameDialogField = new StringDialogField(); - fClassNameDialogField.setDialogFieldListener(classAdapter); - fClassNameDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.className.label")); //$NON-NLS-1$ - - BaseClassesFieldAdapter baseClassesAdapter = new BaseClassesFieldAdapter(); - fBaseClassesDialogField = new BaseClassesListDialogField(NewClassWizardMessages.getString("NewClassCreationWizardPage.baseClasses.label"), baseClassesAdapter); //$NON-NLS-1$ - - MethodStubsFieldAdapter methodStubsAdapter = new MethodStubsFieldAdapter(); - fMethodStubsDialogField = new MethodStubsListDialogField(NewClassWizardMessages.getString("NewClassCreationWizardPage.methodStubs.label"), methodStubsAdapter); //$NON-NLS-1$ - - FileGroupFieldAdapter fileGroupAdapter = new FileGroupFieldAdapter(); - fUseDefaultSelection = new SelectionButtonDialogField(SWT.CHECK); - fUseDefaultSelection.setDialogFieldListener(fileGroupAdapter); - fUseDefaultSelection.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.useDefaultLocation.label")); //$NON-NLS-1$ - fHeaderFileDialogField = new StringButtonDialogField(fileGroupAdapter); - fHeaderFileDialogField.setDialogFieldListener(fileGroupAdapter); - fHeaderFileDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.headerFile.label")); //$NON-NLS-1$ - fHeaderFileDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.headerFile.button")); //$NON-NLS-1$ - fSourceFileDialogField = new StringButtonDialogField(fileGroupAdapter); - fSourceFileDialogField.setDialogFieldListener(fileGroupAdapter); - fSourceFileDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.sourceFile.label")); //$NON-NLS-1$ - fSourceFileDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.sourceFile.button")); //$NON-NLS-1$ - - fSourceFolderStatus = STATUS_OK; - fEnclosingTypeStatus = STATUS_OK; - fClassNameStatus = STATUS_OK; - fBaseClassesStatus = STATUS_OK; - fMethodStubsStatus = STATUS_OK; - fHeaderFileStatus = STATUS_OK; - fSourceFileStatus = STATUS_OK; - fLastFocusedField = 0; - - updateEnclosingTypeEnableState(); - updateFileGroupEnableState(); - } - - // -------- UI Creation --------- - - public void createControl(Composite parent) { - initializeDialogUnits(parent); - - Composite composite = new Composite(parent, SWT.NONE); - int nColumns = 4; - - GridLayout layout = new GridLayout(); - layout.numColumns = nColumns; - composite.setLayout(layout); - composite.setLayoutData(new GridData(GridData.FILL_BOTH)); - composite.setFont(parent.getFont()); - - createSourceFolderControls(composite, nColumns); - createEnclosingTypeControls(composite, nColumns); - - createSeparator(composite, nColumns); - - createClassNameControls(composite, nColumns); - createBaseClassesControls(composite, nColumns); - createMethodStubsControls(composite, nColumns); - - createSeparator(composite, nColumns); - - createFileControls(composite, nColumns); - - composite.layout(); - - setErrorMessage(null); - setMessage(null); - setControl(composite); - } - - /** - * Creates a separator line. Expects a GridLayout with at least 1 column. - * - * @param composite the parent composite - * @param nColumns number of columns to span - */ - protected void createSeparator(Composite composite, int nColumns) { - (new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, convertHeightInCharsToPixels(1)); - } - - /** - * Creates the necessary controls (label, text field and browse button) to edit - * the source folder location. The method expects that the parent composite - * uses a GridLayout as its layout manager and that the - * grid layout has at least 3 columns. - * - * @param parent the parent composite - * @param nColumns the number of columns to span. This number must be - * greater or equal three - */ - protected void createSourceFolderControls(Composite parent, int nColumns) { - fSourceFolderDialogField.doFillIntoGrid(parent, nColumns); - Text textControl = fSourceFolderDialogField.getTextControl(null); - LayoutUtil.setWidthHint(textControl, getMaxFieldWidth()); - textControl.addFocusListener(new StatusFocusListener(SOURCE_FOLDER_ID)); - } - - /** - * Creates the controls for the enclosing class name field. Expects a GridLayout with at - * least 4 columns. - * - * @param composite the parent composite - * @param nColumns number of columns to span - */ - protected void createEnclosingTypeControls(Composite composite, int nColumns) { - Composite tabGroup= new Composite(composite, SWT.NONE); - GridLayout layout= new GridLayout(); - layout.marginWidth= 0; - layout.marginHeight= 0; - tabGroup.setLayout(layout); - - fEnclosingTypeSelection.doFillIntoGrid(tabGroup, 1); - - Text textControl= fEnclosingTypeDialogField.getTextControl(composite); - GridData gd= new GridData(GridData.FILL_HORIZONTAL); - gd.widthHint= getMaxFieldWidth(); - gd.horizontalSpan= 2; - textControl.setLayoutData(gd); - textControl.addFocusListener(new StatusFocusListener(ENCLOSING_TYPE_ID)); - - Button button= fEnclosingTypeDialogField.getChangeControl(composite); - gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL); - gd.heightHint = SWTUtil.getButtonHeigthHint(button); - gd.widthHint = SWTUtil.getButtonWidthHint(button); - button.setLayoutData(gd); - -// fEnclosingTypeSelection.doFillIntoGrid(composite, 1); -// GridData gd; -// Control buttonGroup = fEnclosingTypeButtons.getSelectionButtonsGroup(composite); -// gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); -// gd.widthHint = convertWidthInCharsToPixels(32); -// gd.horizontalSpan = nColumns - 2; -// buttonGroup.setLayoutData(gd); -// DialogField.createEmptySpace(composite, 1); -// -// DialogField.createEmptySpace(composite, 1); -// -// Text textControl = fEnclosingTypeDialogField.getTextControl(composite); -// gd = new GridData(GridData.FILL_HORIZONTAL); -// gd.horizontalSpan = 2; -// textControl.setLayoutData(gd); -// textControl.addFocusListener(new StatusFocusListener(ENCLOSING_TYPE_ID)); -// -// Button button = fEnclosingTypeDialogField.getChangeControl(composite); -// gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); -// gd.heightHint = SWTUtil.getButtonHeigthHint(button); -// button.setLayoutData(gd); -// -// DialogField.createEmptySpace(composite, 1); -// -// buttonGroup = fEnclosingClassAccessButtons.getSelectionButtonsGroup(composite); -// gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); -// gd.widthHint = convertWidthInCharsToPixels(42); -// gd.horizontalSpan = nColumns - 2; -// buttonGroup.setLayoutData(gd); -// DialogField.createEmptySpace(composite, 1); - } - - /** - * Creates the controls for the type name field. Expects a GridLayout with at - * least 2 columns. - * - * @param composite the parent composite - * @param nColumns number of columns to span - */ - protected void createClassNameControls(Composite composite, int nColumns) { - fClassNameDialogField.doFillIntoGrid(composite, nColumns - 1); - DialogField.createEmptySpace(composite); - Text textControl = fClassNameDialogField.getTextControl(null); - LayoutUtil.setWidthHint(textControl, getMaxFieldWidth()); - textControl.addFocusListener(new StatusFocusListener(CLASS_NAME_ID)); - } - - /** - * Creates the controls for the base classes field. Expects a GridLayout with - * at least 3 columns. - * - * @param composite the parent composite - * @param nColumns number of columns to span - */ - protected void createBaseClassesControls(Composite composite, int nColumns) { - fBaseClassesDialogField.doFillIntoGrid(composite, nColumns); - Control listControl = fBaseClassesDialogField.getListControl(null); - GridData gd = (GridData) listControl.getLayoutData(); - gd.heightHint = convertHeightInCharsToPixels(5); - gd.grabExcessVerticalSpace = false; - gd.widthHint = getMaxFieldWidth(); - listControl.addFocusListener(new StatusFocusListener(BASE_CLASSES_ID)); - } - - /** - * Creates the controls for the base classes field. Expects a GridLayout with - * at least 4 columns. - * - * @param composite the parent composite - * @param nColumns number of columns to span - */ - protected void createMethodStubsControls(Composite composite, int nColumns) { - fMethodStubsDialogField.doFillIntoGrid(composite, nColumns); - Control listControl = fMethodStubsDialogField.getListControl(null); - GridData gd = (GridData) listControl.getLayoutData(); - gd.heightHint = convertHeightInCharsToPixels(5); - gd.grabExcessVerticalSpace = false; - gd.widthHint = getMaxFieldWidth(); - listControl.addFocusListener(new StatusFocusListener(METHOD_STUBS_ID)); - } - - /** - * Creates the controls for the enclosing class name field. Expects a GridLayout with at - * least 4 columns. - * - * @param composite the parent composite - * @param nColumns number of columns to span - */ - protected void createFileControls(Composite composite, int nColumns) { - Composite tabGroup = new Composite(composite, SWT.NONE); - GridLayout layout = new GridLayout(); - layout.marginWidth = 0; - layout.marginHeight = 0; - tabGroup.setLayout(layout); - - fUseDefaultSelection.doFillIntoGrid(tabGroup, 1); - - LayoutUtil.setHorizontalSpan(fHeaderFileDialogField.getLabelControl(composite), 1); - Text textControl = fHeaderFileDialogField.getTextControl(composite); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); - gd.widthHint = getMaxFieldWidth(); - gd.horizontalSpan = 1; - textControl.setLayoutData(gd); - textControl.addFocusListener(new StatusFocusListener(HEADER_FILE_ID)); - - Button button = fHeaderFileDialogField.getChangeControl(composite); - gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); - gd.heightHint = SWTUtil.getButtonHeigthHint(button); - gd.widthHint = SWTUtil.getButtonWidthHint(button); - button.setLayoutData(gd); - - DialogField.createEmptySpace(composite, 1); - - LayoutUtil.setHorizontalSpan(fSourceFileDialogField.getLabelControl(composite), 1); - textControl = fSourceFileDialogField.getTextControl(composite); - gd = new GridData(GridData.FILL_HORIZONTAL); - gd.widthHint = getMaxFieldWidth(); - gd.horizontalSpan = 1; - textControl.setLayoutData(gd); - textControl.addFocusListener(new StatusFocusListener(SOURCE_FILE_ID)); - - button = fSourceFileDialogField.getChangeControl(composite); - gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); - gd.heightHint = SWTUtil.getButtonHeigthHint(button); - gd.widthHint = SWTUtil.getButtonWidthHint(button); - button.setLayoutData(gd); - } - - /** - * The wizard owning this page is responsible for calling this method with the - * current selection. The selection is used to initialize the fields of the wizard - * page. - * - * @param selection used to initialize the fields - */ - public void init(IStructuredSelection selection) { - ICElement celem = getInitialCElement(selection); - initFields(celem); - doStatusUpdate(); - - //TODO restore dialog settings for method stubs - // IDialogSettings section = getDialogSettings().getSection(PAGE_NAME); - // if (section != null) { - // enabled = section.getBoolean(stubName); - // } - } - - /** - * Utility method to inspect a selection to find a C element. - * - * @param selection the selection to be inspected - * @return a C element to be used as the initial selection, or null, - * if no C element exists in the given selection - */ - protected ICElement getInitialCElement(IStructuredSelection selection) { - ICElement celem = null; - if (selection != null && !selection.isEmpty()) { - Object selectedElement = selection.getFirstElement(); - if (selectedElement instanceof IAdaptable) { - IAdaptable adaptable = (IAdaptable) selectedElement; - - celem = (ICElement) adaptable.getAdapter(ICElement.class); - if (celem == null) { - IResource resource = (IResource) adaptable.getAdapter(IResource.class); - if (resource != null && resource.getType() != IResource.ROOT) { - while (celem == null && resource.getType() != IResource.PROJECT) { - resource = resource.getParent(); - celem = (ICElement) resource.getAdapter(ICElement.class); - } - if (celem == null) { - celem = CoreModel.getDefault().create(resource); // c project - } - } - } - } - } - if (celem == null) { - IWorkbenchPart part = CUIPlugin.getActivePage().getActivePart(); - if (part instanceof ContentOutline) { - part = CUIPlugin.getActivePage().getActiveEditor(); - } - - if (part instanceof IViewPartInputProvider) { - Object elem = ((IViewPartInputProvider)part).getViewPartInput(); - if (elem instanceof ICElement) { - celem = (ICElement) elem; - } - } - - if (celem == null && part instanceof CEditor) { - IEditorInput input = ((IEditorPart)part).getEditorInput(); - if (input != null) { - final IResource res = (IResource) input.getAdapter(IResource.class); - if (res != null && res instanceof IFile) { - celem = CoreModel.getDefault().create((IFile)res); - } - } - } - } - - if (celem == null || celem.getElementType() == ICElement.C_MODEL) { - try { - ICProject[] projects = CoreModel.create(getWorkspaceRoot()).getCProjects(); - if (projects.length == 1) { - celem = projects[0]; - } - } catch (CModelException e) { - CUIPlugin.getDefault().log(e); - } - } - return celem; - } - - /** - * Initializes all fields provided by the page with a given selection. - * - * @param elem the selection used to initialize this page or - * null if no selection was available - */ - protected void initFields(ICElement elem) { - ICElement enclosingElem = initEnclosingType(elem); - initSourceFolder(enclosingElem != null ? enclosingElem : elem); - - IQualifiedTypeName className = null; - ITextSelection selection = getCurrentTextSelection(); - if (selection != null) { - String text = selection.getText(); - if (text != null && text.length() > 0 && CConventions.validateClassName(text).isOK()) { - className = new QualifiedTypeName(text); - } - } - - setClassTypeName(className, false); - addMethodStub(new ConstructorMethodStub(), true); - addMethodStub(new DestructorMethodStub(), true); - setFileGroupSelection(true, true); - handleFieldChanged(ALL_FIELDS); - } - - /** - * Initializes the source folder field. - * - * @param elem the C element used to compute the initial folder - */ - protected void initSourceFolder(ICElement elem) { - ICContainer folder = null; - if (elem != null) { - folder = CModelUtil.getSourceFolder(elem); - if (folder == null) { - ICProject cproject = elem.getCProject(); - if (cproject != null) { - try { - if (cproject.exists()) { - ISourceRoot[] roots = cproject.getSourceRoots(); - if (roots != null && roots.length > 0) - folder = roots[0]; - } - } catch (CModelException e) { - CUIPlugin.getDefault().log(e); - } - if (folder == null) { - folder = cproject.findSourceRoot(cproject.getResource()); - } - } - } - } - setSourceFolderFullPath(folder != null ? folder.getResource().getFullPath() : null, false); - } - - /** - * Initializes the enclosing type field. - * - * @param elem the C element used to compute the enclosing type - */ - protected ICElement initEnclosingType(ICElement elem) { - ICElement enclosingElem = null; - while (elem != null) { - if (elem.getElementType() == ICElement.C_NAMESPACE - || elem.getElementType() == ICElement.C_CLASS) { - enclosingElem = elem; - break; - } - elem = elem.getParent(); - } - IQualifiedTypeName enclosingTypeName = null; - boolean isNamespace = true; - if (enclosingElem != null) { - enclosingTypeName = TypeUtil.getFullyQualifiedName(enclosingElem); - isNamespace = TypeUtil.isNamespace(enclosingElem); - } - setEnclosingTypeName(enclosingTypeName, isNamespace, false); - setEnclosingTypeSelection((enclosingElem != null), true); - return enclosingElem; - } - - /** - * 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(MAX_FIELD_CHARS); - } - - /** - * Returns the test selection of the current editor. null is returned - * when the current editor does not have focus or does not return a text selection. - * @return Returns the test selection of the current editor or null. - * - * @since 3.0 - */ - protected ITextSelection getCurrentTextSelection() { - IWorkbenchPart part = CUIPlugin.getActivePage().getActivePart(); - if (part instanceof IEditorPart) { - ISelectionProvider selectionProvider = part.getSite().getSelectionProvider(); - if (selectionProvider != null) { - ISelection selection = selectionProvider.getSelection(); - if (selection instanceof ITextSelection) { - return (ITextSelection) selection; - } - } - } - return null; - } - - /** - * Sets the focus to the source folder's text field. - */ - protected void setFocusOnSourceFolder() { - fSourceFolderDialogField.setFocus(); - } - - private final class StatusFocusListener implements FocusListener { - private int fieldID; - - public StatusFocusListener(int fieldID) { - this.fieldID = fieldID; - } - public void focusGained(FocusEvent e) { - fLastFocusedField = this.fieldID; - doStatusUpdate(); - } - - public void focusLost(FocusEvent e) { - fLastFocusedField = 0; - doStatusUpdate(); - } - } - - private class SourceFolderFieldAdapter implements IStringButtonAdapter, IDialogFieldListener { - public void changeControlPressed(DialogField field) { - IPath oldFolderPath = getSourceFolderFullPath(); - IPath newFolderPath = chooseSourceFolder(oldFolderPath); - if (newFolderPath != null) { - IPath headerPath = getHeaderFileFullPath(); - IPath sourcePath = getSourceFileFullPath(); - setSourceFolderFullPath(newFolderPath, false); - if (!isUseDefaultSelected()) { - if (oldFolderPath != null && oldFolderPath.matchingFirstSegments(newFolderPath) == 0) { - if (headerPath != null) { - headerPath = newFolderPath.append(headerPath.lastSegment()); - } - if (sourcePath != null) { - sourcePath = newFolderPath.append(sourcePath.lastSegment()); - } - } - // adjust the relative paths - setHeaderFileFullPath(headerPath, false); - setSourceFileFullPath(sourcePath, false); - } - handleFieldChanged(SOURCE_FOLDER_ID|ALL_FIELDS); - } - } - - public void dialogFieldChanged(DialogField field) { - handleFieldChanged(SOURCE_FOLDER_ID|ALL_FIELDS); - } - } - - private class EnclosingTypeFieldAdapter implements IStringButtonAdapter, IDialogFieldListener { - public void changeControlPressed(DialogField field) { - if (field == fEnclosingTypeDialogField) { - ITypeInfo enclosingType = null; -// boolean isNamespace = isNamespaceButtonSelected(); - boolean isNamespace = true; -// if (isNamespace) { - enclosingType = chooseNamespace(); -// } else { -// enclosingType = chooseEnclosingClass(); -// } - if (enclosingType != null) { - int changedFields = ENCLOSING_TYPE_ID|CLASS_NAME_ID; - IPath oldFolderPath = getSourceFolderFullPath(); - if (oldFolderPath == null) { - IPath headerPath = getHeaderFileFullPath(); - IPath sourcePath = getSourceFileFullPath(); - IPath newFolderPath = updateSourceFolderFromPath(enclosingType.getEnclosingProject().getFullPath()); - if (newFolderPath != null) { - changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID; - // adjust the relative paths - if (oldFolderPath != null && oldFolderPath.matchingFirstSegments(newFolderPath) == 0) { - if (headerPath != null) { - headerPath = newFolderPath.append(headerPath.lastSegment()); - } - if (sourcePath != null) { - sourcePath = newFolderPath.append(sourcePath.lastSegment()); - } - } - setSourceFolderFullPath(newFolderPath, false); - // adjust the relative paths - setHeaderFileFullPath(headerPath, false); - setSourceFileFullPath(sourcePath, false); - } - } - IQualifiedTypeName typeName = enclosingType.getQualifiedTypeName(); - setEnclosingTypeName(typeName, isNamespace, false); - handleFieldChanged(changedFields); - } - } - } - - public void dialogFieldChanged(DialogField field) { -// if (field == fEnclosingTypeSelection || field == fEnclosingTypeButtons) { - if (field == fEnclosingTypeSelection) { - updateEnclosingTypeEnableState(); - } - handleFieldChanged(ENCLOSING_TYPE_ID|CLASS_NAME_ID); - } - } - - private class ClassNameFieldAdapter implements IDialogFieldListener { - public void dialogFieldChanged(DialogField field) { - int changedFields = CLASS_NAME_ID; - if (isUseDefaultSelected()) { - updateFilesFromClassName(fClassNameDialogField.getText()); - changedFields |= (HEADER_FILE_ID|SOURCE_FILE_ID); - } - handleFieldChanged(changedFields); - } - } - - private static final int MAX_UNIQUE_CLASSNAME = 99; - - private String findUniqueName(String className) { - IPath folderPath = getSourceFolderFullPath(); - if (folderPath == null) - return className; - - String currName = className; - int count = 0; - String separator = ""; //$NON-NLS-1$ - //TODO could have a prefs option for how unique file names are generated - if (Character.isDigit(className.charAt(className.length()-1))) - separator = "_"; //$NON-NLS-1$ - while (count < MAX_UNIQUE_CLASSNAME) { - String headerfileName = NewSourceFileGenerator.generateHeaderFileNameFromClass(currName); - String sourcefileName = NewSourceFileGenerator.generateSourceFileNameFromClass(currName); - IPath path = folderPath.append(headerfileName); - if (!path.toFile().exists()) { - path = folderPath.append(sourcefileName); - if (!path.toFile().exists()) { - return currName; - } - } - ++count; - currName = className + separator + count; //$NON-NLS-1$ - } - return null; - } - - void updateFilesFromClassName(String className) { - String headerName = ""; //$NON-NLS-1$ - String sourceName = ""; //$NON-NLS-1$ - if (className.length() > 0) { - className = findUniqueName(className); - if (className != null) { - headerName = NewSourceFileGenerator.generateHeaderFileNameFromClass(className); - sourceName = NewSourceFileGenerator.generateSourceFileNameFromClass(className); - } - } - fHeaderFileDialogField.setTextWithoutUpdate(headerName); - fSourceFileDialogField.setTextWithoutUpdate(sourceName); - } - - private final class BaseClassesFieldAdapter implements IListAdapter { - public void customButtonPressed(ListDialogField field, int index) { - if (index == 0) { - chooseBaseClasses(); - } - handleFieldChanged(BASE_CLASSES_ID); - } - - public void selectionChanged(ListDialogField field) { - } - - public void doubleClicked(ListDialogField field) { - } - } - - private final class MethodStubsFieldAdapter implements IListAdapter { - - public void customButtonPressed(ListDialogField field, int index) { - } - - public void selectionChanged(ListDialogField field) { - } - - public void doubleClicked(ListDialogField field) { - } - } - - private class FileGroupFieldAdapter implements IStringButtonAdapter, IDialogFieldListener { - public void changeControlPressed(DialogField field) { - IPath filePath = null; - IPath headerPath = getHeaderFileFullPath(); - IPath sourcePath = getSourceFileFullPath(); - if (field == fHeaderFileDialogField) { - filePath = chooseHeaderFile(); - if (filePath != null) { - headerPath = filePath; - } - } else if (field == fSourceFileDialogField) { - filePath = chooseSourceFile(); - if (filePath != null) { - sourcePath = filePath; - } - } - if (filePath != null) { - IPath folderPath = null; - int changedFields = 0; - int headerSegments = 0; - int sourceSegments = 0; - if (headerPath != null) - headerSegments = filePath.matchingFirstSegments(headerPath); - if (sourcePath != null) - sourceSegments = filePath.matchingFirstSegments(sourcePath); - int segments = Math.min(headerSegments, sourceSegments); - if (segments > 0) { - IPath newFolderPath = filePath.uptoSegment(segments); - folderPath = updateSourceFolderFromPath(newFolderPath); - } - if (folderPath != null) { - changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID; - // adjust the relative paths - setSourceFolderFullPath(folderPath, false); - setHeaderFileFullPath(headerPath, false); - setSourceFileFullPath(sourcePath, false); - } - if (field == fHeaderFileDialogField) { - setHeaderFileFullPath(filePath, false); - changedFields |= HEADER_FILE_ID; - } else if (field == fSourceFileDialogField) { - setSourceFileFullPath(filePath, false); - changedFields |= SOURCE_FILE_ID; - } - handleFieldChanged(changedFields); - } - } - - public void dialogFieldChanged(DialogField field) { - int changedFields = 0; - if (field == fUseDefaultSelection) { - boolean enabled = !isUseDefaultSelected(); - fHeaderFileDialogField.setEnabled(enabled); - fSourceFileDialogField.setEnabled(enabled); - if (!enabled) { - updateFilesFromClassName(fClassNameDialogField.getText()); - } - changedFields = HEADER_FILE_ID | SOURCE_FILE_ID; - updateFileGroupEnableState(); - } - if (field == fHeaderFileDialogField) { - changedFields |= HEADER_FILE_ID; - } else if (field == fSourceFileDialogField) { - changedFields |= SOURCE_FILE_ID; - } - handleFieldChanged(changedFields); - } - } - - // ----------- validation ---------- - - /** - * This method is a hook which gets called after the source folder's - * text input field has changed. This default implementation updates - * the model and returns an error status. The underlying model - * is only valid if the returned status is OK. - * - * @return the model's error status - */ - protected IStatus sourceFolderChanged() { - StatusInfo status = new StatusInfo(); - - IPath folderPath = getSourceFolderFullPath(); - if (folderPath == null) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterSourceFolderName")); //$NON-NLS-1$ - return status; - } - - IResource res = fWorkspaceRoot.findMember(folderPath); - 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("NewClassCreationWizardPage.error.NotAFolder", folderPath)); //$NON-NLS-1$ - return status; - } - if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) { - if (resType == IResource.PROJECT) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.NotACProject")); //$NON-NLS-1$ - return status; - } - status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.NotInACProject")); //$NON-NLS-1$ - } - ICElement e = CoreModel.getDefault().create(res.getFullPath()); - if (CModelUtil.getSourceFolder(e) == null) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.NotASourceFolder", folderPath)); //$NON-NLS-1$ - return status; - } - } else { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.NotAFolder", folderPath)); //$NON-NLS-1$ - return status; - } - } else { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.FolderDoesNotExist", folderPath)); //$NON-NLS-1$ - return status; - } - - return status; - } - - /** - * This method is a hook which gets called after the enclosing type - * text input field has changed. This default implementation updates - * the model and returns an error status. The underlying model - * is only valid if the returned status is OK. - * - * @return the model's error status - */ - protected IStatus enclosingTypeChanged() { - StatusInfo status = new StatusInfo(); - if (!isEnclosingTypeSelected()) { - return status; - } -// if (isNamespaceButtonSelected()) { - return namespaceChanged(); -// } else { -// return enclosingClassChanged(); -// } - } - - private IStatus namespaceChanged() { - StatusInfo status = new StatusInfo(); - - // must not be empty - IQualifiedTypeName typeName = getEnclosingTypeName(); - if (typeName == null) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterNamespace")); //$NON-NLS-1$ - return status; - } - - IStatus val = CConventions.validateNamespaceName(typeName.toString()); - if (val.getSeverity() == IStatus.ERROR) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidNamespace", val.getMessage())); //$NON-NLS-1$ - return status; - } else if (val.getSeverity() == IStatus.WARNING) { - status.setWarning(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.warning.NamespaceDiscouraged", val.getMessage())); //$NON-NLS-1$ - } - - IProject project = getCurrentProject(); - if (project != null) { - prepareTypeCache(); - - if (typeName.isQualified()) { - // make sure enclosing namespace exists - ITypeInfo parentNamespace = AllTypesCache.getType(project, ICElement.C_NAMESPACE, typeName.getEnclosingTypeName()); - if (parentNamespace == null) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnclosingNamespaceNotExists")); //$NON-NLS-1$ - return status; - } - } - - ITypeInfo[] types = AllTypesCache.getTypes(project, typeName, false, true); - if (types.length > 0) { - // look for namespace - boolean foundNamespace = false; - boolean exactMatch = false; - for (int i = 0; i < types.length; ++i) { - ITypeInfo currType = types[i]; - if (currType.getCElementType() == ICElement.C_NAMESPACE) { - foundNamespace = true; - exactMatch = currType.getQualifiedTypeName().equals(typeName); - if (exactMatch) { - // found a matching namespace - break; - } - } - } - if (foundNamespace) { - if (exactMatch) { - // we're good to go - status.setOK(); - } else { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.NamespaceExistsDifferentCase")); //$NON-NLS-1$ - } - return status; - } - // look for other types - exactMatch = false; - for (int i = 0; i < types.length; ++i) { - ITypeInfo currType = types[i]; - if (currType.getCElementType() != ICElement.C_NAMESPACE) { - exactMatch = currType.getQualifiedTypeName().equals(typeName); - if (exactMatch) { - // found a matching type - break; - } - } - } - if (exactMatch) { - status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.TypeMatchingNamespaceExists")); //$NON-NLS-1$ - } else { - status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.TypeMatchingNamespaceExistsDifferentCase")); //$NON-NLS-1$ - } - } else { - status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.NamespaceNotExists")); //$NON-NLS-1$ - } - } - - val = CConventions.validateNamespaceName(typeName.lastSegment()); - if (val.getSeverity() == IStatus.ERROR) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidNamespace", val.getMessage())); //$NON-NLS-1$ - return status; - } - - return status; - } - -/* private IStatus enclosingClassChanged() { - StatusInfo status = new StatusInfo(); - - // must not be empty - IQualifiedTypeName typeName = getEnclosingTypeName(); - if (typeName == null) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterEnclosingClassName")); //$NON-NLS-1$ - return status; - } - - IStatus val = CConventions.validateClassName(typeName.toString()); - if (val.getSeverity() == IStatus.ERROR) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidEnclosingClassName", val.getMessage())); //$NON-NLS-1$ - return status; - } - - IProject project = getCurrentProject(); - if (project != null) { - prepareTypeCache(); - - ITypeInfo[] types = AllTypesCache.getTypes(project, typeName, false, true); - if (types.length > 0) { - // look for class - boolean foundClass = false; - boolean exactMatch = false; - for (int i = 0; i < types.length; ++i) { - ITypeInfo currType = types[i]; - if (currType.getCElementType() == ICElement.C_CLASS) { - foundClass = true; - exactMatch = currType.getQualifiedTypeName().equals(typeName); - if (exactMatch) { - // found a matching class - break; - } - } - } - if (foundClass) { - if (exactMatch) { - // we're good to go - status.setOK(); - } else { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnclosingClassExistsDifferentCase")); //$NON-NLS-1$ - } - return status; - } - } - - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnclosingClassNotExists")); //$NON-NLS-1$ - } - - return status; - } -*/ - /** - * Hook method that gets called when the class name has changed. The method validates the - * class name and returns the status of the validation. - * - * @return the status of the validation - */ - protected IStatus classNameChanged() { - StatusInfo status = new StatusInfo(); - - IQualifiedTypeName className = getClassTypeName(); - // must not be empty - if (className == null) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterClassName")); //$NON-NLS-1$ - return status; - } - if (className.isQualified()) { //$NON-NLS-1$ - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.QualifiedClassName")); //$NON-NLS-1$ - return status; - } - - IStatus val = CConventions.validateClassName(className.toString()); - if (val.getSeverity() == IStatus.ERROR) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidClassName", val.getMessage())); //$NON-NLS-1$ - return status; - } else if (val.getSeverity() == IStatus.WARNING) { - status.setWarning(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.warning.ClassNameDiscouraged", val.getMessage())); //$NON-NLS-1$ - // continue checking - } - - IProject project = getCurrentProject(); - if (project != null) { - prepareTypeCache(); - - IQualifiedTypeName fullyQualifiedName = className; - if (isEnclosingTypeSelected()) { - IQualifiedTypeName enclosing = getEnclosingTypeName(); - if (enclosing != null) { - fullyQualifiedName = enclosing.append(className); - } - } - - ITypeInfo[] types = AllTypesCache.getTypes(project, fullyQualifiedName, false, true); - if (types.length > 0) { - // look for class - boolean foundClass = false; - boolean exactMatch = false; - for (int i = 0; i < types.length; ++i) { - ITypeInfo currType = types[i]; - if (currType.getCElementType() == ICElement.C_CLASS - || currType.getCElementType() == ICElement.C_STRUCT) { - foundClass = true; - exactMatch = currType.getQualifiedTypeName().equals(fullyQualifiedName); - if (exactMatch) { - // found a matching class - break; - } - } - } - if (foundClass) { - if (exactMatch) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.ClassNameExists")); //$NON-NLS-1$ - } else { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.ClassNameExistsDifferentCase")); //$NON-NLS-1$ - } - return status; - } - // look for other types - exactMatch = false; - for (int i = 0; i < types.length; ++i) { - ITypeInfo currType = types[i]; - if (currType.getCElementType() != ICElement.C_CLASS - && currType.getCElementType() != ICElement.C_STRUCT) { - exactMatch = currType.getQualifiedTypeName().equals(fullyQualifiedName); - if (exactMatch) { - // found a matching type - break; - } - } - } - if (exactMatch) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.TypeMatchingClassExists")); //$NON-NLS-1$ - } else { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.TypeMatchingClassExistsDifferentCase")); //$NON-NLS-1$ - } - return status; - } - } - return status; - } - - /** - * Hook method that gets called when the list of base classes has changed. The method - * validates the base classes and returns the status of the validation. - *

- * Subclasses may extend this method to perform their own validation. - *

- * - * @return the status of the validation - */ - protected IStatus baseClassesChanged() { - StatusInfo status = new StatusInfo(); - if (fErrorIfBaseClassNotInPath) { - IPath folderPath = getSourceFolderFullPath(); - if (folderPath != null) { - // make sure all classes belong to the project - IBaseClassInfo[] baseClasses = getBaseClasses(); - if (baseClasses != null && baseClasses.length > 0) { - // filter out classes not reachable from current source folder - IProject project = PathUtil.getEnclosingProject(folderPath); - IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project); - if (provider != null) { - //TODO get the scanner info for the actual source folder - IScannerInfo info = provider.getScannerInformation(project); - if (info != null) { - String[] includePaths = info.getIncludePaths(); - for (int i = 0; i < baseClasses.length; ++i) { - ITypeInfo baseType = baseClasses[i].getType(); - if (!isTypeReachable(baseType, project, includePaths)) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.BaseClassNotExistsInProject", baseType.getQualifiedTypeName().toString())); //$NON-NLS-1$ - return status; - } - } - } - } - } - } - } - return status; - } - - private boolean isTypeReachable(ITypeInfo type, IProject project, String[] includePaths) { - IProject baseProject = type.getEnclosingProject(); - if (baseProject != null) { - if (baseProject.equals(project)) { - return true; - } - ITypeReference ref = type.getResolvedReference(); - for (int i = 0; i < includePaths.length; ++i) { - IPath includePath = new Path(includePaths[i]); - if (ref != null) { - if (includePath.isPrefixOf(ref.getLocation())) - return true; - } else { - // we don't have the real location, so just check the project path - if (baseProject.getLocation().isPrefixOf(includePath)) - return true; - } - } - } - return false; - } - - - /** - * This method is a hook which gets called after the method stubs - * input field has changed. This default implementation updates - * the model and returns an error status. The underlying model - * is only valid if the returned status is OK. - * - * @return the model's error status - */ - protected IStatus methodStubsChanged() { - StatusInfo status = new StatusInfo(); - return status; - } - - /** - * This method is a hook which gets called after the header file's - * text input field has changed. This default implementation updates - * the model and returns an error status. The underlying model - * is only valid if the returned status is OK. - * - * @return the model's error status - */ - protected IStatus headerFileChanged() { - StatusInfo status = new StatusInfo(); - if (isUseDefaultSelected()) { - return status; - } - - IPath path = getHeaderFileFullPath(); - if (path == null) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterHeaderFileName")); //$NON-NLS-1$ - return status; - } - - IPath sourceFolderPath = getSourceFolderFullPath(); - if (sourceFolderPath == null || !sourceFolderPath.isPrefixOf(path)) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.HeaderFileNotInSourceFolder")); //$NON-NLS-1$ - return status; - } - - boolean fileExists = false; - // check if file already exists - IResource file = getWorkspaceRoot().findMember(path); - if (file != null && file.exists()) { - if (file.getType() == IResource.FILE) { - IProject proj = file.getProject(); - if (!proj.isOpen()) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.NotAFile", path)); //$NON-NLS-1$ - return status; - } - - fileExists = true; - if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) { - status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.NotInACProject")); //$NON-NLS-1$ - } else { - status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.HeaderFileExists")); //$NON-NLS-1$ - } - } else { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.NotAFile")); //$NON-NLS-1$ - return status; - } - } - - // check if folder exists - IPath folderPath = path.removeLastSegments(1).makeRelative(); - IResource folder = getWorkspaceRoot().findMember(folderPath); - if (folder == null || !folder.exists() || (folder.getType() != IResource.PROJECT && folder.getType() != IResource.FOLDER)) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.FolderDoesNotExist", folderPath)); //$NON-NLS-1$ - return status; - } - - if (!fileExists) { - IStatus val = CConventions.validateHeaderFileName(getCurrentProject(), path.lastSegment()); - if (val.getSeverity() == IStatus.ERROR) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidHeaderFileName", val.getMessage())); //$NON-NLS-1$ - return status; - } else if (val.getSeverity() == IStatus.WARNING) { - status.setWarning(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.warning.HeaderFileNameDiscouraged", val.getMessage())); //$NON-NLS-1$ - } - } - return status; - } - - /** - * This method is a hook which gets called after the source file's - * text input field has changed. This default implementation updates - * the model and returns an error status. The underlying model - * is only valid if the returned status is OK. - * - * @return the model's error status - */ - protected IStatus sourceFileChanged() { - StatusInfo status = new StatusInfo(); - if (isUseDefaultSelected()) { - return status; - } - - IPath path = getSourceFileFullPath(); - if (path == null) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterSourceFileName")); //$NON-NLS-1$ - return status; - } - - IPath sourceFolderPath = getSourceFolderFullPath(); - if (sourceFolderPath == null || !sourceFolderPath.isPrefixOf(path)) { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.SourceFileNotInSourceFolder")); //$NON-NLS-1$ - return status; - } - - boolean fileExists = false; - // check if file already exists - IResource file = getWorkspaceRoot().findMember(path); - if (file != null && file.exists()) { - if (file.getType() == IResource.FILE) { - IProject proj = file.getProject(); - if (!proj.isOpen()) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.NotAFile", path)); //$NON-NLS-1$ - return status; - } - - fileExists = true; - if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) { - status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.NotInACProject")); //$NON-NLS-1$ - } else { - status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.SourceFileExists")); //$NON-NLS-1$ - } - } else { - status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.NotAFile")); //$NON-NLS-1$ - return status; - } - } - - // check if folder exists - IPath folderPath = path.removeLastSegments(1).makeRelative(); - IResource folder = getWorkspaceRoot().findMember(folderPath); - if (folder == null || !folder.exists() || (folder.getType() != IResource.PROJECT && folder.getType() != IResource.FOLDER)) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.FolderDoesNotExist", folderPath)); //$NON-NLS-1$ - return status; - } - - if (!fileExists) { - IStatus val = CConventions.validateSourceFileName(getCurrentProject(), path.lastSegment()); - if (val.getSeverity() == IStatus.ERROR) { - status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidSourceFileName", val.getMessage())); //$NON-NLS-1$ - return status; - } else if (val.getSeverity() == IStatus.WARNING) { - status.setWarning(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.warning.SourceFileNameDiscouraged", val.getMessage())); //$NON-NLS-1$ - } - } - return status; - } - - /** - * Hook method that gets called when a field on this page has changed. - * - * @param fields Bitwise-OR'd ids of the fields that changed. - */ - protected void handleFieldChanged(int fields) { - if (fields == 0) - return; // no change - - if (fieldChanged(fields, SOURCE_FOLDER_ID)) { - fSourceFolderStatus = sourceFolderChanged(); - } - if (fieldChanged(fields, ENCLOSING_TYPE_ID)) { - fEnclosingTypeStatus = enclosingTypeChanged(); - } - if (fieldChanged(fields, CLASS_NAME_ID)) { - fClassNameStatus = classNameChanged(); - } - if (fieldChanged(fields, BASE_CLASSES_ID)) { - fBaseClassesStatus = baseClassesChanged(); - } - if (fieldChanged(fields, METHOD_STUBS_ID)) { - fMethodStubsStatus = methodStubsChanged(); - } - if (fieldChanged(fields, HEADER_FILE_ID)) { - fHeaderFileStatus = headerFileChanged(); - } - if (fieldChanged(fields, SOURCE_FILE_ID)) { - fSourceFileStatus = sourceFileChanged(); - } - doStatusUpdate(); - } - - private boolean fieldChanged(int fields, int fieldID) { - return ((fields & fieldID) != 0); - } - - protected void doStatusUpdate() { - // do the last focused field first - IStatus lastStatus = getLastFocusedStatus(); - - // status of all used components - IStatus[] status = new IStatus[] { - lastStatus, - (fSourceFolderStatus != lastStatus) ? fSourceFolderStatus : STATUS_OK, - (fEnclosingTypeStatus != lastStatus) ? fEnclosingTypeStatus : STATUS_OK, - (fClassNameStatus != lastStatus) ? fClassNameStatus : STATUS_OK, - (fBaseClassesStatus != lastStatus) ? fBaseClassesStatus : STATUS_OK, - (fMethodStubsStatus != lastStatus) ? fMethodStubsStatus : STATUS_OK, - (fHeaderFileStatus != lastStatus) ? fHeaderFileStatus : STATUS_OK, - (fSourceFileStatus != lastStatus) ? fSourceFileStatus : STATUS_OK - }; - - // the mode severe status will be displayed and the ok button enabled/disabled. - updateStatus(status); - } - - private IStatus getLastFocusedStatus() { - switch (fLastFocusedField) { - case SOURCE_FOLDER_ID: - return fSourceFolderStatus; - case ENCLOSING_TYPE_ID: - return fEnclosingTypeStatus; - case CLASS_NAME_ID: - return fClassNameStatus; - case BASE_CLASSES_ID: - return fBaseClassesStatus; - case METHOD_STUBS_ID: - return fMethodStubsStatus; - case HEADER_FILE_ID: - return fHeaderFileStatus; - case SOURCE_FILE_ID: - return fSourceFileStatus; - default: - return STATUS_OK; - } - } - - public IPath getSourceFolderFullPath() { - String text = fSourceFolderDialogField.getText(); - if (text.length() > 0) - return new Path(text).makeAbsolute(); - return null; - } - - public void setSourceFolderFullPath(IPath folderPath, boolean update) { - String str = (folderPath != null) ? folderPath.makeRelative().toString() : ""; //.makeRelative().toString(); //$NON-NLS-1$ - fSourceFolderDialogField.setTextWithoutUpdate(str); - if (update) { - fSourceFolderDialogField.dialogFieldChanged(); - } - } - - private IProject getCurrentProject() { - IPath folderPath = getSourceFolderFullPath(); - if (folderPath != null) { - return PathUtil.getEnclosingProject(folderPath); - } - return null; - } - - private ICElement getSourceFolderFromPath(IPath path) { - if (path == null) - return null; - while (!path.isEmpty()) { - IResource res = fWorkspaceRoot.findMember(path); - if (res != null && res.exists()) { - int resType = res.getType(); - if (resType == IResource.PROJECT || resType == IResource.FOLDER) { - ICElement elem = CoreModel.getDefault().create(res.getFullPath()); - ICContainer sourceFolder = CModelUtil.getSourceFolder(elem); - if (sourceFolder != null) - return sourceFolder; - if (resType == IResource.PROJECT) { - return elem; - } - } - } - path = path.removeLastSegments(1); - } - return null; - } - - /** - * Returns the enclosing type name entered into the enclosing type input field. - * - * @return the enclosing type name - */ - public IQualifiedTypeName getEnclosingTypeName() { - String text = fEnclosingTypeDialogField.getText(); - if (text.length() > 0) - return new QualifiedTypeName(text); - return null; - } - - /** - * Sets the enclosing type name. The method updates the underlying model - * and the text of the control. - * - * @param typeName the enclosing type name - */ - public void setEnclosingTypeName(IQualifiedTypeName typeName, boolean isNamespace, boolean update) { - if (typeName != null) { - fEnclosingTypeDialogField.setTextWithoutUpdate(typeName.toString()); //$NON-NLS-1$ - } else { - fEnclosingTypeDialogField.setTextWithoutUpdate(""); //$NON-NLS-1$ - } -// fEnclosingTypeButtons.setSelection(isNamespace ? CLASS_INDEX : NAMESPACE_INDEX, false); -// fEnclosingTypeButtons.setSelection(isNamespace ? NAMESPACE_INDEX : CLASS_INDEX, true); - if (update) { - fEnclosingTypeDialogField.dialogFieldChanged(); - } - } - - /** - * Returns the selection state of the enclosing class checkbox. - * - * @return the selection state of the enclosing class checkbox - */ - public boolean isEnclosingTypeSelected() { - return fEnclosingTypeSelection.isSelected(); - } - - /** - * Returns the selection state of the enclosing class checkbox. - * - * @return the selection state of the enclosing class checkbox - */ -// public boolean isNamespaceButtonSelected() { -// return fEnclosingTypeButtons.isSelected(NAMESPACE_INDEX); -// } - - /** - * Returns the class name entered into the class input field. - * - * @return the class name - */ - public IQualifiedTypeName getClassTypeName() { - String text = fClassNameDialogField.getText(); - if (text.length() > 0) { - return new QualifiedTypeName(text); - } - return null; - } - - /** - * Sets the class name input field's text to the given value. Method doesn't update - * the model. - * - * @param name the new type name - * @param canBeModified if true the type name field is - * editable; otherwise it is read-only. - */ - public void setClassTypeName(IQualifiedTypeName typeName, boolean update) { - fClassNameDialogField.setTextWithoutUpdate(typeName != null ? typeName.toString() : ""); //$NON-NLS-1$ - if (update) { - fClassNameDialogField.dialogFieldChanged(); - } - } - - /** - * Returns the chosen base classes. - * - * @return array of IBaseClassInfo - */ - public IBaseClassInfo[] getBaseClasses() { - List classesList = fBaseClassesDialogField.getElements(); - return (IBaseClassInfo[]) classesList.toArray(new IBaseClassInfo[classesList.size()]); - } - - /** - * Returns the chosen method stubs. - * - * @return array of IMethodStub or empty array if none selected. - */ - public IMethodStub[] getCheckedMethodStubs() { - return fMethodStubsDialogField.getCheckedMethodStubs(); - } - - /** - * Returns the selection state of the file group checkbox. - * - * @return the selection state of the file group checkbox - */ - public boolean isUseDefaultSelected() { - return fUseDefaultSelection.isSelected(); - } - - /** - * Returns the file path entered into the header file field. - * - * @return the file path - */ - public IPath getHeaderFileFullPath() { - String str = fHeaderFileDialogField.getText(); - IPath path = null; - if (str.length() > 0) { - path = new Path(str); - if (!path.isAbsolute()) { - IPath folderPath = getSourceFolderFullPath(); - if (folderPath != null) - path = folderPath.append(path); - } - } - return path; - } - - /** - * Sets the current header file. - * - * @param path The new header path - */ - public void setHeaderFileFullPath(IPath path, boolean update) { - String str = ""; //$NON-NLS-1$ - if (path != null) { - IPath sourceFolder = getSourceFolderFullPath(); - if (sourceFolder != null) { - IPath relativePath = PathUtil.makeRelativePath(path, sourceFolder); - if (relativePath != null) - path = relativePath; - } - str = path.toString(); - } - fHeaderFileDialogField.setTextWithoutUpdate(str); - if (update) - fHeaderFileDialogField.dialogFieldChanged(); - } - - /** - * Returns the file path entered into the source file field. - * - * @return the file path - */ - public IPath getSourceFileFullPath() { - String str = fSourceFileDialogField.getText(); - IPath path = null; - if (str.length() > 0) { - path = new Path(str); - if (!path.isAbsolute()) { - IPath folderPath = getSourceFolderFullPath(); - if (folderPath != null) - path = folderPath.append(path); - } - } - return path; - } - - /** - * Sets the current source file. - * - * @param path The new source path - */ - public void setSourceFileFullPath(IPath path, boolean update) { - String str = ""; //$NON-NLS-1$ - if (path != null) { - IPath sourceFolder = getSourceFolderFullPath(); - if (sourceFolder != null) { - IPath relativePath = PathUtil.makeRelativePath(path, sourceFolder); - if (relativePath != null) - path = relativePath; - } - str = path.makeRelative().toString(); - } - fSourceFileDialogField.setTextWithoutUpdate(str); - if (update) - fSourceFileDialogField.dialogFieldChanged(); - } - - /** - * Returns the workspace root. - * - * @return the workspace root - */ - protected IWorkspaceRoot getWorkspaceRoot() { - return fWorkspaceRoot; - } - - /* - * @see WizardPage#becomesVisible - */ - public void setVisible(boolean visible) { - super.setVisible(visible); - if (visible) { - setFocus(); - } - } - - /** - * Sets the focus on the type name input field. - */ - protected void setFocus() { - fClassNameDialogField.setFocus(); - } - - public void addBaseClass(ITypeInfo newBaseClass, ASTAccessVisibility access, boolean isVirtual) { - List baseClasses = fBaseClassesDialogField.getElements(); - boolean classExists = false; - if (baseClasses != null) { - for (Iterator i = baseClasses.iterator(); i.hasNext(); ) { - BaseClassInfo info = (BaseClassInfo) i.next(); - if (info.getType().equals(newBaseClass)) { - classExists = true; - break; - } - } - } - if (!classExists) { - prepareTypeCache(); - - // resolve location of base class - if (newBaseClass.getResolvedReference() == null) { - final ITypeInfo[] typesToResolve = new ITypeInfo[] { newBaseClass }; - IRunnableWithProgress runnable = new IRunnableWithProgress() { - public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException { - AllTypesCache.resolveTypeLocation(typesToResolve[0], progressMonitor); - if (progressMonitor.isCanceled()) { - throw new InterruptedException(); - } - } - }; - - try { - getContainer().run(true, true, runnable); - } catch (InvocationTargetException e) { - String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.title"); //$NON-NLS-1$ - String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.message"); //$NON-NLS-1$ - ExceptionHandler.handle(e, title, message); - return; - } catch (InterruptedException e) { - // cancelled by user - return; - } - } - fBaseClassesDialogField.addBaseClass(new BaseClassInfo(newBaseClass, access, isVirtual)); - } - } - - public void addMethodStub(IMethodStub methodStub, boolean checked) { - fMethodStubsDialogField.addMethodStub(methodStub, checked); - } - - void prepareTypeCache() { - final ITypeSearchScope scope = new TypeSearchScope(true); - if (!AllTypesCache.isCacheUpToDate(scope)) { - IRunnableWithProgress runnable = new IRunnableWithProgress() { - public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { - AllTypesCache.updateCache(scope, monitor); - if (monitor.isCanceled()) { - throw new InterruptedException(); - } - } - }; - - try { - getContainer().run(true, true, runnable); - } catch (InvocationTargetException e) { - String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.title"); //$NON-NLS-1$ - String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.message"); //$NON-NLS-1$ - ExceptionHandler.handle(e, title, message); - } catch (InterruptedException e) { - // cancelled by user - } - } - } - - /** - * Sets the enclosing class checkbox's selection state. - * - * @param isSelected the checkbox's selection state - * @param canBeModified if true the enclosing class checkbox is - * modifiable; otherwise it is read-only. - */ - public void setEnclosingTypeSelection(boolean isSelected, boolean canBeModified) { - fEnclosingTypeSelection.setSelection(isSelected); - fEnclosingTypeSelection.setEnabled(canBeModified); - updateEnclosingTypeEnableState(); - } - - /** - * Sets the enclosing class checkbox's selection state. - * - * @param isSelected the checkbox's selection state - * @param canBeModified if true the enclosing class checkbox is - * modifiable; otherwise it is read-only. - */ - public void setFileGroupSelection(boolean isSelected, boolean canBeModified) { - fUseDefaultSelection.setSelection(isSelected); - fUseDefaultSelection.setEnabled(canBeModified); - updateFileGroupEnableState(); - } - - /* - * Updates the enable state of buttons related to the enclosing type selection checkbox. - */ - void updateEnclosingTypeEnableState() { - boolean enclosing = isEnclosingTypeSelected(); - fEnclosingTypeDialogField.setEnabled(enclosing); -// fEnclosingTypeButtons.setEnabled(enclosing); -// fEnclosingClassAccessButtons.setEnabled(enclosing && !isNamespaceButtonSelected()); - } - - /* - * Updates the enable state of buttons related to the file group selection checkbox. - */ - void updateFileGroupEnableState() { - boolean filegroup = !isUseDefaultSelected(); - fHeaderFileDialogField.setEnabled(filegroup); - fSourceFileDialogField.setEnabled(filegroup); - } - - IPath chooseSourceFolder(IPath initialPath) { - ICElement initElement = getSourceFolderFromPath(initialPath); - if (initElement instanceof ISourceRoot) { - ICProject cProject = initElement.getCProject(); - ISourceRoot projRoot = cProject.findSourceRoot(cProject.getProject()); - if (projRoot != null && projRoot.equals(initElement)) - initElement = cProject; - } - - SourceFolderSelectionDialog dialog = new SourceFolderSelectionDialog(getShell()); - dialog.setInput(CoreModel.create(fWorkspaceRoot)); - dialog.setInitialSelection(initElement); - - if (dialog.open() == Window.OK) { - 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.getResource().getFullPath(); - } - return element.getResource().getFullPath(); - } - } - return null; - } - - ITypeInfo chooseNamespace() { - ITypeSearchScope scope; - IProject project = getCurrentProject(); - if (project != null) { - scope = new TypeSearchScope(project); - } else { - scope = new TypeSearchScope(true); - } - - prepareTypeCache(); - - ITypeInfo[] elements = AllTypesCache.getNamespaces(scope, false); - if (elements == null || elements.length == 0) { - String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.noNamespaces.title"); //$NON-NLS-1$ - String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.noNamespaces.message"); //$NON-NLS-1$ - MessageDialog.openInformation(getShell(), title, message); - return null; - } - - NamespaceSelectionDialog dialog = new NamespaceSelectionDialog(getShell()); - dialog.setElements(elements); - int result = dialog.open(); - if (result == IDialogConstants.OK_ID) { - ITypeInfo namespace = (ITypeInfo) dialog.getFirstResult(); -/* if (namespace != null) { - // resolve location of namespace - if (namespace.getResolvedReference() == null) { - final ITypeInfo[] typesToResolve = new ITypeInfo[] { namespace }; - IRunnableWithProgress runnable = new IRunnableWithProgress() { - public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException { - AllTypesCache.resolveTypeLocation(typesToResolve[0], progressMonitor); - if (progressMonitor.isCanceled()) { - throw new InterruptedException(); - } - } - }; - - try { - getContainer().run(true, true, runnable); - } catch (InvocationTargetException e) { - String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.title"); //$NON-NLS-1$ - String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.message"); //$NON-NLS-1$ - ExceptionHandler.handle(e, title, message); - return null; - } catch (InterruptedException e) { - // cancelled by user - return null; - } - } - } -*/ return namespace; - } - - return null; - } - - private final int[] ENCLOSING_CLASS_TYPES = { ICElement.C_CLASS }; - - ITypeInfo chooseEnclosingClass() { - ITypeSearchScope scope; - IProject project = getCurrentProject(); - if (project != null) { - scope = new TypeSearchScope(project); - } else { - scope = new TypeSearchScope(true); - } - - prepareTypeCache(); - - ITypeInfo[] elements = AllTypesCache.getTypes(scope, ENCLOSING_CLASS_TYPES); - if (elements == null || elements.length == 0) { - String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.noClasses.title"); //$NON-NLS-1$ - String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.noClasses.message"); //$NON-NLS-1$ - MessageDialog.openInformation(getShell(), title, message); - return null; - } - - EnclosingClassSelectionDialog dialog = new EnclosingClassSelectionDialog(getShell()); - dialog.setElements(elements); - int result = dialog.open(); - if (result == IDialogConstants.OK_ID) { - ITypeInfo enclosingClass = (ITypeInfo) dialog.getFirstResult(); - if (enclosingClass != null) { - // resolve location of class - if (enclosingClass.getResolvedReference() == null) { - prepareTypeCache(); - - final ITypeInfo[] typesToResolve = new ITypeInfo[] { enclosingClass }; - IRunnableWithProgress runnable = new IRunnableWithProgress() { - public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException { - AllTypesCache.resolveTypeLocation(typesToResolve[0], progressMonitor); - if (progressMonitor.isCanceled()) { - throw new InterruptedException(); - } - } - }; - - try { - getContainer().run(true, true, runnable); - } catch (InvocationTargetException e) { - String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.title"); //$NON-NLS-1$ - String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.message"); //$NON-NLS-1$ - ExceptionHandler.handle(e, title, message); - return null; - } catch (InterruptedException e) { - // cancelled by user - return null; - } - } - } - return enclosingClass; - } - - return null; - } - - void chooseBaseClasses() { - prepareTypeCache(); - - ITypeInfo[] elements = getAllReachableTypes(); - if (elements == null || elements.length == 0) { - String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.noClasses.title"); //$NON-NLS-1$ - String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.noClasses.message"); //$NON-NLS-1$ - MessageDialog.openInformation(getShell(), title, message); - return; - } - - List oldContents = fBaseClassesDialogField.getElements(); - NewBaseClassSelectionDialog dialog = new NewBaseClassSelectionDialog(getShell()); - dialog.addListener(new ITypeSelectionListener() { - public void typeAdded(ITypeInfo newBaseClass) { - addBaseClass(newBaseClass, ASTAccessVisibility.PUBLIC, false); - } - }); - dialog.setElements(elements); - int result = dialog.open(); - if (result != IDialogConstants.OK_ID) { - // restore the old contents - fBaseClassesDialogField.setElements(oldContents); - } - } - - private final int[] CLASS_TYPES = { ICElement.C_CLASS, ICElement.C_STRUCT }; - - private ITypeInfo[] getAllReachableTypes() { - ITypeInfo[] elements = AllTypesCache.getTypes(new TypeSearchScope(true), CLASS_TYPES); - if (elements != null && elements.length > 0) { - // filter out classes not reachable from current source folder - IPath folderPath = getSourceFolderFullPath(); - if (folderPath != null) { - IProject project = PathUtil.getEnclosingProject(folderPath); - IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project); - if (provider != null) { - //TODO get the scanner info for the actual source folder - IScannerInfo info = provider.getScannerInformation(project); - if (info != null) { - String[] includePaths = info.getIncludePaths(); - List filteredTypes = new ArrayList(); - for (int i = 0; i < elements.length; ++i) { - ITypeInfo baseType = elements[i]; - if (isTypeReachable(baseType, project, includePaths)) { - filteredTypes.add(baseType); - } - } - return (ITypeInfo[]) filteredTypes.toArray(new ITypeInfo[filteredTypes.size()]); - } - } - } - } - return elements; - } - - IPath chooseHeaderFile() { - SourceFileSelectionDialog dialog = new SourceFileSelectionDialog(getShell()); - dialog.setTitle(NewClassWizardMessages.getString("NewClassCreationWizardPage.ChooseHeaderFileDialog.title")); //$NON-NLS-1$ - ICElement input = CoreModel.create(fWorkspaceRoot); - IProject project = getCurrentProject(); - if (project != null) - input = CoreModel.getDefault().create(project); - dialog.setInput(input); - - IPath filePath = getHeaderFileFullPath(); - if (filePath != null) { - String folderName = filePath.removeLastSegments(1).toString(); - String fileName = filePath.lastSegment(); - dialog.setInitialSelection(folderName, fileName); - } else { - filePath = getSourceFolderFullPath(); - if (filePath != null) { - dialog.setInitialSelection(filePath.toString(), null); - } - } - - if (dialog.open() == Window.OK) { - return dialog.getFilePath(); - } - return null; - } - - IPath chooseSourceFile() { - SourceFileSelectionDialog dialog = new SourceFileSelectionDialog(getShell()); - dialog.setTitle(NewClassWizardMessages.getString("NewClassCreationWizardPage.ChooseSourceFileDialog.title")); //$NON-NLS-1$ - ICElement input = CoreModel.create(fWorkspaceRoot); - IProject project = getCurrentProject(); - if (project != null) - input = CoreModel.getDefault().create(project); - dialog.setInput(input); - - IPath filePath = getSourceFileFullPath(); - if (filePath != null) { - String folderName = filePath.removeLastSegments(1).toString(); - String fileName = filePath.lastSegment(); - dialog.setInitialSelection(folderName, fileName); - } else { - filePath = getSourceFolderFullPath(); - if (filePath != null) { - dialog.setInitialSelection(filePath.toString(), null); - } - } - - if (dialog.open() == Window.OK) { - return dialog.getFilePath(); - } - return null; - } - - - // ---- creation ---------------- - - /** - * Creates the new class using the entered field values. - * - * @param monitor a progress monitor to report progress. - * @throws CoreException Thrown when the creation failed. - * @throws InterruptedException Thrown when the operation was cancelled. - */ - public void createClass(IProgressMonitor monitor) { - try { - fCodeGenerator = new NewClassCodeGenerator( - getHeaderFileFullPath(), - getSourceFileFullPath(), - getClassTypeName(), - isEnclosingTypeSelected() ? getEnclosingTypeName() : null, - getBaseClasses(), - getCheckedMethodStubs()); - fCodeGenerator.createClass(monitor); - } catch (CodeGeneratorException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (CoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * Returns the created type. The method only returns a valid type - * after createType has been called. - * - * @return the created type - * @see #createClass(IProgressMonitor) - */ - public ICElement getCreatedClass() { - if (fCodeGenerator != null) { - return fCodeGenerator.getCreatedClass(); - } - return null; - } - - public ITranslationUnit getCreatedHeaderTU(){ - if (fCodeGenerator != null) { - return fCodeGenerator.getCreatedHeaderTU(); - } - return null; - } - - public ITranslationUnit getCreatedSourceTU(){ - if (fCodeGenerator != null) { - return fCodeGenerator.getCreatedSourceTU(); - } - return null; - } - - IPath updateSourceFolderFromPath(IPath filePath) { - ICElement folder = getSourceFolderFromPath(filePath); - if (folder != null) { - return folder.getPath(); - } - IProject proj = PathUtil.getEnclosingProject(filePath); - if (proj != null) - return proj.getFullPath(); - return null; - } -} 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 ab13c56b16d..18c615b8bb4 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 @@ -35,14 +35,8 @@ NewClassCreationWizardPage.error.ProjectClosed=Project ''{0}'' must be accessibl NewClassCreationWizardPage.warning.NotACProject=Folder is not a C/C++ project. NewClassCreationWizardPage.warning.NotInACProject=Folder is not in a C/C++ project. -# NewClassCreationWizardPage.enclosingType.label=&Enclosing Type: -NewClassCreationWizardPage.enclosingType.label=&Namespace: -NewClassCreationWizardPage.enclosingType.namespace=Namespace -NewClassCreationWizardPage.enclosingType.class=Class -NewClassCreationWizardPage.enclosingType.button=Bro&wse... -NewClassCreationWizardPage.enclosingClassAccess.public=public -NewClassCreationWizardPage.enclosingClassAccess.protected=protected -NewClassCreationWizardPage.enclosingClassAccess.private=private +NewClassCreationWizardPage.namespace.label=&Namespace: +NewClassCreationWizardPage.namespace.button=Bro&wse... NewClassCreationWizardPage.error.EnterNamespace=Namespace is empty. NewClassCreationWizardPage.error.EnclosingNamespaceNotExists=Enclosing namespace does not exist. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardPrefs.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardPrefs.java new file mode 100644 index 00000000000..3cd10d12b61 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardPrefs.java @@ -0,0 +1,37 @@ +package org.eclipse.cdt.internal.ui.wizards.classwizard; + +public class NewClassWizardPrefs { + + /** + * Checks if the base classes need to be verified (ie they must exist in the project) + * + * @return true if the base classes should be verified + */ + public static boolean verifyBaseClasses() { + //TODO this should be a prefs option + return true; + } + + /** + * Checks if include paths can be added to the project as needed. + * + * @return true if the include paths should be added + */ + public static boolean createIncludePaths() { + //TODO this should be a prefs option + return true; + } + + /** + * Returns whether the generated header and source files should be + * opened in editors after the finish button is pressed. + * + * @return true if the header and source file should be + * displayed + */ + public static boolean openClassInEditor() { + //TODO this should be a prefs option + return true; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardUtil.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardUtil.java new file mode 100644 index 00000000000..000c2939fcc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardUtil.java @@ -0,0 +1,398 @@ +package org.eclipse.cdt.internal.ui.wizards.classwizard; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.browser.AllTypesCache; +import org.eclipse.cdt.core.browser.ITypeInfo; +import org.eclipse.cdt.core.browser.ITypeReference; +import org.eclipse.cdt.core.browser.ITypeSearchScope; +import org.eclipse.cdt.core.browser.TypeSearchScope; +import org.eclipse.cdt.core.model.CModelException; +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.ICProject; +import org.eclipse.cdt.core.model.ISourceRoot; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoProvider; +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.util.ExceptionHandler; +import org.eclipse.cdt.internal.ui.viewsupport.IViewPartInputProvider; +import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.resources.IFile; +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.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.operation.IRunnableContext; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.views.contentoutline.ContentOutline; + +public class NewClassWizardUtil { + + /** + * Returns the parent source folder of the given element. If the given + * element is already a source folder, the element itself is returned. + * + * @param element the C Element + * @return the source folder + */ + public static ICContainer getSourceFolder(ICElement element) { + ICContainer folder = null; + boolean foundSourceRoot = false; + ICElement curr = element; + while (curr != null && !foundSourceRoot) { + if (curr instanceof ICContainer && folder == null) { + folder = (ICContainer)curr; + } + foundSourceRoot = (curr instanceof ISourceRoot); + curr = curr.getParent(); + } + if (folder == null) { + ICProject cproject = element.getCProject(); + folder = cproject.findSourceRoot(cproject.getProject()); + } + return folder; + } + + /** + * Returns the parent source folder for the given path. If the given + * path is already a source folder, the corresponding C element is returned. + * + * @param path the path + * @return the source folder + */ + public static ICContainer getSourceFolder(IPath path) { + if (path == null) + return null; + while (!path.isEmpty()) { + IResource res = getWorkspaceRoot().findMember(path); + if (res != null && res.exists()) { + int resType = res.getType(); + if (resType == IResource.PROJECT || resType == IResource.FOLDER) { + ICElement elem = CoreModel.getDefault().create(res.getFullPath()); + if (elem != null) { + ICContainer sourceFolder = getSourceFolder(elem); + if (sourceFolder != null) + return sourceFolder; + if (resType == IResource.PROJECT) { + return (ICContainer)elem; + } + } + } + } + path = path.removeLastSegments(1); + } + return null; + } + + /** + * Returns the parent source folder for the given resource. If the given + * resource is already a source folder, the corresponding C element is returned. + * + * @param resource the resource + * @return the source folder + */ + public static ICContainer getSourceFolder(IResource resource) { + if (resource != null && resource.exists()) { + int resType = resource.getType(); + if (resType == IResource.PROJECT || resType == IResource.FOLDER) { + ICElement elem = CoreModel.getDefault().create(resource.getFullPath()); + if (elem != null) { + ICContainer sourceFolder = getSourceFolder(elem); + if (sourceFolder != null) + return sourceFolder; + if (resType == IResource.PROJECT) { + return (ICContainer)elem; + } + } + } else { + return getSourceFolder(resource.getParent()); + } + } + return null; + } + + /** + * Returns the first source root in the given project. If the project has + * no source roots as children, the project itself is returned. + * + * @param cproject + * @return the source root + */ + public static ISourceRoot getFirstSourceRoot(ICProject cproject) { + ISourceRoot folder = null; + try { + if (cproject.exists()) { + ISourceRoot[] roots = cproject.getSourceRoots(); + if (roots != null && roots.length > 0) + folder = roots[0]; + } + } catch (CModelException e) { + CUIPlugin.getDefault().log(e); + } + if (folder == null) { + folder = cproject.findSourceRoot(cproject.getResource()); + } + return folder; + } + + /** + * Returns the C Element which corresponds to the given selection. + * + * @param selection the selection to be inspected + * @return a C element matching the selection, or null + * if no C element exists in the given selection + */ + public static ICElement getCElementFromSelection(IStructuredSelection selection) { + ICElement celem = null; + if (selection != null && !selection.isEmpty()) { + Object selectedElement = selection.getFirstElement(); + if (selectedElement instanceof IAdaptable) { + IAdaptable adaptable = (IAdaptable) selectedElement; + + celem = (ICElement) adaptable.getAdapter(ICElement.class); + if (celem == null) { + IResource resource = (IResource) adaptable.getAdapter(IResource.class); + if (resource != null && resource.getType() != IResource.ROOT) { + while (celem == null && resource.getType() != IResource.PROJECT) { + resource = resource.getParent(); + celem = (ICElement) resource.getAdapter(ICElement.class); + } + if (celem == null) { + celem = CoreModel.getDefault().create(resource); // c project + } + } + } + } + } + return celem; + } + + /** + * Returns the C Element which corresponds to the active editor. + * + * @return a C element matching the active editor, or null + * if no C element can be found + */ + public static ICElement getCElementFromEditor() { + ICElement celem = null; + IWorkbenchPart part = CUIPlugin.getActivePage().getActivePart(); + if (part instanceof ContentOutline) { + part = CUIPlugin.getActivePage().getActiveEditor(); + } + if (part instanceof IViewPartInputProvider) { + Object elem = ((IViewPartInputProvider)part).getViewPartInput(); + if (elem instanceof ICElement) { + celem = (ICElement) elem; + } + } + if (celem == null && part instanceof CEditor) { + IEditorInput input = ((IEditorPart)part).getEditorInput(); + if (input != null) { + final IResource res = (IResource) input.getAdapter(IResource.class); + if (res != null && res instanceof IFile) { + celem = CoreModel.getDefault().create((IFile)res); + } + } + } + return celem; + } + + /** + * Returns the parent namespace for the given element. If the given element is + * already a namespace, the element itself is returned. + * + * @param element the given C Element + * @return the C Element for the namespace, or null if not found + */ + public static ICElement getNamespace(ICElement element) { + ICElement curr = element; + while (curr != null) { + int type = curr.getElementType(); + if (type == ICElement.C_UNIT) { + break; + } + if (type == ICElement.C_NAMESPACE) { + return curr; + } + curr = curr.getParent(); + } + return null; + } + + /** + * Creates a header file name from the given class name. This is the file name + * to be used when the class is created. eg. "MyClass" -> "MyClass.h" + * + * @param className the class name + * @return the header file name for the given class + */ + public static String createHeaderFileName(String className) { + return NewSourceFileGenerator.generateHeaderFileNameFromClass(className); + } + + /** + * Creates a source file name from the given class name. This is the file name + * to be used when the class is created. eg. "MyClass" -> "MyClass.cpp" + * + * @param className the class name + * @return the source file name for the given class + */ + public static String createSourceFileName(String className) { + return NewSourceFileGenerator.generateSourceFileNameFromClass(className); + } + + /** + * Returns the workspace root. + * + * @return the workspace root + */ + public static IWorkspaceRoot getWorkspaceRoot() { + return ResourcesPlugin.getWorkspace().getRoot(); + } + + /** + * Ensures the type cache is up to date. + * + * @param context the runnable context + */ + public static void prepareTypeCache(IRunnableContext context) { + final ITypeSearchScope scope = new TypeSearchScope(true); + if (!AllTypesCache.isCacheUpToDate(scope)) { + IRunnableWithProgress runnable = new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + AllTypesCache.updateCache(scope, monitor); + if (monitor.isCanceled()) { + throw new InterruptedException(); + } + } + }; + + try { + context.run(true, true, runnable); + } catch (InvocationTargetException e) { + String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.title"); //$NON-NLS-1$ + String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.message"); //$NON-NLS-1$ + ExceptionHandler.handle(e, title, message); + } catch (InterruptedException e) { + // cancelled by user + } + } + } + + /** + * Resolve the location of the given class. + * + * @param type the class to resolve + * @param context the runnable context + * @return the class location, or null if not found + */ + public static ITypeReference resolveClassLocation(ITypeInfo type, IRunnableContext context) { + prepareTypeCache(context); + + // resolve location of base class + if (type.getResolvedReference() == null) { + final ITypeInfo[] typesToResolve = new ITypeInfo[] { type }; + IRunnableWithProgress runnable = new IRunnableWithProgress() { + public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException { + AllTypesCache.resolveTypeLocation(typesToResolve[0], progressMonitor); + if (progressMonitor.isCanceled()) { + throw new InterruptedException(); + } + } + }; + + try { + context.run(true, true, runnable); + } catch (InvocationTargetException e) { + String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.title"); //$NON-NLS-1$ + String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.exception.message"); //$NON-NLS-1$ + ExceptionHandler.handle(e, title, message); + return null; + } catch (InterruptedException e) { + // cancelled by user + return null; + } + } + return type.getResolvedReference(); + } + + private static final int[] CLASS_TYPES = { ICElement.C_CLASS, ICElement.C_STRUCT }; + + /** + * Returns all classes/structs which are accessible from the include + * paths of the given project. + * + * @param project the given project + * @return array of classes/structs + */ + public static ITypeInfo[] getReachableClasses(IProject project) { + ITypeInfo[] elements = AllTypesCache.getTypes(new TypeSearchScope(true), CLASS_TYPES); + if (elements != null && elements.length > 0) { + if (project != null) { + IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project); + if (provider != null) { + //TODO get the scanner info for the actual source folder + IScannerInfo info = provider.getScannerInformation(project); + if (info != null) { + String[] includePaths = info.getIncludePaths(); + List filteredTypes = new ArrayList(); + for (int i = 0; i < elements.length; ++i) { + ITypeInfo baseType = elements[i]; + if (isTypeReachable(baseType, project, includePaths)) { + filteredTypes.add(baseType); + } + } + return (ITypeInfo[]) filteredTypes.toArray(new ITypeInfo[filteredTypes.size()]); + } + } + } + } + return elements; + } + + /** + * Checks whether the given type can be found in the given project or the + * given include paths. + * + * @param type the type + * @param project the project + * @param includePaths the include paths + * @return true if the given type is found + */ + public static boolean isTypeReachable(ITypeInfo type, IProject project, String[] includePaths) { + IProject baseProject = type.getEnclosingProject(); + if (baseProject != null) { + if (baseProject.equals(project)) { + return true; + } + ITypeReference ref = type.getResolvedReference(); + for (int i = 0; i < includePaths.length; ++i) { + IPath includePath = new Path(includePaths[i]); + if (ref != null) { + if (includePath.isPrefixOf(ref.getLocation())) + return true; + } else { + // we don't have the real location, so just check the project path + if (baseProject.getLocation().isPrefixOf(includePath)) + return true; + } + } + } + return false; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java index 807ed9a4cb2..c048b43734b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewSourceFileGenerator.java @@ -61,8 +61,9 @@ public class NewSourceFileGenerator { buf.append(includeGuardSymbol); buf.append(fLineDelimiter); buf.append(fLineDelimiter); - buf.append("#endif //"); //$NON-NLS-1$ + buf.append("#endif /*"); //$NON-NLS-1$ buf.append(includeGuardSymbol); + buf.append("*/"); //$NON-NLS-1$ buf.append(fLineDelimiter); stream = new ByteArrayInputStream(buf.toString().getBytes()); } else { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java new file mode 100644 index 00000000000..99b00951f2d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java @@ -0,0 +1,1954 @@ +/******************************************************************************* + * 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.ui.wizards; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.cdt.core.CConventions; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.browser.AllTypesCache; +import org.eclipse.cdt.core.browser.IQualifiedTypeName; +import org.eclipse.cdt.core.browser.ITypeInfo; +import org.eclipse.cdt.core.browser.ITypeSearchScope; +import org.eclipse.cdt.core.browser.PathUtil; +import org.eclipse.cdt.core.browser.QualifiedTypeName; +import org.eclipse.cdt.core.browser.TypeSearchScope; +import org.eclipse.cdt.core.browser.TypeUtil; +import org.eclipse.cdt.core.model.CModelException; +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.ICProject; +import org.eclipse.cdt.core.model.ISourceRoot; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoProvider; +import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; +import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; +import org.eclipse.cdt.internal.ui.dialogs.StatusUtil; +import org.eclipse.cdt.internal.ui.util.SWTUtil; +import org.eclipse.cdt.internal.ui.wizards.NewElementWizardPage; +import org.eclipse.cdt.internal.ui.wizards.SourceFolderSelectionDialog; +import org.eclipse.cdt.internal.ui.wizards.classwizard.BaseClassInfo; +import org.eclipse.cdt.internal.ui.wizards.classwizard.BaseClassesListDialogField; +import org.eclipse.cdt.internal.ui.wizards.classwizard.ConstructorMethodStub; +import org.eclipse.cdt.internal.ui.wizards.classwizard.DestructorMethodStub; +import org.eclipse.cdt.internal.ui.wizards.classwizard.IBaseClassInfo; +import org.eclipse.cdt.internal.ui.wizards.classwizard.IMethodStub; +import org.eclipse.cdt.internal.ui.wizards.classwizard.MethodStubsListDialogField; +import org.eclipse.cdt.internal.ui.wizards.classwizard.NamespaceSelectionDialog; +import org.eclipse.cdt.internal.ui.wizards.classwizard.NewBaseClassSelectionDialog; +import org.eclipse.cdt.internal.ui.wizards.classwizard.NewClassCodeGenerator; +import org.eclipse.cdt.internal.ui.wizards.classwizard.NewClassWizardMessages; +import org.eclipse.cdt.internal.ui.wizards.classwizard.NewClassWizardPrefs; +import org.eclipse.cdt.internal.ui.wizards.classwizard.SourceFileSelectionDialog; +import org.eclipse.cdt.internal.ui.wizards.classwizard.NewClassWizardUtil; +import org.eclipse.cdt.internal.ui.wizards.classwizard.NewBaseClassSelectionDialog.ITypeSelectionListener; +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.IListAdapter; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.IStringButtonAdapter; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.ListDialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.Separator; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringButtonDialogField; +import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; + +public class NewClassCreationWizardPage extends NewElementWizardPage { + + protected final static String PAGE_NAME = "NewClassWizardPage"; //$NON-NLS-1$ + protected static final int MAX_FIELD_CHARS = 50; + + // field IDs + protected static final int SOURCE_FOLDER_ID = 1; + protected static final int NAMESPACE_ID = 2; + protected static final int CLASS_NAME_ID = 4; + protected static final int BASE_CLASSES_ID = 8; + protected static final int METHOD_STUBS_ID = 16; + protected static final int HEADER_FILE_ID = 32; + protected static final int SOURCE_FILE_ID = 64; + protected static final int ALL_FIELDS = SOURCE_FOLDER_ID | NAMESPACE_ID + | CLASS_NAME_ID | BASE_CLASSES_ID | METHOD_STUBS_ID + | HEADER_FILE_ID | SOURCE_FILE_ID; + protected int fLastFocusedField = 0; + + protected StringButtonDialogField fSourceFolderDialogField; + protected SelectionButtonDialogField fNamespaceSelection; + protected StringButtonDialogField fNamespaceDialogField; + protected StringDialogField fClassNameDialogField; + protected BaseClassesListDialogField fBaseClassesDialogField; + protected MethodStubsListDialogField fMethodStubsDialogField; + protected SelectionButtonDialogField fUseDefaultSelection; + protected StringButtonDialogField fHeaderFileDialogField; + protected StringButtonDialogField fSourceFileDialogField; + + protected IStatus fSourceFolderStatus; + protected IStatus fNamespaceStatus; + protected IStatus fClassNameStatus; + protected IStatus fBaseClassesStatus; + protected IStatus fMethodStubsStatus; + protected IStatus fHeaderFileStatus; + protected IStatus fSourceFileStatus; + protected final IStatus STATUS_OK = new StatusInfo(); + + protected IFile fCreatedSourceFile = null; + protected IFile fCreatedHeaderFile = null; + protected ICElement fCreatedClass = null; + + /** + * the default method stubs + */ + protected static final IMethodStub[] DEFAULT_METHOD_STUBS = { + new ConstructorMethodStub(), + new DestructorMethodStub() + }; + + + /** + * Constructor for NewClassCreationWizardPage + */ + public NewClassCreationWizardPage() { + super(PAGE_NAME); + + setDescription(NewClassWizardMessages.getString("NewClassCreationWizardPage.description")); //$NON-NLS-1$ + + SourceFolderFieldAdapter sourceFolderAdapter = new SourceFolderFieldAdapter(); + fSourceFolderDialogField = new StringButtonDialogField(sourceFolderAdapter); + fSourceFolderDialogField.setDialogFieldListener(sourceFolderAdapter); + fSourceFolderDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.sourceFolder.label")); //$NON-NLS-1$ + fSourceFolderDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.sourceFolder.button")); //$NON-NLS-1$ + + NamespaceFieldAdapter namespaceAdapter = new NamespaceFieldAdapter(); + fNamespaceSelection = new SelectionButtonDialogField(SWT.CHECK); + fNamespaceSelection.setDialogFieldListener(namespaceAdapter); + fNamespaceSelection.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.namespace.label")); //$NON-NLS-1$ + + fNamespaceDialogField = new StringButtonDialogField(namespaceAdapter); + fNamespaceDialogField.setDialogFieldListener(namespaceAdapter); + fNamespaceDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.namespace.button")); //$NON-NLS-1$ + + ClassNameFieldAdapter classAdapter = new ClassNameFieldAdapter(); + fClassNameDialogField = new StringDialogField(); + fClassNameDialogField.setDialogFieldListener(classAdapter); + fClassNameDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.className.label")); //$NON-NLS-1$ + + BaseClassesFieldAdapter baseClassesAdapter = new BaseClassesFieldAdapter(); + fBaseClassesDialogField = new BaseClassesListDialogField(NewClassWizardMessages.getString("NewClassCreationWizardPage.baseClasses.label"), baseClassesAdapter); //$NON-NLS-1$ + + MethodStubsFieldAdapter methodStubsAdapter = new MethodStubsFieldAdapter(); + fMethodStubsDialogField = new MethodStubsListDialogField(NewClassWizardMessages.getString("NewClassCreationWizardPage.methodStubs.label"), methodStubsAdapter); //$NON-NLS-1$ + + FileGroupFieldAdapter fileGroupAdapter = new FileGroupFieldAdapter(); + fUseDefaultSelection = new SelectionButtonDialogField(SWT.CHECK); + fUseDefaultSelection.setDialogFieldListener(fileGroupAdapter); + fUseDefaultSelection.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.useDefaultLocation.label")); //$NON-NLS-1$ + fHeaderFileDialogField = new StringButtonDialogField(fileGroupAdapter); + fHeaderFileDialogField.setDialogFieldListener(fileGroupAdapter); + fHeaderFileDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.headerFile.label")); //$NON-NLS-1$ + fHeaderFileDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.headerFile.button")); //$NON-NLS-1$ + fSourceFileDialogField = new StringButtonDialogField(fileGroupAdapter); + fSourceFileDialogField.setDialogFieldListener(fileGroupAdapter); + fSourceFileDialogField.setLabelText(NewClassWizardMessages.getString("NewClassCreationWizardPage.sourceFile.label")); //$NON-NLS-1$ + fSourceFileDialogField.setButtonLabel(NewClassWizardMessages.getString("NewClassCreationWizardPage.sourceFile.button")); //$NON-NLS-1$ + + fSourceFolderStatus = STATUS_OK; + fNamespaceStatus = STATUS_OK; + fClassNameStatus = STATUS_OK; + fBaseClassesStatus = STATUS_OK; + fMethodStubsStatus = STATUS_OK; + fHeaderFileStatus = STATUS_OK; + fSourceFileStatus = STATUS_OK; + fLastFocusedField = 0; + + updateNamespaceEnableState(); + updateFileGroupEnableState(); + } + + // -------- UI Creation --------- + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + */ + public void createControl(Composite parent) { + initializeDialogUnits(parent); + + Composite composite = new Composite(parent, SWT.NONE); + int nColumns = 4; + + GridLayout layout = new GridLayout(); + layout.numColumns = nColumns; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + composite.setFont(parent.getFont()); + + createSourceFolderControls(composite, nColumns); + createNamespaceControls(composite, nColumns); + + createSeparator(composite, nColumns); + + createClassNameControls(composite, nColumns); + createBaseClassesControls(composite, nColumns); + createMethodStubsControls(composite, nColumns); + + createSeparator(composite, nColumns); + + createFileControls(composite, nColumns); + + composite.layout(); + + setErrorMessage(null); + setMessage(null); + setControl(composite); + } + + /** + * Creates a separator line. Expects a GridLayout with at least 1 column. + * + * @param composite the parent composite + * @param nColumns number of columns to span + */ + protected void createSeparator(Composite composite, int nColumns) { + (new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, convertHeightInCharsToPixels(1)); + } + + /** + * Creates the necessary controls (label, text field and browse button) to edit + * the source folder location. The method expects that the parent composite + * uses a GridLayout as its layout manager and that the + * grid layout has at least 3 columns. + * + * @param parent the parent composite + * @param nColumns the number of columns to span. This number must be + * greater or equal three + */ + protected void createSourceFolderControls(Composite parent, int nColumns) { + fSourceFolderDialogField.doFillIntoGrid(parent, nColumns); + Text textControl = fSourceFolderDialogField.getTextControl(null); + LayoutUtil.setWidthHint(textControl, getMaxFieldWidth()); + textControl.addFocusListener(new StatusFocusListener(SOURCE_FOLDER_ID)); + } + + /** + * Creates the controls for the namespace field. Expects a GridLayout with at + * least 4 columns. + * + * @param composite the parent composite + * @param nColumns number of columns to span + */ + protected void createNamespaceControls(Composite composite, int nColumns) { + Composite tabGroup= new Composite(composite, SWT.NONE); + GridLayout layout= new GridLayout(); + layout.marginWidth= 0; + layout.marginHeight= 0; + tabGroup.setLayout(layout); + + fNamespaceSelection.doFillIntoGrid(tabGroup, 1); + + Text textControl= fNamespaceDialogField.getTextControl(composite); + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + gd.widthHint= getMaxFieldWidth(); + gd.horizontalSpan= 2; + textControl.setLayoutData(gd); + textControl.addFocusListener(new StatusFocusListener(NAMESPACE_ID)); + + Button button= fNamespaceDialogField.getChangeControl(composite); + gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.heightHint = SWTUtil.getButtonHeigthHint(button); + gd.widthHint = SWTUtil.getButtonWidthHint(button); + button.setLayoutData(gd); + } + + /** + * Creates the controls for the class name field. Expects a GridLayout with at + * least 2 columns. + * + * @param composite the parent composite + * @param nColumns number of columns to span + */ + protected void createClassNameControls(Composite composite, int nColumns) { + fClassNameDialogField.doFillIntoGrid(composite, nColumns - 1); + DialogField.createEmptySpace(composite); + Text textControl = fClassNameDialogField.getTextControl(null); + LayoutUtil.setWidthHint(textControl, getMaxFieldWidth()); + textControl.addFocusListener(new StatusFocusListener(CLASS_NAME_ID)); + } + + /** + * Creates the controls for the base classes field. Expects a GridLayout with + * at least 3 columns. + * + * @param composite the parent composite + * @param nColumns number of columns to span + */ + protected void createBaseClassesControls(Composite composite, int nColumns) { + fBaseClassesDialogField.doFillIntoGrid(composite, nColumns); + Control listControl = fBaseClassesDialogField.getListControl(null); + GridData gd = (GridData) listControl.getLayoutData(); + gd.heightHint = convertHeightInCharsToPixels(5); + gd.grabExcessVerticalSpace = false; + gd.widthHint = getMaxFieldWidth(); + listControl.addFocusListener(new StatusFocusListener(BASE_CLASSES_ID)); + } + + /** + * Creates the controls for the method stubs field. Expects a GridLayout with + * at least 4 columns. + * + * @param composite the parent composite + * @param nColumns number of columns to span + */ + protected void createMethodStubsControls(Composite composite, int nColumns) { + fMethodStubsDialogField.doFillIntoGrid(composite, nColumns); + Control listControl = fMethodStubsDialogField.getListControl(null); + GridData gd = (GridData) listControl.getLayoutData(); + gd.heightHint = convertHeightInCharsToPixels(5); + gd.grabExcessVerticalSpace = false; + gd.widthHint = getMaxFieldWidth(); + listControl.addFocusListener(new StatusFocusListener(METHOD_STUBS_ID)); + } + + /** + * Creates the controls for the file name fields. Expects a GridLayout with at + * least 4 columns. + * + * @param composite the parent composite + * @param nColumns number of columns to span + */ + protected void createFileControls(Composite composite, int nColumns) { + Composite tabGroup = new Composite(composite, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + tabGroup.setLayout(layout); + + fUseDefaultSelection.doFillIntoGrid(tabGroup, 1); + + LayoutUtil.setHorizontalSpan(fHeaderFileDialogField.getLabelControl(composite), 1); + Text textControl = fHeaderFileDialogField.getTextControl(composite); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.widthHint = getMaxFieldWidth(); + gd.horizontalSpan = 1; + textControl.setLayoutData(gd); + textControl.addFocusListener(new StatusFocusListener(HEADER_FILE_ID)); + + Button button = fHeaderFileDialogField.getChangeControl(composite); + gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.heightHint = SWTUtil.getButtonHeigthHint(button); + gd.widthHint = SWTUtil.getButtonWidthHint(button); + button.setLayoutData(gd); + + DialogField.createEmptySpace(composite, 1); + + LayoutUtil.setHorizontalSpan(fSourceFileDialogField.getLabelControl(composite), 1); + textControl = fSourceFileDialogField.getTextControl(composite); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.widthHint = getMaxFieldWidth(); + gd.horizontalSpan = 1; + textControl.setLayoutData(gd); + textControl.addFocusListener(new StatusFocusListener(SOURCE_FILE_ID)); + + button = fSourceFileDialogField.getChangeControl(composite); + gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.heightHint = SWTUtil.getButtonHeigthHint(button); + gd.widthHint = SWTUtil.getButtonWidthHint(button); + button.setLayoutData(gd); + } + + /** + * The wizard owning this page is responsible for calling this method with the + * current selection. The selection is used to initialize the fields of the wizard + * page. + * + * @param selection used to initialize the fields + */ + public void init(IStructuredSelection selection) { + ICElement celem = getInitialCElement(selection); + + String namespace = null; + if (celem != null) { + ICElement ns = NewClassWizardUtil.getNamespace(celem); + if (ns != null) { + namespace = TypeUtil.getFullyQualifiedName(ns).toString(); + if (namespace == null && namespace.length() == 0) { + namespace = null; + } + } + } + setNamespaceText(namespace, false); + setNamespaceSelection(namespace != null, true); + + IPath folderPath = null; + if (celem != null) { + ICContainer folder = NewClassWizardUtil.getSourceFolder(celem); + if (folder == null) { + ICProject cproject = celem.getCProject(); + if (cproject != null) { + folder = NewClassWizardUtil.getFirstSourceRoot(cproject); + } + } + if (folder != null) { + folderPath = folder.getResource().getFullPath(); + } + } + setSourceFolderFullPath(folderPath, false); + + String className = null; + ITextSelection textSel = getEditorTextSelection(); + if (textSel != null) { + String text = textSel.getText(); + if (text != null && text.length() > 0 && CConventions.validateClassName(text).isOK()) { + className = text; + } + } + setClassName(className, false); + + IMethodStub[] stubs = getDefaultMethodStubs(); + for (int i = 0; i < stubs.length; ++i) { + addMethodStub(stubs[i], true); + } + //TODO restore dialog settings for method stubs? + // IDialogSettings section = getDialogSettings().getSection(PAGE_NAME); + // if (section != null) { + // enabled = section.getBoolean(stubName); + // } + + setUseDefaultSelection(true, true); + + handleFieldChanged(ALL_FIELDS); + } + + /** + * Attempts to extract a C Element from the initial selection. + * + * @param selection the initial selection + * @return a C Element, or null if not available + */ + protected ICElement getInitialCElement(IStructuredSelection selection) { + ICElement celem = NewClassWizardUtil.getCElementFromSelection(selection); + if (celem == null) { + celem = NewClassWizardUtil.getCElementFromEditor(); + } + if (celem == null || celem.getElementType() == ICElement.C_MODEL) { + try { + ICProject[] projects = CoreModel.create(NewClassWizardUtil.getWorkspaceRoot()).getCProjects(); + if (projects.length == 1) { + celem = projects[0]; + } + } catch (CModelException e) { + CUIPlugin.getDefault().log(e); + } + } + return celem; + } + + /** + * 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(MAX_FIELD_CHARS); + } + + /** + * Returns the text selection of the current editor. null is returned + * when the current editor does not have focus or does not return a text selection. + * + * @return the selection of the current editor, or null. + */ + protected ITextSelection getEditorTextSelection() { + IWorkbenchPage page = CUIPlugin.getActivePage(); + if (page != null) { + IWorkbenchPart part = page.getActivePart(); + if (part instanceof IEditorPart) { + ISelectionProvider selectionProvider = part.getSite().getSelectionProvider(); + if (selectionProvider != null) { + ISelection selection = selectionProvider.getSelection(); + if (selection instanceof ITextSelection) { + return (ITextSelection) selection; + } + } + } + } + return null; + } + + /** + * Returns the method stubs to display in the wizard. + * + * @return array of method stubs + */ + protected IMethodStub[] getDefaultMethodStubs() { + return DEFAULT_METHOD_STUBS; + } + + /** + * Returns the text entered into the source folder input field. + * + * @return the source folder + */ + public String getSourceFolderText() { + return fSourceFolderDialogField.getText(); + } + + /** + * Sets the text of the source folder input field. + * + * @param folder the folder name + * @param update true if the dialog should be updated + */ + public void setSourceFolderText(String folder, boolean update) { + fSourceFolderDialogField.setTextWithoutUpdate(folder != null ? folder : ""); //$NON-NLS-1$ + if (update) { + fSourceFolderDialogField.dialogFieldChanged(); + } + } + + /** + * Returns the current source folder as a path. + * + * @return the source folder path + */ + protected IPath getSourceFolderFullPath() { + String text = getSourceFolderText(); + if (text.length() > 0) + return new Path(text).makeAbsolute(); + return null; + } + + /** + * Sets the source folder from the given path. + * + * @param folderPath the source folder path + * @param update true if the dialog should be updated + */ + protected void setSourceFolderFullPath(IPath folderPath, boolean update) { + String str = (folderPath != null) ? folderPath.makeRelative().toString() : ""; //.makeRelative().toString(); //$NON-NLS-1$ + setSourceFolderText(str, update); + } + + /** + * Returns the current project, based on the current source folder. + * + * @return the current project + */ + protected IProject getCurrentProject() { + IPath folderPath = getSourceFolderFullPath(); + if (folderPath != null) { + return PathUtil.getEnclosingProject(folderPath); + } + return null; + } + + /** + * Returns the text entered into the namespace input field. + * + * @return the namespace + */ + public String getNamespaceText() { + return fNamespaceDialogField.getText(); + } + + /** + * Sets the text of the namespace input field. + * + * @param namespace the namespace name + * @param update true if the dialog should be updated + */ + public void setNamespaceText(String namespace, boolean update) { + fNamespaceDialogField.setTextWithoutUpdate(namespace != null ? namespace : ""); //$NON-NLS-1$ + if (update) { + fNamespaceDialogField.dialogFieldChanged(); + } + } + + /** + * Returns the selection state of the namespace checkbox. + * + * @return the selection state of the namespace checkbox + */ + public boolean isNamespaceSelected() { + return fNamespaceSelection.isSelected(); + } + + /** + * Sets the namespace checkbox's selection state. + * + * @param isSelected the checkbox's selection state + * @param canBeModified if true the checkbox is + * modifiable; otherwise it is read-only. + */ + public void setNamespaceSelection(boolean isSelected, boolean canBeModified) { + fNamespaceSelection.setSelection(isSelected); + fNamespaceSelection.setEnabled(canBeModified); + updateNamespaceEnableState(); + } + + /** + * Updates the enable state of the namespace button. + */ + private void updateNamespaceEnableState() { + fNamespaceDialogField.setEnabled(isNamespaceSelected()); + } + + /** + * Returns the class name entered into the class input field. + * + * @return the class name + */ + public String getClassName() { + return fClassNameDialogField.getText(); + } + + /** + * Sets the text of the class name input field. + * + * @param name the new class name + * @param update true if the dialog should be updated + */ + public void setClassName(String name, boolean update) { + fClassNameDialogField.setTextWithoutUpdate(name != null ? name : ""); //$NON-NLS-1$ + if (update) { + fClassNameDialogField.dialogFieldChanged(); + } + } + + /** + * Returns the currently selected (checked) method stubs. + * + * @return array of IMethodStub or empty array if none selected. + */ + protected IMethodStub[] getSelectedMethodStubs() { + return fMethodStubsDialogField.getCheckedMethodStubs(); + } + + /** + * Adds a method stub to the method stubs field. + * @param methodStub the method stub to add + * @param checked true if the stub is initially selected (checked) + */ + protected void addMethodStub(IMethodStub methodStub, boolean selected) { + fMethodStubsDialogField.addMethodStub(methodStub, selected); + } + + /** + * Returns the contents of the base classes field. + * + * @return array of IBaseClassInfo + */ + protected IBaseClassInfo[] getBaseClasses() { + List classesList = fBaseClassesDialogField.getElements(); + return (IBaseClassInfo[]) classesList.toArray(new IBaseClassInfo[classesList.size()]); + } + + /** + * Adds a base class to the base classes field. + * @param newBaseClass the new base class + * @param access the access visibility (public/private/protected) + * @param isVirtual true if the inheritance is virtual + */ + protected void addBaseClass(ITypeInfo newBaseClass, ASTAccessVisibility access, boolean isVirtual) { + // check if already exists + List baseClasses = fBaseClassesDialogField.getElements(); + if (baseClasses != null) { + for (Iterator i = baseClasses.iterator(); i.hasNext(); ) { + BaseClassInfo info = (BaseClassInfo) i.next(); + if (info.getType().equals(newBaseClass)) { + // already added + return; + } + } + } + + if (verifyBaseClasses()) { + NewClassWizardUtil.resolveClassLocation(newBaseClass, getContainer()); + } + + fBaseClassesDialogField.addBaseClass(new BaseClassInfo(newBaseClass, access, isVirtual)); + } + + /** + * Returns the selection state of the file group checkbox. + * + * @return the selection state of the file group checkbox + */ + public boolean isUseDefaultSelected() { + return fUseDefaultSelection.isSelected(); + } + + /** + * Sets the use default checkbox's selection state. + * + * @param isSelected the checkbox's selection state + * @param canBeModified if true the checkbox is + * modifiable; otherwise it is read-only. + */ + public void setUseDefaultSelection(boolean isSelected, boolean canBeModified) { + fUseDefaultSelection.setSelection(isSelected); + fUseDefaultSelection.setEnabled(canBeModified); + updateFileGroupEnableState(); + } + + /** + * Updates the enable state of buttons related to the use default checkbox. + */ + private void updateFileGroupEnableState() { + boolean filegroup = !isUseDefaultSelected(); + fHeaderFileDialogField.setEnabled(filegroup); + fSourceFileDialogField.setEnabled(filegroup); + } + + /** + * Returns the text entered into the header file input field. + * + * @return the header file + */ + public String getHeaderFileText() { + return fHeaderFileDialogField.getText(); + } + + /** + * Sets the text of the header file input field. + * + * @param header the header file name + * @param update true if the dialog should be updated + */ + public void setHeaderFileText(String header, boolean update) { + fHeaderFileDialogField.setTextWithoutUpdate(header != null ? header : ""); //$NON-NLS-1$ + if (update) { + fHeaderFileDialogField.dialogFieldChanged(); + } + } + + /** + * Returns the current header file as a path. + * + * @return the header file path + */ + protected IPath getHeaderFileFullPath() { + String str = getHeaderFileText(); + IPath path = null; + if (str.length() > 0) { + path = new Path(str); + if (!path.isAbsolute()) { + IPath folderPath = getSourceFolderFullPath(); + if (folderPath != null) + path = folderPath.append(path); + } + } + return path; + } + + /** + * Sets the header file from the given path. + * + * @param path the header file path + * @param update true if the dialog should be updated + */ + protected void setHeaderFileFullPath(IPath path, boolean update) { + String str = null; + if (path != null) { + IPath sourceFolder = getSourceFolderFullPath(); + if (sourceFolder != null) { + IPath relativePath = PathUtil.makeRelativePath(path, sourceFolder); + if (relativePath != null) + path = relativePath; + } + str = path.makeRelative().toString(); + } + setHeaderFileText(str, update); + } + + + /** + * Returns the text entered into the source file input field. + * + * @return the source file + */ + public String getSourceFileText() { + return fSourceFileDialogField.getText(); + } + + /** + * Sets the text of the source file input field. + * + * @param source the source file name + * @param update true if the dialog should be updated + */ + public void setSourceFileText(String source, boolean update) { + fSourceFileDialogField.setTextWithoutUpdate(source != null ? source : ""); //$NON-NLS-1$ + if (update) { + fSourceFileDialogField.dialogFieldChanged(); + } + } + + /** + * Returns the current source file as a path. + * + * @return the source file path + */ + protected IPath getSourceFileFullPath() { + String str = getSourceFileText(); + IPath path = null; + if (str.length() > 0) { + path = new Path(str); + if (!path.isAbsolute()) { + IPath folderPath = getSourceFolderFullPath(); + if (folderPath != null) + path = folderPath.append(path); + } + } + return path; + } + + /** + * Sets the source file from the given path. + * + * @param path the source file path + * @param update true if the dialog should be updated + */ + protected void setSourceFileFullPath(IPath path, boolean update) { + String str = null; + if (path != null) { + IPath sourceFolder = getSourceFolderFullPath(); + if (sourceFolder != null) { + IPath relativePath = PathUtil.makeRelativePath(path, sourceFolder); + if (relativePath != null) + path = relativePath; + } + str = path.makeRelative().toString(); + } + setSourceFileText(str, update); + } + + /* + * @see WizardPage#becomesVisible + */ + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible) { + setFocus(); + } + } + + /** + * Sets the focus on the class name input field. + */ + protected void setFocus() { + fClassNameDialogField.setFocus(); + } + + // ----------- UI Validation ---------- + + /** + * Causes doStatusUpdate() to be called whenever the focus changes. + * Remembers the last focused field. + */ + private final class StatusFocusListener implements FocusListener { + private int fieldID; + + public StatusFocusListener(int fieldID) { + this.fieldID = fieldID; + } + + public void focusGained(FocusEvent e) { + if (fLastFocusedField != this.fieldID) { + fLastFocusedField = this.fieldID; + doStatusUpdate(); + } + } + + public void focusLost(FocusEvent e) { + if (fLastFocusedField != 0) { + fLastFocusedField = 0; + doStatusUpdate(); + } + } + } + + /** + * handles changes to the source folder field + */ + private final class SourceFolderFieldAdapter implements IStringButtonAdapter, IDialogFieldListener { + public void changeControlPressed(DialogField field) { + IPath oldFolderPath = getSourceFolderFullPath(); + IPath newFolderPath = chooseSourceFolder(oldFolderPath); + if (newFolderPath != null) { + IPath headerPath = getHeaderFileFullPath(); + IPath sourcePath = getSourceFileFullPath(); + setSourceFolderFullPath(newFolderPath, false); + if (!isUseDefaultSelected()) { + if (oldFolderPath != null && oldFolderPath.matchingFirstSegments(newFolderPath) == 0) { + if (headerPath != null) { + headerPath = newFolderPath.append(headerPath.lastSegment()); + } + if (sourcePath != null) { + sourcePath = newFolderPath.append(sourcePath.lastSegment()); + } + } + // adjust the relative paths + setHeaderFileFullPath(headerPath, false); + setSourceFileFullPath(sourcePath, false); + } + handleFieldChanged(SOURCE_FOLDER_ID|ALL_FIELDS); + } + } + + public void dialogFieldChanged(DialogField field) { + handleFieldChanged(SOURCE_FOLDER_ID|ALL_FIELDS); + } + } + + private IPath chooseSourceFolder(IPath initialPath) { + ICElement initElement = NewClassWizardUtil.getSourceFolder(initialPath); + if (initElement instanceof ISourceRoot) { + ICProject cProject = initElement.getCProject(); + ISourceRoot projRoot = cProject.findSourceRoot(cProject.getProject()); + if (projRoot != null && projRoot.equals(initElement)) + initElement = cProject; + } + + SourceFolderSelectionDialog dialog = new SourceFolderSelectionDialog(getShell()); + dialog.setInput(CoreModel.create(NewClassWizardUtil.getWorkspaceRoot())); + dialog.setInitialSelection(initElement); + + if (dialog.open() == Window.OK) { + 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.getResource().getFullPath(); + } + return element.getResource().getFullPath(); + } + } + return null; + } + + /** + * handles changes to the namespace field + */ + private final class NamespaceFieldAdapter implements IStringButtonAdapter, IDialogFieldListener { + public void changeControlPressed(DialogField field) { + ITypeInfo ns = chooseNamespace(); + if (ns != null) { + int changedFields = NAMESPACE_ID|CLASS_NAME_ID; + IPath oldFolderPath = getSourceFolderFullPath(); + if (oldFolderPath == null) { + IPath headerPath = getHeaderFileFullPath(); + IPath sourcePath = getSourceFileFullPath(); + IPath newFolderPath = updateSourceFolderFromPath(ns.getEnclosingProject().getFullPath()); + if (newFolderPath != null) { + changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID; + // adjust the relative paths + if (oldFolderPath != null && oldFolderPath.matchingFirstSegments(newFolderPath) == 0) { + if (headerPath != null) { + headerPath = newFolderPath.append(headerPath.lastSegment()); + } + if (sourcePath != null) { + sourcePath = newFolderPath.append(sourcePath.lastSegment()); + } + } + setSourceFolderFullPath(newFolderPath, false); + // adjust the relative paths + setHeaderFileFullPath(headerPath, false); + setSourceFileFullPath(sourcePath, false); + } + } + setNamespaceText(ns.getQualifiedTypeName().toString(), false); + handleFieldChanged(changedFields); + } + } + + public void dialogFieldChanged(DialogField field) { + updateNamespaceEnableState(); + handleFieldChanged(NAMESPACE_ID|CLASS_NAME_ID); + } + } + + private IPath updateSourceFolderFromPath(IPath filePath) { + ICElement folder = NewClassWizardUtil.getSourceFolder(filePath); + if (folder instanceof ISourceRoot) { + ICProject cProject = folder.getCProject(); + ISourceRoot projRoot = cProject.findSourceRoot(cProject.getProject()); + if (projRoot != null && projRoot.equals(folder)) + folder = cProject; + } + if (folder != null) { + return folder.getPath(); + } + IProject proj = PathUtil.getEnclosingProject(filePath); + if (proj != null) + return proj.getFullPath(); + return null; + } + + private ITypeInfo chooseNamespace() { + ITypeSearchScope scope; + IProject project = getCurrentProject(); + if (project != null) { + scope = new TypeSearchScope(project); + } else { + scope = new TypeSearchScope(true); + } + + NewClassWizardUtil.prepareTypeCache(getContainer()); + + ITypeInfo[] elements = AllTypesCache.getNamespaces(scope, false); + if (elements == null || elements.length == 0) { + String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.noNamespaces.title"); //$NON-NLS-1$ + String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.noNamespaces.message"); //$NON-NLS-1$ + MessageDialog.openInformation(getShell(), title, message); + return null; + } + + NamespaceSelectionDialog dialog = new NamespaceSelectionDialog(getShell()); + dialog.setElements(elements); + int result = dialog.open(); + if (result == IDialogConstants.OK_ID) { + return (ITypeInfo) dialog.getFirstResult(); + } + + return null; + } + + /** + * handles changes to the class name field + */ + private final class ClassNameFieldAdapter implements IDialogFieldListener { + public void dialogFieldChanged(DialogField field) { + int changedFields = CLASS_NAME_ID; + if (isUseDefaultSelected()) { + updateFilesFromClassName(fClassNameDialogField.getText()); + changedFields |= (HEADER_FILE_ID|SOURCE_FILE_ID); + } + handleFieldChanged(changedFields); + } + } + + /** + * handles changes to the base classes field + */ + private final class BaseClassesFieldAdapter implements IListAdapter { + public void customButtonPressed(ListDialogField field, int index) { + if (index == 0) { + chooseBaseClasses(); + } + handleFieldChanged(BASE_CLASSES_ID); + } + + public void selectionChanged(ListDialogField field) { + } + + public void doubleClicked(ListDialogField field) { + } + } + + private void chooseBaseClasses() { + NewClassWizardUtil.prepareTypeCache(getContainer()); + + ITypeInfo[] elements = NewClassWizardUtil.getReachableClasses(getCurrentProject()); + if (elements == null || elements.length == 0) { + String title = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.noClasses.title"); //$NON-NLS-1$ + String message = NewClassWizardMessages.getString("NewClassCreationWizardPage.getTypes.noClasses.message"); //$NON-NLS-1$ + MessageDialog.openInformation(getShell(), title, message); + return; + } + + List oldContents = fBaseClassesDialogField.getElements(); + NewBaseClassSelectionDialog dialog = new NewBaseClassSelectionDialog(getShell()); + dialog.addListener(new ITypeSelectionListener() { + public void typeAdded(ITypeInfo newBaseClass) { + addBaseClass(newBaseClass, ASTAccessVisibility.PUBLIC, false); + } + }); + dialog.setElements(elements); + int result = dialog.open(); + if (result != IDialogConstants.OK_ID) { + // restore the old contents + fBaseClassesDialogField.setElements(oldContents); + } + } + + /** + * handles changes to the method stubs field + */ + private final class MethodStubsFieldAdapter implements IListAdapter { + + public void customButtonPressed(ListDialogField field, int index) { + } + + public void selectionChanged(ListDialogField field) { + } + + public void doubleClicked(ListDialogField field) { + } + } + + /** + * handles changes to the file name fields + */ + private final class FileGroupFieldAdapter implements IStringButtonAdapter, IDialogFieldListener { + public void changeControlPressed(DialogField field) { + IPath filePath = null; + IPath headerPath = getHeaderFileFullPath(); + IPath sourcePath = getSourceFileFullPath(); + if (field == fHeaderFileDialogField) { + filePath = chooseHeaderFile(); + if (filePath != null) { + headerPath = filePath; + } + } else if (field == fSourceFileDialogField) { + filePath = chooseSourceFile(); + if (filePath != null) { + sourcePath = filePath; + } + } + if (filePath != null) { + IPath folderPath = null; + int changedFields = 0; + int headerSegments = 0; + int sourceSegments = 0; + if (headerPath != null) + headerSegments = filePath.matchingFirstSegments(headerPath); + if (sourcePath != null) + sourceSegments = filePath.matchingFirstSegments(sourcePath); + int segments = Math.min(headerSegments, sourceSegments); + if (segments > 0) { + IPath newFolderPath = filePath.uptoSegment(segments); + folderPath = updateSourceFolderFromPath(newFolderPath); + } + if (folderPath != null) { + changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID; + // adjust the relative paths + setSourceFolderFullPath(folderPath, false); + setHeaderFileFullPath(headerPath, false); + setSourceFileFullPath(sourcePath, false); + } + if (field == fHeaderFileDialogField) { + setHeaderFileFullPath(filePath, false); + changedFields |= HEADER_FILE_ID; + } else if (field == fSourceFileDialogField) { + setSourceFileFullPath(filePath, false); + changedFields |= SOURCE_FILE_ID; + } + handleFieldChanged(changedFields); + } + } + + public void dialogFieldChanged(DialogField field) { + int changedFields = 0; + if (field == fUseDefaultSelection) { + boolean enabled = !isUseDefaultSelected(); + fHeaderFileDialogField.setEnabled(enabled); + fSourceFileDialogField.setEnabled(enabled); + if (!enabled) { + updateFilesFromClassName(fClassNameDialogField.getText()); + } + changedFields = HEADER_FILE_ID | SOURCE_FILE_ID; + updateFileGroupEnableState(); + } + if (field == fHeaderFileDialogField) { + changedFields |= HEADER_FILE_ID; + } else if (field == fSourceFileDialogField) { + changedFields |= SOURCE_FILE_ID; + } + handleFieldChanged(changedFields); + } + } + + private IPath chooseHeaderFile() { + SourceFileSelectionDialog dialog = new SourceFileSelectionDialog(getShell()); + dialog.setTitle(NewClassWizardMessages.getString("NewClassCreationWizardPage.ChooseHeaderFileDialog.title")); //$NON-NLS-1$ + ICElement input = CoreModel.create(NewClassWizardUtil.getWorkspaceRoot()); + IProject project = getCurrentProject(); + if (project != null) + input = CoreModel.getDefault().create(project); + dialog.setInput(input); + + IPath filePath = getHeaderFileFullPath(); + if (filePath != null) { + String folderName = filePath.removeLastSegments(1).toString(); + String fileName = filePath.lastSegment(); + dialog.setInitialSelection(folderName, fileName); + } else { + filePath = getSourceFolderFullPath(); + if (filePath != null) { + dialog.setInitialSelection(filePath.toString(), null); + } + } + + if (dialog.open() == Window.OK) { + return dialog.getFilePath(); + } + return null; + } + + private IPath chooseSourceFile() { + SourceFileSelectionDialog dialog = new SourceFileSelectionDialog(getShell()); + dialog.setTitle(NewClassWizardMessages.getString("NewClassCreationWizardPage.ChooseSourceFileDialog.title")); //$NON-NLS-1$ + ICElement input = CoreModel.create(NewClassWizardUtil.getWorkspaceRoot()); + IProject project = getCurrentProject(); + if (project != null) + input = CoreModel.getDefault().create(project); + dialog.setInput(input); + + IPath filePath = getSourceFileFullPath(); + if (filePath != null) { + String folderName = filePath.removeLastSegments(1).toString(); + String fileName = filePath.lastSegment(); + dialog.setInitialSelection(folderName, fileName); + } else { + filePath = getSourceFolderFullPath(); + if (filePath != null) { + dialog.setInitialSelection(filePath.toString(), null); + } + } + + if (dialog.open() == Window.OK) { + return dialog.getFilePath(); + } + return null; + } + + /** + * update header and source file fields from the class name + */ + private void updateFilesFromClassName(String className) { + String headerName = null; + String sourceName = null; + IPath folder = getSourceFolderFullPath(); + if (className != null && className.length() > 0) { + String[] names = generateFileNames(className, folder); + if (names != null && names.length == 2) { + headerName = names[0]; + sourceName = names[1]; + } + } + fHeaderFileDialogField.setTextWithoutUpdate(headerName != null ? headerName : ""); //$NON-NLS-1$ + fSourceFileDialogField.setTextWithoutUpdate(sourceName != null ? sourceName : ""); //$NON-NLS-1$ + } + + private static final int MAX_UNIQUE_CLASSNAME = 99; + + /** + * Returns the names of the header file and source file which will be + * used when this class is created, e.g. "MyClass" -> ["MyClass.h","MyClass.cpp"] + * Note: the file names should be unique to avoid overwriting existing files. + * + * @param className the class name + * @param folder the folder where the files are to be created, or null + * @return an array of 2 Strings, containing the header file name and + * source file name, respectively. + */ + protected String[] generateFileNames(String className, IPath folder) { + String headerName = null; + String sourceName = null; + + if (folder == null) { + headerName = NewClassWizardUtil.createHeaderFileName(className); + sourceName = NewClassWizardUtil.createSourceFileName(className); + } else { + // make sure the file names are unique + String currName = className; + int count = 0; + String separator = ""; //$NON-NLS-1$ + if (Character.isDigit(className.charAt(className.length()-1))) + separator = "_"; //$NON-NLS-1$ + while (count < MAX_UNIQUE_CLASSNAME) { + String header = NewClassWizardUtil.createHeaderFileName(currName); + IPath path = folder.append(header); + if (!path.toFile().exists()) { + String source = NewClassWizardUtil.createSourceFileName(currName); + path = folder.append(source); + if (!path.toFile().exists()) { + headerName = header; + sourceName = source; + // we're done + break; + } + } + ++count; + currName = className + separator + count; //$NON-NLS-1$ + } + } + + return new String[] { headerName, sourceName }; + } + + /** + * Hook method that gets called when a field on this page has changed. + * + * @param fields Bitwise-OR'd ids of the fields that changed. + */ + protected void handleFieldChanged(int fields) { + if (fields == 0) + return; // no change + + if (fieldChanged(fields, SOURCE_FOLDER_ID)) { + fSourceFolderStatus = sourceFolderChanged(); + } + if (fieldChanged(fields, NAMESPACE_ID)) { + fNamespaceStatus = namespaceChanged(); + } + if (fieldChanged(fields, CLASS_NAME_ID)) { + fClassNameStatus = classNameChanged(); + } + if (fieldChanged(fields, BASE_CLASSES_ID)) { + fBaseClassesStatus = baseClassesChanged(); + } + if (fieldChanged(fields, METHOD_STUBS_ID)) { + fMethodStubsStatus = methodStubsChanged(); + } + if (fieldChanged(fields, HEADER_FILE_ID)) { + fHeaderFileStatus = headerFileChanged(); + } + if (fieldChanged(fields, SOURCE_FILE_ID)) { + fSourceFileStatus = sourceFileChanged(); + } + doStatusUpdate(); + } + + private boolean fieldChanged(int fields, int fieldID) { + return ((fields & fieldID) != 0); + } + + /** + * Updates the status line and the ok button according to the status of the fields + * on the page. The most severe error is taken, with the last-focused field being + * evaluated first. + */ + protected void doStatusUpdate() { + // do the last focused field first + IStatus lastStatus = getLastFocusedStatus(); + + // status of all used components + IStatus[] status = new IStatus[] { + lastStatus, + (fSourceFolderStatus != lastStatus) ? fSourceFolderStatus : STATUS_OK, + (fNamespaceStatus != lastStatus) ? fNamespaceStatus : STATUS_OK, + (fClassNameStatus != lastStatus) ? fClassNameStatus : STATUS_OK, + (fBaseClassesStatus != lastStatus) ? fBaseClassesStatus : STATUS_OK, + (fMethodStubsStatus != lastStatus) ? fMethodStubsStatus : STATUS_OK, + (fHeaderFileStatus != lastStatus) ? fHeaderFileStatus : STATUS_OK, + (fSourceFileStatus != lastStatus) ? fSourceFileStatus : STATUS_OK + }; + + // the mode severe status will be displayed and the ok button enabled/disabled. + updateStatus(status); + } + + /** + * Returns the status of the last field which had focus. + * + * @return status of the last field which had focus + */ + protected IStatus getLastFocusedStatus() { + switch (fLastFocusedField) { + case SOURCE_FOLDER_ID: + return fSourceFolderStatus; + case NAMESPACE_ID: + return fNamespaceStatus; + case CLASS_NAME_ID: + return fClassNameStatus; + case BASE_CLASSES_ID: + return fBaseClassesStatus; + case METHOD_STUBS_ID: + return fMethodStubsStatus; + case HEADER_FILE_ID: + return fHeaderFileStatus; + case SOURCE_FILE_ID: + return fSourceFileStatus; + default: + return STATUS_OK; + } + } + + /** + * Hook method that gets called when the source folder has changed. The method validates the + * source folder and returns the status of the validation. + * + * @return the status of the validation + */ + protected IStatus sourceFolderChanged() { + StatusInfo status = new StatusInfo(); + + IPath folderPath = getSourceFolderFullPath(); + if (folderPath == null) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterSourceFolderName")); //$NON-NLS-1$ + return status; + } + + IResource res = NewClassWizardUtil.getWorkspaceRoot().findMember(folderPath); + 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("NewClassCreationWizardPage.error.NotAFolder", folderPath)); //$NON-NLS-1$ + return status; + } + if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) { + if (resType == IResource.PROJECT) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.NotACProject")); //$NON-NLS-1$ + return status; + } + status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.NotInACProject")); //$NON-NLS-1$ + } + if (NewClassWizardUtil.getSourceFolder(res) == null) { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.NotASourceFolder", folderPath)); //$NON-NLS-1$ + return status; + } + } else { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.NotAFolder", folderPath)); //$NON-NLS-1$ + return status; + } + } else { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.FolderDoesNotExist", folderPath)); //$NON-NLS-1$ + return status; + } + + return status; + } + + /** + * Hook method that gets called when the namespace has changed. The method validates the + * namespace and returns the status of the validation. + * + * @return the status of the validation + */ + protected IStatus namespaceChanged() { + StatusInfo status = new StatusInfo(); + if (!isNamespaceSelected()) { + return status; + } + + // must not be empty + String namespace = getNamespaceText(); + if (namespace == null || namespace.length() == 0) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterNamespace")); //$NON-NLS-1$ + return status; + } + + IStatus val = CConventions.validateNamespaceName(namespace); + if (val.getSeverity() == IStatus.ERROR) { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidNamespace", val.getMessage())); //$NON-NLS-1$ + return status; + } else if (val.getSeverity() == IStatus.WARNING) { + status.setWarning(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.warning.NamespaceDiscouraged", val.getMessage())); //$NON-NLS-1$ + } + + IQualifiedTypeName typeName = new QualifiedTypeName(namespace); + IProject project = getCurrentProject(); + if (project != null) { + NewClassWizardUtil.prepareTypeCache(getContainer()); + + if (typeName.isQualified()) { + // make sure enclosing namespace exists + ITypeInfo parentNamespace = AllTypesCache.getType(project, ICElement.C_NAMESPACE, typeName.getEnclosingTypeName()); + if (parentNamespace == null) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnclosingNamespaceNotExists")); //$NON-NLS-1$ + return status; + } + } + + ITypeInfo[] types = AllTypesCache.getTypes(project, typeName, false, true); + if (types.length > 0) { + // look for namespace + boolean foundNamespace = false; + boolean exactMatch = false; + for (int i = 0; i < types.length; ++i) { + ITypeInfo currType = types[i]; + if (currType.getCElementType() == ICElement.C_NAMESPACE) { + foundNamespace = true; + exactMatch = currType.getQualifiedTypeName().equals(typeName); + if (exactMatch) { + // found a matching namespace + break; + } + } + } + if (foundNamespace) { + if (exactMatch) { + // we're good to go + status.setOK(); + } else { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.NamespaceExistsDifferentCase")); //$NON-NLS-1$ + } + return status; + } + // look for other types + exactMatch = false; + for (int i = 0; i < types.length; ++i) { + ITypeInfo currType = types[i]; + if (currType.getCElementType() != ICElement.C_NAMESPACE) { + exactMatch = currType.getQualifiedTypeName().equals(typeName); + if (exactMatch) { + // found a matching type + break; + } + } + } + if (exactMatch) { + status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.TypeMatchingNamespaceExists")); //$NON-NLS-1$ + } else { + status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.TypeMatchingNamespaceExistsDifferentCase")); //$NON-NLS-1$ + } + } else { + status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.NamespaceNotExists")); //$NON-NLS-1$ + } + } + + val = CConventions.validateNamespaceName(typeName.lastSegment()); + if (val.getSeverity() == IStatus.ERROR) { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidNamespace", val.getMessage())); //$NON-NLS-1$ + return status; + } + + return status; + } + + /** + * Hook method that gets called when the class name has changed. The method validates the + * class name and returns the status of the validation. + * + * @return the status of the validation + */ + protected IStatus classNameChanged() { + StatusInfo status = new StatusInfo(); + + String className = getClassName(); + // must not be empty + if (className == null || className.length() == 0) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterClassName")); //$NON-NLS-1$ + return status; + } + + IQualifiedTypeName typeName = new QualifiedTypeName(className); + if (typeName.isQualified()) { //$NON-NLS-1$ + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.QualifiedClassName")); //$NON-NLS-1$ + return status; + } + + IStatus val = CConventions.validateClassName(className); + if (val.getSeverity() == IStatus.ERROR) { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidClassName", val.getMessage())); //$NON-NLS-1$ + return status; + } else if (val.getSeverity() == IStatus.WARNING) { + status.setWarning(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.warning.ClassNameDiscouraged", val.getMessage())); //$NON-NLS-1$ + // continue checking + } + + IProject project = getCurrentProject(); + if (project != null) { + NewClassWizardUtil.prepareTypeCache(getContainer()); + + IQualifiedTypeName fullyQualifiedName = typeName; + if (isNamespaceSelected()) { + String namespace = getNamespaceText(); + if (namespace != null && namespace.length() > 0) { + fullyQualifiedName = new QualifiedTypeName(namespace).append(typeName); + } + } + + ITypeInfo[] types = AllTypesCache.getTypes(project, fullyQualifiedName, false, true); + if (types.length > 0) { + // look for class + boolean foundClass = false; + boolean exactMatch = false; + for (int i = 0; i < types.length; ++i) { + ITypeInfo currType = types[i]; + if (currType.getCElementType() == ICElement.C_CLASS + || currType.getCElementType() == ICElement.C_STRUCT) { + foundClass = true; + exactMatch = currType.getQualifiedTypeName().equals(fullyQualifiedName); + if (exactMatch) { + // found a matching class + break; + } + } + } + if (foundClass) { + if (exactMatch) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.ClassNameExists")); //$NON-NLS-1$ + } else { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.ClassNameExistsDifferentCase")); //$NON-NLS-1$ + } + return status; + } + // look for other types + exactMatch = false; + for (int i = 0; i < types.length; ++i) { + ITypeInfo currType = types[i]; + if (currType.getCElementType() != ICElement.C_CLASS + && currType.getCElementType() != ICElement.C_STRUCT) { + exactMatch = currType.getQualifiedTypeName().equals(fullyQualifiedName); + if (exactMatch) { + // found a matching type + break; + } + } + } + if (exactMatch) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.TypeMatchingClassExists")); //$NON-NLS-1$ + } else { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.TypeMatchingClassExistsDifferentCase")); //$NON-NLS-1$ + } + return status; + } + } + return status; + } + + /** + * Hook method that gets called when the list of base classes has changed. The method + * validates the base classes and returns the status of the validation. + * + * @return the status of the validation + */ + protected IStatus baseClassesChanged() { + if (verifyBaseClasses()) { + IPath folder = getSourceFolderFullPath(); + IProject project = getCurrentProject(); + if (project != null) { + IBaseClassInfo[] baseClasses = getBaseClasses(); + // make sure all classes belong to the project + if (baseClasses != null && baseClasses.length > 0) { + IStatus status = baseClassesChanged(project, folder, baseClasses); + if (status.isMultiStatus()) { + // we only want to show the most severe error + return StatusUtil.getMostSevere(status.getChildren()); + } + return status; + } + } + } + return Status.OK_STATUS; + } + + /** + * This method validates the base classes by searching through the project's + * include paths and checking if each base class is reachable. + * + * @param project the current project + * @param sourceFolder the current source folder + * @param baseClasses an array of base classes + * + * @return the status of the validation + */ + protected IStatus baseClassesChanged(IProject project, IPath sourceFolder, IBaseClassInfo[] baseClasses) { + MultiStatus status = new MultiStatus(CUIPlugin.getPluginId(), IStatus.OK, "", null); //$NON-NLS-1$ + IScannerInfoProvider provider = CCorePlugin.getDefault().getScannerInfoProvider(project); + if (provider != null) { + //TODO get the scanner info for the actual source folder + IScannerInfo info = provider.getScannerInformation(project); + if (info != null) { + String[] includePaths = info.getIncludePaths(); + for (int i = 0; i < baseClasses.length; ++i) { + IBaseClassInfo baseClass = baseClasses[i]; + ITypeInfo baseType = baseClass.getType(); + StatusInfo baseClassStatus = new StatusInfo(); + if (!NewClassWizardUtil.isTypeReachable(baseType, project, includePaths)) { + baseClassStatus.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.BaseClassNotExistsInProject", baseType.getQualifiedTypeName().toString())); //$NON-NLS-1$ + } + status.add(baseClassStatus); + } + } + } + return status; + } + + /** + * Checks if the base classes need to be verified (ie they must exist in the project) + * + * @return true if the base classes should be verified + */ + public boolean verifyBaseClasses() { + return NewClassWizardPrefs.verifyBaseClasses(); + } + + /** + * Hook method that gets called when the list of method stubs has changed. The method + * validates the method stubs and returns the status of the validation. + * + * @return the status of the validation + */ + protected IStatus methodStubsChanged() { + // do nothing + return Status.OK_STATUS; + } + + /** + * Hook method that gets called when the header file has changed. The method + * validates the header file and returns the status of the validation. + * + * @return the status of the validation + */ + protected IStatus headerFileChanged() { + StatusInfo status = new StatusInfo(); + if (isUseDefaultSelected()) { + return status; + } + + IPath path = getHeaderFileFullPath(); + if (path == null) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterHeaderFileName")); //$NON-NLS-1$ + return status; + } + + IPath sourceFolderPath = getSourceFolderFullPath(); + if (sourceFolderPath == null || !sourceFolderPath.isPrefixOf(path)) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.HeaderFileNotInSourceFolder")); //$NON-NLS-1$ + return status; + } + + boolean fileExists = false; + // check if file already exists + IResource file = NewClassWizardUtil.getWorkspaceRoot().findMember(path); + if (file != null && file.exists()) { + if (file.getType() == IResource.FILE) { + IProject proj = file.getProject(); + if (!proj.isOpen()) { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.NotAFile", path)); //$NON-NLS-1$ + return status; + } + + fileExists = true; + if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) { + status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.NotInACProject")); //$NON-NLS-1$ + } else { + status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.HeaderFileExists")); //$NON-NLS-1$ + } + } else { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.NotAFile")); //$NON-NLS-1$ + return status; + } + } + + // check if folder exists + IPath folderPath = path.removeLastSegments(1).makeRelative(); + IResource folder = NewClassWizardUtil.getWorkspaceRoot().findMember(folderPath); + if (folder == null || !folder.exists() || (folder.getType() != IResource.PROJECT && folder.getType() != IResource.FOLDER)) { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.FolderDoesNotExist", folderPath)); //$NON-NLS-1$ + return status; + } + + if (!fileExists) { + IStatus val = CConventions.validateHeaderFileName(getCurrentProject(), path.lastSegment()); + if (val.getSeverity() == IStatus.ERROR) { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidHeaderFileName", val.getMessage())); //$NON-NLS-1$ + return status; + } else if (val.getSeverity() == IStatus.WARNING) { + status.setWarning(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.warning.HeaderFileNameDiscouraged", val.getMessage())); //$NON-NLS-1$ + } + } + return status; + } + + /** + * Hook method that gets called when the source file has changed. The method + * validates the source file and returns the status of the validation. + * + * @return the status of the validation + */ + protected IStatus sourceFileChanged() { + StatusInfo status = new StatusInfo(); + if (isUseDefaultSelected()) { + return status; + } + + IPath path = getSourceFileFullPath(); + if (path == null) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.EnterSourceFileName")); //$NON-NLS-1$ + return status; + } + + IPath sourceFolderPath = getSourceFolderFullPath(); + if (sourceFolderPath == null || !sourceFolderPath.isPrefixOf(path)) { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.SourceFileNotInSourceFolder")); //$NON-NLS-1$ + return status; + } + + boolean fileExists = false; + // check if file already exists + IResource file = NewClassWizardUtil.getWorkspaceRoot().findMember(path); + if (file != null && file.exists()) { + if (file.getType() == IResource.FILE) { + IProject proj = file.getProject(); + if (!proj.isOpen()) { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.NotAFile", path)); //$NON-NLS-1$ + return status; + } + + fileExists = true; + if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) { + status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.NotInACProject")); //$NON-NLS-1$ + } else { + status.setWarning(NewClassWizardMessages.getString("NewClassCreationWizardPage.warning.SourceFileExists")); //$NON-NLS-1$ + } + } else { + status.setError(NewClassWizardMessages.getString("NewClassCreationWizardPage.error.NotAFile")); //$NON-NLS-1$ + return status; + } + } + + // check if folder exists + IPath folderPath = path.removeLastSegments(1).makeRelative(); + IResource folder = NewClassWizardUtil.getWorkspaceRoot().findMember(folderPath); + if (folder == null || !folder.exists() || (folder.getType() != IResource.PROJECT && folder.getType() != IResource.FOLDER)) { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.FolderDoesNotExist", folderPath)); //$NON-NLS-1$ + return status; + } + + if (!fileExists) { + IStatus val = CConventions.validateSourceFileName(getCurrentProject(), path.lastSegment()); + if (val.getSeverity() == IStatus.ERROR) { + status.setError(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.error.InvalidSourceFileName", val.getMessage())); //$NON-NLS-1$ + return status; + } else if (val.getSeverity() == IStatus.WARNING) { + status.setWarning(NewClassWizardMessages.getFormattedString("NewClassCreationWizardPage.warning.SourceFileNameDiscouraged", val.getMessage())); //$NON-NLS-1$ + } + } + return status; + } + + // -------- Code Generation --------- + + /** + * Creates the new class using the entered field values. + * + * @param monitor a progress monitor to report progress. + * @throws CoreException Thrown when the creation failed. + * @throws InterruptedException Thrown when the operation was cancelled. + */ + public void createClass(IProgressMonitor monitor) throws CoreException, InterruptedException { + fCreatedClass = null; + fCreatedHeaderFile = null; + fCreatedSourceFile = null; + + createClass( + getHeaderFileFullPath(), + getSourceFileFullPath(), + getClassName(), + isNamespaceSelected() ? getNamespaceText() : null, + getBaseClasses(), + getSelectedMethodStubs(), monitor); + } + + /** + * Returns whether the generated header and source files should be + * opened in editors after the finish button is pressed. + * + * @return true if the header and source file should be + * displayed + */ + public boolean openClassInEditor() { + return NewClassWizardPrefs.openClassInEditor(); + } + + /** + * Creates a new class. + * + * @param headerPath the header file path + * @param sourcePath the source file path + * @param className the class name + * @param namespace the namespace + * @param baseClasses array of base classes + * @param methodStubs array of method stubs + * @param monitor a progress monitor + * @throws CoreException if the creation failed + * @throws InterruptedException if the operation was cancelled + */ + protected void createClass(IPath headerPath, IPath sourcePath, String className, String namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs, IProgressMonitor monitor) throws CoreException, InterruptedException { + NewClassCodeGenerator generator = new NewClassCodeGenerator( + headerPath, + sourcePath, + className, + namespace, + baseClasses, + methodStubs); + generator.createClass(monitor); + + fCreatedClass = generator.getCreatedClass(); + fCreatedHeaderFile = generator.getCreatedHeaderFile(); + fCreatedSourceFile = generator.getCreatedSourceFile(); + } + + /** + * Returns the created class. The method only returns a valid class + * after createClass has been called. + * + * @return the created class + * @see #createClass(IProgressMonitor) + */ + public ICElement getCreatedClass() { + return fCreatedClass; + } + + /** + * Returns the created header file. The method only returns a valid file + * after createClass has been called. + * + * @return the created header file + * @see #createClass(IProgressMonitor) + */ + public IFile getCreatedHeaderFile() { + return fCreatedHeaderFile; + } + + /** + * Returns the created source file. The method only returns a valid file + * after createClass has been called. + * + * @return the created source file + * @see #createClass(IProgressMonitor) + */ + public IFile getCreatedSourceFile() { + return fCreatedSourceFile; + } +}