/*******************************************************************************
* Copyright (c) 2004, 2010 BREDEX GmbH.
* 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:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.client.ui.rcp.controllers.dnd.objectmapping;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.jubula.client.core.model.IComponentNamePO;
import org.eclipse.jubula.client.core.model.IObjectMappingAssoziationPO;
import org.eclipse.jubula.client.core.model.IObjectMappingCategoryPO;
import org.eclipse.jubula.client.ui.constants.Constants;
import org.eclipse.jubula.client.ui.rcp.Plugin;
import org.eclipse.jubula.client.ui.rcp.editors.JBEditorHelper;
import org.eclipse.jubula.client.ui.rcp.editors.ObjectMappingMultiPageEditor;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TransferData;
/**
* @author BREDEX GmbH
* @created 26.04.2005
*/
public class OMDropTargetListener extends ViewerDropAdapter {
/** editor */
private ObjectMappingMultiPageEditor m_editor;
/**
* Constructor
*
* @param editor
* The editor.
* @param viewer
* The viewer.
*/
public OMDropTargetListener(ObjectMappingMultiPageEditor editor,
Viewer viewer) {
super(viewer);
m_editor = editor;
boolean scrollExpand = Plugin.getDefault().getPreferenceStore()
.getBoolean(Constants.TREEAUTOSCROLL_KEY);
setScrollExpandEnabled(scrollExpand);
}
/**{@inheritDoc} */
public void dropAccept(DropTargetEvent event) {
if (!(LocalSelectionTransfer.getTransfer().getSelection()
instanceof IStructuredSelection)) {
return;
}
IStructuredSelection selection =
(IStructuredSelection)LocalSelectionTransfer.getTransfer()
.getSelection();
ObjectMappingMultiPageEditor editor = getEditor();
if (editor.getEditorHelper().requestEditableState()
!= JBEditorHelper.EditableState.OK) {
return;
}
Object target = getCurrentTarget() != null
? getCurrentTarget() : getViewer().getInput();
if (containsOnlyType(selection,
IObjectMappingAssoziationPO.class)) {
// Use logic for dropping associations
List<IObjectMappingAssoziationPO> toMove = selection.toList();
dropAssociations(editor, toMove, target);
} else if (containsOnlyType(selection,
IObjectMappingCategoryPO.class)) {
// Use logic for dropping categories
List<IObjectMappingCategoryPO> toMove = selection.toList();
dropCategories(toMove, target);
editor.getTreeViewer().refresh();
} else if (containsOnlyType(selection, IComponentNamePO.class)) {
// Use logic for dropping Component Names
List<IComponentNamePO> toMove = selection.toList();
if (dropComponentNames(editor, toMove, target)) {
return;
}
}
LocalSelectionTransfer.getTransfer().setSelection(null);
editor.getEditorHelper().setDirty(true);
event.item = null; // because to avoid an SWTException:
// item will be disposed after getViewer().refresh()
getViewer().setSelection(new StructuredSelection(target));
}
/**
*
* @param editor
* The editor in which the drop occurred.
* @param toMove
* The associations being moved.
* @param target
* The location to which the associations are being moved.
*/
protected void dropAssociations(ObjectMappingMultiPageEditor editor,
List<IObjectMappingAssoziationPO> toMove, Object target) {
if (target instanceof IObjectMappingCategoryPO) {
OMEditorDndSupport.checkAndMoveAssociations(toMove,
(IObjectMappingCategoryPO)target, editor);
}
}
/**
*
* @param editor
* The editor in which the drop occurred.
* @param toMove
* The Component Names being moved.
* @param target
* The location to which the Component Names are being moved.
* @return whether the operation is cancelled by the user
*/
protected boolean dropComponentNames(ObjectMappingMultiPageEditor editor,
List<IComponentNamePO> toMove, Object target) {
if (target instanceof IObjectMappingAssoziationPO) {
return OMEditorDndSupport.checkTypeCompatibilityAndMove(toMove,
(IObjectMappingAssoziationPO)target, editor);
} else if (target instanceof IObjectMappingCategoryPO) {
OMEditorDndSupport.checkTypeCompatibilityAndMove(toMove,
(IObjectMappingCategoryPO)target, editor);
}
return false;
}
/**
*
* @param toMove
* The categories being moved.
* @param target
* The location to which the categories are being moved.
*
* @return <code>true</code> if the drop was successful. Otherwise
* <code>false</code>.
*/
protected boolean dropCategories(List<IObjectMappingCategoryPO> toMove,
Object target) {
if (target instanceof IObjectMappingCategoryPO) {
IObjectMappingCategoryPO targetCategory =
(IObjectMappingCategoryPO)target;
return OMEditorDndSupport.moveCategories(toMove, targetCategory);
}
return false;
}
/**
* @param data
* Object
* @return boolean
*/
public boolean performDrop(Object data) {
return true;
}
/**
*
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public boolean validateDrop(Object target, int op, TransferData type) {
if (!(LocalSelectionTransfer.getTransfer().getSelection()
instanceof IStructuredSelection)) {
return false;
}
IStructuredSelection selection =
(IStructuredSelection)LocalSelectionTransfer.getTransfer()
.getSelection();
Object dropTarget = target != null ? target : getViewer().getInput();
if (dropTarget == null) {
return false;
}
if (ObjectMappingTransferHelper.getDndToken() != null
&& !ObjectMappingTransferHelper.getDndToken().equals(
m_editor.getAut())) {
return false;
}
if (!hasSingleClassType(selection)) {
return false;
}
if (containsOnlyType(selection,
IObjectMappingAssoziationPO.class)) {
// Use logic for validating associations
List<IObjectMappingAssoziationPO> toMove = selection.toList();
if (dropTarget instanceof IObjectMappingCategoryPO) {
return OMEditorDndSupport.canMoveAssociations(toMove,
(IObjectMappingCategoryPO)dropTarget, m_editor);
}
} else if (containsOnlyType(selection,
IObjectMappingCategoryPO.class)) {
// Use logic for validating categories
if (dropTarget instanceof IObjectMappingCategoryPO) {
return canDropCats(selection.toList(),
(IObjectMappingCategoryPO) dropTarget);
}
return false;
} else if (containsOnlyType(selection, IComponentNamePO.class)) {
// Use logic for validating Component Names
if (dropTarget instanceof IObjectMappingAssoziationPO) {
return true;
} else if (dropTarget instanceof IObjectMappingCategoryPO) {
return OMEditorDndSupport.canMoveCompNames(
(IObjectMappingCategoryPO)dropTarget, m_editor);
}
}
return false;
}
/**
* Checks whether the list of Categories is draggable to the target category
* @param cats the categories
* @param target the target
* @return whether
*/
private static boolean canDropCats(List<IObjectMappingCategoryPO> cats,
IObjectMappingCategoryPO target) {
if (cats.isEmpty()) {
return false;
}
IObjectMappingCategoryPO currCat = target;
while (currCat.getParent() != null) {
if (cats.contains(currCat)) {
// Trying to move a parent inside a child??
// The case when currCat is the top node is ignored, but that
// cannot be in cats anyway
return false;
}
currCat = currCat.getParent();
}
IObjectMappingCategoryPO srcTop = cats.get(0);
while (srcTop.getParent() != null) {
srcTop = srcTop.getParent();
}
// cannot Dnd categories between different tree viewers
return currCat == srcTop;
}
/**
* @return Returns the editor.
*/
public ObjectMappingMultiPageEditor getEditor() {
return m_editor;
}
/**
* Checks whether all elements in the selection are instances of the given
* class.
*
* @param selection The selection to check.
* @param supportedClass The class/interface to check against.
* @return <code>true</code> if all elements in the selection are instances
* of the given class. Otherwise, <code>false</code>.
*/
public boolean containsOnlyType(
IStructuredSelection selection, Class supportedClass) {
Iterator iter = selection.iterator();
while (iter.hasNext()) {
if (!supportedClass.isInstance(iter.next())) {
return false;
}
}
return true;
}
/**
* checks if there are objects of different classes in selection
*
* @param selection The selection to check.
* @return boolean
*/
public boolean hasSingleClassType(IStructuredSelection selection) {
Class classType = null;
Iterator iter = selection.iterator();
while (iter.hasNext()) {
Object obj = iter.next();
//selectionitems must be same type
if (classType == null) {
classType = obj.getClass();
}
if (obj.getClass() != classType) {
return false;
}
}
return true;
}
}