/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.update.ui.forms.internal;
import java.util.Vector;

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. 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.
 */

public class HTMLTableLayout extends Layout implements ILayoutExtension {
	public int numColumns = 1;
	public int leftMargin = 5;
	public int rightMargin = 5;
	public int topMargin = 5;
	public int bottomMargin = 5;
	public int horizontalSpacing = 5;
	public int verticalSpacing = 5;
	public boolean makeColumnsEqualWidth = false;

	private boolean initialLayout = true;
	private Vector grid = null;
	private int[] minColumnWidths, maxColumnWidths;
	private int widestColumnWidth;
	private int[] growingColumns;

	public int getMinimumWidth(Composite parent, boolean changed) {
		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);
	}

	public int getMaximumWidth(Composite parent, boolean changed) {
		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 (children.length == 0)
			return;
		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 {
				int[] extraSpace =
					calculateExtraSpace(tableWidth, maxWidth, minWidth);
				for (int i = 0; i < numColumns; i++) {
					int minCWidth = minColumnWidths[i];
					columnWidths[i] = minCWidth + extraSpace[i];
				}
			}
		}
		int x = 0;
		int y = topMargin;
		// assign widths
		for (int i = 0; i < grid.size(); i++) {
			TableData[] row = (TableData[]) grid.elementAt(i);
			// assign widths, calculate heights
			int rowHeight = 0;
			x = leftMargin;
			for (int j = 0; j < numColumns; j++) {
				TableData 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(child, cwidth, changed);
				td.compWidth = cwidth;
				if (td.heightHint != SWT.DEFAULT) {
					size = new Point(size.x, td.heightHint);
				}
				td.compSize = size;
				rowHeight = Math.max(rowHeight, size.y);
			}
			for (int j = 0; j < numColumns; j++) {
				TableData td = row[j];
				if (td.isItemData == false) {
					continue;
				}
				Control child = children[td.childIndex];
				placeControl(child, td, x, y, rowHeight);
				x += td.compWidth;
				if (j < numColumns - 1)
					x += horizontalSpacing;
			}
			y += rowHeight + verticalSpacing;
		}
	}

	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[] calculateExtraSpace(int tableWidth, int maxWidth, int minWidth) {
		int fixedPart =
			leftMargin + rightMargin + (numColumns - 1) * horizontalSpacing;
		int D = maxWidth - minWidth;

		int W = tableWidth - fixedPart - minWidth;

		int extraSpace[] = 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) {
				extraSpace[i] = extra;
				rem += extra;
			} else {
				extraSpace[i] = W - rem;
			}
		}
		return extraSpace;
	}

	Point computeSize(Control child, int width, boolean changed) {
		int widthArg = width;
		if (!isWrap(child))
			widthArg = SWT.DEFAULT;
		Point size = child.computeSize(widthArg, SWT.DEFAULT, changed);
		return size;
	}

	void placeControl(
		Control control,
		TableData td,
		int x,
		int y,
		int rowHeight) {
		int xloc = x + td.indent;
		int yloc = y;
		int width = td.compSize.x;
		int height = td.compSize.y;
		int colWidth = td.compWidth;

		// align horizontally
		if (td.align == TableData.CENTER) {
			xloc = x + colWidth / 2 - width / 2;
		} else if (td.align == TableData.RIGHT) {
			xloc = x + colWidth - width;
		} else if (td.align == TableData.FILL) {
			width = colWidth;
		}
		// align vertically
		if (td.valign == TableData.MIDDLE) {
			yloc = y + rowHeight / 2 - height / 2;
		} else if (td.valign == TableData.BOTTOM) {
			yloc = y + rowHeight - height;
		} else if (td.valign == TableData.FILL) {
			height = rowHeight;
		}
		control.setBounds(xloc, yloc, width, height);
	}

	void createGrid(Composite composite) {
		int row, column, rowFill, columnFill;
		Control[] children;
		TableData spacerSpec;
		Vector growingCols = new Vector();

		// 
		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];
			TableData spec = (TableData) child.getLayoutData();
			while (((TableData[]) 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.
			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.
			 ((TableData[]) grid.elementAt(row))[column] = spec;
			spec.childIndex = i;

			if (spec.grabHorizontal) {
				updateGrowingColumns(growingCols, spec, column);
			}

			// 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 TableData();
					spacerSpec.isItemData = false;
					((TableData[]) grid.elementAt(row + r))[column + c] =
						spacerSpec;
				}
			}
			for (int c = 1; c <= columnFill; c++) {
				for (int r = 0; r < spec.rowspan; r++) {
					spacerSpec = new TableData();
					spacerSpec.isItemData = false;
					((TableData[]) 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 TableData();
			spacerSpec.isItemData = false;
			((TableData[]) grid.elementAt(row))[k] = spacerSpec;
		}
		for (int k = row + 1; k < grid.size(); k++) {
			spacerSpec = new TableData();
			spacerSpec.isItemData = false;
			((TableData[]) 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();
		}
	}

	private void updateGrowingColumns(
		Vector growingColumns,
		TableData 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 TableData[] createEmptyRow() {
		TableData[] row = new TableData[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 (children.length == 0) {
			return new Point(0, 0);
		}
		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 {
				int[] extraSpace =
					calculateExtraSpace(tableWidth, maxWidth, minWidth);
				for (int i = 0; i < numColumns; i++) {
					int minCWidth = minColumnWidths[i];
					columnWidths[i] = minCWidth + extraSpace[i];
				}
			}
		}
		int totalHeight = 0;
		int y = topMargin;
		// compute widths
		for (int i = 0; i < grid.size(); i++) {
			TableData[] row = (TableData[]) grid.elementAt(i);
			// assign widths, calculate heights
			int rowHeight = 0;
			for (int j = 0; j < numColumns; j++) {
				TableData 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(child, cwidth, changed);
					cy = size.y;
				}
				rowHeight = Math.max(rowHeight, cy);
			}
			y += rowHeight + verticalSpacing;
		}
		totalHeight = y + bottomMargin;
		return new Point(tableWidth, 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++) {
			TableData[] row = (TableData[]) grid.elementAt(i);
			for (int j = 0; j < numColumns; j++) {
				TableData td = row[j];
				if (td.isItemData == false)
					continue;
				Control child = children[td.childIndex];
				int minWidth = -1;
				if (child instanceof Composite) {
					Composite cc = (Composite) child;
					Layout l = cc.getLayout();
					if (l instanceof ILayoutExtension) {
						minWidth =
							((ILayoutExtension) l).getMinimumWidth(cc, changed);
					}
				}
				if (minWidth == -1) {
					if (isWrap(child)) {
						// Should be the width of the
						// longest word, we'll pick
						// some small number instead
						minWidth = 30;
					} else {
						Point size =
							child.computeSize(
								SWT.DEFAULT,
								SWT.DEFAULT,
								changed);
						minWidth = size.x;
					}
				}
				minWidth += td.indent;
				minColumnWidths[j] = Math.max(minColumnWidths[j], minWidth);
			}
		}
	}

	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++) {
			TableData[] row = (TableData[]) grid.elementAt(i);
			for (int j = 0; j < numColumns; j++) {
				TableData td = row[j];
				if (td.isItemData == false)
					continue;
				Control child = children[td.childIndex];
				int maxWidth = -1;
				if (child instanceof Composite) {
					Composite cc = (Composite) child;
					Layout l = cc.getLayout();
					if (l instanceof ILayoutExtension) {
						maxWidth =
							((ILayoutExtension) l).getMaximumWidth(cc, changed);
					}
				}
				if (maxWidth == -1) {
					Point size =
						child.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed);
					maxWidth = size.x;
				}
				maxWidth += td.indent;
				if (td.colspan == 1)
					maxColumnWidths[j] = Math.max(maxColumnWidths[j], maxWidth);
				else {
					// grow the last column
					int last = j + td.colspan - 1;
					int rem = 0;
					for (int k = j; k < j + td.colspan - 1; k++) {
						rem += maxColumnWidths[k];
					}
					int reduced = maxWidth - rem;
					maxColumnWidths[last] =
						Math.max(maxColumnWidths[last], reduced);
				}
			}
		}
	}

	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 TableData());
			}
		}
	}
}
