blob: 719deb43ab952bd0a519cc82bbc5915315093957 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2008 Tasktop Technologies 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
* Sebastian Davids <sdavids@gmx.de> - layout tweaks
* Jeff Pound - modified for attachment input
* Chris Aniszczyk <caniszczyk@gmail.com> - bug 20957
* Tasktop Technologies - improvements
*******************************************************************************/
package org.eclipse.mylyn.internal.tasks.ui.wizards;
import java.io.File;
import java.util.ArrayList;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.resources.mapping.ResourceMappingContext;
import org.eclipse.core.resources.mapping.ResourceTraversal;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.mylyn.internal.tasks.core.data.FileTaskAttachmentSource;
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
import org.eclipse.mylyn.internal.tasks.ui.wizards.TaskAttachmentWizard.ClipboardTaskAttachmentSource;
import org.eclipse.mylyn.tasks.core.data.AbstractTaskAttachmentSource;
import org.eclipse.mylyn.tasks.core.data.TaskAttachmentModel;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
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.graphics.Point;
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.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.navigator.ResourceComparator;
/**
* A wizard to input the source of the attachment.
* <p>
* Based on org.eclipse.compare.internal.InputPatchPage.
*/
public class AttachmentSourcePage extends WizardPage {
// constants
protected static final int SIZING_TEXT_FIELD_WIDTH = 250;
protected static final int COMBO_HISTORY_LENGTH = 5;
// input constants
protected final static int CLIPBOARD = 1;
protected final static int FILE = 2;
protected final static int WORKSPACE = 3;
protected final static int SCREENSHOT = 4;
static final char SEPARATOR = System.getProperty("file.separator").charAt(0); //$NON-NLS-1$
private boolean showError = false;
// SWT widgets
private Button useClipboardButton;
// private Button useScreenshotButton;
private Combo fileNameField;
private Button fileBrowseButton;
private Button useFileButton;
private Button useWorkspaceButton;
private Label workspaceSelectLabel;
private TreeViewer treeViewer;
private String clipboardContents;
private boolean initUseClipboard = false;
private final String DIALOG_SETTINGS = "InputAttachmentSourcePage"; //$NON-NLS-1$
private final String S_LAST_SELECTION = "lastSelection"; //$NON-NLS-1$
private final TaskAttachmentModel model;
public AttachmentSourcePage(TaskAttachmentModel model) {
super("InputAttachmentPage"); //$NON-NLS-1$
this.model = model;
setTitle(Messages.AttachmentSourcePage_Select_attachment_source);
setDescription(Messages.AttachmentSourcePage_Clipboard_supports_text_and_image_attachments_only);
// setMessage("Please select the source for the attachment");
}
private void initialize(IDialogSettings settings) {
String selection = settings.get(S_LAST_SELECTION);
if (selection != null) {
setInputMethod(Integer.valueOf(selection).intValue());
} else {
updateWidgetEnablements();
}
}
/*
* Get a path from the supplied text widget. @return
* org.eclipse.core.runtime.IPath
*/
protected IPath getPathFromText(Text textField) {
return (new Path(textField.getText())).makeAbsolute();
}
public String getAttachmentName() {
if (getInputMethod() == CLIPBOARD) {
return Messages.AttachmentSourcePage__Clipboard_;
} else if (getInputMethod() == WORKSPACE) {
return getResources(treeViewer.getSelection())[0].getFullPath().toOSString();
}
return getAttachmentFilePath();
}
public void createControl(Composite parent) {
Composite composite = new Composite(parent, SWT.NULL);
composite.setLayout(new GridLayout());
GridData gd = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL);
gd.heightHint = 800;
composite.setLayoutData(gd);
setControl(composite);
initializeDialogUnits(parent);
createAttachmentFileGroup(composite);
// No error for dialog opening
showError = false;
clearErrorMessage();
initialize(getDialogSettings());
Dialog.applyDialogFont(composite);
}
@Override
public IWizardPage getNextPage() {
model.setSource(getSource());
saveDialogSettings();
return super.getNextPage();
}
private void saveDialogSettings() {
IDialogSettings settings = getDialogSettings();
settings.put(S_LAST_SELECTION, getInputMethod());
}
@Override
public boolean canFlipToNextPage() {
return isPageComplete();
}
private void setEnableAttachmentFile(boolean enable) {
fileNameField.setEnabled(enable);
fileBrowseButton.setEnabled(enable);
}
private void setEnableWorkspaceAttachment(boolean enable) {
workspaceSelectLabel.setEnabled(enable);
treeViewer.getTree().setEnabled(enable);
}
/*
* Create the group for selecting the attachment file
*/
private void createAttachmentFileGroup(Composite parent) {
final Composite composite = new Composite(parent, SWT.NULL);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 3;
composite.setLayout(gridLayout);
composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// new row
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
useFileButton = new Button(composite, SWT.RADIO);
useFileButton.setText(Messages.AttachmentSourcePage_File);
fileNameField = new Combo(composite, SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint = SIZING_TEXT_FIELD_WIDTH;
fileNameField.setLayoutData(gd);
fileNameField.setText(""); //$NON-NLS-1$
fileBrowseButton = new Button(composite, SWT.PUSH);
fileBrowseButton.setText(Messages.AttachmentSourcePage_Browse_);
GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
Point minSize = fileBrowseButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
data.widthHint = Math.max(widthHint, minSize.x);
fileBrowseButton.setLayoutData(data);
// new row
gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalSpan = 3;
useClipboardButton = new Button(composite, SWT.RADIO);
useClipboardButton.setText(Messages.AttachmentSourcePage_Clipboard);
useClipboardButton.setLayoutData(gd);
useClipboardButton.setSelection(initUseClipboard);
// new row
useWorkspaceButton = new Button(composite, SWT.RADIO);
useWorkspaceButton.setText(Messages.AttachmentSourcePage_Workspace);
gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
useWorkspaceButton.setLayoutData(gd);
addWorkspaceControls(parent);
// Add listeners
useClipboardButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (!useClipboardButton.getSelection()) {
return;
}
clearErrorMessage();
showError = true;
storeClipboardContents();
updateWidgetEnablements();
}
});
useFileButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (!useFileButton.getSelection()) {
return;
}
// If there is anything typed in at all
clearErrorMessage();
showError = (fileNameField.getText() != ""); //$NON-NLS-1$
updateWidgetEnablements();
}
});
fileNameField.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
setSourceName(fileNameField.getText());
updateWidgetEnablements();
}
});
fileNameField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
clearErrorMessage();
showError = true;
updateWidgetEnablements();
}
});
fileBrowseButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
clearErrorMessage();
showError = true;
/* Launch Browser */
FileDialog fileChooser = new FileDialog(composite.getShell(), SWT.OPEN);
String file = fileChooser.open();
// Check if the dialog was canceled or an error occured
if (file == null) {
return;
}
// update UI
fileNameField.setText(file);
updateWidgetEnablements();
}
});
useWorkspaceButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (!useWorkspaceButton.getSelection()) {
return;
}
clearErrorMessage();
// If there is anything typed in at all
showError = (!treeViewer.getSelection().isEmpty());
updateWidgetEnablements();
}
});
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
clearErrorMessage();
updateWidgetEnablements();
}
});
treeViewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
ISelection selection = event.getSelection();
if (selection instanceof TreeSelection) {
TreeSelection treeSel = (TreeSelection) selection;
Object res = treeSel.getFirstElement();
if (res != null) {
if (res instanceof IProject || res instanceof IFolder) {
if (treeViewer.getExpandedState(res)) {
treeViewer.collapseToLevel(res, 1);
} else {
treeViewer.expandToLevel(res, 1);
}
} else if (res instanceof IFile) {
getContainer().showPage(getNextPage());
}
}
}
}
});
useFileButton.setSelection(!initUseClipboard);
setEnableWorkspaceAttachment(false);
}
private void addWorkspaceControls(Composite composite) {
Composite newComp = new Composite(composite, SWT.NONE);
GridLayout layout = new GridLayout(1, false);
layout.marginLeft = 16; // align w/ lable of check button
newComp.setLayout(layout);
newComp.setLayoutData(new GridData(GridData.FILL_BOTH));
workspaceSelectLabel = new Label(newComp, SWT.LEFT);
workspaceSelectLabel.setText(Messages.AttachmentSourcePage_Select_the_location_of_the_attachment);
treeViewer = new TreeViewer(newComp, SWT.BORDER);
treeViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
treeViewer.setLabelProvider(new WorkbenchLabelProvider());
treeViewer.setContentProvider(new WorkbenchContentProvider());
treeViewer.setComparator(new ResourceComparator(ResourceComparator.NAME));
treeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
}
/**
* Updates the enable state of this page's controls.
*/
private void updateWidgetEnablements() {
String error = null;
boolean attachmentFound = false;
int inputMethod = getInputMethod();
if (inputMethod == CLIPBOARD) {
if (ClipboardTaskAttachmentSource.isSupportedType(getControl().getDisplay())) {
attachmentFound = true;
} else {
error = Messages.AttachmentSourcePage_Clipboard_contains_an_unsupported_data;
}
} else if (inputMethod == SCREENSHOT) {
attachmentFound = true;
} else if (inputMethod == FILE) {
String path = fileNameField.getText();
if (path != null && path.length() > 0) {
File file = new File(path);
attachmentFound = file.exists() && file.isFile() && file.length() > 0;
if (!attachmentFound) {
error = Messages.AttachmentSourcePage_Cannot_locate_attachment_file;
}
} else {
error = Messages.AttachmentSourcePage_No_file_name;
}
} else if (inputMethod == WORKSPACE) {
// Get the selected attachment file (tree will only allow for one
// selection)
IResource[] resources = getResources(treeViewer.getSelection());
if (resources == null || resources.length <= 0) {
error = Messages.AttachmentSourcePage_No_file_name;
} else {
IResource attachmentFile = resources[0];
if (attachmentFile != null && attachmentFile.getType() == IResource.FILE) {
File actualFile = attachmentFile.getRawLocation().toFile();
attachmentFound = actualFile.exists() && actualFile.isFile() && actualFile.length() > 0;
if (!attachmentFound) {
error = Messages.AttachmentSourcePage_Cannot_locate_attachment_file;
}
}
}
}
setPageComplete(attachmentFound);
if (showError) {
setErrorMessage(error);
}
setEnableAttachmentFile(inputMethod == FILE);
setEnableWorkspaceAttachment(inputMethod == WORKSPACE);
}
/**
* 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 = fileNameField.getItems();
int selectionIndex = -1;
for (int i = 0; i < currentItems.length; i++) {
if (currentItems[i].equals(path)) {
selectionIndex = i;
}
}
if (selectionIndex < 0) { // not found in history
int oldLength = currentItems.length;
String[] newItems = new String[oldLength + 1];
System.arraycopy(currentItems, 0, newItems, 0, oldLength);
newItems[oldLength] = path;
fileNameField.setItems(newItems);
selectionIndex = oldLength;
}
fileNameField.select(selectionIndex);
// resetSelection();
}
}
/*
* Clears the dialog message box
*/
private void clearErrorMessage() {
setErrorMessage(null);
}
protected int getInputMethod() {
if (useClipboardButton == null) {
if (initUseClipboard) {
return CLIPBOARD;
}
return FILE;
}
if (useClipboardButton.getSelection()) {
return CLIPBOARD;
}
if (useFileButton.getSelection()) {
return FILE;
}
return WORKSPACE;
}
protected void setInputMethod(int input) {
switch (input) {
case WORKSPACE:
useWorkspaceButton.setSelection(true);
useClipboardButton.setSelection(false);
useFileButton.setSelection(false);
break;
case CLIPBOARD:
storeClipboardContents();
useClipboardButton.setSelection(true);
useFileButton.setSelection(false);
useWorkspaceButton.setSelection(false);
break;
default:
useFileButton.setSelection(true);
useWorkspaceButton.setSelection(false);
useClipboardButton.setSelection(false);
break;
}
updateWidgetEnablements();
}
private String getAttachmentFilePath() {
if (fileNameField != null) {
return fileNameField.getText();
}
return null;
}
public String getAbsoluteAttachmentPath() {
switch (getInputMethod()) {
case CLIPBOARD:
return Messages.AttachmentSourcePage__Clipboard_;
case SCREENSHOT:
return Messages.AttachmentSourcePage__Screenshot_;
case WORKSPACE:
IResource[] resources = getResources(treeViewer.getSelection());
if (resources.length > 0 && resources[0].getRawLocation() != null) {
return resources[0].getRawLocation().toOSString();
} else {
return null;
}
case FILE:
default:
return getAttachmentFilePath();
}
}
/*
* Based on .eclipse.compare.internal.Utilities
*
* Convenience method: extract all accessible <code>IResources</code> from
* given selection. Never returns null.
*/
public static IResource[] getResources(ISelection selection) {
ArrayList<IResource> tmp = new ArrayList<IResource>();
Class<?> type = IResource.class;
if (selection instanceof IStructuredSelection) {
Object[] s = ((IStructuredSelection) selection).toArray();
for (Object o : s) {
IResource resource = null;
if (type.isInstance(o)) {
resource = (IResource) o;
} else if (o instanceof ResourceMapping) {
try {
ResourceTraversal[] travs = ((ResourceMapping) o).getTraversals(
ResourceMappingContext.LOCAL_CONTEXT, null);
if (travs != null) {
for (ResourceTraversal trav : travs) {
IResource[] resources = trav.getResources();
for (IResource resource2 : resources) {
if (type.isInstance(resource2) && resource2.isAccessible()) {
tmp.add(resource2);
}
}
}
}
} catch (CoreException ex) {
// TODO handle error
}
} else if (o instanceof IAdaptable) {
IAdaptable a = (IAdaptable) o;
Object adapter = a.getAdapter(IResource.class);
if (type.isInstance(adapter)) {
resource = (IResource) adapter;
}
}
if (resource != null && resource.isAccessible()) {
tmp.add(resource);
}
}
}
return tmp.toArray(new IResource[tmp.size()]);
}
private void storeClipboardContents() {
Control c = getControl();
if (c != null) {
Clipboard clipboard = new Clipboard(c.getDisplay());
Object o = clipboard.getContents(TextTransfer.getInstance());
clipboard.dispose();
if (o instanceof String) {
clipboardContents = ((String) o).trim();
}
}
}
public String getClipboardContents() {
return clipboardContents;
}
public void setClipboardContents(String attachContents) {
clipboardContents = attachContents;
}
public void setUseClipboard(boolean b) {
if (useClipboardButton != null) {
useClipboardButton.setSelection(b);
}
initUseClipboard = b;
}
@Override
protected IDialogSettings getDialogSettings() {
TasksUiPlugin plugin = TasksUiPlugin.getDefault();
IDialogSettings settings = plugin.getDialogSettings();
IDialogSettings section = settings.getSection(DIALOG_SETTINGS);
if (section == null) {
section = settings.addNewSection(DIALOG_SETTINGS);
}
return section;
}
public AbstractTaskAttachmentSource getSource() {
switch (getInputMethod()) {
case CLIPBOARD:
return new TaskAttachmentWizard.ClipboardTaskAttachmentSource();
case WORKSPACE:
IResource[] resources = getResources(treeViewer.getSelection());
if (resources.length > 0) {
return new FileTaskAttachmentSource(resources[0].getLocation().toFile());
} else {
return null;
}
default: // FILE
return new FileTaskAttachmentSource(new File(getAttachmentFilePath()));
}
}
}