📄 gridlayout.java
字号:
/******************************************************************************* * Copyright (c) 2000, 2004 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.swt.layout;import org.eclipse.swt.*;import org.eclipse.swt.widgets.*;import org.eclipse.swt.graphics.*;import java.util.Enumeration;import java.util.Hashtable;import java.util.Vector;/** * Instances of this class lay out the control children of a * <code>Composite</code> in a grid. * <p> * <code>GridLayout</code> has a number of configuration fields, and the * controls it lays out can have an associated layout data object, called * <code>GridData</code>. The power of <code>GridLayout</code> lies in the * ability to configure <code>GridData</code> for each control in the layout. * </p> * <p> * The following code creates a shell managed by a <code>GridLayout</code> * with 3 columns: * <pre> * Display display = new Display(); * Shell shell = new Shell(display); * GridLayout gridLayout = new GridLayout(); * gridLayout.numColumns = 3; * shell.setLayout(gridLayout); * </pre> * The <code>numColumns</code> field is the most important field in a * <code>GridLayout</code>. Widgets are laid out in columns from left * to right, and a new row is created when <code>numColumns</code> + 1 * controls are added to the <code>Composite<code>. * </p> * * @see GridData */public final class GridLayout extends Layout { /** * marginWidth specifies the number of pixels of horizontal margin * that will be placed along the left and right edges of the layout. * * The default value is 5. */ public int marginWidth = 5; /** * marginHeight specifies the number of pixels of vertical margin * that will be placed along the top and bottom edges of the layout. * * The default value is 5. */ public int marginHeight = 5; /** * numColumns specifies the number of cell columns in the layout. * * The default value is 1. */ public int numColumns = 1; /** * makeColumnsEqualWidth specifies whether all columns in the layout * will be forced to have the same width. * * The default value is false. */ public boolean makeColumnsEqualWidth = false; /** * horizontalSpacing specifies the number of pixels between the right * edge of one cell and the left edge of its neighbouring cell to * the right. * * The default value is 5. */ public int horizontalSpacing = 5; /** * verticalSpacing specifies the number of pixels between the bottom * edge of one cell and the top edge of its neighbouring cell underneath. * * The default value is 5. */ public int verticalSpacing = 5; // Private variables. Cached values used to cut down on grid calculations. Vector grid = new Vector(); int [] pixelColumnWidths; int [] pixelRowHeights; int [] expandableColumns; int [] expandableRows; /** * Constructs a new instance of this class. */public GridLayout() {}/** * Constructs a new instance of this class given the * number of columns, and whether or not the columns * should be forced to have the same width. * * @param numColumns the number of columns in the grid * @param makeColumnsEqualWidth whether or not the columns will have equal width * * @since 2.0 */public GridLayout(int numColumns, boolean makeColumnsEqualWidth) { this.numColumns = numColumns; this.makeColumnsEqualWidth = makeColumnsEqualWidth;}void adjustGridDimensions(Composite composite, boolean flushCache) { // Ensure that controls that span more than one row or column have enough space. for (int row = 0; row < grid.size(); row++) { for (int column = 0; column < numColumns; column++) { GridData spec = ((GridData[]) grid.elementAt(row))[column]; if (spec.isItemData()) { // Widgets spanning columns. if (spec.hSpan > 1) { Control child = composite.getChildren()[spec.childIndex]; Point extent = child.computeSize(spec.widthHint, spec.heightHint, flushCache); // Calculate the size of the control's spanned columns. int lastSpanIndex = column + spec.hSpan; int spannedSize = 0; for (int c = column; c < lastSpanIndex; c++) { spannedSize = spannedSize + pixelColumnWidths[c] + horizontalSpacing; } spannedSize = spannedSize - horizontalSpacing; // If the spanned columns are not large enough to display the control, adjust the column // sizes to account for the extra space that is needed. if (extent.x + spec.horizontalIndent > spannedSize) { int extraSpaceNeeded = extent.x + spec.horizontalIndent - spannedSize; int lastColumn = column + spec.hSpan - 1; int colWidth; if (makeColumnsEqualWidth) { // Evenly distribute the extra space amongst all of the columns. int columnExtra = extraSpaceNeeded / numColumns; int columnRemainder = extraSpaceNeeded % numColumns; for (int i = 0; i < pixelColumnWidths.length; i++) { colWidth = pixelColumnWidths[i] + columnExtra; pixelColumnWidths[i] = colWidth; } colWidth = pixelColumnWidths[lastColumn] + columnRemainder; pixelColumnWidths[lastColumn] = colWidth; } else { Vector localExpandableColumns = new Vector(); for (int i = column; i <= lastColumn; i++) { for (int j = 0; j < expandableColumns.length; j++) { if (expandableColumns[j] == i) { localExpandableColumns.addElement(new Integer(i)); } } } if (localExpandableColumns.size() > 0) { // If any of the control's columns grab excess space, allocate the space amongst those columns. int columnExtra = extraSpaceNeeded / localExpandableColumns.size(); int columnRemainder = extraSpaceNeeded % localExpandableColumns.size(); for (int i = 0; i < localExpandableColumns.size(); i++) { int expandableCol = ((Integer) localExpandableColumns.elementAt(i)).intValue(); colWidth = pixelColumnWidths[expandableCol] + columnExtra; pixelColumnWidths[expandableCol] = colWidth; } colWidth = pixelColumnWidths[lastColumn] + columnRemainder; pixelColumnWidths[lastColumn] = colWidth; } else { // Add the extra space to the control's last column if none of its columns grab excess space. colWidth = pixelColumnWidths[lastColumn] + extraSpaceNeeded; pixelColumnWidths[lastColumn] = colWidth; } } } } // Widgets spanning rows. if (spec.verticalSpan > 1) { Control child = composite.getChildren()[spec.childIndex]; Point extent = child.computeSize(spec.widthHint, spec.heightHint, flushCache); // Calculate the size of the control's spanned rows. int lastSpanIndex = row + spec.verticalSpan; int spannedSize = 0; for (int r = row; r < lastSpanIndex; r++) { spannedSize = spannedSize + pixelRowHeights[r] + verticalSpacing; } spannedSize = spannedSize - verticalSpacing; // If the spanned rows are not large enough to display the control, adjust the row // sizes to account for the extra space that is needed. if (extent.y > spannedSize) { int extraSpaceNeeded = extent.y - spannedSize; int lastRow = row + spec.verticalSpan - 1; int rowHeight; Vector localExpandableRows = new Vector(); for (int i = row; i <= lastRow; i++) { for (int j = 0; j < expandableRows.length; j++) { if (expandableRows[j] == i) { localExpandableRows.addElement(new Integer(i)); } } } if (localExpandableRows.size() > 0) { // If any of the control's rows grab excess space, allocate the space amongst those rows. int rowExtra = extraSpaceNeeded / localExpandableRows.size(); int rowRemainder = extraSpaceNeeded % localExpandableRows.size(); for (int i = 0; i < localExpandableRows.size(); i++) { int expandableRow = ((Integer) localExpandableRows.elementAt(i)).intValue(); rowHeight = pixelRowHeights[expandableRow] + rowExtra; pixelRowHeights[expandableRow] = rowHeight; } rowHeight = pixelRowHeights[lastRow] + rowRemainder; pixelRowHeights[lastRow] = rowHeight; } else { // Add the extra space to the control's last row if no rows grab excess space. rowHeight = pixelRowHeights[lastRow] + extraSpaceNeeded; pixelRowHeights[lastRow] = rowHeight; } } } } } }}void calculateGridDimensions(Composite composite, boolean flushCache) { int maxWidth, childWidth, maxHeight, childHeight; // Control[] children = composite.getChildren(); Point[] childSizes = new Point[children.length]; pixelColumnWidths = new int[numColumns]; pixelRowHeights = new int[grid.size()]; // Loop through the grid by column to get the width that each column needs to be. // Each column will be as wide as its widest control. for (int column = 0; column < numColumns; column++) { maxWidth = 0; for (int row = 0; row < grid.size(); row++) { GridData spec = ((GridData[]) grid.elementAt(row))[column]; if (spec.isItemData()) { Control child = children[spec.childIndex]; childSizes[spec.childIndex] = child.computeSize(spec.widthHint, spec.heightHint, flushCache); childWidth = childSizes[spec.childIndex].x + spec.horizontalIndent; if (spec.hSpan == 1) { maxWidth = Math.max(maxWidth, childWidth); } } } // Cache the values for later use. pixelColumnWidths[column] = maxWidth; } // if (makeColumnsEqualWidth) { maxWidth = 0; // Find the largest column size that is necessary and make each column that size. for (int i = 0; i < numColumns; i++) { maxWidth = Math.max(maxWidth, pixelColumnWidths[i]); } maxWidth += horizontalSpacing; for (int i = 0; i < numColumns; i++) { pixelColumnWidths[i] = maxWidth; } } // Loop through the grid by row to get the height that each row needs to be. // Each row will be as high as its tallest control. for (int row = 0; row < grid.size(); row++) { maxHeight = 0; for (int column = 0; column < numColumns; column++) { GridData spec = ((GridData[]) grid.elementAt(row))[column]; if (spec.isItemData()) { childHeight = childSizes[spec.childIndex].y; if (spec.verticalSpan == 1) { maxHeight = Math.max(maxHeight, childHeight); } } } // Cache the values for later use. pixelRowHeights[row] = maxHeight; }}void computeExpandableCells() { // If a control grabs excess horizontal space, the last column that the control spans // will be expandable. Similarly, if a control grabs excess vertical space, the // last row that the control spans will be expandable. Hashtable growColumns = new Hashtable(); Hashtable growRows = new Hashtable(); for (int col = 0; col < numColumns; col++) { for (int row = 0; row < grid.size(); row++) { GridData spec = ((GridData[]) grid.elementAt(row))[col]; if (spec.grabExcessHorizontalSpace) { growColumns.put(new Integer(col + spec.hSpan - 1), new Object()); } if (spec.grabExcessVerticalSpace) { growRows.put(new Integer(row + spec.verticalSpan - 1), new Object()); } } } // Cache the values. These values are used later during children layout. int i = 0; Enumeration enum = growColumns.keys(); expandableColumns = new int[growColumns.size()]; while (enum.hasMoreElements()) { expandableColumns[i] = ((Integer)enum.nextElement()).intValue(); i = i + 1; } i = 0; enum = growRows.keys(); expandableRows = new int[growRows.size()]; while (enum.hasMoreElements()) { expandableRows[i] = ((Integer)enum.nextElement()).intValue(); i = i + 1; }}Point computeLayoutSize(Composite composite, int wHint, int hHint, boolean flushCache) { int totalMarginHeight, totalMarginWidth; int totalWidth, totalHeight; int cols, rows; // Initialize the grid and other cached information that help with the grid layout. if (grid.size() == 0) { createGrid(composite); calculateGridDimensions(composite, flushCache); computeExpandableCells(); adjustGridDimensions(composite, flushCache); } // cols = numColumns; rows = grid.size(); totalMarginHeight = marginHeight; totalMarginWidth = marginWidth; // The total width is the margin plus border width plus space between each column, // plus the width of each column. totalWidth = (totalMarginWidth * 2) + ((cols - 1) * horizontalSpacing); //Add up the width of each column. for (int i = 0; i < pixelColumnWidths.length; i++) { totalWidth = totalWidth + pixelColumnWidths[i];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -