/*******************************************************************************
* Copyright (c) 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:
* Serge Beauchamp (Freescale Semiconductor) - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.ide.dialogs;
import java.io.File;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
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.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.internal.ide.IDEInternalPreferences;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
import org.eclipse.ui.internal.ide.dialogs.LinkedResourcesPreferencePage;
import org.eclipse.ui.internal.ide.dialogs.RelativePathVariableGroup;
/**
* Dialog to let the user customise how files and resources are created in a project
* hierarchy after the user drag and drop items on a workspace container.
*
* Files and folders can be created either by copying the source objects, creating
* linked resources, and/or creating virtual folders.
* @noextend This class is not intended to be subclassed by clients.
* @since 3.6
*
*/
public class ImportTypeDialog extends TrayDialog {
/**
* Copy the files and folders to the destination
*/
public final static int IMPORT_COPY = 1;
/**
* Import only files
*/
public final static int IMPORT_FILES_ONLY = 16;
/**
* Create linked resources for each file and folder
*/
public final static int IMPORT_LINK = 4;
/**
* Move the files and folders to the destination
*/
public final static int IMPORT_MOVE = 8;
/**
* Do not perform an import operation
*/
public final static int IMPORT_NONE = 0;
/**
* Recreate the file and folder hierarchy using groups and links
*/
public final static int IMPORT_VIRTUAL_FOLDERS_AND_LINKS = 2;
private Button copyButton = null;
private int currentSelection;
private Button linkButton = null;
private Button moveButton = null;
private int operationMask;
private String preferredVariable;
private IResource receivingResource = null;
private Button shadowCopyButton = null;
private String variable = null;
private RelativePathVariableGroup relativePathVariableGroup;
/**
* Creates the Import Type Dialog when resources are dragged and dropped from an Eclipse
* view.
*
* @param shell
* the parent Shell
* @param dropOperation
* The dropOperation that was used by the user
* @param sources
* The list of resources that were dragged
* @param target
* The target container onto which the resources were dropped
*/
public ImportTypeDialog(Shell shell, int dropOperation,
IResource[] sources, IContainer target) {
this(shell, selectAppropriateMask(dropOperation, sources, target), RelativePathVariableGroup.getPreferredVariable(sources, target));
}
/**
* Creates the Import Type Dialog when files are dragged and dropped from the
* operating system's shell (Windows Explorer on Windows Platform, for example).
*
* @param shell
* the parent Shell
* @param dropOperation
* The dropOperation that was used by the user
* @param names
* The list of files that were dragged
* @param target
* The target container onto which the files were dropped
*/
public ImportTypeDialog(Shell shell, int dropOperation, String[] names, IContainer target) {
this(shell, selectAppropriateMask(dropOperation, names, target), RelativePathVariableGroup.getPreferredVariable(names, target));
}
/**
* @param parentShell
* @param operationMask
*/
private ImportTypeDialog(Shell parentShell, int operationMask, String preferredVariable) {
super(parentShell);
this.preferredVariable = preferredVariable;
this.operationMask = operationMask;
currentSelection = 0;
String tmp = readContextPreference(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_TYPE);
if (tmp.length() > 0)
currentSelection = Integer.parseInt(tmp);
currentSelection = currentSelection & operationMask;
if (currentSelection == 0) {
if (hasFlag(IMPORT_COPY))
currentSelection = IMPORT_COPY;
else
currentSelection = IMPORT_MOVE;
}
IPreferenceStore store = IDEWorkbenchPlugin.getDefault().getPreferenceStore();
if (store.getBoolean(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_RELATIVE))
variable = preferredVariable;
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.TrayDialog#close()
*/
public boolean close() {
return super.close();
}
/**
* Get the user selection from the dialog.
* @return The current selection (one of IMPORT_COPY, IMPORT_VIRTUAL_FOLDERS_AND_LINKS, IMPORT_LINK and IMPORT_MOVE)
*/
public int getSelection() {
return currentSelection;
}
/**
* Get the selected variable if the selection is either IMPORT_VIRTUAL_FOLDERS_AND_LINKS or IMPORT_LINK
* @return The currently selected variable, or AUTOMATIC or ABSOLUTE_PATH
*/
public String getVariable() {
return variable;
}
/** Set the project that is the destination of the import operation
* @param resource
*/
public void setResource(IResource resource) {
receivingResource = resource;
}
private boolean hasFlag(int flag) {
return (operationMask & flag) != 0;
}
// the format of the context is operationMask,value:operationMask,value:operationMask,value
private String readContextPreference(String key) {
String value = IDEWorkbenchPlugin.getDefault().getPreferenceStore().getString(key);
String [] keyPairs = value.split(":"); //$NON-NLS-1$
for (int i = 0; i < keyPairs.length; i++) {
String [] element = keyPairs[i].split(","); //$NON-NLS-1$
if (element.length == 2) {
if (element[0].equals(Integer.toString(operationMask)))
return element[1];
}
}
return ""; //$NON-NLS-1$
}
private void refreshSelection() {
if (copyButton != null)
copyButton.setSelection(currentSelection == IMPORT_COPY);
if (shadowCopyButton != null)
shadowCopyButton.setSelection(currentSelection == IMPORT_VIRTUAL_FOLDERS_AND_LINKS);
if (linkButton != null)
linkButton.setSelection(currentSelection == IMPORT_LINK);
if (moveButton != null)
moveButton.setSelection(currentSelection == IMPORT_MOVE);
if (relativePathVariableGroup != null) {
relativePathVariableGroup.setEnabled((currentSelection & (IMPORT_VIRTUAL_FOLDERS_AND_LINKS | IMPORT_LINK)) != 0);
}
}
private void writeContextPreference(String key, String value) {
String oldValue = IDEWorkbenchPlugin.getDefault().getPreferenceStore().getString(key);
StringBuffer buffer = new StringBuffer();
String [] keyPairs = oldValue.split(":"); //$NON-NLS-1$
boolean found = false;
for (int i = 0; i < keyPairs.length; i++) {
if (i > 0)
buffer.append(":"); //$NON-NLS-1$
String [] element = keyPairs[i].split(","); //$NON-NLS-1$
if (element.length == 2) {
if (element[0].equals(Integer.toString(operationMask))) {
buffer.append(element[0] + "," + value); //$NON-NLS-1$
found = true;
}
else
buffer.append(keyPairs[i]);
}
}
if (!found) {
if (buffer.length() > 0)
buffer.append(":"); //$NON-NLS-1$
buffer.append(Integer.toString(operationMask) + "," + value); //$NON-NLS-1$
}
String newValue = buffer.toString();
IDEWorkbenchPlugin.getDefault().getPreferenceStore().setValue(key, newValue);
}
protected void buttonPressed(int buttonId) {
if (buttonId == IDialogConstants.OK_ID) {
writeContextPreference(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_TYPE, Integer.toString(currentSelection));
IPreferenceStore store = IDEWorkbenchPlugin.getDefault().getPreferenceStore();
store.putValue(IDEInternalPreferences.IMPORT_FILES_AND_FOLDERS_RELATIVE, Boolean.toString(variable != null));
}
super.buttonPressed(buttonId);
}
protected void configureShell(Shell shell) {
super.configureShell(shell);
String title = (operationMask & IMPORT_FILES_ONLY) != 0 ? IDEWorkbenchMessages.ImportTypeDialog_titleFilesOnly:
IDEWorkbenchMessages.ImportTypeDialog_title;
shell.setText(title);
PlatformUI.getWorkbench().getHelpSystem().setHelp(shell,
IIDEHelpContextIds.IMPORT_TYPE_DIALOG);
}
protected Control createDialogArea(Composite parent) {
boolean linkIsOnlyChoice = hasFlag(IMPORT_LINK) && !(hasFlag(IMPORT_COPY | IMPORT_MOVE) || (hasFlag(IMPORT_VIRTUAL_FOLDERS_AND_LINKS) && !hasFlag(IMPORT_FILES_ONLY)));
if (!linkIsOnlyChoice)
createMessageArea(parent);
Composite composite = new Composite(parent, 0);
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
composite.setLayoutData(gridData);
composite.setFont(parent.getFont());
GridLayout layout = new GridLayout();
layout.numColumns = 1;
layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
layout.verticalSpacing= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
int indent= linkIsOnlyChoice ? 0: convertWidthInCharsToPixels(3);
layout.marginWidth += indent;
composite.setLayout(layout);
SelectionListener listener = new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
currentSelection = ((Integer) e.widget.getData()).intValue();
refreshSelection();
}
public void widgetSelected(SelectionEvent e) {
currentSelection = ((Integer) e.widget.getData()).intValue();
refreshSelection();
}
};
if (hasFlag(IMPORT_COPY)) {
copyButton = new Button(composite, SWT.RADIO);
copyButton.setText(hasFlag(IMPORT_FILES_ONLY) ? IDEWorkbenchMessages.ImportTypeDialog_copyFiles: IDEWorkbenchMessages.ImportTypeDialog_copyFilesAndDirectories);
gridData = new GridData(GridData.FILL_HORIZONTAL);
copyButton.setLayoutData(gridData);
copyButton.setData(new Integer(IMPORT_COPY));
copyButton.addSelectionListener(listener);
copyButton.setFont(parent.getFont());
}
if (hasFlag(IMPORT_MOVE)) {
moveButton = new Button(composite, SWT.RADIO);
moveButton.setText(hasFlag(IMPORT_FILES_ONLY) ? IDEWorkbenchMessages.ImportTypeDialog_moveFiles:IDEWorkbenchMessages.ImportTypeDialog_moveFilesAndDirectories);
gridData = new GridData(GridData.FILL_HORIZONTAL);
moveButton.setLayoutData(gridData);
moveButton.setData(new Integer(IMPORT_MOVE));
moveButton.addSelectionListener(listener);
moveButton.setFont(parent.getFont());
}
if (hasFlag(IMPORT_LINK) && !linkIsOnlyChoice) {
linkButton = new Button(composite, SWT.RADIO);
linkButton.setText(hasFlag(IMPORT_FILES_ONLY) ? IDEWorkbenchMessages.ImportTypeDialog_linkFiles:IDEWorkbenchMessages.ImportTypeDialog_createLinks);
gridData = new GridData(GridData.FILL_HORIZONTAL);
linkButton.setLayoutData(gridData);
linkButton.setData(new Integer(IMPORT_LINK));
linkButton.addSelectionListener(listener);
linkButton.setFont(parent.getFont());
}
if (hasFlag(IMPORT_VIRTUAL_FOLDERS_AND_LINKS) && !hasFlag(IMPORT_FILES_ONLY)) {
shadowCopyButton = new Button(composite, SWT.RADIO);
shadowCopyButton.setText(IDEWorkbenchMessages.ImportTypeDialog_recreateFilesAndDirectories);
gridData = new GridData(GridData.FILL_HORIZONTAL);
shadowCopyButton.setLayoutData(gridData);
shadowCopyButton.setData(new Integer(IMPORT_VIRTUAL_FOLDERS_AND_LINKS));
shadowCopyButton.addSelectionListener(listener);
shadowCopyButton.setFont(parent.getFont());
}
if (hasFlag(IMPORT_VIRTUAL_FOLDERS_AND_LINKS | IMPORT_LINK)) {
relativePathVariableGroup = new RelativePathVariableGroup(new RelativePathVariableGroup.IModel() {
public IResource getResource() {
return receivingResource;
}
public void setVariable(String string) {
variable = string;
}
public String getVariable() {
return variable;
}
});
int groupIndent = 0;
if (!linkIsOnlyChoice) {
Button tmp = new Button(composite, SWT.CHECK);
tmp.setText("."); //$NON-NLS-1$
groupIndent = tmp.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
tmp.dispose();
Label tmpLabel = new Label(composite, SWT.NONE);
tmpLabel.setText("."); //$NON-NLS-1$
groupIndent -= tmpLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
tmpLabel.dispose();
}
Composite variableGroup = new Composite(composite, 0);
gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.horizontalIndent = groupIndent;
variableGroup.setLayoutData(gridData);
variableGroup.setFont(parent.getFont());
layout = new GridLayout();
layout.numColumns = 2;
layout.marginWidth= 0;
variableGroup.setLayout(layout);
relativePathVariableGroup.createContents(variableGroup);
relativePathVariableGroup.setSelection(variable != null);
if (variable != null)
relativePathVariableGroup.selectVariable(variable);
else
relativePathVariableGroup.selectVariable(preferredVariable);
}
if (linkIsOnlyChoice) {
currentSelection = IMPORT_LINK;
parent.getShell().setText(IDEWorkbenchMessages.ImportTypeDialog_titleFilesLinking);
}
createLinkControl(parent);
refreshSelection();
return composite;
}
private Control createLinkControl(Composite composite) {
Link link= new Link(composite, SWT.WRAP | SWT.RIGHT);
link.setText(IDEWorkbenchMessages.ImportTypeDialog_configureSettings);
link.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
openSettingsPage();
}
});
GridData gridData= new GridData(GridData.FILL, GridData.CENTER, true, false);
gridData.horizontalIndent = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
link.setLayoutData(gridData);
link.setFont(composite.getFont());
return link;
}
protected void openSettingsPage() {
String prefID = LinkedResourcesPreferencePage.PREF_ID;
PreferencesUtil.createPreferenceDialogOn(getShell(), prefID, new String[] {prefID}, null).open();
}
protected Control createMessageArea(Composite parent) {
Composite composite = new Composite(parent, 0);
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
composite.setLayoutData(gridData);
composite.setFont(parent.getFont());
GridLayout layout = new GridLayout();
layout.numColumns = 1;
layout.marginTop= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
composite.setLayout(layout);
String message = (operationMask & IMPORT_FILES_ONLY) != 0 ? IDEWorkbenchMessages.ImportTypeDialog_questionFilesOnly:
IDEWorkbenchMessages.ImportTypeDialog_question;
// create message
if (message != null) {
Label messageLabel = new Label(composite, SWT.WRAP);
messageLabel.setFont(parent.getFont());
messageLabel.setText(message);
gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
messageLabel.setLayoutData(gridData);
}
return composite;
}
/**
* @param resources
* The list of items that were dragged
* @return true if a set of paths are files only or a mix of files and folders, false otherwise
*/
private static boolean areOnlyFiles(IResource[] resources) {
for (int i = 0; i < resources.length; i++) {
if (resources[i].getType() != IResource.FILE)
return false;
}
return true;
}
/**
* @param names
* The list of items that were dragged
* @return true if a set of paths are files only or a mix of files and folders, false otherwise
*/
private static boolean areOnlyFiles(String[] names) {
for (int i = 0; i < names.length; i++) {
File file = new File(names[i]);
if (file.exists() && !file.isFile())
return false;
}
return true;
}
/**
* Select the most appropriate mode that should be used for the dialog given
* the items dropped on the container, the container type, and the drop operation.
*
* @param dropOperation
* @param resources
* The list of items that were dragged
* @param target
* The target container onto which the items were dropped
* @return the appropriate import mask given the files dropped on the target
*/
private static int selectAppropriateMask(int dropOperation, IResource[] resources, IContainer target) {
int mask = ImportTypeDialog.IMPORT_VIRTUAL_FOLDERS_AND_LINKS | ImportTypeDialog.IMPORT_LINK;
if (!target.isVirtual() && (dropOperation != DND.DROP_LINK))
mask |= ImportTypeDialog.IMPORT_COPY;
if (areOnlyFiles(resources))
mask |= ImportTypeDialog.IMPORT_FILES_ONLY;
return mask;
}
/**
* Select the most appropriate mode that should be used for the dialog given
* the items dropped on the container, the container type, and the drop operation.
*
* @param dropOperation
* @param names
* The list of items that were dragged
* @param target
* The target container onto which the items were dropped
* @return the appropriate import mask given the files dropped on the target
*/
private static int selectAppropriateMask(int dropOperation, String[] names, IContainer target) {
int mask = ImportTypeDialog.IMPORT_VIRTUAL_FOLDERS_AND_LINKS | ImportTypeDialog.IMPORT_LINK;
if (!target.isVirtual() && (dropOperation != DND.DROP_LINK))
mask |= ImportTypeDialog.IMPORT_COPY;
if (areOnlyFiles(names))
mask |= ImportTypeDialog.IMPORT_FILES_ONLY;
return mask;
}
}