diff --git a/core/org.eclipse.cdt.ui/.settings/.api_filters b/core/org.eclipse.cdt.ui/.settings/.api_filters
new file mode 100644
index 00000000000..d75b37633f2
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/.settings/.api_filters
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.cdt.ui" version="2">
+    <resource path="src/org/eclipse/cdt/ui/wizards/NewClassCreationWizardPage.java" type="org.eclipse.cdt.ui.wizards.NewClassCreationWizardPage">
+        <filter id="338755678">
+            <message_arguments>
+                <message_argument value="org.eclipse.cdt.ui.wizards.NewClassCreationWizardPage"/>
+                <message_argument value="DEFAULT_METHOD_STUBS"/>
+            </message_arguments>
+        </filter>
+        <filter id="338755678">
+            <message_arguments>
+                <message_argument value="org.eclipse.cdt.ui.wizards.NewClassCreationWizardPage"/>
+                <message_argument value="fUseDefaultSelection"/>
+            </message_arguments>
+        </filter>
+        <filter id="338792546">
+            <message_arguments>
+                <message_argument value="org.eclipse.cdt.ui.wizards.NewClassCreationWizardPage"/>
+                <message_argument value="isUseDefaultSelected()"/>
+            </message_arguments>
+        </filter>
+        <filter id="338792546">
+            <message_arguments>
+                <message_argument value="org.eclipse.cdt.ui.wizards.NewClassCreationWizardPage"/>
+                <message_argument value="setUseDefaultSelection(boolean, boolean)"/>
+            </message_arguments>
+        </filter>
+        <filter id="388194388">
+            <message_arguments>
+                <message_argument value="org.eclipse.cdt.ui.wizards.NewClassCreationWizardPage"/>
+                <message_argument value="ALL_FIELDS"/>
+                <message_argument value="127"/>
+            </message_arguments>
+        </filter>
+    </resource>
+</component>
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java
index b7333b61081..d53a69d6ff0 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java
@@ -9,6 +9,7 @@
  *     Rational Software - initial implementation
  *     Anton Leherbauer (Wind River Systems)
  *     Jens Elmenthaler (Verigy) - http://bugs.eclipse.org/235586
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.internal.corext.codemanipulation;
 
@@ -24,7 +25,6 @@ import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.ProjectScope;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.preferences.IScopeContext;
@@ -67,7 +67,7 @@ import org.eclipse.cdt.internal.corext.util.Strings;
 import org.eclipse.cdt.internal.ui.viewsupport.ProjectTemplateStore;
 
 public class StubUtility {
-	private static final String[] EMPTY= new String[0];
+	private static final String[] EMPTY= {};
 	
 	private StubUtility() {
 	}
@@ -76,57 +76,110 @@ public class StubUtility {
 	 * Don't use this method directly, use CodeGeneration.
 	 * @see org.eclipse.cdt.ui.CodeGeneration#getHeaderFileContent(ITranslationUnit, String, String, String)
 	 */	
-	public static String getHeaderFileContent(ITranslationUnit tu, String fileComment, String typeComment, String declarations, String lineDelimiter) throws CoreException {
-		return getHeaderFileContent(getDefaultFileTemplate(tu), tu, fileComment, typeComment, declarations, lineDelimiter);
+	public static String getHeaderFileContent(ITranslationUnit tu, String declarations,
+			String fileComment, String includes, String namespaceBegin,	String namespaceEnd,
+			String namespaceName, String typeComment, String typeName,
+			String lineDelimiter) throws CoreException {
+		return getHeaderFileContent(getDefaultFileTemplate(tu), tu, declarations, fileComment,
+				includes, namespaceBegin, namespaceEnd, namespaceName, typeComment, typeName,
+				lineDelimiter);
 	}
 
 	/*
 	 * Don't use this method directly, use CodeGeneration.
 	 * @see org.eclipse.cdt.ui.CodeGeneration#getHeaderFileContent(Template, ITranslationUnit, String, String, String)
 	 */	
-	public static String getHeaderFileContent(Template template, ITranslationUnit tu, String fileComment, String typeComment, String declarations, String lineDelimiter) throws CoreException {
+	public static String getHeaderFileContent(Template template, ITranslationUnit tu,
+			String declarations, String fileComment, String includes, String namespaceBegin,
+			String namespaceEnd, String namespaceName, String typeComment, String typeName,
+			String lineDelimiter) throws CoreException {
 		if (template == null) {
 			return null;
 		}
 		ICProject project= tu.getCProject();
 		CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter);
 		context.setTranslationUnitVariables(tu);
-		context.setVariable(CodeTemplateContextType.TYPE_COMMENT, typeComment != null ? typeComment : ""); //$NON-NLS-1$
-		context.setVariable(CodeTemplateContextType.FILE_COMMENT, fileComment != null ? fileComment : ""); //$NON-NLS-1$
-		context.setVariable(CodeTemplateContextType.DECLARATIONS, declarations != null ? declarations : ""); //$NON-NLS-1$
-		context.setVariable(CodeTemplateContextType.TYPENAME, new Path(tu.getElementName()).removeFileExtension().toString());
 		String includeGuardSymbol= generateIncludeGuardSymbol(tu.getResource(), project);
+		context.setVariable(CodeTemplateContextType.DECLARATIONS, declarations != null ? declarations : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.FILE_COMMENT, fileComment != null ? fileComment : ""); //$NON-NLS-1$
 		context.setVariable(CodeTemplateContextType.INCLUDE_GUARD_SYMBOL, includeGuardSymbol != null ? includeGuardSymbol : ""); //$NON-NLS-1$
-		
-		String[] fullLine= { CodeTemplateContextType.FILE_COMMENT, CodeTemplateContextType.TYPE_COMMENT, CodeTemplateContextType.DECLARATIONS };
-		return evaluateTemplate(context, template, fullLine);
+		context.setVariable(CodeTemplateContextType.INCLUDES, includes != null ? includes : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.NAMESPACE_BEGIN, namespaceBegin != null ? namespaceBegin : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.NAMESPACE_END, namespaceEnd != null ? namespaceEnd : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.NAMESPACE_NAME, namespaceName != null ? namespaceName : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.TYPE_COMMENT, typeComment != null ? typeComment : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.TYPENAME, typeName != null ? typeName : ""); //$NON-NLS-1$
+		String[] fullLine= {
+				CodeTemplateContextType.DECLARATIONS, CodeTemplateContextType.FILE_COMMENT,
+				CodeTemplateContextType.INCLUDES,
+				CodeTemplateContextType.NAMESPACE_BEGIN, CodeTemplateContextType.NAMESPACE_END,
+				CodeTemplateContextType.TYPE_COMMENT
+			};
+
+		String text = evaluateTemplate(context, template, fullLine);
+		if (!text.endsWith(lineDelimiter))
+			text += lineDelimiter;
+		return text;
 	}
 
 	/*
 	 * Don't use this method directly, use CodeGeneration.
-	 * @see org.eclipse.cdt.ui.CodeGeneration#getBodyFileContent(ITranslationUnit, String, String, String)
+	 * @see org.eclipse.cdt.ui.CodeGeneration#getBodyFileContent(ITranslationUnit, String, String, String, String, String, String, String, String, String)
 	 */	
-	public static String getBodyFileContent(ITranslationUnit tu, String fileComment, String typeComment, String declarations, String lineDelimiter) throws CoreException {
-		return getBodyFileContent(getDefaultFileTemplate(tu), tu, fileComment, typeComment, declarations, lineDelimiter);
+	public static String getBodyFileContent(ITranslationUnit tu,
+			String declarations, String fileComment, String includes, String namespaceBegin,
+			String namespaceEnd, String namespaceName, String typeComment, String typeName,
+			String lineDelimiter) throws CoreException {
+		return getBodyFileContent(getDefaultFileTemplate(tu), tu, declarations, fileComment,
+				includes, namespaceBegin, namespaceEnd, namespaceName, typeComment, typeName,
+				lineDelimiter);
 	}
 
 	/*
 	 * Don't use this method directly, use CodeGeneration.
-	 * @see org.eclipse.cdt.ui.CodeGeneration#getBodyFileContent(Template, ITranslationUnit, String, String, String)
+	 * @see org.eclipse.cdt.ui.CodeGeneration#getBodyFileContent(Template, ITranslationUnit, String, String, String, String, String, String, String, String, String)
 	 */	
-	public static String getBodyFileContent(Template template, ITranslationUnit tu, String fileComment, String typeComment, String declarations, String lineDelimiter) throws CoreException {
+	public static String getBodyFileContent(Template template, ITranslationUnit tu,
+			String declarations, String fileComment, String includes, String namespaceBegin,
+			String namespaceEnd, String namespaceName, String typeComment, String typeName,
+			String lineDelimiter) throws CoreException {
 		if (template == null) {
 			return null;
 		}
 		ICProject project= tu.getCProject();
 		CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter);
 		context.setTranslationUnitVariables(tu);
-		context.setVariable(CodeTemplateContextType.TYPE_COMMENT, typeComment != null ? typeComment : ""); //$NON-NLS-1$
-		context.setVariable(CodeTemplateContextType.FILE_COMMENT, fileComment != null ? fileComment : ""); //$NON-NLS-1$
 		context.setVariable(CodeTemplateContextType.DECLARATIONS, declarations != null ? declarations : ""); //$NON-NLS-1$
-		
-		String[] fullLine= { CodeTemplateContextType.FILE_COMMENT, CodeTemplateContextType.TYPE_COMMENT, CodeTemplateContextType.DECLARATIONS };
-		return evaluateTemplate(context, template, fullLine);
+		context.setVariable(CodeTemplateContextType.FILE_COMMENT, fileComment != null ? fileComment : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.INCLUDES, includes != null ? includes : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.NAMESPACE_BEGIN, namespaceBegin != null ? namespaceBegin : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.NAMESPACE_END, namespaceEnd != null ? namespaceEnd : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.NAMESPACE_NAME, namespaceName != null ? namespaceName : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.TYPE_COMMENT, typeComment != null ? typeComment : ""); //$NON-NLS-1$
+		context.setVariable(CodeTemplateContextType.TYPENAME, typeName != null ? typeName : ""); //$NON-NLS-1$
+		String[] fullLine= {
+				CodeTemplateContextType.DECLARATIONS, CodeTemplateContextType.FILE_COMMENT,
+				CodeTemplateContextType.INCLUDES,
+				CodeTemplateContextType.NAMESPACE_BEGIN, CodeTemplateContextType.NAMESPACE_END,
+				CodeTemplateContextType.TYPE_COMMENT
+			};
+		String text = evaluateTemplate(context, template, fullLine);
+		if (!text.endsWith(lineDelimiter))
+			text += lineDelimiter;
+		return text;
+	}
+
+	/*
+	 * Don't use this method directly, use CodeGeneration.
+	 * @see org.eclipse.cdt.ui.CodeGeneration#getTestFileContent(ITranslationUnit, String, String, String)
+	 */	
+	public static String getTestFileContent(ITranslationUnit tu, String declarations,
+			String fileComment, String includes, String namespaceBegin, String namespaceEnd,
+			String namespaceName, String typeName, String lineDelimiter)
+					throws CoreException {
+		return getBodyFileContent(getTestFileTemplate(tu), tu, declarations, fileComment,
+				includes, namespaceBegin, namespaceEnd, namespaceName, null, typeName,
+				lineDelimiter);
 	}
 
 	public static String getFileContent(Template template, IFile file, String lineDelimiter) throws CoreException {
@@ -147,7 +200,31 @@ public class StubUtility {
 		context.setVariable(CodeTemplateContextType.INCLUDE_GUARD_SYMBOL, includeGuardSymbol != null ? includeGuardSymbol : ""); //$NON-NLS-1$
 		context.setResourceVariables(file);
 		String[] fullLine= { CodeTemplateContextType.FILE_COMMENT };
-		return evaluateTemplate(context, template, fullLine);
+		
+		String text = evaluateTemplate(context, template, fullLine);
+		if (!text.endsWith(lineDelimiter))
+			text += lineDelimiter;
+		return text;
+	}
+
+	/*
+	 * Don't use this method directly, use CodeGeneration.
+	 */
+	public static String getClassBodyContent(ICProject project, String className,
+			String classMemberDeclarations, String lineDelimiter) throws CoreException {
+		Template template= getCodeTemplate(CodeTemplateContextType.CLASS_BODY_ID, project);
+		if (template == null) {
+			return classMemberDeclarations;
+		}
+		CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter);
+		context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, className);
+		context.setVariable(CodeTemplateContextType.DECLARATIONS, classMemberDeclarations != null ? classMemberDeclarations : ""); //$NON-NLS-1$
+		String str= evaluateTemplate(context, template,
+				new String[] { CodeTemplateContextType.DECLARATIONS });
+		if (str == null && classMemberDeclarations != null && !Strings.containsOnlyWhitespaces(classMemberDeclarations)) {
+			return classMemberDeclarations;
+		}
+		return str;
 	}
 
 	/*
@@ -158,6 +235,26 @@ public class StubUtility {
 		return getMethodBodyContent(templateId, project, typeName, methodName, bodyStatement, lineDelimiter);
 	}
 
+	/*
+	 * Don't use this method directly, use CodeGeneration.
+	 */
+	public static String getMethodBodyContent(String templateId, ICProject project, String typeName,
+			String methodName, String bodyStatement, String lineDelimiter) throws CoreException {
+		Template template= getCodeTemplate(templateId, project);
+		if (template == null) {
+			return bodyStatement;
+		}
+		CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter);
+		context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, methodName);
+		context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName);
+		context.setVariable(CodeTemplateContextType.BODY_STATEMENT, bodyStatement != null ? bodyStatement : ""); //$NON-NLS-1$
+		String str= evaluateTemplate(context, template, new String[] { CodeTemplateContextType.BODY_STATEMENT });
+		if (str == null && bodyStatement != null && !Strings.containsOnlyWhitespaces(bodyStatement)) {
+			return bodyStatement;
+		}
+		return str;
+	}
+
 	/*
 	 * Don't use this method directly, use CodeGeneration.
 	 */
@@ -177,20 +274,29 @@ public class StubUtility {
 	/*
 	 * Don't use this method directly, use CodeGeneration.
 	 */
-	public static String getMethodBodyContent(String templateId, ICProject project, String typeName, String methodName, String bodyStatement, String lineDelimiter) throws CoreException {
-		Template template= getCodeTemplate(templateId, project);
+	public static String getNamespaceBeginContent(ICProject project, String namespaceName,
+			String lineDelimiter) throws CoreException {
+		Template template= getCodeTemplate(CodeTemplateContextType.NAMESPACE_BEGIN_ID, project);
 		if (template == null) {
-			return bodyStatement;
+			return null;
 		}
 		CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter);
-		context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, methodName);
-		context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName);
-		context.setVariable(CodeTemplateContextType.BODY_STATEMENT, bodyStatement != null ? bodyStatement : ""); //$NON-NLS-1$
-		String str= evaluateTemplate(context, template, new String[] { CodeTemplateContextType.BODY_STATEMENT });
-		if (str == null && bodyStatement != null && !Strings.containsOnlyWhitespaces(bodyStatement)) {
-			return bodyStatement;
+		context.setVariable(CodeTemplateContextType.NAMESPACE_NAME, namespaceName);
+		return evaluateTemplate(context, template, EMPTY);
+	}
+
+	/*
+	 * Don't use this method directly, use CodeGeneration.
+	 */
+	public static String getNamespaceEndContent(ICProject project, String namespaceName,
+			String lineDelimiter) throws CoreException {
+		Template template= getCodeTemplate(CodeTemplateContextType.NAMESPACE_END_ID, project);
+		if (template == null) {
+			return null;
 		}
-		return str;
+		CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter);
+		context.setVariable(CodeTemplateContextType.NAMESPACE_NAME, namespaceName);
+		return evaluateTemplate(context, template, EMPTY);
 	}
 
 	/*
@@ -512,6 +618,14 @@ public class StubUtility {
 		return getCodeTemplate(templateId, tu.getCProject());
 	}
 
+	private static Template getTestFileTemplate(ITranslationUnit tu) {
+		String templateId= null;
+		if (tu.isCXXLanguage() && !tu.isHeaderUnit()) {
+			templateId= CodeTemplateContextType.CPP_TESTFILE_ID;
+		}
+		return getCodeTemplate(templateId, tu.getCProject());
+	}
+
 	private static Template getCodeTemplate(String id, ICProject cProject) {
 		return getCodeTemplate(id, cProject != null ? cProject.getProject() : null);
 	}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java
index 5ca6fe3864c..2d1270cb151 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CodeTemplateContextType.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Anton Leherbauer (Wind River Systems)
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.internal.corext.template.c;
 
@@ -22,7 +23,7 @@ import org.eclipse.cdt.core.model.ICProject;
 import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility;
 
 public class CodeTemplateContextType extends FileTemplateContextType {
-	/* context types */
+	/* Context types */
 	private static final String CONTEXTTYPE_PREFIX= "org.eclipse.cdt.ui.text.codetemplates."; //$NON-NLS-1$
 
 	public static final String CPPSOURCEFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_CXXSOURCE + FileTemplateContextType.CONTEXTTYPE_SUFFIX;
@@ -31,9 +32,11 @@ public class CodeTemplateContextType extends FileTemplateContextType {
 	public static final String CHEADERFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_CHEADER + FileTemplateContextType.CONTEXTTYPE_SUFFIX;
 	public static final String ASMSOURCEFILE_CONTEXTTYPE= CCorePlugin.CONTENT_TYPE_ASMSOURCE + FileTemplateContextType.CONTEXTTYPE_SUFFIX;
 
-	public static final String METHODBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "methodbody_context"; //$NON-NLS-1$
+	public static final String NAMESPACE_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "namespace_context"; //$NON-NLS-1$
+	public static final String CLASS_BODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "class_context"; //$NON-NLS-1$
 	public static final String CONSTRUCTORBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "constructorbody_context"; //$NON-NLS-1$
 	public static final String DESTRUCTORBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "destructorbody_context"; //$NON-NLS-1$
+	public static final String METHODBODY_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "methodbody_context"; //$NON-NLS-1$
 	public static final String FILECOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "filecomment_context"; //$NON-NLS-1$
 	public static final String TYPECOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "typecomment_context"; //$NON-NLS-1$
 	public static final String FIELDCOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "fieldcomment_context"; //$NON-NLS-1$
@@ -41,16 +44,20 @@ public class CodeTemplateContextType extends FileTemplateContextType {
 	public static final String CONSTRUCTORCOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "constructorcomment_context"; //$NON-NLS-1$
 	public static final String DESTRUCTORCOMMENT_CONTEXTTYPE= CONTEXTTYPE_PREFIX + "destructorcomment_context"; //$NON-NLS-1$
 
-	/* templates */
+	/* Templates */
 	private static final String CODETEMPLATES_PREFIX= "org.eclipse.cdt.ui.text.codetemplates."; //$NON-NLS-1$
 	public static final String COMMENT_SUFFIX= "comment"; //$NON-NLS-1$
-
-	public static final String ASM_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "asmsourcefile"; //$NON-NLS-1$
-	public static final String CPP_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "cppsourcefile"; //$NON-NLS-1$
-	public static final String CPP_HEADERFILE_ID= CODETEMPLATES_PREFIX + "cppheaderfile"; //$NON-NLS-1$
-	public static final String C_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "csourcefile"; //$NON-NLS-1$
-	public static final String C_HEADERFILE_ID= CODETEMPLATES_PREFIX + "cheaderfile"; //$NON-NLS-1$
-	public static final String METHODSTUB_ID= CODETEMPLATES_PREFIX + "methodbody"; //$NON-NLS-1$
+	
+	public static final String ASM_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "asmsourcefile"; //$NON-NLS-1$	
+	public static final String CPP_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "cppsourcefile"; //$NON-NLS-1$	
+	public static final String CPP_HEADERFILE_ID= CODETEMPLATES_PREFIX + "cppheaderfile"; //$NON-NLS-1$	
+	public static final String CPP_TESTFILE_ID= CODETEMPLATES_PREFIX + "cpptestfile"; //$NON-NLS-1$	
+	public static final String C_SOURCEFILE_ID= CODETEMPLATES_PREFIX + "csourcefile"; //$NON-NLS-1$	
+	public static final String C_HEADERFILE_ID= CODETEMPLATES_PREFIX + "cheaderfile"; //$NON-NLS-1$	
+	public static final String NAMESPACE_BEGIN_ID= CODETEMPLATES_PREFIX + "namespace_begin"; //$NON-NLS-1$	
+	public static final String NAMESPACE_END_ID= CODETEMPLATES_PREFIX + "namespace_end"; //$NON-NLS-1$	
+	public static final String CLASS_BODY_ID= CODETEMPLATES_PREFIX + "class_body"; //$NON-NLS-1$	
+	public static final String METHODSTUB_ID= CODETEMPLATES_PREFIX + "methodbody"; //$NON-NLS-1$	
 	public static final String CONSTRUCTORSTUB_ID= CODETEMPLATES_PREFIX + "constructorbody"; //$NON-NLS-1$
 	public static final String DESTRUCTORSTUB_ID= CODETEMPLATES_PREFIX + "destructorbody"; //$NON-NLS-1$
 	public static final String FILECOMMENT_ID= CODETEMPLATES_PREFIX + "file" + COMMENT_SUFFIX; //$NON-NLS-1$
@@ -60,7 +67,7 @@ public class CodeTemplateContextType extends FileTemplateContextType {
 	public static final String CONSTRUCTORCOMMENT_ID= CODETEMPLATES_PREFIX + "constructor" + COMMENT_SUFFIX; //$NON-NLS-1$
 	public static final String DESTRUCTORCOMMENT_ID= CODETEMPLATES_PREFIX + "destructor" + COMMENT_SUFFIX; //$NON-NLS-1$
 
-	/* resolver types */
+	/* Resolver types */
 	public static final String ENCLOSING_METHOD= "enclosing_method"; //$NON-NLS-1$
 	public static final String ENCLOSING_TYPE= "enclosing_type"; //$NON-NLS-1$
 	public static final String BODY_STATEMENT= "body_statement"; //$NON-NLS-1$
@@ -70,11 +77,16 @@ public class CodeTemplateContextType extends FileTemplateContextType {
 	public static final String RETURN_TYPE= "return_type"; //$NON-NLS-1$
 
 	public static final String TYPENAME= "type_name"; //$NON-NLS-1$
+	public static final String NAMESPACE_NAME= "namespace_name"; //$NON-NLS-1$
+	public static final String BASE_CLASSES= "base_classes"; //$NON-NLS-1$
 	public static final String INCLUDE_GUARD_SYMBOL= "include_guard_symbol"; //$NON-NLS-1$
 
 	public static final String DECLARATIONS= "declarations"; //$NON-NLS-1$
 	public static final String TYPE_COMMENT= "typecomment"; //$NON-NLS-1$
 	public static final String FILE_COMMENT= "filecomment"; //$NON-NLS-1$
+	public static final String INCLUDES= "includes"; //$NON-NLS-1$
+	public static final String NAMESPACE_BEGIN= "namespace_begin"; //$NON-NLS-1$
+	public static final String NAMESPACE_END= "namespace_end"; //$NON-NLS-1$
 
 	/**
 	 * Resolver that resolves to the variable defined in the context.
@@ -123,34 +135,53 @@ public class CodeTemplateContextType extends FileTemplateContextType {
 
 		if (CPPSOURCEFILE_CONTEXTTYPE.equals(contextTypeId)) {
 			addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); 
-			addResolver(new CodeTemplateVariableResolver(TYPE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_typecomment)); 
 			addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); 
+			addResolver(new CodeTemplateVariableResolver(INCLUDES, TemplateMessages.CodeTemplateContextType_variable_description_includes)); 
+			addResolver(new CodeTemplateVariableResolver(NAMESPACE_BEGIN, TemplateMessages.CodeTemplateContextType_variable_description_namespace_begin)); 
+			addResolver(new CodeTemplateVariableResolver(NAMESPACE_END, TemplateMessages.CodeTemplateContextType_variable_description_namespace_end)); 
+			addResolver(new CodeTemplateVariableResolver(NAMESPACE_NAME, TemplateMessages.CodeTemplateContextType_variable_description_namespace_name)); 
+			addResolver(new CodeTemplateVariableResolver(TYPE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_typecomment)); 
+			addResolver(new CodeTemplateVariableResolver(TYPENAME, TemplateMessages.CodeTemplateContextType_variable_description_class_name));
 			addTranslationUnitVariables();
 		} else if (CPPHEADERFILE_CONTEXTTYPE.equals(contextTypeId)) {
-			addResolver(new CodeTemplateVariableResolver(INCLUDE_GUARD_SYMBOL, TemplateMessages.CodeTemplateContextType_variable_description_include_guard_symbol)); 
 			addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); 
-			addResolver(new CodeTemplateVariableResolver(TYPE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_typecomment)); 
 			addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); 
+			addResolver(new CodeTemplateVariableResolver(INCLUDE_GUARD_SYMBOL, TemplateMessages.CodeTemplateContextType_variable_description_include_guard_symbol)); 
+			addResolver(new CodeTemplateVariableResolver(INCLUDES, TemplateMessages.CodeTemplateContextType_variable_description_includes)); 
+			addResolver(new CodeTemplateVariableResolver(NAMESPACE_BEGIN, TemplateMessages.CodeTemplateContextType_variable_description_namespace_begin)); 
+			addResolver(new CodeTemplateVariableResolver(NAMESPACE_END, TemplateMessages.CodeTemplateContextType_variable_description_namespace_end)); 
+			addResolver(new CodeTemplateVariableResolver(NAMESPACE_NAME, TemplateMessages.CodeTemplateContextType_variable_description_namespace_name)); 
+			addResolver(new CodeTemplateVariableResolver(TYPE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_typecomment)); 
+			addResolver(new CodeTemplateVariableResolver(TYPENAME, TemplateMessages.CodeTemplateContextType_variable_description_class_name));
 			addTranslationUnitVariables();
 		} else if (CSOURCEFILE_CONTEXTTYPE.equals(contextTypeId)) {
 			addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); 
 			addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); 
+			addResolver(new CodeTemplateVariableResolver(INCLUDES, TemplateMessages.CodeTemplateContextType_variable_description_includes)); 
 			addTranslationUnitVariables();
 		} else if (CHEADERFILE_CONTEXTTYPE.equals(contextTypeId)) {
-			addResolver(new CodeTemplateVariableResolver(INCLUDE_GUARD_SYMBOL, TemplateMessages.CodeTemplateContextType_variable_description_include_guard_symbol)); 
 			addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_typedeclaration)); 
 			addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment)); 
+			addResolver(new CodeTemplateVariableResolver(INCLUDE_GUARD_SYMBOL, TemplateMessages.CodeTemplateContextType_variable_description_include_guard_symbol)); 
+			addResolver(new CodeTemplateVariableResolver(INCLUDES, TemplateMessages.CodeTemplateContextType_variable_description_includes)); 
 			addTranslationUnitVariables();
 		} else if (METHODBODY_CONTEXTTYPE.equals(contextTypeId)) {
-			addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); 
+			addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); 
 			addResolver(new CodeTemplateVariableResolver(ENCLOSING_METHOD, TemplateMessages.CodeTemplateContextType_variable_description_enclosingmethod)); 
-			addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); 
+			addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); 
 		} else if (CONSTRUCTORBODY_CONTEXTTYPE.equals(contextTypeId)) {
-			addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); 
 			addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); 
+			addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); 
 		} else if (DESTRUCTORBODY_CONTEXTTYPE.equals(contextTypeId)) {
-			addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); 
 			addResolver(new CodeTemplateVariableResolver(BODY_STATEMENT, TemplateMessages.CodeTemplateContextType_variable_description_bodystatement)); 
+			addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); 
+		} else if (CLASS_BODY_CONTEXTTYPE.equals(contextTypeId)) {
+			addResolver(new CodeTemplateVariableResolver(DECLARATIONS, TemplateMessages.CodeTemplateContextType_variable_description_class_members)); 
+			addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_class_name)); 
+		} else if (NAMESPACE_CONTEXTTYPE.equals(contextTypeId)) {
+			addResolver(new CodeTemplateVariableResolver(NAMESPACE_BEGIN, TemplateMessages.CodeTemplateContextType_variable_description_namespace_begin)); 
+			addResolver(new CodeTemplateVariableResolver(NAMESPACE_END, TemplateMessages.CodeTemplateContextType_variable_description_namespace_end)); 
+			addResolver(new CodeTemplateVariableResolver(NAMESPACE_NAME, TemplateMessages.CodeTemplateContextType_variable_description_namespace_name)); 
 		} else if (TYPECOMMENT_CONTEXTTYPE.equals(contextTypeId)) {
 			addResolver(new CodeTemplateVariableResolver(TYPENAME, TemplateMessages.CodeTemplateContextType_variable_description_typename)); 
 			addTranslationUnitVariables();
@@ -159,13 +190,13 @@ public class CodeTemplateContextType extends FileTemplateContextType {
 			addTranslationUnitVariables();
 			fIsComment= true;
 		} else if (FIELDCOMMENT_CONTEXTTYPE.equals(contextTypeId)) {
-			addResolver(new CodeTemplateVariableResolver(FIELD_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_fieldtype)); 
 			addResolver(new CodeTemplateVariableResolver(FIELD, TemplateMessages.CodeTemplateContextType_variable_description_fieldname)); 
+			addResolver(new CodeTemplateVariableResolver(FIELD_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_fieldtype)); 
 			addTranslationUnitVariables();
 			fIsComment= true;
 		} else if (METHODCOMMENT_CONTEXTTYPE.equals(contextTypeId)) {
-			addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); 
 			addResolver(new CodeTemplateVariableResolver(ENCLOSING_METHOD, TemplateMessages.CodeTemplateContextType_variable_description_enclosingmethod)); 
+			addResolver(new CodeTemplateVariableResolver(ENCLOSING_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_enclosingtype)); 
 			addResolver(new CodeTemplateVariableResolver(RETURN_TYPE, TemplateMessages.CodeTemplateContextType_variable_description_returntype)); 
 			addTranslationUnitVariables();
 			fIsComment= true;
@@ -203,9 +234,11 @@ public class CodeTemplateContextType extends FileTemplateContextType {
 		asmContextType.addResolver(new CodeTemplateVariableResolver(FILE_COMMENT, TemplateMessages.CodeTemplateContextType_variable_description_filecomment));
 		registry.addContextType(asmContextType);
 
-		registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.METHODBODY_CONTEXTTYPE));
+		registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.NAMESPACE_CONTEXTTYPE));
+		registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.CLASS_BODY_CONTEXTTYPE));
 		registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.CONSTRUCTORBODY_CONTEXTTYPE));
 		registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.DESTRUCTORBODY_CONTEXTTYPE));
+		registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.METHODBODY_CONTEXTTYPE));
 
 		registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.FILECOMMENT_CONTEXTTYPE));
 		registry.addContextType(new CodeTemplateContextType(CodeTemplateContextType.TYPECOMMENT_CONTEXTTYPE));
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java
index fa3b10f93a5..5e159189d82 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.java
@@ -9,19 +9,13 @@
  *     IBM Corporation - initial API and implementation
  *     QnX Software System
  *     Anton Leherbauer (Wind River Systems)
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.internal.corext.template.c;
 
 import org.eclipse.osgi.util.NLS;
 
 public final class TemplateMessages extends NLS {
-
-	private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.corext.template.c.TemplateMessages";//$NON-NLS-1$
-
-	private TemplateMessages() {
-		// Do not instantiate
-	}
-
 	public static String CContextType_variable_description_file;
 	public static String CContextType_variable_description_file_base;
 	public static String CContextType_variable_description_enclosing_method;
@@ -32,11 +26,18 @@ public final class TemplateMessages extends NLS {
 	
 	public static String CodeTemplateContextType_variable_description_todo;
 	public static String CodeTemplateContextType_variable_description_typedeclaration;
+	public static String CodeTemplateContextType_variable_description_class_members;
 	public static String CodeTemplateContextType_variable_description_fieldname;
 	public static String CodeTemplateContextType_variable_description_fieldtype;
 	public static String CodeTemplateContextType_variable_description_typecomment;
 	public static String CodeTemplateContextType_variable_description_enclosingtype;
+	public static String CodeTemplateContextType_variable_description_includes;
+	public static String CodeTemplateContextType_variable_description_namespace_begin;
+	public static String CodeTemplateContextType_variable_description_namespace_end;
+	public static String CodeTemplateContextType_variable_description_namespace_name;
 	public static String CodeTemplateContextType_variable_description_typename;
+	public static String CodeTemplateContextType_variable_description_class_name;
+	public static String CodeTemplateContextType_variable_description_base_classes;
 	public static String CodeTemplateContextType_variable_description_include_guard_symbol;
 	public static String CodeTemplateContextType_variable_description_enclosingmethod;
 	public static String CodeTemplateContextType_variable_description_bodystatement;
@@ -60,6 +61,10 @@ public final class TemplateMessages extends NLS {
 	public static String FileTemplateContextType_variable_description_projectname;
 
 	static {
-		NLS.initializeMessages(BUNDLE_NAME, TemplateMessages.class);
+		NLS.initializeMessages(TemplateMessages.class.getName(), TemplateMessages.class);
+	}
+
+	// Do not instantiate.
+	private TemplateMessages() {
 	}
 }
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties
index b4401be3b06..95a3b7dac63 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/TemplateMessages.properties
@@ -9,6 +9,7 @@
 #     IBM Corporation - initial API and implementation
 #	  QnX Software System
 #     Anton Leherbauer (Wind River Systems)
+#     Sergey Prigogin (Google)
 #########################################
 
 CContextType_variable_description_file=Name of source file
@@ -21,11 +22,18 @@ CContextType_variable_description_todo=Todo task tag
 
 CodeTemplateContextType_variable_description_todo=Todo task tag
 CodeTemplateContextType_variable_description_typedeclaration=Generated type declaration
+CodeTemplateContextType_variable_description_class_members=Generated declarations of class members
 CodeTemplateContextType_variable_description_fieldname=The name of field
 CodeTemplateContextType_variable_description_fieldtype=The type of the field
 CodeTemplateContextType_variable_description_typecomment=Content of code template 'Comments > Types'
 CodeTemplateContextType_variable_description_enclosingtype=The enclosing type
+CodeTemplateContextType_variable_description_includes=Generated include statements
+CodeTemplateContextType_variable_description_namespace_begin=Beginning of namespace declaration
+CodeTemplateContextType_variable_description_namespace_end=End of namespace declaration
+CodeTemplateContextType_variable_description_namespace_name=Name of the current namespace
+CodeTemplateContextType_variable_description_class_name=Name of the current class
 CodeTemplateContextType_variable_description_typename=Name of the current type
+CodeTemplateContextType_variable_description_base_classes=Base clauses
 CodeTemplateContextType_variable_description_include_guard_symbol=Include guard symbol
 CodeTemplateContextType_variable_description_enclosingmethod=The enclosing method
 CodeTemplateContextType_variable_description_bodystatement=Return statement or super call
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java
index 10e822ba8c7..8242e9cdd5b 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/util/Strings.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,12 +24,11 @@ import org.eclipse.osgi.util.TextProcessor;
 import org.eclipse.cdt.core.formatter.IndentManipulation;
 import org.eclipse.cdt.core.model.ICProject;
 
-
 /**
  * Helper class to provide String manipulation functions not available in standard JDK.
  */
 public class Strings {
-	
+
 	private Strings() {}
 	
 	/**
@@ -46,7 +45,7 @@ public class Strings {
 
 	private static final String C_ELEMENT_DELIMITERS= TextProcessor.getDefaultDelimiters() + "<>(),?{} "; //$NON-NLS-1$
 
-	public static boolean startsWithIgnoreCase(String text, String prefix) {
+	public static boolean startsWithIgnoreCase(CharSequence text, CharSequence prefix) {
 		int textLength= text.length();
 		int prefixLength= prefix.length();
 		if (textLength < prefixLength)
@@ -58,6 +57,17 @@ public class Strings {
 		return true;
 	}
 
+	public static boolean endsWith(CharSequence containing, CharSequence contained) {
+		int start = containing.length() - contained.length();
+		if (start < 0)
+			return false;
+		for (int i = start, j = 0; i < containing.length(); i++, j++) {
+			if (containing.charAt(i) != contained.charAt(j))
+				return false;
+		}
+		return true;
+	}
+
 	public static String removeNewLine(String message) {
 		StringBuffer result= new StringBuffer();
 		int current= 0;
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java
index 83eb79e4e5d..e081001666b 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CodeTemplateBlock.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,6 +9,7 @@
  *     IBM Corporation - initial API and implementation
  *     Anton Leherbauer (Wind River Systems)
  *     Andrew Ferguson (Symbian)
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.internal.ui.preferences;
 
@@ -112,7 +113,7 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock {
 			} else if (element == FILE_NODE) {
 				return getFileTemplateContextTypes();
 			} else if (element instanceof TemplateContextType) {
-				return getTemplatesOfContextType(((TemplateContextType)element).getId());
+				return getTemplatesOfContextType(((TemplateContextType) element).getId());
 			}
 			return NO_CHILDREN;
 		}
@@ -147,7 +148,7 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock {
 		}
 		
 		/*
-		 * @see org.eclipse.jface.viewers.ViewerSorter#category(java.lang.Object)
+		 * @see org.eclipse.jface.viewers.ViewerComparator#category(java.lang.Object)
 		 */
 		@Override
 		public int category(Object element) {
@@ -181,12 +182,18 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock {
 			
 			if (CodeTemplateContextType.ASMSOURCEFILE_CONTEXTTYPE.equals(id)) {
 				return 105;
-			} else if (CodeTemplateContextType.METHODSTUB_ID.equals(id)) {
+			} else if (CodeTemplateContextType.NAMESPACE_BEGIN_ID.equals(id)) {
 				return 106;
-			} else if (CodeTemplateContextType.CONSTRUCTORSTUB_ID.equals(id)) {
+			} else if (CodeTemplateContextType.NAMESPACE_END_ID.equals(id)) {
 				return 107;
-			} else if (CodeTemplateContextType.DESTRUCTORSTUB_ID.equals(id)) {
+			} else if (CodeTemplateContextType.CLASS_BODY_ID.equals(id)) {
 				return 108;
+			} else if (CodeTemplateContextType.METHODSTUB_ID.equals(id)) {
+				return 109;
+			} else if (CodeTemplateContextType.CONSTRUCTORSTUB_ID.equals(id)) {
+				return 110;
+			} else if (CodeTemplateContextType.DESTRUCTORSTUB_ID.equals(id)) {
+				return 111;
 			} else if (CodeTemplateContextType.FILECOMMENT_ID.equals(id)) {
 				return 1;
 			} else if (CodeTemplateContextType.TYPECOMMENT_ID.equals(id)) {
@@ -251,18 +258,24 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock {
 				return (String) element;
 			}
 			if (element instanceof TemplateContextType) {
-				return ((TemplateContextType)element).getName();
+				return ((TemplateContextType) element).getName();
 			}
 			TemplatePersistenceData data= (TemplatePersistenceData) element;
 			String id= data.getId();
 			if (FileTemplateContextType.isFileTemplateContextType(data.getTemplate().getContextTypeId())) {
 				return data.getTemplate().getName();
-			} else if (CodeTemplateContextType.METHODSTUB_ID.equals(id)) {
-				return PreferencesMessages.CodeTemplateBlock_methodstub_label;
+			} else if (CodeTemplateContextType.NAMESPACE_BEGIN_ID.equals(id)) {
+				return PreferencesMessages.CodeTemplateBlock_namespace_begin_label;
+			} else if (CodeTemplateContextType.NAMESPACE_END_ID.equals(id)) {
+				return PreferencesMessages.CodeTemplateBlock_namespace_end_label;
+			} else if (CodeTemplateContextType.CLASS_BODY_ID.equals(id)) {
+				return PreferencesMessages.CodeTemplateBlock_class_body_label;
 			} else if (CodeTemplateContextType.CONSTRUCTORSTUB_ID.equals(id)) {
 				return PreferencesMessages.CodeTemplateBlock_constructorstub_label;
 			} else if (CodeTemplateContextType.DESTRUCTORSTUB_ID.equals(id)) {
 				return PreferencesMessages.CodeTemplateBlock_destructorstub_label;
+			} else if (CodeTemplateContextType.METHODSTUB_ID.equals(id)) {
+				return PreferencesMessages.CodeTemplateBlock_methodstub_label;
 			} else if (CodeTemplateContextType.FILECOMMENT_ID.equals(id)) {
 				return PreferencesMessages.CodeTemplateBlock_filecomment_label;
 			} else if (CodeTemplateContextType.TYPECOMMENT_ID.equals(id)) {
@@ -310,7 +323,8 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock {
 	private TemplateVariableProcessor fTemplateProcessor;
 	private ContextTypeRegistry fFileTemplateContextTypes;
 	
-	public CodeTemplateBlock(IStatusChangeListener context, IProject project, IWorkbenchPreferenceContainer container) {
+	public CodeTemplateBlock(IStatusChangeListener context, IProject project,
+			IWorkbenchPreferenceContainer container) {
 		super(context, project, getAllKeys(), container);
 		
 		fTemplateStore= new ProjectTemplateStore(project);
@@ -387,7 +401,7 @@ public class CodeTemplateBlock extends OptionsConfigurationBlock {
 		
 		fCodeTemplateTree.doFillIntoGrid(composite, 3);
 		LayoutUtil.setHorizontalSpan(fCodeTemplateTree.getLabelControl(null), 2);
-		LayoutUtil.setHorizontalGrabbing(fCodeTemplateTree.getTreeControl(null));
+		LayoutUtil.setHorizontalGrabbing(fCodeTemplateTree.getTreeControl(null), true);
 		
 		fPatternViewer= createViewer(composite, 2);
 		
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java
index 8ee4b80cc10..b42b007b03b 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java
@@ -186,14 +186,6 @@ public class NameStyleBlock extends OptionsConfigurationBlock {
 				.setSeedNameGenerator(fieldCategory)
 				.setNameValidator(IDENTIFIER_VALIDATOR);
 		Category fileCategory = new Category(PreferencesMessages.NameStyleBlock_files_node);
-		new Category(PreferencesMessages.NameStyleBlock_cpp_source_node,
-				PreferencesMessages.NameStyleBlock_cpp_source_node_description, EXAMPLE_CLASS_NAME,
-				fileCategory)
-				.setCapitalizationKey(KEY_CPP_SOURCE_CAPITALIZATION)
-				.setWordDelimiterKey(KEY_CPP_SOURCE_WORD_DELIMITER)
-				.setPrefixKey(KEY_CPP_SOURCE_PREFIX)
-				.setSuffixKey(KEY_CPP_SOURCE_SUFFIX)
-				.setNameValidator(FILENAME_VALIDATOR);
 		new Category(PreferencesMessages.NameStyleBlock_cpp_header_node,
 				PreferencesMessages.NameStyleBlock_cpp_header_node_description, EXAMPLE_CLASS_NAME,
 				fileCategory)
@@ -202,10 +194,17 @@ public class NameStyleBlock extends OptionsConfigurationBlock {
 				.setPrefixKey(KEY_CPP_HEADER_PREFIX)
 				.setSuffixKey(KEY_CPP_HEADER_SUFFIX)
 				.setNameValidator(FILENAME_VALIDATOR);
-		// TODO(sprigogin): Unhide the test name style category
+		new Category(PreferencesMessages.NameStyleBlock_cpp_source_node,
+				PreferencesMessages.NameStyleBlock_cpp_source_node_description, EXAMPLE_CLASS_NAME,
+				fileCategory)
+				.setCapitalizationKey(KEY_CPP_SOURCE_CAPITALIZATION)
+				.setWordDelimiterKey(KEY_CPP_SOURCE_WORD_DELIMITER)
+				.setPrefixKey(KEY_CPP_SOURCE_PREFIX)
+				.setSuffixKey(KEY_CPP_SOURCE_SUFFIX)
+				.setNameValidator(FILENAME_VALIDATOR);
 		new Category(PreferencesMessages.NameStyleBlock_cpp_test_node,
 				PreferencesMessages.NameStyleBlock_cpp_test_node_description, EXAMPLE_CLASS_NAME,
-				null)  // Hidden for now.
+				fileCategory)
 				.setCapitalizationKey(KEY_CPP_TEST_CAPITALIZATION)
 				.setWordDelimiterKey(KEY_CPP_TEST_WORD_DELIMITER)
 				.setPrefixKey(KEY_CPP_TEST_PREFIX)
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java
index 13cd389f659..1876973a9f9 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java
@@ -336,9 +336,13 @@ public final class PreferencesMessages extends NLS {
 	public static String CodeTemplateBlock_templates_comment_node;
 	public static String CodeTemplateBlock_templates_code_node;
 	public static String CodeTemplateBlock_templates_file_node;
-	public static String CodeTemplateBlock_methodstub_label;
+
+	public static String CodeTemplateBlock_namespace_begin_label;
+	public static String CodeTemplateBlock_namespace_end_label;
+	public static String CodeTemplateBlock_class_body_label;
 	public static String CodeTemplateBlock_constructorstub_label;
 	public static String CodeTemplateBlock_destructorstub_label;
+	public static String CodeTemplateBlock_methodstub_label;
 	public static String CodeTemplateBlock_typecomment_label;
 	public static String CodeTemplateBlock_fieldcomment_label;
 	public static String CodeTemplateBlock_filecomment_label;
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties
index 092b51a35ae..0c71a2db623 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties
@@ -389,9 +389,12 @@ CodeTemplateBlock_templates_comment_node=Comments
 CodeTemplateBlock_templates_code_node=Code
 CodeTemplateBlock_templates_file_node=Files
 
-CodeTemplateBlock_methodstub_label=Method body
+CodeTemplateBlock_namespace_begin_label=Beginning of namespace declaration
+CodeTemplateBlock_namespace_end_label=End of namespace declaration
+CodeTemplateBlock_class_body_label=Class body
 CodeTemplateBlock_constructorstub_label=Constructor body
 CodeTemplateBlock_destructorstub_label=Destructor body
+CodeTemplateBlock_methodstub_label=Method body
 CodeTemplateBlock_typecomment_label=Types
 CodeTemplateBlock_fieldcomment_label=Fields
 CodeTemplateBlock_filecomment_label=Files
@@ -406,7 +409,7 @@ CodeTemplateBlock_templates_import_button=I&mport...
 CodeTemplateBlock_templates_export_button=E&xport...
 CodeTemplateBlock_templates_exportall_button=Ex&port All...
 
-CodeTemplateBlock_createcomment_label=Automatically add comments &for new methods and classes
+CodeTemplateBlock_createcomment_label=&Automatically add comments for new methods and classes
 CodeTemplateBlock_templates_label=&Configure generated code and comments:
 CodeTemplateBlock_preview=Pa&ttern:
 
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 f64de1012c7..0631ec5985b 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2009 QNX Software Systems and others.
+ * Copyright (c) 2004, 2011 QNX Software Systems and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -10,6 +10,7 @@
  *     IBM Corporation
  *     Warren Paul (Nokia) - 173555
  *     Anton Leherbauer (Wind River Systems)
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.internal.ui.wizards.classwizard;
 
@@ -30,7 +31,10 @@ import org.eclipse.core.runtime.SubProgressMonitor;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.Document;
 import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.text.edits.DeleteEdit;
 import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MultiTextEdit;
 import org.eclipse.text.edits.TextEdit;
 
 import org.eclipse.cdt.core.CCorePlugin;
@@ -57,20 +61,24 @@ import org.eclipse.cdt.utils.PathUtil;
 import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility;
 import org.eclipse.cdt.internal.corext.util.CModelUtil;
 import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil;
+import org.eclipse.cdt.internal.corext.util.Strings;
+import org.eclipse.cdt.internal.formatter.scanner.Scanner;
+import org.eclipse.cdt.internal.formatter.scanner.Token;
 
 import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator;
 
 public class NewClassCodeGenerator {
-
-    private IPath fHeaderPath = null;
-    private IPath fSourcePath = null;
-    private String fClassName = null;
-    private IQualifiedTypeName fNamespace = null;
-    private IBaseClassInfo[] fBaseClasses = null;
-    private IMethodStub[] fMethodStubs = null;
-    private ITranslationUnit fCreatedHeaderTU = null;
-    private ITranslationUnit fCreatedSourceTU = null;
-    private ICElement fCreatedClass = null;
+    private final IPath fHeaderPath;
+    private final IPath fSourcePath;
+    private final IPath fTestPath;
+    private String fClassName;
+    private IQualifiedTypeName fNamespace;
+    private final IBaseClassInfo[] fBaseClasses;
+    private final IMethodStub[] fMethodStubs;
+    private ITranslationUnit fCreatedHeaderTU;
+    private ITranslationUnit fCreatedSourceTU;
+    private ITranslationUnit fCreatedTestTU;
+    private ICElement fCreatedClass;
 	private String fFullyQualifiedClassName;
 	private boolean fForceSourceFileCreation;
     
@@ -97,9 +105,20 @@ public class NewClassCodeGenerator {
         }
 	}
 
-    public NewClassCodeGenerator(IPath headerPath, IPath sourcePath, String className, String namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs) {
+	/**
+	 * @param headerPath the header file path
+	 * @param sourcePath the source file path
+	 * @param testPath the test file path, can be {@code null}
+	 * @param className the class name
+	 * @param namespace the namespace name
+	 * @param baseClasses the base classes
+	 * @param methodStubs the method stubs
+	 */
+    public NewClassCodeGenerator(IPath headerPath, IPath sourcePath, IPath testPath,
+    		String className, String namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs) {
         fHeaderPath = headerPath;
         fSourcePath = sourcePath;
+        fTestPath = testPath;
         if (className != null && className.length() > 0) {
             fClassName = className;
         }
@@ -125,7 +144,7 @@ public class NewClassCodeGenerator {
     
     public IFile getCreatedHeaderFile() {
         if (fCreatedHeaderTU != null) {
-            return (IFile)fCreatedHeaderTU.getResource();
+            return (IFile) fCreatedHeaderTU.getResource();
         }
         return null;
     }
@@ -136,7 +155,14 @@ public class NewClassCodeGenerator {
 
     public IFile getCreatedSourceFile() {
         if (fCreatedSourceTU != null) {
-            return (IFile)fCreatedSourceTU.getResource();
+            return (IFile) fCreatedSourceTU.getResource();
+        }
+        return null;
+    }
+
+    public IFile getCreatedTestFile() {
+        if (fCreatedTestTU != null) {
+            return (IFile) fCreatedTestTU.getResource();
         }
         return null;
     }
@@ -151,7 +177,8 @@ public class NewClassCodeGenerator {
      * @throws InterruptedException
      *             Thrown when the operation was cancelled.
      */
-    public ICElement createClass(IProgressMonitor monitor) throws CodeGeneratorException, CoreException, InterruptedException {
+    public ICElement createClass(IProgressMonitor monitor)
+    		throws CodeGeneratorException, CoreException, InterruptedException {
         if (monitor == null)
             monitor = new NullProgressMonitor();
 
@@ -159,27 +186,31 @@ public class NewClassCodeGenerator {
 
 	    ITranslationUnit headerTU = null;
         ITranslationUnit sourceTU = null;
+        ITranslationUnit testTU = null;
         ICElement createdClass = null;
 
         IWorkingCopy headerWorkingCopy = null;
         IWorkingCopy sourceWorkingCopy = null;
+        IWorkingCopy testWorkingCopy = null;
         try {
             if (fHeaderPath != null) {
-
-                // get method stubs
+                // Get method stubs
                 List<IMethodStub> publicMethods = getStubs(ASTAccessVisibility.PUBLIC, false);
                 List<IMethodStub> protectedMethods = getStubs(ASTAccessVisibility.PROTECTED, false);
                 List<IMethodStub> privateMethods = getStubs(ASTAccessVisibility.PRIVATE, false);
                 
-	            IFile headerFile = NewSourceFileGenerator.createHeaderFile(fHeaderPath, true, new SubProgressMonitor(monitor, 50));
+	            IFile headerFile = NewSourceFileGenerator.createHeaderFile(fHeaderPath, true,
+	            		new SubProgressMonitor(monitor, 50));
 	            if (headerFile != null) {
 	                headerTU = (ITranslationUnit) CoreModel.getDefault().create(headerFile);
 	
-	                // create a working copy with a new owner
+	                // Create a working copy with a new owner
 	                headerWorkingCopy = headerTU.getWorkingCopy();
 	                // headerWorkingCopy = headerTU.getSharedWorkingCopy(null, CUIPlugin.getDefault().getBufferFactory());
 
-	                String headerContent = constructHeaderFileContent(headerTU, publicMethods, protectedMethods, privateMethods, headerWorkingCopy.getBuffer().getContents(), new SubProgressMonitor(monitor, 100));
+	                String headerContent = constructHeaderFileContent(headerTU, publicMethods,
+	                		protectedMethods, privateMethods, headerWorkingCopy.getBuffer().getContents(),
+	                		new SubProgressMonitor(monitor, 100));
 	                headerContent= formatSource(headerContent, headerTU);
 	                headerWorkingCopy.getBuffer().setContents(headerContent);
 
@@ -198,24 +229,27 @@ public class NewClassCodeGenerator {
             }
 
             if (fSourcePath != null) {
-                
-                // get method stubs
+                // Get method stubs
                 List<IMethodStub> publicMethods = getStubs(ASTAccessVisibility.PUBLIC, true);
                 List<IMethodStub> protectedMethods = getStubs(ASTAccessVisibility.PROTECTED, true);
                 List<IMethodStub> privateMethods = getStubs(ASTAccessVisibility.PRIVATE, true);
                 
-                if (!fForceSourceFileCreation && publicMethods.isEmpty() && protectedMethods.isEmpty() && privateMethods.isEmpty()) {
+                if (!fForceSourceFileCreation && publicMethods.isEmpty() &&
+                		protectedMethods.isEmpty() && privateMethods.isEmpty()) {
                     monitor.worked(100);
                 } else {
-		            IFile sourceFile = NewSourceFileGenerator.createSourceFile(fSourcePath, true, new SubProgressMonitor(monitor, 50));
+		            IFile sourceFile = NewSourceFileGenerator.createSourceFile(fSourcePath, true,
+		            		new SubProgressMonitor(monitor, 50));
 		            if (sourceFile != null) {
 		                sourceTU = (ITranslationUnit) CoreModel.getDefault().create(sourceFile);
 		                monitor.worked(50);
 
-		                // create a working copy with a new owner
+		                // Create a working copy with a new owner
 		                sourceWorkingCopy = sourceTU.getWorkingCopy();
 
-		                String sourceContent = constructSourceFileContent(sourceTU, headerTU, publicMethods, protectedMethods, privateMethods, sourceWorkingCopy.getBuffer().getContents(), new SubProgressMonitor(monitor, 100));
+		                String sourceContent = constructSourceFileContent(sourceTU, headerTU,
+		                		publicMethods, protectedMethods, privateMethods,
+		                		sourceWorkingCopy.getBuffer().getContents(), new SubProgressMonitor(monitor, 100));
 		                sourceContent= formatSource(sourceContent, sourceTU);
 		                sourceWorkingCopy.getBuffer().setContents(sourceContent);
 
@@ -231,6 +265,33 @@ public class NewClassCodeGenerator {
 		            fCreatedSourceTU = sourceTU;
                 }
             }
+
+            if (fTestPath != null) {
+	            IFile testFile = NewSourceFileGenerator.createTestFile(fTestPath, true,
+	            		new SubProgressMonitor(monitor, 50));
+	            if (testFile != null) {
+	                testTU = (ITranslationUnit) CoreModel.getDefault().create(testFile);
+	                monitor.worked(50);
+
+	                // Create a working copy with a new owner
+	                testWorkingCopy = testTU.getWorkingCopy();
+
+	                String testContent = constructTestFileContent(testTU, headerTU,
+	                		testWorkingCopy.getBuffer().getContents(), new SubProgressMonitor(monitor, 100));
+	                testContent= formatSource(testContent, testTU);
+	                testWorkingCopy.getBuffer().setContents(testContent);
+
+	                if (monitor.isCanceled()) {
+	                	throw new InterruptedException();
+	                }
+
+	                testWorkingCopy.reconcile();
+	                testWorkingCopy.commit(true, monitor);
+	                monitor.worked(50);
+	            }
+	
+	            fCreatedTestTU = testTU;
+            }
         } finally {
             if (headerWorkingCopy != null) {
                 headerWorkingCopy.destroy();
@@ -238,6 +299,9 @@ public class NewClassCodeGenerator {
             if (sourceWorkingCopy != null) {
                 sourceWorkingCopy.destroy();
             }
+            if (testWorkingCopy != null) {
+                testWorkingCopy.destroy();
+            }
             monitor.done();
         }
 
@@ -254,7 +318,8 @@ public class NewClassCodeGenerator {
 	 */
 	private String formatSource(String content, ITranslationUnit tu) throws CModelException {
         String lineDelimiter= StubUtility.getLineDelimiterUsed(tu);
-        TextEdit edit= CodeFormatterUtil.format(CodeFormatter.K_TRANSLATION_UNIT, content, 0, lineDelimiter, tu.getCProject().getOptions(true));
+        TextEdit edit= CodeFormatterUtil.format(CodeFormatter.K_TRANSLATION_UNIT, content, 0, lineDelimiter,
+        		tu.getCProject().getOptions(true));
         if (edit != null) {
         	IDocument doc= new Document(content);
         	try {
@@ -269,24 +334,43 @@ public class NewClassCodeGenerator {
         return content;
 	}
 
-	public String constructHeaderFileContent(ITranslationUnit headerTU, List<IMethodStub> publicMethods, List<IMethodStub> protectedMethods, List<IMethodStub> privateMethods, String oldContents, IProgressMonitor monitor) throws CoreException {
+	public String constructHeaderFileContent(ITranslationUnit headerTU, List<IMethodStub> publicMethods,
+			List<IMethodStub> protectedMethods, List<IMethodStub> privateMethods, String oldContents,
+			IProgressMonitor monitor) throws CoreException {
         monitor.beginTask(NewClassWizardMessages.NewClassCodeGeneration_createType_task_header, 100); 
         
         String lineDelimiter= StubUtility.getLineDelimiterUsed(headerTU);
 
-		if (oldContents != null && oldContents.length() == 0)
-            oldContents = null;
-        
+    	String namespaceBegin = fNamespace == null ?
+    			null : constructNamespaceBegin(headerTU, lineDelimiter);
+    	String namespaceEnd = fNamespace == null ?
+    			null : constructNamespaceEnd(headerTU, lineDelimiter);
+    	String classDefinition = constructClassDefinition(headerTU, publicMethods, protectedMethods,
+        		privateMethods, lineDelimiter);
+
+        String includes = null;
+        if (fBaseClasses != null && fBaseClasses.length > 0) {
+            includes = constructBaseClassIncludes(headerTU, lineDelimiter,
+            		new SubProgressMonitor(monitor, 50));
+        }
 
-        StringBuffer text = new StringBuffer();
-        
-        int appendFirstCharPos = -1;
         if (oldContents != null) {
+        	if (oldContents.length() == 0) {
+        		oldContents = null;
+        	} else if (!oldContents.endsWith(lineDelimiter)) {
+        		oldContents += lineDelimiter;
+        	}
+        }
+
+        String fileContent;
+        if (oldContents != null) {
+            int appendFirstCharPos = -1;
+            StringBuilder text = new StringBuilder();
 	        int insertionPos = getClassDefInsertionPos(oldContents);
 	        if (insertionPos == -1) {
 		        text.append(oldContents);
 	        } else {
-	            // skip over whitespace
+	            // Skip over whitespace
 	            int prependLastCharPos = insertionPos - 1;
 	            while (prependLastCharPos >= 0 && Character.isWhitespace(oldContents.charAt(prependLastCharPos))) {
 	                --prependLastCharPos;
@@ -298,64 +382,137 @@ public class NewClassCodeGenerator {
 	        }
             text.append(lineDelimiter);
             
-            // insert a blank line before class definition
+            // Insert a blank line before class definition
             text.append(lineDelimiter);
-        }
-
-        if (fBaseClasses != null && fBaseClasses.length > 0) {
-            addBaseClassIncludes(headerTU, text, lineDelimiter, new SubProgressMonitor(monitor, 50));
-            text.append(lineDelimiter);
-        }
-        
-        if (fNamespace != null) {
-            beginNamespace(text, lineDelimiter);
-        }
-        
-        text.append("class "); //$NON-NLS-1$
-        text.append(fClassName);
-        addBaseClassInheritance(text);
-        text.append(lineDelimiter);
-        text.append('{');
-        text.append(lineDelimiter);
-
-        //TODO sort methods (eg constructor always first?)
-        if (!publicMethods.isEmpty()
-	            || !protectedMethods.isEmpty()
-	            || !privateMethods.isEmpty()) {
-            addMethodDeclarations(headerTU, publicMethods, protectedMethods, privateMethods, text, lineDelimiter);
-        }
-
-        text.append("};"); //$NON-NLS-1$
-        text.append(lineDelimiter);
-
-        if (fNamespace != null) {
-            endNamespace(text, lineDelimiter);
-        }
-
-        String fileContent;
-        if (oldContents != null && appendFirstCharPos != -1) {
-            // insert a blank line after class definition
-            text.append(lineDelimiter);
-            
-            // skip over any extra whitespace
-            int len = oldContents.length();
-            while (appendFirstCharPos < len && Character.isWhitespace(oldContents.charAt(appendFirstCharPos))) {
-                ++appendFirstCharPos;
+            if (namespaceBegin != null) {
+            	text.append(namespaceBegin);
+            	text.append(lineDelimiter);
+            	text.append(lineDelimiter);
             }
-            if (appendFirstCharPos < len) {
-                text.append(oldContents.substring(appendFirstCharPos));
+            text.append(classDefinition);
+            if (namespaceEnd != null) {
+            	if (!classDefinition.endsWith(lineDelimiter))
+            		text.append(lineDelimiter);
+            	text.append(lineDelimiter);
+            	text.append(namespaceEnd);
             }
+            if (appendFirstCharPos != -1) {
+                // Insert a blank line after class definition
+                text.append(lineDelimiter);
+                
+                // Skip over any extra whitespace
+                int len = oldContents.length();
+                while (appendFirstCharPos < len &&
+                		Character.isWhitespace(oldContents.charAt(appendFirstCharPos))) {
+                    ++appendFirstCharPos;
+                }
+                if (appendFirstCharPos < len) {
+                    text.append(oldContents.substring(appendFirstCharPos));
+                }
+            }
+            if (Strings.endsWith(text, lineDelimiter))
+            	text.append(lineDelimiter);
             fileContent= text.toString();
         } else {
-        	String classComment= getClassComment(headerTU, lineDelimiter);
-    		fileContent= CodeGeneration.getHeaderFileContent(headerTU, classComment, text.toString(), lineDelimiter);
+        	String namespaceName = fNamespace == null ?
+        			null : fNamespace.getFullyQualifiedName();
+        	String classComment = getClassComment(headerTU, lineDelimiter);
+    		fileContent= CodeGeneration.getHeaderFileContent(headerTU, includes, namespaceBegin,
+        			namespaceEnd, namespaceName, classComment, classDefinition, fClassName,
+        			lineDelimiter);
         }
 
         monitor.done();
         return fileContent;
     }
 
-    private int getClassDefInsertionPos(String contents) {
+	public String constructNamespaceBegin(ITranslationUnit tu, String lineDelimiter) throws CoreException {
+		StringBuilder text = new StringBuilder();
+		for (int i = 0; i < fNamespace.segmentCount(); i++) {
+		    String namespaceName = fNamespace.segment(i);
+		    if (i > 0) {
+		    	text.append(lineDelimiter);
+		    }
+		    text.append(CodeGeneration.getNamespaceBeginContent(tu, namespaceName, lineDelimiter));
+		}
+		return text.toString();
+	}
+
+	public String constructNamespaceEnd(ITranslationUnit tu, String lineDelimiter) throws CoreException {
+		StringBuilder text = new StringBuilder();
+		for (int i = fNamespace.segmentCount(); --i >= 0;) {
+		    String namespaceName = fNamespace.segment(i);
+		    text.append(CodeGeneration.getNamespaceEndContent(tu, namespaceName, lineDelimiter));
+		    if (i > 0) {
+		    	text.append(lineDelimiter);
+		    }
+		}
+		return text.toString();
+	}
+
+	public String constructClassDefinition(ITranslationUnit tu, List<IMethodStub> publicMethods,
+			List<IMethodStub> protectedMethods,	List<IMethodStub> privateMethods,
+			String lineDelimiter) throws CoreException {
+        StringBuilder code = new StringBuilder();
+        String comment = getClassComment(tu, lineDelimiter);
+        if (comment != null) {
+        	code.append(comment);
+        	code.append(lineDelimiter);
+        }
+        code.append("class "); //$NON-NLS-1$
+        code.append(fClassName);
+        code.append(constructBaseClassInheritance());
+        code.append(" {"); //$NON-NLS-1$
+    	code.append(lineDelimiter);
+		String body = constructMethodDeclarations(tu, publicMethods, protectedMethods,
+				privateMethods, lineDelimiter);
+        body = CodeGeneration.getClassBodyContent(tu, fClassName, body, lineDelimiter);
+        code.append(body);
+        if (!body.endsWith(lineDelimiter)) {
+        	code.append(lineDelimiter);
+        }
+        code.append("};"); //$NON-NLS-1$
+        return removeRedundantVisibilityLabels(code.toString());
+	}
+
+    private String removeRedundantVisibilityLabels(String code) {
+		Scanner scanner = new Scanner();
+		scanner.setSource(code.toCharArray());
+		scanner.resetTo(0, code.length());
+		IDocument doc = new Document(code);
+		try {
+			MultiTextEdit edit = new MultiTextEdit();
+			int sectionType = Token.tBADCHAR;
+			int previousTokenType = Token.tBADCHAR;
+			int previousTokenOffset = -1;
+			Token token;
+			while ((token = scanner.nextToken()) != null) {
+				if (token.type == Token.tCOLON) {
+					switch (previousTokenType) {
+					case Token.t_public:
+					case Token.t_protected:
+					case Token.t_private:
+						if (previousTokenType == sectionType) {
+							IRegion region1 = doc.getLineInformationOfOffset(previousTokenOffset);
+							IRegion region2 = doc.getLineInformationOfOffset(token.offset);
+							edit.addChild(new DeleteEdit(region1.getOffset(), region2.getOffset() + region2.getLength() - region1.getOffset()));
+						}
+						sectionType = previousTokenType;
+					}
+				}
+				previousTokenType = token.type;
+				previousTokenOffset = token.offset;
+			}
+			edit.apply(doc, 0);
+		} catch (MalformedTreeException e) {
+			CUIPlugin.log(e);
+		} catch (BadLocationException e) {
+			CUIPlugin.log(e);
+		}
+		return doc.get();
+	}
+
+	private int getClassDefInsertionPos(String contents) {
         if (contents.length() == 0) {
             return -1;
         }
@@ -412,26 +569,10 @@ public class NewClassCodeGenerator {
 		return StubUtility.doAddComments(tu.getCProject()); 
 	}
 			
-    private void beginNamespace(StringBuffer text, String lineDelimiter) {
-        for (int i = 0; i < fNamespace.segmentCount(); ++i) {
-	        text.append("namespace "); //$NON-NLS-1$
-	        text.append(fNamespace.segment(i));
-	        text.append(lineDelimiter);
-	        text.append('{');
-	        text.append(lineDelimiter);
-	        text.append(lineDelimiter);
-        }
-    }
-
-    private void endNamespace(StringBuffer text, String lineDelimiter) {
-        for (int i = 0; i < fNamespace.segmentCount(); ++i) {
-            text.append(lineDelimiter);
-	        text.append("}"); //$NON-NLS-1$
-	        text.append(lineDelimiter);
-        }
-    }
-
-    private void addMethodDeclarations(ITranslationUnit tu, List<IMethodStub> publicMethods, List<IMethodStub> protectedMethods, List<IMethodStub> privateMethods, StringBuffer text, String lineDelimiter) throws CoreException {
+    private String constructMethodDeclarations(ITranslationUnit tu, List<IMethodStub> publicMethods,
+    		List<IMethodStub> protectedMethods, List<IMethodStub> privateMethods, String lineDelimiter)
+    		throws CoreException {
+    	StringBuilder text = new StringBuilder();
         if (!publicMethods.isEmpty()) {
             text.append("public:"); //$NON-NLS-1$
             text.append(lineDelimiter);
@@ -444,6 +585,9 @@ public class NewClassCodeGenerator {
         }
 
         if (!protectedMethods.isEmpty()) {
+        	if (text.length() > 0) {
+                text.append(lineDelimiter);
+        	}
             text.append("protected:"); //$NON-NLS-1$
             text.append(lineDelimiter);
             for (IMethodStub stub : protectedMethods) {
@@ -455,6 +599,9 @@ public class NewClassCodeGenerator {
         }
 
         if (!privateMethods.isEmpty()) {
+        	if (text.length() > 0) {
+                text.append(lineDelimiter);
+        	}
             text.append("private:"); //$NON-NLS-1$
             text.append(lineDelimiter);
             for (IMethodStub stub : privateMethods) {
@@ -464,6 +611,8 @@ public class NewClassCodeGenerator {
                 text.append(lineDelimiter);
             }
         }
+
+        return text.toString();
     }
 
     private List<IMethodStub> getStubs(ASTAccessVisibility access, boolean skipInline) {
@@ -479,32 +628,35 @@ public class NewClassCodeGenerator {
         return list;
     }
 
-    private void addBaseClassInheritance(StringBuffer text) {
-        if (fBaseClasses != null && fBaseClasses.length > 0) {
-            text.append(" : "); //$NON-NLS-1$
-            for (int i = 0; i < fBaseClasses.length; ++i) {
-                IBaseClassInfo baseClass = fBaseClasses[i];
-                String baseClassName = baseClass.getType().getQualifiedTypeName().getFullyQualifiedName();
-                if (i > 0)
-                    text.append(", "); //$NON-NLS-1$
-                if (baseClass.getAccess() == ASTAccessVisibility.PRIVATE)
-                    text.append("private"); //$NON-NLS-1$
-                else if (baseClass.getAccess() == ASTAccessVisibility.PROTECTED)
-                    text.append("private"); //$NON-NLS-1$
-                else
-                    text.append("public"); //$NON-NLS-1$
-                text.append(' ');
-
-                if (baseClass.isVirtual())
-                    text.append("virtual "); //$NON-NLS-1$
-
-                text.append(baseClassName);
-            }
+    private String constructBaseClassInheritance() {
+        if (fBaseClasses == null || fBaseClasses.length == 0) {
+        	return ""; //$NON-NLS-1$
         }
+    	StringBuilder text = new StringBuilder();
+        text.append(" : "); //$NON-NLS-1$
+        for (int i = 0; i < fBaseClasses.length; ++i) {
+            IBaseClassInfo baseClass = fBaseClasses[i];
+            String baseClassName = baseClass.getType().getQualifiedTypeName().getFullyQualifiedName();
+            if (i > 0)
+                text.append(", "); //$NON-NLS-1$
+            if (baseClass.getAccess() == ASTAccessVisibility.PRIVATE)
+                text.append("private"); //$NON-NLS-1$
+            else if (baseClass.getAccess() == ASTAccessVisibility.PROTECTED)
+                text.append("private"); //$NON-NLS-1$
+            else
+                text.append("public"); //$NON-NLS-1$
+            text.append(' ');
+
+            if (baseClass.isVirtual())
+                text.append("virtual "); //$NON-NLS-1$
+
+            text.append(baseClassName);
+        }
+        return text.toString();
     }
 
-    private void addBaseClassIncludes(ITranslationUnit headerTU, StringBuffer text, String lineDelimiter, IProgressMonitor monitor) throws CodeGeneratorException {
-
+    private String constructBaseClassIncludes(ITranslationUnit headerTU, String lineDelimiter,
+    		IProgressMonitor monitor) throws CodeGeneratorException {
         monitor.beginTask(NewClassWizardMessages.NewClassCodeGeneration_createType_task_header_includePaths, 100); 
         
         ICProject cProject = headerTU.getCProject();
@@ -515,7 +667,7 @@ public class NewClassCodeGenerator {
         List<IPath> includePaths = getIncludePaths(headerTU);
         List<IPath> baseClassPaths = getBaseClassPaths(verifyBaseClasses());
         
-	    // add the missing include paths to the project
+	    // Add the missing include paths to the project
         if (createIncludePaths()) {
 	        List<IPath> newIncludePaths = getMissingIncludePaths(projectLocation, includePaths, baseClassPaths);
 	        if (!newIncludePaths.isEmpty()) {
@@ -526,7 +678,7 @@ public class NewClassCodeGenerator {
         List<IPath> systemIncludes = new ArrayList<IPath>();
         List<IPath> localIncludes = new ArrayList<IPath>();
         
-        // sort the include paths into system and local
+        // Sort the include paths into system and local
         for (IPath baseClassLocation : baseClassPaths) {
             boolean isSystemIncludePath = false;
 
@@ -540,7 +692,8 @@ public class NewClassCodeGenerator {
             if (includePath == null)
                 includePath = baseClassLocation;
             
-            // make the new #include path in the source file only point to a relative file (i.e. now that the path has been included above in the project)
+            // Make the new #include path in the source file only point to a relative file
+            // (i.e. now that the path has been included above in the project)
             includePath = includePath.removeFirstSegments(includePath.segmentCount() - 1).setDevice(null);
             
             if (isSystemIncludePath)
@@ -549,7 +702,8 @@ public class NewClassCodeGenerator {
                 localIncludes.add(includePath);
         }
         
-        // write the system include paths, e.g. #include <header.h>
+    	StringBuilder text = new StringBuilder();
+        // Write the system include paths, e.g. #include <header.h>
         for (IPath includePath : systemIncludes) {
             if (!(headerTU.getElementName().equals(includePath.toString()))) {
 			    String include = getIncludeString(includePath.toString(), true);
@@ -558,7 +712,7 @@ public class NewClassCodeGenerator {
 			}
         }
         
-        // write the local include paths, e.g. #include "header.h"
+        // Write the local include paths, e.g. #include "header.h"
         for (IPath includePath : localIncludes) {
             if (!(headerTU.getElementName().equals(includePath.toString()))) {
 			    String include = getIncludeString(includePath.toString(), false);
@@ -568,6 +722,7 @@ public class NewClassCodeGenerator {
         }
         
         monitor.done();
+        return text.toString();
     }
     
     /**
@@ -616,7 +771,8 @@ public class NewClassCodeGenerator {
                 
                 ICProject includeProject = toCProject(PathUtil.getEnclosingProject(folderToAdd));
                 if (includeProject != null) {
-                    // make sure that the include is made the same way that build properties for projects makes them, so .contains below is a valid check
+                    // Make sure that the include is made the same way that build properties for
+                	// projects makes them, so .contains below is a valid check
                     IIncludeEntry entry = CoreModel.newIncludeEntry(addToResourcePath, null, new Path(includeProject.getProject().getLocationURI().getPath()), true);
                     
                     if (!checkEntryList.contains(entry)) // if the path already exists in the #includes then don't add it
@@ -737,30 +893,49 @@ public class NewClassCodeGenerator {
 	    return list;
     }
     
-    public String constructSourceFileContent(ITranslationUnit sourceTU, ITranslationUnit headerTU, List<IMethodStub> publicMethods, List<IMethodStub> protectedMethods, List<IMethodStub> privateMethods, String oldContents, IProgressMonitor monitor) throws CoreException {
+    public String constructSourceFileContent(ITranslationUnit sourceTU, ITranslationUnit headerTU,
+    		List<IMethodStub> publicMethods, List<IMethodStub> protectedMethods,
+    		List<IMethodStub> privateMethods, String oldContents, IProgressMonitor monitor) throws CoreException {
         monitor.beginTask(NewClassWizardMessages.NewClassCodeGeneration_createType_task_source, 150); 
         
         String lineDelimiter= StubUtility.getLineDelimiterUsed(sourceTU);
-        if (oldContents != null && oldContents.length() == 0)
-            oldContents = null;
-
-        //TODO should use code templates
-        StringBuffer text = new StringBuffer();
-
         String includeString = null;
         if (headerTU != null) {
-            includeString = getHeaderIncludeString(sourceTU, headerTU, text, new SubProgressMonitor(monitor, 50));
+            includeString = getHeaderIncludeString(sourceTU, headerTU, new SubProgressMonitor(monitor, 50));
 	        if (includeString != null) {
-	            // check if file already has the include
+	            // Check if file already has the include.
 	            if (oldContents != null && hasInclude(oldContents, includeString)) {
-	                // don't bother to add it
+	                // Don't bother to add it.
 	                includeString = null;
 	            }
 	        }
         }
-        
-        if (includeString != null) {
-            if (oldContents != null) {
+
+        String methodBodies = null;
+        if (!publicMethods.isEmpty() || !protectedMethods.isEmpty() || !privateMethods.isEmpty()) {
+            // TODO sort methods (e.g. constructor always first?)
+            methodBodies = constructMethodBodies(sourceTU, publicMethods, protectedMethods,
+            		privateMethods, lineDelimiter, new SubProgressMonitor(monitor, 50));
+        }
+
+    	String namespaceBegin = fNamespace == null ?
+    			null : constructNamespaceBegin(sourceTU, lineDelimiter);
+    	String namespaceEnd = fNamespace == null ?
+    			null : constructNamespaceEnd(sourceTU, lineDelimiter);
+
+        if (oldContents != null) {
+        	if (oldContents.length() == 0) {
+        		oldContents = null;
+        	} else if (!oldContents.endsWith(lineDelimiter)) {
+        		oldContents += lineDelimiter;
+        	}
+        }
+
+    	String fileContent;
+        if (oldContents != null) {
+            StringBuilder text = new StringBuilder();
+
+        	if (includeString != null) {
     	        int insertionPos = getIncludeInsertionPos(oldContents);
     	        if (insertionPos == -1) {
     		        text.append(oldContents);
@@ -773,48 +948,106 @@ public class NewClassCodeGenerator {
                     text.append(lineDelimiter);
                     text.append(oldContents.substring(insertionPos));
     	        }
-            } else {
-                text.append(includeString);
-                text.append(lineDelimiter);
-            }
-
-            // add a blank line
+        	} else {
+        		text.append(oldContents);
+        	}
+            // Add a blank line
             text.append(lineDelimiter);
-        } else if (oldContents != null) {
-	        text.append(oldContents);
 
-	        // add a blank line
-            text.append(lineDelimiter);
-        }
-        
-        //TODO sort methods (eg constructor always first?)
-        if (publicMethods.isEmpty()
-                && protectedMethods.isEmpty()
-                && privateMethods.isEmpty()) {
-            // no methods
-        } else {
-            if (fNamespace != null) {
-                beginNamespace(text, lineDelimiter);
+            if (methodBodies != null) {
+	            if (namespaceBegin != null) {
+	            	text.append(namespaceBegin);
+	            	text.append(lineDelimiter);
+	            	text.append(lineDelimiter);
+	            }
+	            text.append(methodBodies);
+	            if (namespaceEnd != null) {
+	            	if (!methodBodies.endsWith(lineDelimiter))
+		            	text.append(lineDelimiter);
+	            	text.append(lineDelimiter);
+	            	text.append(namespaceEnd);
+	            }
             }
-
-            addMethodBodies(sourceTU, publicMethods, protectedMethods, privateMethods, text, lineDelimiter, new SubProgressMonitor(monitor, 50));
-
-            if (fNamespace != null) {
-                endNamespace(text, lineDelimiter);
-            }
-        }
-
-        String fileContent;
-        if (oldContents != null) {
+            
+            if (Strings.endsWith(text, lineDelimiter))
+            	text.append(lineDelimiter);
         	fileContent = text.toString();
         } else {
-        	fileContent= CodeGeneration.getBodyFileContent(sourceTU, null, text.toString(), lineDelimiter);
+        	String namespaceName = fNamespace == null ?
+        			null : fNamespace.getFullyQualifiedName();
+        	fileContent= CodeGeneration.getBodyFileContent(sourceTU, includeString, namespaceBegin,
+        			namespaceEnd, namespaceName, null, methodBodies, fClassName, lineDelimiter);
         }
         monitor.done();
         return fileContent;
     }
     
-    private String getHeaderIncludeString(ITranslationUnit sourceTU, ITranslationUnit headerTU, StringBuffer text, IProgressMonitor monitor) {
+    public String constructTestFileContent(ITranslationUnit testTU, ITranslationUnit headerTU,
+    		String oldContents, IProgressMonitor monitor) throws CoreException {
+        monitor.beginTask(NewClassWizardMessages.NewClassCodeGeneration_createType_task_source, 150); 
+        
+        String lineDelimiter= StubUtility.getLineDelimiterUsed(testTU);
+
+        String includeString = null;
+        if (headerTU != null) {
+            includeString = getHeaderIncludeString(testTU, headerTU, new SubProgressMonitor(monitor, 50));
+	        if (includeString != null) {
+	            // Check if file already has the include.
+	            if (oldContents != null && hasInclude(oldContents, includeString)) {
+	                // Don't bother to add it.
+	                includeString = null;
+	            }
+	        }
+        }
+        
+        if (oldContents != null) {
+        	if (oldContents.length() == 0) {
+        		oldContents = null;
+        	} else if (!oldContents.endsWith(lineDelimiter)) {
+        		oldContents += lineDelimiter;
+        	}
+        }
+
+        String fileContent;
+        if (oldContents != null) {
+            StringBuilder text = new StringBuilder();
+
+        	if (includeString != null) {
+    	        int insertionPos = getIncludeInsertionPos(oldContents);
+    	        if (insertionPos == -1) {
+    		        text.append(oldContents);
+                    text.append(lineDelimiter);
+                    text.append(includeString);
+                    text.append(lineDelimiter);
+    	        } else {
+    	            text.append(oldContents.substring(0, insertionPos));
+                    text.append(includeString);
+                    text.append(lineDelimiter);
+                    text.append(oldContents.substring(insertionPos));
+    	        }
+        	} else {
+        		text.append(oldContents);
+        	}
+
+        	if (Strings.endsWith(text, lineDelimiter))
+            	text.append(lineDelimiter);
+        	fileContent = text.toString();
+        } else {
+        	String namespaceBegin = fNamespace == null ?
+        			null : constructNamespaceBegin(testTU, lineDelimiter);
+        	String namespaceEnd = fNamespace == null ?
+        			null : constructNamespaceEnd(testTU, lineDelimiter);
+        	String namespaceName = fNamespace == null ?
+        			null : fNamespace.getFullyQualifiedName();
+        	fileContent= CodeGeneration.getTestFileContent(testTU, includeString, namespaceBegin,
+        			namespaceEnd, namespaceName, null, fClassName, lineDelimiter);
+        }
+        monitor.done();
+        return fileContent;
+    }
+    
+    private String getHeaderIncludeString(ITranslationUnit sourceTU, ITranslationUnit headerTU,
+    		IProgressMonitor monitor) {
         IProject project = headerTU.getCProject().getProject();
         IPath projectLocation = new Path(project.getLocationURI().getPath());
         IPath headerLocation = new Path(headerTU.getResource().getLocationURI().getPath());
@@ -825,7 +1058,7 @@ public class NewClassCodeGenerator {
         if (includePath != null && !projectLocation.isPrefixOf(headerLocation)) {
             isSystemIncludePath = true;
         } else if (projectLocation.isPrefixOf(headerLocation)
-                && projectLocation.isPrefixOf(sourceLocation)) {
+        		&& projectLocation.isPrefixOf(sourceLocation)) {
             includePath = PathUtil.makeRelativePath(headerLocation, sourceLocation.removeLastSegments(1));
         }
         if (includePath == null)
@@ -881,7 +1114,7 @@ public class NewClassCodeGenerator {
         //TODO temporary hack
         int includePos = contents.lastIndexOf("#include "); //$NON-NLS-1$
         if (includePos != -1) {
-            // find the end of line
+            // Find the end of line
             int startPos = includePos + "#include ".length(); //$NON-NLS-1$
             int eolPos = findLastLineChar(contents, startPos);
             if (eolPos != -1) {
@@ -894,7 +1127,10 @@ public class NewClassCodeGenerator {
         return -1;
     }
 
-    private void addMethodBodies(ITranslationUnit tu, List<IMethodStub> publicMethods, List<IMethodStub> protectedMethods, List<IMethodStub> privateMethods, StringBuffer text, String lineDelimiter, IProgressMonitor monitor) throws CoreException {
+    private String constructMethodBodies(ITranslationUnit tu, List<IMethodStub> publicMethods,
+    		List<IMethodStub> protectedMethods, List<IMethodStub> privateMethods, String lineDelimiter,
+    		IProgressMonitor monitor) throws CoreException {
+    	StringBuilder text = new StringBuilder();
         if (!publicMethods.isEmpty()) {
             for (Iterator<IMethodStub> i = publicMethods.iterator(); i.hasNext();) {
                 IMethodStub stub = i.next();
@@ -927,10 +1163,11 @@ public class NewClassCodeGenerator {
                     text.append(lineDelimiter);
             }
         }
+        return text.toString();
     }
 
     private String getIncludeString(String fileName, boolean isSystemInclude) {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         buf.append("#include "); //$NON-NLS-1$
         if (isSystemInclude)
             buf.append('<'); 
@@ -977,6 +1214,5 @@ public class NewClassCodeGenerator {
         }
         return -1;
     }
-    
 }
 
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.java
index e3fd199b6f3..3c1510f2046 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/classwizard/NewClassWizardMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2009 QNX Software Systems and others.
+ * Copyright (c) 2004, 2011 QNX Software Systems and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,19 +7,13 @@
  *
  * Contributors:
  *     QNX Software Systems - initial API and implementation
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.internal.ui.wizards.classwizard;
 
 import org.eclipse.osgi.util.NLS;
 
 public final class NewClassWizardMessages extends NLS {
-
-	private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.wizards.classwizard.NewClassWizardMessages";//$NON-NLS-1$
-
-	private NewClassWizardMessages() {
-		// Do not instantiate
-	}
-
 	public static String NewClassCreationWizard_title;
 	public static String NewClassCreationWizardPage_title;
 	public static String NewClassCreationWizardPage_description;
@@ -58,7 +52,7 @@ public final class NewClassWizardMessages extends NLS {
 	public static String NewClassCreationWizardPage_methodStubs_label;
 	public static String NewClassCreationWizardPage_error_NotAFile;
 	public static String NewClassCreationWizardPage_error_FolderDoesNotExist;
-	public static String NewClassCreationWizardPage_useDefaultLocation_label;
+	public static String NewClassCreationWizardPage_error_LocationUnknown;
 	public static String NewClassCreationWizardPage_headerFile_label;
 	public static String NewClassCreationWizardPage_headerFile_button;
 	public static String NewClassCreationWizardPage_ChooseHeaderFileDialog_title;
@@ -75,7 +69,14 @@ public final class NewClassWizardMessages extends NLS {
 	public static String NewClassCreationWizardPage_warning_SourceFileNameDiscouraged;
 	public static String NewClassCreationWizardPage_warning_SourceFileExists;
 	public static String NewClassCreationWizardPage_error_InvalidSourceFileName;
-	public static String NewClassCreationWizardPage_error_LocationUnknown;
+	public static String NewClassCreationWizardPage_testFile_label;
+	public static String NewClassCreationWizardPage_testFile_button;
+	public static String NewClassCreationWizardPage_ChooseTestFileDialog_title;
+	public static String NewClassCreationWizardPage_error_EnterTestFileName;
+	public static String NewClassCreationWizardPage_error_TestFileNotInSourceFolder;
+	public static String NewClassCreationWizardPage_warning_TestFileNameDiscouraged;
+	public static String NewClassCreationWizardPage_warning_TestFileExists;
+	public static String NewClassCreationWizardPage_error_InvalidTestFileName;
 	public static String BaseClassesListDialogField_buttons_add;
 	public static String BaseClassesListDialogField_buttons_remove;
 	public static String BaseClassesListDialogField_buttons_up;
@@ -124,6 +125,10 @@ public final class NewClassWizardMessages extends NLS {
 	public static String NewClassCodeGeneration_stub_destructor_name;
 
 	static {
-		NLS.initializeMessages(BUNDLE_NAME, NewClassWizardMessages.class);
+		NLS.initializeMessages(NewClassWizardMessages.class.getName(), NewClassWizardMessages.class);
+	}
+
+	// Do not instantiate
+	private NewClassWizardMessages() {
 	}
 }
\ No newline at end of file
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 c61eadebfb9..db06f35dc59 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
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2004, 2009 QNX Software Systems and others.
+# Copyright (c) 2004, 2011 QNX Software Systems and others.
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -9,6 +9,7 @@
 #     QNX Software Systems - Initial API and implementation
 #	  IBM Corporation
 #     Anton Leherbauer (Wind River Systems)
+#     Sergey Prigogin (Google)
 ###############################################################################
 
 # ------- NewClassCreationWizard -------
@@ -60,10 +61,10 @@ NewClassCreationWizardPage_methodStubs_label=&Method stubs:
 
 NewClassCreationWizardPage_error_NotAFile=''{0}'' is not a file.
 NewClassCreationWizardPage_error_FolderDoesNotExist=Folder ''{0}'' does not exist.
+NewClassCreationWizardPage_error_LocationUnknown=Cannot locate resource. {0}
 
-NewClassCreationWizardPage_useDefaultLocation_label=&Use default
 NewClassCreationWizardPage_headerFile_label=&Header:
-NewClassCreationWizardPage_headerFile_button=Br&owse...
+NewClassCreationWizardPage_headerFile_button=Browse...
 NewClassCreationWizardPage_ChooseHeaderFileDialog_title=Header File Selection
 NewClassCreationWizardPage_error_EnterHeaderFileName=Header file name is empty.
 NewClassCreationWizardPage_error_HeaderFileNotInSourceFolder=Header file must be inside source folder.
@@ -71,15 +72,23 @@ NewClassCreationWizardPage_warning_HeaderFileNameDiscouraged=Header file name is
 NewClassCreationWizardPage_warning_HeaderFileExists=Header file already exists. Contents will be appended.
 NewClassCreationWizardPage_error_InvalidHeaderFileName=Header file name is not valid. {0}.
 
-NewClassCreationWizardPage_sourceFile_button=Br&owse...
 NewClassCreationWizardPage_sourceFile_label=Sourc&e:
+NewClassCreationWizardPage_sourceFile_button=Browse...
 NewClassCreationWizardPage_ChooseSourceFileDialog_title=Source File Selection
 NewClassCreationWizardPage_error_EnterSourceFileName=Source file name is empty.
 NewClassCreationWizardPage_error_SourceFileNotInSourceFolder=Source file must be inside source folder.
 NewClassCreationWizardPage_warning_SourceFileNameDiscouraged=Source file name is discouraged. {0}
 NewClassCreationWizardPage_warning_SourceFileExists=Source file already exists. Contents will be appended.
 NewClassCreationWizardPage_error_InvalidSourceFileName=Source file name is not valid. {0}
-NewClassCreationWizardPage_error_LocationUnknown=Cannot locate resource. {0}
+
+NewClassCreationWizardPage_testFile_label=Unit &Test:
+NewClassCreationWizardPage_testFile_button=Browse...
+NewClassCreationWizardPage_ChooseTestFileDialog_title=Test File Selection
+NewClassCreationWizardPage_error_EnterTestFileName=Test file name is empty.
+NewClassCreationWizardPage_error_TestFileNotInSourceFolder=Test file must be inside source folder.
+NewClassCreationWizardPage_warning_TestFileNameDiscouraged=Test file name is discouraged. {0}
+NewClassCreationWizardPage_warning_TestFileExists=Test file already exists. Contents will be appended.
+NewClassCreationWizardPage_error_InvalidTestFileName=Test file name is not valid. {0}
 
 # -----------BaseClassesListDialogField -------------
 BaseClassesListDialogField_buttons_add=&Add...
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java
index 3f98b6764eb..483089096d0 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/wizards/filewizard/NewHeaderFileCreationWizardPage.java
@@ -158,7 +158,8 @@ public class NewHeaderFileCreationWizardPage extends AbstractFileCreationWizardP
 	            	fNewFileTU = (ITranslationUnit) CoreModel.getDefault().create(newFile);
 	            	if (fNewFileTU != null) {
 	            		String lineDelimiter= StubUtility.getLineDelimiterUsed(fNewFileTU);
-						String content= CodeGeneration.getHeaderFileContent(getTemplate(), fNewFileTU, null, null, lineDelimiter);
+						String content= CodeGeneration.getHeaderFileContent(getTemplate(),
+								fNewFileTU, lineDelimiter);
 						if (content != null) {
 							fNewFileTU.getBuffer().setContents(content.toCharArray());
 							fNewFileTU.save(monitor, true);
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 397e6cd86d5..5e9c6a3189e 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2007 QNX Software Systems and others.
+ * Copyright (c) 2004, 2011 QNX Software Systems and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
  * Contributors:
  *     QNX Software Systems - initial API and implementation
  *     Anton Leherbauer (Wind River Systems)
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.internal.ui.wizards.filewizard;
 
@@ -33,7 +34,6 @@ import org.eclipse.core.runtime.preferences.IPreferencesService;
 import org.eclipse.ui.dialogs.ContainerGenerator;
 
 public class NewSourceFileGenerator {
-
     /**
      * 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"
@@ -78,20 +78,51 @@ public class NewSourceFileGenerator {
     	return composer.compose(className);
     }
 
-    public static IFile createHeaderFile(IPath filePath, boolean force, IProgressMonitor monitor) throws CoreException {
+    /**
+     * Creates a file name for the unit test from the given class name. This is the file name
+     * to be used when the test is created. e.g. "MyClass" -> "MyClass_test.cpp"
+     * 
+     * @param className the class name
+     * @return the test file name for the given class
+     */
+    public static String generateTestFileNameFromClass(String className) {
+    	IPreferencesService preferences = Platform.getPreferencesService();
+    	int capitalization = preferences.getInt(CUIPlugin.PLUGIN_ID,
+    			PreferenceConstants.NAME_STYLE_CPP_TEST_CAPITALIZATION,
+    			PreferenceConstants.NAME_STYLE_CAPITALIZATION_ORIGINAL, null);
+    	String wordDelimiter = preferences.getString(CUIPlugin.PLUGIN_ID,
+    			PreferenceConstants.NAME_STYLE_CPP_TEST_WORD_DELIMITER, "", null); //$NON-NLS-1$
+    	String prefix = preferences.getString(CUIPlugin.PLUGIN_ID,
+    			PreferenceConstants.NAME_STYLE_CPP_TEST_PREFIX, "", null); //$NON-NLS-1$
+    	String suffix = preferences.getString(CUIPlugin.PLUGIN_ID,
+    			PreferenceConstants.NAME_STYLE_CPP_TEST_SUFFIX, "_test.cpp", null); //$NON-NLS-1$
+    	NameComposer composer = new NameComposer(capitalization, wordDelimiter, prefix, suffix);
+    	return composer.compose(className);
+    }
+
+    public static IFile createHeaderFile(IPath filePath, boolean force, IProgressMonitor monitor)
+    		throws CoreException {
 		return createEmptyFile(filePath, force, monitor);
     }
     
-    public static IFile createSourceFile(IPath filePath, boolean force, IProgressMonitor monitor) throws CoreException {
+    public static IFile createSourceFile(IPath filePath, boolean force, IProgressMonitor monitor)
+    		throws CoreException {
 		return createEmptyFile(filePath, force, monitor);
     }
 
-    public static IFile createEmptyFile(IPath filePath, boolean force, IProgressMonitor monitor) throws CoreException {
+    public static IFile createTestFile(IPath filePath, boolean force, IProgressMonitor monitor)
+    		throws CoreException {
+		return createEmptyFile(filePath, force, monitor);
+    }
+
+    public static IFile createEmptyFile(IPath filePath, boolean force, IProgressMonitor monitor)
+    		throws CoreException {
         ByteArrayInputStream stream = new ByteArrayInputStream(new byte[0]);
 		return createNewFile(filePath, stream, force, monitor);
     }
 
-    private static IFile createNewFile(IPath newFilePath, InputStream contents, boolean force, IProgressMonitor monitor) throws CoreException {
+    private static IFile createNewFile(IPath newFilePath, InputStream contents, boolean force,
+    		IProgressMonitor monitor) throws CoreException {
         int totalWork = 100;
         int createFileWork = totalWork;
 
@@ -122,7 +153,8 @@ public class NewSourceFileGenerator {
         return newFile;
     }
 
-    private static void createFile(IFile fileHandle, InputStream contents, boolean force, IProgressMonitor monitor) throws CoreException {
+    private static void createFile(IFile fileHandle, InputStream contents, boolean force,
+    		IProgressMonitor monitor) throws CoreException {
         if (contents == null)
             contents = new ByteArrayInputStream(new byte[0]);
 
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java
index 00f5e7e443e..10bdb306c96 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CodeGeneration.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2001, 2008 IBM Corporation and others.
+ *  Copyright (c) 2001, 2011 IBM Corporation and others.
  *  All rights reserved. This program and the accompanying materials
  *  are made available under the terms of the Eclipse Public License v1.0
  *  which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
  *  Contributors:
  *     Rational Software - initial implementation
  *     Anton Leherbauer (Wind River Systems)
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.ui;
 
@@ -18,7 +19,6 @@ import org.eclipse.cdt.core.model.ITranslationUnit;
 
 import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility;
 
-
 /**
  * Class that offers access to the templates contained in the 'Code Templates' preference page.
  * 
@@ -33,60 +33,229 @@ public class CodeGeneration {
 
 	/**
 	 * Returns the content for a new header file using the default 'header file' code template.
-	 * @param tu The translation unit to create the source for. The translation unit does not need to exist.
-	 * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be <code>null</code> if
-	 * no comment should be added.
+	 * @param tu The translation unit to create the source for. The translation unit does not need
+	 * 		to exist.
+	 * @param lineDelimiter The line delimiter to be used.
+	 * @return Returns the new content or <code>null</code> if the template is undefined or empty.
+	 * @throws CoreException
+	 * @since 5.3
+	 */
+	public static String getHeaderFileContent(Template template, ITranslationUnit tu,
+			String lineDelimiter) throws CoreException {	
+		return getHeaderFileContent(template, tu, null, null, null, null, null, null, null,
+				lineDelimiter);
+	}
+
+	/**
+	 * Returns the content for a new header file using the default 'header file' code template.
+	 * @param tu The translation unit to create the source for. The translation unit does not need
+	 * 		to exist.
+	 * @param typeComment The comment for the type to created. Used when the code template contains
+	 * 		a ${typecomment} variable. Can be <code>null</code> if no comment should be added.
 	 * @param typeContent The code of the type, including type declaration and body.
 	 * @param lineDelimiter The line delimiter to be used.
 	 * @return Returns the new content or <code>null</code> if the template is undefined or empty.
 	 * @throws CoreException
 	 */
-	public static String getHeaderFileContent(ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException {	
-		return StubUtility.getHeaderFileContent(tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter);
+	public static String getHeaderFileContent(ITranslationUnit tu, String typeComment,
+			String typeContent, String lineDelimiter) throws CoreException {	
+		return getHeaderFileContent(tu, null, null, null, null, typeComment, typeContent, null,
+				lineDelimiter);
 	}
 
 	/**
 	 * Returns the content for a new header file using the default 'header file' code template.
 	 * @param template  The file template to use or <code>null</code> for the default template
-	 * @param tu The translation unit to create the source for. The translation unit does not need to exist.
-	 * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be <code>null</code> if
-	 * no comment should be added.
+	 * @param tu The translation unit to create the source for. The translation unit does not need
+	 * 		to exist.
+	 * @param typeComment The comment for the type to created. Used when the code template contains
+	 * 		a ${typecomment} variable. Can be <code>null</code> if no comment should be added.
 	 * @param typeContent The code of the type, including type declaration and body.
 	 * @param lineDelimiter The line delimiter to be used.
 	 * @return Returns the new content or <code>null</code> if the template is undefined or empty.
 	 * @throws CoreException
 	 */
-	public static String getHeaderFileContent(Template template, ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException {	
-		return StubUtility.getHeaderFileContent(template, tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter);
+	public static String getHeaderFileContent(Template template, ITranslationUnit tu,
+			String typeComment, String typeContent, String lineDelimiter) throws CoreException {	
+		return getHeaderFileContent(template, tu, null, null, null, null, typeComment, typeContent,
+				null, lineDelimiter);
+	}
+
+	/**
+	 * Returns the content for a new header file using the default 'header file' code template.
+	 * @param tu The translation unit to create the source for. The translation unit does not need
+	 * 		to exist.
+	 * @param includes Include statements, or {@code null} if there are no includes.
+	 * @param namespaceBegin Beginning of namespace declarations, or {@code null} if there is no
+	 * 		namespace.
+	 * @param namespaceEnd End of namespace declarations, or {@code null} if there is no
+	 * 		namespace.
+	 * @param namespaceName Fully qualified namespace name, or {@code null} if there is no
+	 * 		namespace.
+	 * @param typeComment The comment for the type to created. Used when the code template contains
+	 * 		a ${typecomment} variable. Can be <code>null</code> if no comment should be added.
+	 * @param typeContent The code of the type, including type declaration and body.
+	 * @param typeName The name of the type.
+	 * @param lineDelimiter The line delimiter to be used.
+	 * @return Returns the new content or <code>null</code> if the template is undefined or empty.
+	 * @throws CoreException
+	 * @since 5.3
+	 */
+	public static String getHeaderFileContent(ITranslationUnit tu, String includes,
+			String namespaceBegin, String namespaceEnd, String namespaceName, String typeComment,
+			String typeContent, String typeName, String lineDelimiter) throws CoreException {	
+		return StubUtility.getHeaderFileContent(tu, typeContent,
+				getFileComment(tu, lineDelimiter), includes, namespaceBegin, namespaceEnd,
+				namespaceName, typeComment, typeName, lineDelimiter);
+	}
+
+	/**
+	 * Returns the content for a new header file using the default 'header file' code template.
+	 * @param template  The file template to use or <code>null</code> for the default template
+	 * @param tu The translation unit to create the source for. The translation unit does not need
+	 * 		to exist.
+	 * @param includes Include statements, or {@code null} if there are no includes.
+	 * @param namespaceBegin Beginning of namespace declarations, or {@code null} if there is no
+	 * 		namespace.
+	 * @param namespaceEnd End of namespace declarations, or {@code null} if there is no
+	 * 		namespace.
+	 * @param namespaceName Fully qualified namespace name, or {@code null} if there is no
+	 * 		namespace.
+	 * @param typeComment The comment for the type to created. Used when the code template contains
+	 * 		a ${typecomment} variable. Can be <code>null</code> if no comment should be added.
+	 * @param typeContent The code of the type, including type declaration and body.
+	 * @param typeName The name of the type.
+	 * @param lineDelimiter The line delimiter to be used.
+	 * @return Returns the new content or <code>null</code> if the template is undefined or empty.
+	 * @throws CoreException
+	 * @since 5.3
+	 */
+	public static String getHeaderFileContent(Template template, ITranslationUnit tu,
+			String includes, String namespaceBegin, String namespaceEnd, String namespaceName,
+			String typeComment, String typeContent, String typeName, String lineDelimiter)
+			throws CoreException {	
+		return StubUtility.getHeaderFileContent(template, tu, typeContent,
+				getFileComment(tu, lineDelimiter), includes, namespaceBegin, namespaceEnd,
+				namespaceName, typeComment, typeName, lineDelimiter);
 	}
 
 	/**
 	 * Returns the content for a new translation unit using the 'source file' code template.
-	 * @param tu The translation unit to create the source for. The translation unit does not need to exist.
-	 * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be <code>null</code> if
-	 * no comment should be added.
+	 * @param tu The translation unit to create the source for. The translation unit does not need
+	 * 		to exist.
+	 * @param typeComment The comment for the type to created. Used when the code template contains
+	 * 		a ${typecomment} variable. Can be <code>null</code> if no comment should be added.
 	 * @param typeContent The code of the type, including type declaration and body.
 	 * @param lineDelimiter The line delimiter to be used.
 	 * @return Returns the new content or <code>null</code> if the template is undefined or empty.
 	 * @throws CoreException
 	 */
-	public static String getBodyFileContent(ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException {	
-		return StubUtility.getBodyFileContent(tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter);
+	public static String getBodyFileContent(ITranslationUnit tu, String typeComment,
+			String typeContent, String lineDelimiter) throws CoreException {	
+		return getBodyFileContent(tu, typeContent, null, null, null, null, typeComment, null,
+				lineDelimiter);
 	}
 
 	/**
 	 * Returns the content for a new translation unit using the 'source file' code template.
 	 * @param template  The file template to use or <code>null</code> for the default template
-	 * @param tu The translation unit to create the source for. The translation unit does not need to exist.
-	 * @param typeComment The comment for the type to created. Used when the code template contains a ${typecomment} variable. Can be <code>null</code> if
-	 * no comment should be added.
+	 * @param tu The translation unit to create the source for. The translation unit does not need
+	 * 		to exist.
+	 * @param typeComment The comment for the type to created. Used when the code template contains
+	 * 		a ${typecomment} variable. Can be <code>null</code> if no comment should be added.
 	 * @param typeContent The code of the type, including type declaration and body.
 	 * @param lineDelimiter The line delimiter to be used.
 	 * @return Returns the new content or <code>null</code> if the template is undefined or empty.
 	 * @throws CoreException
 	 */
-	public static String getBodyFileContent(Template template, ITranslationUnit tu, String typeComment, String typeContent, String lineDelimiter) throws CoreException {	
-		return StubUtility.getBodyFileContent(template, tu, getFileComment(tu, lineDelimiter), typeComment, typeContent, lineDelimiter);
+	public static String getBodyFileContent(Template template, ITranslationUnit tu,
+			String typeComment, String typeContent, String lineDelimiter) throws CoreException {	
+		return getBodyFileContent(template, tu, typeContent, null, null, null, null, typeComment,
+				null, lineDelimiter);
+	}
+
+	/**
+	 * Returns the content for a new source file using the default 'source file' code template.
+	 * @param tu The translation unit to create the source for. The translation unit does not need
+	 * 		to exist.
+	 * @param includes Include statements, or {@code null} if there are no includes.
+	 * @param namespaceBegin Beginning of namespace declarations, or {@code null} if there is no
+	 * 		namespace.
+	 * @param namespaceEnd End of namespace declarations, or {@code null} if there is no
+	 * 		namespace.
+	 * @param namespaceName Fully qualified namespace name, or {@code null} if there is no
+	 * 		namespace.
+	 * @param typeComment The comment for the type to created. Used when the code template contains
+	 * 		a ${typecomment} variable. Can be <code>null</code> if no comment should be added.
+	 * @param typeContent The code of the type, including type declaration and body.
+	 * @param typeName The name of the type.
+	 * @param lineDelimiter The line delimiter to be used.
+	 * @return Returns the new content or <code>null</code> if the template is undefined or empty.
+	 * @throws CoreException
+	 * @since 5.3
+	 */
+	public static String getBodyFileContent(ITranslationUnit tu,
+			String includes, String namespaceBegin, String namespaceEnd, String namespaceName,
+			String typeComment, String typeContent, String typeName, String lineDelimiter)
+			throws CoreException {	
+		return StubUtility.getBodyFileContent(tu, typeContent, getFileComment(tu, lineDelimiter),
+				includes, namespaceBegin, namespaceEnd, namespaceName, typeComment, typeName,
+				lineDelimiter);
+	}
+
+	/**
+	 * Returns the content for a new source file using the default 'source file' code template.
+	 * @param template  The file template to use or <code>null</code> for the default template
+	 * @param tu The translation unit to create the source for. The translation unit does not need
+	 * 		to exist.
+	 * @param includes Include statements, or {@code null} if there are no includes.
+	 * @param namespaceBegin Beginning of namespace declarations, or {@code null} if there is no
+	 * 		namespace.
+	 * @param namespaceEnd End of namespace declarations, or {@code null} if there is no
+	 * 		namespace.
+	 * @param namespaceName Fully qualified namespace name, or {@code null} if there is no
+	 * 		namespace.
+	 * @param typeComment The comment for the type to created. Used when the code template contains
+	 * 		a ${typecomment} variable. Can be <code>null</code> if no comment should be added.
+	 * @param typeContent The code of the type, including type declaration and body.
+	 * @param typeName The name of the type.
+	 * @param lineDelimiter The line delimiter to be used.
+	 * @return Returns the new content or <code>null</code> if the template is undefined or empty.
+	 * @throws CoreException
+	 * @since 5.3
+	 */
+	public static String getBodyFileContent(Template template, ITranslationUnit tu,
+			String includes, String namespaceBegin, String namespaceEnd, String namespaceName,
+			String typeComment, String typeContent, String typeName, String lineDelimiter)
+			throws CoreException {	
+		return StubUtility.getBodyFileContent(template, tu, typeContent,
+				getFileComment(tu, lineDelimiter), includes, namespaceBegin, namespaceEnd,
+				namespaceName, typeComment, typeName, lineDelimiter);
+	}
+
+	/**
+	 * Returns the content for a new translation unit using the 'test file' code template.
+	 * @param tu The translation unit to create the source for. The translation unit does not need
+	 * 		to exist.
+	 * @param includes Include statements, or {@code null} if there are no includes.
+	 * @param namespaceBegin Beginning of namespace declarations, or {@code null} if there is no
+	 * 		namespace.
+	 * @param namespaceEnd End of namespace declarations, or {@code null} if there is no
+	 * 		namespace.
+	 * @param namespaceName Fully qualified namespace name, or {@code null} if there is no
+	 * 		namespace.
+	 * @param testCases The test cases code.
+	 * @param typeName The name of the type.
+	 * @param lineDelimiter The line delimiter to be used.
+	 * @return Returns the new content or <code>null</code> if the template is undefined or empty.
+	 * @throws CoreException
+	 * @since 5.3
+	 */
+	public static String getTestFileContent(ITranslationUnit tu,
+			String includes, String namespaceBegin, String namespaceEnd, String namespaceName,
+			String testCases, String typeName, String lineDelimiter) throws CoreException {	
+		return StubUtility.getTestFileContent(tu, testCases, getFileComment(tu, lineDelimiter),
+				includes, namespaceBegin, namespaceEnd, namespaceName, typeName, lineDelimiter);
 	}
 
 	/**
@@ -103,8 +272,10 @@ public class CodeGeneration {
 	 * the comment code template is empty. The returned string is unformatted and and has no indent (formatting required).
 	 * @throws CoreException Thrown when the evaluation of the code template fails.
 	 */	
-	public static String getMethodBodyContent(ITranslationUnit tu, String typeName, String methodName, String bodyStatement, String lineDelimiter) throws CoreException {
-		return StubUtility.getMethodBodyContent(tu.getCProject(), typeName, methodName, bodyStatement, lineDelimiter);
+	public static String getMethodBodyContent(ITranslationUnit tu, String typeName,
+			String methodName, String bodyStatement, String lineDelimiter) throws CoreException {
+		return StubUtility.getMethodBodyContent(tu.getCProject(), typeName, methodName,
+				bodyStatement, lineDelimiter);
 	}
 
 	/**
@@ -112,16 +283,20 @@ public class CodeGeneration {
 	 * <code>null</code> is returned if the template is empty.
 	 * <p>The returned string is unformatted and not indented.
 	 * 
-	 * @param tu The translation unit to which the method belongs. The translation unit does not need to exist.
+	 * @param tu The translation unit to which the method belongs. The translation unit
+	 * 		does not need to exist.
 	 * @param typeName Name of the type to which the constructor belongs.
 	 * @param bodyStatement The code to be entered at the place of the variable ${body_statement}. 
 	 * @param lineDelimiter The line delimiter to be used.
-	 * @return Returns the constructed body content or <code>null</code> if
-	 * the comment code template is empty. The returned string is unformatted and and has no indent (formatting required).
+	 * @return Returns the constructed body content or <code>null</code> if the comment code
+	 * 		template is empty. The returned string is unformatted and and has no indent
+	 * 		(formatting required).
 	 * @throws CoreException Thrown when the evaluation of the code template fails.
 	 */	
-	public static String getConstructorBodyContent(ITranslationUnit tu, String typeName, String bodyStatement, String lineDelimiter) throws CoreException {
-		return StubUtility.getConstructorBodyContent(tu.getCProject(), typeName, bodyStatement, lineDelimiter);
+	public static String getConstructorBodyContent(ITranslationUnit tu, String typeName,
+			String bodyStatement, String lineDelimiter) throws CoreException {
+		return StubUtility.getConstructorBodyContent(tu.getCProject(), typeName, bodyStatement,
+				lineDelimiter);
 	}
 
 	/**
@@ -129,40 +304,116 @@ public class CodeGeneration {
 	 * <code>null</code> is returned if the template is empty.
 	 * <p>The returned string is unformatted and not indented.
 	 * 
-	 * @param tu The translation unit to which the method belongs. The translation unit does not need to exist.
+	 * @param tu The translation unit to which the method belongs. The translation unit
+	 * 		does not need to exist.
 	 * @param typeName Name of the type to which the constructor belongs.
 	 * @param bodyStatement The code to be entered at the place of the variable ${body_statement}. 
 	 * @param lineDelimiter The line delimiter to be used.
-	 * @return Returns the constructed body content or <code>null</code> if
-	 * the comment code template is empty. The returned string is unformatted and and has no indent (formatting required).
+	 * @return Returns the constructed body content or <code>null</code> if the comment code
+	 * 		template is empty. The returned string is unformatted and and has no indent
+	 * 		(formatting required).
 	 * @throws CoreException Thrown when the evaluation of the code template fails.
 	 */	
-	public static String getDestructorBodyContent(ITranslationUnit tu, String typeName, String bodyStatement, String lineDelimiter) throws CoreException {
-		return StubUtility.getDestructorBodyContent(tu.getCProject(), typeName, bodyStatement, lineDelimiter);
+	public static String getDestructorBodyContent(ITranslationUnit tu, String typeName,
+			String bodyStatement, String lineDelimiter) throws CoreException {
+		return StubUtility.getDestructorBodyContent(tu.getCProject(), typeName, bodyStatement,
+				lineDelimiter);
 	}
 
 	/**
-	 * Returns the content for a new file comment using the 'file comment' code template. The returned content is unformatted and is not indented.
-	 * @param tu The translation unit to add the comment to. The translation unit does not need to exist.
+	 * Returns the content of the class definition body using the class body template.
+	 * <code>null</code> is returned if the template is empty.
+	 * <p>The returned string is unformatted and not indented.
+	 * 
+	 * @param tu The translation unit to which the method belongs. The translation unit
+	 * 		does not need to exist.
+	 * @param className The name of the class.
+	 * @param classMemberDeclarations The code to be entered at the place of the variable
+	 * 		${declarations}. 
 	 * @param lineDelimiter The line delimiter to be used.
-	 * @return Returns the new content or <code>null</code> if the code template is undefined or empty. The returned content is unformatted and is not indented.
+	 * @return Returns the constructed class body content or <code>null</code> if
+	 * 		the class body code template is empty. The returned string is unformatted and
+	 * 		has no indent (formatting required).
+	 * @throws CoreException Thrown when the evaluation of the code template fails.
+	 * @since 5.3
+	 */	
+	public static String getClassBodyContent(ITranslationUnit tu, String className,
+			String classMemberDeclarations, String lineDelimiter)
+			throws CoreException {
+		return StubUtility.getClassBodyContent(tu.getCProject(), className, classMemberDeclarations,
+				lineDelimiter);
+	}
+
+	/**
+	 * Returns the content of the beginning of a namespace declaration using the corresponding
+	 * template. <code>null</code> is returned if the template is empty.
+	 * <p>The returned string is unformatted and not indented.
+	 * 
+	 * @param tu The translation unit to which the method belongs. The translation unit
+	 * 		does not need to exist.
+	 * @param namespaceName The name of the namespace.
+	 * @param lineDelimiter The line delimiter to be used.
+	 * @return Returns the constructed beginning of a namespace declaration,or <code>null</code> if
+	 * 		the namespace code template is empty. The returned string is unformatted and has no
+	 * 		indent (formatting required).
+	 * @throws CoreException Thrown when the evaluation of the code template fails.
+	 * @since 5.3
+	 */	
+	public static String getNamespaceBeginContent(ITranslationUnit tu, String namespaceName,
+			String lineDelimiter) throws CoreException {
+		return StubUtility.getNamespaceBeginContent(tu.getCProject(), namespaceName, lineDelimiter);
+	}
+
+	/**
+	 * Returns the content of the end of a namespace declaration using the corresponding
+	 * template. <code>null</code> is returned if the template is empty.
+	 * <p>The returned string is unformatted and not indented.
+	 * 
+	 * @param tu The translation unit to which the method belongs. The translation unit
+	 * 		does not need to exist.
+	 * @param namespaceName The name of the namespace.
+	 * @param lineDelimiter The line delimiter to be used.
+	 * @return Returns the constructed end of a namespace declaration,or <code>null</code> if
+	 * 		the namespace code template is empty. The returned string is unformatted and has no
+	 * 		indent (formatting required).
+	 * @throws CoreException Thrown when the evaluation of the code template fails.
+	 * @since 5.3
+	 */	
+	public static String getNamespaceEndContent(ITranslationUnit tu, String namespaceName,
+			String lineDelimiter) throws CoreException {
+		return StubUtility.getNamespaceEndContent(tu.getCProject(), namespaceName, lineDelimiter);
+	}
+
+	/**
+	 * Returns the content for a new file comment using the 'file comment' code template.
+	 * The returned content is unformatted and is not indented.
+	 * @param tu The translation unit to add the comment to. The translation unit does not need
+	 * 		to exist.
+	 * @param lineDelimiter The line delimiter to be used.
+	 * @return Returns the new content or <code>null</code> if the code template is undefined
+	 * 		or empty. The returned content is unformatted and is not indented.
 	 * @throws CoreException Thrown when the evaluation of the code template fails.
 	 * @since 5.0
 	 */	
-	public static String getFileComment(ITranslationUnit tu, String lineDelimiter) throws CoreException {
+	public static String getFileComment(ITranslationUnit tu, String lineDelimiter)
+			throws CoreException {
 		return StubUtility.getFileComment(tu, lineDelimiter);
 	}
 	
 	/**
-	 * Returns the content for a new type comment using the 'typecomment' code template. The returned content is unformatted and is not indented.
-	 * @param tu The translation unit where the type is contained. The translation unit does not need to exist.
-	 * @param typeQualifiedName The name of the type to which the comment is added. For inner types the name must be qualified and include the outer
-	 * types names (dot separated). 
+	 * Returns the content for a new type comment using the 'typecomment' code template.
+	 * The returned content is unformatted and is not indented.
+	 * @param tu The translation unit where the type is contained. The translation unit
+	 * 		does not need to exist.
+	 * @param typeQualifiedName The name of the type to which the comment is added. For inner types
+	 * 		the name must be qualified and include the outer types names (dot separated). 
 	 * @param lineDelimiter The line delimiter to be used.
-	 * @return Returns the new content or <code>null</code> if the code template is undefined or empty. The returned content is unformatted and is not indented.
+	 * @return Returns the new content or <code>null</code> if the code template is undefined
+	 * 		or empty. The returned content is unformatted and is not indented.
 	 * @throws CoreException
 	 */	
-	public static String getClassComment(ITranslationUnit tu, String typeQualifiedName, String lineDelimiter) throws CoreException {
+	public static String getClassComment(ITranslationUnit tu, String typeQualifiedName,
+			String lineDelimiter) throws CoreException {
 		return StubUtility.getClassComment(tu, typeQualifiedName, lineDelimiter);
 	}
 
@@ -171,19 +422,23 @@ public class CodeGeneration {
 	 * <code>null</code> is returned if the template is empty.
 	 * <p>The returned string is unformatted and not indented.
 	 * 
-	 * @param tu The translation unit to which the method belongs. The translation unit does not need to exist.
+	 * @param tu The translation unit to which the method belongs. The translation unit
+	 * 		does not need to exist.
 	 * @param declaringTypeName Name of the type to which the method belongs.
 	 * @param methodName Name of the method.
 	 * @param paramNames Names of the parameters for the method.
 	 * @param excTypeSig Thrown exceptions.
 	 * @param retTypeSig Return type.
 	 * @param lineDelimiter The line delimiter to be used.
-	 * @return Returns the constructed comment or <code>null</code> if
-	 * the comment code template is empty. The returned content is unformatted and not indented (formatting required).
+	 * @return Returns the constructed comment or <code>null</code> if the comment code template
+	 * 		is empty. The returned content is unformatted and not indented (formatting required).
 	 * @throws CoreException Thrown when the evaluation of the code template fails.
 	 */
-	public static String getMethodComment(ITranslationUnit tu, String declaringTypeName, String methodName, String[] paramNames, String[] excTypeSig, String retTypeSig, String lineDelimiter) throws CoreException {
-		return StubUtility.getMethodComment(tu, declaringTypeName, methodName, paramNames, excTypeSig, retTypeSig, lineDelimiter);
+	public static String getMethodComment(ITranslationUnit tu, String declaringTypeName,
+			String methodName, String[] paramNames, String[] excTypeSig, String retTypeSig,
+			String lineDelimiter) throws CoreException {
+		return StubUtility.getMethodComment(tu, declaringTypeName, methodName, paramNames,
+				excTypeSig, retTypeSig, lineDelimiter);
 	}
 
 	/**
@@ -191,17 +446,20 @@ public class CodeGeneration {
 	 * <code>null</code> is returned if the template is empty.
 	 * <p>The returned string is unformatted and not indented.
 	 * 
-	 * @param tu The translation unit to which the method belongs. The translation unit does not need to exist.
+	 * @param tu The translation unit to which the method belongs. The translation unit
+	 * 		does not need to exist.
 	 * @param declaringTypeName Name of the type to which the method belongs.
 	 * @param paramNames Names of the parameters for the method.
 	 * @param excTypeSig Thrown exceptions.
 	 * @param lineDelimiter The line delimiter to be used.
-	 * @return Returns the constructed comment or <code>null</code> if
-	 * the comment code template is empty. The returned content is unformatted and not indented (formatting required).
+	 * @return Returns the constructed comment or <code>null</code> if the comment code template
+	 * 		is empty. The returned content is unformatted and not indented (formatting required).
 	 * @throws CoreException Thrown when the evaluation of the code template fails.
 	 */
-	public static String getConstructorComment(ITranslationUnit tu, String declaringTypeName, String[] paramNames, String[] excTypeSig, String lineDelimiter) throws CoreException {
-		return StubUtility.getConstructorComment(tu, declaringTypeName, paramNames, excTypeSig, lineDelimiter);
+	public static String getConstructorComment(ITranslationUnit tu, String declaringTypeName,
+			String[] paramNames, String[] excTypeSig, String lineDelimiter) throws CoreException {
+		return StubUtility.getConstructorComment(tu, declaringTypeName, paramNames, excTypeSig,
+				lineDelimiter);
 	}
 
 	/**
@@ -209,16 +467,17 @@ public class CodeGeneration {
 	 * <code>null</code> is returned if the template is empty.
 	 * <p>The returned string is unformatted and not indented.
 	 * 
-	 * @param tu The translation unit to which the method belongs. The translation unit does not need to exist.
+	 * @param tu The translation unit to which the method belongs. The translation unit
+	 * 		does not need to exist.
 	 * @param declaringTypeName Name of the type to which the method belongs.
 	 * @param excTypeSig Thrown exceptions.
 	 * @param lineDelimiter The line delimiter to be used.
-	 * @return Returns the constructed comment or <code>null</code> if
-	 * the comment code template is empty. The returned content is unformatted and not indented (formatting required).
+	 * @return Returns the constructed comment or <code>null</code> if the comment code template
+	 * 		is empty. The returned content is unformatted and not indented (formatting required).
 	 * @throws CoreException Thrown when the evaluation of the code template fails.
 	 */
-	public static String getDestructorComment(ITranslationUnit tu, String declaringTypeName, String[] excTypeSig, String lineDelimiter) throws CoreException {
+	public static String getDestructorComment(ITranslationUnit tu, String declaringTypeName,
+			String[] excTypeSig, String lineDelimiter) throws CoreException {
 		return StubUtility.getDestructorComment(tu, declaringTypeName, excTypeSig, lineDelimiter);
 	}
-
 }
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
index 364c948afca..f57fb9261cb 100644
--- 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
@@ -9,6 +9,7 @@
  *     QNX Software Systems - initial API and implementation
  *     IBM Corporation
  *     Warren Paul (Nokia) - 174238
+ *     Sergey Prigogin (Google)
  *******************************************************************************/
 package org.eclipse.cdt.ui.wizards;
 
@@ -29,6 +30,7 @@ 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.IDialogSettings;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.text.ITextSelection;
 import org.eclipse.jface.viewers.ISelection;
@@ -105,10 +107,18 @@ import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField;
 import org.eclipse.cdt.internal.ui.wizards.filewizard.NewSourceFileGenerator;
 
 public class NewClassCreationWizardPage extends NewElementWizardPage {
-    protected final static String PAGE_NAME = "NewClassWizardPage"; //$NON-NLS-1$
+    protected static final String PAGE_NAME = "NewClassWizardPage"; //$NON-NLS-1$
     protected static final int MAX_FIELD_CHARS = 50;
-	
-	// field IDs
+
+    // Dialog setting keys.
+    private static final String KEY_NAMESPACE_SELECTED = "namespaceSelected"; //$NON-NLS-1$
+    private static final String KEY_NAMESPACE = "namespace"; //$NON-NLS-1$
+    private static final String KEY_TEST_FILE_SELECTED = "testFileSelected"; //$NON-NLS-1$
+    private static final String KEY_STUB_SELECTED = "stubSelected"; //$NON-NLS-1$
+    private static final String KEY_STUB_VIRTUAL = "stubVirtual"; //$NON-NLS-1$
+    private static final String KEY_STUB_INLINE = "stubInline"; //$NON-NLS-1$
+    
+	// 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;
@@ -116,9 +126,11 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
     protected static final int METHOD_STUBS_ID = 16;
     protected static final int HEADER_FILE_ID = 32;
     protected static final int SOURCE_FILE_ID = 64;
+    /** @since 5.3 */
+    protected static final int TEST_FILE_ID = 128;
     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;
+            | HEADER_FILE_ID | SOURCE_FILE_ID | TEST_FILE_ID;
 	protected int fLastFocusedField = 0;
 
     protected StringButtonDialogField fSourceFolderDialogField;
@@ -127,9 +139,18 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
     protected StringDialogField fClassNameDialogField;
     protected BaseClassesListDialogField fBaseClassesDialogField;
     protected MethodStubsListDialogField fMethodStubsDialogField;
-    protected SelectionButtonDialogField fUseDefaultSelection;
     protected StringButtonDialogField fHeaderFileDialogField;
-    protected StringButtonDialogField fSourceFileDialogField;
+	protected StringButtonDialogField fSourceFileDialogField;
+    /** @since 5.3 */
+    protected StringButtonDialogField fTestFileDialogField;
+    /** @since 5.3 */
+    protected SelectionButtonDialogField fTestFileSelection;
+    /** @since 5.3 */
+    protected boolean fHeaderFileDerivedFromClassName;
+    /** @since 5.3 */
+    protected boolean fSourceFileDerivedFromClassName;
+    /** @since 5.3 */
+    protected boolean fTestFileDerivedFromClassName;
 
 	protected IStatus fSourceFolderStatus;
 	protected IStatus fNamespaceStatus;
@@ -138,10 +159,14 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 	protected IStatus fMethodStubsStatus;
 	protected IStatus fHeaderFileStatus;
 	protected IStatus fSourceFileStatus;
+	/** @since 5.3 */
+	protected IStatus fTestFileStatus;
 	protected final IStatus STATUS_OK = new StatusInfo();
 
-    protected IFile fCreatedSourceFile;
     protected IFile fCreatedHeaderFile;
+    protected IFile fCreatedSourceFile;
+    /** @since 5.3 */
+    protected IFile fCreatedTestFile;
     protected ICElement fCreatedClass;
     
     /**
@@ -150,13 +175,6 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * created.
      */
     private boolean isFirstTime = false;
-    /**
-     * the default method stubs
-     */
-    protected static final IMethodStub[] DEFAULT_METHOD_STUBS = {
-        new ConstructorMethodStub(),
-        new DestructorMethodStub()
-    };
     
     
 	/**
@@ -194,9 +212,6 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		fMethodStubsDialogField = new MethodStubsListDialogField(NewClassWizardMessages.NewClassCreationWizardPage_methodStubs_label, methodStubsAdapter);
 	    
 		FileGroupFieldAdapter fileGroupAdapter = new FileGroupFieldAdapter();
-		fUseDefaultSelection = new SelectionButtonDialogField(SWT.CHECK);
-		fUseDefaultSelection.setDialogFieldListener(fileGroupAdapter);
-		fUseDefaultSelection.setLabelText(NewClassWizardMessages.NewClassCreationWizardPage_useDefaultLocation_label);
 		fHeaderFileDialogField = new StringButtonDialogField(fileGroupAdapter);
 		fHeaderFileDialogField.setDialogFieldListener(fileGroupAdapter);
 		fHeaderFileDialogField.setLabelText(NewClassWizardMessages.NewClassCreationWizardPage_headerFile_label);
@@ -205,7 +220,17 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		fSourceFileDialogField.setDialogFieldListener(fileGroupAdapter);
 		fSourceFileDialogField.setLabelText(NewClassWizardMessages.NewClassCreationWizardPage_sourceFile_label);
 		fSourceFileDialogField.setButtonLabel(NewClassWizardMessages.NewClassCreationWizardPage_sourceFile_button);
-		
+		fTestFileSelection = new SelectionButtonDialogField(SWT.CHECK);
+		fTestFileSelection.setDialogFieldListener(fileGroupAdapter);
+		fTestFileSelection.setLabelText(NewClassWizardMessages.NewClassCreationWizardPage_testFile_label);
+		fTestFileDialogField = new StringButtonDialogField(fileGroupAdapter);
+		fTestFileDialogField.setDialogFieldListener(fileGroupAdapter);
+		fTestFileDialogField.setButtonLabel(NewClassWizardMessages.NewClassCreationWizardPage_testFile_button);
+
+	    fHeaderFileDerivedFromClassName = true;
+	    fSourceFileDerivedFromClassName = true;
+	    fTestFileDerivedFromClassName = true;
+
 		fSourceFolderStatus = STATUS_OK;
 		fNamespaceStatus = STATUS_OK;
 		fClassNameStatus = STATUS_OK;
@@ -213,12 +238,10 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		fMethodStubsStatus = STATUS_OK;
 		fHeaderFileStatus = STATUS_OK;
 		fSourceFileStatus = STATUS_OK;
+		fTestFileStatus = STATUS_OK;
 		fLastFocusedField = 0;
 		
 		isFirstTime = true;
-		
-		updateNamespaceEnableState();
-		updateFileGroupEnableState();
 	}
 	
 	// -------- UI Creation ---------
@@ -339,10 +362,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 	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();
+	    LayoutUtil.setVerticalGrabbing(listControl, false);
 		listControl.addFocusListener(new StatusFocusListener(BASE_CLASSES_ID));
 	}
 	
@@ -356,53 +376,46 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 	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();
+	    LayoutUtil.setHeightHint(listControl,
+	    		convertHeightInCharsToPixels(6) + convertHeightInCharsToPixels(1) / 2);
+	    LayoutUtil.setVerticalGrabbing(listControl, false);
 		listControl.addFocusListener(new StatusFocusListener(METHOD_STUBS_ID));
 	}
 	
 	/**
-	 * Creates the controls for the file name fields. Expects a <code>GridLayout</code> with at 
-	 * least 4 columns.
+	 * Creates the controls for the file name fields. Expects a <code>GridLayout</code> with 
+	 * at least 4 columns.
 	 * 
 	 * @param composite the parent composite
 	 * @param nColumns number of columns to span
 	 */		
 	protected void createFileControls(Composite composite, int nColumns) {
+ 		fHeaderFileDialogField.doFillIntoGrid(composite, nColumns);
+		Text textControl = fHeaderFileDialogField.getTextControl(null);
+		LayoutUtil.setWidthHint(textControl, getMaxFieldWidth());
+		textControl.addFocusListener(new StatusFocusListener(HEADER_FILE_ID));
+		
+		fSourceFileDialogField.doFillIntoGrid(composite, nColumns);
+		textControl = fSourceFileDialogField.getTextControl(null);
+		LayoutUtil.setWidthHint(textControl, getMaxFieldWidth());
+		textControl.addFocusListener(new StatusFocusListener(SOURCE_FILE_ID));
+		
 		Composite tabGroup = new Composite(composite, SWT.NONE);
 		GridLayout layout = new GridLayout();
 		layout.marginWidth = 0;
 		layout.marginHeight = 0;
  		tabGroup.setLayout(layout);
 
-		fUseDefaultSelection.doFillIntoGrid(tabGroup, 1);
+		fTestFileSelection.doFillIntoGrid(tabGroup, 1);
 		
-		LayoutUtil.setHorizontalSpan(fHeaderFileDialogField.getLabelControl(composite), 1);
-		Text textControl = fHeaderFileDialogField.getTextControl(composite);
+		textControl = fTestFileDialogField.getTextControl(composite);
 		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
 		gd.widthHint = getMaxFieldWidth();
-		gd.horizontalSpan = 1;
+		gd.horizontalSpan = 2;
 		textControl.setLayoutData(gd);
-		textControl.addFocusListener(new StatusFocusListener(HEADER_FILE_ID));
+		textControl.addFocusListener(new StatusFocusListener(TEST_FILE_ID));
 		
-		Button button = fHeaderFileDialogField.getChangeControl(composite);
-		gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
-		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);
+		Button button = fTestFileDialogField.getChangeControl(composite);
 		gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
 		gd.widthHint = SWTUtil.getButtonWidthHint(button);
 		button.setLayoutData(gd);
@@ -416,7 +429,14 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @param selection used to initialize the fields
      */
     public void init(IStructuredSelection selection) {
-    	ICElement celem = getInitialCElement(selection);
+    	if (fDialogSettings == null) {
+			fDialogSettings = getDialogSettings().getSection(PAGE_NAME);
+			if (fDialogSettings == null) {
+				fDialogSettings = getDialogSettings().addNewSection(PAGE_NAME);
+			}
+    	}
+
+		ICElement celem = getInitialCElement(selection);
         
         String namespace = null;
         if (celem != null) {
@@ -428,8 +448,13 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
                 }
             }
         }
+        if (namespace == null) {
+        	namespace = fDialogSettings.get(KEY_NAMESPACE);
+        }
+
         setNamespaceText(namespace, false);
-        setNamespaceSelection(namespace != null, true);
+        setNamespaceSelection(namespace != null || fDialogSettings.getBoolean(KEY_NAMESPACE_SELECTED),
+        		true);
         
         IPath folderPath = null;
         if (celem != null) {
@@ -450,8 +475,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
         ITextSelection textSel = getEditorTextSelection();
         if (textSel != null) {
             String text = textSel.getText();
-            if (text != null && text.length() > 0 &&
-            		CConventions.validateClassName(text).isOK()) {
+            if (text != null && text.length() > 0 && CConventions.validateClassName(text).isOK()) {
                 className = text;
             }
         }
@@ -459,19 +483,28 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
         
         IMethodStub[] stubs = getDefaultMethodStubs();
         for (int i = 0; i < stubs.length; ++i) {
-            addMethodStub(stubs[i], true);
+        	IMethodStub stub = stubs[i];
+        	if (stub.canModifyVirtual()) {
+        		stub.setVirtual(getBooleanSettingWithDefault(KEY_STUB_VIRTUAL + i, stub.isVirtual()));
+        	}
+        	if (stub.canModifyInline()) {
+        		stub.setInline(getBooleanSettingWithDefault(KEY_STUB_INLINE + i, stub.isInline()));
+        	}
+            addMethodStub(stub, getBooleanSettingWithDefault(KEY_STUB_SELECTED + 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);
-
+        setTestFileSelection(fDialogSettings.getBoolean(KEY_TEST_FILE_SELECTED), true);
         handleFieldChanged(ALL_FIELDS);
     }
-    
+
+    private boolean getBooleanSettingWithDefault(String key, boolean defaultValue) {
+    	String value = fDialogSettings.get(key);
+    	if (value == null) {
+    		return defaultValue;
+    	}
+    	return Boolean.valueOf(value);
+    }
+
     /**
      * Attempts to extract a C Element from the initial selection.
      * 
@@ -537,7 +570,10 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @return array of method stubs
      */
     protected IMethodStub[] getDefaultMethodStubs() {
-        return DEFAULT_METHOD_STUBS;
+        return new IMethodStub[] {
+            new ConstructorMethodStub(),
+            new DestructorMethodStub()
+        };
     }
     
     /**
@@ -546,7 +582,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @return the source folder
      */
     public String getSourceFolderText() {
-        return fSourceFolderDialogField.getText();
+        return fSourceFolderDialogField.getText().trim();
     }
     
     /**
@@ -610,7 +646,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @return the namespace
      */
     public String getNamespaceText() {
-        return fNamespaceDialogField.getText();
+        return fNamespaceDialogField.getText().trim();
     }
 
     /**
@@ -661,7 +697,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @return the class name
      */
     public String getClassName() {
-        return fClassNameDialogField.getText();
+        return fClassNameDialogField.getText().trim();
     }
 
     /**
@@ -732,34 +768,24 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
     }
 
     /**
-     * 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.
+     * Sets the use test file creation checkbox's selection state.
      * 
      * @param isSelected the checkbox's selection state
      * @param canBeModified if <code>true</code> the checkbox is
      * modifiable; otherwise it is read-only.
+     * @since 5.3
      */
-    public void setUseDefaultSelection(boolean isSelected, boolean canBeModified) {
-        fUseDefaultSelection.setSelection(isSelected);
-        fUseDefaultSelection.setEnabled(canBeModified);
-        updateFileGroupEnableState();
+    public void setTestFileSelection(boolean isSelected, boolean canBeModified) {
+    	fTestFileSelection.setSelection(isSelected);
+    	fTestFileSelection.setEnabled(canBeModified);
+    	updateTestFileEnableState();
     }
 
     /**
-     * Updates the enable state of buttons related to the use default checkbox.
+     * Updates the enable state of test file name text box.
      */
-    private void updateFileGroupEnableState() {
-        boolean filegroup = !isUseDefaultSelected();
-        fHeaderFileDialogField.setEnabled(filegroup);
-        fSourceFileDialogField.setEnabled(filegroup);
+    private void updateTestFileEnableState() {
+        fTestFileDialogField.setEnabled(fTestFileSelection.isSelected());
     }
     
     /**
@@ -768,7 +794,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @return the header file
      */
     public String getHeaderFileText() {
-        return fHeaderFileDialogField.getText();
+        return fHeaderFileDialogField.getText().trim();
     }
     
     /**
@@ -778,29 +804,16 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @param update <code>true</code> 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();
-        }
+    	setFileText(fHeaderFileDialogField, header, update);
     }
-    
+
     /**
      * 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;
+    	return getFilePath(getHeaderFileText());
     }
     
     /**
@@ -810,27 +823,16 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @param update <code>true</code> 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);
+    	setFileFullPath(fHeaderFileDialogField, path, update);
     }
 
-
     /**
      * Returns the text entered into the source file input field.
      * 
      * @return the source file
      */
     public String getSourceFileText() {
-        return fSourceFileDialogField.getText();
+        return fSourceFileDialogField.getText().trim();
     }
     
     /**
@@ -840,10 +842,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @param update <code>true</code> 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();
-        }
+    	setFileText(fSourceFileDialogField, source, update);
     }
     
     /**
@@ -852,17 +851,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @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;
+    	return getFilePath(getSourceFileText());
     }
     
     /**
@@ -872,6 +861,80 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @param update <code>true</code> if the dialog should be updated
      */
     protected void setSourceFileFullPath(IPath path, boolean update) {
+    	setFileFullPath(fSourceFileDialogField, path, update);
+    }
+
+    /**
+     * Returns the text entered into the source file input field.
+     * 
+     * @return the source file
+     * @since 5.3
+     */
+    public String getTestFileText() {
+    	return fTestFileDialogField.isEnabled() ? fTestFileDialogField.getText().trim() : null;
+    }
+
+    /**
+     * Sets the text of the test file input field.
+     * 
+     * @param testFile the test file name
+     * @param update <code>true</code> if the dialog should be updated
+     * @since 5.3
+     */ 
+    public void setTestFileText(String testFile, boolean update) {
+    	setFileText(fTestFileDialogField, testFile, update);
+    }
+
+    /**
+     * Returns the current test file as a path. Returns {@code null} if creation of test file
+     * is disabled.
+     * 
+     * @return the test file path, or {@code null} if creation of test file is disabled.
+     * @since 5.3
+     */
+    protected IPath getTestFileFullPath() {
+    	return getFilePath(getTestFileText());
+    }
+
+    /**
+     * Returns a path corresponding to a file name.
+     * @param filename the name of a header, a source, or a test file. Can be {@code null}.
+     * @return the corresponding path, or {@code null} if the filename is {@code null}.
+     */
+	private IPath getFilePath(String filename) {
+		if (filename == null || filename.length() == 0) {
+    		return null;
+    	}
+    	IPath path = new Path(filename);
+		if (!path.isAbsolute()) {
+			IPath folderPath = getSourceFolderFullPath();
+			if (folderPath != null)
+				path = folderPath.append(path);
+		}
+    	return path;
+	}
+
+    /**
+     * Sets a file name field to a given value.
+     * 
+     * @param field the field to set
+     * @param filename the new value of the field
+     * @param update <code>true</code> if the dialog should be updated
+     */
+    private void setFileText(StringButtonDialogField field, String filename, boolean update) {
+    	field.setTextWithoutUpdate(filename != null ? filename : ""); //$NON-NLS-1$
+        if (update) {
+        	field.dialogFieldChanged();
+        }
+    }
+
+    /**
+     * Sets a file name field from the given path.
+     * 
+     * @param path the file path
+     * @param update <code>true</code> if the dialog should be updated
+     */
+    private void setFileFullPath(StringButtonDialogField field, IPath path, boolean update) {
         String str = null;
         if (path != null) {
             IPath sourceFolder = getSourceFolderFullPath();
@@ -882,9 +945,20 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
             }
             str = path.makeRelative().toString();
         }
-        setSourceFileText(str, update);
+        setFileText(field, str, update);
     }
-    
+
+    /**
+     * Sets the test file from the given path.
+     * 
+     * @param path the test file path
+     * @param update <code>true</code> if the dialog should be updated
+     * @since 5.3
+     */
+    protected void setTestFileFullPath(IPath path, boolean update) {
+    	setFileFullPath(fTestFileDialogField, path, update);
+    }
+
     /*
      * @see WizardPage#becomesVisible
      */
@@ -919,7 +993,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
         public void focusGained(FocusEvent e) {
             if (fLastFocusedField != this.fieldID) {
                 fLastFocusedField = this.fieldID;
-            	if( isFirstTime ) {
+            	if (isFirstTime) {
             		isFirstTime = false;
             		return;
             	}
@@ -946,19 +1020,17 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 				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);
-			    }
+				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);
 			}
 		}
@@ -1009,13 +1081,15 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		        if (oldFolderPath == null) {
 					IPath headerPath = getHeaderFileFullPath();
 					IPath sourcePath = getSourceFileFullPath();
+					IPath testPath = getTestFileFullPath();
 		            IPath newFolderPath = updateSourceFolderFromPath(ns.getEnclosingProject().getProject().getFullPath());
 			        if (newFolderPath != null) {
-			            changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID;
+			            changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID | TEST_FILE_ID;
 					    setSourceFolderFullPath(newFolderPath, false);
-					    // adjust the relative paths
+					    // Adjust the relative paths
 					    setHeaderFileFullPath(headerPath, false);
 					    setSourceFileFullPath(sourcePath, false);
+					    setTestFileFullPath(testPath, false);
 			        }
 		        }
 		        setNamespaceText(ns.getQualifiedTypeName().toString(), false);
@@ -1074,21 +1148,19 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
     }
     
     /**
-     * handles changes to the class name field
+     * 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);
-		    }
+			updateFilesFromClassName(fClassNameDialogField.getText().trim());
+			changedFields |= HEADER_FILE_ID | SOURCE_FILE_ID | TEST_FILE_ID;
 			handleFieldChanged(changedFields);
 		}
 	}
     
     /**
-     * handles changes to the base classes field
+     * Handles changes to the base classes field
      */
 	private final class BaseClassesFieldAdapter implements IListAdapter<IBaseClassInfo> {
         public void customButtonPressed(ListDialogField<IBaseClassInfo> field, int index) {
@@ -1152,37 +1224,50 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		    IPath filePath = null;
 			IPath headerPath = getHeaderFileFullPath();
 			IPath sourcePath = getSourceFileFullPath();
+			IPath testPath = getTestFileFullPath();
 		    if (field == fHeaderFileDialogField) {
-		        filePath = chooseHeaderFile();
+		        filePath = chooseFile(NewClassWizardMessages.NewClassCreationWizardPage_ChooseHeaderFileDialog_title,
+				getHeaderFileFullPath());
 		        if (filePath != null) {
 		            headerPath = filePath;
 		        }
 		    } else if (field == fSourceFileDialogField) {
-				filePath = chooseSourceFile();
+				filePath = chooseFile(NewClassWizardMessages.NewClassCreationWizardPage_ChooseSourceFileDialog_title,
+				getSourceFileFullPath());
 		        if (filePath != null) {
 		            sourcePath = filePath;
 		        }
+		    } else if (field == fTestFileDialogField) {
+				filePath = chooseFile(NewClassWizardMessages.NewClassCreationWizardPage_ChooseTestFileDialog_title,
+				getTestFileFullPath());
+		        if (filePath != null) {
+		            testPath = filePath;
+		        }
 		    }
 		    if (filePath != null) {
 		        IPath folderPath = null;
 			    int changedFields = 0;
 	            int headerSegments = 0;
 	            int sourceSegments = 0;
+	            int testSegments = 0;
 	            if (headerPath != null)
 	                headerSegments = filePath.matchingFirstSegments(headerPath);
 	            if (sourcePath != null)
 	                sourceSegments = filePath.matchingFirstSegments(sourcePath);
-	            int segments = Math.min(headerSegments, sourceSegments);
+	            if (testPath != null)
+	                testSegments = filePath.matchingFirstSegments(testPath);
+	            int segments = Math.min(Math.min(headerSegments, sourceSegments), testSegments);
 	            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
+		            changedFields |= SOURCE_FOLDER_ID | HEADER_FILE_ID | SOURCE_FILE_ID | TEST_FILE_ID;
+				    // Adjust the relative paths
 		            setSourceFolderFullPath(folderPath, false);
 				    setHeaderFileFullPath(headerPath, false);
 				    setSourceFileFullPath(sourcePath, false);
+				    setTestFileFullPath(testPath, false);
 		        }
 			    if (field == fHeaderFileDialogField) {
 		            setHeaderFileFullPath(filePath, false);
@@ -1190,6 +1275,9 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		        } else if (field == fSourceFileDialogField) {
 		            setSourceFileFullPath(filePath, false);
 		            changedFields |= SOURCE_FILE_ID;
+		        } else if (field == fTestFileDialogField) {
+		            setTestFileFullPath(filePath, false);
+		            changedFields |= TEST_FILE_ID;
 		        }
 				handleFieldChanged(changedFields);
 		    }
@@ -1197,36 +1285,43 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		
 		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());
+		    if (field == fTestFileSelection) {
+		        boolean enabled = fTestFileSelection.isSelected();
+		        fTestFileDialogField.setEnabled(enabled);
+		        if (enabled) {
+		        	fTestFileDerivedFromClassName = true;
+		        	updateFilesFromClassName(fClassNameDialogField.getText().trim());
+		        } else {
+		        	fTestFileDialogField.setTextWithoutUpdate(""); //$NON-NLS-1$
 		        }
-		        changedFields = HEADER_FILE_ID | SOURCE_FILE_ID;
-			    updateFileGroupEnableState();
+		        changedFields = TEST_FILE_ID;
+			    updateTestFileEnableState();
 			    handleFieldChanged(SOURCE_FOLDER_ID);
 		    }
 		    if (field == fHeaderFileDialogField) {
 	            changedFields |= HEADER_FILE_ID;
+	            fHeaderFileDerivedFromClassName = false;
 	        } else if (field == fSourceFileDialogField) {
 	            changedFields |= SOURCE_FILE_ID;
+	            fSourceFileDerivedFromClassName = false;
+	        } else if (field == fTestFileDialogField) {
+	            changedFields |= TEST_FILE_ID;
+	            fTestFileDerivedFromClassName = false;
 	        }
 			handleFieldChanged(changedFields);
 		}
 	}
     
-    private IPath chooseHeaderFile() {
+    private IPath chooseFile(String title, IPath initialPath) {
         SourceFileSelectionDialog dialog = new SourceFileSelectionDialog(getShell());
-        dialog.setTitle(NewClassWizardMessages.NewClassCreationWizardPage_ChooseHeaderFileDialog_title);
+        dialog.setTitle(title);
         ICElement input = CoreModel.create(NewClassWizardUtil.getWorkspaceRoot());
         ICProject project = getCurrentProject();
         if (project != null)
             input = project;
         dialog.setInput(input);
 
-        IPath filePath = getHeaderFileFullPath();
+        IPath filePath = initialPath;
         if (filePath != null) {
             String folderName = filePath.removeLastSegments(1).toString();
             String fileName = filePath.lastSegment();
@@ -1244,52 +1339,32 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
         return null;
     }   
 
-    private IPath chooseSourceFile() {
-        SourceFileSelectionDialog dialog = new SourceFileSelectionDialog(getShell());
-        dialog.setTitle(NewClassWizardMessages.NewClassCreationWizardPage_ChooseSourceFileDialog_title);
-        ICElement input = CoreModel.create(NewClassWizardUtil.getWorkspaceRoot());
-        ICProject project = getCurrentProject();
-        if (project != null)
-            input = 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;
+        String headerName = ""; //$NON-NLS-1$
+        String sourceName = ""; //$NON-NLS-1$
+        String testName = ""; //$NON-NLS-1$
         IPath folder = getSourceFolderFullPath();
         if (className != null && className.length() > 0) {
             String[] names = generateFileNames(className, folder);
-            if (names != null && names.length == 2) {
+            if (names != null && names.length == 3) {
                 headerName = names[0];
                 sourceName = names[1];
+                testName = names[2];
             }
         }
-        fHeaderFileDialogField.setTextWithoutUpdate(headerName != null ? headerName : ""); //$NON-NLS-1$
-        fSourceFileDialogField.setTextWithoutUpdate(sourceName != null ? sourceName : ""); //$NON-NLS-1$
+        if (fHeaderFileDerivedFromClassName)
+        	fHeaderFileDialogField.setTextWithoutUpdate(headerName);
+        if (fSourceFileDerivedFromClassName)
+        	fSourceFileDialogField.setTextWithoutUpdate(sourceName);
+        if (fTestFileDerivedFromClassName && fTestFileDialogField.isEnabled())
+        	fTestFileDialogField.setTextWithoutUpdate(testName);
     }
     
     private static final int MAX_UNIQUE_CLASSNAME = 99;
+	private IDialogSettings fDialogSettings;
 
     /**
      * Returns the names of the header file and source file which will be
@@ -1304,10 +1379,12 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
     protected String[] generateFileNames(String className, IPath folder) {
         String headerName = null;
         String sourceName = null;
+        String testName = null;
         
         if (folder == null) {
             headerName = NewSourceFileGenerator.generateHeaderFileNameFromClass(className);
             sourceName = NewSourceFileGenerator.generateSourceFileNameFromClass(className);
+            testName = NewSourceFileGenerator.generateTestFileNameFromClass(className);
         } else {
             // make sure the file names are unique
             String currName = className;
@@ -1322,10 +1399,15 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
                     String source = NewSourceFileGenerator.generateSourceFileNameFromClass(currName);
                     path = folder.append(source);
                     if (!path.toFile().exists()) {
-                        headerName = header;
-                        sourceName = source;
-                        // we're done
-                        break;
+                        String test = NewSourceFileGenerator.generateTestFileNameFromClass(currName);
+                        path = folder.append(test);
+                        if (!path.toFile().exists()) {
+	                        headerName = header;
+	                        sourceName = source;
+	                        testName = test;
+	                        // we're done
+	                        break;
+                        }
                     }
                 }
                 ++count;
@@ -1333,7 +1415,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
             }
         }
         
-        return new String[] { headerName, sourceName };
+        return new String[] { headerName, sourceName, testName };
     }
     
     /**
@@ -1366,6 +1448,9 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
         if (fieldChanged(fields, SOURCE_FILE_ID)) {
             fSourceFileStatus = sourceFileChanged();
         }
+        if (fieldChanged(fields, TEST_FILE_ID)) {
+            fTestFileStatus = testFileChanged();
+        }
         doStatusUpdate();
     }
 
@@ -1389,16 +1474,17 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
             (fSourceFolderStatus != lastStatus) ? fSourceFolderStatus : STATUS_OK,
             (fNamespaceStatus != lastStatus) ? fNamespaceStatus : STATUS_OK,
 
-            // give priority to file-level warnings over
-        	// class name warnings
+            // Give priority to file-level warnings over class name warnings
             (fHeaderFileStatus != lastStatus && isClassNameWarning) ? fHeaderFileStatus : STATUS_OK,
             (fSourceFileStatus != lastStatus && isClassNameWarning) ? fSourceFileStatus : STATUS_OK,
+            (fTestFileStatus != lastStatus && isClassNameWarning) ? fTestFileStatus : STATUS_OK,
                     
             (fClassNameStatus != lastStatus) ? fClassNameStatus : STATUS_OK,
             (fBaseClassesStatus != lastStatus) ? fBaseClassesStatus : STATUS_OK,
             (fMethodStubsStatus != lastStatus) ? fMethodStubsStatus : STATUS_OK,
-            (fSourceFileStatus != lastStatus) ? fSourceFileStatus : STATUS_OK,
             (fHeaderFileStatus != lastStatus) ? fHeaderFileStatus : STATUS_OK,
+            (fSourceFileStatus != lastStatus) ? fSourceFileStatus : STATUS_OK,
+            (fTestFileStatus != lastStatus) ? fTestFileStatus : STATUS_OK,
         };
         
         // the mode severe status will be displayed and the ok button enabled/disabled.
@@ -1412,22 +1498,24 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      */
     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;
+        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;
+        case TEST_FILE_ID:
+            return fTestFileStatus;
+        default:
+        	return STATUS_OK;
         }
     }
     
@@ -1463,10 +1551,8 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 					status.setWarning(NewClassWizardMessages.NewClassCreationWizardPage_warning_NotInACProject);
 				}
 			    if (NewClassWizardUtil.getSourceFolder(res) == null) {
-			    	if (isUseDefaultSelected()) {
-						status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_NotASourceFolder, folderPath));
-						return status;
-			    	}
+					status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_NotASourceFolder, folderPath));
+					return status;
 				}
 			} else {
 				status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_NotAFolder, folderPath));
@@ -1698,9 +1784,6 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		StatusInfo status = new StatusInfo();
 		
 		IPath path = getHeaderFileFullPath();
-		if (path == null && isUseDefaultSelected()) {
-			return status;
-		}
 		if (path == null) {
 			status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_EnterHeaderFileName);
 			return status;
@@ -1719,7 +1802,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		}
 		
 		boolean fileExists = false;
-		// check if file already exists
+		// Check if the file already exists
 		IResource file = NewClassWizardUtil.getWorkspaceRoot().getFile(path);
     	if (file.getType() == IResource.FILE) {
     		if (!file.exists()) {
@@ -1751,7 +1834,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
     		return status;
     	}
 		
-		// check if folder exists
+		// 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)) {
@@ -1799,7 +1882,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		}
 		
 		boolean fileExists = false;
-		// check if file already exists
+		// Check if file already exists
 		IResource file = NewClassWizardUtil.getWorkspaceRoot().getFile(path);
     	if (file.getType() == IResource.FILE) {
     		if (!file.exists()) {
@@ -1831,7 +1914,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
     		return status;
     	}
 		
-		// check if folder exists
+		// 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)) {
@@ -1851,6 +1934,90 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 		return status;
 	}
     
+    /**
+     * Hook method that gets called when the test file has changed. The method 
+     * validates the test file and returns the status of the validation.
+     * 
+     * @return the status of the validation
+     * @since 5.3
+     */
+	protected IStatus testFileChanged() {
+		StatusInfo status = new StatusInfo();
+
+		if (!fTestFileDialogField.isEnabled()) {
+			return status;
+		}
+		IPath path = getTestFileFullPath();
+		if (path == null) {
+			status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_EnterTestFileName);
+			return status;
+		}
+
+		IPath sourceFolderPath = getSourceFolderFullPath();
+		if (sourceFolderPath == null || !sourceFolderPath.isPrefixOf(path)) {
+			status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_TestFileNotInSourceFolder);
+			return status;
+		}
+		
+		// Make sure the file location is under a source root
+		if (NewClassWizardUtil.getSourceFolder(path) == null) {
+			status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_TestFileNotInSourceFolder);
+			return status;
+		}
+		
+		boolean fileExists = false;
+		// Check if file already exists
+		IResource file = NewClassWizardUtil.getWorkspaceRoot().getFile(path);
+    	if (file.getType() == IResource.FILE) {
+    		if (!file.exists()) {
+				URI location = file.getLocationURI();
+				try {
+					IFileStore store = EFS.getStore(location);
+					fileExists = store.fetchInfo().exists();
+				} catch (CoreException e) {
+					status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_LocationUnknown);
+					return status;
+				}
+    		} else {
+    			fileExists = true;
+    		}
+    		
+			IProject proj = file.getProject();
+			if (!proj.isOpen()) {
+				status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_NotAFile, path));
+				return status;
+			}
+
+		    if (!CoreModel.hasCCNature(proj) && !CoreModel.hasCNature(proj)) {
+				status.setWarning(NewClassWizardMessages.NewClassCreationWizardPage_warning_NotInACProject);
+			} else if (fileExists) {
+			    status.setWarning(NewClassWizardMessages.NewClassCreationWizardPage_warning_TestFileExists);
+			}
+    	} else {
+    		status.setError(NewClassWizardMessages.NewClassCreationWizardPage_error_NotAFile);
+    		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(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_FolderDoesNotExist, folderPath));
+			return status;
+		}
+
+		if (!fileExists) {
+			IStatus val = CConventions.validateSourceFileName(getCurrentProject().getProject(), path.lastSegment());
+			if (val.getSeverity() == IStatus.ERROR) {
+				status.setError(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_error_InvalidTestFileName, val.getMessage()));
+				return status;
+			} else if (val.getSeverity() == IStatus.WARNING) {
+				status.setWarning(NLS.bind(NewClassWizardMessages.NewClassCreationWizardPage_warning_TestFileNameDiscouraged, val.getMessage()));
+			}
+		}
+		return status;
+	}
+    
     // -------- Code Generation ---------
     
 	/**
@@ -1861,15 +2028,37 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
 	 * @throws InterruptedException Thrown when the operation was cancelled.
 	 */
 	public void createClass(IProgressMonitor monitor) throws CoreException, InterruptedException {
-        fCreatedClass = null;
+		// Update dialog settings.
+		fDialogSettings.put(KEY_NAMESPACE_SELECTED, fNamespaceSelection.isSelected());
+		fDialogSettings.put(KEY_TEST_FILE_SELECTED, fTestFileSelection.isSelected());
+		String namespace = fNamespaceSelection.isSelected() ? getNamespaceText() : null;
+		fDialogSettings.put(KEY_NAMESPACE, namespace);
+        IMethodStub[] stubs = fMethodStubsDialogField.getMethodStubs();
+        for (int i = 0; i < stubs.length; ++i) {
+        	IMethodStub stub = stubs[i];
+        	if (stub.canModifyVirtual()) {
+        		fDialogSettings.put(KEY_STUB_VIRTUAL + i, stub.isVirtual());
+        	}
+        	if (stub.canModifyInline()) {
+        		fDialogSettings.put(KEY_STUB_INLINE + i, stub.isInline());
+        	}
+    		fDialogSettings.put(KEY_STUB_SELECTED + i, fMethodStubsDialogField.isChecked(stub));
+        }
+
+		fCreatedClass = null;
         fCreatedHeaderFile = null;
         fCreatedSourceFile = null;
-        
+        fCreatedTestFile = null;
+
+        IPath headerPath = getHeaderFileFullPath();
+        IPath sourcePath = getSourceFileFullPath();
+        IPath testPath = getTestFileFullPath();
         createClass(
-                getCanonicalPath(getHeaderFileFullPath()),
-                getCanonicalPath(getSourceFileFullPath()),
+        		headerPath != null ? getCanonicalPath(headerPath) : null,
+        		sourcePath != null ? getCanonicalPath(sourcePath) : null,
+                testPath != null ? getCanonicalPath(testPath) : null,
                 getClassName(),
-                isNamespaceSelected() ? getNamespaceText() : null,
+                namespace,
                 getBaseClasses(),
                 getSelectedMethodStubs(), monitor);
 	}
@@ -1902,6 +2091,7 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * 
      * @param headerPath the header file path
      * @param sourcePath the source file path
+     * @param testPath the test file path, can be {@code null}.
      * @param className the class name
      * @param namespace the namespace
      * @param baseClasses array of base classes
@@ -1909,11 +2099,15 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
      * @param monitor a progress monitor
      * @throws CoreException if the creation failed
      * @throws InterruptedException if the operation was cancelled
+     * @since 5.3
      */
-    protected void createClass(IPath headerPath, IPath sourcePath, String className, String namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs, IProgressMonitor monitor) throws CoreException, InterruptedException {
+    protected void createClass(IPath headerPath, IPath sourcePath, IPath testPath, String className,
+    		String namespace, IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs, IProgressMonitor monitor)
+    		throws CoreException, InterruptedException {
         NewClassCodeGenerator generator = new NewClassCodeGenerator(
                 headerPath,
                 sourcePath,
+                testPath,
                 className,
                 namespace,
                 baseClasses,
@@ -1924,8 +2118,16 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
         fCreatedClass = generator.getCreatedClass();
         fCreatedHeaderFile = generator.getCreatedHeaderFile();
         fCreatedSourceFile = generator.getCreatedSourceFile();
+        fCreatedTestFile = generator.getCreatedTestFile();
     }
 	
+    protected void createClass(IPath headerPath, IPath sourcePath, String className, String namespace,
+    		IBaseClassInfo[] baseClasses, IMethodStub[] methodStubs, IProgressMonitor monitor)
+    		throws CoreException, InterruptedException {
+    	createClass(headerPath, sourcePath, null, className, namespace, baseClasses, methodStubs,
+    			monitor);
+    }
+
 	/**
 	 * Returns the created class. The method only returns a valid class 
 	 * after <code>createClass</code> has been called.
@@ -1947,15 +2149,27 @@ public class NewClassCreationWizardPage extends NewElementWizardPage {
     public IFile getCreatedHeaderFile() {
         return fCreatedHeaderFile;
     }
-	
-   /**
-    * Returns the created source file. The method only returns a valid file 
-    * after <code>createClass</code> has been called.
-    * 
-    * @return the created source file
-    * @see #createClass(IProgressMonitor)
-    */         
+
+    /**
+     * Returns the created source file. The method only returns a valid file 
+     * after <code>createClass</code> has been called.
+     * 
+     * @return the created source file
+     * @see #createClass(IProgressMonitor)
+     */         
     public IFile getCreatedSourceFile() {
-        return fCreatedSourceFile;
+    	return fCreatedSourceFile;
+    }
+
+    /**
+     * Returns the created test file. The method only returns a valid file 
+     * after <code>createClass</code> has been called.
+     * 
+     * @return the created test file
+     * @see #createClass(IProgressMonitor)
+     * @since 5.3
+     */         
+    public IFile getCreatedTestFile() {
+    	return fCreatedTestFile;
     }
 }
diff --git a/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml b/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml
index 81325dc23d6..7efcef21724 100644
--- a/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml
+++ b/core/org.eclipse.cdt.ui/templates/default-codetemplates.xml
@@ -11,6 +11,7 @@
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     Anton Leherbauer (Wind River Systems)
+ *	   Sergey Prigogin (Google)
  *******************************************************************************/
 -->
 
@@ -45,21 +46,42 @@
 
 <template name="%CodeTemplates.cppsourcefile" id="org.eclipse.cdt.ui.text.codetemplates.cppsourcefile" description="%CodeTemplates.cppsourcefile.desc" context="org.eclipse.cdt.core.cxxSource.contenttype_context" enabled="true">${filecomment}
 
-${declarations}</template>
+${includes}
+
+${namespace_begin}
+
+${declarations}
+
+${namespace_end}</template>
+
+<template name="%CodeTemplates.cpptestfile" id="org.eclipse.cdt.ui.text.codetemplates.cpptestfile" description="%CodeTemplates.cpptestfile.desc" context="org.eclipse.cdt.core.cxxSource.contenttype_context" enabled="true">${filecomment}
+
+${includes}
+
+${namespace_begin}
+
+${declarations}
+
+${namespace_end}</template>
 
 <template name="%CodeTemplates.cppheaderfile" id="org.eclipse.cdt.ui.text.codetemplates.cppheaderfile" description="%CodeTemplates.cppheaderfile.desc" context="org.eclipse.cdt.core.cxxHeader.contenttype_context" enabled="true">${filecomment}
 
 #ifndef ${include_guard_symbol}
 #define ${include_guard_symbol}
 
-${typecomment}
+${includes}
+
+${namespace_begin}
+
 ${declarations}
 
-#endif /* ${include_guard_symbol} */
-</template>
+${namespace_end}
+#endif /* ${include_guard_symbol} */</template>
 
 <template name="%CodeTemplates.csourcefile" id="org.eclipse.cdt.ui.text.codetemplates.csourcefile" description="%CodeTemplates.csourcefile.desc" context="org.eclipse.cdt.core.cSource.contenttype_context" enabled="true">${filecomment}
 
+${includes}
+
 ${declarations}</template>
 
 <template name="%CodeTemplates.cheaderfile" id="org.eclipse.cdt.ui.text.codetemplates.cheaderfile" description="%CodeTemplates.cheaderfile.desc" context="org.eclipse.cdt.core.cHeader.contenttype_context" enabled="true">${filecomment}
@@ -67,18 +89,25 @@ ${declarations}</template>
 #ifndef ${include_guard_symbol}
 #define ${include_guard_symbol}
 
+${includes}
+
 ${declarations}
 
-#endif /* ${include_guard_symbol} */
-</template>
+#endif /* ${include_guard_symbol} */</template>
 
-<template name="methodbody" id="org.eclipse.cdt.ui.text.codetemplates.methodbody" description="%CodeTemplates.methodstub" context="org.eclipse.cdt.ui.text.codetemplates.methodbody_context" enabled="true">// ${todo} %CodeTemplates.methodstub.tododesc
-${body_statement}</template>
+<template name="namespace_begin" id="org.eclipse.cdt.ui.text.codetemplates.namespace_begin" description="%CodeTemplates.namespace_begin" context="org.eclipse.cdt.ui.text.codetemplates.namespace_context" enabled="true">namespace ${namespace_name} {</template>
 
-<template name="constructorbody" id="org.eclipse.cdt.ui.text.codetemplates.constructorbody" description="%CodeTemplates.constructorstub" context="org.eclipse.cdt.ui.text.codetemplates.constructorbody_context" enabled="true">// ${todo} %CodeTemplates.constructorstub.tododesc
-${body_statement}</template>
+<template name="namespace_end" id="org.eclipse.cdt.ui.text.codetemplates.namespace_end" description="%CodeTemplates.namespace_end" context="org.eclipse.cdt.ui.text.codetemplates.namespace_context" enabled="true">} /* namespace ${namespace_name} */</template>
 
-<template name="destructorbody" id="org.eclipse.cdt.ui.text.codetemplates.destructorbody" description="%CodeTemplates.destructorstub" context="org.eclipse.cdt.ui.text.codetemplates.destructorbody_context" enabled="true">${body_statement}
-// ${todo} %CodeTemplates.destructorstub.tododesc</template>
+<template name="class_body" id="org.eclipse.cdt.ui.text.codetemplates.class_body" description="%CodeTemplates.class_body" context="org.eclipse.cdt.ui.text.codetemplates.class_context" enabled="true">${declarations}</template>
+
+<template name="methodbody" id="org.eclipse.cdt.ui.text.codetemplates.methodbody" description="%CodeTemplates.methodstub" context="org.eclipse.cdt.ui.text.codetemplates.methodbody_context" enabled="true">&#9;// ${todo} %CodeTemplates.methodstub.tododesc
+&#9;${body_statement}</template>
+
+<template name="constructorbody" id="org.eclipse.cdt.ui.text.codetemplates.constructorbody" description="%CodeTemplates.constructorstub" context="org.eclipse.cdt.ui.text.codetemplates.constructorbody_context" enabled="true">&#9;// ${todo} %CodeTemplates.constructorstub.tododesc
+&#9;${body_statement}</template>
+
+<template name="destructorbody" id="org.eclipse.cdt.ui.text.codetemplates.destructorbody" description="%CodeTemplates.destructorstub" context="org.eclipse.cdt.ui.text.codetemplates.destructorbody_context" enabled="true">&#9;${body_statement}
+&#9;// ${todo} %CodeTemplates.destructorstub.tododesc</template>
 
 </templates>
diff --git a/core/org.eclipse.cdt.ui/templates/default-templates.properties b/core/org.eclipse.cdt.ui/templates/default-templates.properties
index 20ba0e771cb..e4688b72a92 100644
--- a/core/org.eclipse.cdt.ui/templates/default-templates.properties
+++ b/core/org.eclipse.cdt.ui/templates/default-templates.properties
@@ -7,6 +7,7 @@
 #
 # Contributors:
 #     IBM Corporation - initial API and implementation
+#	  Sergey Prigogin (Google)
 ###############################################################################
 
 ## NOTE TO TRANSLATORS:
@@ -46,13 +47,18 @@ CodeTemplates.methodcomment=Comment for methods
 
 CodeTemplates.cppsourcefile=Default C++ source template
 CodeTemplates.cppheaderfile=Default C++ header template
+CodeTemplates.cpptestfile=Default C++ test template
 CodeTemplates.csourcefile=Default C source template
 CodeTemplates.cheaderfile=Default C header template
 CodeTemplates.cppsourcefile.desc=Default template for newly created C++ source files
 CodeTemplates.cppheaderfile.desc=Default template for newly created C++ header files
+CodeTemplates.cpptestfile.desc=Default template for newly created C++ test files
 CodeTemplates.csourcefile.desc=Default template for newly created C source files
 CodeTemplates.cheaderfile.desc=Default template for newly created C header files
 
+CodeTemplates.namespace_begin=Beginning of namespace declaration
+CodeTemplates.namespace_end=End of namespace declaration
+CodeTemplates.class_body=Code in created class definitions
 CodeTemplates.methodstub=Code in created method stubs
 CodeTemplates.constructorstub=Code in created constructor stubs
 CodeTemplates.destructorstub=Code in created destructor stubs