blob: 8a15efc75c1224c23319ec836847b091eff2ee22 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2002, 2006 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:
* IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.runtime.common.ui.services.dnd.drop;
import java.util.ArrayList;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.gmf.runtime.common.core.util.Log;
import org.eclipse.gmf.runtime.common.core.util.Trace;
import org.eclipse.gmf.runtime.common.ui.services.dnd.core.DragDropListenerService;
import org.eclipse.gmf.runtime.common.ui.services.dnd.core.IListenerContext;
import org.eclipse.gmf.runtime.common.ui.services.dnd.core.TransferAdapterService;
import org.eclipse.gmf.runtime.common.ui.services.dnd.internal.CommonUIServicesDNDDebugOptions;
import org.eclipse.gmf.runtime.common.ui.services.dnd.internal.CommonUIServicesDNDPlugin;
import org.eclipse.gmf.runtime.common.ui.services.dnd.internal.CommonUIServicesDNDStatusCodes;
import org.eclipse.gmf.runtime.common.ui.services.dnd.internal.l10n.CommonUIServicesDNDMessages;
/**
* This class delegates all the drop target events to the transfer drop target
* adapter. The transfer adapter delegates to the registered listeners
*
* @author Vishy Ramaswamy
*/
public class DelegatingDropTargetAdapter
implements DropTargetListener {
/**
* Attribute for the error message
*/
//private static final String ERROR_MSG = ResourceManager
// .getI18NString("DelegatingDropTargetAdapter.errorMessage"); //$NON-NLS-1$
/**
* Attribute for the error message for logging
*/
//private static final String ERROR_MSG_LOG = ResourceManager
// .getI18NString("DelegatingDropTargetAdapter._ERROR_.errorMessage"); //$NON-NLS-1$
/**
* Attribute for the transfer drop target adapters.
*/
private ITransferDropTargetListener[] adapters = null;
/**
* Attribute for the current transfer drop target adapter.
*/
private ITransferDropTargetListener chosenAdapter = null;
/**
* Attribute for the drop target context.
*/
private final DropTargetContext context;
/**
* Attribute for the original drop event type.
*/
private int origDropType = DND.DROP_NONE;
/**
* Attribute for the current drop event type.
*/
private int currentDropType = DND.DROP_NONE;
/**
* Constructor for DelegatingDropTargetAdapter.
*
* @param aContext
* context information for the drop target
*/
public DelegatingDropTargetAdapter(DropTargetContext aContext) {
super();
assert null != aContext : "context information for the drop target cannot be null"; //$NON-NLS-1$
this.context = aContext;
/* Set the adapters */
adapters = getAllTransferAdapters();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#dragEnter(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragEnter(DropTargetEvent event) {
try {
/* Set the original drop type */
setOrigDropType(event.detail);
/* Set the current target and location */
getContext().setCurrentTargetAndLocation(event);
/*
* Re-Initialize the Transfer Adapters with dynamically with the
* correct context
*/
initAdapters();
/* Set the chosen adapter */
setChosenAdapter(event);
/* Check if a chosen adapter exists */
if (getChosenAdapter() != null) {
getChosenAdapter().dragEnter(event);
} else {
/* Delegate to the drop target */
getContext().dragEnter(event);
}
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND)) {
String adapterChosen = getChosenAdapter() != null ? getChosenAdapter()
.getClass().getName()
: "No Adapter"; //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"DragEnter::Event detail is " + event.detail); //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"DragEnter::Chosen adapter is " + adapterChosen); //$NON-NLS-1$
}
} catch (Throwable e) {
event.detail = DND.DROP_NONE;
handle(e, false);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#dragLeave(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragLeave(DropTargetEvent event) {
try {
/* Check if a chosen adapter exists */
if (getChosenAdapter() != null) {
getChosenAdapter().dragLeave(event);
} else {
/* Delegate to the drop target */
getContext().dragLeave(event);
}
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND)) {
String adapterChosen = getChosenAdapter() != null ? getChosenAdapter()
.getClass().getName()
: "No Adapter"; //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"DragLeave::Event detail is " + event.detail); //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"DragLeave::Chosen adapter is " + adapterChosen); //$NON-NLS-1$
}
} catch (Throwable e) {
handle(e, false);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragOperationChanged(DropTargetEvent event) {
try {
/* Set the original drop type */
setOrigDropType(event.detail);
/* Set the current target and location */
getContext().setCurrentTargetAndLocation(event);
/* Set the chosen adapter */
setChosenAdapter(event);
/* Check if a chosen adapter exists */
if (getChosenAdapter() != null) {
getChosenAdapter().dragOperationChanged(event);
} else {
/* Delegate to the drop target */
getContext().dragOperationChanged(event);
}
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND)) {
String adapterChosen = getChosenAdapter() != null ? getChosenAdapter()
.getClass().getName()
: "No Adapter"; //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"DragOperationChanged::Event detail is " + event.detail); //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"DragOperationChanged::Chosen adapter is " + adapterChosen); //$NON-NLS-1$
}
} catch (Throwable e) {
event.detail = DND.DROP_NONE;
handle(e, false);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#dragOver(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragOver(DropTargetEvent event) {
try {
/* Set the current target and location */
getContext().setCurrentTargetAndLocation(event);
/* Set the event detail as the original drop type */
event.detail = getOrigDropType();
/* Set the chosen adapter */
setChosenAdapter(event);
/* Check if a chosen adapter exists */
if (getChosenAdapter() != null) {
getChosenAdapter().dragOver(event);
/* Check the event detail */
if (event.detail != DND.DROP_NONE) {
setCurrentDropType(event.detail);
}
} else {
/* Delegate to the drop target */
getContext().dragOver(event);
}
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND)) {
String adapterChosen = getChosenAdapter() != null ? getChosenAdapter()
.getClass().getName()
: "No Adapter"; //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"DragOver::Event detail is " + event.detail); //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"DragOver::Chosen adapter is " + adapterChosen); //$NON-NLS-1$
}
} catch (Throwable e) {
event.detail = DND.DROP_NONE;
handle(e, false);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#drop(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void drop(DropTargetEvent event) {
try {
/*
* Save the event detail just in case the event has to be delegated
* to the drop target
*/
int oldDetail = event.detail;
/* Set the current target and location */
getContext().setCurrentTargetAndLocation(event);
/* Set the event detail as the current drop type */
event.detail = getCurrentDropType();
/* Set the chosen adapter */
setChosenAdapter(event);
/* Check if a chosen adapter exists */
if (getChosenAdapter() != null) {
getChosenAdapter().drop(event);
} else {
event.detail = oldDetail;
/* Delegate to the drop target */
getContext().drop(event);
}
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND)) {
String adapterChosen = getChosenAdapter() != null ? getChosenAdapter()
.getClass().getName()
: "No Adapter"; //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"Drop::Event detail is " + event.detail); //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"Drop::Chosen adapter is " + adapterChosen); //$NON-NLS-1$
}
} catch (Throwable e) {
event.detail = DND.DROP_NONE;
handle(e, true);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#dropAccept(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dropAccept(DropTargetEvent event) {
try {
/*
* Save the event detail just in case the event has to be delegated
* to the drop target
*/
int oldDetail = event.detail;
/* Set the current target and location */
getContext().setCurrentTargetAndLocation(event);
/* Set the event detail as the original drop type */
event.detail = getCurrentDropType();
/* Set the chosen adapter */
setChosenAdapter(event);
/* Check if a chosen adapter exists */
if (getChosenAdapter() != null) {
getChosenAdapter().dropAccept(event);
/* Check the event detail */
if (event.detail != getCurrentDropType()) {
setCurrentDropType(event.detail);
}
} else {
event.detail = oldDetail;
/* Delegate to the drop target */
getContext().dropAccept(event);
}
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND)) {
String adapterChosen = getChosenAdapter() != null ? getChosenAdapter()
.getClass().getName()
: "No Adapter"; //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"DropAccept::Event detail is " + event.detail); //$NON-NLS-1$
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"DropAccept::Chosen adapter is " + adapterChosen); //$NON-NLS-1$
}
} catch (Throwable e) {
event.detail = DND.DROP_NONE;
handle(e, false);
}
}
/**
* Returns the adapters.
*
* @return ITransferDropTargetListener[]
*/
private ITransferDropTargetListener[] getAdapters() {
return adapters;
}
/**
* Returns the drop target context.
*
* @return DropTargetContext
*/
private DropTargetContext getContext() {
return context;
}
/**
* Returns the set of registered transfer agents. This is determined from
* the drop target service.
*
* @return Transfer[] an array of transfer agents
*/
public Transfer[] getAllTransferAgents() {
/* Return null if no registered agents */
if (getAdapters() == null || getAdapters().length == 0) {
return null;
}
/* Get the transfers */
ArrayList list = new ArrayList();
for (int i = 0; i < getAdapters().length; i++) {
list.add(getAdapters()[i].getTransferAgent().getTransfer());
}
return (Transfer[]) list.toArray(new Transfer[list.size()]);
}
/**
* Returns the set of transfer drop target adapters. The adapters are
* created based on the provided transfer ids determined from the drag and
* drop service.
*
* @return ITransferDropTargetListener[] an array of transfer adapters
*/
private ITransferDropTargetListener[] getAllTransferAdapters() {
/* Create placeholder for possible adapters */
ArrayList listOfSupportedAdapters = new ArrayList();
/* Get the ids from the drag and drop service */
String[] transferIds = DragDropListenerService.getInstance()
.getAllTransferIds(getContext().getActivePart().getSite().getId(),
IListenerContext.DROP);
/* Iterate through the ids */
if (transferIds == null || transferIds.length == 0) {
return null;
}
/* Create the adapters */
for (int i = 0; i < transferIds.length; i++) {
ITransferDropTargetListener adapter = TransferAdapterService
.getInstance().getTransferDropTargetAdapter(transferIds[i]);
if (adapter != null) {
listOfSupportedAdapters.add(adapter);
}
}
/* Return the adapters */
return !listOfSupportedAdapters.isEmpty() ? (ITransferDropTargetListener[]) listOfSupportedAdapters
.toArray(new ITransferDropTargetListener[listOfSupportedAdapters
.size()])
: null;
}
/**
* Set the chosen adapter.
*
* @param event
* the event
*/
private void setChosenAdapter(DropTargetEvent event) {
/* Set the chosen adapter to null */
chosenAdapter = null;
/* Get the data types */
TransferData[] dataTypes = event.dataTypes;
if (dataTypes == null || dataTypes.length == 0) {
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND)) {
Trace
.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"setChosenAdapter::No transfer types available in the event"); //$NON-NLS-1$
}
return;
}
/* Check if there are any adapters */
if (getAdapters() == null) {
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND)) {
Trace
.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"setChosenAdapter::No adapters registered with this target"); //$NON-NLS-1$
}
return;
}
/* Check if the target is null */
if (getContext().getCurrentTarget() == null) {
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND)) {
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"setChosenAdapter::Current target is null"); //$NON-NLS-1$
}
return;
}
/*
* Preferably use the selection transfer for in-process drag and drop
* operations. Iterate through the adapters
*/
for (int i = 0; i < getAdapters().length; i++) {
if (getAdapters()[i].getTransferAgent().isSelectionType()) {
/* Check if the adapter can handle */
if (getAdapters()[i].canSupport(event)) {
/* Set the adapter */
chosenAdapter = getAdapters()[i];
return;
}
}
}
/* Iterate through the rest of the adapters */
for (int i = 0; i < getAdapters().length; i++) {
if (!getAdapters()[i].getTransferAgent().isSelectionType()) {
/* Check if the adapter can handle */
if (getAdapters()[i].canSupport(event)) {
/* Set the adapter */
chosenAdapter = getAdapters()[i];
return;
}
}
}
}
/**
* Returns the chosenAdapter.
*
* @return ITransferDropTargetListener
*/
private ITransferDropTargetListener getChosenAdapter() {
return chosenAdapter;
}
/**
* Handles the specified exception.
*
* @param exception
* The exception to be handled.
* @param displayDialog
* boolean to indicate whether to display dialog
*/
private void handle(Throwable exception, boolean displayDialog) {
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.EXCEPTIONS_CATCHING)) {
Trace.catching(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.EXCEPTIONS_CATCHING,
getClass(), "handle", exception); //$NON-NLS-1$
}
IStatus status = new Status(IStatus.ERROR, CommonUIServicesDNDPlugin
.getPluginId(), CommonUIServicesDNDStatusCodes.DROP_ACTION_FAILURE,
CommonUIServicesDNDMessages.DelegatingDropTargetAdapter__ERROR__errorMessage, exception);
Log.log(CommonUIServicesDNDPlugin.getDefault(), status);
if (displayDialog) {
status = new Status(IStatus.ERROR, CommonUIServicesDNDPlugin
.getPluginId(),
CommonUIServicesDNDStatusCodes.DROP_ACTION_FAILURE,
CommonUIServicesDNDMessages.DelegatingDropTargetAdapter_errorMessage,
exception);
ErrorDialog.openError(getContext().getActivePart().getSite()
.getShell(), null, null, status);
}
}
/**
* Return the original drop type
*
* @return int the drop type
*/
private int getOrigDropType() {
return origDropType;
}
/**
* Set the original drop type
*
* @param anOrigDropType
* the drop type
*/
private void setOrigDropType(int anOrigDropType) {
this.origDropType = anOrigDropType;
}
/**
* Return the current drop type
*
* @return int the drop type
*/
private int getCurrentDropType() {
return currentDropType;
}
/**
* Set the current drop type
*
* @param aCurrentDropType
* the drop type
*/
private void setCurrentDropType(int aCurrentDropType) {
this.currentDropType = aCurrentDropType;
}
/**
* Inititializes the transfer adapters' context
*/
private void initAdapters() {
/* Iterate through the adapters */
if (getAdapters() != null)
for (int i = 0; i < getAdapters().length; i++) {
/* Initialize the adapter */
getAdapters()[i].init(getContext());
}
}
}