blob: e17543b9e90a194edbed9743d93583517b0bc212 [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:
* Tasktop Technologies - initial API and implementation
* Jevgeni Holodkov - improvements
*******************************************************************************/
package org.eclipse.mylyn.internal.tasks.ui.views;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.internal.provisional.commons.ui.AbstractRetrieveTitleFromUrlJob;
import org.eclipse.mylyn.internal.tasks.core.AbstractTask;
import org.eclipse.mylyn.internal.tasks.core.AbstractTaskCategory;
import org.eclipse.mylyn.internal.tasks.core.LocalTask;
import org.eclipse.mylyn.internal.tasks.core.RepositoryQuery;
import org.eclipse.mylyn.internal.tasks.core.ScheduledTaskContainer;
import org.eclipse.mylyn.internal.tasks.core.TaskCategory;
import org.eclipse.mylyn.internal.tasks.core.UncategorizedTaskContainer;
import org.eclipse.mylyn.internal.tasks.core.UnmatchedTaskContainer;
import org.eclipse.mylyn.internal.tasks.ui.ITasksUiPreferenceConstants;
import org.eclipse.mylyn.internal.tasks.ui.TaskTransfer;
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
import org.eclipse.mylyn.internal.tasks.ui.actions.QueryImportAction;
import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal;
import org.eclipse.mylyn.internal.tasks.ui.views.TaskScheduleContentProvider.Unscheduled;
import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.ITaskContainer;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.ui.TasksUi;
import org.eclipse.mylyn.tasks.ui.TasksUiUtil;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.ui.PlatformUI;
/**
* @author Mik Kersten
* @author Rob Elves (added URL based task creation support)
* @author Jevgeni Holodkov
*/
// TODO 3.1 rename to TaskListDropTargetListener
public class TaskListDropAdapter extends ViewerDropAdapter {
private AbstractTask newTask = null;
private TransferData currentTransfer;
public TaskListDropAdapter(Viewer viewer) {
super(viewer);
setFeedbackEnabled(true);
}
@Override
public void dragOver(DropTargetEvent event) {
// support dragging from sources only supporting DROP_LINK
if (event.detail == DND.DROP_NONE && (event.operations & DND.DROP_LINK) == DND.DROP_LINK) {
event.detail = DND.DROP_LINK;
}
super.dragOver(event);
}
@Override
public boolean performDrop(final Object data) {
if (data == null) {
return false;
}
Object currentTarget = getCurrentTarget();
List<ITask> tasksToMove = new ArrayList<ITask>();
if (isUrl(data) && createTaskFromUrl(data)) {
tasksToMove.add(newTask);
} else if (TaskTransfer.getInstance().isSupportedType(currentTransfer) && data instanceof ITask[]) {
ITask[] tasks = (ITask[]) data;
for (ITask task : tasks) {
if (task != null) {
tasksToMove.add(task);
}
}
} else if (data instanceof String && createTaskFromString((String) data)) {
tasksToMove.add(newTask);
} else if (FileTransfer.getInstance().isSupportedType(currentTransfer)) {
// transfer the context if the target is a Task
// if (getCurrentTarget() instanceof ITask) {
// final AbstractTask targetTask = (AbstractTask) getCurrentTarget();
// final String[] names = (String[]) data;
// PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
//
// public void run() {
// boolean confirmed = MessageDialog.openConfirm(getViewer().getControl().getShell(),
// "Task Import", "Overwrite the context of the target task with the source's?");
// if (confirmed) {
// String path = names[0];
// File file = new File(path);
// boolean succeeded = ContextCore.getContextStore().copyContext(file,
// targetTask.getHandleIdentifier());
// if (succeeded) {
// new TaskActivateAction().run(targetTask);
// }
// }
// }
// });
// } else {
// otherwise it is queries or tasks
final String[] names = (String[]) data;
for (String path : names) {
final File file = new File(path);
final List<RepositoryQuery> queries = new ArrayList<RepositoryQuery>();
final Set<TaskRepository> repositories = new HashSet<TaskRepository>();
final List<AbstractTask> readTasks = TasksUiPlugin.getTaskListManager().getTaskListWriter().readTasks(
file);
if (file.isFile()) {
List<RepositoryQuery> readQueries;
try {
readQueries = TasksUiPlugin.getTaskListManager().getTaskListWriter().readQueries(file);
if (readQueries.size() > 0) {
queries.addAll(readQueries);
repositories.addAll(TasksUiPlugin.getTaskListManager()
.getTaskListWriter()
.readRepositories(file));
} else {
repositories.addAll(TasksUiPlugin.getTaskListManager()
.getTaskListWriter()
.readRepositories(file));
}
} catch (IOException e) {
StatusHandler.log(new Status(IStatus.WARNING, TasksUiPlugin.ID_PLUGIN, "The specified file \""
+ file.getName()
+ "\" is not an exported query. Please, check that you have provided the correct file."));
// PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
// public void run() {
// MessageDialog.openError(null, "Query Import Error",
// "The specified file is not an exported query. Please, check that you have provided the correct file.");
// }
// });
}
}
// FIXME: remove async exec
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
public void run() {
// TODO: we should consider batching this up
if (queries.size() > 0) {
new QueryImportAction().importQueries(queries, repositories, getViewer().getControl()
.getShell());
} else {
TasksUiInternal.importTasks(readTasks, repositories, file, getViewer().getControl()
.getShell());
}
}
});
}
}
if (currentTarget instanceof LocalTask
&& areAllLocalTasks(tasksToMove)
&& getCurrentLocation() == LOCATION_ON
&& TasksUiPlugin.getDefault().getPreferenceStore().getBoolean(
ITasksUiPreferenceConstants.LOCAL_SUB_TASKS_ENABLED)) {
for (ITask task : tasksToMove) {
if (!((AbstractTask) task).contains(((LocalTask) currentTarget).getHandleIdentifier())) {
TasksUiInternal.getTaskList().addTask(task, (LocalTask) currentTarget);
}
}
} else {
for (ITask task : tasksToMove) {
if (currentTarget instanceof UncategorizedTaskContainer) {
TasksUiInternal.getTaskList().addTask(task, (UncategorizedTaskContainer) currentTarget);
} else if (currentTarget instanceof TaskCategory) {
TasksUiInternal.getTaskList().addTask(task, (TaskCategory) currentTarget);
} else if (currentTarget instanceof UnmatchedTaskContainer) {
if (((UnmatchedTaskContainer) currentTarget).getRepositoryUrl().equals(task.getRepositoryUrl())) {
TasksUiInternal.getTaskList().addTask(task, (AbstractTaskCategory) currentTarget);
}
} else if (currentTarget instanceof ITask) {
ITask targetTask = (ITask) currentTarget;
AbstractTaskCategory targetCategory = null;
// TODO: TaskCategory only used what about AbstractTaskCategory descendants?
ITaskContainer container = TaskCategory.getParentTaskCategory(targetTask);
if (container instanceof TaskCategory || container instanceof UncategorizedTaskContainer) {
targetCategory = (AbstractTaskCategory) container;
} else if (container instanceof UnmatchedTaskContainer) {
if (((UnmatchedTaskContainer) container).getRepositoryUrl().equals(task.getRepositoryUrl())) {
targetCategory = (AbstractTaskCategory) container;
}
}
if (targetCategory != null) {
TasksUiInternal.getTaskList().addTask(task, targetCategory);
}
} else if (currentTarget instanceof ScheduledTaskContainer) {
ScheduledTaskContainer container = (ScheduledTaskContainer) currentTarget;
if (container instanceof Unscheduled) {
TasksUiPlugin.getTaskActivityManager().setScheduledFor((AbstractTask) task, null);
} else {
TasksUiPlugin.getTaskActivityManager().setScheduledFor((AbstractTask) task,
container.getDateRange());
}
} else if (currentTarget == null) {
TasksUiInternal.getTaskList().addTask(newTask, TasksUiPlugin.getTaskList().getDefaultCategory());
}
}
}
// Make new task the current selection in the view
if (newTask != null) {
StructuredSelection ss = new StructuredSelection(newTask);
getViewer().setSelection(ss);
//getViewer().refresh();
}
return true;
}
private boolean areAllLocalTasks(List<ITask> tasksToMove) {
for (ITask task : tasksToMove) {
if (!(task instanceof LocalTask)) {
return false;
}
}
return true;
}
/**
* @return true if string is a http(s) url
*/
public boolean isUrl(Object data) {
String uri = "";
if (data instanceof String) {
uri = (String) data;
if ((uri.startsWith("http://") || uri.startsWith("https://"))) {
return true;
}
}
return false;
}
/**
* @param data
* string containing url and title separated by <quote>\n</quote>
* @return true if task succesfully created, false otherwise
*/
public boolean createTaskFromUrl(Object data) {
if (!(data instanceof String)) {
return false;
}
String[] urlTransfer = ((String) data).split("\n");
String url = "";
String urlTitle = "<retrieving from URL>";
if (urlTransfer.length > 0) {
url = urlTransfer[0];
} else {
return false;
}
AbstractRepositoryConnector connector = TasksUiPlugin.getRepositoryManager().getConnectorForRepositoryTaskUrl(
url);
if (connector != null) {
String repositoryUrl = connector.getRepositoryUrlFromTaskUrl(url);
String id = connector.getTaskIdFromTaskUrl(url);
if (repositoryUrl == null || id == null) {
return false;
}
for (TaskRepository repository : TasksUi.getRepositoryManager().getRepositories(
connector.getConnectorKind())) {
if (repository.getRepositoryUrl().equals(repositoryUrl)) {
try {
newTask = (AbstractTask) TasksUiInternal.createTask(repository, id, new NullProgressMonitor());
TasksUiInternal.refreshAndOpenTaskListElement(newTask);
return true;
} catch (CoreException e) {
StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not create task", e));
return false;
}
}
}
return false;
} else {
// Removed in order to default to retrieving title from url rather
// than
// accepting what was sent by the brower's DnD code. (see bug
// 114401)
// If a Title is provided, use it.
// if (urlTransfer.length > 1) {
// urlTitle = urlTransfer[1];
// }
// if (urlTransfer.length < 2) { // no title provided
// retrieveTaskDescription(url);
// }
retrieveTaskDescription(url);
newTask = TasksUiInternal.createNewLocalTask(urlTitle);
if (newTask == null) {
return false;
}
newTask.setUrl(url);
TasksUiUtil.openTask(newTask);
return true;
}
}
public boolean createTaskFromString(String title) {
//newTask = new Task(TasksUiPlugin.getTaskListManager().genUniqueTaskHandle(), title);
newTask = TasksUiInternal.createNewLocalTask(title);
if (newTask == null) {
return false;
} else {
//newTask.setPriority(Task.PriorityLevel.P3.toString());
TasksUiUtil.openTask(newTask);
return true;
}
}
@Override
public boolean validateDrop(Object targetObject, int operation, TransferData transferType) {
currentTransfer = transferType;
if (FileTransfer.getInstance().isSupportedType(currentTransfer)) {
// handle all files
return true;
} else if (TaskTransfer.getInstance().isSupportedType(currentTransfer)) {
if (getCurrentTarget() instanceof UncategorizedTaskContainer || getCurrentTarget() instanceof TaskCategory
|| getCurrentTarget() instanceof UnmatchedTaskContainer
|| getCurrentTarget() instanceof ScheduledTaskContainer) {
return true;
} else if (getCurrentTarget() instanceof ITaskContainer
&& (getCurrentLocation() == ViewerDropAdapter.LOCATION_AFTER || getCurrentLocation() == ViewerDropAdapter.LOCATION_BEFORE)) {
return true;
} else if (getCurrentTarget() instanceof LocalTask
&& getCurrentLocation() == ViewerDropAdapter.LOCATION_ON
&& TasksUiPlugin.getDefault().getPreferenceStore().getBoolean(
ITasksUiPreferenceConstants.LOCAL_SUB_TASKS_ENABLED)) {
return true;
} else {
return false;
}
}
return TextTransfer.getInstance().isSupportedType(transferType);
}
/**
* Attempts to set the task pageTitle to the title from the specified url
*/
protected void retrieveTaskDescription(final String url) {
try {
AbstractRetrieveTitleFromUrlJob job = new AbstractRetrieveTitleFromUrlJob(url) {
@Override
protected void titleRetrieved(final String pageTitle) {
newTask.setSummary(pageTitle);
TasksUiInternal.getTaskList().notifyElementChanged(newTask);
}
};
job.schedule();
} catch (RuntimeException e) {
// FIXME what exception is caught here?
StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Could not open task web page", e));
}
}
}