/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* 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.
*/
/*
* Created on Jul 14, 2004
*/
package org.jkiss.dbeaver.ext.erd.layout.algorithm.direct;
import org.eclipse.draw2d.graph.*;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.swt.graphics.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Creates dummy edges between nodes, to be used with NodeJoiningDirectedGraphLayout
*
* @author Serge Rider
*/
public class StandaloneNodeConnector {
private AbstractGraphicalEditPart diagram;
private NodeList nodeList;
private EdgeList edgeList;
public StandaloneNodeConnector(AbstractGraphicalEditPart diagram)
{
this.diagram = diagram;
}
//private boolean cleanNextTime = false;
public void visit(DirectedGraph graph)
{
this.nodeList = graph.nodes;
this.edgeList = graph.edges;
setDummyEdges();
}
protected void setDummyEdges()
{
//if node count is only one then we don't have to worry about whether
// the nodes are connected
if (nodeList.size() > 1) {
// Order nodes by their connections count
// Order unconnected nodes by their geometrical size
Collections.sort(nodeList, new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2)
{
final int connCount1 = o2.outgoing.size() + o2.incoming.size();
final int connCount2 = o1.outgoing.size() + o1.incoming.size();
if (connCount1 == 0 && connCount1 == connCount2) {
if (o1.data instanceof NodeEditPart && o2.data instanceof NodeEditPart) {
return ((NodeEditPart) o1.data).getFigure().getMinimumSize().height - ((NodeEditPart) o2.data).getFigure().getMinimumSize().height;
} else {
return 0;
}
} else {
return connCount1 - connCount2;
}
}
});
// Find unconnected nodes
List<Node> unconnectedNodes = new ArrayList<>();
for (int i = 0; i < nodeList.size(); i++) {
Node sourceNode = (Node) nodeList.get(i);
if (sourceNode.outgoing.size() + sourceNode.incoming.size() == 0) {
unconnectedNodes.add(sourceNode);
}
}
final int nodeCount = unconnectedNodes.size();
if (nodeCount > 1) {
// Connect all unconnected nodes between each other
final Point diagramSize = diagram.getViewer().getControl().getSize();
double horizontalRatio = (float)diagramSize.x / (float)diagramSize.y;
double middleRowSize = Math.sqrt(nodeCount);
int nodesInLine = (int)(middleRowSize * horizontalRatio) + 1;//(int)Math.sqrt(nodeCount) + 1;
for (int i = 0; i < nodeCount; i++) {
for (int k = 0; k < nodesInLine - 1 && i < nodeCount - 1; k++, i++) {
Node sourceNode = unconnectedNodes.get(i);
Node targetNode = unconnectedNodes.get(i + 1);
Edge edge = new Edge(null, sourceNode, targetNode);
edge.weight = 2;
edgeList.add(edge);
}
}
}
}
}
}