*/
protected void preLayout() {
// super.preLayout will setup the block box.
super.preLayout();
ICSSStyle style = this.getCSSStyle();
_hspacing = _vspacing = 3; // default value
if (style != null) {
Object borderspacing = style
.getStyleProperty(ICSSPropertyID.ATTR_BORDER_SPACING);
if (borderspacing instanceof int[]) {
int[] intvalues = (int[]) borderspacing;
_hspacing = intvalues[0];
_vspacing = intvalues[1];
} else {
ITagEditInfo info = (ITagEditInfo) style
.getAdapter(ITagEditInfo.class);
if (info != null && info.needTableDecorator()) {
// default decorating value. to make things look more
// separated.
if (_hspacing < 5) {
_hspacing = 5;
}
if (_vspacing < 5) {
_vspacing = 5;
}
}
}
}
// TODO: support caption
_tableInfo = new TableInfo(getCSSFigure());
// construct the table structure.
_tableInfo.constructTable();
// calculate the user specified width/height for table and cells.
// contentWidth is the user specified content width. If <= 0 means no
// user
// specification.
int contentWidth = this._blockBox.getContentWidth();
int availableWidth = this._blockBox.getRecommendedContentWidth();
int contentHeight = this._blockBox.getContentHeight();
_tableInfo.calculateWidth(contentWidth, availableWidth);
_tableInfo.calculateHeight(contentHeight);
int columnCount = _tableInfo.getColumnCount();
int columnMinWidths[] = new int[columnCount];
int columnMaxWidths[] = new int[columnCount];
// For each column, determine a maximum and minimum column width from
// the cells that span only that column. The minimum is that required by
// the cell with the largest minimum cell width (or the column 'width',
// whichever is larger). The maximum is that required by the cell with
// the
// largest maximum cell width (or the column 'width', whichever is
// larger).
List cells = _tableInfo.getCells();
for (int i = 0, size = cells.size(); i < size; i++) {
TableCellInfo cellinfo = (TableCellInfo) cells.get(i);
if (cellinfo.getColSpan() == 1) {
int column = cellinfo.getColumnIndex();
Dimension mincw = cellinfo.getMinCWDimension();
Dimension maxcw = cellinfo.getMaxCWDimension();
if (maxcw.width < mincw.width) {
maxcw.width = mincw.width;
}
if (mincw.width > columnMinWidths[column]) {
columnMinWidths[column] = mincw.width;
}
if (maxcw.width > columnMaxWidths[column]) {
columnMaxWidths[column] = maxcw.width;
}
}
}
// For caption, determine a maximum and minimum width from it.
int captionWidth = 0;
if (_tableInfo.getCaption() != null) {
captionWidth = _tableInfo.getCaption().getDimension().width;
}
// For each cell that spans more than one column, increase the
// minimum widths of the columns it spans so that together, they
// are at least as wide as the cell. Do the same for the maximum
// widths. If possible, widen all spanned columns by approximately
// the same amount.
for (int i = 0, size = cells.size(); i < size; i++) {
TableCellInfo cellinfo = (TableCellInfo) cells.get(i);
int colspan = cellinfo.getColSpan();
if (colspan > 1) {
int column = cellinfo.getColumnIndex();
Dimension mincw = cellinfo.getMinCWDimension();
Dimension maxcw = cellinfo.getMaxCWDimension();
adjustWidth(column, colspan, mincw.width, columnMinWidths);
adjustWidth(column, colspan, maxcw.width, columnMaxWidths);
}
}
int sigmaMinWidth = 0;
int sigmaMaxWidth = 0;
for (int i = 0; i < columnMinWidths.length; i++) {
sigmaMinWidth += columnMinWidths[i];
if (columnMaxWidths[i] == Integer.MAX_VALUE) {
sigmaMaxWidth = Integer.MAX_VALUE;
} else if (sigmaMaxWidth != Integer.MAX_VALUE) {
sigmaMaxWidth += columnMaxWidths[i];
if (sigmaMaxWidth < 0) {
sigmaMaxWidth = Integer.MAX_VALUE;
}
}
}
int spacingall = (columnMinWidths.length + 1) * _hspacing;
sigmaMinWidth += spacingall;
if (sigmaMaxWidth != Integer.MAX_VALUE) {
sigmaMaxWidth += spacingall;
if (sigmaMaxWidth < 0) {
sigmaMaxWidth = Integer.MAX_VALUE;
}
}
int tableWidth = _tableInfo.getTableWidth();
if (tableWidth > 0) {
// If the 'table' or 'inline-table' element's 'width' property has a
// specified value (W) other than 'auto', the property's computed
// value
// is the greater of W and the minimum width required by all the
// columns
// plus cell spacing or borders (MIN). If W is greater than MIN, the
// extra
// width should be distributed over the columns.
int maxMin = Math.max(captionWidth, sigmaMinWidth);
if (maxMin >= tableWidth) {
tableWidth = maxMin;
}
distribute(tableWidth - sigmaMinWidth, columnMinWidths,
columnMaxWidths);
} else {
// If the 'table' or 'inline-table' element has 'width: auto', the
// computed
// table width is the greater of the table's containing block width
// and MIN.
// However, if the maximum width required by the columns plus cell
// spacing or
// borders (MAX) is less than that of the containing block, use MAX.
// int availableWidth = this.getCurrentLine().getAvailableWidth();
int maxMin = Math.max(captionWidth, sigmaMaxWidth);
if (maxMin <= availableWidth) {
// TODO: if _tableInfo.hasWidthPercentage, then we need take
// that into consideration
// to distribute the column width. Left to next version.
tableWidth = maxMin;
// columnMinWidths = columnMaxWidths;
} else {
tableWidth = availableWidth;
}
distribute(tableWidth - sigmaMinWidth, columnMinWidths,
columnMaxWidths);
}
// now columnMinWidths contains width for each column
_columnWidths = columnMinWidths;
// ok, we have finished calculating column width.
// next we need to find out row heights.
_rowHeights = new int[_tableInfo.getRowCount()];
// first find out those TR that has height settings and use them.
List rows = _tableInfo.getRows();
for (int i = 0, size = rows.size(); i < size && i < _rowHeights.length; i++) {
TableRowInfo rowInfo = (TableRowInfo) rows.get(i);
if (rowInfo.getSpecifiedRowHeight() > 0) {
_rowHeights[i] = rowInfo.getSpecifiedRowHeight();
}
}
// First the cells don't span multiple rows.
cells = _tableInfo.getCells();
for (int i = 0, size = cells.size(); i < size; i++) {
TableCellInfo cellinfo = (TableCellInfo) cells.get(i);
IFigure figure = cellinfo.getFigure();
int rowspan = cellinfo.getRowSpan();
if (rowspan == 1) {
int cellWidth = getCellWidth(cellinfo, _columnWidths);
Dimension d = figure.getPreferredSize(cellWidth, cellinfo
.getHeight());
if (d.height > _rowHeights[cellinfo.getRowIndex()]) {
_rowHeights[cellinfo.getRowIndex()] = d.height;
}
}
}
// Next those cells span multiple rows.
cells = _tableInfo.getCells();
for (int i = 0, size = cells.size(); i < size; i++) {
TableCellInfo cellinfo = (TableCellInfo) cells.get(i);
IFigure figure = cellinfo.getFigure();
int rowspan = cellinfo.getRowSpan();
if (rowspan > 1) {
int cellWidth = getCellWidth(cellinfo, _columnWidths);
Dimension d = figure.getPreferredSize(cellWidth, cellinfo
.getHeight());
if (d.height > getCellHeight(cellinfo, _rowHeights)) {
adjustHeight(cellinfo.getRowIndex(), rowspan, d.height,
_rowHeights);
}
}
}
// Next we may need distribute height.
int sigmaHeight = (_tableInfo.getRowCount() + 1) * _vspacing;
for (int i = 0; i < _rowHeights.length; i++) {
sigmaHeight += _rowHeights[i];
}
if (sigmaHeight < contentHeight) {
distributeHeights(contentHeight - sigmaHeight, _rowHeights);
}
// now we have calculated the width and height of all cells.
// FIXME: border?
Insets insets = (style == null ? new Insets() : style.getBorderInsets()
.getAdded(style.getPaddingInsets()));
_internalTableWidth = (_tableInfo.getColumnCount() + 1) * _hspacing;
for (int i = 0; i < _columnWidths.length; i++) {
_internalTableWidth += _columnWidths[i];
}
int minWidth = getLengthValue(style, ICSSPropertyID.ATTR_MIN_WIDTH);