content: /*******************************************************************************
   * Copyright (c) 2000, 2009 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
   *******************************************************************************/
  package org.eclipse.wst.jsdt.internal.ui.dialogs;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  
  import org.eclipse.jface.dialogs.IDialogConstants;
  import org.eclipse.jface.dialogs.IDialogSettings;
  import org.eclipse.jface.resource.StringConverter;
  import org.eclipse.jface.text.ITextSelection;
  import org.eclipse.jface.viewers.CheckboxTreeViewer;
  import org.eclipse.jface.viewers.ILabelProvider;
  import org.eclipse.jface.viewers.ITreeContentProvider;
  import org.eclipse.jface.viewers.StructuredSelection;
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.SelectionAdapter;
  import org.eclipse.swt.events.SelectionEvent;
  import org.eclipse.swt.events.SelectionListener;
  import org.eclipse.swt.layout.GridData;
  import org.eclipse.swt.layout.GridLayout;
  import org.eclipse.swt.widgets.Button;
  import org.eclipse.swt.widgets.Combo;
  import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.Control;
  import org.eclipse.swt.widgets.Group;
  import org.eclipse.swt.widgets.Label;
  import org.eclipse.swt.widgets.Shell;
  import org.eclipse.swt.widgets.TreeItem;
  import org.eclipse.ui.dialogs.CheckedTreeSelectionDialog;
  import org.eclipse.ui.dialogs.PreferencesUtil;
  import org.eclipse.wst.jsdt.core.IFunction;
  import org.eclipse.wst.jsdt.core.IJavaScriptElement;
  import org.eclipse.wst.jsdt.core.IMember;
  import org.eclipse.wst.jsdt.core.ISourceRange;
  import org.eclipse.wst.jsdt.core.ISourceReference;
  import org.eclipse.wst.jsdt.core.IType;
  import org.eclipse.wst.jsdt.core.JavaScriptModelException;
  import org.eclipse.wst.jsdt.core.dom.Modifier;
  import org.eclipse.wst.jsdt.internal.corext.util.Messages;
  import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
  import org.eclipse.wst.jsdt.internal.ui.actions.ActionMessages;
  import org.eclipse.wst.jsdt.internal.ui.javaeditor.CompilationUnitEditor;
  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.IVisibilityChangeListener;
  import org.eclipse.wst.jsdt.ui.JavaScriptElementLabels;
  
  /**
   * An advanced version of CheckedTreeSelectionDialog with right-side button layout and
   * extra buttons and composites.
   */
  public class SourceActionDialog extends CheckedTreeSelectionDialog {
  	
  	protected List fInsertPositions;
  	protected List fLabels;
  	protected int fCurrentPositionIndex;
  	
  	protected IDialogSettings fSettings;
  	protected CompilationUnitEditor fEditor;
  	protected ITreeContentProvider fContentProvider;
  	protected boolean fGenerateComment;
  	protected IType fType;
  	protected int fWidth, fHeight;
  	protected String fCommentString;
  	protected boolean fEnableInsertPosition= true;
  		
  	protected int fVisibilityModifier;
  	protected boolean fFinal;
  	protected boolean fSynchronized;
  	
  	protected final String SETTINGS_SECTION_METHODS= "SourceActionDialog.methods"; //$NON-NLS-1$
  	protected final String SETTINGS_SECTION_CONSTRUCTORS= "SourceActionDialog.constructors"; //$NON-NLS-1$
  	
  	protected final String SETTINGS_INSERTPOSITION= "InsertPosition"; //$NON-NLS-1$
  	protected final String SETTINGS_VISIBILITY_MODIFIER= "VisibilityModifier"; //$NON-NLS-1$
  	protected final String SETTINGS_FINAL_MODIFIER= "FinalModifier"; //$NON-NLS-1$
  	protected final String SETTINGS_SYNCHRONIZED_MODIFIER= "SynchronizedModifier"; //$NON-NLS-1$
  	protected final String SETTINGS_COMMENTS= "Comments"; //$NON-NLS-1$
  	protected Composite fInsertPositionComposite;
  	
  	public SourceActionDialog(Shell parent, ILabelProvider labelProvider, ITreeContentProvider contentProvider, CompilationUnitEditor editor, IType type, boolean isConstructor) throws JavaScriptModelException {
  		super(parent, labelProvider, contentProvider);
  		fEditor= editor;
  		fContentProvider= contentProvider;		
  		fType= type;
  		fCommentString= ActionMessages.SourceActionDialog_createMethodComment; 
  		setEmptyListMessage(ActionMessages.SourceActionDialog_no_entries); 
  
  		fWidth= 60;
  		fHeight= 18;
  		
  		int insertionDefault= isConstructor ? 0 : 1;
  		boolean generateCommentsDefault= JavaPreferencesSettings.getCodeGenerationSettings(type.getJavaScriptProject()).createComments;
  		
  		IDialogSettings dialogSettings= JavaScriptPlugin.getDefault().getDialogSettings();
  		String sectionId= isConstructor ? SETTINGS_SECTION_CONSTRUCTORS : SETTINGS_SECTION_METHODS;
  		fSettings= dialogSettings.getSection(sectionId);		
  		if (fSettings == null)  {
  			fSettings= dialogSettings.addNewSection(sectionId);
  		}	
  		
  		fVisibilityModifier= asInt(fSettings.get(SETTINGS_VISIBILITY_MODIFIER), Modifier.PUBLIC);
  		fFinal= asBoolean(fSettings.get(SETTINGS_FINAL_MODIFIER), false);
  		fSynchronized= asBoolean(fSettings.get(SETTINGS_SYNCHRONIZED_MODIFIER), false);
  		fCurrentPositionIndex= asInt(fSettings.get(SETTINGS_INSERTPOSITION), insertionDefault);
  		fGenerateComment= asBoolean(fSettings.get(SETTINGS_COMMENTS), generateCommentsDefault);
  		setupInsertPostions();
  	}
  
  	public void setupInsertPostions(){
  		fInsertPositions= new ArrayList();
  		fLabels= new ArrayList(); 
  		
  		IJavaScriptElement[] members = new IJavaScriptElement[0];
  		IFunction[] methods = new IFunction[0];
  		try {
  			members = fType.getChildren();
  			methods= fType.getFunctions();
  		} catch (JavaScriptModelException e) {
  			// TODO Auto-generated catch block
  			e.printStackTrace();
  		}
  		
  		
  		fInsertPositions.add(methods.length > 0 ? methods[0]: null); // first
  		fInsertPositions.add(null); // last
  		
  		fLabels.add(ActionMessages.SourceActionDialog_first_method); 
  		fLabels.add(ActionMessages.SourceActionDialog_last_method); 
  
  		try {
  			if (hasCursorPositionElement(fEditor, members, fInsertPositions)) {
  				fLabels.add(ActionMessages.SourceActionDialog_cursor); 
  				fCurrentPositionIndex= 2;
  			} else {
  				// code is needed to deal with bogus values already present in the dialog store.
  				fCurrentPositionIndex= Math.max(fCurrentPositionIndex, 0);
  				fCurrentPositionIndex= Math.min(fCurrentPositionIndex, 1);
  			}
  		} catch (JavaScriptModelException e) {
  			// TODO Auto-generated catch block
  			e.printStackTrace();
  		}
  		
  		for (int i = 0; i < methods.length; i++) {
  			IFunction curr= methods[i];
  			String methodLabel= JavaScriptElementLabels.getElementLabel(curr, JavaScriptElementLabels.M_PARAMETER_TYPES);
  			fLabels.add(Messages.format(ActionMessages.SourceActionDialog_after, methodLabel)); 
  			try {
  				fInsertPositions.add(findSibling(curr, members));
  			} catch (JavaScriptModelException e) {
  				// TODO Auto-generated catch block
  				e.printStackTrace();
  			}
  		}
  		fInsertPositions.add(null);
  	}
  	
  	protected IType getType() {
  		return fType;
  	}
  
  	protected boolean asBoolean(String string, boolean defaultValue) {
  		if (string != null) {
  			return StringConverter.asBoolean(string, defaultValue);
  		}
  		return defaultValue;
  	}
  
  	protected int asInt(String string, int defaultValue) {
  		if (string != null) {
  			return StringConverter.asInt(string, defaultValue);
  		}
  		return defaultValue;
  	}
  
  	private IJavaScriptElement findSibling(IFunction curr, IJavaScriptElement[] members) throws JavaScriptModelException {
  		IJavaScriptElement res= null;
  		int methodStart= curr.getSourceRange().getOffset();
  		for (int i= members.length-1; i >= 0; i--) {
  			IMember member= (IMember) members[i];
  			if (methodStart >= member.getSourceRange().getOffset()) {
  				return res;
  			}
  			res= member;
  		}
  		return null;
  	}
  
  	protected boolean hasCursorPositionElement(CompilationUnitEditor editor, IJavaScriptElement[] members, List insertPositions) throws JavaScriptModelException {
  		if (editor == null) {
  			return false;
  		}
  		int offset= ((ITextSelection) editor.getSelectionProvider().getSelection()).getOffset();
  
  		for (int i= 0; i < members.length; i++) {
  			IMember curr= (IMember) members[i];
  			ISourceRange range= curr.getSourceRange();
  			if (offset < range.getOffset()) {
  				insertPositions.add(curr);
  				return true;
  			} else if (offset < range.getOffset() + range.getLength()) {
  				return false; // in the middle of a member
  			}
  		}
  		insertPositions.add(null);
  		return true;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.eclipse.jface.dialogs.Dialog#close()
  	 */
  	public boolean close() {
  		fSettings.put(SETTINGS_VISIBILITY_MODIFIER, StringConverter.asString(fVisibilityModifier));
  		fSettings.put(SETTINGS_FINAL_MODIFIER, StringConverter.asString(fFinal));
  		fSettings.put(SETTINGS_SYNCHRONIZED_MODIFIER, StringConverter.asString(fSynchronized));
  		
  		if (fCurrentPositionIndex == 0 || fCurrentPositionIndex == 1) {
  			fSettings.put(SETTINGS_INSERTPOSITION, StringConverter.asString(fCurrentPositionIndex));
  		}
  		fSettings.put(SETTINGS_COMMENTS, fGenerateComment);
  		return super.close();
  	}
  	
  	/**
  	 * Sets the size of the tree in unit of characters.
  	 * @param width  the width of the tree.
  	 * @param height the height of the tree.
  	 */
  	public void setSize(int width, int height) {
  		fWidth = width;
  		fHeight = height;
  	}
  
  	
  	/***
  	 * Set insert position valid input is 0 for the first position, 1 for the last position, > 1 for all else.
  	 */
  	private void setInsertPosition(int insert) {
  		fCurrentPositionIndex= insert;
  	}	
  	
  	public void setCommentString(String string) {
  		fCommentString= string;
  	}
  
  	protected ITreeContentProvider getContentProvider() {
  		return fContentProvider;
  	}
  	
  	public boolean getGenerateComment() {
  		return fGenerateComment;
  	}
  	
  	public int getVisibilityModifier() {
  		return fVisibilityModifier;
  	}
  	
  	public void setGenerateComment(boolean comment) {
  		fGenerateComment= comment;
  	}
  	
  	protected void setVisibility(int visibility) {
  		fVisibilityModifier= visibility;
  	}
  	
  	private void setFinal(boolean value) {
  		fFinal= value;
  	}
  		
  	private void setSynchronized(boolean value)  {
  		fSynchronized= value;
  	}	
  	
  	protected Composite createSelectionButtons(Composite composite) {
  		Composite buttonComposite= super.createSelectionButtons(composite);
  
  		GridLayout layout = new GridLayout();
  		buttonComposite.setLayout(layout);						
  
  		layout.marginHeight= 0;
  		layout.marginWidth= 0;						
  		layout.numColumns= 1;
  			
  		return buttonComposite;
  	}	
  	
  	protected void buttonPressed(int buttonId) {
  		switch (buttonId) {
  			case IDialogConstants.OK_ID: {
  				okPressed();
  				break;
  			}
  			case IDialogConstants.CANCEL_ID: {
  				cancelPressed();
  				break;
  			}
  		}
  	}
  	
  	/**
  	 * Returns a composite containing the label created at the top of the dialog. Returns null if there is the
  	 * message for the label is null.
  	 */
  	protected Label createMessageArea(Composite composite) {
  		if (getMessage() != null) {
  			Label label = new Label(composite,SWT.NONE);
  			label.setText(getMessage());
  			label.setFont(composite.getFont());
  			return label;
  		} 
  		return null;
  	}
  	
  	/*
  	 * @see Dialog#createDialogArea(Composite)
  	 */
  	protected Control createDialogArea(Composite parent) {
  		initializeDialogUnits(parent);
  			
  		Composite composite= new Composite(parent, SWT.NONE);
  		GridLayout layout= new GridLayout();
  		GridData gd= null;
  		
  		layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
  		layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
  		layout.verticalSpacing=	convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
  		layout.horizontalSpacing= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);			
  		composite.setLayout(layout);
  						
  		Label messageLabel = createMessageArea(composite);			
  		if (messageLabel != null) {
  			gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
  			gd.horizontalSpan= 2;
  			messageLabel.setLayoutData(gd);	
  		}
  			
  		Composite inner= new Composite(composite, SWT.NONE);
  		GridLayout innerLayout = new GridLayout();
  		innerLayout.numColumns= 2;
  		innerLayout.marginHeight= 0;
  		innerLayout.marginWidth= 0;
  		inner.setLayout(innerLayout);
  		inner.setFont(parent.getFont());		
  			
  		CheckboxTreeViewer treeViewer= createTreeViewer(inner);
  		gd= new GridData(GridData.FILL_BOTH);
  		gd.widthHint = convertWidthInCharsToPixels(fWidth);
  		gd.heightHint = convertHeightInCharsToPixels(fHeight);
  		treeViewer.getControl().setLayoutData(gd);			
  		
  		Composite buttonComposite= createSelectionButtons(inner);
  		gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
  		buttonComposite.setLayoutData(gd);
  			
  		gd= new GridData(GridData.FILL_BOTH);
  		inner.setLayoutData(gd);
  		
  		fInsertPositionComposite= createInsertPositionCombo(composite);
  		fInsertPositionComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  
  		Composite commentComposite= createCommentSelection(composite);
  		commentComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));		
  
  		Control linkControl= createLinkControl(composite);
  		if (linkControl != null)
  			linkControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  		
  		gd= new GridData(GridData.FILL_BOTH);
  		composite.setLayoutData(gd);
  		
  		applyDialogFont(composite);
  					
  		return composite;
  	}				
  
  	protected Control createLinkControl(Composite composite) {
  		return null; // No link as default
  	}
  	
  	protected void openCodeTempatePage(String id) {
  		HashMap arg= new HashMap();
  		arg.put(CodeTemplatePreferencePage.DATA_SELECT_TEMPLATE, id);
  		PreferencesUtil.createPropertyDialogOn(getShell(), fType.getJavaScriptProject().getProject(), CodeTemplatePreferencePage.PROP_ID, null, arg).open();
  	}
  	
  
  	protected Composite createCommentSelection(Composite composite) {
  		Composite commentComposite = new Composite(composite, SWT.NONE);
  		GridLayout layout = new GridLayout();
  		layout.marginHeight= 0;
  		layout.marginWidth= 0;
  		commentComposite.setLayout(layout);
  		commentComposite.setFont(composite.getFont());	
  		
  		Button commentButton= new Button(commentComposite, SWT.CHECK);
  		commentButton.setText(fCommentString); 
  
  		commentButton.addSelectionListener(new SelectionListener() {
  			public void widgetSelected(SelectionEvent e) {
  				boolean isSelected= (((Button) e.widget).getSelection());
  				setGenerateComment(isSelected);
  			}
  
  			public void widgetDefaultSelected(SelectionEvent e) {
  				widgetSelected(e);
  			}
  		});
  		commentButton.setSelection(getGenerateComment());
  		GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
  		gd.horizontalSpan= 2;
  		commentButton.setLayoutData(gd);
  		
  		return commentComposite;
  	}
  
  	protected Composite addVisibilityAndModifiersChoices(Composite buttonComposite) {
  		// Add visibility and modifiers buttons: http://bugs.eclipse.org/bugs/show_bug.cgi?id=35870
  		// Add persistence of options: http://bugs.eclipse.org/bugs/show_bug.cgi?id=38400
  		IVisibilityChangeListener visibilityChangeListener= new IVisibilityChangeListener(){
  			public void visibilityChanged(int newVisibility) {
  				setVisibility(newVisibility);
  			}
  			public void modifierChanged(int modifier, boolean isChecked) {	
  				switch (modifier) {
  					case Modifier.FINAL:  {
  						setFinal(isChecked);
  						return; 
  					}
  					case Modifier.SYNCHRONIZED:  {
  						setSynchronized(isChecked);
  						return;
  					}
  					default: return;
  				}
  			}
  		};
  			
  		int initialVisibility= getVisibilityModifier();
  		int[] availableVisibilities= new int[]{Modifier.PUBLIC, Modifier.PROTECTED, Modifier.PRIVATE, Modifier.NONE};
  			
  		Composite visibilityComposite= createVisibilityControlAndModifiers(buttonComposite, visibilityChangeListener, availableVisibilities, initialVisibility);
  		return visibilityComposite;				
  	}
  	
  	private List convertToIntegerList(int[] array) {
  		List result= new ArrayList(array.length);
  		for (int i= 0; i < array.length; i++) {
  			result.add(Integer.valueOf(array[i]));
  		}
  		return result;
  	}
  	
  	/* (non-Javadoc)
  	 * @see org.eclipse.ui.dialogs.CheckedTreeSelectionDialog#create()
  	 */
  	public void create() {
  		super.create();
  		
  		// select the first checked element, or if none are checked, the first element
  		CheckboxTreeViewer treeViewer= getTreeViewer();
  		TreeItem[] items= treeViewer.getTree().getItems();
  		if (items.length > 0) {
  			Object revealedElement= items[0];
  
  			for (int i= 0; i < items.length; i++) {
  				if (items[i].getChecked()) {
  					revealedElement= items[i].getData();
  					break;
  				}
  			}
  			treeViewer.setSelection(new StructuredSelection(revealedElement));
  			treeViewer.reveal(revealedElement);
  		}
  	}
  	
  	protected Composite createVisibilityControl(Composite parent, final IVisibilityChangeListener visibilityChangeListener, int[] availableVisibilities, int correctVisibility) {
  		List allowedVisibilities= convertToIntegerList(availableVisibilities);
  		if (allowedVisibilities.size() == 1)
  			return null;
  		
  		Group group= new Group(parent, SWT.NONE);
  		group.setText(ActionMessages.SourceActionDialog_modifier_group); 
  		GridData gd= new GridData(GridData.FILL_BOTH);
  		group.setLayoutData(gd);
  		GridLayout layout= new GridLayout();
  		layout.makeColumnsEqualWidth= true;
  		layout.numColumns= 4; 
  		group.setLayout(layout);
  		
  		String[] labels= new String[] {
  			ActionMessages.SourceActionDialog_modifier_public, 
  			ActionMessages.SourceActionDialog_modifier_protected, 
  			ActionMessages.SourceActionDialog_modifier_default, 
  			ActionMessages.SourceActionDialog_modifier_private, 
  		};
  		Integer[] data= new Integer[] {
  					Integer.valueOf(Modifier.PUBLIC),
  					Integer.valueOf(Modifier.PROTECTED),
  					Integer.valueOf(Modifier.NONE),
  					Integer.valueOf(Modifier.PRIVATE)};
  		Integer initialVisibility= Integer.valueOf(correctVisibility);
  		for (int i= 0; i < labels.length; i++) {
  			Button radio= new Button(group, SWT.RADIO);
  			Integer visibilityCode= data[i];
  			radio.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
  			radio.setText(labels[i]);
  			radio.setData(visibilityCode);
  			radio.setSelection(visibilityCode.equals(initialVisibility));
  			radio.setEnabled(allowedVisibilities.contains(visibilityCode));
  			radio.addSelectionListener(new SelectionAdapter() {
  				public void widgetSelected(SelectionEvent event) {
  					visibilityChangeListener.visibilityChanged(((Integer)event.widget.getData()).intValue());
  				}
  			});
  		}
  		return group;
  	}
  	
  	protected Composite createVisibilityControlAndModifiers(Composite parent, final IVisibilityChangeListener visibilityChangeListener, int[] availableVisibilities, int correctVisibility) {
  		Composite visibilityComposite= createVisibilityControl(parent, visibilityChangeListener, availableVisibilities, correctVisibility);
  
  		Button finalCheckboxButton= new Button(visibilityComposite, SWT.CHECK);
  		finalCheckboxButton.setText(ActionMessages.SourceActionDialog_modifier_final); 
  		GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
  		finalCheckboxButton.setLayoutData(gd);
  		finalCheckboxButton.setData(Integer.valueOf(Modifier.FINAL));
  		finalCheckboxButton.setEnabled(true);
  		finalCheckboxButton.setSelection(isFinal());
  		finalCheckboxButton.addSelectionListener(new SelectionListener() {
  			public void widgetSelected(SelectionEvent event) {
  				visibilityChangeListener.modifierChanged(((Integer)event.widget.getData()).intValue(), ((Button) event.widget).getSelection());
  			}
  
  			public void widgetDefaultSelected(SelectionEvent event) {
  				widgetSelected(event);
  			}
  		});	
  			
  		Button syncCheckboxButton= new Button(visibilityComposite, SWT.CHECK);
  		syncCheckboxButton.setText(ActionMessages.SourceActionDialog_modifier_synchronized); 
  		gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
  		syncCheckboxButton.setLayoutData(gd);
  		syncCheckboxButton.setData(Integer.valueOf(Modifier.SYNCHRONIZED));
  		syncCheckboxButton.setEnabled(true);
  		syncCheckboxButton.setSelection(isSynchronized());
  		syncCheckboxButton.addSelectionListener(new SelectionListener() {
  			public void widgetSelected(SelectionEvent event) {
  				visibilityChangeListener.modifierChanged(((Integer)event.widget.getData()).intValue(), ((Button) event.widget).getSelection());
  			}
  
  			public void widgetDefaultSelected(SelectionEvent event) {
  				widgetSelected(event);
  			}
  		});	
  		return visibilityComposite;			
  	}	
  			
  	protected Composite createInsertPositionCombo(Composite composite) {
  		Composite selectionComposite = new Composite(composite, SWT.NONE);
  		GridLayout layout = new GridLayout();
  		layout.marginHeight= 0;
  		layout.marginWidth= 0;
  		selectionComposite.setLayout(layout);
  					
  		addOrderEntryChoices(selectionComposite);	
  										
  		return selectionComposite;
  	}
  
  	private Composite addOrderEntryChoices(Composite buttonComposite) {
  		Label enterLabel= new Label(buttonComposite, SWT.NONE);
  		enterLabel.setText(ActionMessages.SourceActionDialog_enterAt_label); 
  		if (!fEnableInsertPosition)
  			enterLabel.setEnabled(false);
  		GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
  		enterLabel.setLayoutData(gd);
  
  		final Combo enterCombo= new Combo(buttonComposite, SWT.READ_ONLY);
  		if (!fEnableInsertPosition)
  			enterCombo.setEnabled(false);
  		fillWithPossibleInsertPositions(enterCombo);
  			
  		gd= new GridData(GridData.FILL_BOTH);
  		gd.widthHint= convertWidthInCharsToPixels(fWidth);
  		enterCombo.setLayoutData(gd);
  		enterCombo.addSelectionListener(new SelectionAdapter(){
  			public void widgetSelected(SelectionEvent e) {
  				int index= enterCombo.getSelectionIndex();
  				// Add persistence only if first or last method: http://bugs.eclipse.org/bugs/show_bug.cgi?id=38400				
  				setInsertPosition(index);
  			}
  		});	
  
  		return buttonComposite;			
  	}
  
  	private void fillWithPossibleInsertPositions(Combo combo) {
  		combo.setItems((String[]) fLabels.toArray(new String[fLabels.size()]));
  		combo.select(fCurrentPositionIndex);
  	}
  	
  	public boolean getFinal() {
  		return fFinal;
  	}		
  	
  	public boolean getSynchronized() {
  		return fSynchronized;
  	}	
  	
  	public boolean isFinal() {
  		return fFinal;
  	}
  
  	public boolean isSynchronized() {
  		return fSynchronized;
  	}	
  	
  	public void setElementPositionEnabled(boolean enabled) {
  		fEnableInsertPosition= enabled;
  	}
  	
  	public boolean isElementPositionEnabled() {
  		return fEnableInsertPosition;
  	}
  
  	/*
  	 * Determine where in the file to enter the newly created methods.
  	 */
  	public IJavaScriptElement getElementPosition() {
  		return (IJavaScriptElement) fInsertPositions.get(fCurrentPositionIndex);	
  	}
  	
  	public int getInsertOffset() throws JavaScriptModelException {
  		IJavaScriptElement elementPosition= getElementPosition();
  		if (elementPosition instanceof ISourceReference) {
  			return ((ISourceReference) elementPosition).getSourceRange().getOffset();
  		}
  		return -1;
  	}
  
  	protected IDialogSettings getDialogSettings() {
  		return fSettings;
  	}
  }
  