package opg.spacer; import java.awt.Point; import opg.spacer.Node.NodeGender; import opg.spacer.Node.NodeType; public class Spacer { public static void space(Node n) { n.bounds.clear(); for (Node child : n.children) { space(child); } n.bounds.add(n.d.height / 2, -n.d.height / 2); if (n.children.size() == 1) { Node child = n.getFirstChild(); n.bounds.addAll(child.bounds); if(n.type == NodeType.Ancestor){ int height = child.d.height; if(child.gender == NodeGender.Male){ n.bounds.shift(height/2); } else if(child.gender == NodeGender.Female){ n.bounds.shift(-height/2); } } n.offsets.add(0); } else if (n.children.size() > 1) { // copy first child limits int generation = 0; n.offsets.add(0); while (true) { if (!n.children.get(0).bounds.has(generation)) { break; } int upper = n.children.get(0).bounds.getUpper(generation); int lower = n.children.get(0).bounds.getLower(generation); n.bounds.add(upper, lower); generation++; } // merge children trees into parent tree for (int i = 1; i < n.children.size(); i++) { combineChildTree(n, n.children.get(i)); } // center parent among children n.bounds.shift((n.bounds.getUpper(1) - n.bounds.getLower(1)) / 2 - n.bounds.getUpper(1)); } // update children offset relative to parent height for (int i = 0; i < n.offsets.size(); i++) { int previous = n.offsets.get(i); n.offsets.set(i, previous + n.d.height / 2); } } private static void combineChildTree(Node parent, Node child) { int minSpacing = child.d.height; int generation = 0; while (true) { if (!parent.bounds.has(generation + 1) || !child.bounds.has(generation)) { break; } int lower = parent.bounds.getLower(generation + 1); int upper = child.bounds.getUpper(generation); int spacing = -lower + upper; if (spacing > minSpacing) { minSpacing = spacing; } generation++; } parent.offsets.add(minSpacing); generation = 0; while (true) { if (!parent.bounds.has(generation + 1) && !child.bounds.has(generation)) { // tree ends at this generation, so stop break; } if (parent.bounds.has(generation + 1) && !child.bounds.has(generation)) { // previous lower is still correct } else if (!parent.bounds.has(generation + 1) && child.bounds.has(generation)) { int lower = child.bounds.getLower(generation); int upper = child.bounds.getUpper(generation); parent.bounds.add(-minSpacing + upper, -minSpacing + lower); } else { int value = -minSpacing + child.bounds.getLower(generation); parent.bounds.updateLower(generation + 1, value); } generation++; } } public static void position(Node parent) { if (parent.parent == null) { // top left corner parent.p = new Point(0, parent.d.height/2); } for (int i = 0; i < parent.children.size(); i++) { Node child = parent.children.get(i); int x = parent.p.x + parent.d.width; int y = parent.p.y - parent.d.height/2 + child.d.height/2 + parent.bounds.getUpper(1) - parent.offsets.get(i); child.p = new Point(x, y); position(parent.children.get(i)); } } }