Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 211068 Details for
Bug 370283
[api] allow clients to be notified of drop events in the task list
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
patch
clipboard.txt (text/plain), 20.87 KB, created by
Sam Davis
on 2012-02-15 14:21:48 EST
(
hide
)
Description:
patch
Filename:
MIME Type:
Creator:
Sam Davis
Created:
2012-02-15 14:21:48 EST
Size:
20.87 KB
patch
obsolete
>diff --git a/org.eclipse.mylyn.tasks.ui/plugin.xml b/org.eclipse.mylyn.tasks.ui/plugin.xml >index 7c6ea0c..cc7b005 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 0000000..8b55062 >--- /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 35c9be8..bb69ecf 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 @@ > } > // 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 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 0000000..f72fa91 >--- /dev/null >+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TaskDropHandler.java >@@ -0,0 +1,62 @@ >+/******************************************************************************* >+ * 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; >+ >+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/TasksUiInternal.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiInternal.java >index 4d93e1a..70f9034 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 @@ > > 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 @@ > && 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 cee178f..b290fd0 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.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 @@ > * @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 @@ > } > > @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 @@ > } > } > } 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 @@ > 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 0000000..fe88a1c >--- /dev/null >+++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/TaskDropListener.java >@@ -0,0 +1,72 @@ >+/******************************************************************************* >+ * 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 extensin 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 >+ */ >+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 965d6f0..9ba55ab 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.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 @@ > } > > 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);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 370283
:
210344
|
210345
|
210391
| 211068