/**
* This program (working title: MAS Prover) is an automated tableaux prover
* for epistemic logic (S5n).
* Copyright (C) 2007 Elske van der Vaart and Gert van Valkenhoef
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package nl.rug.ai.mas.oops.render.tree;
import java.util.Observer;
import java.util.Observable;
import java.awt.Point;
import java.awt.Dimension;
import java.util.List;
public class TreeStructuredDiagram<CellType extends Cell> implements Observer {
private TreeStructure<CellType> d_tree;
private Placement<CellType> d_placement;
private boolean d_valid;
private int d_coherence; // j from C3(j)
public TreeStructuredDiagram(TreeStructure<CellType> tree,
int coherence) {
d_tree = tree;
d_placement = null;
d_valid = false;
d_coherence = coherence;
d_tree.addObserver(this);
}
public void update(Observable o, Object arg) {
if (o == d_tree && arg == null) {
d_valid = false;
}
}
public Placement<CellType> getPlacement() {
if (d_valid == false) {
layout();
}
return d_placement;
}
public Dimension getSize() {
if (d_valid == false) {
layout();
}
int maxX = 0; int maxY = 0;
int minX = d_placement.get(d_tree.getRoot()).x;
int minY = d_placement.get(d_tree.getRoot()).y;
for (CellType c : new IterableImpl<CellType>(d_tree.cellIterator())) {
Point p = d_placement.get(c);
if (p.x + c.getWidth() > maxX) {
maxX = p.x + c.getWidth();
}
if (p.y + c.getHeight() > maxY) {
maxY = p.y + c.getHeight();
}
if (p.x < minX) {
minX = p.x;
}
if (p.y < minY) {
minY = p.y;
}
}
return new Dimension(maxX - minX, maxY - minY);
}
private void layout() {
d_placement = subOpt(init());
// d_valid = true;
}
private int d_freeX;
private Placement<CellType> init() {
d_freeX = 0;
Placement<CellType> placement = new Placement<CellType>();
init(d_tree.getRoot(), placement, 0);
return placement;
}
private void init(CellType v, Placement<CellType> p, int freeY) {
if (d_tree.childCount(v) == 0) {
p.put(v, new Point(d_freeX, freeY));
d_freeX += v.getWidth();
} else {
CellType vFirst = d_tree.firstChild(v);
for(CellType s : new IterableImpl<CellType>(
d_tree.childIterator(v))) {
init(s, p, freeY + v.getHeight());
p.put(v, new Point(
p.get(vFirst).x +
Math.min(d_coherence, p.get(s).x - p.get(vFirst).x),
freeY));
d_freeX = Math.max(d_freeX, p.get(v).x + v.getWidth());
}
}
}
private Placement<CellType> subOpt(Placement<CellType> init) {
Placement<CellType> placement = new Placement<CellType>();
subOpt(d_tree.getRoot(), init, placement);
return placement;
}
private void subOpt(CellType q, Placement<CellType> in,
Placement<CellType> out) {
if (d_tree.childCount(q) == 0) {
shift(q, in, out);
} else {
for(CellType p : new IterableImpl<CellType>(
d_tree.childIterator(q))) {
subOpt(p, in, out);
in = out.copy();
}
// re-evaluate pi_in_x(q) satisfying C3(j)
int p1x = in.get(d_tree.firstChild(q)).x;
int pkx = in.get(d_tree.lastChild(q)).x;
int qx = p1x + Math.min(d_coherence, pkx - p1x);
in.put(q, new Point(qx, in.get(q).y));
shift(q, in, out);
}
}
private void shift(CellType q, Placement<CellType> in,
Placement<CellType> out) {
int move = 0;
if (d_tree.index(q) != 1) {
move = leftMovement(q, in);
}
moveLeft(q, move, in, out);
}
private int leftMovement(CellType q, Placement<CellType> placement) {
List<CellType> uj = placement.getByY(placement.get(q).y);
int idx = uj.indexOf(q);
if (idx == 0) {
return placement.get(q).y;
}
CellType c = (CellType)uj.get(idx - 1);
return placement.get(q).y - placement.get(c).y - c.getWidth();
}
private void moveLeft(CellType q, int dx,
Placement<CellType> in, Placement<CellType> out) {
out.clear();
out.putAll(in);
if (dx > 0) {
moveLeft(q, dx, out);
}
}
private void moveLeft(CellType q, int dx, Placement<CellType> p) {
Point point = p.get(q);
p.put(q, new Point(point.x - dx, point.y));
for (CellType r : new IterableImpl<CellType>(d_tree.childIterator(q))) {
moveLeft(r, dx, p);
}
}
}