blob: d8974904694f7888b1dfb2e350f813562a5434c0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 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.wst.xsd.ui.internal.commands;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.wst.xsd.ui.internal.actions.MoveXSDElementAction;
import org.eclipse.wst.xsd.ui.internal.adapters.XSDElementDeclarationAdapter;
import org.eclipse.wst.xsd.ui.internal.adapters.XSDWildcardAdapter;
import org.eclipse.wst.xsd.ui.internal.adt.design.editparts.BaseFieldEditPart;
import org.eclipse.wst.xsd.ui.internal.adt.design.editparts.CompartmentEditPart;
import org.eclipse.wst.xsd.ui.internal.adt.design.editparts.ComplexTypeEditPart;
import org.eclipse.wst.xsd.ui.internal.adt.design.editparts.StructureEditPart;
import org.eclipse.wst.xsd.ui.internal.design.editparts.ModelGroupDefinitionReferenceEditPart;
import org.eclipse.wst.xsd.ui.internal.design.editparts.ModelGroupEditPart;
import org.eclipse.wst.xsd.ui.internal.design.editparts.TargetConnectionSpacingFigureEditPart;
import org.eclipse.wst.xsd.ui.internal.design.editparts.XSDBaseFieldEditPart;
import org.eclipse.wst.xsd.ui.internal.design.editparts.XSDGroupsForAnnotationEditPart;
import org.eclipse.wst.xsd.ui.internal.design.figures.GenericGroupFigure;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDModelGroup;
import org.eclipse.xsd.XSDWildcard;
public class XSDElementDragAndDropCommand extends BaseDragAndDropCommand
{
protected ModelGroupEditPart topMostGroup;
public XSDElementDragAndDropCommand(EditPartViewer viewer, ChangeBoundsRequest request, GraphicalEditPart target, XSDBaseFieldEditPart itemToDrag, Point location)
{
super(viewer, request);
this.target = target;
this.itemToDrag = itemToDrag;
this.location = location;
setup();
}
public XSDElementDragAndDropCommand(XSDBaseFieldEditPart itemToDrag, XSDBaseFieldEditPart leftField, XSDBaseFieldEditPart rightField, int direction)
{
super(itemToDrag.getViewer(), null);
this.itemToDrag = itemToDrag;
canExecute = false;
handleKeyboardDragAndDrop(leftField, rightField, direction);
}
protected void handleKeyboardDragAndDrop(XSDBaseFieldEditPart leftField, XSDBaseFieldEditPart rightField, int direction)
{
super.handleKeyboardDragAndDrop(leftField, rightField, direction);
if (direction == PositionConstants.NORTH)
{
if (target == null)
{
target = rightField;
this.location = target.getFigure().getBounds().getTop();
}
else if (!(leftField.getModel() instanceof XSDElementDeclarationAdapter)
|| leftField.getModel() instanceof XSDWildcardAdapter)
{
target = rightField;
this.location = target.getFigure().getBounds().getTop();
}
}
if (location == null) return;
setup();
}
protected void setup()
{
canExecute = false;
// Drop target is model group
if (target instanceof ModelGroupEditPart)
{
parentEditPart = (ModelGroupEditPart) target;
if (((GenericGroupFigure) parentEditPart.getFigure()).getIconFigure().getBounds().contains(location))
{
xsdComponentToDrag = (XSDConcreteComponent) ((XSDElementDeclarationAdapter) itemToDrag.getModel()).getTarget();
action = new MoveXSDElementAction(((ModelGroupEditPart) target).getXSDModelGroup(), xsdComponentToDrag, null, null);
canExecute = action.canMove();
}
}
else if (target instanceof BaseFieldEditPart)
{
targetSpacesList = new ArrayList();
// Calculate the list of all sibling field edit parts;
List targetEditPartSiblings = calculateFieldEditParts();
calculateModelGroupList();
doDrop(targetEditPartSiblings, itemToDrag);
}
}
protected void doDrop(List siblings, GraphicalEditPart movingEditPart)
{
commonSetup(siblings, movingEditPart);
// Can common this code up with XSDAttributeDragAndDropCommand...
if ((previousRefComponent instanceof XSDElementDeclaration || previousRefComponent instanceof XSDWildcard)
&& (nextRefComponent instanceof XSDElementDeclaration || nextRefComponent instanceof XSDWildcard))
{
XSDModelGroup modelGroup = (XSDModelGroup) previousRefComponent.getContainer().getContainer();
if (parentEditPart != null)
modelGroup = ((ModelGroupEditPart) parentEditPart).getXSDModelGroup();
action = new MoveXSDElementAction(modelGroup, xsdComponentToDrag, previousRefComponent, nextRefComponent);
}
else if (previousRefComponent == null && (nextRefComponent instanceof XSDElementDeclaration || nextRefComponent instanceof XSDWildcard))
{
if (closerSibling == ABOVE_IS_CLOSER)
{
if (leftSiblingEditPart == null)
{
action = new MoveXSDElementAction(topMostGroup.getXSDModelGroup(), xsdComponentToDrag, null, null, false);
}
else if (parentEditPart != null)
{
action = new MoveXSDElementAction(((ModelGroupEditPart) parentEditPart).getXSDModelGroup(), xsdComponentToDrag, previousRefComponent, nextRefComponent);
}
}
else
{
XSDModelGroup modelGroup = (XSDModelGroup) nextRefComponent.getContainer().getContainer();
action = new MoveXSDElementAction(modelGroup, xsdComponentToDrag, previousRefComponent, nextRefComponent);
}
}
else if ((previousRefComponent instanceof XSDElementDeclaration || previousRefComponent instanceof XSDWildcard)
&& nextRefComponent == null)
{
XSDModelGroup modelGroup = (XSDModelGroup)previousRefComponent.getContainer().getContainer();
if (parentEditPart != null)
modelGroup = ((ModelGroupEditPart) parentEditPart).getXSDModelGroup();
if (closerSibling == ABOVE_IS_CLOSER)
{
action = new MoveXSDElementAction(modelGroup, xsdComponentToDrag, previousRefComponent, nextRefComponent);
}
else
{
if (rightSiblingEditPart == null)
{
action = new MoveXSDElementAction(topMostGroup.getXSDModelGroup(), xsdComponentToDrag, null, null, true);
}
else
{
action = new MoveXSDElementAction(modelGroup, xsdComponentToDrag, previousRefComponent, nextRefComponent);
}
}
}
if (action != null)
canExecute = action.canMove();
}
/**
* overrides base
*/
protected boolean handleFirstAndLastDropTargets(int index, List siblings)
{
// This boolean is to handle the Top and Bottom drop targets for which we want to drop
// to the top most model group
// TODO: I need to rearrange this code better
boolean isHandled = false;
int pointerYLocation = location.y;
// We need to find the parent editpart, which is the model group
// Handle case where you drop to first position
if (index == 0 && siblings.size() > 0)
{
leftSiblingEditPart = null;
rightSiblingEditPart = (GraphicalEditPart) siblings.get(0);
int siblingYLocation = getZoomedBounds(rightSiblingEditPart.getFigure().getBounds()).getCenter().y;
closerSibling = BELOW_IS_CLOSER;
if (Math.abs(pointerYLocation - siblingYLocation) > getZoomedBounds(rightSiblingEditPart.getFigure().getBounds()).height / 4)
{
isHandled = true;
parentEditPart = topMostGroup;
if (topMostGroup != null)
closerSibling = ABOVE_IS_CLOSER;
}
}
// Handle case where you drop to last position
if (index > 0 && index == siblings.size())
{
leftSiblingEditPart = (GraphicalEditPart) siblings.get(index - 1);
int siblingYLocation = getZoomedBounds(leftSiblingEditPart.getFigure().getBounds()).getCenter().y;
if (Math.abs(pointerYLocation - siblingYLocation) > getZoomedBounds(leftSiblingEditPart.getFigure().getBounds()).height / 4)
{
isHandled = true;
parentEditPart = topMostGroup;
if (topMostGroup != null)
closerSibling = BELOW_IS_CLOSER;
}
}
return isHandled;
}
// Methods specific to element as drag source
// Model Group related helper method
protected void calculateModelGroupList()
{
EditPart editPart = target;
while (editPart != null)
{
if (editPart instanceof ModelGroupEditPart)
{
getModelGroupEditParts((ModelGroupEditPart) editPart);
}
else if (editPart instanceof ComplexTypeEditPart || editPart instanceof StructureEditPart)
{
boolean foundTop = false;
List list = editPart.getChildren();
for (Iterator i = list.iterator(); i.hasNext();)
{
Object child = i.next();
if (child instanceof CompartmentEditPart)
{
List compartmentList = ((CompartmentEditPart) child).getChildren();
for (Iterator it = compartmentList.iterator(); it.hasNext();)
{
Object obj = it.next();
if (obj instanceof XSDGroupsForAnnotationEditPart)
{
XSDGroupsForAnnotationEditPart groups = (XSDGroupsForAnnotationEditPart) obj;
List groupList = groups.getChildren();
for (Iterator iter = groupList.iterator(); iter.hasNext();)
{
Object groupChild = iter.next();
if (groupChild instanceof ModelGroupEditPart)
{
if (!foundTop)
{
foundTop = true;
topMostGroup = (ModelGroupEditPart) groupChild;
}
getModelGroupEditParts((ModelGroupEditPart) groupChild);
}
}
}
}
}
}
}
editPart = editPart.getParent();
}
}
// Model Group related helper method
protected List getModelGroupEditParts(ModelGroupEditPart modelGroupEditPart)
{
List modelGroupList = new ArrayList();
List list = modelGroupEditPart.getChildren();
for (Iterator i = list.iterator(); i.hasNext();)
{
Object object = i.next();
if (object instanceof TargetConnectionSpacingFigureEditPart)
{
targetSpacesList.add(object);
}
else if (object instanceof ModelGroupDefinitionReferenceEditPart)
{
ModelGroupDefinitionReferenceEditPart groupRef = (ModelGroupDefinitionReferenceEditPart) object;
List groupRefChildren = groupRef.getChildren();
for (Iterator it = groupRefChildren.iterator(); it.hasNext();)
{
Object o = it.next();
if (o instanceof ModelGroupEditPart)
{
getModelGroupEditParts((ModelGroupEditPart) o);
}
}
}
else if (object instanceof ModelGroupEditPart)
{
getModelGroupEditParts((ModelGroupEditPart) object);
}
}
return modelGroupList;
}
}