/*******************************************************************************
 * 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.ui.forms.widgets;
import java.util.*;
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.
 * @since 3.0
 */

public class TableWrapLayout 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 Hashtable rowspans;
	private int[] minColumnWidths, maxColumnWidths;
	private int widestColumnWidth;
	private int[] growingColumns;
	private int[] growingRows;
	
	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;
			else
				return 0;
		}
	}

	/**
	 * Implements ILayoutExtension.
	 */
	public int computeMinimumWidth(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);
	}
	/**
	 * Implements ILayoutExtension.
	 */
	public int computeMaximumWidth(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 {
				columnWidths =
					assignExtraSpace(tableWidth, maxWidth, minWidth);
			}
		}
		int y = topMargin;
		int [] rowHeights = computeRowHeights(children, columnWidths, changed);

		for (int i=0; i<grid.size(); i++) {
			int rowHeight = rowHeights[i];
			int x = leftMargin;
			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(child, cwidth, changed);
				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 enum=rowspans.elements(); enum.hasMoreElements();) {
			RowSpan rowspan = (RowSpan)enum.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(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,
		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;
		int width = Math.min(td.compSize.x, 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 (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 {
				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(child, cwidth, changed);
					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 enum=rowspans.elements(); enum.hasMoreElements();) {
			RowSpan rowspan = (RowSpan)enum.nextElement();
			rowspan.update(row, rowHeight);
		}
	}
	private int compensateForRowSpans(int totalHeight) {
		for (Enumeration enum=rowspans.elements(); enum.hasMoreElements();) {
			RowSpan rowspan = (RowSpan)enum.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];
				int minWidth = -1;
				if (child instanceof Composite) {
					Composite cc = (Composite) child;
					Layout l = cc.getLayout();
					if (l instanceof ILayoutExtension) {
						minWidth =
							((ILayoutExtension) l).computeMinimumWidth(
								cc,
								changed);
					}
				}
				if (minWidth == -1) {
					int minWHint = isWrap(child)?0:SWT.DEFAULT;
					Point size =
						child.computeSize(
							minWHint,
							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++) {
			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];
				int maxWidth = SWT.DEFAULT;
				if (child instanceof Composite) {
					Composite cc = (Composite) child;
					Layout l = cc.getLayout();
					if (l instanceof ILayoutExtension) {
						maxWidth =
							((ILayoutExtension) l).computeMaximumWidth(
								cc,
								changed);
					}
				}
				else if (td.maxWidth!=SWT.DEFAULT)
					maxWidth = td.maxWidth;
				if (maxWidth == SWT.DEFAULT) {
					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 TableWrapData());
			}
		}
	}
}
