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;
+    }
+}