content: /*******************************************************************************
   * Copyright (c) 2000, 2010 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
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *     IBM Corporation - initial API and implementation
   *     John Kaplan, johnkaplantech@gmail.com - 108071 [code templates] template for body of newly created class
   *******************************************************************************/
  package org.eclipse.wst.jsdt.ui.wizards;
  
  import java.lang.reflect.InvocationTargetException;
  import java.net.URI;
  import java.util.ArrayList;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Set;
  
  import org.eclipse.core.filesystem.EFS;
  import org.eclipse.core.filesystem.IFileStore;
  import org.eclipse.core.resources.IResource;
  import org.eclipse.core.runtime.CoreException;
  import org.eclipse.core.runtime.IProgressMonitor;
  import org.eclipse.core.runtime.IStatus;
  import org.eclipse.core.runtime.NullProgressMonitor;
  import org.eclipse.core.runtime.SubProgressMonitor;
  import org.eclipse.jface.contentassist.SubjectControlContentAssistant;
  import org.eclipse.jface.dialogs.MessageDialog;
  import org.eclipse.jface.operation.IRunnableWithProgress;
  import org.eclipse.jface.preference.PreferenceDialog;
  import org.eclipse.jface.text.BadLocationException;
  import org.eclipse.jface.text.ITextSelection;
  import org.eclipse.jface.text.templates.Template;
  import org.eclipse.jface.text.templates.TemplateException;
  import org.eclipse.jface.viewers.CellEditor;
  import org.eclipse.jface.viewers.ICellModifier;
  import org.eclipse.jface.viewers.ISelection;
  import org.eclipse.jface.viewers.IStructuredSelection;
  import org.eclipse.jface.viewers.LabelProvider;
  import org.eclipse.jface.viewers.TableViewer;
  import org.eclipse.jface.window.Window;
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.accessibility.AccessibleAdapter;
  import org.eclipse.swt.accessibility.AccessibleEvent;
  import org.eclipse.swt.events.KeyAdapter;
  import org.eclipse.swt.events.KeyEvent;
  import org.eclipse.swt.events.SelectionEvent;
  import org.eclipse.swt.events.SelectionListener;
  import org.eclipse.swt.graphics.Image;
  import org.eclipse.swt.layout.GridData;
  import org.eclipse.swt.layout.GridLayout;
  import org.eclipse.swt.widgets.Button;
  import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.Control;
  import org.eclipse.swt.widgets.Item;
  import org.eclipse.swt.widgets.Link;
  import org.eclipse.swt.widgets.Text;
  import org.eclipse.text.edits.TextEdit;
  import org.eclipse.ui.contentassist.ContentAssistHandler;
  import org.eclipse.ui.dialogs.ElementListSelectionDialog;
  import org.eclipse.ui.dialogs.PreferencesUtil;
  import org.eclipse.wst.jsdt.core.Flags;
  import org.eclipse.wst.jsdt.core.IBuffer;
  import org.eclipse.wst.jsdt.core.IFunction;
  import org.eclipse.wst.jsdt.core.IJavaScriptElement;
  import org.eclipse.wst.jsdt.core.IJavaScriptProject;
  import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
  import org.eclipse.wst.jsdt.core.IPackageFragment;
  import org.eclipse.wst.jsdt.core.IPackageFragmentRoot;
  import org.eclipse.wst.jsdt.core.ISourceRange;
  import org.eclipse.wst.jsdt.core.IType;
  import org.eclipse.wst.jsdt.core.JavaScriptConventions;
  import org.eclipse.wst.jsdt.core.JavaScriptCore;
  import org.eclipse.wst.jsdt.core.JavaScriptModelException;
  import org.eclipse.wst.jsdt.core.Signature;
  import org.eclipse.wst.jsdt.core.ToolFactory;
  import org.eclipse.wst.jsdt.core.compiler.IProblem;
  import org.eclipse.wst.jsdt.core.compiler.IScanner;
  import org.eclipse.wst.jsdt.core.compiler.ITerminalSymbols;
  import org.eclipse.wst.jsdt.core.compiler.InvalidInputException;
  import org.eclipse.wst.jsdt.core.dom.AST;
  import org.eclipse.wst.jsdt.core.dom.ASTNode;
  import org.eclipse.wst.jsdt.core.dom.ASTParser;
  import org.eclipse.wst.jsdt.core.dom.AbstractTypeDeclaration;
  import org.eclipse.wst.jsdt.core.dom.ITypeBinding;
  import org.eclipse.wst.jsdt.core.dom.ImportDeclaration;
  import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
  import org.eclipse.wst.jsdt.core.dom.Type;
  import org.eclipse.wst.jsdt.core.dom.rewrite.ImportRewrite;
  import org.eclipse.wst.jsdt.core.formatter.CodeFormatter;
  import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchConstants;
  import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchScope;
  import org.eclipse.wst.jsdt.core.search.SearchEngine;
  import org.eclipse.wst.jsdt.internal.corext.codemanipulation.AddUnimplementedConstructorsOperation;
  import org.eclipse.wst.jsdt.internal.corext.codemanipulation.AddUnimplementedMethodsOperation;
  import org.eclipse.wst.jsdt.internal.corext.codemanipulation.CodeGenerationSettings;
  import org.eclipse.wst.jsdt.internal.corext.codemanipulation.StubUtility;
  import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes;
  import org.eclipse.wst.jsdt.internal.corext.dom.TokenScanner;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.StubTypeContext;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.TypeContextChecker;
  import org.eclipse.wst.jsdt.internal.corext.template.java.JavaContext;
  import org.eclipse.wst.jsdt.internal.corext.util.CodeFormatterUtil;
  import org.eclipse.wst.jsdt.internal.corext.util.JavaModelUtil;
  import org.eclipse.wst.jsdt.internal.corext.util.Messages;
  import org.eclipse.wst.jsdt.internal.corext.util.Resources;
  import org.eclipse.wst.jsdt.internal.corext.util.Strings;
  import org.eclipse.wst.jsdt.internal.ui.JavaPluginImages;
  import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
  import org.eclipse.wst.jsdt.internal.ui.dialogs.FilteredTypesSelectionDialog;
  import org.eclipse.wst.jsdt.internal.ui.dialogs.StatusInfo;
  import org.eclipse.wst.jsdt.internal.ui.dialogs.TableTextCellEditor;
  import org.eclipse.wst.jsdt.internal.ui.dialogs.TextFieldNavigationHandler;
  import org.eclipse.wst.jsdt.internal.ui.preferences.CodeTemplatePreferencePage;
  import org.eclipse.wst.jsdt.internal.ui.preferences.JavaPreferencesSettings;
  import org.eclipse.wst.jsdt.internal.ui.refactoring.contentassist.CompletionContextRequestor;
  import org.eclipse.wst.jsdt.internal.ui.refactoring.contentassist.ControlContentAssistHelper;
  import org.eclipse.wst.jsdt.internal.ui.refactoring.contentassist.JavaPackageCompletionProcessor;
  import org.eclipse.wst.jsdt.internal.ui.refactoring.contentassist.JavaTypeCompletionProcessor;
  import org.eclipse.wst.jsdt.internal.ui.util.SWTUtil;
  import org.eclipse.wst.jsdt.internal.ui.wizards.NewWizardMessages;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.DialogField;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.IListAdapter;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.LayoutUtil;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.ListDialogField;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.SelectionButtonDialogFieldGroup;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.Separator;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.StringButtonStatusDialogField;
  import org.eclipse.wst.jsdt.internal.ui.wizards.dialogfields.StringDialogField;
  import org.eclipse.wst.jsdt.ui.CodeGeneration;
  import org.eclipse.wst.jsdt.ui.CodeStyleConfiguration;
  import org.eclipse.wst.jsdt.ui.JavaScriptElementLabelProvider;
  
  /**
   * The class <code>NewTypeWizardPage</code> contains controls and validation routines 
   * for a 'New Type WizardPage'. Implementors decide which components to add and to enable. 
   * Implementors can also customize the validation code. <code>NewTypeWizardPage</code> 
   * is intended to serve as base class of all wizards that create types like applets, servlets, classes, 
   * interfaces, etc.
   * <p>
   * See {@link NewClassWizardPage} or {@link NewInterfaceWizardPage} for an
   * example usage of the <code>NewTypeWizardPage</code>.
   * </p>
   *
   * Provisional API: This class/interface is part of an interim API that is still under development and expected to
   * change significantly before reaching stability. It is being made available at this early stage to solicit feedback
   * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken
   * (repeatedly) as the API evolves.
   * 
   * @see org.eclipse.wst.jsdt.ui.wizards.NewClassWizardPage
   * @see org.eclipse.wst.jsdt.ui.wizards.NewInterfaceWizardPage
   * 
   */
  public abstract class NewTypeWizardPage extends NewContainerWizardPage {
  
  	/**
  	 * Class used in stub creation routines to add needed imports to a 
  	 * compilation unit.
  	 */
  	public static class ImportsManager {
  
  		private ImportRewrite fImportsRewrite;
  				
  		/* package */ ImportsManager(JavaScriptUnit astRoot) throws CoreException {
  			fImportsRewrite= CodeStyleConfiguration.createImportRewrite(astRoot, true);
  		}
  
  		/* package */ IJavaScriptUnit getCompilationUnit() {
  			return fImportsRewrite.getCompilationUnit();
  		}
  						
  		/**
  		 * Adds a new import declaration that is sorted in the existing imports.
  		 * If an import already exists or the import would conflict with an import
  		 * of an other type with the same simple name, the import is not added.
  		 * 
  		 * @param qualifiedTypeName The fully qualified name of the type to import
  		 * (dot separated).
  		 * @return Returns the simple type name that can be used in the code or the
  		 * fully qualified type name if an import conflict prevented the import.
  		 */				
  		public String addImport(String qualifiedTypeName) {
  			return fImportsRewrite.addImport(qualifiedTypeName);
  		}
  				
  		/**
  		 * Adds a new import declaration that is sorted in the existing imports.
  		 * If an import already exists or the import would conflict with an import
  		 * of an other type with the same simple name, the import is not added.
  		 * 
  		 * @param typeBinding the binding of the type to import
  		 * 
  		 * @return Returns the simple type name that can be used in the code or the
  		 * fully qualified type name if an import conflict prevented the import.
  		 */				
  		public String addImport(ITypeBinding typeBinding) {
  			return fImportsRewrite.addImport(typeBinding);
  		}
  		
  		/**
  		 * Adds a new import declaration for a static type that is sorted in the existing imports.
  		 * If an import already exists or the import would conflict with an import
  		 * of an other static import with the same simple name, the import is not added.
  		 * 
  		 * @param declaringTypeName The qualified name of the static's member declaring type
  		 * @param simpleName the simple name of the member; either a field or a method name.
  		 * @param isField <code>true</code> specifies that the member is a field, <code>false</code> if it is a
  		 * method.
  		 * @return returns either the simple member name if the import was successful or else the qualified name if
  		 * an import conflict prevented the import.
  		 * 
  		 * 
  		 */				
  		public String addStaticImport(String declaringTypeName, String simpleName, boolean isField) {
  			return fImportsRewrite.addStaticImport(declaringTypeName, simpleName, isField);
  		}
  				
  		/* package */ void create(boolean needsSave, IProgressMonitor monitor) throws CoreException {
  			TextEdit edit= fImportsRewrite.rewriteImports(monitor);
  			JavaModelUtil.applyEdit(fImportsRewrite.getCompilationUnit(), edit, needsSave, null);
  		}
  		
  		/* package */ void removeImport(String qualifiedName) {
  			fImportsRewrite.removeImport(qualifiedName);
  		}
  		
  		/* package */ void removeStaticImport(String qualifiedName) {
  			fImportsRewrite.removeStaticImport(qualifiedName);
  		}
  	}
  		
  	
  	/** Public access flag. See The JavaScript Virtual Machine Specification for more details. */
  	public int F_PUBLIC = Flags.AccPublic;
  	/** Private access flag. See The JavaScript Virtual Machine Specification for more details. */
  	public int F_PRIVATE = Flags.AccPrivate;
  	/** Static access flag. See The JavaScript Virtual Machine Specification for more details. */
  	public int F_STATIC = Flags.AccStatic;
  	/** Abstract property flag. See The JavaScript Virtual Machine Specification for more details. */
  	public int F_ABSTRACT = Flags.AccAbstract;
  
  	private final static String PAGE_NAME= "NewTypeWizardPage"; //$NON-NLS-1$
  		
  	/** Field ID of the package input field. */
  	protected final static String PACKAGE= PAGE_NAME + ".package";	 //$NON-NLS-1$
  	/** Field ID of the enclosing type input field. */
  	protected final static String ENCLOSING= PAGE_NAME + ".enclosing"; //$NON-NLS-1$
  	/** Field ID of the enclosing type checkbox. */
  	protected final static String ENCLOSINGSELECTION= ENCLOSING + ".selection"; //$NON-NLS-1$
  	/** Field ID of the type name input field. */	
  	protected final static String TYPENAME= PAGE_NAME + ".typename"; //$NON-NLS-1$
  	/** Field ID of the super type input field. */
  	protected final static String SUPER= PAGE_NAME + ".superclass"; //$NON-NLS-1$
  	/** Field ID of the super interfaces input field. */
  	protected final static String INTERFACES= PAGE_NAME + ".interfaces"; //$NON-NLS-1$
  	/** Field ID of the modifier check boxes. */
  	protected final static String MODIFIERS= PAGE_NAME + ".modifiers"; //$NON-NLS-1$
  	/** Field ID of the method stubs check boxes. */
  	protected final static String METHODS= PAGE_NAME + ".methods"; //$NON-NLS-1$
  
  	private static class InterfaceWrapper {
  		public String interfaceName;
  
  		public InterfaceWrapper(String interfaceName) {
  			this.interfaceName= interfaceName;
  		}
  
  		public int hashCode() {
  			return interfaceName.hashCode();
  		}
  
  		public boolean equals(Object obj) {
  			return obj != null && getClass().equals(obj.getClass()) && ((InterfaceWrapper) obj).interfaceName.equals(interfaceName);
  		}
  	}
  	
  	private static class InterfacesListLabelProvider extends LabelProvider {
  		private Image fInterfaceImage;
  		
  		public InterfacesListLabelProvider() {
  			fInterfaceImage= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_INTERFACE);
  		}
  		
  		public String getText(Object element) {
  			return ((InterfaceWrapper) element).interfaceName;
  		}
  		
  		public Image getImage(Object element) {
  			return fInterfaceImage;
  		}
  	}	
  
  	private StringButtonStatusDialogField fPackageDialogField;
  	
  	private SelectionButtonDialogField fEnclosingTypeSelection;
  	private StringButtonDialogField fEnclosingTypeDialogField;
  		
  	private boolean fCanModifyPackage;
  	private boolean fCanModifyEnclosingType;
  	
  	private IPackageFragment fCurrPackage;
  	
  	private IType fCurrEnclosingType;
  	/**
  	 * a handle to the type to be created (does usually not exist, can be null)
  	 */
  	private IType fCurrType;
  	private StringDialogField fTypeNameDialogField;
  	
  	private StringButtonDialogField fSuperClassDialogField;
  	private ListDialogField fSuperInterfacesDialogField;
  	
  	private SelectionButtonDialogFieldGroup fAccMdfButtons;
  	private SelectionButtonDialogFieldGroup fOtherMdfButtons;
  	
  	private SelectionButtonDialogField fAddCommentButton;
  	private boolean fUseAddCommentButtonValue; // used for compatibility: Wizards that don't show the comment button control
  	// will use the preferences settings
  	
  	private IType fCreatedType;
  	
  	private JavaPackageCompletionProcessor fCurrPackageCompletionProcessor;
  	private JavaTypeCompletionProcessor fEnclosingTypeCompletionProcessor;
  	private StubTypeContext fSuperClassStubTypeContext;
  	private StubTypeContext fSuperInterfaceStubTypeContext;
  	
  	protected IStatus fEnclosingTypeStatus;
  	protected IStatus fPackageStatus;
  	protected IStatus fTypeNameStatus;
  	protected IStatus fSuperClassStatus;
  	protected IStatus fModifierStatus;
  	protected IStatus fSuperInterfacesStatus;	
  	
  	private final int PUBLIC_INDEX= 0, DEFAULT_INDEX= 1, PRIVATE_INDEX= 2, PROTECTED_INDEX= 3;
  	private final int ABSTRACT_INDEX= 0, STATIC_INDEX= 2, ENUM_ANNOT_STATIC_INDEX= 1;
  	
  	private int fTypeKind;
  	
  	/**
  	 * Constant to signal that the created type is a class.
  	 * 
  	 */
  	public static final int CLASS_TYPE = 1;
  	
  	/**
  	 * Constant to signal that the created type is a interface.
  	 * 
  	 */
  	public static final int INTERFACE_TYPE = 2;
  	
  	/**
  	 * Constant to signal that the created type is an enum.
  	 * 
  	 */
  	public static final int ENUM_TYPE = 3;
  	
  	/**
  	 * Constant to signal that the created type is an annotation.
  	 * 
  	 */
  	public static final int ANNOTATION_TYPE = 4;
  
  	/**
  	 * Creates a new <code>NewTypeWizardPage</code>.
  	 * 
  	 * @param isClass <code>true</code> if a new class is to be created; otherwise
  	 * an interface is to be created
  	 * @param pageName the wizard page's name
  	 */
  	public NewTypeWizardPage(boolean isClass, String pageName) {
  		this(isClass ? CLASS_TYPE : INTERFACE_TYPE, pageName);
  	}
  	
  	/**
  	 * Creates a new <code>NewTypeWizardPage</code>.
  	 * 
  	 * @param typeKind Signals the kind of the type to be created. Valid kinds are
  	 * {@link #CLASS_TYPE}, {@link #INTERFACE_TYPE}, {@link #ENUM_TYPE} and {@link #ANNOTATION_TYPE}
  	 * @param pageName the wizard page's name
  	 * 
  	 */
  	public NewTypeWizardPage(int typeKind, String pageName) {
  	    super(pageName);
  	    fTypeKind= typeKind;
  
  	    fCreatedType= null;
  		
  		TypeFieldsAdapter adapter= new TypeFieldsAdapter();
  		
  		fPackageDialogField= new StringButtonStatusDialogField(adapter);
  		fPackageDialogField.setDialogFieldListener(adapter);
  		fPackageDialogField.setLabelText(getPackageLabel()); 
  		fPackageDialogField.setButtonLabel(NewWizardMessages.NewTypeWizardPage_package_button); 
  		fPackageDialogField.setStatusWidthHint(NewWizardMessages.NewTypeWizardPage_default); 
  				
  		fEnclosingTypeSelection= new SelectionButtonDialogField(SWT.CHECK);
  		fEnclosingTypeSelection.setDialogFieldListener(adapter);
  		fEnclosingTypeSelection.setLabelText(getEnclosingTypeLabel()); 
  		
  		fEnclosingTypeDialogField= new StringButtonDialogField(adapter);
  		fEnclosingTypeDialogField.setDialogFieldListener(adapter);
  		fEnclosingTypeDialogField.setButtonLabel(NewWizardMessages.NewTypeWizardPage_enclosing_button); 
  		
  		fTypeNameDialogField= new StringDialogField();
  		fTypeNameDialogField.setDialogFieldListener(adapter);
  		fTypeNameDialogField.setLabelText(getTypeNameLabel()); 
  		
  		fSuperClassDialogField= new StringButtonDialogField(adapter);
  		fSuperClassDialogField.setDialogFieldListener(adapter);
  		fSuperClassDialogField.setLabelText(getSuperClassLabel()); 
  		fSuperClassDialogField.setButtonLabel(NewWizardMessages.NewTypeWizardPage_superclass_button); 
  		
  		String[] addButtons= new String[] {
  			NewWizardMessages.NewTypeWizardPage_interfaces_add, 
  			/* 1 */ null,
  			NewWizardMessages.NewTypeWizardPage_interfaces_remove
  		}; 
  		fSuperInterfacesDialogField= new ListDialogField(adapter, addButtons, new InterfacesListLabelProvider());
  		fSuperInterfacesDialogField.setDialogFieldListener(adapter);
  		fSuperInterfacesDialogField.setTableColumns(new ListDialogField.ColumnsDescription(1, false));
  		fSuperInterfacesDialogField.setLabelText(getSuperInterfacesLabel());
  		fSuperInterfacesDialogField.setRemoveButtonIndex(2);
  	
  		String[] buttonNames1= new String[] {
  			NewWizardMessages.NewTypeWizardPage_modifiers_public, 
  			NewWizardMessages.NewTypeWizardPage_modifiers_default, 
  			NewWizardMessages.NewTypeWizardPage_modifiers_private, 
  			NewWizardMessages.NewTypeWizardPage_modifiers_protected
  		};
  		fAccMdfButtons= new SelectionButtonDialogFieldGroup(SWT.RADIO, buttonNames1, 4);
  		fAccMdfButtons.setDialogFieldListener(adapter);
  		fAccMdfButtons.setLabelText(getModifiersLabel());		 
  		fAccMdfButtons.setSelection(0, true);
  		
  		String[] buttonNames2;
  		if (fTypeKind == CLASS_TYPE) {
  			buttonNames2= new String[] {
  				NewWizardMessages.NewTypeWizardPage_modifiers_abstract, 
  				NewWizardMessages.NewTypeWizardPage_modifiers_final, 
  				NewWizardMessages.NewTypeWizardPage_modifiers_static
  			};
  		} else {
  		    if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) {
  		        buttonNames2= new String[] {
  					NewWizardMessages.NewTypeWizardPage_modifiers_abstract, 
  					NewWizardMessages.NewTypeWizardPage_modifiers_static
  		        };
  		    }
  		    else
  		        buttonNames2= new String[] {};
  		}
  
  		fOtherMdfButtons= new SelectionButtonDialogFieldGroup(SWT.CHECK, buttonNames2, 4);
  		fOtherMdfButtons.setDialogFieldListener(adapter);
  		
  		fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, false);
  		fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX, false);
  		fOtherMdfButtons.enableSelectionButton(STATIC_INDEX, false);
  		
  		if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) {
  		    fOtherMdfButtons.enableSelectionButton(ABSTRACT_INDEX, false);
  		    fOtherMdfButtons.enableSelectionButton(ENUM_ANNOT_STATIC_INDEX, false);
  		}
  		
  		fAddCommentButton= new SelectionButtonDialogField(SWT.CHECK);
  		fAddCommentButton.setLabelText(NewWizardMessages.NewTypeWizardPage_addcomment_label); 
  		
  		fUseAddCommentButtonValue= false; // only used when enabled
  		
  		fCurrPackageCompletionProcessor= new JavaPackageCompletionProcessor();
  		fEnclosingTypeCompletionProcessor= new JavaTypeCompletionProcessor(false, false, true);
  		
  		fPackageStatus= new StatusInfo();
  		fEnclosingTypeStatus= new StatusInfo();
  		
  		fCanModifyPackage= true;
  		fCanModifyEnclosingType= true;
  		updateEnableState();
  					
  		fTypeNameStatus= new StatusInfo();
  		fSuperClassStatus= new StatusInfo();
  		fSuperInterfacesStatus= new StatusInfo();
  		fModifierStatus= new StatusInfo();
  	}
  	
  	/**
  	 * Initializes all fields provided by the page with a given selection.
  	 * 
  	 * @param elem the selection used to initialize this page or <code>
  	 * null</code> if no selection was available
  	 */
  	protected void initTypePage(IJavaScriptElement elem) {
  		String initSuperclass= "java.lang.Object"; //$NON-NLS-1$
  		ArrayList initSuperinterfaces= new ArrayList(5);
  
  		IJavaScriptProject project= null;
  		IPackageFragment pack= null;
  		IType enclosingType= null;
  				
  		if (elem != null) {
  			// evaluate the enclosing type
  			project= elem.getJavaScriptProject();
  			pack= (IPackageFragment) elem.getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT);
  			IType typeInCU= (IType) elem.getAncestor(IJavaScriptElement.TYPE);
  			if (typeInCU != null) {
  				if (typeInCU.getJavaScriptUnit() != null) {
  					enclosingType= typeInCU;
  				}
  			} else {
  				IJavaScriptUnit cu= (IJavaScriptUnit) elem.getAncestor(IJavaScriptElement.JAVASCRIPT_UNIT);
  				if (cu != null) {
  					enclosingType= cu.findPrimaryType();
  				}
  			}
  			
  			IType type= null;
  			if (elem.getElementType() == IJavaScriptElement.TYPE) {
  				type= (IType)elem;
  				if (type.exists()) {
  					String superName= JavaModelUtil.getFullyQualifiedName(type);
  					initSuperclass= superName;
  				}
  			}			
  		}
  		
  		String typeName= ""; //$NON-NLS-1$
  		
  		ITextSelection selection= getCurrentTextSelection();
  		if (selection != null) {
  			String text= selection.getText();
  			if (text != null && validateJavaTypeName(text, project).isOK()) {
  				typeName= text;
  			}
  		}
  
  		setPackageFragment(pack, true);
  		setEnclosingType(enclosingType, true);
  		setEnclosingTypeSelection(false, true);
  	
  		setTypeName(typeName, true);
  		setSuperClass(initSuperclass, true);
  		setSuperInterfaces(initSuperinterfaces, true);
  		
  		setAddComments(StubUtility.doAddComments(project), true); // from project or workspace
  	}
  	
  	private static IStatus validateJavaTypeName(String text, IJavaScriptProject project) {
  		if (project == null || !project.exists()) {
  			return JavaScriptConventions.validateJavaScriptTypeName(text, JavaScriptCore.VERSION_1_3, JavaScriptCore.VERSION_1_3);
  		}
  		String sourceLevel= project.getOption(JavaScriptCore.COMPILER_SOURCE, true);
  		String compliance= project.getOption(JavaScriptCore.COMPILER_COMPLIANCE, true);
  		return JavaScriptConventions.validateJavaScriptTypeName(text, sourceLevel, compliance);
  	}
  	
  	private static IStatus validatePackageName(String text, IJavaScriptProject project) {
  		if (project == null || !project.exists()) {
  			return JavaScriptConventions.validatePackageName(text, JavaScriptCore.VERSION_1_3, JavaScriptCore.VERSION_1_3);
  		}
  		String sourceLevel= project.getOption(JavaScriptCore.COMPILER_SOURCE, true);
  		String compliance= project.getOption(JavaScriptCore.COMPILER_COMPLIANCE, true);
  		return JavaScriptConventions.validatePackageName(text, sourceLevel, compliance);
  	}
  	
  	// -------- UI Creation ---------
  	
  	/**
  	 * Returns the label that is used for the package input field.
  	 * 
  	 * @return the label that is used for the package input field.
  	 * 
  	 */
  	protected String getPackageLabel() {
  		return NewWizardMessages.NewTypeWizardPage_package_label;
  	}
  
  	/**
  	 * Returns the label that is used for the enclosing type input field.
  	 * 
  	 * @return the label that is used for the enclosing type input field.
  	 * 
  	 */
  	protected String getEnclosingTypeLabel() {
  		return NewWizardMessages.NewTypeWizardPage_enclosing_selection_label;
  	}
  	
  	/**
  	 * Returns the label that is used for the type name input field.
  	 * 
  	 * @return the label that is used for the type name input field.
  	 * 
  	 */
  	protected String getTypeNameLabel() {
  		return NewWizardMessages.NewTypeWizardPage_typename_label;
  	}
  
  	/**
  	 * Returns the label that is used for the modifiers input field.
  	 * 
  	 * @return the label that is used for the modifiers input field
  	 * 
  	 */
  	protected String getModifiersLabel() {
  		return NewWizardMessages.NewTypeWizardPage_modifiers_acc_label;
  	}
  
  	/**
  	 * Returns the label that is used for the super class input field.
  	 * 
  	 * @return the label that is used for the super class input field.
  	 * 
  	 */
  	protected String getSuperClassLabel() {
  		return NewWizardMessages.NewTypeWizardPage_superclass_label;
  	}
  
  	/**
  	 * Returns the label that is used for the super interfaces input field.
  	 * 
  	 * @return the label that is used for the super interfaces input field.
  	 * 
  	 */
  	protected String getSuperInterfacesLabel() {
  	    if (fTypeKind != INTERFACE_TYPE)
  	        return NewWizardMessages.NewTypeWizardPage_interfaces_class_label; 
  	    return NewWizardMessages.NewTypeWizardPage_interfaces_ifc_label; 
  	}
  	
  	/**
  	 * Creates a separator line. Expects a <code>GridLayout</code> with at least 1 column.
  	 * 
  	 * @param composite the parent composite
  	 * @param nColumns number of columns to span
  	 */
  	protected void createSeparator(Composite composite, int nColumns) {
  		(new Separator(SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, convertHeightInCharsToPixels(1));		
  	}
  
  	/**
  	 * Creates the controls for the package name field. Expects a <code>GridLayout</code> with at 
  	 * least 4 columns.
  	 * 
  	 * @param composite the parent composite
  	 * @param nColumns number of columns to span
  	 */	
  	protected void createPackageControls(Composite composite, int nColumns) {
  		fPackageDialogField.doFillIntoGrid(composite, nColumns);
  		Text text= fPackageDialogField.getTextControl(null);
  		LayoutUtil.setWidthHint(text, getMaxFieldWidth());	
  		LayoutUtil.setHorizontalGrabbing(text);
  		ControlContentAssistHelper.createTextContentAssistant(text, fCurrPackageCompletionProcessor);
  		TextFieldNavigationHandler.install(text);
  	}
  
  	/**
  	 * Creates the controls for the enclosing type name field. Expects a <code>GridLayout</code> with at 
  	 * least 4 columns.
  	 * 
  	 * @param composite the parent composite
  	 * @param nColumns number of columns to span
  	 */		
  	protected void createEnclosingTypeControls(Composite composite, int nColumns) {
  		// #6891
  		Composite tabGroup= new Composite(composite, SWT.NONE);
  		GridLayout layout= new GridLayout();
  		layout.marginWidth= 0;
  		layout.marginHeight= 0;
   		tabGroup.setLayout(layout);
  
  		fEnclosingTypeSelection.doFillIntoGrid(tabGroup, 1);
  
  		Text text= fEnclosingTypeDialogField.getTextControl(composite);
  		text.getAccessible().addAccessibleListener(new AccessibleAdapter() {
  			public void getName(AccessibleEvent e) {
  				e.result= NewWizardMessages.NewTypeWizardPage_enclosing_field_description;
  			}
  		});
  		GridData gd= new GridData(GridData.FILL_HORIZONTAL);
  		gd.widthHint= getMaxFieldWidth();
  		gd.horizontalSpan= 2;
  		text.setLayoutData(gd);
  		
  		Button button= fEnclosingTypeDialogField.getChangeControl(composite);
  		gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
  		gd.widthHint = SWTUtil.getButtonWidthHint(button);
  		button.setLayoutData(gd);
  		ControlContentAssistHelper.createTextContentAssistant(text, fEnclosingTypeCompletionProcessor);
  		TextFieldNavigationHandler.install(text);
  	}	
  
  	/**
  	 * Creates the controls for the type name field. Expects a <code>GridLayout</code> with at 
  	 * least 2 columns.
  	 * 
  	 * @param composite the parent composite
  	 * @param nColumns number of columns to span
  	 */		
  	protected void createTypeNameControls(Composite composite, int nColumns) {
  		fTypeNameDialogField.doFillIntoGrid(composite, nColumns - 1);
  		DialogField.createEmptySpace(composite);
  		
  		Text text= fTypeNameDialogField.getTextControl(null);
  		LayoutUtil.setWidthHint(text, getMaxFieldWidth());
  		TextFieldNavigationHandler.install(text);
  	}
  
  	/**
  	 * Creates the controls for the modifiers radio/checkbox buttons. Expects a 
  	 * <code>GridLayout</code> with at least 3 columns.
  	 * 
  	 * @param composite the parent composite
  	 * @param nColumns number of columns to span
  	 */		
  	protected void createModifierControls(Composite composite, int nColumns) {
  		LayoutUtil.setHorizontalSpan(fAccMdfButtons.getLabelControl(composite), 1);
  		
  		Control control= fAccMdfButtons.getSelectionButtonsGroup(composite);
  		GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
  		gd.horizontalSpan= nColumns - 2;
  		control.setLayoutData(gd);
  		
  		DialogField.createEmptySpace(composite);
  		
  		if (fTypeKind == CLASS_TYPE) {
  			DialogField.createEmptySpace(composite);
  			
  			control= fOtherMdfButtons.getSelectionButtonsGroup(composite);
  			gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
  			gd.horizontalSpan= nColumns - 2;
  			control.setLayoutData(gd);		
  	
  			DialogField.createEmptySpace(composite);
  		}
  	}
  
  	/**
  	 * Creates the controls for the superclass name field. Expects a <code>GridLayout</code> 
  	 * with at least 3 columns.
  	 * 
  	 * @param composite the parent composite
  	 * @param nColumns number of columns to span
  	 */		
  	protected void createSuperClassControls(Composite composite, int nColumns) {
  		fSuperClassDialogField.doFillIntoGrid(composite, nColumns);
  		Text text= fSuperClassDialogField.getTextControl(null);
  		LayoutUtil.setWidthHint(text, getMaxFieldWidth());
  		
  		JavaTypeCompletionProcessor superClassCompletionProcessor= new JavaTypeCompletionProcessor(false, false, true);
  		superClassCompletionProcessor.setCompletionContextRequestor(new CompletionContextRequestor() {
  			public StubTypeContext getStubTypeContext() {
  				return getSuperClassStubTypeContext();
  			}
  		});
  
  		ControlContentAssistHelper.createTextContentAssistant(text, superClassCompletionProcessor);
  		TextFieldNavigationHandler.install(text);
  	}
  
  	/**
  	 * Creates the controls for the superclass name field. Expects a <code>GridLayout</code> with 
  	 * at least 3 columns.
  	 * 
  	 * @param composite the parent composite
  	 * @param nColumns number of columns to span
  	 */			
  	protected void createSuperInterfacesControls(Composite composite, int nColumns) {
  		final String INTERFACE= "interface"; //$NON-NLS-1$
  		fSuperInterfacesDialogField.doFillIntoGrid(composite, nColumns);
  		final TableViewer tableViewer= fSuperInterfacesDialogField.getTableViewer();
  		tableViewer.setColumnProperties(new String[] {INTERFACE});
  		
  		TableTextCellEditor cellEditor= new TableTextCellEditor(tableViewer, 0) {
  		    protected void doSetFocus() {
  		        if (text != null) {
  		            text.setFocus();
  		            text.setSelection(text.getText().length());
  		            checkSelection();
  		            checkDeleteable();
  		            checkSelectable();
  		        }
  		    }
  		};
  		JavaTypeCompletionProcessor superInterfaceCompletionProcessor= new JavaTypeCompletionProcessor(false, false, true);
  		superInterfaceCompletionProcessor.setCompletionContextRequestor(new CompletionContextRequestor() {
  			public StubTypeContext getStubTypeContext() {
  				return getSuperInterfacesStubTypeContext();
  			}
  		});
  		SubjectControlContentAssistant contentAssistant= ControlContentAssistHelper.createJavaContentAssistant(superInterfaceCompletionProcessor);
  		Text cellEditorText= cellEditor.getText();
  		ContentAssistHandler.createHandlerForText(cellEditorText, contentAssistant);
  		TextFieldNavigationHandler.install(cellEditorText);
  		cellEditor.setContentAssistant(contentAssistant);
  		
  		tableViewer.setCellEditors(new CellEditor[] { cellEditor });
  		tableViewer.setCellModifier(new ICellModifier() {
  			public void modify(Object element, String property, Object value) {
  				if (element instanceof Item)
  					element = ((Item) element).getData();
  				
  				((InterfaceWrapper) element).interfaceName= (String) value;
  				fSuperInterfacesDialogField.elementChanged(element);
  			}
  			public Object getValue(Object element, String property) {
  				return ((InterfaceWrapper) element).interfaceName;
  			}
  			public boolean canModify(Object element, String property) {
  				return true;
  			}
  		});
  		tableViewer.getTable().addKeyListener(new KeyAdapter() {
  			public void keyPressed(KeyEvent event) {
  				if (event.keyCode == SWT.F2 && event.stateMask == 0) {
  					ISelection selection= tableViewer.getSelection();
  					if (! (selection instanceof IStructuredSelection))
  						return;
  					IStructuredSelection structuredSelection= (IStructuredSelection) selection;
  					tableViewer.editElement(structuredSelection.getFirstElement(), 0);
  				} 
  			}
  		});
  		GridData gd= (GridData) fSuperInterfacesDialogField.getListControl(null).getLayoutData();
  		if (fTypeKind == CLASS_TYPE) {
  			gd.heightHint= convertHeightInCharsToPixels(3);
  		} else {
  			gd.heightHint= convertHeightInCharsToPixels(6);
  		}
  		gd.grabExcessVerticalSpace= false;
  		gd.widthHint= getMaxFieldWidth();
  	}
  	
  	/**
  	 * Creates the controls for the preference page links. Expects a <code>GridLayout</code> with 
  	 * at least 3 columns.
  	 * 
  	 * @param composite the parent composite
  	 * @param nColumns number of columns to span
  	 * 
  	 * 
  	 */			
  	protected void createCommentControls(Composite composite, int nColumns) {
      	Link link= new Link(composite, SWT.NONE);
      	link.setText(NewWizardMessages.NewTypeWizardPage_addcomment_description);
      	link.addSelectionListener(new TypeFieldsAdapter());
      	link.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false, nColumns, 1));
  		DialogField.createEmptySpace(composite);
  		fAddCommentButton.doFillIntoGrid(composite, nColumns - 1);
  	}
  
  
  	
  	/**
  	 * Sets the focus on the type name input field.
  	 */		
  	protected void setFocus() {
  		fTypeNameDialogField.setFocus();
  	}
  				
  	// -------- TypeFieldsAdapter --------
  
  	private class TypeFieldsAdapter implements IStringButtonAdapter, IDialogFieldListener, IListAdapter, SelectionListener {
  		
  		// -------- IStringButtonAdapter
  		public void changeControlPressed(DialogField field) {
  			typePageChangeControlPressed(field);
  		}
  		
  		// -------- IListAdapter
  		public void customButtonPressed(ListDialogField field, int index) {
  			typePageCustomButtonPressed(field, index);
  		}
  		
  		public void selectionChanged(ListDialogField field) {}
  		
  		// -------- IDialogFieldListener
  		public void dialogFieldChanged(DialogField field) {
  			typePageDialogFieldChanged(field);
  		}
  		
  		public void doubleClicked(ListDialogField field) {
  		}
  
  
  		public void widgetSelected(SelectionEvent e) {
  			typePageLinkActivated(e);
  		}
  
  		public void widgetDefaultSelected(SelectionEvent e) {
  			typePageLinkActivated(e);
  		}
  	}
  	
  	private void typePageLinkActivated(SelectionEvent e) {
  		IJavaScriptProject project= getJavaProject();
  		if (project != null) {
  			PreferenceDialog dialog= PreferencesUtil.createPropertyDialogOn(getShell(), project.getProject(), CodeTemplatePreferencePage.PROP_ID, null, null);
  			dialog.open();
  		} else {
  			String title= NewWizardMessages.NewTypeWizardPage_configure_templates_title; 
  			String message= NewWizardMessages.NewTypeWizardPage_configure_templates_message; 
  			MessageDialog.openInformation(getShell(), title, message);
  		}
  	}
  	
  	private void typePageChangeControlPressed(DialogField field) {
  		if (field == fPackageDialogField) {
  			IPackageFragment pack= choosePackage();	
  			if (pack != null) {
  				fPackageDialogField.setText(pack.getElementName());
  			}
  		} else if (field == fEnclosingTypeDialogField) {
  			IType type= chooseEnclosingType();
  			if (type != null) {
  				fEnclosingTypeDialogField.setText(JavaModelUtil.getFullyQualifiedName(type));
  			}
  		} else if (field == fSuperClassDialogField) {
  			IType type= chooseSuperClass();
  			if (type != null) {
  				fSuperClassDialogField.setText(JavaModelUtil.getFullyQualifiedName(type));
  			}
  		}
  	}
  	
  	private void typePageCustomButtonPressed(DialogField field, int index) {		
  		if (field == fSuperInterfacesDialogField) {
  			List interfaces= fSuperInterfacesDialogField.getElements();
  			if (!interfaces.isEmpty()) {
  				Object element= interfaces.get(interfaces.size() - 1);
  				fSuperInterfacesDialogField.editElement(element);
  			}
  		}
  	}
  	
  	/*
  	 * A field on the type has changed. The fields' status and all dependent
  	 * status are updated.
  	 */
  	private void typePageDialogFieldChanged(DialogField field) {
  		String fieldName= null;
  		if (field == fPackageDialogField) {
  			fPackageStatus= packageChanged();
  			updatePackageStatusLabel();
  			fTypeNameStatus= typeNameChanged();
  			fSuperClassStatus= superClassChanged();			
  			fieldName= PACKAGE;
  		} else if (field == fEnclosingTypeDialogField) {
  			fEnclosingTypeStatus= enclosingTypeChanged();
  			fTypeNameStatus= typeNameChanged();
  			fSuperClassStatus= superClassChanged();				
  			fieldName= ENCLOSING;
  		} else if (field == fEnclosingTypeSelection) {
  			updateEnableState();
  			boolean isEnclosedType= isEnclosingTypeSelected();
  			if (!isEnclosedType) {
  				if (fAccMdfButtons.isSelected(PRIVATE_INDEX) || fAccMdfButtons.isSelected(PROTECTED_INDEX)) {
  					fAccMdfButtons.setSelection(PRIVATE_INDEX, false);
  					fAccMdfButtons.setSelection(PROTECTED_INDEX, false); 
  					fAccMdfButtons.setSelection(PUBLIC_INDEX, true);
  				}
  				if (fOtherMdfButtons.isSelected(STATIC_INDEX)) {
  					fOtherMdfButtons.setSelection(STATIC_INDEX, false);
  				}
  			}
  			fAccMdfButtons.enableSelectionButton(PRIVATE_INDEX, isEnclosedType);
  			fAccMdfButtons.enableSelectionButton(PROTECTED_INDEX, isEnclosedType);
  			fOtherMdfButtons.enableSelectionButton(STATIC_INDEX, isEnclosedType);
  			fTypeNameStatus= typeNameChanged();
  			fSuperClassStatus= superClassChanged();
  			fieldName= ENCLOSINGSELECTION;
  		} else if (field == fTypeNameDialogField) {
  			fTypeNameStatus= typeNameChanged();
  			fieldName= TYPENAME;
  		} else if (field == fSuperClassDialogField) {
  			fSuperClassStatus= superClassChanged();
  			fieldName= SUPER;
  		} else if (field == fSuperInterfacesDialogField) {
  			fSuperInterfacesStatus= superInterfacesChanged();
  			fieldName= INTERFACES;
  		} else if (field == fOtherMdfButtons || field == fAccMdfButtons) {
  			fModifierStatus= modifiersChanged();
  			fieldName= MODIFIERS;
  		} else {
  			fieldName= METHODS;
  		}
  		// tell all others
  		handleFieldChanged(fieldName);
  	}		
  	
  	// -------- update message ----------------		
  	
  	/*
  	 * @see org.eclipse.wst.jsdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(String)
  	 */
  	protected void handleFieldChanged(String fieldName) {
  		super.handleFieldChanged(fieldName);
  		if (fieldName == CONTAINER) {
  			fPackageStatus= packageChanged();
  			fEnclosingTypeStatus= enclosingTypeChanged();			
  			fTypeNameStatus= typeNameChanged();
  			fSuperClassStatus= superClassChanged();
  			fSuperInterfacesStatus= superInterfacesChanged();
  		}
  	}
  	
  	// ---- set / get ----------------
  	
  	/**
  	 * Returns the text of the package input field.
  	 * 
  	 * @return the text of the package input field
  	 */
  	public String getPackageText() {
  		return fPackageDialogField.getText();
  	}
  
  	/**
  	 * Returns the text of the enclosing type input field.
  	 * 
  	 * @return the text of the enclosing type input field
  	 */	
  	public String getEnclosingTypeText() {
  		return fEnclosingTypeDialogField.getText();
  	}	
  	
  	
  	/**
  	 * Returns the package fragment corresponding to the current input.
  	 * 
  	 * @return a package fragment or <code>null</code> if the input 
  	 * could not be resolved.
  	 */
  	public IPackageFragment getPackageFragment() {
  		if (!isEnclosingTypeSelected()) {
  			return fCurrPackage;
  		} else {
  			if (fCurrEnclosingType != null) {
  				return fCurrEnclosingType.getPackageFragment();
  			}
  		}
  		return null;
  	}
  	
  	/**
  	 * Sets the package fragment to the given value. The method updates the model 
  	 * and the text of the control.
  	 * 
  	 * @param pack the package fragment to be set
  	 * @param canBeModified if <code>true</code> the package fragment is
  	 * editable; otherwise it is read-only.
  	 */
  	public void setPackageFragment(IPackageFragment pack, boolean canBeModified) {
  		fCurrPackage= pack;
  		fCanModifyPackage= canBeModified;
  		String str= (pack == null) ? "" : pack.getElementName(); //$NON-NLS-1$
  		fPackageDialogField.setText(str);
  		updateEnableState();
  	}	
  
  	/**
  	 * Returns the enclosing type corresponding to the current input.
  	 * 
  	 * @return the enclosing type or <code>null</code> if the enclosing type is 
  	 * not selected or the input could not be resolved
  	 */
  	public IType getEnclosingType() {
  		if (isEnclosingTypeSelected()) {
  			return fCurrEnclosingType;
  		}
  		return null;
  	}
  
  	/**
  	 * Sets the enclosing type. The method updates the underlying model 
  	 * and the text of the control.
  	 * 
  	 * @param type the enclosing type
  	 * @param canBeModified if <code>true</code> the enclosing type field is
  	 * editable; otherwise it is read-only.
  	 */	
  	public void setEnclosingType(IType type, boolean canBeModified) {
  		fCurrEnclosingType= type;
  		fCanModifyEnclosingType= canBeModified;
  		String str= (type == null) ? "" : JavaModelUtil.getFullyQualifiedName(type); //$NON-NLS-1$
  		fEnclosingTypeDialogField.setText(str);
  		updateEnableState();
  	}
  	
  	/**
  	 * Returns the selection state of the enclosing type checkbox.
  	 * 
  	 * @return the selection state of the enclosing type checkbox
  	 */
  	public boolean isEnclosingTypeSelected() {
  		return fEnclosingTypeSelection.isSelected();
  	}
  
  	/**
  	 * Sets the enclosing type checkbox's selection state.
  	 * 
  	 * @param isSelected the checkbox's selection state
  	 * @param canBeModified if <code>true</code> the enclosing type checkbox is
  	 * modifiable; otherwise it is read-only.
  	 */
  	public void setEnclosingTypeSelection(boolean isSelected, boolean canBeModified) {
  		fEnclosingTypeSelection.setSelection(isSelected);
  		fEnclosingTypeSelection.setEnabled(canBeModified);
  		updateEnableState();
  	}
  	
  	/**
  	 * Returns the type name entered into the type input field.
  	 * 
  	 * @return the type name
  	 */
  	public String getTypeName() {
  		return fTypeNameDialogField.getText();
  	}
  
  	/**
  	 * Sets the type name input field's text to the given value. Method doesn't update
  	 * the model.
  	 * 
  	 * @param name the new type name
  	 * @param canBeModified if <code>true</code> the type name field is
  	 * editable; otherwise it is read-only.
  	 */	
  	public void setTypeName(String name, boolean canBeModified) {
  		fTypeNameDialogField.setText(name);
  		fTypeNameDialogField.setEnabled(canBeModified);
  	}	
  	
  	/**
  	 * Returns the selected modifiers.
  	 * 
  	 * @return the selected modifiers
  	 * @see Flags 
  	 */	
  	public int getModifiers() {
  		int mdf= 0;
  		if (fAccMdfButtons.isSelected(PUBLIC_INDEX)) {
  			mdf+= F_PUBLIC;
  		} else if (fAccMdfButtons.isSelected(PRIVATE_INDEX)) {
  			mdf+= F_PRIVATE;
  		}
  		if (fOtherMdfButtons.isSelected(ABSTRACT_INDEX)) {	
  			mdf+= F_ABSTRACT;
  		}
  		if (fOtherMdfButtons.isSelected(STATIC_INDEX)) {	
  			mdf+= F_STATIC;
  		}
  		return mdf;
  	}
  
  	/**
  	 * Sets the modifiers.
  	 * 
  	 * @param modifiers <code>F_PUBLIC</code>, <code>F_PRIVATE</code>, 
  	 * <code>F_PROTECTED</code>, <code>F_ABSTRACT</code>, <code>F_FINAL</code>
  	 * or <code>F_STATIC</code> or a valid combination.
  	 * @param canBeModified if <code>true</code> the modifier fields are
  	 * editable; otherwise they are read-only
  	 * @see Flags 
  	 */		
  	public void setModifiers(int modifiers, boolean canBeModified) {
  		if (Flags.isPublic(modifiers)) {
  			fAccMdfButtons.setSelection(PUBLIC_INDEX, true);
  		} else if (Flags.isPrivate(modifiers)) {
  			fAccMdfButtons.setSelection(PRIVATE_INDEX, true);
  		} else {
  			fAccMdfButtons.setSelection(DEFAULT_INDEX, true);
  		}
  		if (Flags.isAbstract(modifiers)) {
  			fOtherMdfButtons.setSelection(ABSTRACT_INDEX, true);
  		}
  		if (Flags.isStatic(modifiers)) {
  			fOtherMdfButtons.setSelection(STATIC_INDEX, true);
  		}
  		
  		fAccMdfButtons.setEnabled(canBeModified);
  		fOtherMdfButtons.setEnabled(canBeModified);
  	}
  		
  	/**
  	 * Returns the content of the superclass input field.
  	 * 
  	 * @return the superclass name
  	 */
  	public String getSuperClass() {
  		return fSuperClassDialogField.getText();
  	}
  
  	/**
  	 * Sets the super class name.
  	 * 
  	 * @param name the new superclass name
  	 * @param canBeModified  if <code>true</code> the superclass name field is
  	 * editable; otherwise it is read-only.
  	 */		
  	public void setSuperClass(String name, boolean canBeModified) {
  		fSuperClassDialogField.setText(name);
  		fSuperClassDialogField.setEnabled(canBeModified);
  	}	
  	
  	/**
  	 * Returns the chosen super interfaces.
  	 * 
  	 * @return a list of chosen super interfaces. The list's elements
  	 * are of type <code>String</code>
  	 */
  	public List getSuperInterfaces() {
  		List interfaces= fSuperInterfacesDialogField.getElements();
  		ArrayList result= new ArrayList(interfaces.size());
  		for (Iterator iter= interfaces.iterator(); iter.hasNext();) {
  			InterfaceWrapper wrapper= (InterfaceWrapper) iter.next();
  			result.add(wrapper.interfaceName);
  		}
  		return result;
  	}
  
  	/**
  	 * Sets the super interfaces.
  	 * 
  	 * @param interfacesNames a list of super interface. The method requires that
  	 * the list's elements are of type <code>String</code>
  	 * @param canBeModified if <code>true</code> the super interface field is
  	 * editable; otherwise it is read-only.
  	 */	
  	public void setSuperInterfaces(List interfacesNames, boolean canBeModified) {
  		ArrayList interfaces= new ArrayList(interfacesNames.size());
  		for (Iterator iter= interfacesNames.iterator(); iter.hasNext();) {
  			interfaces.add(new InterfaceWrapper((String) iter.next()));
  		}
  		fSuperInterfacesDialogField.setElements(interfaces);
  		fSuperInterfacesDialogField.setEnabled(canBeModified);
  	}
  	
  	/**
  	 * Adds a super interface to the end of the list and selects it if it is not in the list yet.
  	 * 
  	 * @param superInterface the fully qualified type name of the interface.
  	 * @return returns <code>true</code>if the interfaces has been added, <code>false</code>
  	 * if the interface already is in the list.
  	 * 
  	 */
  	public boolean addSuperInterface(String superInterface) {
  		return fSuperInterfacesDialogField.addElement(new InterfaceWrapper(superInterface));
  	}
  	
  	
  	/**
  	 * Sets 'Add comment' checkbox. The value set will only be used when creating source when
  	 * the comment control is enabled (see {@link #enableCommentControl(boolean)}
  	 * 
  	 * @param doAddComments if <code>true</code>, comments are added.
  	 * @param canBeModified if <code>true</code> check box is
  	 * editable; otherwise it is read-only.
  	 * 	
  	 */	
  	public void setAddComments(boolean doAddComments, boolean canBeModified) {
  		fAddCommentButton.setSelection(doAddComments);
  		fAddCommentButton.setEnabled(canBeModified);
  	}
  	
  	/**
  	 * Sets to use the 'Add comment' checkbox value. Clients that use the 'Add comment' checkbox
  	 * additionally have to enable the control. This has been added for backwards compatibility.
  	 * 
  	 * @param useAddCommentValue if <code>true</code>, 
  	 * 	
  	 */	
  	public void enableCommentControl(boolean useAddCommentValue) {
  		fUseAddCommentButtonValue= useAddCommentValue;
  	}
  	
  	
  	/**
  	 * Returns if comments are added. This method can be overridden by clients.
  	 * The selection of the comment control is taken if enabled (see {@link #enableCommentControl(boolean)}, otherwise
  	 * the settings as specified in the preferences is used.
  	 * 
  	 * @return Returns <code>true</code> if comments can be added
  	 * 
  	 */	
  	public boolean isAddComments() {
  		if (fUseAddCommentButtonValue) {
  			return fAddCommentButton.isSelected();
  		}
  		return StubUtility.doAddComments(getJavaProject()); 
  	}
  			
  	/**
  	 * Returns the resource handle that corresponds to the compilation unit to was or
  	 * will be created or modified.
  	 * @return A resource or null if the page contains illegal values.
  	 * 
  	 */
  	public IResource getModifiedResource() {
  		IType enclosing= getEnclosingType();
  		if (enclosing != null) {
  			return enclosing.getResource();
  		}
  		IPackageFragment pack= getPackageFragment();
  		if (pack != null) {
  			String cuName= getCompilationUnitName(getTypeNameWithoutParameters());
  			return pack.getJavaScriptUnit(cuName).getResource();
  		}
  		return null;
  	}
  			
  	// ----------- validation ----------
  			
  	/*
  	 * @see org.eclipse.wst.jsdt.ui.wizards.NewContainerWizardPage#containerChanged()
  	 */
  	protected IStatus containerChanged() {
  		IStatus status= super.containerChanged();
  	    IPackageFragmentRoot root= getPackageFragmentRoot();
  		if ((fTypeKind == ANNOTATION_TYPE || fTypeKind == ENUM_TYPE) && !status.matches(IStatus.ERROR)) {
  	    	if (root != null && !JavaModelUtil.is50OrHigher(root.getJavaScriptProject())) {
  	    		// error as createType will fail otherwise (bug 96928)
  				return new StatusInfo(IStatus.ERROR, Messages.format(NewWizardMessages.NewTypeWizardPage_warning_NotJDKCompliant, root.getJavaScriptProject().getElementName()));  
  	    	}
  	    	if (fTypeKind == ENUM_TYPE) {
  		    	try {
  		    	    // if findType(...) == null then Enum is unavailable
  		    	    if (findType(root.getJavaScriptProject(), "java.lang.Enum") == null) //$NON-NLS-1$
  		    	        return new StatusInfo(IStatus.WARNING, NewWizardMessages.NewTypeWizardPage_warning_EnumClassNotFound);  
  		    	} catch (JavaScriptModelException e) {
  		    	    JavaScriptPlugin.log(e);
  		    	}
  	    	}
  	    }
  		
  		fCurrPackageCompletionProcessor.setPackageFragmentRoot(root);
  		if (root != null) {
  			fEnclosingTypeCompletionProcessor.setPackageFragment(root.getPackageFragment("")); //$NON-NLS-1$
  		}
  		return status;
  	}
  	
  	/**
  	 * A hook method that gets called when the package field has changed. The method 
  	 * validates the package name and returns the status of the validation. The validation
  	 * also updates the package fragment model.
  	 * <p>
  	 * Subclasses may extend this method to perform their own validation.
  	 * </p>
  	 * 
  	 * @return the status of the validation
  	 */
  	protected IStatus packageChanged() {
  		StatusInfo status= new StatusInfo();
  		IPackageFragmentRoot root= getPackageFragmentRoot();
  		fPackageDialogField.enableButton(root != null);
  		
  		IJavaScriptProject project= root != null ? root.getJavaScriptProject() : null;
  		
  		String packName= getPackageText();
  		if (packName.length() > 0) {
  			IStatus val= validatePackageName(packName, project);
  			if (val.getSeverity() == IStatus.ERROR) {
  				status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidPackageName, val.getMessage())); 
  				return status;
  			} else if (val.getSeverity() == IStatus.WARNING) {
  				status.setWarning(Messages.format(NewWizardMessages.NewTypeWizardPage_warning_DiscouragedPackageName, val.getMessage())); 
  				// continue
  			}
  		} else {
  			status.setWarning(NewWizardMessages.NewTypeWizardPage_warning_DefaultPackageDiscouraged); 
  		}
  		
  		if (project != null) {
  			fCurrPackage= root.getPackageFragment(packName);
  		} else {
  			status.setError(""); //$NON-NLS-1$
  		}
  		return status;
  	}
  
  	/*
  	 * Updates the 'default' label next to the package field.
  	 */	
  	private void updatePackageStatusLabel() {
  		String packName= getPackageText();
  		
  		if (packName.length() == 0) {
  			fPackageDialogField.setStatus(NewWizardMessages.NewTypeWizardPage_default); 
  		} else {
  			fPackageDialogField.setStatus(""); //$NON-NLS-1$
  		}
  	}
  	
  	/*
  	 * Updates the enable state of buttons related to the enclosing type selection checkbox.
  	 */
  	private void updateEnableState() {
  		boolean enclosing= isEnclosingTypeSelected();
  		fPackageDialogField.setEnabled(fCanModifyPackage && !enclosing);
  		fEnclosingTypeDialogField.setEnabled(fCanModifyEnclosingType && enclosing);
  		if (fTypeKind == ENUM_TYPE || fTypeKind == ANNOTATION_TYPE) {
  		    fOtherMdfButtons.enableSelectionButton(ABSTRACT_INDEX, enclosing);
  		    fOtherMdfButtons.enableSelectionButton(ENUM_ANNOT_STATIC_INDEX, enclosing);
  		}
  	}	
  
  	/**
  	 * Hook method that gets called when the enclosing type name has changed. The method 
  	 * validates the enclosing type and returns the status of the validation. It also updates the 
  	 * enclosing type model.
  	 * <p>
  	 * Subclasses may extend this method to perform their own validation.
  	 * </p>
  	 * 
  	 * @return the status of the validation
  	 */
  	protected IStatus enclosingTypeChanged() {
  		StatusInfo status= new StatusInfo();
  		fCurrEnclosingType= null;
  		
  		IPackageFragmentRoot root= getPackageFragmentRoot();
  		
  		fEnclosingTypeDialogField.enableButton(root != null);
  		if (root == null) {
  			status.setError(""); //$NON-NLS-1$
  			return status;
  		}
  		
  		String enclName= getEnclosingTypeText();
  		if (enclName.length() == 0) {
  			status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeEnterName); 
  			return status;
  		}
  		try {
  			IType type= findType(root.getJavaScriptProject(), enclName);
  			if (type == null) {
  				status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeNotExists); 
  				return status;
  			}
  
  			if (type.getJavaScriptUnit() == null) {
  				status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingNotInCU); 
  				return status;
  			}
  			if (!JavaModelUtil.isEditable(type.getJavaScriptUnit())) {
  				status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingNotEditable); 
  				return status;			
  			}
  			
  			fCurrEnclosingType= type;
  			IPackageFragmentRoot enclosingRoot= JavaModelUtil.getPackageFragmentRoot(type);
  			if (!enclosingRoot.equals(root)) {
  				status.setWarning(NewWizardMessages.NewTypeWizardPage_warning_EnclosingNotInSourceFolder); 
  			}
  			return status;
  		} catch (JavaScriptModelException e) {
  			status.setError(NewWizardMessages.NewTypeWizardPage_error_EnclosingTypeNotExists); 
  			JavaScriptPlugin.log(e);
  			return status;
  		}
  	}
  	
  	private IType findType(IJavaScriptProject project, String typeName) throws JavaScriptModelException {
  		if (project.exists()) {
  			return project.findType(typeName);
  		}
  		return null;
  	}
  	
  	private String getTypeNameWithoutParameters() {
  		String typeNameWithParameters= getTypeName();
  		int angleBracketOffset= typeNameWithParameters.indexOf('<');
  		if (angleBracketOffset == -1) {
  			return typeNameWithParameters;
  		} else {
  			return typeNameWithParameters.substring(0, angleBracketOffset);
  		}
  	}
  	
  	/**
  	 * Hook method that is called when evaluating the name of the compilation unit to create. By default, a file extension
  	 * <code>java</code> is added to the given type name, but implementors can override this behavior.
  	 * 
  	 * @param typeName the name of the type to create the compilation unit for.
  	 * @return the name of the compilation unit to be created for the given name
  	 * 
  	 * 
  	 */
  	protected String getCompilationUnitName(String typeName) {
  		return typeName + JavaModelUtil.DEFAULT_CU_SUFFIX;
  	}
  	
  	
  	/**
  	 * Hook method that gets called when the type name has changed. The method validates the 
  	 * type name and returns the status of the validation.
  	 * <p>
  	 * Subclasses may extend this method to perform their own validation.
  	 * </p>
  	 * 
  	 * @return the status of the validation
  	 */
  	protected IStatus typeNameChanged() {
  		StatusInfo status= new StatusInfo();
  		fCurrType= null;
  		String typeNameWithParameters= getTypeName();
  		// must not be empty
  		if (typeNameWithParameters.length() == 0) {
  			status.setError(NewWizardMessages.NewTypeWizardPage_error_EnterTypeName); 
  			return status;
  		}
  		
  		String typeName= getTypeNameWithoutParameters();
  		if (typeName.indexOf('.') != -1) {
  			status.setError(NewWizardMessages.NewTypeWizardPage_error_QualifiedName); 
  			return status;
  		}
  		
  		IJavaScriptProject project= getJavaProject();	
  		IStatus val= validateJavaTypeName(typeName, project);
  		if (val.getSeverity() == IStatus.ERROR) {
  			status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidTypeName, val.getMessage())); 
  			return status;
  		} else if (val.getSeverity() == IStatus.WARNING) {
  			status.setWarning(Messages.format(NewWizardMessages.NewTypeWizardPage_warning_TypeNameDiscouraged, val.getMessage())); 
  			// continue checking
  		}		
  
  		// must not exist
  		if (!isEnclosingTypeSelected()) {
  			IPackageFragment pack= getPackageFragment();
  			if (pack != null) {
  				IJavaScriptUnit cu= pack.getJavaScriptUnit(getCompilationUnitName(typeName));
  				fCurrType= cu.getType(typeName);
  				IResource resource= cu.getResource();
  
  				if (resource.exists()) {
  					status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists); 
  					return status;
  				}
  				URI location= resource.getLocationURI();
  				if (location != null) {
  					try {
  						IFileStore store= EFS.getStore(location);
  						if (store.fetchInfo().exists()) {
  							status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExistsDifferentCase); 
  							return status;
  						}
  					} catch (CoreException e) {
  						status.setError(Messages.format(
  							NewWizardMessages.NewTypeWizardPage_error_uri_location_unkown, 
  							Resources.getLocationString(resource)));
  					}
  				}
  			}
  		} else {
  			IType type= getEnclosingType();
  			if (type != null) {
  				fCurrType= type.getType(typeName);
  				if (fCurrType.exists()) {
  					status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeNameExists); 
  					return status;
  				}
  			}
  		}
  		
  		if (!typeNameWithParameters.equals(typeName) && project != null) {
  			if (!JavaModelUtil.is50OrHigher(project)) {
  				status.setError(NewWizardMessages.NewTypeWizardPage_error_TypeParameters); 
  				return status;
  			}
  			String typeDeclaration= "class " + typeNameWithParameters + " {}"; //$NON-NLS-1$//$NON-NLS-2$
  			ASTParser parser= ASTParser.newParser(AST.JLS3);
  			parser.setSource(typeDeclaration.toCharArray());
  			parser.setProject(project);
  			JavaScriptUnit compilationUnit= (JavaScriptUnit) parser.createAST(null);
  			IProblem[] problems= compilationUnit.getProblems();
  			if (problems.length > 0) {
  				status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidTypeName, problems[0].getMessage())); 
  				return status;
  			}
  		}
  		return status;
  	}
  	
  	/**
  	 * Hook method that gets called when the superclass name has changed. The method 
  	 * validates the superclass name and returns the status of the validation.
  	 * <p>
  	 * Subclasses may extend this method to perform their own validation.
  	 * </p>
  	 * 
  	 * @return the status of the validation
  	 */
  	protected IStatus superClassChanged() {
  		StatusInfo status= new StatusInfo();
  		IPackageFragmentRoot root= getPackageFragmentRoot();
  		fSuperClassDialogField.enableButton(root != null);
  		
  		fSuperClassStubTypeContext= null;
  		
  		String sclassName= getSuperClass();
  		if (sclassName.length() == 0) {
  			// accept the empty field (stands for java.lang.Object)
  			return status;
  		}
  		
  		if (root != null) {
  			Type type= TypeContextChecker.parseSuperClass(sclassName);
  			if (type == null) {
  				status.setError(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperClassName); 
  				return status;
  			}
  		} else {
  			status.setError(""); //$NON-NLS-1$
  		}
  		return status;
  	}
  
  	private StubTypeContext getSuperClassStubTypeContext() {
  		if (fSuperClassStubTypeContext == null) {
  			String typeName;
  			if (fCurrType != null) {
  				typeName= getTypeName();
  			} else {
  				typeName= JavaTypeCompletionProcessor.DUMMY_CLASS_NAME;
  			}
  			fSuperClassStubTypeContext= TypeContextChecker.createSuperClassStubTypeContext(typeName, getEnclosingType(), getPackageFragment());
  		}
  		return fSuperClassStubTypeContext;
  	}
  
  	/**
  	 * Hook method that gets called when the list of super interface has changed. The method 
  	 * validates the super interfaces and returns the status of the validation.
  	 * <p>
  	 * Subclasses may extend this method to perform their own validation.
  	 * </p>
  	 * 
  	 * @return the status of the validation
  	 */
  	protected IStatus superInterfacesChanged() {
  		StatusInfo status= new StatusInfo();
  		
  		IPackageFragmentRoot root= getPackageFragmentRoot();
  		fSuperInterfacesDialogField.enableButton(0, root != null);
  						
  		if (root != null) {
  			List elements= fSuperInterfacesDialogField.getElements();
  			int nElements= elements.size();
  			for (int i= 0; i < nElements; i++) {
  				String intfname= ((InterfaceWrapper) elements.get(i)).interfaceName;
  				Type type= TypeContextChecker.parseSuperInterface(intfname);
  				if (type == null) {
  					status.setError(Messages.format(NewWizardMessages.NewTypeWizardPage_error_InvalidSuperInterfaceName, intfname)); 
  					return status;
  				}
  			}				
  		}
  		return status;
  	}
  
  	private StubTypeContext getSuperInterfacesStubTypeContext() {
  		if (fSuperInterfaceStubTypeContext == null) {
  			String typeName;
  			if (fCurrType != null) {
  				typeName= getTypeName();
  			} else {
  				typeName= JavaTypeCompletionProcessor.DUMMY_CLASS_NAME;
  			}
  			fSuperInterfaceStubTypeContext= TypeContextChecker.createSuperInterfaceStubTypeContext(typeName, getEnclosingType(), getPackageFragment());
  		}
  		return fSuperInterfaceStubTypeContext;
  	}
  	
  	/**
  	 * Hook method that gets called when the modifiers have changed. The method validates 
  	 * the modifiers and returns the status of the validation.
  	 * <p>
  	 * Subclasses may extend this method to perform their own validation.
  	 * </p>
  	 * 
  	 * @return the status of the validation
  	 */
  	protected IStatus modifiersChanged() {
  		StatusInfo status= new StatusInfo();
  		return status;
  	}
  	
  	// selection dialogs
  
  	/**
  	 * Opens a selection dialog that allows to select a package. 
  	 * 
  	 * @return returns the selected package or <code>null</code> if the dialog has been canceled.
  	 * The caller typically sets the result to the package input field.
  	 * <p>
  	 * Clients can override this method if they want to offer a different dialog.
  	 * </p>
  	 * 
  	 * 
  	 */
  	protected IPackageFragment choosePackage() {
  		IPackageFragmentRoot froot= getPackageFragmentRoot();
  		IJavaScriptElement[] packages= null;
  		try {
  			if (froot != null && froot.exists()) {
  				packages= froot.getChildren();
  			}
  		} catch (JavaScriptModelException e) {
  			JavaScriptPlugin.log(e);
  		}
  		if (packages == null) {
  			packages= new IJavaScriptElement[0];
  		}
  		
  		ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), new JavaScriptElementLabelProvider(JavaScriptElementLabelProvider.SHOW_DEFAULT));
  		dialog.setIgnoreCase(false);
  		dialog.setTitle(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_title); 
  		dialog.setMessage(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_description); 
  		dialog.setEmptyListMessage(NewWizardMessages.NewTypeWizardPage_ChoosePackageDialog_empty); 
  		dialog.setElements(packages);
  		dialog.setHelpAvailable(false);
  		
  		IPackageFragment pack= getPackageFragment();
  		if (pack != null) {
  			dialog.setInitialSelections(new Object[] { pack });
  		}
  
  		if (dialog.open() == Window.OK) {
  			return (IPackageFragment) dialog.getFirstResult();
  		}
  		return null;
  	}
  	
  	/**
  	 * Opens a selection dialog that allows to select an enclosing type. 
  	 * 
  	 * @return returns the selected type or <code>null</code> if the dialog has been canceled.
  	 * The caller typically sets the result to the enclosing type input field.
  	 * <p>
  	 * Clients can override this method if they want to offer a different dialog.
  	 * </p>
  	 * 
  	 * 
  	 */
  	protected IType chooseEnclosingType() {
  		IPackageFragmentRoot root= getPackageFragmentRoot();
  		if (root == null) {
  			return null;
  		}
  		
  		IJavaScriptSearchScope scope= SearchEngine.createJavaSearchScope(new IJavaScriptElement[] { root });
  	
  		FilteredTypesSelectionDialog dialog= new FilteredTypesSelectionDialog(getShell(), 
  			false, getWizard().getContainer(), scope, IJavaScriptSearchConstants.TYPE);
  		dialog.setTitle(NewWizardMessages.NewTypeWizardPage_ChooseEnclosingTypeDialog_title); 
  		dialog.setMessage(NewWizardMessages.NewTypeWizardPage_ChooseEnclosingTypeDialog_description); 
  		dialog.setInitialPattern(Signature.getSimpleName(getEnclosingTypeText()));
  		
  		if (dialog.open() == Window.OK) {	
  			return (IType) dialog.getFirstResult();
  		}
  		return null;
  	}	
  	
  	/**
  	 * Opens a selection dialog that allows to select a super class. 
  	 * 
  	 * @return returns the selected type or <code>null</code> if the dialog has been canceled.
  	 * The caller typically sets the result to the super class input field.
  	 * 	<p>
  	 * Clients can override this method if they want to offer a different dialog.
  	 * </p>
  	 * 
  	 * 
  	 */
  	protected IType chooseSuperClass() {
  		IJavaScriptProject project= getJavaProject();
  		if (project == null) {
  			return null;
  		}
  		
  		IJavaScriptElement[] elements= new IJavaScriptElement[] { project };
  		IJavaScriptSearchScope scope= SearchEngine.createJavaSearchScope(elements);
  
  		FilteredTypesSelectionDialog dialog= new FilteredTypesSelectionDialog(getShell(), false,
  			getWizard().getContainer(), scope, IJavaScriptSearchConstants.CLASS);
  		dialog.setTitle(NewWizardMessages.NewTypeWizardPage_SuperClassDialog_title); 
  		dialog.setMessage(NewWizardMessages.NewTypeWizardPage_SuperClassDialog_message); 
  		dialog.setInitialPattern(getSuperClass());
  
  		if (dialog.open() == Window.OK) {
  			return (IType) dialog.getFirstResult();
  		}
  		return null;
  	}
  		
  	// ---- creation ----------------
  
  	/**
  	 * Creates the new type using the entered field values.
  	 * 
  	 * @param monitor a progress monitor to report progress.
  	 * @throws CoreException Thrown when the creation failed.
  	 * @throws InterruptedException Thrown when the operation was canceled.
  	 */
  	public void createType(IProgressMonitor monitor) throws CoreException, InterruptedException {		
  		if (monitor == null) {
  			monitor= new NullProgressMonitor();
  		}
  
  		monitor.beginTask(NewWizardMessages.NewTypeWizardPage_operationdesc, 8); 
  		
  		IPackageFragmentRoot root= getPackageFragmentRoot();
  		IPackageFragment pack= getPackageFragment();
  		if (pack == null) {
  			pack= root.getPackageFragment(""); //$NON-NLS-1$
  		}
  		
  		if (!pack.exists()) {
  			String packName= pack.getElementName();
  			pack= root.createPackageFragment(packName, true, new SubProgressMonitor(monitor, 1));
  		} else {
  			monitor.worked(1);
  		}
  		
  		boolean needsSave;
  		IJavaScriptUnit connectedCU= null;
  		
  		try {	
  			String typeName= getTypeNameWithoutParameters();
  			
  			boolean isInnerClass= isEnclosingTypeSelected();
  		
  			IType createdType;
  			ImportsManager imports;
  			int indent= 0;
  
  			Set /* String (import names) */ existingImports;
  			
  			String lineDelimiter= null;	
  			if (!isInnerClass) {
  				lineDelimiter= StubUtility.getLineDelimiterUsed(pack.getJavaScriptProject());
  				
  				String cuName= getCompilationUnitName(typeName);
  				IJavaScriptUnit parentCU= pack.createCompilationUnit(cuName, "", false, new SubProgressMonitor(monitor, 2)); //$NON-NLS-1$
  				// create a working copy with a new owner
  				
  				needsSave= true;
  				parentCU.becomeWorkingCopy(new SubProgressMonitor(monitor, 1)); // cu is now a (primary) working copy
  				connectedCU= parentCU;
  				
  				IBuffer buffer= parentCU.getBuffer();
  				
  				String simpleTypeStub= constructSimpleTypeStub();
  				String cuContent= constructCUContent(parentCU, simpleTypeStub, lineDelimiter);
  				buffer.setContents(cuContent);
  				
  				JavaScriptUnit astRoot= createASTForImports(parentCU);
  				existingImports= getExistingImports(astRoot);
  							
  				imports= new ImportsManager(astRoot);
  				// add an import that will be removed again. Having this import solves 14661
  				imports.addImport(JavaModelUtil.concatenateName(pack.getElementName(), typeName));
  				
  				String typeContent= constructTypeStub(parentCU, imports, lineDelimiter);
  				
  				int index= cuContent.lastIndexOf(simpleTypeStub);
  				if (index == -1) {
  					AbstractTypeDeclaration typeNode= (AbstractTypeDeclaration) astRoot.types().get(0);
  					int start= ((ASTNode) typeNode.modifiers().get(0)).getStartPosition();
  					int end= typeNode.getStartPosition() + typeNode.getLength();
  					buffer.replace(start, end - start, typeContent);
  				} else {
  					buffer.replace(index, simpleTypeStub.length(), typeContent);
  				}
  				
  				createdType= parentCU.getType(typeName);
  			} else {
  				IType enclosingType= getEnclosingType();
  				
  				IJavaScriptUnit parentCU= enclosingType.getJavaScriptUnit();
  				
  				needsSave= !parentCU.isWorkingCopy();
  				parentCU.becomeWorkingCopy(new SubProgressMonitor(monitor, 1)); // cu is now for sure (primary) a working copy
  				connectedCU= parentCU;
  				
  				JavaScriptUnit astRoot= createASTForImports(parentCU);
  				imports= new ImportsManager(astRoot);
  				existingImports= getExistingImports(astRoot);
  
  	
  				// add imports that will be removed again. Having the imports solves 14661
  				IType[] topLevelTypes= parentCU.getTypes();
  				for (int i= 0; i < topLevelTypes.length; i++) {
  					imports.addImport(topLevelTypes[i].getFullyQualifiedName('.'));
  				}
  				
  				lineDelimiter= StubUtility.getLineDelimiterUsed(enclosingType);
  				StringBuffer content= new StringBuffer();
  				
  				String comment= getTypeComment(parentCU, lineDelimiter);
  				if (comment != null) {
  					content.append(comment);
  					content.append(lineDelimiter);
  				}
  
  				content.append(constructTypeStub(parentCU, imports, lineDelimiter));
  				IJavaScriptElement sibling= null;
  				
  				IJavaScriptElement[] elems= enclosingType.getChildren();
  				sibling = elems.length > 0 ? elems[0] : null;
  				
  				createdType= enclosingType.createType(content.toString(), sibling, false, new SubProgressMonitor(monitor, 2));
  			
  				indent= StubUtility.getIndentUsed(enclosingType) + 1;
  			}
  			if (monitor.isCanceled()) {
  				throw new InterruptedException();
  			}
  			
  			// add imports for superclass/interfaces, so types can be resolved correctly
  			
  			IJavaScriptUnit cu= createdType.getJavaScriptUnit();	
  			
  			imports.create(false, new SubProgressMonitor(monitor, 1));
  				
  			JavaModelUtil.reconcile(cu);
  
  			if (monitor.isCanceled()) {
  				throw new InterruptedException();
  			}
  			
  			// set up again
  			JavaScriptUnit astRoot= createASTForImports(imports.getCompilationUnit());
  			imports= new ImportsManager(astRoot);
  			
  			createTypeMembers(createdType, imports, new SubProgressMonitor(monitor, 1));
  	
  			// add imports
  			imports.create(false, new SubProgressMonitor(monitor, 1));
  			
  			removeUnusedImports(cu, existingImports, false);
  			
  			JavaModelUtil.reconcile(cu);
  			
  			ISourceRange range= createdType.getSourceRange();
  			
  			IBuffer buf= cu.getBuffer();
  			String originalContent= buf.getText(range.getOffset(), range.getLength());
  			
  			String formattedContent= CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, originalContent, indent, null, lineDelimiter, pack.getJavaScriptProject());
  			formattedContent= Strings.trimLeadingTabsAndSpaces(formattedContent);
  			buf.replace(range.getOffset(), range.getLength(), formattedContent);
  			if (!isInnerClass) {
  				String fileComment= getFileComment(cu);
  				if (fileComment != null && fileComment.length() > 0) {
  					buf.replace(0, 0, fileComment + lineDelimiter);
  				}
  			}
  			fCreatedType= createdType;
  
  			if (needsSave) {
  				cu.commitWorkingCopy(true, new SubProgressMonitor(monitor, 1));
  			} else {
  				monitor.worked(1);
  			}
  			
  		} finally {
  			if (connectedCU != null) {
  				connectedCU.discardWorkingCopy();
  			}
  			monitor.done();
  		}
  	}	
  	
  	private JavaScriptUnit createASTForImports(IJavaScriptUnit cu) {
  		ASTParser parser= ASTParser.newParser(AST.JLS3);
  		parser.setSource(cu);
  		parser.setResolveBindings(false);
  		parser.setFocalPosition(0);
  		return (JavaScriptUnit) parser.createAST(null);
  	}
  	
  	
  	private Set /* String */ getExistingImports(JavaScriptUnit root) {
  		List imports= root.imports();
  		Set res= new HashSet(imports.size());
  		for (int i= 0; i < imports.size(); i++) {
  			res.add(ASTNodes.asString((ImportDeclaration) imports.get(i)));
  		}
  		return res;
  	}
  
  	private void removeUnusedImports(IJavaScriptUnit cu, Set existingImports, boolean needsSave) throws CoreException {
  		ASTParser parser= ASTParser.newParser(AST.JLS3);
  		parser.setSource(cu);
  		parser.setResolveBindings(true);
  		
  		JavaScriptUnit root= (JavaScriptUnit) parser.createAST(null);
  		if (root.getProblems().length == 0) {
  			return;
  		}
  		
  		List importsDecls= root.imports();
  		if (importsDecls.isEmpty()) {
  			return;
  		}
  		ImportsManager imports= new ImportsManager(root);
  		
  		int importsEnd= ASTNodes.getExclusiveEnd((ASTNode) importsDecls.get(importsDecls.size() - 1));
  		IProblem[] problems= root.getProblems();
  		for (int i= 0; i < problems.length; i++) {
  			IProblem curr= problems[i];
  			if (curr.getSourceEnd() < importsEnd) {
  				int id= curr.getID();
  				if( id == IProblem.NotVisibleType) { // not visible problems hide unused -> remove both
  					int pos= curr.getSourceStart();
  					for (int k= 0; k < importsDecls.size(); k++) {
  						ImportDeclaration decl= (ImportDeclaration) importsDecls.get(k);
  						if (decl.getStartPosition() <= pos && pos < decl.getStartPosition() + decl.getLength()) {
  							if (existingImports.isEmpty() || !existingImports.contains(ASTNodes.asString(decl))) {
  								String name= decl.getName().getFullyQualifiedName();
  								if (decl.isOnDemand()) {
  									name += ".*"; //$NON-NLS-1$
  								}
  								if (decl.isStatic()) {
  									imports.removeStaticImport(name);
  								} else {
  									imports.removeImport(name);
  								}
  							}
  							break;
  						}
  					}
  				}
  			}
  		}
  		imports.create(needsSave, null);
  	}
  
  	/**
  	 * Uses the New JavaScript file template from the code template page to generate a
  	 * compilation unit with the given type content.
  	 * @param cu The new created compilation unit
  	 * @param typeContent The content of the type, including signature and type
  	 * body.
  	 * @param lineDelimiter The line delimiter to be used.
  	 * @return String Returns the result of evaluating the new file template
  	 * with the given type content.
  	 * @throws CoreException
  	 * 
  	 */
  	protected String constructCUContent(IJavaScriptUnit cu, String typeContent, String lineDelimiter) throws CoreException {
  		String fileComment= getFileComment(cu, lineDelimiter);
  		String typeComment= getTypeComment(cu, lineDelimiter);
  		IPackageFragment pack= (IPackageFragment) cu.getParent();
  		String content= CodeGeneration.getCompilationUnitContent(cu, fileComment, typeComment, typeContent, lineDelimiter);
  		if (content != null) {
  			ASTParser parser= ASTParser.newParser(AST.JLS3);
  			parser.setProject(cu.getJavaScriptProject());
  			parser.setSource(content.toCharArray());
  			JavaScriptUnit unit= (JavaScriptUnit) parser.createAST(null);
  			if ((pack.isDefaultPackage() || unit.getPackage() != null) && !unit.types().isEmpty()) {
  				return content;
  			}
  		}
  		StringBuffer buf= new StringBuffer();
  		if (!pack.isDefaultPackage()) {
  			buf.append("package ").append(pack.getElementName()).append(';'); //$NON-NLS-1$
  		}
  		buf.append(lineDelimiter).append(lineDelimiter);
  		if (typeComment != null) {
  			buf.append(typeComment).append(lineDelimiter);
  		}
  		buf.append(typeContent);
  		return buf.toString();
  	}
  	
  
  	/**
  	 * Returns the created type or <code>null</code> is the type has not been created yet. The method
  	 * only returns a valid type after <code>createType</code> has been called.
  	 * 
  	 * @return the created type
  	 * @see #createType(IProgressMonitor)
  	 */			
  	public IType getCreatedType() {
  		return fCreatedType;
  	}
  	
  	// ---- construct CU body----------------
  		
  	private void writeSuperClass(StringBuffer buf, ImportsManager imports) {
  		String superclass= getSuperClass();
  		if (fTypeKind == CLASS_TYPE && superclass.length() > 0 && !"java.lang.Object".equals(superclass)) { //$NON-NLS-1$
  			buf.append(" extends "); //$NON-NLS-1$
  			
  			ITypeBinding binding= null;
  			if (fCurrType != null) {
  				binding= TypeContextChecker.resolveSuperClass(superclass, fCurrType, getSuperClassStubTypeContext());
  			}
  			if (binding != null) {
  				buf.append(imports.addImport(binding));
  			} else {
  				buf.append(imports.addImport(superclass));
  			}
  		}
  	}
  	
  	private void writeSuperInterfaces(StringBuffer buf, ImportsManager imports) {
  		List interfaces= getSuperInterfaces();
  		int last= interfaces.size() - 1;
  		if (last >= 0) {
  		    if (fTypeKind != INTERFACE_TYPE) {
  				buf.append(" implements "); //$NON-NLS-1$
  			} else {
  				buf.append(" extends "); //$NON-NLS-1$
  			}
  			String[] intfs= (String[]) interfaces.toArray(new String[interfaces.size()]);
  			ITypeBinding[] bindings;
  			if (fCurrType != null) {
  				bindings= TypeContextChecker.resolveSuperInterfaces(intfs, fCurrType, getSuperInterfacesStubTypeContext());
  			} else {
  				bindings= new ITypeBinding[intfs.length];
  			}
  			for (int i= 0; i <= last; i++) {
  				ITypeBinding binding= bindings[i];
  				if (binding != null) {
  					buf.append(imports.addImport(binding));
  				} else {
  					buf.append(imports.addImport(intfs[i]));
  				}
  				if (i < last) {
  					buf.append(',');
  				}
  			}
  		}
  	}
  	
  	
  	private String constructSimpleTypeStub() {
  		StringBuffer buf= new StringBuffer("public class "); //$NON-NLS-1$
  		buf.append(getTypeName());
  		buf.append("{ }"); //$NON-NLS-1$
  		return buf.toString();
  	}
  	
  	/*
  	 * Called from createType to construct the source for this type
  	 */		
  	private String constructTypeStub(IJavaScriptUnit parentCU, ImportsManager imports, String lineDelimiter) throws CoreException {
  		StringBuffer buf= new StringBuffer();
  		
  		int modifiers= getModifiers();
  		buf.append(Flags.toString(modifiers));
  		if (modifiers != 0) {
  			buf.append(' ');
  		}
  		String type= ""; //$NON-NLS-1$
  		String templateID= ""; //$NON-NLS-1$
  		switch (fTypeKind) {
  			case CLASS_TYPE: 
  				type= "class ";  //$NON-NLS-1$
  				templateID= CodeGeneration.CLASS_BODY_TEMPLATE_ID;
  				break;
  		}
  		buf.append(type);
  		buf.append(getTypeName());
  		writeSuperClass(buf, imports);
  		writeSuperInterfaces(buf, imports);	
  
  		buf.append(" {").append(lineDelimiter); //$NON-NLS-1$
  		String typeBody= CodeGeneration.getTypeBody(templateID, parentCU, getTypeName(), lineDelimiter);
  		if (typeBody != null) {
  			buf.append(typeBody);
  		} else {
  			buf.append(lineDelimiter);
  		}
  		buf.append('}').append(lineDelimiter);
  		return buf.toString();
  	}
  	
  	/**
  	 * Hook method that gets called from <code>createType</code> to support adding of 
  	 * unanticipated methods, fields, and inner types to the created type.
  	 * <p>
  	 * Implementers can use any methods defined on <code>IType</code> to manipulate the
  	 * new type.
  	 * </p>
  	 * <p>
  	 * The source code of the new type will be formatted using the platform's formatter. Needed 
  	 * imports are added by the wizard at the end of the type creation process using the given 
  	 * import manager.
  	 * </p>
  	 * 
  	 * @param newType the new type created via <code>createType</code>
  	 * @param imports an import manager which can be used to add new imports
  	 * @param monitor a progress monitor to report progress. Must not be <code>null</code>
  	 * @throws CoreException thrown when creation of the type members failed
  	 * 
  	 * @see #createType(IProgressMonitor)
  	 */		
  	protected void createTypeMembers(IType newType, final ImportsManager imports, IProgressMonitor monitor) throws CoreException {
  		// default implementation does nothing
  		// example would be
  		// String mainMathod= "public void foo(Vector vec) {}"
  		// createdType.createMethod(main, null, false, null);
  		// imports.addImport("java.lang.Vector");
  	}
  	
  		
  	/**
  	 * @param parentCU the current compilation unit
  	 * @return returns the file template or <code>null</code>
  	 * @deprecated Instead of file templates, the new type code template
  	 * specifies the stub for a compilation unit.
  	 */		
  	protected String getFileComment(IJavaScriptUnit parentCU) {
  		return null;
  	}
  	
  	/**
  	 * Hook method that gets called from <code>createType</code> to retrieve 
  	 * a file comment. This default implementation returns the content of the 
  	 * 'file comment' template or <code>null</code> if no comment should be created.
  	 * 
  	 * @param parentCU the parent compilation unit
  	 * @param lineDelimiter the line delimiter to use
  	 * @return the file comment or <code>null</code> if a file comment 
  	 * is not desired
  	 * @throws CoreException 
       *
       * 
  	 */		
  	protected String getFileComment(IJavaScriptUnit parentCU, String lineDelimiter) throws CoreException {
  		if (isAddComments()) {
  			return CodeGeneration.getFileComment(parentCU, lineDelimiter);
  		}
  		return null;
  		
  	}
  	
  	private boolean isValidComment(String template) {
  		IScanner scanner= ToolFactory.createScanner(true, false, false, false);
  		scanner.setSource(template.toCharArray());
  		try {
  			int next= scanner.getNextToken();
  			while (TokenScanner.isComment(next)) {
  				next= scanner.getNextToken();
  			}
  			return next == ITerminalSymbols.TokenNameEOF;
  		} catch (InvalidInputException e) {
  		}
  		return false;
  	}
  	
  	/**
  	 * Hook method that gets called from <code>createType</code> to retrieve 
  	 * a type comment. This default implementation returns the content of the 
  	 * 'type comment' template.
  	 * 
  	 * @param parentCU the parent compilation unit
  	 * @param lineDelimiter the line delimiter to use
  	 * @return the type comment or <code>null</code> if a type comment 
  	 * is not desired
       *
       * 
  	 */		
  	protected String getTypeComment(IJavaScriptUnit parentCU, String lineDelimiter) {
  		if (isAddComments()) {
  			try {
  				StringBuffer typeName= new StringBuffer();
  				if (isEnclosingTypeSelected()) {
  					typeName.append(JavaModelUtil.getTypeQualifiedName(getEnclosingType())).append('.');
  				}
  				typeName.append(getTypeNameWithoutParameters());
  				String comment= CodeGeneration.getTypeComment(parentCU, typeName.toString(), lineDelimiter);
  				if (comment != null && isValidComment(comment)) {
  					return comment;
  				}
  			} catch (CoreException e) {
  				JavaScriptPlugin.log(e);
  			}
  		}
  		return null;
  	}
  
  	/**
  	 * Returns the string resulting from evaluation the given template in
  	 * the context of the given compilation unit. This accesses the normal
  	 * template page, not the code templates. To use code templates use
  	 * <code>constructCUContent</code> to construct a compilation unit stub or
  	 * getTypeComment for the comment of the type.
  	 * 
  	 * @param name the template to be evaluated
  	 * @param parentCU the templates evaluation context
  	 * @param pos a source offset into the parent compilation unit. The
  	 * template is evaluated at the given source offset
  	 * @return return the template with the given name or <code>null</code> if the template could not be found.
  	 */
  	protected String getTemplate(String name, IJavaScriptUnit parentCU, int pos) {
  		try {
  			Template template= JavaScriptPlugin.getDefault().getTemplateStore().findTemplate(name);
  			if (template != null) {
  				return JavaContext.evaluateTemplate(template, parentCU, pos);
  			}
  		} catch (CoreException e) {
  			JavaScriptPlugin.log(e);
  		} catch (BadLocationException e) {
  			JavaScriptPlugin.log(e);
  		} catch (TemplateException e) {
  			JavaScriptPlugin.log(e);
  		}
  		return null;
  	}	
  	
  
  	/**
  	 * Creates the bodies of all unimplemented methods and constructors and adds them to the type.
  	 * Method is typically called by implementers of <code>NewTypeWizardPage</code> to add
  	 * needed method and constructors.
  	 * 
  	 * @param type the type for which the new methods and constructor are to be created
  	 * @param doConstructors if <code>true</code> unimplemented constructors are created
  	 * @param doUnimplementedMethods if <code>true</code> unimplemented methods are created
  	 * @param imports an import manager to add all needed import statements
  	 * @param monitor a progress monitor to report progress
  	 * @return the created methods.
  	 * @throws CoreException thrown when the creation fails.
  	 */
  	protected IFunction[] createInheritedMethods(IType type, boolean doConstructors, boolean doUnimplementedMethods, ImportsManager imports, IProgressMonitor monitor) throws CoreException {
  		final IJavaScriptUnit cu= type.getJavaScriptUnit();
  		JavaModelUtil.reconcile(cu);
  		IFunction[] typeMethods= type.getFunctions();
  		Set handleIds= new HashSet(typeMethods.length);
  		for (int index= 0; index < typeMethods.length; index++)
  			handleIds.add(typeMethods[index].getHandleIdentifier());
  		ArrayList newMethods= new ArrayList();
  		CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(type.getJavaScriptProject());
  		settings.createComments= isAddComments();
  		ASTParser parser= ASTParser.newParser(AST.JLS3);
  		parser.setResolveBindings(true);
  		parser.setSource(cu);
  		JavaScriptUnit unit= (JavaScriptUnit) parser.createAST(new SubProgressMonitor(monitor, 1));
  		final ITypeBinding binding= ASTNodes.getTypeBinding(unit, type);
  		if (binding != null) {
  			if (doUnimplementedMethods) {
  				AddUnimplementedMethodsOperation operation= new AddUnimplementedMethodsOperation(unit, binding, null, -1, false, true, false);
  				operation.setCreateComments(isAddComments());
  				operation.run(monitor);
  				createImports(imports, operation.getCreatedImports());
  			}
  			if (doConstructors) {
  				AddUnimplementedConstructorsOperation operation= new AddUnimplementedConstructorsOperation(unit, binding, null, -1, false, true, false);
  				operation.setOmitSuper(true);
  				operation.setCreateComments(isAddComments());
  				operation.run(monitor);
  				createImports(imports, operation.getCreatedImports());
  			}
  		}
  		JavaModelUtil.reconcile(cu);
  		typeMethods= type.getFunctions();
  		for (int index= 0; index < typeMethods.length; index++)
  			if (!handleIds.contains(typeMethods[index].getHandleIdentifier()))
  				newMethods.add(typeMethods[index]);
  		IFunction[] methods= new IFunction[newMethods.size()];
  		newMethods.toArray(methods);
  		return methods;
  	}
  
  	private void createImports(ImportsManager imports, String[] createdImports) {
  		for (int index= 0; index < createdImports.length; index++)
  			imports.addImport(createdImports[index]);
  	}
  
  	
  	// ---- creation ----------------
  
  	/**
  	 * Returns the runnable that creates the type using the current settings.
  	 * The returned runnable must be executed in the UI thread.
  	 * 
  	 * @return the runnable to create the new type
  	 */		
  	public IRunnableWithProgress getRunnable() {				
  		return new IRunnableWithProgress() {
  			public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
  				try {
  					if (monitor == null) {
  						monitor= new NullProgressMonitor();
  					}
  					createType(monitor);
  				} catch (CoreException e) {
  					throw new InvocationTargetException(e);
  				} 				
  			}
  		};
  	}
  }
  