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;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.eclipse.core.runtime.Assert;
  import org.eclipse.core.runtime.IStatus;
  import org.eclipse.core.runtime.Status;
  import org.eclipse.jface.dialogs.Dialog;
  import org.eclipse.jface.window.Window;
  import org.eclipse.jface.wizard.IWizardPage;
  import org.eclipse.ltk.core.refactoring.participants.MoveRefactoring;
  import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
  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.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.Label;
  import org.eclipse.ui.PlatformUI;
  import org.eclipse.ui.dialogs.ISelectionStatusValidator;
  import org.eclipse.wst.jsdt.core.IJavaScriptElement;
  import org.eclipse.wst.jsdt.core.IMember;
  import org.eclipse.wst.jsdt.core.IPackageFragment;
  import org.eclipse.wst.jsdt.core.IType;
  import org.eclipse.wst.jsdt.core.JavaScriptConventions;
  import org.eclipse.wst.jsdt.core.JavaScriptModelException;
  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.refactoring.structure.MoveStaticMembersProcessor;
  import org.eclipse.wst.jsdt.internal.corext.util.JavaModelUtil;
  import org.eclipse.wst.jsdt.internal.corext.util.Messages;
  import org.eclipse.wst.jsdt.internal.ui.IJavaHelpContextIds;
  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.TextFieldNavigationHandler;
  import org.eclipse.wst.jsdt.internal.ui.refactoring.contentassist.ControlContentAssistHelper;
  import org.eclipse.wst.jsdt.internal.ui.refactoring.contentassist.JavaTypeCompletionProcessor;
  import org.eclipse.wst.jsdt.internal.ui.util.ExceptionHandler;
  import org.eclipse.wst.jsdt.internal.ui.util.SWTUtil;
  import org.eclipse.wst.jsdt.ui.JavaScriptElementLabels;
  
  public class MoveMembersWizard extends RefactoringWizard {
  
  	public MoveMembersWizard(MoveRefactoring ref) {
  		super(ref, DIALOG_BASED_USER_INTERFACE);
  		setDefaultPageTitle(RefactoringMessages.MoveMembersWizard_page_title); 
  	}
  
  	/* non java-doc
  	 * @see RefactoringWizard#addUserInputPages
  	 */ 
  	protected void addUserInputPages(){
  		addPage(new MoveMembersInputPage());
  	}
  	
  	private static class MoveMembersInputPage extends UserInputWizardPage {
  
  		public static final String PAGE_NAME= "MoveMembersInputPage"; //$NON-NLS-1$
  		private static final long LABEL_FLAGS= JavaScriptElementLabels.ALL_DEFAULT;
  
  		private Combo fDestinationField;
  		private Button fLeaveDelegateCheckBox;
  		private Button fDeprecateDelegateCheckBox;
  		private static final int MRU_COUNT= 10;
  		private static List fgMruDestinations= new ArrayList(MRU_COUNT);
  
  		public MoveMembersInputPage() {
  			super(PAGE_NAME);
  		}
  	
  		public void setVisible(boolean visible){
  			if (visible){
  				String message= Messages.format(RefactoringMessages.MoveMembersInputPage_descriptionKey, 
  					new String[]{Integer.valueOf(getMoveProcessor().getMembersToMove().length).toString(),
  								 JavaModelUtil.getFullyQualifiedName(getMoveProcessor().getDeclaringType())});
  				setDescription(message);
  			}	
  			super.setVisible(visible);	
  		}
  	
  		public void createControl(Composite parent) {		
  			Composite composite= new Composite(parent, SWT.NONE);
  			GridLayout layout= new GridLayout();
  			layout.numColumns= 2;
  			composite.setLayout(layout);
  		
  			addLabel(composite);
  			addDestinationControls(composite);
  			fLeaveDelegateCheckBox= DelegateUIHelper.generateLeaveDelegateCheckbox(composite, getRefactoring(), getMoveProcessor().getMembersToMove().length > 1);
  			GridData data= new GridData();
  			data.horizontalSpan= 2;
  			if (fLeaveDelegateCheckBox != null) {
  				fLeaveDelegateCheckBox.setLayoutData(data);
  				fDeprecateDelegateCheckBox= new Button(composite, SWT.CHECK);
  				data= new GridData();
  				data.horizontalAlignment= GridData.FILL;
  				data.horizontalIndent= (layout.marginWidth + fDeprecateDelegateCheckBox.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
  				data.horizontalSpan= 2;
  				fDeprecateDelegateCheckBox.setLayoutData(data);
  				fDeprecateDelegateCheckBox.setText(DelegateUIHelper.getDeprecateDelegateCheckBoxTitle());
  				fDeprecateDelegateCheckBox.setSelection(DelegateUIHelper.loadDeprecateDelegateSetting(getMoveProcessor()));
  				getMoveProcessor().setDeprecateDelegates(fDeprecateDelegateCheckBox.getSelection());
  				fDeprecateDelegateCheckBox.addSelectionListener(new SelectionAdapter() {
  					public void widgetSelected(SelectionEvent e) {
  						getMoveProcessor().setDeprecateDelegates(fDeprecateDelegateCheckBox.getSelection());
  					}
  				});
  				fDeprecateDelegateCheckBox.setEnabled(fLeaveDelegateCheckBox.getSelection());
  				fLeaveDelegateCheckBox.addSelectionListener(new SelectionAdapter() {
  					public void widgetSelected(SelectionEvent e) {
  						fDeprecateDelegateCheckBox.setEnabled(fLeaveDelegateCheckBox.getSelection());
  					}
  				});
  			}
  			setControl(composite);
  			Dialog.applyDialogFont(composite);
  			PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJavaHelpContextIds.MOVE_MEMBERS_WIZARD_PAGE);
  		}
  
  		public void dispose() {
  			DelegateUIHelper.saveLeaveDelegateSetting(fLeaveDelegateCheckBox);
  			DelegateUIHelper.saveDeprecateDelegateSetting(fDeprecateDelegateCheckBox);
  			super.dispose();
  		}
  		
  		private void addLabel(Composite parent) {
  			Label label= new Label(parent, SWT.NONE);
  			IMember[] members= getMoveProcessor().getMembersToMove();
  			if (members.length == 1) {
  				label.setText(Messages.format(
  						RefactoringMessages.MoveMembersInputPage_destination_single, 
  						JavaScriptElementLabels.getElementLabel(members[0], LABEL_FLAGS)));
  			} else {
  				label.setText(Messages.format(
  						RefactoringMessages.MoveMembersInputPage_destination_multi, 
  						String.valueOf(members.length)));
  			}
  			GridData gd= new GridData();
  			gd.horizontalSpan= 2;
  			label.setLayoutData(gd);
  		}
  
  		private void addDestinationControls(Composite composite) {
  			fDestinationField= new Combo(composite, SWT.SINGLE | SWT.BORDER);
  			fDestinationField.setFocus();
  			fDestinationField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
  			fDestinationField.setItems((String[]) fgMruDestinations.toArray(new String[fgMruDestinations.size()]));
  			fDestinationField.addModifyListener(new ModifyListener(){
  				public void modifyText(ModifyEvent e) {
  					handleDestinationChanged();
  				}
  				private void handleDestinationChanged() {
  					IStatus status= JavaScriptConventions.validateJavaScriptTypeName(fDestinationField.getText());
  					if (status.getSeverity() == IStatus.ERROR){
  						error(status.getMessage());
  					} else {
  						try {
  							final IType declaring= getMoveProcessor().getDeclaringType();
  							IType resolvedType= declaring.getJavaScriptProject().findType(fDestinationField.getText());
  							if (resolvedType == null)
  								resolvedType= declaring.getJavaScriptProject().findType(declaring.getPackageFragment().getElementName(), fDestinationField.getText());
  							IStatus validationStatus= validateDestinationType(resolvedType, fDestinationField.getText());
  							if (validationStatus.isOK()){
  								setErrorMessage(null);
  								setPageComplete(true);
  							} else {
  								error(validationStatus.getMessage());
  							}
  						} catch(JavaScriptModelException ex) {
  							JavaScriptPlugin.log(ex); //no ui here
  							error(RefactoringMessages.MoveMembersInputPage_invalid_name); 
  						}
  					}
  				}
  				private void error(String message){
  					setErrorMessage(message);
  					setPageComplete(false);
  				}
  			});
  			if (fgMruDestinations.size() > 0) {
  				fDestinationField.select(0);
  			} else {
  				setPageComplete(false);
  			}
  			JavaTypeCompletionProcessor processor= new JavaTypeCompletionProcessor(false, false, true);
  			IPackageFragment context= (IPackageFragment) getMoveProcessor().getDeclaringType().getAncestor(IJavaScriptElement.PACKAGE_FRAGMENT);
  			processor.setPackageFragment(context);
  			ControlContentAssistHelper.createComboContentAssistant(fDestinationField, processor);
  			TextFieldNavigationHandler.install(fDestinationField);
  			
  			Button button= new Button(composite, SWT.PUSH);
  			button.setText(RefactoringMessages.MoveMembersInputPage_browse); 
  			button.setLayoutData(new GridData());
  			SWTUtil.setButtonDimensionHint(button);
  			button.addSelectionListener(new SelectionAdapter(){
  				public void widgetSelected(SelectionEvent e) {
  					openTypeSelectionDialog();
  				}
  			});
  		}
  			
  		protected boolean performFinish() {
  			initializeRefactoring();
  			return super.performFinish();
  		}
  	
  		public IWizardPage getNextPage() {
  			initializeRefactoring();
  			return super.getNextPage();
  		}
  
  		private void initializeRefactoring() {
  			try {
  				String destination= fDestinationField.getText();
  				if (!fgMruDestinations.remove(destination) && fgMruDestinations.size() >= MRU_COUNT)
  					fgMruDestinations.remove(fgMruDestinations.size() - 1);
  				fgMruDestinations.add(0, destination);
  				
  				getMoveProcessor().setDestinationTypeFullyQualifiedName(destination);
  			} catch(JavaScriptModelException e) {
  				ExceptionHandler.handle(e, getShell(), RefactoringMessages.MoveMembersInputPage_move_Member, RefactoringMessages.MoveMembersInputPage_exception); 
  			}
  		}
  	
  		private IJavaScriptSearchScope createWorkspaceSourceScope(){
  			IJavaScriptElement[] project= new IJavaScriptElement[] { getMoveProcessor().getDeclaringType().getJavaScriptProject() };
  			return SearchEngine.createJavaSearchScope(project, IJavaScriptSearchScope.REFERENCED_PROJECTS | IJavaScriptSearchScope.SOURCES);
  		}
  	
  		private void openTypeSelectionDialog(){
  			int elementKinds= IJavaScriptSearchConstants.TYPE;
  			final IJavaScriptSearchScope scope= createWorkspaceSourceScope();
  			FilteredTypesSelectionDialog dialog= new FilteredTypesSelectionDialog(getShell(), false,
  				getWizard().getContainer(), scope, elementKinds);
  			dialog.setTitle(RefactoringMessages.MoveMembersInputPage_choose_Type); 
  			dialog.setMessage(RefactoringMessages.MoveMembersInputPage_dialogMessage); 
  			dialog.setValidator(new ISelectionStatusValidator(){
  				public IStatus validate(Object[] selection) {
  					Assert.isTrue(selection.length <= 1);
  					if (selection.length == 0)
  						return new Status(IStatus.ERROR, JavaScriptPlugin.getPluginId(), IStatus.OK, RefactoringMessages.MoveMembersInputPage_Invalid_selection, null); 
  					Object element= selection[0];
  					if (! (element instanceof IType))
  						return new Status(IStatus.ERROR, JavaScriptPlugin.getPluginId(), IStatus.OK, RefactoringMessages.MoveMembersInputPage_Invalid_selection, null); 
  					IType type= (IType)element;
  					return validateDestinationType(type, type.getElementName());
  				}
  			});
  			dialog.setInitialPattern(createInitialFilter());
  			if (dialog.open() == Window.CANCEL)
  				return;
  			IType firstResult= (IType)dialog.getFirstResult();		
  			fDestinationField.setText(JavaModelUtil.getFullyQualifiedName(firstResult));	
  		}
  
  		private String createInitialFilter() {
  			if (! fDestinationField.getText().trim().equals("")) //$NON-NLS-1$
  				return fDestinationField.getText();
  			else
  				return getMoveProcessor().getDeclaringType().getElementName();
  		}
  	
  		private static IStatus validateDestinationType(IType type, String typeName){
  			if (type == null || ! type.exists())
  				return new Status(IStatus.ERROR, JavaScriptPlugin.getPluginId(), IStatus.OK, Messages.format(RefactoringMessages.MoveMembersInputPage_not_found, typeName), null); 
  			if (type.isBinary())
  				return new Status(IStatus.ERROR, JavaScriptPlugin.getPluginId(), IStatus.OK, RefactoringMessages.MoveMembersInputPage_no_binary, null); 
  			return new Status(IStatus.OK, JavaScriptPlugin.getPluginId(), IStatus.OK, "", null); //$NON-NLS-1$
  		}
  	
  		private MoveStaticMembersProcessor getMoveProcessor() {
  			return (MoveStaticMembersProcessor)getRefactoring().getAdapter(MoveStaticMembersProcessor.class);
  		}
  	}
  }
  