package alm;
import java.util.ArrayList;
import java.util.List;
import linearProgramming.Constraint;
import linearProgramming.LinearProgrammingException;
import linearProgramming.OperatorType;
/**
* Represents a column defined by two x-tabs.
*/
public class Column {
/**
* The layout specification this column belongs to.
*/
LayoutSpec ls;
XTab left, right;
Column previous, next;
/**
* The constraint that fixes the left tab of this column to the right tab of
* the previous column.
*/
Constraint previousGlue;
/**
* The constraint that fixes the right tab of this column to the left tab of
* the next column.
*/
Constraint nextGlue;
/**
* The left boundary of the column.
*/
public XTab getLeft() {
return left;
}
/**
* The right boundary of the column.
*/
public XTab getRight() {
return right;
}
/**
* Constraints that are removed when the column is removed.
*/
public List<Constraint> constraints = new ArrayList<Constraint>();
/**
* The column directly to the left of this column. May be null.
*/
public Column getPrevious() {
return previous;
}
public void setPrevious(Column value) throws LinearProgrammingException {
// if there should be no column directly left of this column, then we
// have to
// separate any such column and can remove any constraint that was used
// to glue this column 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.right.isEqual(left);
nextGlue.Owner = this;
}
/**
* The column directly to the right of this column. May be null.
*/
public Column getNext() {
return next;
}
public void setNext(Column value) throws LinearProgrammingException {
// if there should be no column directly right of this column, then we
// have to
// separate any such column and can remove any constraint that was used
// to glue this column 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 = right.isEqual(value.left);
}
public String toString() {
return "Column(" + left.toString() + ", " + right.toString() + ")";
}
/**
* Inserts the given column directly to the left of this column.
*
* @param c
* the column to insert
*/
public void insertBefore(Column c) throws LinearProgrammingException {
setPrevious(c.previous);
setNext(c);
}
/**
* Inserts the given column directly to the right of this column.
*
* @param c
* the column to insert
*/
public void insertAfter(Column c) throws LinearProgrammingException {
setNext(c.next);
setPrevious(c);
}
/**
* Constrains this column to have the same width as the given column.
*
* @param column
* the column that should have the same width
* @return the resulting same-width constraint
*/
public Constraint hasSameWidthAs(Column column) throws LinearProgrammingException {
Constraint c = ls.addConstraint(-1, left, 1, right, 1, column.left, -1,
column.right, OperatorType.EQ, 0);
c.Owner = this;
constraints.add(c);
return c;
}
Column(LayoutSpec ls) {
this.ls = ls;
left = new XTab(ls);
right = new XTab(ls);
}
public void unlink() throws LinearProgrammingException {
if (previous != null)
previous.setNext(next);
else if (next != null)
next.setPrevious(previous);
}
/**
* Removes the column 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();
left.remove();
right.remove();
}
}