package alm;
import java.util.ArrayList;
import java.util.List;
import linearProgramming.Constraint;
import linearProgramming.LinearProgrammingException;
import linearProgramming.OperatorType;
/**
* Represents a row defined by two y-tabs.
*/
public class Row {
/**
* The layout specification this row belongs to.
*/
LayoutSpec ls;
YTab top, bottom;
Row previous, next;
/**
* The constraint that fixes the top tab of this row to the bottom tab of
* the previous row.
*/
Constraint previousGlue;
/**
* The constraint that fixes the bottom tab of this row to the top tab of
* the next row.
*/
Constraint nextGlue;
/**
* The top boundary of the row.
*/
public YTab getTop() {
return top;
}
/**
* The bottom boundary of the row.
*/
public YTab getBottom() {
return bottom;
}
/**
* Constraints that are removed when the row is removed.
*/
public List<Constraint> constraints = new ArrayList<Constraint>();
/**
* The row directly above this row. May be null.
*/
public Row getPrevious() {
return previous;
}
public void setPrevious(Row value) throws LinearProgrammingException {
// if there should be no row directly above this row, then we have to
// separate any such row and can remove any constraint that was used
// to glue this row to it
if (value == null) {
if (previous == null)
return;
previous.next = null;
previous.nextGlue = null;
previous = null;
previousGlue.remove();
previousGlue = null;
return;
}
// otherwise we have to set up the pointers and the glue constraint
// accordingly
if (value.next != null)
value.setNext(null);
if (previous != null)
setPrevious(null);
previous = value;
previous.next = this;
previousGlue = value.nextGlue = value.bottom.isEqual(top);
previousGlue.Owner = this;
}
/**
* The row directly below this row. May be null.
*/
public Row getNext() {
return next;
}
public void setNext(Row value) throws LinearProgrammingException {
// if there should be no row directly below this row, then we have to
// separate any such row and can remove any constraint that was used
// to glue this row to it
if (value == null) {
if (next == null)
return;
next.previous = null;
next.previousGlue = null;
next = null;
nextGlue.remove();
nextGlue = null;
return;
}
// otherwise we have to set up the pointers and the glue constraint
// accordingly
if (value.previous != null)
value.setPrevious(null);
if (next != null)
setNext(null);
next = value;
next.previous = this;
nextGlue = value.previousGlue = bottom.isEqual(value.top);
nextGlue.Owner = this;
}
public String toString() {
return "Row(" + top.toString() + ", " + bottom.toString() + ")";
}
/**
* Inserts the given row directly above this row.
*
* @param r
* the row to insert
*/
public void insertBefore(Row r) throws LinearProgrammingException {
setPrevious(r.previous);
setNext(r);
}
/**
* Inserts the given row directly below this row.
*
* @param r
* the row to insert
*/
public void insertAfter(Row r) throws LinearProgrammingException {
setNext(r.next);
setPrevious(r);
}
/**
* Constrains this row to have the same height as the given row.
*
* @param row
* the row that should have the same height
* @return the resulting same-height constraint
*/
public Constraint hasSameHeightAs(Row row) throws Exception {
Constraint c = ls.addConstraint(-1, top, 1, bottom, 1, row.top, -1,
row.bottom, OperatorType.EQ, 0);
c.Owner = this;
constraints.add(c);
return c;
}
Row(LayoutSpec ls) {
this.ls = ls;
top = new YTab(ls);
bottom = new YTab(ls);
}
public void unlink() throws LinearProgrammingException {
if (previous != null)
previous.setNext(next);
else if (next != null)
next.setPrevious(previous);
}
/**
* Removes the row from the specification.
*/
public void remove() throws LinearProgrammingException {
if (previous != null)
previous.setNext(next);
if (nextGlue != null)
nextGlue.remove();
for (Constraint c : constraints)
c.remove();
top.remove();
bottom.remove();
}
}