blob: bc45b31eea1cd8f4fade1849545aca05892bfacc [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2003, 2010 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.lang.ref.WeakReference;
import org.eclipse.swt.dnd.DropTargetEvent;
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.ITransferAgent;
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.core.DropListenerContext;
/**
* Parent of all the transfer drop target adapters. Every transfer type drop
* target adapter should override the methods in the
* <code>DropTargetListener</code> interface.
*
* @author Vishy Ramaswamy
*/
public class TransferDropTargetAdapter
implements ITransferDropTargetListener {
/**
* Attribute for the drop target listener.
*/
private IDropTargetListener listener;
/**
* Attribute for the transfer agent.
*/
private final ITransferAgent transferAgent;
/**
* Attribute for the drop target context.
*/
private WeakReference<IDropTargetContext> context;
/**
* Attribute for the current event
*/
private final org.eclipse.gmf.runtime.common.ui.services.dnd.drop.DropTargetEvent currentEvent;
/**
* Constructor for TransferDropTargetAdapter.
*
* @param aTransferAgent
* The transfer agent
*/
public TransferDropTargetAdapter(ITransferAgent aTransferAgent) {
super();
assert null != aTransferAgent : "aTransferAgent cannot be null"; //$NON-NLS-1$
this.listener = null;
this.transferAgent = aTransferAgent;
this.context = null;
this.currentEvent = new org.eclipse.gmf.runtime.common.ui.services.dnd.drop.DropTargetEvent();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#dragEnter(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragEnter(DropTargetEvent event) {
if (listener != null) {
/* Send the event to the selected listener */
listener.setFeedback(event);
/* Send the event to the selected listener */
listener.dragEnter(event);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#dragLeave(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragLeave(DropTargetEvent event) {
/* Send the event to the selected listener */
if (listener != null) {
listener.dragLeave(event);
}
listener = null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragOperationChanged(DropTargetEvent event) {
/* Send the event to the selected listener */
if (listener != null) {
listener.dragOperationChanged(event);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#dragOver(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragOver(DropTargetEvent event) {
/* Send the event to the selected listener */
if (listener != null) {
/* Send the event to the selected listener */
listener.setFeedback(event);
/* Send the event to the selected listener */
listener.dragOver(event);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#drop(org.eclipse.swt.dnd.DropTargetEvent)
*/
public final void drop(DropTargetEvent event) {
/* Send the event to the selected listener */
if (listener != null) {
/* Send the event to the selected listener */
listener.drop(event);
}
listener = null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.dnd.DropTargetListener#dropAccept(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dropAccept(DropTargetEvent event) {
/* Set the event to the selected listener */
if (listener != null) {
listener.dropAccept(event);
}
}
/**
* Returns the listener.
*
* @return IDropTargetListener
*/
protected final IDropTargetListener getListener() {
return listener;
}
/**
* Returns the context.
*
* @return IDropTargetContext
*/
protected final IDropTargetContext getContext() {
if(context == null) return null;
return context.get();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gmf.runtime.common.ui.services.dnd.drop.ITransferDropTargetListener#init(org.eclipse.gmf.runtime.common.ui.services.dnd.drop.IDropTargetContext)
*/
public final void init(IDropTargetContext initialContext) {
assert null != initialContext : "initialContext cannot be null"; //$NON-NLS-1$
this.context = new WeakReference<IDropTargetContext>(initialContext);
}
/**
* Returns the transfer agent.
*
* @return ITransferAgent
*/
public final ITransferAgent getTransferAgent() {
return transferAgent;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gmf.runtime.common.ui.services.dnd.drop.ITransferDropTargetListener#canSupport(org.eclipse.swt.dnd.DropTargetEvent)
*/
public boolean canSupport(DropTargetEvent event) {
if (Trace.shouldTrace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND)) {
Trace.trace(CommonUIServicesDNDPlugin.getDefault(),
CommonUIServicesDNDDebugOptions.DND,
"canSupport::Adapter is " + getClass().getName()); //$NON-NLS-1$
}
/*
* Check if one of the transfer data can be supported by this transfer
* and if a supporting listener is available
*/
return canSupportTransferData(event) && isSupportingListenerAvailable();
}
/**
* Check if a supporting listener is available.It also updates the current
* listener cache.
*
* @return boolean true or false
*/
protected final boolean isSupportingListenerAvailable() {
/* Get the listeners if any for the adapter's transfer type */
IDropTargetListener[] listeners = getListeners(false);
/* Get a compatible one if no listener is found for a direct match */
if (listeners == null || listeners.length == 0) {
listeners = getListeners(true);
}
/* Choose the current listener */
if (listeners != null) {
CommonUIServicesDNDPlugin plugin = CommonUIServicesDNDPlugin
.getDefault();
boolean shouldTrace = Trace.shouldTrace(plugin,
CommonUIServicesDNDDebugOptions.DND);
for (int i = 0; i < listeners.length; ++i) {
try {
/* Update the listener */
listener = listeners[i];
if (listener.canSupport(getContext(), currentEvent,
transferAgent)) {
if (shouldTrace) {
Trace
.trace(
plugin,
CommonUIServicesDNDDebugOptions.DND,
"isSupportingListenerAvailable::Chosen listener is " + listener.getClass().getName()); //$NON-NLS-1$
}
return true;
}
} catch (RuntimeException e) {
if (shouldTrace) {
Trace.catching(plugin,
CommonUIServicesDNDDebugOptions.DND, getClass(),
"isSupportingListenerAvailable", e); //$NON-NLS-1$
}
Log
.warning(
plugin,
CommonUIServicesDNDStatusCodes.IGNORED_EXCEPTION_WARNING,
"Drop Listener " + listeners[i].getClass().getName(), e); //$NON-NLS-1$
}
}
}
/* Set the listener back to null */
listener = null;
return false;
}
/**
* Checks if the transfer agent can support one of the transfer datas passed
* into the event. It also updates the internal current event cache and sets
* the current data type on the current event.
*
* @param event
* the drop target event
* @return boolean true or false
*/
protected final boolean canSupportTransferData(DropTargetEvent event) {
/* Update the current event */
currentEvent.setEvent(event);
Transfer transfer = transferAgent.getTransfer();
for (int i = 0; i < event.dataTypes.length; ++i) {
TransferData dataType = event.dataTypes[i];
if (transfer.isSupportedType(dataType)) {
/* Set the current data type */
event.currentDataType = dataType;
return true;
}
}
return false;
}
/**
* Returns the drop target listeners for the current context.
*
* @param isCompatible
* should compatible listeners be considered
* @return IDropTargetListener[] the drop target listeners
*/
private final IDropTargetListener[] getListeners(boolean isCompatible) {
/* Get the drop target listeners */
IDropTargetListener[] listeners = DragDropListenerService.getInstance()
.getDropTargetListeners(
new DropListenerContext(getContext().getActivePart(), getContext()
.getCurrentTarget().getClass(), transferAgent
.getTransferId(), isCompatible));
return listeners;
}
}