| /****************************************************************************** |
| * Copyright (c) 2002, 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 java.lang.reflect.InvocationTargetException; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Vector; |
| |
| import org.eclipse.core.commands.ExecutionException; |
| import org.eclipse.core.commands.operations.IOperationHistory; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jface.dialogs.ProgressMonitorDialog; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.swt.custom.BusyIndicator; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.DropTargetEvent; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.IWorkbenchPartSite; |
| |
| import org.eclipse.gmf.runtime.common.core.command.ICommand; |
| import org.eclipse.gmf.runtime.common.core.util.EnumeratedType; |
| 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.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; |
| |
| /** |
| * Abstract parent of all the drop target listeners |
| * |
| * @author Vishy Ramaswamy |
| */ |
| public abstract class AbstractDropTargetListener |
| implements IDropTargetListener { |
| |
| /** |
| * Attribute for the drop target context. |
| */ |
| private WeakReference<IDropTargetContext> context = null; |
| |
| /** |
| * Attribute for the current transfer agent. |
| */ |
| private ITransferAgent currentAgent = null; |
| |
| /** |
| * Attribute for the current event. |
| */ |
| private IDropTargetEvent currentEvent = null; |
| |
| /** |
| * Attribute for the supporting transfer ids. |
| */ |
| private final List transferIds = new Vector(); |
| |
| /** |
| * Enumerated type for work indicator type |
| */ |
| public static class WorkIndicatorType |
| extends EnumeratedType { |
| |
| private static final long serialVersionUID = 1L; |
| |
| private static int nextOrdinal = 0; |
| |
| /** None work indicator type. */ |
| public static final WorkIndicatorType NONE = new WorkIndicatorType( |
| "None"); //$NON-NLS-1$ |
| |
| /** Busy work indicator type. */ |
| public static final WorkIndicatorType BUSY = new WorkIndicatorType( |
| "Busy"); //$NON-NLS-1$ |
| |
| /** Progress monitor indicator type. */ |
| public static final WorkIndicatorType PROGRESS_MONITOR = new WorkIndicatorType( |
| "Progress Monitor"); //$NON-NLS-1$ |
| |
| /** Cancelable progress monitor indicator type. */ |
| public static final WorkIndicatorType CANCELABLE_PROGRESS_MONITOR = new WorkIndicatorType( |
| "Cancelable Progress Monitor"); //$NON-NLS-1$ |
| |
| /** |
| * The list of values for this enumerated type. |
| */ |
| private static final WorkIndicatorType[] VALUES = {NONE, BUSY, |
| PROGRESS_MONITOR, CANCELABLE_PROGRESS_MONITOR}; |
| |
| /** |
| * Constructor for WorkIndicatorType. |
| * |
| * @param name |
| * The name for the WorkIndicatorType |
| * @param ordinal |
| * The ordinal for theWorkIndicatorType |
| */ |
| protected WorkIndicatorType(String name, int ordinal) { |
| super(name, ordinal); |
| } |
| |
| /** |
| * Constructor for WorkIndicatorType. |
| * |
| * @param name |
| * The name for the WorkIndicatorType |
| */ |
| private WorkIndicatorType(String name) { |
| this(name, nextOrdinal++); |
| } |
| |
| /** |
| * Retrieves the list of constants for this enumerated type. |
| * |
| * @return The list of constants for this enumerated type. |
| */ |
| protected List getValues() { |
| return Collections.unmodifiableList(Arrays.asList(VALUES)); |
| } |
| } |
| |
| /** |
| * Constructor for AbstractDropTargetListener. |
| * |
| * @param transferIdArray |
| * The transfer agent ids |
| */ |
| public AbstractDropTargetListener(String[] transferIdArray) { |
| super(); |
| |
| assert null!=transferIdArray : "transferIdArray cannot be null"; //$NON-NLS-1$ |
| assert transferIdArray.length > 0 : "transferIdArray cannot be empty"; //$NON-NLS-1$ |
| |
| this.transferIds.addAll(Arrays.asList(transferIdArray)); |
| } |
| |
| /** |
| * Default Constructor for AbstractDropTargetListener. |
| * |
| */ |
| public AbstractDropTargetListener() { |
| super(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.gmf.runtime.common.ui.services.dnd.drop.IDropTargetListener#getSupportingTransferIds() |
| */ |
| public final String[] getSupportingTransferIds() { |
| return (String[]) transferIds.toArray(new String[transferIds.size()]); |
| } |
| |
| /** |
| * Add transfer id to the list of transferIds. |
| * |
| * @param transferId |
| * String id to add |
| */ |
| public final void addSupportingTransferId(String transferId) { |
| assert null != transferId : "transferId cannot be null"; //$NON-NLS-1$ |
| |
| if (!transferIds.contains(transferId)) { |
| transferIds.add(transferId); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.swt.dnd.DropTargetListener#dragEnter(org.eclipse.swt.dnd.DropTargetEvent) |
| */ |
| public void dragEnter(DropTargetEvent event) { |
| /* method not implemented */ |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.swt.dnd.DropTargetListener#dragLeave(org.eclipse.swt.dnd.DropTargetEvent) |
| */ |
| public void dragLeave(DropTargetEvent event) { |
| /* method not implemented */ |
| currentAgent = null; |
| currentEvent = null; |
| context = null; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.swt.dnd.DropTargetListener#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent) |
| */ |
| public void dragOperationChanged(DropTargetEvent event) { |
| /* method not implemented */ |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.swt.dnd.DropTargetListener#dragOver(org.eclipse.swt.dnd.DropTargetEvent) |
| */ |
| public void dragOver(DropTargetEvent event) { |
| /* method not implemented */ |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.swt.dnd.DropTargetListener#drop(org.eclipse.swt.dnd.DropTargetEvent) |
| */ |
| public final void drop(DropTargetEvent event) { |
| /* Check the target and data */ |
| // Fix for RATLC00528158 - Linux: Cannot DnD Tables or Database from |
| // Data Definition View to Class Diagram |
| // Removed check "event.data == null" |
| if (getContext().getCurrentTarget() == null) { |
| event.detail = DND.DROP_NONE; |
| return; |
| } |
| |
| /* Get the command */ |
| final ICommand command = getExecutableContext(event); |
| |
| /* Get the command manager */ |
| final IOperationHistory manager = (IOperationHistory) getContext() |
| .getActivePart().getAdapter(IOperationHistory.class); |
| |
| /* Check the manager and command */ |
| if (manager == null || command == null) { |
| event.detail = DND.DROP_NONE; |
| return; |
| } |
| |
| WorkIndicatorType type = getWorkIndicatorType(); |
| |
| if (type == WorkIndicatorType.PROGRESS_MONITOR) { |
| runCommandInProgressMonitorDialog(command, false); |
| |
| } else if (type == WorkIndicatorType.CANCELABLE_PROGRESS_MONITOR) { |
| runCommandInProgressMonitorDialog(command, true); |
| |
| } else if (type == WorkIndicatorType.BUSY) { |
| /* display hour glass cursor */ |
| BusyIndicator.showWhile(null, new Runnable() { |
| |
| public void run() { |
| try { |
| manager.execute(command, new NullProgressMonitor(), |
| null); |
| } catch (ExecutionException e) { |
| Trace |
| .catching( |
| CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDDebugOptions.EXCEPTIONS_CATCHING, |
| getClass(), "drop", e); //$NON-NLS-1$ |
| Log.error(CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDStatusCodes.SERVICE_FAILURE, |
| "drop", e); //$NON-NLS-1$ |
| } |
| |
| } |
| }); |
| } else { |
| try { |
| manager.execute(command, new NullProgressMonitor(), null); |
| } catch (ExecutionException e) { |
| Trace.catching(CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDDebugOptions.EXCEPTIONS_CATCHING, |
| getClass(), "drop", e); //$NON-NLS-1$ |
| Log.error(CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDStatusCodes.SERVICE_FAILURE, "drop", e); //$NON-NLS-1$ |
| } |
| } |
| |
| /* Set the event detail */ |
| event.detail = (command.getCommandResult().getStatus().isOK()) ? event.detail |
| : DND.DROP_NONE; |
| |
| currentAgent = null; |
| currentEvent = null; |
| context = null; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.swt.dnd.DropTargetListener#dropAccept(org.eclipse.swt.dnd.DropTargetEvent) |
| */ |
| public void dropAccept(DropTargetEvent event) { |
| /* method not implemented */ |
| } |
| |
| /** |
| * 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.IDropTargetListener#getExecutableContext(org.eclipse.swt.dnd.DropTargetEvent) |
| */ |
| public ICommand getExecutableContext(DropTargetEvent event) { |
| return null; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.gmf.runtime.common.ui.services.dnd.drop.IDropTargetListener#setFeedback(org.eclipse.swt.dnd.DropTargetEvent) |
| */ |
| public void setFeedback(DropTargetEvent event) { |
| event.feedback |= DND.FEEDBACK_EXPAND | DND.FEEDBACK_SCROLL; |
| switch (getContext().getRelativeLocation()) { |
| case IDropTargetContext.LOCATION_BEFORE: |
| event.feedback |= DND.FEEDBACK_INSERT_BEFORE; |
| break; |
| case IDropTargetContext.LOCATION_AFTER: |
| event.feedback |= DND.FEEDBACK_INSERT_AFTER; |
| break; |
| case IDropTargetContext.LOCATION_ON: |
| default: |
| event.feedback |= DND.FEEDBACK_SELECT; |
| break; |
| } |
| } |
| |
| /** |
| * Returns whether the listener can support handling drop operations on the |
| * current target context and the current event. |
| * |
| * @return true or false |
| */ |
| public abstract boolean canSupport(); |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.gmf.runtime.common.ui.services.dnd.drop.IDropTargetListener#canSupport(org.eclipse.gmf.runtime.common.ui.services.dnd.drop.IDropTargetContext, |
| * org.eclipse.gmf.runtime.common.ui.services.dnd.drop.IDropTargetEvent, |
| * org.eclipse.gmf.runtime.common.ui.services.dnd.core.ITransferAgent) |
| */ |
| public final boolean canSupport(IDropTargetContext cntxt, |
| IDropTargetEvent currEvent, ITransferAgent currAgent) { |
| /* Set the context */ |
| this.context = new WeakReference<IDropTargetContext>(cntxt); |
| /* Set the event */ |
| this.currentEvent = currEvent; |
| /* Set the agent */ |
| this.currentAgent = currAgent; |
| |
| return canSupport(); |
| } |
| |
| /** |
| * Returns the current event. |
| * |
| * @return IDropTargetEvent |
| */ |
| protected final IDropTargetEvent getCurrentEvent() { |
| return currentEvent; |
| } |
| |
| /** |
| * Returns the current transfer agent. |
| * |
| * @return ITransferAgent |
| */ |
| protected final ITransferAgent getCurrentAgent() { |
| return currentAgent; |
| } |
| |
| /** |
| * Returns the current shell. |
| * |
| * @return Shell |
| */ |
| protected final Shell getShell() { |
| IWorkbenchPartSite site = getContext().getActivePart().getSite(); |
| |
| return site != null ? site.getShell() |
| : null; |
| } |
| |
| /** |
| * Gets type of work indicator (progress monitor, hourglass, or none). |
| * |
| * @return type of work indicator |
| */ |
| protected WorkIndicatorType getWorkIndicatorType() { |
| return WorkIndicatorType.BUSY; |
| } |
| |
| /** |
| * Runs <code>command</code> in the context of a progress monitor dialog. |
| * The command runs in the same thread as the dialog. The cancel button on |
| * the dialog is enabled if <code>cancelable</code> is <code>true</code>. |
| * |
| * @param command |
| * the command to run |
| * @param cancelable |
| * <code>true</code> if the progress monitor should have an |
| * enabled cancel button, <code>false</code> otherwise. |
| * |
| * @exception RuntimeException |
| * if any exception or error occurs while running the action |
| */ |
| private void runCommandInProgressMonitorDialog(final ICommand command, |
| boolean cancelable) { |
| |
| /* Get the operation history */ |
| final IOperationHistory manager = (IOperationHistory) getContext() |
| .getActivePart().getAdapter(IOperationHistory.class); |
| |
| IRunnableWithProgress runnable = new IRunnableWithProgress() { |
| |
| public void run(IProgressMonitor monitor) { |
| try { |
| manager.execute(command, monitor, null); |
| |
| } catch (ExecutionException e) { |
| Trace.catching(CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDDebugOptions.EXCEPTIONS_CATCHING, |
| getClass(), "drop", e); //$NON-NLS-1$ |
| Log.error(CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDStatusCodes.SERVICE_FAILURE, "drop", e); //$NON-NLS-1$ |
| |
| RuntimeException re = new RuntimeException(e); |
| |
| Trace.throwing(CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDDebugOptions.EXCEPTIONS_THROWING, |
| getClass(), "runCommandInProgressMonitorDialog", re); //$NON-NLS-1$ |
| throw re; |
| } |
| |
| } |
| }; |
| runInProgressMonitorDialog(runnable, cancelable); |
| } |
| |
| /** |
| * Runs <code>runnable</code> in a progress monitor dialog. The runnable |
| * runs in the same thread as the dialog. The cancel button on the dialog is |
| * enabled if <code>cancelable</code> is <code>true</code>. |
| * |
| * @param runnable |
| * the runnable to run in the context of the progress dialog |
| * @param cancelable |
| * <code>true</code> if the progress monitor should have an |
| * enabled cancel button, <code>false</code> otherwise. |
| * |
| * @exception RuntimeException |
| * if any exception or error occurs while running the |
| * runnable |
| */ |
| private void runInProgressMonitorDialog(IRunnableWithProgress runnable, |
| boolean cancelable) { |
| |
| try { |
| if (System.getProperty("RUN_PROGRESS_IN_UI_HACK") != null) { //$NON-NLS-1$ |
| new ProgressMonitorDialog(null).run(false, cancelable, runnable); |
| } else { |
| new ProgressMonitorDialog(null).run(true, cancelable, runnable); |
| } |
| |
| } catch (InvocationTargetException ite) { |
| Trace.catching(CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDDebugOptions.EXCEPTIONS_CATCHING, |
| getClass(), "runInProgressMonitorDialog", ite); //$NON-NLS-1$ |
| Log.error(CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDStatusCodes.SERVICE_FAILURE, |
| "runInProgressMonitorDialog", ite); //$NON-NLS-1$ |
| |
| RuntimeException cre = new RuntimeException(ite |
| .getTargetException()); |
| |
| Trace.throwing(CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDDebugOptions.EXCEPTIONS_THROWING, |
| getClass(), "runInProgressMonitorDialog", cre); //$NON-NLS-1$ |
| throw cre; |
| |
| } catch (InterruptedException ie) { |
| Trace.catching(CommonUIServicesDNDPlugin.getDefault(), |
| CommonUIServicesDNDDebugOptions.EXCEPTIONS_CATCHING, |
| getClass(), "runInProgressMonitorDialog", ie); //$NON-NLS-1$ |
| } |
| } |
| |
| } |