/******************************************************************************* * Copyright (c) 2003, 2010, 2012 IBM Corporation, Gerhardt Informatics Kft. 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: * IBM Corporation - initial API and implementation * Gerhardt Informatics Kft. - GEFGWT port *******************************************************************************/ package org.eclipse.draw2d.graph; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * Sorts nodes in a compound directed graph. * * @author Randy Hudson * @since 2.1.2 */ class CompoundRankSorter extends RankSorter { static class RowEntry { double contribution; int count; void reset() { count = 0; contribution = 0; } } static class RowKey { int rank; Subgraph s; RowKey() { } RowKey(Subgraph s, int rank) { this.s = s; this.rank = rank; } public boolean equals(Object obj) { RowKey rp = (RowKey) obj; return rp.s == s && rp.rank == rank; } public int hashCode() { return s.hashCode() ^ (rank * 31); } } boolean init; RowKey key = new RowKey(); Map map = new HashMap(); void addRowEntry(Subgraph s, int row) { key.s = s; key.rank = row; if (!map.containsKey(key)) map.put(new RowKey(s, row), new RowEntry()); } protected void assignIncomingSortValues() { super.assignIncomingSortValues(); } protected void assignOutgoingSortValues() { super.assignOutgoingSortValues(); } void optimize(DirectedGraph g) { CompoundDirectedGraph graph = (CompoundDirectedGraph) g; Iterator containment = graph.containment.iterator(); while (containment.hasNext()) graph.removeEdge((Edge) containment.next()); graph.containment.clear(); new LocalOptimizer().visit(graph); } double evaluateNodeOutgoing() { double result = super.evaluateNodeOutgoing(); // result += Math.random() * rankSize * (1.0 - progress) / 3.0; if (progress > 0.2) { Subgraph s = node.getParent(); double connectivity = mergeConnectivity(s, node.rank + 1, result, progress); result = connectivity; } return result; } double evaluateNodeIncoming() { double result = super.evaluateNodeIncoming(); // result += Math.random() * rankSize * (1.0 - progress) / 3.0; if (progress > 0.2) { Subgraph s = node.getParent(); double connectivity = mergeConnectivity(s, node.rank - 1, result, progress); result = connectivity; } return result; } double mergeConnectivity(Subgraph s, int row, double result, double scaleFactor) { while (s != null && getRowEntry(s, row) == null) s = s.getParent(); if (s != null) { RowEntry entry = getRowEntry(s, row); double connectivity = entry.contribution / entry.count; result = connectivity * 0.3 + (0.7) * result; s = s.getParent(); } return result; } RowEntry getRowEntry(Subgraph s, int row) { key.s = s; key.rank = row; return (RowEntry) map.get(key); } void copyConstraints(NestingTree tree) { if (tree.subgraph != null) tree.sortValue = tree.subgraph.rowOrder; for (int i = 0; i < tree.contents.size(); i++) { Object child = tree.contents.get(i); if (child instanceof Node) { Node n = (Node) child; n.sortValue = n.rowOrder; } else { copyConstraints((NestingTree) child); } } } public void init(DirectedGraph g) { super.init(g); init = true; for (int row = 0; row < g.ranks.size(); row++) { Rank rank = g.ranks.getRank(row); NestingTree tree = NestingTree.buildNestingTreeForRank(rank); copyConstraints(tree); tree.recursiveSort(true); rank.clear(); tree.repopulateRank(rank); for (int j = 0; j < rank.count(); j++) { Node n = rank.getNode(j); Subgraph s = n.getParent(); while (s != null) { addRowEntry(s, row); s = s.getParent(); } } } } protected void postSort() { super.postSort(); if (init) updateRank(rank); } void updateRank(Rank rank) { for (int j = 0; j < rank.count(); j++) { Node n = rank.getNode(j); Subgraph s = n.getParent(); while (s != null) { getRowEntry(s, currentRow).reset(); s = s.getParent(); } } for (int j = 0; j < rank.count(); j++) { Node n = rank.getNode(j); Subgraph s = n.getParent(); while (s != null) { RowEntry entry = getRowEntry(s, currentRow); entry.count++; entry.contribution += n.index; s = s.getParent(); } } } }