/**
* Դ�������ƣ�MetadataDropAdapter.java
* �������Ȩ���������ӹɷ�����˾ ��Ȩ����
* ϵͳ���ƣ�JRES Studio
* ģ�����ƣ�com.hundsun.ares.studio.jres.metadata.ui
* ����˵����Ԫ�����û��༭��UIչ����ع���
* ����ĵ���
* ���ߣ�
*/
package com.hundsun.ares.studio.jres.metadata.ui.editors.dnd;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.MoveCommand;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.ui.dnd.LocalTransfer;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.widgets.TreeItem;
import com.hundsun.ares.studio.jres.metadata.ui.viewer.MetadataViewerUtil;
import com.hundsun.ares.studio.jres.metadata.ui.viewer.UncategorizedItemsCategoryImpl;
import com.hundsun.ares.studio.jres.model.metadata.MetadataCategory;
import com.hundsun.ares.studio.jres.model.metadata.MetadataItem;
import com.hundsun.ares.studio.jres.model.metadata.MetadataPackage;
import com.hundsun.ares.studio.jres.model.metadata.MetadataResourceData;
/**
* ��קAdapter
* @author sundl
*/
public class MetadataDropAdapter extends ViewerDropAdapter{
private EditingDomain domain;
private EObject dropTargetContainer;
public MetadataDropAdapter(TreeViewer viewer, EditingDomain domain) {
super(viewer);
this.domain = domain;
}
// ����ֻ��ͨ��UI����ȡ����ǰ��
protected Object determineTarget(DropTargetEvent event) {
dropTargetContainer = determainDropTargetContainer(event);
return super.determineTarget(event);
}
private EObject determainDropTargetContainer(DropTargetEvent event) {
if (MetadataViewerUtil.isShowCategory(getColumnViewer())) {
if (!(event.item instanceof TreeItem)) {
return null;
}
TreeItem item = (TreeItem) event.item;
if (item.getData() instanceof MetadataItem) {
TreeItem parentItem = item.getParentItem();
if (parentItem == null)
return null;
Object data = parentItem.getData();
if (data instanceof MetadataCategory)
return (MetadataCategory) data;
} else if (item.getData() instanceof MetadataCategory) {
// �������ִ�е�ʱ��û��ִ��super.determineLocation()���Բ���getCurrentLocation
MetadataCategory cate = (MetadataCategory) item.getData();
int location = determineLocation(event);
if (location == LOCATION_ON)
return cate;
else if (location == LOCATION_AFTER || location == LOCATION_BEFORE) {
return cate.eContainer();
}
}
} else {
return MetadataViewerUtil.getMetadataModel(getColumnViewer());
}
return null;
}
@Override
public boolean performDrop(Object data) {
int operation = getCurrentOperation();
Collection<?> elements = extractDragSource(data);
Object target = getCurrentTarget();
int location = getCurrentLocation();
Object[] elementArray = elements.toArray();
EStructuralFeature feature = getFeature(elementArray[0]);
EList<?> list = (EList<?>) dropTargetContainer.eGet(getFeature(elementArray[0]));
int index = list.indexOf(target);
if (target.equals(dropTargetContainer)) {
index = 0;
} else {
if (location == LOCATION_AFTER)
index++;
}
Command command = null;
CompoundCommand cmd = new CompoundCommand();
if (dropTargetContainer == getOwner()) {
// ͬһ��container�µ��϶������ƶ�˳��
for (Object element : elements) {
int curIndex = list.indexOf(element);
if(curIndex<index){
//�����϶�
cmd.append(MoveCommand.create(domain, dropTargetContainer, feature, element, index-1));
}else{
cmd.append(MoveCommand.create(domain, dropTargetContainer, feature, element, index));
index++;
}
}
} else {
//�������ʾɾ�����࣬������������ཫ������ by wangxh 2013.6.13
if(feature == MetadataPackage.Literals.METADATA_CATEGORY__CHILDREN){
if(elementArray[0] instanceof MetadataCategory){
cmd.append(RemoveCommand.create(domain, ((MetadataCategory)elementArray[0]).getParent(), feature, elements));
}
}
// ��ͬ��container�µ��϶������ƶ�����
cmd.append(AddCommand.create(domain, dropTargetContainer, feature, elements, index));
// �����ӷ�����containment���ԣ����Բ���Ҫ����ɾ��������Add��ʱ���Ѿ���ԭ����ɾ���ˣ�
// �������Item�Ĺ�ϵ�Dz�ͬ�ģ���Ҫ����ɾ��
if (operation == DND.DROP_MOVE && feature == MetadataPackage.Literals.METADATA_CATEGORY__ITEMS)
cmd.append(RemoveCommand.create(domain, getOwner(), feature, elements));
}
command = cmd;
// if (target instanceof MetadataCategory) {
// command = createCommand(operation, elements, (MetadataCategory)target, -1);
// } else if (target instanceof MetadataItem) {
// if (dropTargetContainer != null) {
// int index = dropTargetContainer.getItems().indexOf(target);
// int location = getCurrentLocation();
// if (location == LOCATION_AFTER) {
// index++;
// }
// command = createCommand(operation, elements, dropTargetContainer, index);
// }
// }
if (command != null)
domain.getCommandStack().execute(command);
return true;
}
private Command createCommand(int operation, Collection<?> elements, MetadataCategory target, int index) {
if (operation == DND.DROP_MOVE) {
return createMoveToCategoryCommand(elements, target, index, false);
} else if (operation == DND.DROP_COPY) {
return createMoveToCategoryCommand(elements, target, index, true);
}
return null;
}
protected Command createMoveToCategoryCommand(Collection<?> items, MetadataCategory target, int index, boolean isCopy) {
CompoundCommand command = new CompoundCommand();
MetadataCategory source = MetadataViewerUtil.getSelectedCategory((ColumnViewer) getViewer(), true);
if (source.equals(target)) {
for (Object obj : items) {
command.append(MoveCommand.create(domain, target, MetadataPackage.Literals.METADATA_CATEGORY__ITEMS, obj, index));
}
}
else {
command.append(AddCommand.create(domain, target, MetadataPackage.Literals.METADATA_CATEGORY__ITEMS, items, index));
if (!isCopy)
command.append(RemoveCommand.create(domain, source, MetadataPackage.Literals.METADATA_CATEGORY__ITEMS, items));
}
return command;
}
@Override
public boolean validateDrop(Object target, int operation, TransferData transferType) {
Collection<?> source = getDragSource(getCurrentEvent());
if (source == null || source.isEmpty())
return false;
if (dropTargetContainer == null)
return false;
// �����϶���δ����
if (dropTargetContainer instanceof UncategorizedItemsCategoryImpl)
return false;
Object[] elements = source.toArray();
// 1. ����ֻ��Item����ֻ�з��飻 ������ͬһ�㣬ͬһ����������
if (!allUnderSameContainer(elements))
return false;
//Ԫ������Ŀ�����϶���root���� by wangxh 2013.6.13
EObject parent = dropTargetContainer.eContainer();
if(parent != null && parent instanceof MetadataResourceData && elements[0] instanceof MetadataItem){
return false;
}
// 2. target�Ƿ���
int location = getCurrentLocation();
if (target instanceof MetadataCategory) {
MetadataCategory cate = (MetadataCategory) target;
// 2.1 �����϶���δ����
if (cate instanceof UncategorizedItemsCategoryImpl) {
if (location == LOCATION_BEFORE)
return true;
else
return false;
}
//��������϶������������ط� by wangxh 2013.6.13
if(dropTargetContainer instanceof MetadataCategory){
return true;
}
// 2.2 �����϶�����ǰ����
MetadataCategory currentCate = MetadataViewerUtil.getSelectedCategory((ColumnViewer) getViewer(), true);
if (cate.equals(currentCate)) {
if (location == LOCATION_BEFORE || location == LOCATION_AFTER)
return true;
else
return false;
}
// 2.3 �϶������飬ֻ����LOCATION_ON�����
if (location != LOCATION_ON) {
return false;
}
return true;
}
// 3. target ��Item
else if (target instanceof MetadataItem) {
if (getFeature(elements[0]) == MetadataPackage.Literals.METADATA_CATEGORY__CHILDREN) {
// ����������϶����ൽ����һ�������£���Ϊһ���ӷ��࣬��������������϶���Item����
if (location == LOCATION_BEFORE)
return true;
}
if (location == LOCATION_BEFORE || location == LOCATION_AFTER)
return true;
return false;
}
return false;
}
/**
* ָ����Ԫ���Ƿ��Ѿ�������Ŀ���������
* @param elements
* @return
*/
private boolean isAnyElementAlreadyInTargetCategory(Object[] elements) {
EStructuralFeature feature = getFeature(elements[0]);
@SuppressWarnings("rawtypes")
EList list = (EList) dropTargetContainer.eGet(feature);
for (Object element : elements) {
if (!list.contains(element))
return true;
}
return false;
}
/**
* ָ����Ԫ���Ƿ��ڵ�ǰ��������
* ���Ԫ��������Item��Ҳ��Category��Ҳ����false
* @param elements
* @return
*/
private boolean allUnderSameContainer(Object[] elements) {
if (elements == null || elements.length == 0)
return false;
if (elements.length == 1)
return true;
EStructuralFeature feature = getFeature(elements[0]);
EObject owner = getOwner();
@SuppressWarnings("rawtypes")
EList list = (EList) owner.eGet(feature);
for (Object element : elements) {
if (!list.contains(element))
return false;
}
return true;
}
protected EObject getOwner() {
if (MetadataViewerUtil.isShowCategory((ColumnViewer) getViewer())) {
MetadataCategory category = MetadataViewerUtil.getSelectedCategory(getColumnViewer(), true);
// if (category instanceof UncategorizedItemsCategoryImpl) {
// return null;
// }
return category;
} else {
return MetadataViewerUtil.getMetadataModel(getColumnViewer());
}
}
private EStructuralFeature getFeature(Object element) {
if (MetadataViewerUtil.isShowCategory((ColumnViewer) getViewer())) {
if (element instanceof MetadataCategory) {
return MetadataPackage.Literals.METADATA_CATEGORY__CHILDREN;
} else if (element instanceof MetadataItem) {
return MetadataPackage.Literals.METADATA_CATEGORY__ITEMS;
}
} else if (element instanceof MetadataItem) {
return MetadataPackage.Literals.METADATA_RESOURCE_DATA__ITEMS;
}
// should not happen
return null;
}
private ColumnViewer getColumnViewer(){
return (ColumnViewer) getViewer();
}
protected Collection<?> getDragSource(DropTargetEvent event) {
// Check whether the current data type can be transfered locally.
//
LocalTransfer localTransfer = LocalTransfer.getInstance();
if (!localTransfer.isSupportedType(event.currentDataType)) {
// Iterate over the data types to see if there is a data type that
// supports a local transfer.
//
TransferData[] dataTypes = event.dataTypes;
for (int i = 0; i < dataTypes.length; ++i) {
TransferData transferData = dataTypes[i];
// If the local transfer supports this data type, switch to that
// data type
//
if (localTransfer.isSupportedType(transferData)) {
event.currentDataType = transferData;
}
}
return null;
} else {
// Transfer the data and, if non-null, extract it.
//
Object object = localTransfer.nativeToJava(event.currentDataType);
return object == null ? null : extractDragSource(object);
}
}
/**
* This extracts a collection of dragged source objects from the given
* object retrieved from the transfer agent. This default implementation
* converts a structured selection into a collection of elements.
*/
protected Collection<?> extractDragSource(Object object) {
// Transfer the data and convert the structured selection to a
// collection of objects.
//
if (object instanceof IStructuredSelection) {
List<?> list = ((IStructuredSelection) object).toList();
return list;
} else {
return Collections.EMPTY_LIST;
}
}
}