diff options
author | Sam Davis | 2012-02-15 23:31:41 +0000 |
---|---|---|
committer | Steffen Pingel | 2012-02-15 23:31:41 +0000 |
commit | 89aa41132c570c96eb9eb0a4c03cf67c7f99532c (patch) | |
tree | 86d8af9d17f816e769b6edc5a70e04d402b67f36 /org.eclipse.mylyn.tasks.ui | |
parent | 0bcb41110f882073ae9a96bb5a1ded863df48a01 (diff) | |
download | org.eclipse.mylyn.tasks-89aa41132c570c96eb9eb0a4c03cf67c7f99532c.tar.gz org.eclipse.mylyn.tasks-89aa41132c570c96eb9eb0a4c03cf67c7f99532c.tar.xz org.eclipse.mylyn.tasks-89aa41132c570c96eb9eb0a4c03cf67c7f99532c.zip |
NEW - bug 370283: [api] allow clients to be notified of drop events in
the task list
https://bugs.eclipse.org/bugs/show_bug.cgi?id=370283
Change-Id: I05ed4d215f9d72895d9cc70ce8db6ed9ffb1721b
Diffstat (limited to 'org.eclipse.mylyn.tasks.ui')
9 files changed, 323 insertions, 51 deletions
diff --git a/org.eclipse.mylyn.tasks.ui/plugin.xml b/org.eclipse.mylyn.tasks.ui/plugin.xml index 2f9ac4248..37ae06db1 100644 --- a/org.eclipse.mylyn.tasks.ui/plugin.xml +++ b/org.eclipse.mylyn.tasks.ui/plugin.xml @@ -22,6 +22,7 @@ <extension-point id="taskEditorPageContribution" name="Task Editor Page Contribution" schema="schema/taskEditorPageContribution.exsd"/> <extension-point id="searchProvider" name="Search Handling Provider" schema="schema/searchProvider.exsd"/> <extension-point id="searchHandler" name="Search Handler" schema="schema/searchHandler.exsd"/> + <extension-point id="taskDropListener" name="Task Drop Listener" schema="schema/taskDropListener.exsd"/> <extension point="org.eclipse.mylyn.context.core.bridges"> diff --git a/org.eclipse.mylyn.tasks.ui/schema/taskDropListener.exsd b/org.eclipse.mylyn.tasks.ui/schema/taskDropListener.exsd new file mode 100644 index 000000000..24b66bde6 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/schema/taskDropListener.exsd @@ -0,0 +1,102 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.mylyn.tasks.ui" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appInfo> + <meta.schema plugin="org.eclipse.mylyn.tasks.ui" id="taskDropListener" name="Task Drop Listener"/> + </appInfo> + <documentation> + Allows clients to be notified when a task is dropped onto another task. + </documentation> + </annotation> + + <element name="extension"> + <annotation> + <appInfo> + <meta.element internal="true" /> + </appInfo> + </annotation> + <complexType> + <sequence minOccurs="1" maxOccurs="unbounded"> + <element ref="listener"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="listener"> + <complexType> + <attribute name="class" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn="org.eclipse.mylyn.internal.tasks.ui.TaskDropListener:"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + [Enter the first release in which this extension point appears.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="examples"/> + </appInfo> + <documentation> + [Enter extension point usage example here.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="apiinfo"/> + </appInfo> + <documentation> + [Enter API information here.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="implementation"/> + </appInfo> + <documentation> + [Enter information about supplied implementation of this extension point.] + </documentation> + </annotation> + + +</schema> diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskAttachmentDropListener.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskAttachmentDropListener.java index 35c9be88a..bb69ecf5e 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskAttachmentDropListener.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/editors/TaskAttachmentDropListener.java @@ -14,11 +14,17 @@ package org.eclipse.mylyn.internal.tasks.ui.editors; import java.io.File; +import java.util.List; import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.ISelection; import org.eclipse.mylyn.internal.tasks.core.data.FileTaskAttachmentSource; import org.eclipse.mylyn.internal.tasks.core.data.TextTaskAttachmentSource; +import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal; import org.eclipse.mylyn.internal.tasks.ui.wizards.NewAttachmentWizardDialog; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.ui.TaskDropListener.Operation; import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DropTargetEvent; @@ -50,9 +56,10 @@ public class TaskAttachmentDropListener implements DropTargetListener { } // will accept text but prefer to have files dropped for (TransferData dataType : event.dataTypes) { - if (FileTransfer.getInstance().isSupportedType(dataType)) { + if (LocalSelectionTransfer.getTransfer().isSupportedType(dataType) + || FileTransfer.getInstance().isSupportedType(dataType)) { event.currentDataType = dataType; - // files should only be copied + // files and tasks should only be copied if (event.detail != DND.DROP_COPY) { event.detail = DND.DROP_NONE; } @@ -86,6 +93,15 @@ public class TaskAttachmentDropListener implements DropTargetListener { } public void drop(DropTargetEvent event) { + if (LocalSelectionTransfer.getTransfer().isSupportedType(event.currentDataType)) { + TasksUiInternal.getTaskDropHandler().loadTaskDropListeners(); + ISelection selection = LocalSelectionTransfer.getTransfer().getSelection(); + List<ITask> tasksToMove = TasksUiInternal.getTasksFromSelection(selection); + if (!tasksToMove.isEmpty()) { + TasksUiInternal.getTaskDropHandler().fireTaskDropped(tasksToMove, page.getTask(), + Operation.DROP_ON_TASK_EDITOR); + } + } if (TextTransfer.getInstance().isSupportedType(event.currentDataType)) { String text = (String) event.data; EditorUtil.openNewAttachmentWizard(page, null, new TextTaskAttachmentSource(text)); diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TaskDropHandler.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TaskDropHandler.java new file mode 100644 index 000000000..21f556aa7 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TaskDropHandler.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2012 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui.util; + +import java.util.List; + +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.commons.core.ExtensionPointReader; +import org.eclipse.mylyn.commons.core.StatusHandler; +import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.ui.TaskDropListener; +import org.eclipse.mylyn.tasks.ui.TaskDropListener.TaskDropEvent; + +/** + * @author Sam Davis + */ +public class TaskDropHandler { + + private List<TaskDropListener> taskDropListeners; + + TaskDropHandler() {// package visible + } + + public void loadTaskDropListeners() { + if (taskDropListeners == null) { + ExtensionPointReader<TaskDropListener> reader = new ExtensionPointReader<TaskDropListener>( + TasksUiPlugin.ID_PLUGIN, "taskDropListener", "listener", TaskDropListener.class); //$NON-NLS-1$//$NON-NLS-2$ + IStatus status = reader.read(); + if (!status.isOK()) { + StatusHandler.log(status); + } + taskDropListeners = reader.getItems(); + } + } + + public void fireTaskDropped(final List<ITask> tasksToMove, final ITask currentTarget, + TaskDropListener.Operation operation) { + final TaskDropEvent event = new TaskDropEvent(tasksToMove, currentTarget, operation); + for (final TaskDropListener listener : taskDropListeners) { + SafeRunner.run(new ISafeRunnable() { + public void run() throws Exception { + listener.tasksDropped(event); + } + + public void handleException(Throwable exception) { + StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, exception.getMessage(), + exception)); + } + }); + } + } + +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TaskOpenEvent.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TaskOpenEvent.java Binary files differindex 2b62f9afe..180155958 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TaskOpenEvent.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TaskOpenEvent.java diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java index 4d93e1abc..70f9034be 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java @@ -149,6 +149,8 @@ public class TasksUiInternal { private static SynchronizationScheduler synchronizationScheduler = new SynchronizationScheduler(); + private static final TaskDropHandler taskDropHandler = new TaskDropHandler(); + // TODO e3.5 replace by SWT.SHEET public static final int SWT_SHEET = 1 << 28; @@ -1440,4 +1442,8 @@ public class TasksUiInternal { && MonitorUiPlugin.getDefault().isActivityTrackingEnabled(); } + public static TaskDropHandler getTaskDropHandler() { + return taskDropHandler; + } + } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListDropAdapter.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListDropAdapter.java index cee178f13..b290fd06a 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListDropAdapter.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListDropAdapter.java @@ -38,9 +38,9 @@ import org.eclipse.mylyn.internal.tasks.ui.views.TaskScheduleContentProvider.Uns 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.ui.TaskDropListener.Operation; 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; @@ -51,6 +51,7 @@ import org.eclipse.ui.PlatformUI; * @author Mik Kersten * @author Rob Elves (added URL based task creation support) * @author Jevgeni Holodkov + * @author Sam Davis */ public class TaskListDropAdapter extends ViewerDropAdapter { @@ -64,18 +65,8 @@ public class TaskListDropAdapter extends ViewerDropAdapter { } @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) { List<ITask> tasksToMove = new ArrayList<ITask>(); - if (localTransfer) { ISelection selection = LocalSelectionTransfer.getTransfer().getSelection(); List<ITask> tasks = TasksUiInternal.getTasksFromSelection(selection); @@ -107,49 +98,57 @@ public class TaskListDropAdapter extends ViewerDropAdapter { } } } else { - for (ITask task : tasksToMove) { - if (currentTarget instanceof UncategorizedTaskContainer) { - moveTask(task, (UncategorizedTaskContainer) currentTarget); - } else if (currentTarget instanceof TaskCategory) { - moveTask(task, (TaskCategory) currentTarget); - } else if (currentTarget instanceof UnmatchedTaskContainer) { - if (((UnmatchedTaskContainer) currentTarget).getRepositoryUrl().equals(task.getRepositoryUrl())) { - moveTask(task, (AbstractTaskCategory) currentTarget); - } - } else if (currentTarget instanceof ITask) { - ITask targetTask = (ITask) currentTarget; - TaskListView view = TaskListView.getFromActivePerspective(); - if ((getCurrentLocation() == LOCATION_BEFORE || getCurrentLocation() == LOCATION_AFTER) - && view != null && view.isScheduledPresentation()) { - if (targetTask instanceof AbstractTask) { - DateRange targetDate = ((AbstractTask) targetTask).getScheduledForDate(); - TasksUiPlugin.getTaskActivityManager().setScheduledFor((AbstractTask) task, targetDate); + if (currentTarget instanceof ITask && getCurrentLocation() == ViewerDropAdapter.LOCATION_ON + && getCurrentOperation() != DND.DROP_MOVE) { + TasksUiInternal.getTaskDropHandler().loadTaskDropListeners(); + Operation operation = (getCurrentOperation() == DND.DROP_COPY) ? Operation.COPY : Operation.LINK; + TasksUiInternal.getTaskDropHandler().fireTaskDropped(tasksToMove, (ITask) currentTarget, operation); + } else { + for (ITask task : tasksToMove) { + if (currentTarget instanceof UncategorizedTaskContainer) { + moveTask(task, (UncategorizedTaskContainer) currentTarget); + } else if (currentTarget instanceof TaskCategory) { + moveTask(task, (TaskCategory) currentTarget); + } else if (currentTarget instanceof UnmatchedTaskContainer) { + if (((UnmatchedTaskContainer) currentTarget).getRepositoryUrl().equals(task.getRepositoryUrl())) { + moveTask(task, (AbstractTaskCategory) currentTarget); } - } else { - 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())) { + } else if (currentTarget instanceof ITask) { + ITask targetTask = (ITask) currentTarget; + TaskListView view = TaskListView.getFromActivePerspective(); + if ((getCurrentLocation() == LOCATION_BEFORE || getCurrentLocation() == LOCATION_AFTER) + && view != null && view.isScheduledPresentation()) { + if (targetTask instanceof AbstractTask) { + DateRange targetDate = ((AbstractTask) targetTask).getScheduledForDate(); + TasksUiPlugin.getTaskActivityManager().setScheduledFor((AbstractTask) task, targetDate); + } + } else { + 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) { + moveTask(task, targetCategory); } } - if (targetCategory != null) { - moveTask(task, targetCategory); + } else if (currentTarget instanceof ScheduledTaskContainer) { + ScheduledTaskContainer container = (ScheduledTaskContainer) currentTarget; + if (container instanceof Unscheduled) { + TasksUiPlugin.getTaskActivityManager().setScheduledFor((AbstractTask) task, null); + } else if (isValidTarget(container)) { + TasksUiPlugin.getTaskActivityManager().setScheduledFor((AbstractTask) task, + container.getDateRange()); } + } else if (currentTarget == null) { + moveTask(task, TasksUiPlugin.getTaskList().getDefaultCategory()); } - } else if (currentTarget instanceof ScheduledTaskContainer) { - ScheduledTaskContainer container = (ScheduledTaskContainer) currentTarget; - if (container instanceof Unscheduled) { - TasksUiPlugin.getTaskActivityManager().setScheduledFor((AbstractTask) task, null); - } else if (isValidTarget(container)) { - TasksUiPlugin.getTaskActivityManager().setScheduledFor((AbstractTask) task, - container.getDateRange()); - } - } else if (currentTarget == null) { - moveTask(task, TasksUiPlugin.getTaskList().getDefaultCategory()); } } } @@ -260,6 +259,9 @@ public class TaskListDropAdapter extends ViewerDropAdapter { return true; } else if (target instanceof LocalTask && getCurrentLocation() == ViewerDropAdapter.LOCATION_ON) { return true; + } else if (target instanceof ITask && getCurrentLocation() == ViewerDropAdapter.LOCATION_ON + && getCurrentOperation() != DND.DROP_MOVE) { + return true; } else { return false; } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/TaskDropListener.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/TaskDropListener.java new file mode 100644 index 000000000..8171f872f --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/TaskDropListener.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2012 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 + *******************************************************************************/ + +package org.eclipse.mylyn.tasks.ui; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import org.eclipse.mylyn.tasks.core.ITask; + +/** + * Clients can contribute an extension of this class to be notified when one task is dropped on a repository task in the + * task list, or when a task is dropped on a task editor. + * + * @author Sam Davis + * @since 3.7 + */ +public abstract class TaskDropListener { + + public static enum Operation { + COPY, LINK, DROP_ON_TASK_EDITOR + }; + + public static class TaskDropEvent { + + private final Collection<ITask> tasks; + + private final ITask target; + + private final Operation operation; + + public TaskDropEvent(Collection<ITask> tasks, ITask target, Operation operation) { + this.tasks = Collections.unmodifiableList(new ArrayList<ITask>(tasks)); + this.target = target; + this.operation = operation; + } + + /** + * @return the tasks that were dropped + */ + public Collection<ITask> getTasks() { + return tasks; + } + + /** + * @return the target task + */ + public ITask getTarget() { + return target; + } + + /** + * @return the drop operation that triggered this event + */ + public Operation getOperation() { + return operation; + } + + } + + /** + * Called when a task drop event occurs. + * + * @param event + */ + public abstract void tasksDropped(TaskDropEvent event); + +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java index 965d6f075..9ba55ab8e 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/AbstractTaskEditorPage.java @@ -41,6 +41,7 @@ import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.util.LocalSelectionTransfer; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; @@ -1487,9 +1488,10 @@ public abstract class AbstractTaskEditorPage extends TaskFormPage implements ISe } DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_DEFAULT); + LocalSelectionTransfer localSelectionTransfer = LocalSelectionTransfer.getTransfer(); final TextTransfer textTransfer = TextTransfer.getInstance(); final FileTransfer fileTransfer = FileTransfer.getInstance(); - Transfer[] types = new Transfer[] { textTransfer, fileTransfer }; + Transfer[] types = new Transfer[] { localSelectionTransfer, textTransfer, fileTransfer }; target.setTransfer(types); if (defaultDropListener == null) { defaultDropListener = new TaskAttachmentDropListener(this); |