/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kie.workbench.common.stunner.core.client.canvas.command;
import java.util.List;
import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler;
import org.kie.workbench.common.stunner.core.client.command.CanvasViolation;
import org.kie.workbench.common.stunner.core.client.shape.EdgeShape;
import org.kie.workbench.common.stunner.core.client.shape.MutationContext;
import org.kie.workbench.common.stunner.core.client.shape.Shape;
import org.kie.workbench.common.stunner.core.command.CommandResult;
import org.kie.workbench.common.stunner.core.definition.morph.MorphDefinition;
import org.kie.workbench.common.stunner.core.graph.Edge;
import org.kie.workbench.common.stunner.core.graph.Node;
import org.kie.workbench.common.stunner.core.graph.content.definition.Definition;
import org.kie.workbench.common.stunner.core.graph.content.relationship.Child;
import org.kie.workbench.common.stunner.core.graph.content.relationship.Dock;
import org.kie.workbench.common.stunner.core.graph.content.view.View;
public class MorphCanvasNodeCommand extends AbstractCanvasCommand {
private Node<? extends Definition<?>, Edge> candidate;
private MorphDefinition morphDefinition;
private String shapeSetId;
public MorphCanvasNodeCommand(final Node<? extends Definition<?>, Edge> candidate,
final MorphDefinition morphDefinition,
final String shapeSetId) {
this.candidate = candidate;
this.morphDefinition = morphDefinition;
this.shapeSetId = shapeSetId;
}
@Override
@SuppressWarnings("unchecked")
public CommandResult<CanvasViolation> execute(final AbstractCanvasHandler context) {
// Deregister the existing shape.
Node parent = getParent();
if (null != parent) {
context.removeChild(parent,
candidate);
}
context.deregister(candidate);
// Register the shape for the new morphed element.
context.register(shapeSetId,
candidate);
if (null != parent) {
context.addChild(parent,
candidate);
}
context.applyElementMutation(candidate,
MutationContext.STATIC);
// Update incoming connections for new shape ( so magnets, connectors, etc on view side ).
final List<Edge> inEdges = candidate.getInEdges();
if (null != inEdges && !inEdges.isEmpty()) {
for (final Edge inEdge : inEdges) {
if (isViewEdge(inEdge)) {
final Node inNode = inEdge.getSourceNode();
updateConnections(context,
inEdge,
inNode,
candidate);
}
}
}
// Update outgoing connections as well for new shape.
final List<Edge> outEdges = candidate.getOutEdges();
if (null != outEdges && !outEdges.isEmpty()) {
for (final Edge outEdge : outEdges) {
if (isViewEdge(outEdge)) {
final Node targetNode = outEdge.getTargetNode();
updateConnections(context,
outEdge,
candidate,
targetNode);
}
}
}
return buildResult();
}
@Override
public CommandResult<CanvasViolation> undo(final AbstractCanvasHandler context) {
return execute(context);
}
@SuppressWarnings("unchecked")
private void updateConnections(final AbstractCanvasHandler context,
final Edge edge,
final Node sourceNode,
final Node targetNode) {
if (null != edge && null != sourceNode && null != targetNode) {
final EdgeShape edgeShape = (EdgeShape) context.getCanvas().getShape(edge.getUUID());
final Shape sourceNodeShape = context.getCanvas().getShape(sourceNode.getUUID());
final Shape targetNodeShape = context.getCanvas().getShape(targetNode.getUUID());
edgeShape.applyConnections(edge,
sourceNodeShape.getShapeView(),
targetNodeShape.getShapeView(),
MutationContext.STATIC);
}
}
private Node getParent() {
List<Edge> inEdges = candidate.getInEdges();
if (null != inEdges && !inEdges.isEmpty()) {
for (final Edge edge : inEdges) {
if (isChildEdge(edge) || isDockEdge(edge)) {
return edge.getSourceNode();
}
}
}
return null;
}
private boolean isChildEdge(final Edge edge) {
return edge.getContent() instanceof Child;
}
private boolean isDockEdge(final Edge edge) {
return edge.getContent() instanceof Dock;
}
private boolean isViewEdge(final Edge edge) {
return edge.getContent() instanceof View;
}
}