/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.forms.widgets;

import java.util.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;

/**
 * This implementation of the layout algorithm attempts to position controls in
 * the composite using a two-pass autolayout HTML table altorithm recommeded by
 * HTML 4.01 W3C specification (see
 * http://www.w3.org/TR/html4/appendix/notes.html#h-B.5.2.2). The main
 * differences with GridLayout is that it has two passes and that width and
 * height are not calculated in the same pass.
 * <p>
 * The advantage of the algorithm over GridLayout is that it is capable of
 * flowing text controls capable of line wrap. These controls do not have
 * natural 'preferred size'. Instead, they are capable of providing the required
 * height if the width is set. Consequently, this algorithm first calculates the
 * widths that will be assigned to columns, and then passes those widths to the
 * controls to calculate the height. When a composite with this layout is a
 * child of the scrolling composite, they should interact in such a way that
 * reduction in the scrolling composite width results in the reflow and increase
 * of the overall height.
 * <p>
 * If none of the columns contain expandable and wrappable controls, the
 * end-result will be similar to the one provided by GridLayout. The difference
 * will show up for layouts that contain controls whose minimum and maximum
 * widths are not the same.
 * 
 * @see TableWrapData
 * @since 3.0
 */
public final class TableWrapLayout extends Layout implements ILayoutExtension {
	/**
	 * Number of columns to use when positioning children (default is 1).
	 */
	public int numColumns = 1;

	/**
	 * Left margin variable (default is 5).
	 */
	public int leftMargin = 5;

	/**
	 * Right margin variable (default is 5).
	 */
	public int rightMargin = 5;

	/**
	 * Top margin variable (default is 5).
	 */
	public int topMargin = 5;

	/**
	 * Botom margin variable (default is 5).
	 */
	public int bottomMargin = 5;

	/**
	 * Horizontal spacing (default is 5).
	 */
	public int horizontalSpacing = 5;

	/**
	 * Vertical spacing (default is 5).
	 */
	public int verticalSpacing = 5;

	/**
	 * If set to <code>true</code>, all the columns will have the same width.
	 * Otherwise, column widths will be computed based on controls in them and
	 * their layout data (default is <code>false</code>).
	 */
	public boolean makeColumnsEqualWidth = false;

	private boolean initialLayout = true;

	private Vector grid = null;

	private Hashtable rowspans;

	private int[] minColumnWidths, maxColumnWidths;

	private int widestColumnWidth;

	private int[] growingColumns;

	private int[] growingRows;

	private LayoutCache cache = new LayoutCache();

	private class RowSpan {
		Control child;

		int row;

		int column;

		int height;

		int totalHeight;

		public RowSpan(Control child, int column, int row) {
			this.child = child;
			this.column = column;
			this.row = row;
		}

		public void update(int currentRow, int rowHeight) {
			TableWrapData td = (TableWrapData) child.getLayoutData();
			if (currentRow - row <= td.rowspan - 1) {
				totalHeight += rowHeight;
				if (currentRow > row)
					totalHeight += verticalSpacing;
			}
		}

		public int getRequiredHeightIncrease() {
			if (totalHeight < height)
				return height - totalHeight;
			return 0;
		}
	}

	/**
	 * Implements ILayoutExtension. Should not be called directly.
	 * 
	 * @see ILayoutExtension
	 */
	public int computeMinimumWidth(Composite parent, boolean changed) {

		Control[] children = parent.getChildren();
		if (changed) {
			cache.flush();
		}

		cache.setControls(children);

		changed = true;
		initializeIfNeeded(parent, changed);
		if (initialLayout) {
			changed = true;
			initialLayout = false;
		}
		if (grid == null || changed) {
			changed = true;
			grid = new Vector();
			createGrid(parent);
		}
		if (minColumnWidths == null)
			minColumnWidths = new int[numColumns];
		for (int i = 0; i < numColumns; i++) {
			minColumnWidths[i] = 0;
		}
		return internalGetMinimumWidth(parent, changed);
	}

	/**
	 * Implements ILayoutExtension. Should not be called directly.
	 * 
	 * @see ILayoutExtension
	 */
	public int computeMaximumWidth(Composite parent, boolean changed) {
		Control[] children = parent.getChildren();
		if (changed) {
			cache.flush();
		}

		cache.setControls(children);

		changed = true;
		initializeIfNeeded(parent, changed);
		if (initialLayout) {
			changed = true;
			initialLayout = false;
		}
		if (grid == null || changed) {
			changed = true;
			grid = new Vector();
			createGrid(parent);
		}
		if (maxColumnWidths == null)
			maxColumnWidths = new int[numColumns];
		for (int i = 0; i < numColumns; i++) {
			maxColumnWidths[i] = 0;
		}
		return internalGetMaximumWidth(parent, changed);
	}

	/**
	 * @see Layout#layout(Composite, boolean)
	 */
	protected void layout(Composite parent, boolean changed) {

		Rectangle clientArea = parent.getClientArea();
		Control[] children = parent.getChildren();
		if (changed) {
			cache.flush();
		}

		if (children.length == 0)
			return;

		cache.setControls(children);

		int parentWidth = clientArea.width;
		changed = true;
		initializeIfNeeded(parent, changed);
		if (initialLayout) {
			changed = true;
			initialLayout = false;
		}
		if (grid == null || changed) {
			changed = true;
			grid = new Vector();
			createGrid(parent);
		}
		resetColumnWidths();
		int minWidth = internalGetMinimumWidth(parent, changed);
		int maxWidth = internalGetMaximumWidth(parent, changed);
		int tableWidth = parentWidth;
		int[] columnWidths;
		if (parentWidth <= minWidth) {
			tableWidth = minWidth;
			if (makeColumnsEqualWidth) {
				columnWidths = new int[numColumns];
				for (int i = 0; i < numColumns; i++) {
					columnWidths[i] = widestColumnWidth;
				}
			} else
				columnWidths = minColumnWidths;
		} else if (parentWidth > maxWidth) {
			if (growingColumns.length == 0) {
				tableWidth = maxWidth;
				columnWidths = maxColumnWidths;
			} else {
				columnWidths = new int[numColumns];
				int colSpace = tableWidth - leftMargin - rightMargin;
				colSpace -= (numColumns - 1) * horizontalSpacing;
				int extra = parentWidth - maxWidth;
				int colExtra = extra / growingColumns.length;
				for (int i = 0; i < numColumns; i++) {
					columnWidths[i] = maxColumnWidths[i];
					if (isGrowingColumn(i)) {
						columnWidths[i] += colExtra;
					}
				}
			}
		} else {
			columnWidths = new int[numColumns];
			if (makeColumnsEqualWidth) {
				int colSpace = tableWidth - leftMargin - rightMargin;
				colSpace -= (numColumns - 1) * horizontalSpacing;
				int col = colSpace / numColumns;
				for (int i = 0; i < numColumns; i++) {
					columnWidths[i] = col;
				}
			} else {
				columnWidths = assignExtraSpace(tableWidth, maxWidth, minWidth);
			}
		}
		int y = topMargin+clientArea.y;
		int[] rowHeights = computeRowHeights(children, columnWidths, changed);
		for (int i = 0; i < grid.size(); i++) {
			int rowHeight = rowHeights[i];
			int x = leftMargin+clientArea.x;
			TableWrapData[] row = (TableWrapData[]) grid.elementAt(i);
			for (int j = 0; j < numColumns; j++) {
				TableWrapData td = row[j];
				if (td.isItemData) {
					Control child = children[td.childIndex];
					placeControl(child, td, x, y, rowHeights, i);
				}
				x += columnWidths[j];
				if (j < numColumns - 1)
					x += horizontalSpacing;
			}
			y += rowHeight + verticalSpacing;
		}
	}

	int[] computeRowHeights(Control[] children, int[] columnWidths,
			boolean changed) {
		int[] rowHeights = new int[grid.size()];
		for (int i = 0; i < grid.size(); i++) {
			TableWrapData[] row = (TableWrapData[]) grid.elementAt(i);
			rowHeights[i] = 0;
			for (int j = 0; j < numColumns; j++) {
				TableWrapData td = row[j];
				if (td.isItemData == false) {
					continue;
				}
				Control child = children[td.childIndex];
				int span = td.colspan;
				int cwidth = 0;
				for (int k = j; k < j + span; k++) {
					cwidth += columnWidths[k];
					if (k < j + span - 1)
						cwidth += horizontalSpacing;
				}
				Point size = computeSize(td.childIndex, cwidth, td.indent, td.maxWidth, td.maxHeight);
				td.compWidth = cwidth;
				if (td.heightHint != SWT.DEFAULT) {
					size = new Point(size.x, td.heightHint);
				}
				td.compSize = size;
				RowSpan rowspan = (RowSpan) rowspans.get(child);
				if (rowspan == null) {
					rowHeights[i] = Math.max(rowHeights[i], size.y);
				} else
					rowspan.height = size.y;
			}
			updateRowSpans(i, rowHeights[i]);
		}
		for (Enumeration enm = rowspans.elements(); enm.hasMoreElements();) {
			RowSpan rowspan = (RowSpan) enm.nextElement();
			int increase = rowspan.getRequiredHeightIncrease();
			if (increase == 0)
				continue;
			TableWrapData td = (TableWrapData) rowspan.child.getLayoutData();
			int ngrowing = 0;
			int[] affectedRows = new int[grid.size()];
			for (int i = 0; i < growingRows.length; i++) {
				int growingRow = growingRows[i];
				if (growingRow >= rowspan.row
						&& growingRow < rowspan.row + td.rowspan) {
					affectedRows[ngrowing++] = growingRow;
				}
			}
			if (ngrowing == 0) {
				ngrowing = 1;
				affectedRows[0] = rowspan.row + td.rowspan - 1;
			}
			increase += increase % ngrowing;
			int perRowIncrease = increase / ngrowing;
			for (int i = 0; i < ngrowing; i++) {
				int growingRow = affectedRows[i];
				rowHeights[growingRow] += perRowIncrease;
			}
		}
		return rowHeights;
	}

	boolean isGrowingColumn(int col) {
		if (growingColumns == null)
			return false;
		for (int i = 0; i < growingColumns.length; i++) {
			if (col == growingColumns[i])
				return true;
		}
		return false;
	}

	int[] assignExtraSpace(int tableWidth, int maxWidth, int minWidth) {
		int fixedPart = leftMargin + rightMargin + (numColumns - 1)
				* horizontalSpacing;
		int D = maxWidth - minWidth;
		int W = tableWidth - fixedPart - minWidth;
		int widths[] = new int[numColumns];
		int rem = 0;
		for (int i = 0; i < numColumns; i++) {
			int cmin = minColumnWidths[i];
			int cmax = maxColumnWidths[i];
			int d = cmax - cmin;
			int extra = D != 0 ? (d * W) / D : 0;
			if (i < numColumns - 1) {
				widths[i] = cmin + extra;
				rem += widths[i];
			} else {
				widths[i] = tableWidth - fixedPart - rem;
			}
		}
		return widths;
	}

	Point computeSize(int childIndex, int width, int indent, int maxWidth, int maxHeight) {
		int widthArg = width - indent;
		SizeCache controlCache = cache.getCache(childIndex);
		if (!isWrap(controlCache.getControl()))
			widthArg = SWT.DEFAULT;
		Point size = controlCache.computeSize(widthArg, SWT.DEFAULT);
		if (maxWidth!=SWT.DEFAULT)
			size.x = Math.min(size.x, maxWidth);
		if (maxHeight!=SWT.DEFAULT)
			size.y = Math.min(size.y, maxHeight);
		size.x += indent;
		return size;
	}

	void placeControl(Control control, TableWrapData td, int x, int y,
			int[] rowHeights, int row) {
		int xloc = x + td.indent;
		int yloc = y;
		int height = td.compSize.y;
		int colWidth = td.compWidth - td.indent;
		int width = td.compSize.x-td.indent;
		width = Math.min(width, colWidth);
		int slotHeight = rowHeights[row];
		RowSpan rowspan = (RowSpan) rowspans.get(control);
		if (rowspan != null) {
			slotHeight = 0;
			for (int i = row; i < row + td.rowspan; i++) {
				if (i > row)
					slotHeight += verticalSpacing;
				slotHeight += rowHeights[i];
			}
		}
		// align horizontally
		if (td.align == TableWrapData.CENTER) {
			xloc = x + colWidth / 2 - width / 2;
		} else if (td.align == TableWrapData.RIGHT) {
			xloc = x + colWidth - width;
		} else if (td.align == TableWrapData.FILL) {
			width = colWidth;
		}
		// align vertically
		if (td.valign == TableWrapData.MIDDLE) {
			yloc = y + slotHeight / 2 - height / 2;
		} else if (td.valign == TableWrapData.BOTTOM) {
			yloc = y + slotHeight - height;
		} else if (td.valign == TableWrapData.FILL) {
			height = slotHeight;
		}
		control.setBounds(xloc, yloc, width, height);
	}

	void createGrid(Composite composite) {
		int row, column, rowFill, columnFill;
		Control[] children;
		TableWrapData spacerSpec;
		Vector growingCols = new Vector();
		Vector growingRows = new Vector();
		rowspans = new Hashtable();
		// 
		children = composite.getChildren();
		if (children.length == 0)
			return;
		// 
		grid.addElement(createEmptyRow());
		row = 0;
		column = 0;
		// Loop through the children and place their associated layout specs in
		// the
		// grid. Placement occurs left to right, top to bottom (i.e., by row).
		for (int i = 0; i < children.length; i++) {
			// Find the first available spot in the grid.
			Control child = children[i];
			TableWrapData spec = (TableWrapData) child.getLayoutData();
			while (((TableWrapData[]) grid.elementAt(row))[column] != null) {
				column = column + 1;
				if (column >= numColumns) {
					row = row + 1;
					column = 0;
					if (row >= grid.size()) {
						grid.addElement(createEmptyRow());
					}
				}
			}
			// See if the place will support the widget's horizontal span. If
			// not, go to the
			// next row.
			if (column + spec.colspan - 1 >= numColumns) {
				grid.addElement(createEmptyRow());
				row = row + 1;
				column = 0;
			}
			// The vertical span for the item will be at least 1. If it is > 1,
			// add other rows to the grid.
			if (spec.rowspan > 1) {
				rowspans.put(child, new RowSpan(child, column, row));
			}
			for (int j = 2; j <= spec.rowspan; j++) {
				if (row + j > grid.size()) {
					grid.addElement(createEmptyRow());
				}
			}
			// Store the layout spec. Also cache the childIndex. NOTE: That we
			// assume the children of a
			// composite are maintained in the order in which they are created
			// and added to the composite.
			((TableWrapData[]) grid.elementAt(row))[column] = spec;
			spec.childIndex = i;
			if (spec.grabHorizontal) {
				updateGrowingColumns(growingCols, spec, column);
			}
			if (spec.grabVertical) {
				updateGrowingRows(growingRows, spec, row);
			}
			// Put spacers in the grid to account for the item's vertical and
			// horizontal
			// span.
			rowFill = spec.rowspan - 1;
			columnFill = spec.colspan - 1;
			for (int r = 1; r <= rowFill; r++) {
				for (int c = 0; c < spec.colspan; c++) {
					spacerSpec = new TableWrapData();
					spacerSpec.isItemData = false;
					((TableWrapData[]) grid.elementAt(row + r))[column + c] = spacerSpec;
				}
			}
			for (int c = 1; c <= columnFill; c++) {
				for (int r = 0; r < spec.rowspan; r++) {
					spacerSpec = new TableWrapData();
					spacerSpec.isItemData = false;
					((TableWrapData[]) grid.elementAt(row + r))[column + c] = spacerSpec;
				}
			}
			column = column + spec.colspan - 1;
		}
		// Fill out empty grid cells with spacers.
		for (int k = column + 1; k < numColumns; k++) {
			spacerSpec = new TableWrapData();
			spacerSpec.isItemData = false;
			((TableWrapData[]) grid.elementAt(row))[k] = spacerSpec;
		}
		for (int k = row + 1; k < grid.size(); k++) {
			spacerSpec = new TableWrapData();
			spacerSpec.isItemData = false;
			((TableWrapData[]) grid.elementAt(k))[column] = spacerSpec;
		}
		growingColumns = new int[growingCols.size()];
		for (int i = 0; i < growingCols.size(); i++) {
			growingColumns[i] = ((Integer) growingCols.get(i)).intValue();
		}
		this.growingRows = new int[growingRows.size()];
		for (int i = 0; i < growingRows.size(); i++) {
			this.growingRows[i] = ((Integer) growingRows.get(i)).intValue();
		}
	}

	private void updateGrowingColumns(Vector growingColumns,
			TableWrapData spec, int column) {
		int affectedColumn = column + spec.colspan - 1;
		for (int i = 0; i < growingColumns.size(); i++) {
			Integer col = (Integer) growingColumns.get(i);
			if (col.intValue() == affectedColumn)
				return;
		}
		growingColumns.add(new Integer(affectedColumn));
	}

	private void updateGrowingRows(Vector growingRows, TableWrapData spec,
			int row) {
		int affectedRow = row + spec.rowspan - 1;
		for (int i = 0; i < growingRows.size(); i++) {
			Integer irow = (Integer) growingRows.get(i);
			if (irow.intValue() == affectedRow)
				return;
		}
		growingRows.add(new Integer(affectedRow));
	}

	private TableWrapData[] createEmptyRow() {
		TableWrapData[] row = new TableWrapData[numColumns];
		for (int i = 0; i < numColumns; i++)
			row[i] = null;
		return row;
	}

	/**
	 * @see Layout#computeSize(Composite, int, int, boolean)
	 */
	protected Point computeSize(Composite parent, int wHint, int hHint,
			boolean changed) {
		Control[] children = parent.getChildren();
		if (changed) {
			cache.flush();
		}
		if (children.length == 0) {
			return new Point(0, 0);
		}
		cache.setControls(children);

		int parentWidth = wHint;
		changed = true;
		initializeIfNeeded(parent, changed);
		if (initialLayout) {
			changed = true;
			initialLayout = false;
		}
		if (grid == null || changed) {
			changed = true;
			grid = new Vector();
			createGrid(parent);
		}
		resetColumnWidths();
		int minWidth = internalGetMinimumWidth(parent, changed);
		int maxWidth = internalGetMaximumWidth(parent, changed);
		int tableWidth = parentWidth;
		int[] columnWidths;
		if (parentWidth <= minWidth) {
			tableWidth = minWidth;
			if (makeColumnsEqualWidth) {
				columnWidths = new int[numColumns];
				for (int i = 0; i < numColumns; i++) {
					columnWidths[i] = widestColumnWidth;
				}
			} else
				columnWidths = minColumnWidths;
		} else if (parentWidth > maxWidth) {
			if (makeColumnsEqualWidth) {
				columnWidths = new int[numColumns];
				int colSpace = parentWidth - leftMargin - rightMargin;
				colSpace -= (numColumns - 1) * horizontalSpacing;
				int col = colSpace / numColumns;
				for (int i = 0; i < numColumns; i++) {
					columnWidths[i] = col;
				}
			} else {
				tableWidth = maxWidth;
				columnWidths = maxColumnWidths;
			}
		} else {
			columnWidths = new int[numColumns];
			if (makeColumnsEqualWidth) {
				int colSpace = tableWidth - leftMargin - rightMargin;
				colSpace -= (numColumns - 1) * horizontalSpacing;
				int col = colSpace / numColumns;
				for (int i = 0; i < numColumns; i++) {
					columnWidths[i] = col;
				}
			} else {
				columnWidths = assignExtraSpace(tableWidth, maxWidth, minWidth);
			}
		}
		int totalHeight = 0;
		int innerHeight = 0;
		// compute widths
		for (int i = 0; i < grid.size(); i++) {
			TableWrapData[] row = (TableWrapData[]) grid.elementAt(i);
			// assign widths, calculate heights
			int rowHeight = 0;
			for (int j = 0; j < numColumns; j++) {
				TableWrapData td = row[j];
				if (td.isItemData == false) {
					continue;
				}
				Control child = children[td.childIndex];
				int span = td.colspan;
				int cwidth = 0;
				for (int k = j; k < j + span; k++) {
					if (k > j)
						cwidth += horizontalSpacing;
					cwidth += columnWidths[k];
				}
				int cy = td.heightHint;
				if (cy == SWT.DEFAULT) {
					Point size = computeSize(td.childIndex, cwidth, td.indent, td.maxWidth, td.maxHeight);
					cy = size.y;
				}
				RowSpan rowspan = (RowSpan) rowspans.get(child);
				if (rowspan != null) {
					// don't take the height of this child into acount
					// because it spans multiple rows
					rowspan.height = cy;
				} else {
					rowHeight = Math.max(rowHeight, cy);
				}
			}
			updateRowSpans(i, rowHeight);
			if (i > 0)
				innerHeight += verticalSpacing;
			innerHeight += rowHeight;
		}
		if (!rowspans.isEmpty())
			innerHeight = compensateForRowSpans(innerHeight);
		totalHeight = topMargin + innerHeight + bottomMargin;
		return new Point(tableWidth, totalHeight);
	}

	private void updateRowSpans(int row, int rowHeight) {
		if (rowspans == null || rowspans.size() == 0)
			return;
		for (Enumeration enm = rowspans.elements(); enm.hasMoreElements();) {
			RowSpan rowspan = (RowSpan) enm.nextElement();
			rowspan.update(row, rowHeight);
		}
	}

	private int compensateForRowSpans(int totalHeight) {
		for (Enumeration enm = rowspans.elements(); enm.hasMoreElements();) {
			RowSpan rowspan = (RowSpan) enm.nextElement();
			totalHeight += rowspan.getRequiredHeightIncrease();
		}
		return totalHeight;
	}

	int internalGetMinimumWidth(Composite parent, boolean changed) {
		if (changed)
			calculateMinimumColumnWidths(parent, true);
		int minimumWidth = 0;
		widestColumnWidth = 0;
		if (makeColumnsEqualWidth) {
			for (int i = 0; i < numColumns; i++) {
				widestColumnWidth = Math.max(widestColumnWidth,
						minColumnWidths[i]);
			}
		}
		for (int i = 0; i < numColumns; i++) {
			if (i > 0)
				minimumWidth += horizontalSpacing;
			if (makeColumnsEqualWidth)
				minimumWidth += widestColumnWidth;
			else
				minimumWidth += minColumnWidths[i];
		}
		// add margins
		minimumWidth += leftMargin + rightMargin;
		return minimumWidth;
	}

	int internalGetMaximumWidth(Composite parent, boolean changed) {
		if (changed)
			calculateMaximumColumnWidths(parent, true);
		int maximumWidth = 0;
		for (int i = 0; i < numColumns; i++) {
			if (i > 0)
				maximumWidth += horizontalSpacing;
			maximumWidth += maxColumnWidths[i];
		}
		// add margins
		maximumWidth += leftMargin + rightMargin;
		return maximumWidth;
	}

	void resetColumnWidths() {
		if (minColumnWidths == null)
			minColumnWidths = new int[numColumns];
		if (maxColumnWidths == null)
			maxColumnWidths = new int[numColumns];
		for (int i = 0; i < numColumns; i++) {
			minColumnWidths[i] = 0;
		}
		for (int i = 0; i < numColumns; i++) {
			maxColumnWidths[i] = 0;
		}
	}

	void calculateMinimumColumnWidths(Composite parent, boolean changed) {
		//Control[] children = parent.getChildren();
		for (int i = 0; i < grid.size(); i++) {
			TableWrapData[] row = (TableWrapData[]) grid.elementAt(i);
			for (int j = 0; j < numColumns; j++) {
				TableWrapData td = row[j];
				if (td.isItemData == false)
					continue;
				//Control child = children[td.childIndex];

				SizeCache childCache = cache.getCache(td.childIndex);
				int minWidth = childCache.computeMinimumWidth();
				if (td.maxWidth!=SWT.DEFAULT)
					minWidth = Math.min(minWidth, td.maxWidth);

				minWidth += td.indent;
				if (td.colspan == 1)
					minColumnWidths[j] = Math.max(minColumnWidths[j], minWidth);
				else {
					// check if the current minimum width is enough to
					// support the control; if not, add the delta to
					// the last column
					int current = 0;
					for (int k = j; k < j + td.colspan; k++) {
						if (k > j)
							current += horizontalSpacing;
						current += minColumnWidths[k];
					}
					if (minWidth <= current) {
						// we are ok - nothing to do here
					} else {
						int ndiv = 0;
						if (growingColumns != null) {
							for (int k = j; k < j + td.colspan; k++) {
								if (isGrowingColumn(k)) {
									ndiv++;
								}
							}
						}
						if (ndiv == 0) {
							// add the delta to the last column
							minColumnWidths[j + td.colspan - 1] += minWidth
									- current;
						} else {
							// distribute the delta to the growing
							// columns
							int percolumn = (minWidth - current) / ndiv;
							if ((minWidth - current) % ndiv > 0)
								percolumn++;
							for (int k = j; k < j + td.colspan; k++) {
								if (isGrowingColumn(k))
									minColumnWidths[k] += percolumn;
							}
						}
					}
				}
			}
		}
	}

	boolean isWrap(Control control) {
		if (control instanceof Composite
				&& ((Composite) control).getLayout() instanceof ILayoutExtension)
			return true;
		return (control.getStyle() & SWT.WRAP) != 0;
	}

	void calculateMaximumColumnWidths(Composite parent, boolean changed) {
		//Control[] children = parent.getChildren();
		for (int i = 0; i < numColumns; i++) {
			maxColumnWidths[i] = 0;
		}
		for (int i = 0; i < grid.size(); i++) {
			TableWrapData[] row = (TableWrapData[]) grid.elementAt(i);
			for (int j = 0; j < numColumns; j++) {
				TableWrapData td = row[j];
				if (td.isItemData == false)
					continue;
				//Control child = children[td.childIndex];

				SizeCache sc = cache.getCache(td.childIndex);
				int maxWidth = sc.computeMaximumWidth();
				if (td.maxWidth!=SWT.DEFAULT)
					maxWidth = Math.min(maxWidth, td.maxWidth);

				maxWidth += td.indent;
				if (td.colspan == 1)
					maxColumnWidths[j] = Math.max(maxColumnWidths[j], maxWidth);
				else {
					// check if the current maximum width is enough to
					// support the control; if not, add the delta to
					// the last column
					int current = 0;
					for (int k = j; k < j + td.colspan; k++) {
						if (k > j)
							current += horizontalSpacing;
						current += maxColumnWidths[k];
					}
					if (maxWidth <= current) {
						// we are ok - nothing to do here
					} else {
						int ndiv = 0;
						if (growingColumns != null) {
							for (int k = j; k < j + td.colspan; k++) {
								if (isGrowingColumn(k)) {
									ndiv++;
								}
							}
						}
						if (ndiv == 0) {
							// add the delta to the last column
							maxColumnWidths[j + td.colspan - 1] += maxWidth
									- current;
						} else {
							// distribute the delta to the growing
							// columns
							int percolumn = (maxWidth - current) / ndiv;
							if ((maxWidth - current) % ndiv > 0)
								percolumn++;
							// divide the distribution per row
							// if the control will span multiple rows
							percolumn /= td.rowspan;
							for (int k = j; k < j + td.colspan; k++) {
								if (isGrowingColumn(k))
									maxColumnWidths[k] += percolumn;
							}
						}
					}
				}
			}
		}
	}

	private void initializeIfNeeded(Composite parent, boolean changed) {
		if (changed)
			initialLayout = true;
		if (initialLayout) {
			initializeLayoutData(parent);
			initialLayout = false;
		}
	}

	void initializeLayoutData(Composite composite) {
		Control[] children = composite.getChildren();
		for (int i = 0; i < children.length; i++) {
			Control child = children[i];
			if (child.getLayoutData() == null) {
				child.setLayoutData(new TableWrapData());
			}
		}
	}
}
