/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.wizards.datatransfer;


import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
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.DirectoryDialog;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.dialogs.FileSystemElement;
import org.eclipse.ui.dialogs.WizardResourceImportPage;
import org.eclipse.ui.help.WorkbenchHelp;
import org.eclipse.ui.internal.ide.dialogs.IElementFilter;
import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
import org.eclipse.ui.model.WorkbenchContentProvider;

/**
 *	Page 1 of the base resource import-from-file-system Wizard
 */
/*package*/
class WizardFileSystemResourceImportPage1
	extends WizardResourceImportPage
	implements Listener {
	// widgets
	protected Combo sourceNameField;
	protected Button overwriteExistingResourcesCheckbox;
	protected Button createContainerStructureButton;
	protected Button createOnlySelectedButton;
	protected Button sourceBrowseButton;
	protected Button selectTypesButton;
	protected Button selectAllButton;
	protected Button deselectAllButton;
	//A boolean to indicate if the user has typed anything
	private boolean entryChanged = false;

	// dialog store id constants
	private final static String STORE_SOURCE_NAMES_ID =
		"WizardFileSystemResourceImportPage1.STORE_SOURCE_NAMES_ID";//$NON-NLS-1$
	private final static String STORE_OVERWRITE_EXISTING_RESOURCES_ID =
		"WizardFileSystemResourceImportPage1.STORE_OVERWRITE_EXISTING_RESOURCES_ID";//$NON-NLS-1$
	private final static String STORE_CREATE_CONTAINER_STRUCTURE_ID =
		"WizardFileSystemResourceImportPage1.STORE_CREATE_CONTAINER_STRUCTURE_ID";//$NON-NLS-1$

	private static final String SELECT_TYPES_TITLE = DataTransferMessages.getString("DataTransfer.selectTypes"); //$NON-NLS-1$
	private static final String SELECT_ALL_TITLE = DataTransferMessages.getString("DataTransfer.selectAll"); //$NON-NLS-1$
	private static final String DESELECT_ALL_TITLE = DataTransferMessages.getString("DataTransfer.deselectAll"); //$NON-NLS-1$
	private static final String SELECT_SOURCE_TITLE =
			DataTransferMessages.getString("FileImport.selectSourceTitle"); //$NON-NLS-1$
	private static final String SELECT_SOURCE_MESSAGE =
		DataTransferMessages.getString("FileImport.selectSource"); //$NON-NLS-1$
	protected static final String SOURCE_EMPTY_MESSAGE = DataTransferMessages.getString("FileImport.sourceEmpty"); //$NON-NLS-1$
/**
 *	Creates an instance of this class
 */
protected WizardFileSystemResourceImportPage1(String name, IWorkbench aWorkbench, IStructuredSelection selection) {
	super(name,selection);
}
/**
 *	Creates an instance of this class
 *
 * @param aWorkbench IWorkbench
 * @param selection IStructuredSelection
 */
public WizardFileSystemResourceImportPage1(IWorkbench aWorkbench, IStructuredSelection selection) {
	this("fileSystemImportPage1", aWorkbench, selection);//$NON-NLS-1$
	setTitle(DataTransferMessages.getString("DataTransfer.fileSystemTitle")); //$NON-NLS-1$
	setDescription(DataTransferMessages.getString("FileImport.importFileSystem")); //$NON-NLS-1$
}
/**
 * Creates a new button with the given id.
 * <p>
 * The <code>Dialog</code> implementation of this framework method
 * creates a standard push button, registers for selection events
 * including button presses and registers
 * default buttons with its shell.
 * The button id is stored as the buttons client data.
 * Note that the parent's layout is assumed to be a GridLayout and 
 * the number of columns in this layout is incremented.
 * Subclasses may override.
 * </p>
 *
 * @param parent the parent composite
 * @param id the id of the button (see
 *  <code>IDialogConstants.*_ID</code> constants 
 *  for standard dialog button ids)
 * @param label the label from the button
 * @param defaultButton <code>true</code> if the button is to be the
 *   default button, and <code>false</code> otherwise
 */
protected Button createButton(Composite parent, int id, String label, boolean defaultButton) {
	// increment the number of columns in the button bar
	((GridLayout)parent.getLayout()).numColumns++;

	Button button = new Button(parent, SWT.PUSH );
	button.setFont(parent.getFont());

	GridData buttonData = new GridData(GridData.FILL_HORIZONTAL);
	button.setLayoutData(buttonData);

	button.setData(new Integer(id));
	button.setText(label);
	
	if (defaultButton) {
		Shell shell = parent.getShell();
		if (shell != null) {
			shell.setDefaultButton(button);
		}
		button.setFocus();
	}
	return button;
}
/**
 * Creates the buttons for selecting specific types or selecting all or none of the
 * elements.
 *
 * @param parent the parent control
 */
protected final void createButtonsGroup(Composite parent) {
	// top level group
	Composite buttonComposite = new Composite(parent, SWT.NONE);
	GridLayout layout = new GridLayout();
	layout.numColumns = 3;
	layout.makeColumnsEqualWidth = true;
	buttonComposite.setLayout(layout);
	buttonComposite.setFont(parent.getFont());
	GridData buttonData = 
		new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL);
	buttonData.horizontalSpan = 2;
	buttonComposite.setLayoutData(buttonData);

	// types edit button
	selectTypesButton =
		createButton(
			buttonComposite,
			IDialogConstants.SELECT_TYPES_ID,
			SELECT_TYPES_TITLE,
			false);

	
	SelectionListener listener = new SelectionAdapter() {
		public void widgetSelected(SelectionEvent e) {
			handleTypesEditButtonPressed();
		}
	};
	selectTypesButton.addSelectionListener(listener);
	setButtonLayoutData(selectTypesButton);

	selectAllButton =
		createButton(
			buttonComposite,
			IDialogConstants.SELECT_ALL_ID,
			SELECT_ALL_TITLE,
			false);

	listener = new SelectionAdapter() {
		public void widgetSelected(SelectionEvent e) {
			setAllSelections(true);
		}
	};
	selectAllButton.addSelectionListener(listener);
	setButtonLayoutData(selectAllButton);

	deselectAllButton =
		createButton(
			buttonComposite,
			IDialogConstants.DESELECT_ALL_ID,
			DESELECT_ALL_TITLE,
			false);

	listener = new SelectionAdapter() {
		public void widgetSelected(SelectionEvent e) {
			setAllSelections(false);
		}
	};
	deselectAllButton.addSelectionListener(listener);
	setButtonLayoutData(deselectAllButton);

}
/** (non-Javadoc)
 * Method declared on IDialogPage.
 */
public void createControl(Composite parent) {
	super.createControl(parent);
	validateSourceGroup();
	WorkbenchHelp.setHelp(getControl(), IDataTransferHelpContextIds.FILE_SYSTEM_IMPORT_WIZARD_PAGE);
}
/**
 *	Create the import options specification widgets.
 */
protected void createOptionsGroupButtons(Group optionsGroup) {

		// overwrite... checkbox
		overwriteExistingResourcesCheckbox = new Button(optionsGroup, SWT.CHECK);
		overwriteExistingResourcesCheckbox.setFont(optionsGroup.getFont());
		overwriteExistingResourcesCheckbox.setText(
			DataTransferMessages.getString("FileImport.overwriteExisting")); //$NON-NLS-1$

		// create containers radio
		createContainerStructureButton = new Button(optionsGroup, SWT.RADIO);
		createContainerStructureButton.setFont(optionsGroup.getFont());
		createContainerStructureButton.setText(
			DataTransferMessages.getString("FileImport.createComplete")); //$NON-NLS-1$
		createContainerStructureButton.setSelection(false);
		
		// create selection only radio
		createOnlySelectedButton = new Button(optionsGroup, SWT.RADIO);
		createOnlySelectedButton.setFont(optionsGroup.getFont());
		createOnlySelectedButton.setText(
			DataTransferMessages.getString("FileImport.createSelectedFolders")); //$NON-NLS-1$
		createOnlySelectedButton.setSelection(true);
		

	}
/**
 *	Create the group for creating the root directory
 */
protected void createRootDirectoryGroup(Composite parent) {
	Composite sourceContainerGroup = new Composite(parent, SWT.NONE);
	GridLayout layout = new GridLayout();
	layout.numColumns = 3;
	sourceContainerGroup.setLayout(layout);
	sourceContainerGroup.setFont(parent.getFont());
	sourceContainerGroup.setLayoutData(
		new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));

	Label groupLabel = new Label(sourceContainerGroup, SWT.NONE);
	groupLabel.setText(getSourceLabel());
	groupLabel.setFont(parent.getFont());

	// source name entry field
	sourceNameField = new Combo(sourceContainerGroup, SWT.BORDER);
	GridData data =
		new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
	data.widthHint = SIZING_TEXT_FIELD_WIDTH;
	sourceNameField.setLayoutData(data);
	sourceNameField.setFont(parent.getFont());

	sourceNameField.addSelectionListener(new SelectionAdapter() {
		public void widgetSelected(SelectionEvent e) {
			updateFromSourceField();
		}
	});
	
	
	sourceNameField.addKeyListener(new KeyListener(){
		/*
		 * @see KeyListener.keyPressed
		 */
		public void keyPressed(KeyEvent e){
			//If there has been a key pressed then mark as dirty
			entryChanged = true;
		}

		/*
		 * @see KeyListener.keyReleased
		 */
		public void keyReleased(KeyEvent e){}
	});
	
	sourceNameField.addFocusListener(new FocusListener(){
		/*
		 * @see FocusListener.focusGained(FocusEvent)
		 */
		public void focusGained(FocusEvent e){
			//Do nothing when getting focus
		}
		
		/*
		 * @see FocusListener.focusLost(FocusEvent)
		 */
		public void focusLost(FocusEvent e){
			//Clear the flag to prevent constant update
			if(entryChanged){
				entryChanged = false;
				updateFromSourceField();
			}
			
		}	
	});

	// source browse button
	sourceBrowseButton = new Button(sourceContainerGroup, SWT.PUSH);
	sourceBrowseButton.setText(DataTransferMessages.getString("DataTransfer.browse")); //$NON-NLS-1$
	sourceBrowseButton.addListener(SWT.Selection, this);
	sourceBrowseButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
	sourceBrowseButton.setFont(parent.getFont());
	setButtonLayoutData(sourceBrowseButton);
}

/**
 * Update the receiver from the source name field.
 */

private void updateFromSourceField(){
	
	setSourceName(sourceNameField.getText());
	//Update enablements when this is selected
	updateWidgetEnablements();
}		
	
/**
 * Creates and returns a <code>FileSystemElement</code> if the specified
 * file system object merits one.  The criteria for this are:
 * Also create the children.
 */
protected MinimizedFileSystemElement createRootElement(
	Object fileSystemObject,
	IImportStructureProvider provider) {
	boolean isContainer = provider.isFolder(fileSystemObject);
	String elementLabel = provider.getLabel(fileSystemObject);

	// Use an empty label so that display of the element's full name
	// doesn't include a confusing label
	MinimizedFileSystemElement dummyParent =
		new MinimizedFileSystemElement("", null, true);//$NON-NLS-1$
	dummyParent.setPopulated();
	MinimizedFileSystemElement result =
		new MinimizedFileSystemElement(elementLabel, dummyParent, isContainer);
	result.setFileSystemObject(fileSystemObject);

	//Get the files for the element so as to build the first level
	result.getFiles(provider);

	return dummyParent;
}
/**
 *	Create the import source specification widgets
 */
protected void createSourceGroup(Composite parent) {

	createRootDirectoryGroup(parent);
	createFileSelectionGroup(parent);
	createButtonsGroup(parent);
}
/**
 * Enable or disable the button group.
 */
protected void enableButtonGroup(boolean enable) {
	selectTypesButton.setEnabled(enable);
	selectAllButton.setEnabled(enable);
	deselectAllButton.setEnabled(enable);
}
/**
 *	Answer a boolean indicating whether the specified source currently exists
 *	and is valid
 */
protected boolean ensureSourceIsValid() {
	if (new File(getSourceDirectoryName()).isDirectory())
		return true;

	displayErrorDialog(DataTransferMessages.getString("FileImport.invalidSource")); //$NON-NLS-1$
	sourceNameField.setFocus();
	return false;
}
/**
 *	Execute the passed import operation.  Answer a boolean indicating success.
 */
protected boolean executeImportOperation(ImportOperation op) {
	initializeOperation(op);
	 
	try {
		getContainer().run(true, true, op);
	} catch (InterruptedException e) {
		return false;
	} catch (InvocationTargetException e) {
		displayErrorDialog(e.getTargetException());
		return false;
	}

	IStatus status = op.getStatus();
	if (!status.isOK()) {
		ErrorDialog.openError(getContainer().getShell(),
			DataTransferMessages.getString("FileImport.importProblems"), //$NON-NLS-1$
			null,		// no special message
			status);
		return false;
	}

	return true;
}
/**
 *	The Finish button was pressed.  Try to do the required work now and answer
 *	a boolean indicating success.  If false is returned then the wizard will
 *	not close.
 *
 * @return boolean
 */
public boolean finish() {
	if (!ensureSourceIsValid())
		return false;

	saveWidgetValues();

	Iterator resourcesEnum = getSelectedResources().iterator();
	List fileSystemObjects = new ArrayList();
	while (resourcesEnum.hasNext()) {
		fileSystemObjects.add(
			((FileSystemElement) resourcesEnum.next()).getFileSystemObject());
	}

	if (fileSystemObjects.size() > 0)
		return importResources(fileSystemObjects);

	MessageDialog
		.openInformation(
			getContainer().getShell(),
			DataTransferMessages.getString("DataTransfer.information"), //$NON-NLS-1$
			DataTransferMessages.getString("FileImport.noneSelected")); //$NON-NLS-1$

	return false;
}
/**
 * Returns a content provider for <code>FileSystemElement</code>s that returns 
 * only files as children.
 */
protected ITreeContentProvider getFileProvider() {
	return new WorkbenchContentProvider() {
		public Object[] getChildren(Object o) {
			if (o instanceof MinimizedFileSystemElement) {
				MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
				return element.getFiles(FileSystemStructureProvider.INSTANCE).getChildren(
					element);
			}
			return new Object[0];
		}
	};
}
/**
 *	Answer the root FileSystemElement that represents the contents of
 *	the currently-specified source.  If this FileSystemElement is not
 *	currently defined then create and return it.
 */
protected MinimizedFileSystemElement getFileSystemTree() {

	File sourceDirectory = getSourceDirectory();
	if (sourceDirectory == null)
		return null;

	return selectFiles(sourceDirectory, FileSystemStructureProvider.INSTANCE);
}
/**
 * Returns a content provider for <code>FileSystemElement</code>s that returns 
 * only folders as children.
 */
protected ITreeContentProvider getFolderProvider() {
	return new WorkbenchContentProvider() {
		public Object[] getChildren(Object o) {
			if (o instanceof MinimizedFileSystemElement) {
				MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
				return element.getFolders(FileSystemStructureProvider.INSTANCE).getChildren(
					element);
			}
			return new Object[0];
		}
		public boolean hasChildren(Object o) {
			if (o instanceof MinimizedFileSystemElement) {
				MinimizedFileSystemElement element = (MinimizedFileSystemElement) o;
				if (element.isPopulated())
					return getChildren(element).length > 0;
				else {
					//If we have not populated then wait until asked
					return true;
				}
			}
			return false;
		}
	};
}

/**
 * Returns a File object representing the currently-named source directory iff
 * it exists as a valid directory, or <code>null</code> otherwise.
 */
protected File getSourceDirectory() {
	return getSourceDirectory(this.sourceNameField.getText());
}
/**
 * Returns a File object representing the currently-named source directory iff
 * it exists as a valid directory, or <code>null</code> otherwise.
 *
 * @param path a String not yet formatted for java.io.File compatability
 */
private File getSourceDirectory(String path) {
	File sourceDirectory = new File(getSourceDirectoryName(path));
	if (!sourceDirectory.exists() || !sourceDirectory.isDirectory()) {
		return null;
	}

	return sourceDirectory;
}
/**
 *	Answer the directory name specified as being the import source.
 *	Note that if it ends with a separator then the separator is first
 *	removed so that java treats it as a proper directory
 */
private String getSourceDirectoryName() {
	return getSourceDirectoryName(this.sourceNameField.getText());
}
/**
 *	Answer the directory name specified as being the import source.
 *	Note that if it ends with a separator then the separator is first
 *	removed so that java treats it as a proper directory
 */
private String getSourceDirectoryName(String sourceName) {
	IPath result = new Path(sourceName.trim());

	if (result.getDevice() != null && result.segmentCount() == 0)	// something like "c:"
		result = result.addTrailingSeparator();
	else
		result = result.removeTrailingSeparator();

	return result.toOSString();
}
/**
 *	Answer the string to display as the label for the source specification field
 */
protected String getSourceLabel() {
	return DataTransferMessages.getString("FileImport.fromDirectory"); //$NON-NLS-1$
}
/**
 *	Handle all events and enablements for widgets in this dialog
 *
 * @param event Event
 */
public void handleEvent(Event event) {
	if (event.widget == sourceBrowseButton)
		handleSourceBrowseButtonPressed();

	super.handleEvent(event);
}
/**
 *	Open an appropriate source browser so that the user can specify a source
 *	to import from
 */
protected void handleSourceBrowseButtonPressed() {

	String currentSource = this.sourceNameField.getText();
	DirectoryDialog dialog =
		new DirectoryDialog(sourceNameField.getShell(), SWT.SAVE);
	dialog.setText(SELECT_SOURCE_TITLE);
	dialog.setMessage(SELECT_SOURCE_MESSAGE);
	dialog.setFilterPath(getSourceDirectoryName(currentSource));

	String selectedDirectory = dialog.open();
	if (selectedDirectory != null) {
		//Just quit if the directory is not valid
		if ((getSourceDirectory(selectedDirectory) == null)
			|| selectedDirectory.equals(currentSource))
			return;
		else { //If it is valid then proceed to populate
			setErrorMessage(null);
			setSourceName(selectedDirectory);
			selectionGroup.setFocus();
		}
	}
}
/**
 * Open a registered type selection dialog and note the selections
 * in the receivers types-to-export field.,
 * Added here so that inner classes can have access
 */
protected void handleTypesEditButtonPressed() {

	super.handleTypesEditButtonPressed();
}
/**
 *  Import the resources with extensions as specified by the user
 */
protected boolean importResources(List fileSystemObjects) {
	ImportOperation operation = new ImportOperation(
		getContainerFullPath(),
		getSourceDirectory(),
		FileSystemStructureProvider.INSTANCE,
		this,
		fileSystemObjects);
		
	operation.setContext(getShell());	 
	return executeImportOperation(operation);
}
/**
 * Initializes the specified operation appropriately.
 */
protected void initializeOperation(ImportOperation op) {
	op.setCreateContainerStructure(createContainerStructureButton.getSelection());
	op.setOverwriteResources(overwriteExistingResourcesCheckbox.getSelection());
}
/**
 * Returns whether the extension provided is an extension that
 * has been specified for export by the user.
 *
 * @param extension the resource name
 * @return <code>true</code> if the resource name is suitable for export based 
 *   upon its extension
 */
protected boolean isExportableExtension(String extension) {
	if (selectedTypes == null)	// ie.- all extensions are acceptable
		return true;

	Iterator enum = selectedTypes.iterator();
	while (enum.hasNext()) {
		if (extension.equalsIgnoreCase((String)enum.next()))
			return true;
	}
	
	return false;
}
/**
 *	Repopulate the view based on the currently entered directory.
 */
protected void resetSelection() {

	MinimizedFileSystemElement currentRoot = getFileSystemTree();
	this.selectionGroup.setRoot(currentRoot);
	

}
/**
 *	Use the dialog store to restore widget values to the values that they held
 *	last time this wizard was used to completion
 */
protected void restoreWidgetValues() {
	IDialogSettings settings = getDialogSettings();
	if (settings != null) {
		String[] sourceNames = settings.getArray(STORE_SOURCE_NAMES_ID);
		if (sourceNames == null)
			return; // ie.- no values stored, so stop

		// set filenames history
		for (int i = 0; i < sourceNames.length; i++)
			sourceNameField.add(sourceNames[i]);

		// radio buttons and checkboxes	
		overwriteExistingResourcesCheckbox.setSelection(
			settings.getBoolean(STORE_OVERWRITE_EXISTING_RESOURCES_ID));

		boolean createStructure =
			settings.getBoolean(STORE_CREATE_CONTAINER_STRUCTURE_ID);
		createContainerStructureButton.setSelection(createStructure);
		createOnlySelectedButton.setSelection(!createStructure);

	}
}
/**
 * 	Since Finish was pressed, write widget values to the dialog store so that they
 *	will persist into the next invocation of this wizard page
 */
protected void saveWidgetValues() {
	IDialogSettings settings = getDialogSettings();
	if (settings != null) {
		// update source names history
		String[] sourceNames = settings.getArray(STORE_SOURCE_NAMES_ID);
		if (sourceNames == null)
			sourceNames = new String[0];

		sourceNames = addToHistory(sourceNames, getSourceDirectoryName());
		settings.put(STORE_SOURCE_NAMES_ID, sourceNames);

		// radio buttons and checkboxes	
		settings.put(
			STORE_OVERWRITE_EXISTING_RESOURCES_ID,
			overwriteExistingResourcesCheckbox.getSelection());

		settings.put(
			STORE_CREATE_CONTAINER_STRUCTURE_ID,
			createContainerStructureButton.getSelection());

	}
}
/**
 * Invokes a file selection operation using the specified file system and
 * structure provider.  If the user specifies files to be imported then
 * this selection is cached for later retrieval and is returned.
 */
protected MinimizedFileSystemElement selectFiles(
	final Object rootFileSystemObject,
	final IImportStructureProvider structureProvider) {

	final MinimizedFileSystemElement[] results = new MinimizedFileSystemElement[1];

	BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
		public void run() {
			//Create the root element from the supplied file system object
			results[0] = createRootElement(rootFileSystemObject, structureProvider);
		}
	});

	return results[0];
}
/**
 * Set all of the selections in the selection group to value. Implemented here
 * to provide access for inner classes.
 * @param value boolean
 */
protected void setAllSelections(boolean value) {
	super.setAllSelections(value);
}
/**
 * Sets the source name of the import to be the supplied path.
 * Adds the name of the path to the list of items in the
 * source combo and selects it.
 *
 * @param path the path to be added
 */
protected void setSourceName(String path) {

	if (path.length() > 0) {

		String[] currentItems = this.sourceNameField.getItems();
		int selectionIndex = -1;
		for (int i = 0; i < currentItems.length; i++) {
			if (currentItems[i].equals(path))
				selectionIndex = i;
		}
		if (selectionIndex < 0) {
			int oldLength = currentItems.length;
			String[] newItems = new String[oldLength + 1];
			System.arraycopy(currentItems, 0, newItems, 0, oldLength);
			newItems[oldLength] = path;
			this.sourceNameField.setItems(newItems);
			selectionIndex = oldLength;
		}
		this.sourceNameField.select(selectionIndex);

		resetSelection();
	}
}
/**
 * Update the tree to only select those elements that match the selected types
 */
protected void setupSelectionsBasedOnSelectedTypes() {
	ProgressMonitorDialog dialog = new ProgressMonitorJobsDialog(getContainer().getShell());	
	final Map selectionMap = new Hashtable();
	
	final IElementFilter filter = new IElementFilter() {
		
		public void filterElements(Collection files,IProgressMonitor monitor) throws InterruptedException{
			if(files == null){
				throw new InterruptedException();
			}				
			Iterator filesList = files.iterator();			
			while (filesList.hasNext()) {
				if(monitor.isCanceled())
					throw new InterruptedException();
				checkFile(filesList.next());
			}
		}
		
		public void filterElements(Object[] files,IProgressMonitor monitor) throws InterruptedException{
			if(files == null){
				throw new InterruptedException();
			}						
			for(int i =0; i < files.length; i ++){
				if(monitor.isCanceled())
					throw new InterruptedException();
				checkFile(files[i]);
			}
		}
		
		private void checkFile(Object fileElement){
			MinimizedFileSystemElement file = (MinimizedFileSystemElement) fileElement;
			if (isExportableExtension(file.getFileNameExtension())) {
				List elements = new ArrayList();
				FileSystemElement parent = file.getParent();
				if (selectionMap.containsKey(parent))
					elements = (List) selectionMap.get(parent);
				elements.add(file);
				selectionMap.put(parent, elements);
			}
		}

	};
	
	IRunnableWithProgress runnable  = new IRunnableWithProgress() {
		public void run(final IProgressMonitor monitor) throws InterruptedException{		
			monitor.beginTask(DataTransferMessages.getString("ImportPage.filterSelections"), IProgressMonitor.UNKNOWN); //$NON-NLS-1$
			getSelectedResources(filter,monitor);
		}
	};
	
	try{
		dialog.run(true,true,runnable);
	}
	catch (InvocationTargetException exception){
		//Couldn't start. Do nothing.
		return;
	}
	catch (InterruptedException exception){
		//Got interrupted. Do nothing.
		return;
	}
	// make sure that all paint operations caused by closing the progress 
	// dialog get flushed, otherwise extra pixels will remain on the screen until 
	// updateSelections is completed
	getShell().update();
	// The updateSelections method accesses SWT widgets so cannot be executed
	// as part of the above progress dialog operation since the operation forks
	// a new process.	
	if (selectionMap != null) {
		updateSelections(selectionMap);
	}
}
/* (non-Javadoc)
 * Method declared on IDialogPage. Set the selection up when it becomes visible.
 */
public void setVisible(boolean visible) {
	super.setVisible(visible);
	resetSelection();
	if(visible)
		this.sourceNameField.setFocus();
}
/**
 * Update the selections with those in map . Implemented here to give inner class
 * visibility
 * @param map Map - key tree elements, values Lists of list elements
 */
protected void updateSelections(Map map) {
	super.updateSelections(map);
}
/**
 * Check if widgets are enabled or disabled by a change in the dialog.
 * Provided here to give access to inner classes.
 * @param event Event
 */
protected void updateWidgetEnablements() {

	super.updateWidgetEnablements();
}
/**
 *	Answer a boolean indicating whether self's source specification
 *	widgets currently all contain valid values.
 */
protected boolean validateSourceGroup() {
	File sourceDirectory = getSourceDirectory();
	if (sourceDirectory == null) {
		setMessage(SOURCE_EMPTY_MESSAGE);
		enableButtonGroup(false);
		return false;
	}
	
	if(sourceConflictsWithDestination(new Path(sourceDirectory.getPath()))){
		setErrorMessage(getSourceConflictMessage()); //$NON-NLS-1$
		enableButtonGroup(false);
		return false;
	}
	
	enableButtonGroup(true);
	return true;
}

/**
 * Returns whether the source location conflicts
 * with the destination resource. This will occur if
 * the source is already under the destination.
 * 
 * @param sourcePath the path to check
 * @return <code>true</code> if there is a conflict, <code>false</code> if not
 */
protected boolean sourceConflictsWithDestination(IPath sourcePath){
	
	IContainer container = getSpecifiedContainer();
	if(container == null)
		return false;
	else {
		IPath destinationLocation = getSpecifiedContainer().getLocation();
		if (destinationLocation != null) { 
			return destinationLocation.isPrefixOf(sourcePath);
		}
		else {
			// null destination location is handled in 
			// WizardResourceImportPage 
			return false;
		}
	}
}


}
