blob: acf17fd6b84be807ada556ba3cd46af888b967a3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2021 THALES GLOBAL SERVICES and others.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.diagram.ui.business.internal.view;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.LayoutConstraint;
import org.eclipse.gmf.runtime.notation.Location;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.Size;
import org.eclipse.sirius.diagram.AbstractDNode;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.diagram.DDiagramElement;
import org.eclipse.sirius.diagram.DEdge;
import org.eclipse.sirius.diagram.DNode;
import org.eclipse.sirius.diagram.DNodeContainer;
import org.eclipse.sirius.diagram.DNodeList;
import org.eclipse.sirius.diagram.DNodeListElement;
import org.eclipse.sirius.diagram.EdgeTarget;
import org.eclipse.sirius.diagram.ui.business.api.view.SiriusGMFHelper;
import org.eclipse.sirius.diagram.ui.provider.Messages;
import org.eclipse.sirius.diagram.ui.tools.api.format.AbstractSiriusFormatDataManager;
/**
* Store the layout information of an AbstractDNode at a given time.
*
* @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a>
*
*/
public class LayoutData extends AbstractLayoutData {
/**
* The target of this LayoutData (can only be a DDiagram or an
* AbstractDNode).
*/
private EObject target;
private Dimension size;
private Point location;
private List<LayoutData> children;
private List<EdgeLayoutData> outgoingEdgeLayoutDatas = new ArrayList<EdgeLayoutData>();
private List<EdgeLayoutData> incomingEdgeLayoutDatas = new ArrayList<EdgeLayoutData>();
/**
* Constructor.
*
*/
public LayoutData() {
}
/**
* Constructor.
*
* @param parent
* the parent layout data.
* @param target
* The node to deal with
* @param gmfNode
* the corresponding GMF node
*/
public LayoutData(final LayoutData parent, final AbstractDNode target, final Node gmfNode) {
setParent(parent);
init(target, gmfNode);
}
/**
* Initialize this object.
*
* @param nodeTarget
* The node to deal with
* @param gmfNode
* the corresponding GMF node
*/
protected void init(final AbstractDNode nodeTarget, final Node gmfNode) {
this.target = nodeTarget;
final LayoutConstraint constaint = gmfNode.getLayoutConstraint();
if (constaint instanceof Size) {
this.size = new Dimension(((Size) constaint).getWidth(), ((Size) constaint).getHeight());
}
if (constaint instanceof Location) {
this.location = new Point(((Location) constaint).getX(), ((Location) constaint).getY());
}
children = new ArrayList<LayoutData>();
if (target instanceof DNode) {
addNodeChildren();
} else if (target instanceof DNodeContainer) {
addNodeContainerChildren();
} else if (target instanceof DNodeList) {
addNodeListChildren();
} else {
AbstractSiriusFormatDataManager.logUnhandledDiagramElementKindMessage(target);
}
if (target instanceof EdgeTarget) {
addOutgoingEdge();
addIncomingEdge();
}
}
/**
* Add children of the node.
*/
protected void addNodeChildren() {
for (DNode child : ((DNode) target).getOwnedBorderedNodes()) {
// Search the GMF node corresponding to the child
final Node gmfNode = SiriusGMFHelper.getGmfNode(child);
if (gmfNode != null) {
children.add(new LayoutData(this, child, gmfNode));
}
}
}
/**
* Add children of the node.
*/
protected void addNodeContainerChildren() {
for (DDiagramElement child : ((DNodeContainer) target).getOwnedDiagramElements()) {
if (child instanceof AbstractDNode) {
// Search the GMF node corresponding to the child
final Node gmfNode = SiriusGMFHelper.getGmfNode(child);
if (gmfNode != null) {
children.add(new LayoutData(this, (AbstractDNode) child, gmfNode));
}
}
}
for (DNode child : ((DNodeContainer) target).getOwnedBorderedNodes()) {
// Search the GMF node corresponding to the child
final Node gmfNode = SiriusGMFHelper.getGmfNode(child);
if (gmfNode != null) {
children.add(new LayoutData(this, child, gmfNode));
}
}
}
/**
* Add children of the node.
*/
protected void addNodeListChildren() {
for (DNodeListElement child : ((DNodeList) target).getOwnedElements()) {
// Search the GMF node corresponding to the child
final Node gmfNode = SiriusGMFHelper.getGmfNode(child);
if (gmfNode != null) {
children.add(new LayoutData(this, child, gmfNode));
}
}
for (DNode child : ((DNodeList) target).getOwnedBorderedNodes()) {
// Search the GMF node corresponding to the child
final Node gmfNode = SiriusGMFHelper.getGmfNode(child);
if (gmfNode != null) {
children.add(new LayoutData(this, child, gmfNode));
}
}
}
/**
* Add outgoing edge of the edgeTarget.
*/
protected void addOutgoingEdge() {
for (DEdge outgoingEdge : ((EdgeTarget) target).getOutgoingEdges()) {
// Search the GMF edge corresponding to the child
final Edge gmfEdge = SiriusGMFHelper.getGmfEdge(outgoingEdge);
if (gmfEdge != null) {
outgoingEdgeLayoutDatas.add(new EdgeLayoutData(this, outgoingEdge, gmfEdge));
}
}
}
/**
* Add incoming edge of the edgeTarget.
*/
protected void addIncomingEdge() {
for (DEdge incomingEdge : ((EdgeTarget) target).getIncomingEdges()) {
// Search the GMF edge corresponding to the child
final Edge gmfEdge = SiriusGMFHelper.getGmfEdge(incomingEdge);
if (gmfEdge != null) {
incomingEdgeLayoutDatas.add(new EdgeLayoutData(this, incomingEdge, gmfEdge));
}
}
}
/**
* Return the target of this layout data.
*
* @return the target
*/
public EObject getTarget() {
return target;
}
/**
* Return the children layout data.
*
* @return the children
*/
public List<LayoutData> getChildren() {
return children;
}
/**
* Search recursively in in all the LayoutData is there is one which have
* the element for target.
*
* @param node
* The search element
* @param ignoreConsumeState
* true to ignore the consume state and to authorize to consume
* an already consumed data, false otherwise
* @return the corresponding LayoutData or null if not found.
*/
public LayoutData getData(final AbstractDNode node, boolean ignoreConsumeState) {
LayoutData result = null;
if ((ignoreConsumeState || !isConsume()) && getTarget().equals(node)) {
result = this;
} else {
for (LayoutData layoutData : getChildren()) {
result = layoutData.getData(node, ignoreConsumeState);
if (result != null) {
break;
}
}
}
return result;
}
/**
* Search recursively in in all the LayoutData is there is one which have
* the element for target.
*
* @param edge
* The search element
* @param ignoreConsumeState
* true to ignore the consume state and to authorize to consume
* an already consumed data, false otherwise
* @return the corresponding LayoutData or null if not found.
*/
public EdgeLayoutData getData(final DEdge edge, boolean ignoreConsumeState) {
EdgeLayoutData result = null;
for (EdgeLayoutData edgeLayoutData : outgoingEdgeLayoutDatas) {
if ((ignoreConsumeState || !edgeLayoutData.isConsume()) && edgeLayoutData.getTarget().equals(edge)) {
result = edgeLayoutData;
break;
}
}
if (result == null) {
for (EdgeLayoutData edgeLayoutData : incomingEdgeLayoutDatas) {
if ((ignoreConsumeState || !edgeLayoutData.isConsume()) && edgeLayoutData.getTarget().equals(edge)) {
result = edgeLayoutData;
break;
}
}
}
if (result == null) {
for (LayoutData layoutData : getChildren()) {
result = layoutData.getData(edge, ignoreConsumeState);
if (result != null) {
break;
}
}
}
return result;
}
/**
* Return the size.
*
* @return the size
*/
public Dimension getSize() {
return size;
}
/**
* Return the location.
*
* @return the location
*/
public Point getLocation() {
return location;
}
/**
* Indicates if this layoutData and all his children has already been
* consumed.
*
* @return true if this layoutData and all his children has already been
* consumed, false otherwise
*/
public boolean isAllConsume() {
boolean isAllConsume = isConsume();
for (LayoutData layoutData : getChildren()) {
isAllConsume = isAllConsume && layoutData.isAllConsume();
if (!isAllConsume) {
break;
}
}
for (EdgeLayoutData edgeLayoutData : outgoingEdgeLayoutDatas) {
isAllConsume = isAllConsume && edgeLayoutData.isConsume();
if (!isAllConsume) {
break;
}
}
if (isAllConsume) {
for (EdgeLayoutData edgeLayoutData : incomingEdgeLayoutDatas) {
isAllConsume = isAllConsume && edgeLayoutData.isConsume();
if (!isAllConsume) {
break;
}
}
}
return isAllConsume;
}
/**
* Set the target.
*
* @param target
* the target to set
*/
protected void setTarget(final EObject target) {
if (!(target instanceof AbstractDNode || target instanceof DDiagram || target instanceof DEdge)) {
throw new IllegalArgumentException(Messages.LayoutData_illegalTarget);
}
this.target = target;
}
/**
* Set the target.
*
* @param target
* the target to set
*/
protected void setTarget(final DDiagram target) {
this.target = target;
}
/**
* Set the size.
*
* @param size
* the size to set
*/
protected void setSize(final Dimension size) {
this.size = size;
}
/**
* Set the location.
*
* @param location
* the location to set
*/
protected void setLocation(final Point location) {
this.location = location;
}
/**
* Set the children.
*
* @param children
* the children to set
*/
protected void setChildren(final List<LayoutData> children) {
this.children = children;
}
/**
* {@inheritDoc}
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
String toString = getTarget().toString();
if (getLocation() != null) {
toString += ", " + getLocation().toString(); //$NON-NLS-1$
}
if (getSize() != null) {
toString += ", " + getSize().toString(); //$NON-NLS-1$
}
return toString;
}
}