content: /*******************************************************************************
   * Copyright (c) 2000, 2008 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.refactoring.code;
  
  import java.util.Iterator;
  import java.util.List;
  
  import org.eclipse.jface.dialogs.Dialog;
  import org.eclipse.jface.dialogs.IDialogSettings;
  import org.eclipse.jface.preference.IPreferenceStore;
  import org.eclipse.jface.resource.JFaceResources;
  import org.eclipse.jface.text.Document;
  import org.eclipse.ltk.core.refactoring.RefactoringStatus;
  import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.events.ModifyEvent;
  import org.eclipse.swt.events.ModifyListener;
  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.Label;
  import org.eclipse.swt.widgets.Text;
  import org.eclipse.ui.PlatformUI;
  import org.eclipse.wst.jsdt.core.dom.ASTNode;
  import org.eclipse.wst.jsdt.core.dom.AbstractTypeDeclaration;
  import org.eclipse.wst.jsdt.core.dom.AnonymousClassDeclaration;
  import org.eclipse.wst.jsdt.core.dom.ClassInstanceCreation;
  import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.ParameterInfo;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.code.ExtractMethodRefactoring;
  import org.eclipse.wst.jsdt.internal.corext.util.Messages;
  import org.eclipse.wst.jsdt.internal.ui.IJavaHelpContextIds;
  import org.eclipse.wst.jsdt.internal.ui.JavaPluginImages;
  import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
  import org.eclipse.wst.jsdt.internal.ui.dialogs.TextFieldNavigationHandler;
  import org.eclipse.wst.jsdt.internal.ui.javaeditor.JavaSourceViewer;
  import org.eclipse.wst.jsdt.internal.ui.preferences.JavaPreferencesSettings;
  import org.eclipse.wst.jsdt.internal.ui.refactoring.ChangeParametersControl;
  import org.eclipse.wst.jsdt.internal.ui.refactoring.IParameterListChangeListener;
  import org.eclipse.wst.jsdt.internal.ui.refactoring.RefactoringMessages;
  import org.eclipse.wst.jsdt.internal.ui.util.PixelConverter;
  import org.eclipse.wst.jsdt.internal.ui.util.RowLayouter;
  import org.eclipse.wst.jsdt.ui.PreferenceConstants;
  import org.eclipse.wst.jsdt.ui.text.JavaScriptSourceViewerConfiguration;
  
  public class ExtractMethodInputPage extends UserInputWizardPage {
  
  	public static final String PAGE_NAME= "ExtractMethodInputPage";//$NON-NLS-1$
  
  	private ExtractMethodRefactoring fRefactoring;
  	private Text fTextField;
  	private boolean fFirstTime;
  	private JavaSourceViewer fSignaturePreview;
  	private Document fSignaturePreviewDocument;
  	private IDialogSettings fSettings;
  	
  	private static final String DESCRIPTION = RefactoringMessages.ExtractMethodInputPage_description;
  	private static final String THROW_RUNTIME_EXCEPTIONS= "ThrowRuntimeExceptions"; //$NON-NLS-1$
  	private static final String GENERATE_JAVADOC= "GenerateJavadoc";  //$NON-NLS-1$
  
  	public ExtractMethodInputPage() {
  		super(PAGE_NAME);
  		setImageDescriptor(JavaPluginImages.DESC_WIZBAN_REFACTOR_CU);
  		setDescription(DESCRIPTION);
  		fFirstTime= true;
  		fSignaturePreviewDocument= new Document();
  	}
  
  	public void createControl(Composite parent) {
  		fRefactoring= (ExtractMethodRefactoring)getRefactoring();
  		loadSettings();
  		
  		Composite result= new Composite(parent, SWT.NONE);
  		setControl(result);
  		GridLayout layout= new GridLayout();
  		layout.numColumns= 2;
  		result.setLayout(layout);
  		RowLayouter layouter= new RowLayouter(2);
  		GridData gd= null;
  		
  		initializeDialogUnits(result);
  		
  		Label label= new Label(result, SWT.NONE);
  		label.setText(getLabelText());
  		
  		fTextField= createTextInputField(result, SWT.BORDER);
  		fTextField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  		
  		layouter.perform(label, fTextField, 1);
  		
  		ASTNode[] destinations= fRefactoring.getDestinations();
  		if (destinations.length > 1) {
  			label= new Label(result, SWT.NONE);
  			label.setText(RefactoringMessages.ExtractMethodInputPage_destination_type); 
  			final Combo combo= new Combo(result, SWT.READ_ONLY | SWT.DROP_DOWN);
  			for (int i= 0; i < destinations.length; i++) {
  				ASTNode declaration= destinations[i];
  				combo.add(getLabel(declaration));
  			}
  			combo.select(0);
  			combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  			combo.addSelectionListener(new SelectionListener() {
  				public void widgetSelected(SelectionEvent e) {
  					fRefactoring.setDestination(combo.getSelectionIndex());
  				}
  				public void widgetDefaultSelected(SelectionEvent e) {
  					// nothing
  				}
  			});
  		}
  		
  //		label= new Label(result, SWT.NONE);
  //		label.setText(RefactoringMessages.ExtractMethodInputPage_access_Modifiers); 
  //		
  //		Composite group= new Composite(result, SWT.NONE);
  //		group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  //		layout= new GridLayout();
  //		layout.numColumns= 4; layout.marginWidth= 0;
  //		group.setLayout(layout);
  //		
  //		String[] labels= new String[] {
  //			RefactoringMessages.ExtractMethodInputPage_public,  
  //			RefactoringMessages.ExtractMethodInputPage_protected, 
  //			RefactoringMessages.ExtractMethodInputPage_default, 
  //			RefactoringMessages.ExtractMethodInputPage_private
  //		};
  //		Integer[] data= Integer.valueOf[] {Integer.valueOf(Modifier.PUBLIC), Integer.valueOf(Modifier.PROTECTED), Integer.valueOf(Modifier.NONE), Integer.valueOf(Modifier.PRIVATE)};
  //		Integer visibility= Integer.valueOf(fRefactoring.getVisibility());
  //		for (int i= 0; i < labels.length; i++) {
  //			Button radio= new Button(group, SWT.RADIO);
  //			radio.setText(labels[i]);
  //			radio.setData(data[i]);
  //			if (data[i].equals(visibility))
  //				radio.setSelection(true);
  //			radio.addSelectionListener(new SelectionAdapter() {
  //				public void widgetSelected(SelectionEvent event) {
  //					setVisibility((Integer)event.widget.getData());
  //				}
  //			});
  //		}
  //		layouter.perform(label, group, 1);
  		
  		if (!fRefactoring.getParameterInfos().isEmpty()) {
  			ChangeParametersControl cp= new ChangeParametersControl(result, SWT.NONE, 
  				RefactoringMessages.ExtractMethodInputPage_parameters, 
  				new IParameterListChangeListener() {
  				public void parameterChanged(ParameterInfo parameter) {
  					parameterModified();
  				}
  				public void parameterListChanged() {
  					parameterModified();
  				}
  				public void parameterAdded(ParameterInfo parameter) {
  					updatePreview(getText());
  				}
  			}, ChangeParametersControl.Mode.EXTRACT_METHOD);
  			gd= new GridData(GridData.FILL_BOTH);
  			gd.horizontalSpan= 2;
  			cp.setLayoutData(gd);
  			cp.setInput(fRefactoring.getParameterInfos());
  		}
  		
  //		Button checkBox= new Button(result, SWT.CHECK);
  //		checkBox.setText(RefactoringMessages.ExtractMethodInputPage_throwRuntimeExceptions); 
  //		checkBox.setSelection(fSettings.getBoolean(THROW_RUNTIME_EXCEPTIONS));
  //		checkBox.addSelectionListener(new SelectionAdapter() {
  //			public void widgetSelected(SelectionEvent e) {
  //				setRethrowRuntimeException(((Button)e.widget).getSelection());
  //			}
  //		});
  //		layouter.perform(checkBox);
  //		
  		Button checkBox= new Button(result, SWT.CHECK);
  		checkBox.setText(RefactoringMessages.ExtractMethodInputPage_generateJavadocComment); 
  		boolean generate= computeGenerateJavadoc();
  		setGenerateJavadoc(generate);
  		checkBox.setSelection(generate);
  		checkBox.addSelectionListener(new SelectionAdapter() {
  			public void widgetSelected(SelectionEvent e) {
  				setGenerateJavadoc(((Button)e.widget).getSelection());
  			}
  		});
  		layouter.perform(checkBox);
  		
  		int duplicates= fRefactoring.getNumberOfDuplicates();
  		checkBox= new Button(result, SWT.CHECK);
  		if (duplicates == 0) {
  			checkBox.setText(RefactoringMessages.ExtractMethodInputPage_duplicates_none); 
  		} else  if (duplicates == 1) {
  			checkBox.setText(RefactoringMessages.ExtractMethodInputPage_duplicates_single); 
  		} else {
  			checkBox.setText(Messages.format(
  				RefactoringMessages.ExtractMethodInputPage_duplicates_multi, 
  				Integer.valueOf(duplicates))); 
  		}
  		checkBox.setSelection(fRefactoring.getReplaceDuplicates());
  		checkBox.setEnabled(duplicates > 0);
  		checkBox.addSelectionListener(new SelectionAdapter() {
  			public void widgetSelected(SelectionEvent e) {
  				fRefactoring.setReplaceDuplicates(((Button)e.widget).getSelection());
  			}
  		});
  		layouter.perform(checkBox);
  		
  		label= new Label(result, SWT.SEPARATOR | SWT.HORIZONTAL);
  		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  		layouter.perform(label);
  		
  		createSignaturePreview(result, layouter);
  		
  		Dialog.applyDialogFont(result);
  		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaHelpContextIds.EXTRACT_METHOD_WIZARD_PAGE);		
  	}
  	
  	private String getLabel(ASTNode node) {
  		if (node instanceof AbstractTypeDeclaration) {
  			return ((AbstractTypeDeclaration)node).getName().getIdentifier();
  		} else if (node instanceof AnonymousClassDeclaration) {
  			if (node.getLocationInParent() == ClassInstanceCreation.ANONYMOUS_CLASS_DECLARATION_PROPERTY) {
  				ClassInstanceCreation creation= (ClassInstanceCreation)node.getParent();
  				return Messages.format(
  					RefactoringMessages.ExtractMethodInputPage_anonymous_type_label,  
  					ASTNodes.asString(creation.getType()));
  			}
  		}
  		return "UNKNOWN"; //$NON-NLS-1$
  	}
  
  	private Text createTextInputField(Composite parent, int style) {
  		Text result= new Text(parent, style);
  		result.addModifyListener(new ModifyListener() {
  			public void modifyText(ModifyEvent e) {
  				textModified(getText());
  			}
  		});
  		TextFieldNavigationHandler.install(result);
  		return result;
  	}
  	
  	private String getText() {
  		if (fTextField == null)
  			return null;
  		return fTextField.getText();	
  	}
  	
  	private String getLabelText(){
  		return RefactoringMessages.ExtractMethodInputPage_label_text; 
  	}
  	
  //	private void setVisibility(Integer visibility) {
  //		fRefactoring.setVisibility(visibility.intValue());
  //		updatePreview(getText());
  //	}
  //	
  //	private void setRethrowRuntimeException(boolean value) {
  //		fSettings.put(THROW_RUNTIME_EXCEPTIONS, value);
  //		fRefactoring.setThrowRuntimeExceptions(value);
  //		updatePreview(getText());
  //	}
  	
  	private boolean computeGenerateJavadoc() {
  		boolean result= fRefactoring.getGenerateJavadoc();
  		if (result)
  			return result;
  		return fSettings.getBoolean(GENERATE_JAVADOC);
  	}
  	
  	private void setGenerateJavadoc(boolean value) {
  		fSettings.put(GENERATE_JAVADOC, value);
  		fRefactoring.setGenerateJavadoc(value);
  	}
  	
  	private void createSignaturePreview(Composite composite, RowLayouter layouter) {
  		Label previewLabel= new Label(composite, SWT.NONE);
  		previewLabel.setText(RefactoringMessages.ExtractMethodInputPage_signature_preview); 
  		layouter.perform(previewLabel);
  		
  		IPreferenceStore store= JavaScriptPlugin.getDefault().getCombinedPreferenceStore();
  		fSignaturePreview= new JavaSourceViewer(composite, null, null, false, SWT.READ_ONLY | SWT.V_SCROLL | SWT.WRAP /*| SWT.BORDER*/, store);
  		fSignaturePreview.configure(new JavaScriptSourceViewerConfiguration(JavaScriptPlugin.getDefault().getJavaTextTools().getColorManager(), store, null, null));
  		fSignaturePreview.getTextWidget().setFont(JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT));
  		fSignaturePreview.getTextWidget().setBackground(composite.getBackground());
  		fSignaturePreview.setDocument(fSignaturePreviewDocument);
  		fSignaturePreview.setEditable(false);
  		
  		//Layouting problems with wrapped text: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=9866
  		Control signaturePreviewControl= fSignaturePreview.getControl();
  		PixelConverter pixelConverter= new PixelConverter(signaturePreviewControl);
  		GridData gdata= new GridData(GridData.FILL_BOTH);
  		gdata.widthHint= pixelConverter.convertWidthInCharsToPixels(50);
  		gdata.heightHint= pixelConverter.convertHeightInCharsToPixels(2);
  		signaturePreviewControl.setLayoutData(gdata);
  		layouter.perform(signaturePreviewControl);
  	}
  	
  	private void updatePreview(String text) {
  		if (fSignaturePreview == null)
  			return;
  			
  		if (text.length() == 0)
  			text= "someMethodName";			 //$NON-NLS-1$
  		
  		int top= fSignaturePreview.getTextWidget().getTopPixel();
  		String signature;
  		try {
  			signature= fRefactoring.getSignature(text);
  		} catch (IllegalArgumentException e) { 
  			signature= ""; //$NON-NLS-1$ 
  		}
  		fSignaturePreviewDocument.set(signature);
  		fSignaturePreview.getTextWidget().setTopPixel(top);
  	}
  	
  	private void loadSettings() {
  		fSettings= getDialogSettings().getSection(ExtractMethodWizard.DIALOG_SETTING_SECTION);
  		if (fSettings == null) {
  			fSettings= getDialogSettings().addNewSection(ExtractMethodWizard.DIALOG_SETTING_SECTION);
  			fSettings.put(THROW_RUNTIME_EXCEPTIONS, false);
  			fSettings.put(GENERATE_JAVADOC, JavaPreferencesSettings.getCodeGenerationSettings(fRefactoring.getCompilationUnit().getJavaScriptProject()).createComments);
  		}
  		fRefactoring.setThrowRuntimeExceptions(fSettings.getBoolean(THROW_RUNTIME_EXCEPTIONS));
  	}
  	
  	//---- Input validation ------------------------------------------------------
  	
  	public void setVisible(boolean visible) {
  		if (visible) {
  			if (fFirstTime) {
  				fFirstTime= false;
  				setPageComplete(false);
  				updatePreview(getText());
  				fTextField.setFocus();
  			} else {
  				setPageComplete(validatePage(true));
  			}
  		}
  		super.setVisible(visible);
  	}
  	
  	private void textModified(String text) {
  		fRefactoring.setMethodName(text);
  		RefactoringStatus status= validatePage(true);
  		if (!status.hasFatalError()) {
  			updatePreview(text);
  		} else {
  			fSignaturePreviewDocument.set(""); //$NON-NLS-1$
  		}
  		setPageComplete(status);
  	}
  	
  	private void parameterModified() {
  		updatePreview(getText());
  		setPageComplete(validatePage(false));
  	}
  	
  	private RefactoringStatus validatePage(boolean text) {
  		RefactoringStatus result= new RefactoringStatus();
  		if (text) {
  			result.merge(validateMethodName());
  			result.merge(validateParameters());
  		} else {
  			result.merge(validateParameters());
  			result.merge(validateMethodName());
  		}
  		return result;
  	}
  	
  	private RefactoringStatus validateMethodName() {
  		RefactoringStatus result= new RefactoringStatus();
  		String text= getText();
  		if ("".equals(text)) { //$NON-NLS-1$
  			result.addFatalError(RefactoringMessages.ExtractMethodInputPage_validation_emptyMethodName); 
  			return result;
  		}
  		result.merge(fRefactoring.checkMethodName());
  		return result;
  	}
  	
  	private RefactoringStatus validateParameters() {
  		RefactoringStatus result= new RefactoringStatus();
  		List parameters= fRefactoring.getParameterInfos();
  		for (Iterator iter= parameters.iterator(); iter.hasNext();) {
  			ParameterInfo info= (ParameterInfo) iter.next();
  			if ("".equals(info.getNewName())) { //$NON-NLS-1$
  				result.addFatalError(RefactoringMessages.ExtractMethodInputPage_validation_emptyParameterName); 
  				return result;
  			}
  		}
  		result.merge(fRefactoring.checkParameterNames());
  		result.merge(fRefactoring.checkVarargOrder());
  		return result;
  	}
  }
  