/*******************************************************************************
* Copyright (c) 2010-2015 Henshin developers. 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:
* TU Berlin, University of Luxembourg, SES S.A.
*******************************************************************************/
/**
*
*/
package de.tub.tfs.henshin.editor.util;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.henshin.model.Attribute;
import org.eclipse.emf.henshin.model.Mapping;
import org.eclipse.emf.henshin.model.Node;
import org.eclipse.emf.henshin.model.Rule;
import org.eclipse.swt.graphics.Color;
import de.tub.tfs.henshin.model.layout.HenshinLayoutFactory;
import de.tub.tfs.henshin.model.layout.Layout;
import de.tub.tfs.henshin.model.layout.LayoutSystem;
import de.tub.tfs.henshin.model.layout.NodeLayout;
/**
* The Class NodeUtil.
*/
public class NodeUtil {
public static final Color BG_COLOR= new Color(null,245,245,245); // very light grey
public static final Color BG_COLOR_CREATED = new Color(null,226,240,217); // very light green
public static final Color BG_COLOR_DELETED = new Color(null,251,229,214); // very light red
public static final Color FG_COLOR=ColorConstants.buttonDarkest;
public static final Color FG_COLOR_DARK=ColorConstants.darkGray;
/**
* Calculate position.
*
* @param points
* the points
* @param nodeLayout
* the node layout
* @return the point
*/
public static Point calculatePosition(
Map<PointAndRadius, NodeLayout> points, NodeLayout nodeLayout) {
boolean wiederholen = false;
int x = nodeLayout.getX();
int y = nodeLayout.getY();
int xCenter = x
+ Math.round(getWidth((Node) nodeLayout.getModel(), true) / 2.0f);
int yCenter = y
+ Math.round(getHeight((Node) nodeLayout.getModel()) / 2.0f);
double radius = Math.sqrt((x - xCenter) * (x - xCenter) + (y - yCenter)
* (y - yCenter));
do {
wiederholen = false;
for (PointAndRadius p : points.keySet()) {
while (Math.sqrt((p.getPoint().x - xCenter)
* (p.getPoint().x - xCenter)
+ (p.getPoint().y - yCenter)
* (p.getPoint().y - yCenter)) < radius + p.getRadius()) {
x += 10;
y += 10;
xCenter += 10;
yCenter += 10;
wiederholen = true;
}
}
} while (wiederholen);
points.put(new PointAndRadius(new Point(xCenter, yCenter), radius),
nodeLayout);
nodeLayout.setX(x);
nodeLayout.setY(y);
return new Point(x, y);
}
// /**
// * Gets the node layout.
// *
// * @param node
// * the node
// * @return the node layout
// *
// * @deprecated
// */
// public static NodeLayout getNodeLayout(Node node) {
// return getNodeLayout(node,
// ModelUtil.getModelRoot(node, LayoutSystem.class));
// }
/**
* Gets the node layout.
*
* @param node
* the node
* @param layoutSystem
* the layout system
* @return the node layout
*/
public static NodeLayout getNodeLayout(Node node, LayoutSystem layoutSystem) {
NodeLayout result = null;
if (layoutSystem != null) {
result = findNodeLayout(node, layoutSystem);
if (result == null) {
result = createNodeLayout(node, layoutSystem);
}
}
return result;
}
protected static NodeLayout findNodeLayout(Node node,
LayoutSystem layoutSystem) {
for (Layout nodeLayout : layoutSystem.getLayouts()) {
if (nodeLayout.getModel() == node) {
return (NodeLayout) nodeLayout;
}
}
return null;
}
/**
* Gets the height.
*
* @param node
* the node
* @return the height
*/
public static int getHeight(Node node) {
int height = 16;
if (node.getAttributes().size() > 0) {
height += 3+ 15 * node.getAttributes().size();
}
return height;
}
/**
* Gets the weight.
*
* @param node
* the node
* @return the weight
*/
public static int getWidth(Node node, boolean withAttributes) {
int width = 100;
if (node != null) {
String name = new String();
if (node.getName() != null) {
name += node.getName();
}
if (node.getType() != null) {
name += ":" + node.getType().getName();
width = Math.max(name.length() * 7 + 10, width);
if (withAttributes) {
for (Attribute attr : node.getAttributes()) {
String s = "";
if (attr.getType() != null) {
s = ("- " + attr.getType().getName() + "=" + attr
.getValue());
width = Math.max((s.length() * 7) + 10, width);
}
}
}
}
}
return width;
}
/**
* Creates the node layout.
*
* @param node
* the node
* @return the node layout
*/
private static NodeLayout createNodeLayout(Node node,
LayoutSystem layoutSystem) {
return createNodeLayout(node, layoutSystem, 0);
}
/**
* Creates the node layout.
*
* @param node
* the node
* @return the node layout
*/
private static NodeLayout createNodeLayout(Node node,
LayoutSystem layoutSystem, int mappingColor) {
NodeLayout nodeLayout = HenshinLayoutFactory.eINSTANCE
.createNodeLayout();
int x = 150;
int y = 80;
Map<PointAndRadius, NodeLayout> points = getPoints2NodeLyouts(node,
layoutSystem);
nodeLayout.setX(x);
nodeLayout.setY(y);
nodeLayout.setModel(node);
if (mappingColor == 0) {
setMappingColor(nodeLayout);
} else {
nodeLayout.setColor(mappingColor);
}
calculatePosition(points, nodeLayout);
layoutSystem.getLayouts().add(nodeLayout);
return nodeLayout;
}
/**
* @param node
* @param layoutSystem
* @return
*/
public static Map<PointAndRadius, NodeLayout> getPoints2NodeLyouts(
Node node, LayoutSystem layoutSystem) {
return getPoints2NodeLyouts(node, layoutSystem.getLayouts());
}
public static Map<PointAndRadius, NodeLayout> getPoints2NodeLyouts(
Node node, Collection<Layout> layouts) {
Map<PointAndRadius, NodeLayout> points = new HashMap<PointAndRadius, NodeLayout>();
Iterator<Layout> iter = layouts.iterator();
while (iter.hasNext()) {
Layout l = iter.next();
if (l instanceof NodeLayout) {
NodeLayout nL = (NodeLayout) l;
if (nL.getModel() != null) {
if (node.getGraph().getNodes().contains(nL.getModel())) {
int xCenter = nL.getX()
+ Math.round(NodeUtil.getWidth(
(Node) nL.getModel(), true) / 2.0f);
int yCenter = nL.getY()
+ Math.round(NodeUtil.getHeight((Node) nL
.getModel()) / 2.0f);
int dx = nL.getX() - xCenter;
int dy = nL.getY() - yCenter;
points.put(new PointAndRadius(new Point(xCenter,
yCenter), Math.sqrt(dx * dx + dy * dy)), nL);
}
} else {
iter.remove();
}
}
}
return points;
}
private static void setMappingColor(final NodeLayout nodeLayout) {
final Node node = (Node) nodeLayout.getModel();
int mappingColor = nodeLayout.getColor();
// If the grand parent of the node is a rule and
// the node doesn't have a mapping color, then compute one.
if (node.eContainer().eContainer() instanceof Rule && mappingColor == 0) {
final Rule rule = node.getGraph().getRule();
mappingColor = getMappingColorByUnit(node, rule);
if (mappingColor == 0) {
mappingColor = getMappingColor(node, rule.getMappings());
}
if (mappingColor != 0) {
nodeLayout.setColor(mappingColor);
setMappingColorInAc(node, mappingColor,
ModelUtil.getMappings(rule.getLhs().getFormula()));
ColorUtil.addMappingColor(mappingColor, rule);
}
}
}
/**
* Check, if the node is mapped in an amalgamation unit and take the color
* of the mapped node in the unit
*
* @param node
* Node to check
* @param rule
* Rule to check
* @return The mapping color of the mapped node in amalgamation unit.
*/
private static int getMappingColorByUnit(final Node node, final Rule rule) {
int mappingColor = 0;
return mappingColor;
}
/**
* @param node
* @param formula
*/
private static void setMappingColorInAc(Node node, int mappingColor,
List<Mapping> mappings) {
Node mappedNode = null;
for (Mapping mapping : mappings) {
final Node origin = mapping.getOrigin();
final Node image = mapping.getImage();
if (origin == node) {
mappedNode = mapping.getImage();
}
if (image == node) {
mappedNode = mapping.getOrigin();
}
if (mappedNode != null) {
final NodeLayout mappedNodeLayout = findNodeLayout(mappedNode,
ModelUtil.getModelRoot(node, LayoutSystem.class));
if (mappedNodeLayout != null) {
mappedNodeLayout.setColor(mappingColor);
} else {
createNodeLayout(mappedNode, ModelUtil.getModelRoot(
mappedNode, LayoutSystem.class), mappingColor);
}
setMappingColorInAc(mappedNode, mappingColor,
ModelUtil.getMappings(mappedNode.getGraph()
.getFormula()));
} else {
NodeLayout originLayout = findNodeLayout(origin,
ModelUtil.getModelRoot(origin, LayoutSystem.class));
if (originLayout == null) {
originLayout = createNodeLayout(origin,
ModelUtil.getModelRoot(origin, LayoutSystem.class));
}
if (originLayout.getColor() == 0) {
final int color = ColorUtil.getNextMappingColor(ModelUtil
.getRule(origin));
originLayout.setColor(color);
NodeLayout imageLayout = findNodeLayout(image,
ModelUtil.getModelRoot(image, LayoutSystem.class));
if (imageLayout == null) {
imageLayout = createNodeLayout(image,
ModelUtil.getModelRoot(image,
LayoutSystem.class));
}
imageLayout.setColor(color);
}
}
}
}
/**
*
*/
private static int getMappingColor(Node node, List<Mapping> mappings,
boolean forceColorCreation) {
int mappingColor = 0;
final Node mappedNode = getMappedNode(node, mappings);
if (mappedNode != null) {
final NodeLayout mappedNodeLayout = findNodeLayout(mappedNode,
ModelUtil.getModelRoot(mappedNode, LayoutSystem.class));
if (mappedNodeLayout != null) {
mappingColor = mappedNodeLayout.getColor();
} else {
if (forceColorCreation) {
mappingColor = ColorUtil.getNextMappingColor(ModelUtil
.getRule(node));
createNodeLayout(mappedNode, ModelUtil.getModelRoot(
mappedNode, LayoutSystem.class), mappingColor);
}
}
}
return mappingColor;
}
private static Node getMappedNode(Node node, List<Mapping> mappings) {
for (Mapping mapping : mappings) {
if (mapping.getOrigin() == node) {
return mapping.getImage();
}
if (mapping.getImage() == node) {
return mapping.getOrigin();
}
}
return null;
}
public static boolean nodeIsMapped(Node node, List<Mapping> mappings) {
for (Mapping mapping : mappings) {
if (mapping.getOrigin() == node) {
return true;
}
if (mapping.getImage() == node) {
return true;
}
}
return false;
}
/**
*
*/
private static int getMappingColor(Node node, List<Mapping> mappings) {
return getMappingColor(node, mappings, true);
}
}