/*******************************************************************************
* Copyright (c) 2005, 2016 The Chisel Group 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: Ian Bull (The Chisel Group) - initial API and implementation
* Mateusz Matela - "Tree Views for Zest" contribution, Google Summer of Code 2009
* Matthias Wienand (itemis AG) - refactorings
******************************************************************************/
package org.eclipse.gef.layout.algorithms;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.eclipse.gef.geometry.planar.Dimension;
import org.eclipse.gef.geometry.planar.Point;
import org.eclipse.gef.geometry.planar.Rectangle;
import org.eclipse.gef.graph.Node;
import org.eclipse.gef.layout.ILayoutAlgorithm;
import org.eclipse.gef.layout.LayoutContext;
import org.eclipse.gef.layout.LayoutProperties;
/**
* This layout shifts overlapping nodes to the right.
*
* @author Ian Bull
* @author Mateusz Matela
* @author mwienand
*/
public class HorizontalShiftAlgorithm implements ILayoutAlgorithm {
private static final double DELTA = 10;
private static final double VSPACING = 16;
public void applyLayout(LayoutContext context, boolean clean) {
if (!clean)
return;
ArrayList<List<Node>> rowsList = new ArrayList<>();
Node[] entities = context.getNodes();
for (int i = 0; i < entities.length; i++) {
addToRowList(entities[i], rowsList);
}
Collections.sort(rowsList, new Comparator<List<Node>>() {
public int compare(List<Node> o1, List<Node> o2) {
Node entity0 = o1.get(0);
Node entity1 = o2.get(0);
return (int) (LayoutProperties.getLocation(entity0).y
- LayoutProperties.getLocation(entity1).y);
}
});
Comparator<Node> entityComparator = new Comparator<Node>() {
public int compare(Node o1, Node o2) {
return (int) (LayoutProperties.getLocation(o1).y
- LayoutProperties.getLocation(o2).y);
}
};
Rectangle bounds = LayoutProperties.getBounds(context.getGraph());
int heightSoFar = 0;
for (Iterator<List<Node>> iterator = rowsList.iterator(); iterator
.hasNext();) {
List<Node> currentRow = iterator.next();
Collections.sort(currentRow, entityComparator);
int i = 0;
int width = (int) (bounds.getWidth() / 2 - currentRow.size() * 75);
heightSoFar += LayoutProperties.getSize(currentRow.get(0)).height
+ VSPACING;
for (Iterator<Node> iterator2 = currentRow.iterator(); iterator2
.hasNext();) {
Node entity = (Node) iterator2.next();
Dimension size = LayoutProperties.getSize(entity);
LayoutProperties.setLocation(entity,
new Point(width + 10 * ++i + size.width / 2,
heightSoFar + size.height / 2));
width += size.width;
}
}
}
private void addToRowList(Node entity, ArrayList<List<Node>> rowsList) {
double layoutY = LayoutProperties.getLocation(entity).y;
for (Iterator<List<Node>> iterator = rowsList.iterator(); iterator
.hasNext();) {
List<Node> currentRow = iterator.next();
Node currentRowEntity = currentRow.get(0);
double currentRowY = LayoutProperties
.getLocation(currentRowEntity).y;
if (layoutY >= currentRowY - DELTA
&& layoutY <= currentRowY + DELTA) {
currentRow.add(entity);
return;
}
}
List<Node> newRow = new ArrayList<>();
newRow.add(entity);
rowsList.add(newRow);
}
}