Mercurial > projects > dwt-addons
diff dwtx/ui/forms/widgets/ColumnLayout.d @ 75:5d489b9f966c
Fix continue porting
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 24 May 2008 05:11:16 +0200 |
parents | |
children | c3583c6ec027 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/ui/forms/widgets/ColumnLayout.d Sat May 24 05:11:16 2008 +0200 @@ -0,0 +1,282 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 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 + * dinko.ivanov@sap.com - patch #70790 + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.ui.forms.widgets.ColumnLayout; + +import dwtx.ui.forms.widgets.ILayoutExtension; +import dwtx.ui.forms.widgets.ColumnLayoutData; + +import dwt.DWT; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Layout; + +import dwt.dwthelper.utils; + +/** + * This layout manager arranges children of the composite parent in vertical + * columns. All the columns are identical size and children are stretched + * horizontally to fill the column width. The goal is to give layout some + * reasonable range of column numbers to allow it to handle various parent + * widths. That way, column number will drop to the lowest number in the range + * when width decreases, and grow up to the highest number in the range when + * allowed by the parent width. + * <p> + * In addition, the layout attempts to 'fill the space' equally i.e. to avoid + * large gaps at the and of the last column. + * <p> + * Child controls are layed out according to their 'natural' (preferred) size. + * For 'stretchy' controls that do not have natural preferred size, it is + * possible to set width and/or height hints using ColumnLayoutData objects. + * + * @see ColumnLayoutData + * @since 3.0 + */ +public final class ColumnLayout : Layout, ILayoutExtension { + /** + * Minimum number of columns (default is 1). + */ + public int minNumColumns = 1; + /** + * Maximum number of columns (default is 3). + */ + public int maxNumColumns = 3; + /** + * Horizontal spacing between columns (default is 5). + */ + public int horizontalSpacing = 5; + /** + * Vertical spacing between controls (default is 5). + */ + public int verticalSpacing = 5; + /** + * Top margin (default is 5). + */ + public int topMargin = 5; + /** + * Left margin (default is 5). + */ + public int leftMargin = 5; + /** + * Bottom margin (default is 5). + */ + public int bottomMargin = 5; + /** + * Right margin (default is 5). + */ + public int rightMargin = 5; + + /** + * Creates a new instance of the column layout. + */ + public this() { + } + + /+protected+/ Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) { + if (wHint is 0) + return computeSize(composite, wHint, hHint, minNumColumns); + else if (wHint is DWT.DEFAULT) + return computeSize(composite, wHint, hHint, maxNumColumns); + else + return computeSize(composite, wHint, hHint, -1); + } + + private Point computeSize(Composite parent, int wHint, int hHint, int ncolumns) { + Control[] children = parent.getChildren(); + int cwidth = 0; + int cheight = 0; + Point[] sizes = new Point[children.length]; + + int cwHint = DWT.DEFAULT; + if (ncolumns !is -1) { + cwHint = wHint - leftMargin - rightMargin - (ncolumns - 1) * horizontalSpacing; + if (cwHint <= 0) + cwHint = 0; + else + cwHint /= ncolumns; + } + + for (int i = 0; i < children.length; i++) { + sizes[i] = computeControlSize(children[i], cwHint); + cwidth = Math.max(cwidth, sizes[i].x); + cheight += sizes[i].y; + } + if (ncolumns is -1) { + // must compute + ncolumns = (wHint - leftMargin - rightMargin - horizontalSpacing) / (cwidth + horizontalSpacing); + ncolumns = Math.min(ncolumns, children.length); + ncolumns = Math.max(ncolumns, minNumColumns); + ncolumns = Math.min(ncolumns, maxNumColumns); + } + int perColHeight = cheight / ncolumns; + if (cheight % ncolumns !is 0) + perColHeight++; + int colHeight = 0; + int[] heights = new int[ncolumns]; + int ncol = 0; + + bool fillIn = false; + + for (int i = 0; i < sizes.length; i++) { + int childHeight = sizes[i].y; + if (i>0 && colHeight + childHeight > perColHeight) { + heights[ncol] = colHeight; + ncol++; + if (ncol is ncolumns || fillIn) { + // overflow - start filling in + fillIn = true; + ncol = findShortestColumn(heights); + } + colHeight = heights[ncol]; + } + if (colHeight > 0) + colHeight += verticalSpacing; + colHeight += childHeight; + } + heights[ncol] = Math.max(heights[ncol],colHeight); + + Point size = new Point(0, 0); + for (int i = 0; i < ncolumns; i++) { + size.y = Math.max(size.y, heights[i]); + } + size.x = cwidth * ncolumns + (ncolumns - 1) * horizontalSpacing; + size.x += leftMargin + rightMargin; + //System.out.println("ColumnLayout: whint="+wHint+", size.x="+size.x); + size.y += topMargin + bottomMargin; + return size; + } + + private Point computeControlSize(Control c, int wHint) { + ColumnLayoutData cd = cast(ColumnLayoutData) c.getLayoutData(); + int widthHint = cd !is null ? cd.widthHint : wHint; + int heightHint = cd !is null ? cd.heightHint : DWT.DEFAULT; + return c.computeSize(widthHint, heightHint); + } + + private int findShortestColumn(int[] heights) { + int result = 0; + int height = Integer.MAX_VALUE; + for (int i = 0; i < heights.length; i++) { + if (height > heights[i]) { + height = heights[i]; + result = i; + } + } + return result; + } + + /* + * (non-Javadoc) + * + * @see dwt.widgets.Layout#layout(dwt.widgets.Composite, + * bool) + */ + protected void layout(Composite parent, bool flushCache) { + Control[] children = parent.getChildren(); + Rectangle carea = parent.getClientArea(); + int cwidth = 0; + int cheight = 0; + Point[] sizes = new Point[children.length]; + for (int i = 0; i < children.length; i++) { + sizes[i] = computeControlSize(children[i], DWT.DEFAULT); + cwidth = Math.max(cwidth, sizes[i].x); + cheight += sizes[i].y; + } + int ncolumns = (carea.width - leftMargin - rightMargin - horizontalSpacing) / (cwidth + horizontalSpacing); + ncolumns = Math.min(ncolumns, children.length); + ncolumns = Math.max(ncolumns, minNumColumns); + ncolumns = Math.min(ncolumns, maxNumColumns); + int realWidth = (carea.width - leftMargin - rightMargin + horizontalSpacing) / ncolumns - horizontalSpacing; +// int childrenPerColumn = children.length / ncolumns; +// if (children.length % ncolumns !is 0) +// childrenPerColumn++; +// int colWidth = 0; + + int fillWidth = Math.max(cwidth, realWidth); + + int perColHeight = cheight / ncolumns; + if (cheight % ncolumns !is 0) + perColHeight++; + + int colHeight = 0; + int[] heights = new int[ncolumns]; + int ncol = 0; + int x = leftMargin; + bool fillIn = false; + + for (int i = 0; i < sizes.length; i++) { + Control child = children[i]; + Point csize = sizes[i]; + ColumnLayoutData cd = cast(ColumnLayoutData) child.getLayoutData(); + int align_ = cd !is null ? cd.horizontalAlignment : ColumnLayoutData.FILL; + int childWidth = align_ is ColumnLayoutData.FILL ? fillWidth : csize.x; + + if (i>0 && colHeight + csize.y > perColHeight) { + heights[ncol] = colHeight; + if (fillIn || ncol is ncolumns-1) { + // overflow - start filling in + fillIn = true; + ncol = findShortestColumn(heights); + + x = leftMargin + ncol * (fillWidth + horizontalSpacing); + + } + else { + ncol++; + x += fillWidth + horizontalSpacing; + } + colHeight = heights[ncol]; + } + if (colHeight > 0) + colHeight += verticalSpacing; + + + switch (align_) { + case ColumnLayoutData.LEFT : + case ColumnLayoutData.FILL : + child.setBounds(x, topMargin+colHeight, childWidth, csize.y); + break; + case ColumnLayoutData.RIGHT : + child.setBounds(x + fillWidth - childWidth, topMargin+colHeight, childWidth, csize.y); + break; + case ColumnLayoutData.CENTER : + child.setBounds(x + fillWidth / 2 - childWidth / 2, topMargin+colHeight, childWidth, csize.y); + break; + } + + colHeight += csize.y; + } + } + + /* + * (non-Javadoc) + * + * @see dwtx.ui.forms.widgets.ILayoutExtension#computeMaximumWidth(dwt.widgets.Composite, + * bool) + */ + public int computeMaximumWidth(Composite parent, bool changed) { + return computeSize(parent, DWT.DEFAULT, DWT.DEFAULT, changed).x; + } + + /* + * (non-Javadoc) + * + * @see dwtx.ui.forms.widgets.ILayoutExtension#computeMinimumWidth(dwt.widgets.Composite, + * bool) + */ + public int computeMinimumWidth(Composite parent, bool changed) { + return computeSize(parent, 0, DWT.DEFAULT, changed).x; + } +}