/******************************************************************************* * Copyright (c) 2000, 2018 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.layout; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; /** * Instances of this class determine the size and position of the * children of a Composite by placing them either in * horizontal rows or vertical columns within the parent Composite. *

* RowLayout aligns all controls in one row if the * type is set to horizontal, and one column if it is * set to vertical. It has the ability to wrap, and provides configurable * margins and spacing. RowLayout has a number of configuration * fields. In addition, the height and width of each control in a * RowLayout can be specified by setting a RowData * object into the control using setLayoutData (). *

*

* The following example code creates a RowLayout, sets all * of its fields to non-default values, and then sets it into a * Shell.

*
 * 		RowLayout rowLayout = new RowLayout();
 * 		rowLayout.wrap = false;
 * 		rowLayout.pack = false;
 * 		rowLayout.justify = true;
 * 		rowLayout.type = SWT.VERTICAL;
 * 		rowLayout.marginLeft = 5;
 * 		rowLayout.marginTop = 5;
 * 		rowLayout.marginRight = 5;
 * 		rowLayout.marginBottom = 5;
 * 		rowLayout.spacing = 0;
 * 		shell.setLayout(rowLayout);
 * 
* If you are using the default field values, you only need one line of code: *
 * 		shell.setLayout(new RowLayout());
 * 
* * @see RowData * @see RowLayout snippets * @see SWT Example: LayoutExample * @see Sample code and further information */ public final class RowLayout extends Layout { /** * type specifies whether the layout places controls in rows or * columns. * * The default value is HORIZONTAL. * * Possible values are: * * @since 2.0 */ public int type = SWT.HORIZONTAL; /** * marginWidth specifies the number of points of horizontal margin * that will be placed along the left and right edges of the layout. * * The default value is 0. * * @since 3.0 */ public int marginWidth = 0; /** * marginHeight specifies the number of points of vertical margin * that will be placed along the top and bottom edges of the layout. * * The default value is 0. * * @since 3.0 */ public int marginHeight = 0; /** * spacing specifies the number of points between the edge of one cell * and the edge of its neighbouring cell. * * The default value is 3. */ public int spacing = 3; /** * wrap specifies whether a control will be wrapped to the next * row if there is insufficient space on the current row. * * The default value is true. */ public boolean wrap = true; /** * pack specifies whether all controls in the layout take * their preferred size. If pack is false, all controls will * have the same size which is the size required to accommodate the * largest preferred height and the largest preferred width of all * the controls in the layout. * * The default value is true. */ public boolean pack = true; /** * fill specifies whether the controls in a row should be * all the same height for horizontal layouts, or the same * width for vertical layouts. * * The default value is false. * * @since 3.0 */ public boolean fill = false; /** * center specifies whether the controls in a row should be * centered vertically in each cell for horizontal layouts, * or centered horizontally in each cell for vertical layouts. * * The default value is false. * * @since 3.4 */ public boolean center = false; /** * justify specifies whether the controls in a row should be * fully justified, with any extra space placed between the controls. * * The default value is false. */ public boolean justify = false; /** * marginLeft specifies the number of points of horizontal margin * that will be placed along the left edge of the layout. * * The default value is 3. */ public int marginLeft = 3; /** * marginTop specifies the number of points of vertical margin * that will be placed along the top edge of the layout. * * The default value is 3. */ public int marginTop = 3; /** * marginRight specifies the number of points of horizontal margin * that will be placed along the right edge of the layout. * * The default value is 3. */ public int marginRight = 3; /** * marginBottom specifies the number of points of vertical margin * that will be placed along the bottom edge of the layout. * * The default value is 3. */ public int marginBottom = 3; /** * Constructs a new instance of this class with type HORIZONTAL. */ public RowLayout () { } /** * Constructs a new instance of this class given the type. * * @param type the type of row layout * * @since 2.0 */ public RowLayout (int type) { this.type = type; } @Override protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) { Point extent; if (type == SWT.HORIZONTAL) { extent = layoutHorizontal (composite, false, (wHint != SWT.DEFAULT) && wrap, wHint, flushCache); } else { extent = layoutVertical (composite, false, (hHint != SWT.DEFAULT) && wrap, hHint, flushCache); } if (wHint != SWT.DEFAULT) extent.x = wHint; if (hHint != SWT.DEFAULT) extent.y = hHint; return extent; } Point computeSize (Control control, boolean flushCache) { int wHint = SWT.DEFAULT, hHint = SWT.DEFAULT; RowData data = (RowData) control.getLayoutData (); if (data != null) { wHint = data.width; hHint = data.height; } return control.computeSize (wHint, hHint, flushCache); } @Override protected boolean flushCache (Control control) { return true; } String getName () { String string = getClass ().getName (); int index = string.lastIndexOf ('.'); if (index == -1) return string; return string.substring (index + 1, string.length ()); } @Override protected void layout (Composite composite, boolean flushCache) { Rectangle clientArea = composite.getClientArea (); if (type == SWT.HORIZONTAL) { layoutHorizontal (composite, true, wrap, clientArea.width, flushCache); } else { layoutVertical (composite, true, wrap, clientArea.height, flushCache); } } Point layoutHorizontal (Composite composite, boolean move, boolean wrap, int width, boolean flushCache) { Control [] children = composite.getChildren (); int count = 0; for (int i=0; i SWT.DEFAULT && width < size.x && wrap) { size = child.computeSize (width, child.getLayoutData() == null ? SWT.DEFAULT : ((RowData) child.getLayoutData()).height, flushCache); } childWidth = Math.max (childWidth, size.x); childHeight = Math.max (childHeight, size.y); } maxHeight = childHeight; } int clientX = 0, clientY = 0; if (move) { Rectangle rect = composite.getClientArea (); clientX = rect.x; clientY = rect.y; } int [] wraps = null; boolean wrapped = false; Rectangle [] bounds = null; if (move && (justify || fill || center)) { bounds = new Rectangle [count]; wraps = new int [count]; } int maxX = 0, x = marginLeft + marginWidth, y = marginTop + marginHeight; for (int i=0; i SWT.DEFAULT && width < size.x && wrap) { size = child.computeSize (width, child.getLayoutData() == null ? SWT.DEFAULT : ((RowData) child.getLayoutData()).height, flushCache); } childWidth = size.x; childHeight = size.y; } if (wrap && (i != 0) && (x + childWidth > width)) { wrapped = true; if (move && (justify || fill || center)) wraps [i - 1] = maxHeight; x = marginLeft + marginWidth; y += spacing + maxHeight; if (pack) maxHeight = 0; } if (pack || fill || center) { maxHeight = Math.max (maxHeight, childHeight); } if (move) { int childX = x + clientX, childY = y + clientY; if (justify || fill || center) { bounds [i] = new Rectangle (childX, childY, childWidth, childHeight); } else { child.setBounds (childX, childY, childWidth, childHeight); } } x += spacing + childWidth; maxX = Math.max (maxX, x); } maxX = Math.max (clientX + marginLeft + marginWidth, maxX - spacing); if (!wrapped) maxX += marginRight + marginWidth; if (move && (justify || fill || center)) { int space = 0, margin = 0; if (!wrapped) { space = Math.max (0, (width - maxX) / (count + 1)); margin = Math.max (0, ((width - maxX) % (count + 1)) / 2); } else { if (fill || justify || center) { int last = 0; if (count > 0) wraps [count - 1] = maxHeight; for (int i=0; iSWT.DEFAULT && heightSWT.DEFAULT && height height)) { wrapped = true; if (move && (justify || fill || center)) wraps [i - 1] = maxWidth; x += spacing + maxWidth; y = marginTop + marginHeight; if (pack) maxWidth = 0; } if (pack || fill || center) { maxWidth = Math.max (maxWidth, childWidth); } if (move) { int childX = x + clientX, childY = y + clientY; if (justify || fill || center) { bounds [i] = new Rectangle (childX, childY, childWidth, childHeight); } else { child.setBounds (childX, childY, childWidth, childHeight); } } y += spacing + childHeight; maxY = Math.max (maxY, y); } maxY = Math.max (clientY + marginTop + marginHeight, maxY - spacing); if (!wrapped) maxY += marginBottom + marginHeight; if (move && (justify || fill || center)) { int space = 0, margin = 0; if (!wrapped) { space = Math.max (0, (height - maxY) / (count + 1)); margin = Math.max (0, ((height - maxY) % (count + 1)) / 2); } else { if (fill || justify || center) { int last = 0; if (count > 0) wraps [count - 1] = maxWidth; for (int i=0; i