blob: c48bb002713c5217a10a5b011fa71d554238914a [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.authoring.ui.dnd;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.edit.command.DragAndDropCommand;
import org.eclipse.emf.edit.command.DragAndDropFeedback;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter;
import org.eclipse.epf.library.edit.util.ProcessScopeUtil;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.jface.viewers.TableTreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Widget;
/**
* Drop adapter for drag and drop
*
* @author Phong Nguyen Le
* @since 1.0
*/
public class EditingDomainTableTreeViewerDropAdapter extends
EditingDomainViewerDropAdapter {
public EditingDomainTableTreeViewerDropAdapter(EditingDomain domain,
Viewer viewer) {
super(domain, viewer);
}
/**
* @see org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter#dragEnter(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragEnter(DropTargetEvent event) {
if (event.detail == DND.DROP_NONE) {
event.detail = DND.DROP_COPY;
}
super.dragEnter(event);
}
/**
* @see org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter#dragOver(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dragOver(DropTargetEvent event) {
if (event.detail == DND.DROP_NONE) {
event.detail = DND.DROP_COPY;
}
super.dragOver(event);
}
/**
* @see org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter#dropAccept(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void dropAccept(DropTargetEvent event) {
if (event.detail == DND.DROP_NONE) {
event.detail = DND.DROP_COPY;
}
super.dropAccept(event);
}
/**
* @see org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter#helper(org.eclipse.swt.dnd.DropTargetEvent)
*/
protected void helper(DropTargetEvent event) {
Table table = null;
TableItem item = null;
if (viewer instanceof TableTreeViewer) {
table = ((TableTreeViewer) viewer).getTableTree().getTable();
item = table.getItem(table.toControl(event.x, event.y));
event.item = item;
}
superHelper(event);
if (item != null && (event.feedback & DND.FEEDBACK_SELECT) != 0) {
table.setSelection(new TableItem[] { item });
}
}
/**
* Get drop target
*
* @param item
* @return drop target object
*/
protected Object getDropTarget(Widget item) {
return extractDropTarget(item);
}
/**
* This is called to indicate that the drop action should be invoked.
* @see org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter#drop(org.eclipse.swt.dnd.DropTargetEvent)
*/
public void drop(DropTargetEvent event) {
// A command was created if the source was available early, and the
// information used to create it was cached...
if (dragAndDropCommandInformation != null) {
// Recreate the command.
command = dragAndDropCommandInformation.createCommand();
} else {
// Otherwise, the source should be available now as event.data, and
// we can create the command.
source = extractDragSource(event.data);
Object target = getDropTarget(event.item);
command = DragAndDropCommand.create(domain, target,
getLocation(event), event.operations, originalOperation,
source);
}
// If the command can execute...
if (command.canExecute()) {
// Execute it.
domain.getCommandStack().execute(command);
} else {
// Otherwise, let's call the whole thing off.
event.detail = DND.DROP_NONE;
command.dispose();
}
// Clean up the state.
command = null;
commandTarget = null;
source = null;
}
/**
* This method is called the same way for each of the
* {@link org.eclipse.swt.dnd.DropTargetListener} methods, except for leave
* and drop. If the source is available early, it creates or revalidates the
* {@link DragAndDropCommand}, and updates the event's detail (operation)
* and feedback (drag under effect), appropriately.
*/
protected void superHelper(DropTargetEvent event) {
// If we can't do anything else, we'll provide the default select
// feedback and enable auto-scroll and auto-expand effects.
event.feedback = DND.FEEDBACK_SELECT | getAutoFeedback();
// If we don't already have it, try to get the source early. We can't
// give feedback if it's not available yet (this is platform-dependent).
if (source == null) {
source = getDragSource(event);
if (source == null)
return;
}
// Get the target object from the item widget and the mouse location in
// it.
Object target = getDropTarget(event.item);
float location = getLocation(event);
// Determine if we can create a valid command at the current location.
boolean valid = false;
modifiySource(target);
// If we don't have a previous cached command...
if (command == null) {
// We'll need to keep track of the information we use to create the
// command, so that we can recreate it in drop.
dragAndDropCommandInformation = new DragAndDropCommandInformation(
domain, target, location, event.operations,
originalOperation, source);
// Remember the target; create the command and test if it is
// executable.
commandTarget = target;
command = dragAndDropCommandInformation.createCommand();
valid = command.canExecute();
} else {
// Check if the cached command can provide DND
// feedback/revalidation.
if (target == commandTarget
&& command instanceof DragAndDropFeedback) {
// If so, revalidate the command.
valid = ((DragAndDropFeedback) command).validate(target,
location, event.operations, originalOperation, source);
// Keep track of any changes to the command information.
dragAndDropCommandInformation = new DragAndDropCommandInformation(
domain, target, location, event.operations,
originalOperation, source);
} else {
// If not, dispose the current command and create a new one.
dragAndDropCommandInformation = new DragAndDropCommandInformation(
domain, target, location, event.operations,
originalOperation, source);
commandTarget = target;
command.dispose();
command = dragAndDropCommandInformation.createCommand();
valid = command.canExecute();
}
}
// If this command can provide detailed drag and drop feedback...
if (command instanceof DragAndDropFeedback) {
// Use it for the operation and drag under effect.
DragAndDropFeedback dragAndDropFeedback = (DragAndDropFeedback) command;
event.detail = dragAndDropFeedback.getOperation();
event.feedback = dragAndDropFeedback.getFeedback()
| getAutoFeedback();
} else if (!valid) {
// There is no executable command, so we'd better nix the whole
// deal.
event.detail = DND.DROP_NONE;
}
}
private void modifiySource(Object target) {
if (source == null || source.isEmpty()) {
return;
}
if (!(target instanceof Activity)) {
return;
}
Process proc = ProcessUtil.getProcess((Activity) target);
if (! ProcessScopeUtil.getInstance().isConfigFree(proc)) {
return;
}
boolean toModify = false;
for (Object obj : source) {
if (obj instanceof ProcessComponent) {
toModify = true;
break;
}
}
if (!toModify) {
return;
}
List<Object> list = new ArrayList<Object>();
for (Object obj : source) {
if (obj instanceof ProcessComponent) {
Object process = ((ProcessComponent) obj).getProcess();
if (process != null) {
obj = process;
}
}
list.add(obj);
}
source = list;
}
}