| /****************************************************************************** |
| * 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()); |
| |
| } |
| |
| } |
| } |