Save This Page
Home » Eclipse-SWT-3.5.1 » org.eclipse.swt.layout » [javadoc | source]
    1   /*******************************************************************************
    2    * Copyright (c) 2000, 2004 IBM Corporation and others.
    3    * All rights reserved. This program and the accompanying materials
    4    * are made available under the terms of the Common Public License v1.0
    5    * which accompanies this distribution, and is available at
    6    * http://www.eclipse.org/legal/cpl-v10.html
    7    * 
    8    * Contributors:
    9    *     IBM Corporation - initial API and implementation
   10    *******************************************************************************/
   11   package org.eclipse.swt.layout;
   12   
   13   import org.eclipse.swt;
   14   import org.eclipse.swt.widgets;
   15   import org.eclipse.swt.graphics;
   16   import java.util.Enumeration;
   17   import java.util.Hashtable;
   18   import java.util.Vector;
   19   
   20   /**
   21    * Instances of this class lay out the control children of a 
   22    * <code>Composite</code> in a grid. 
   23    * <p>
   24    * <code>GridLayout</code> has a number of configuration fields, and the 
   25    * controls it lays out can have an associated layout data object, called 
   26    * <code>GridData</code>. The power of <code>GridLayout</code> lies in the 
   27    * ability to configure <code>GridData</code> for each control in the layout. 
   28    * </p>
   29    * <p>
   30    * The following code creates a shell managed by a <code>GridLayout</code>
   31    * with 3 columns:
   32    * <pre>
   33    * 		Display display = new Display();
   34    * 		Shell shell = new Shell(display);
   35    * 		GridLayout gridLayout = new GridLayout();
   36    * 		gridLayout.numColumns = 3;
   37    * 		shell.setLayout(gridLayout);
   38    * </pre>
   39    * The <code>numColumns</code> field is the most important field in a 
   40    * <code>GridLayout</code>. Widgets are laid out in columns from left 
   41    * to right, and a new row is created when <code>numColumns</code> + 1 
   42    * controls are added to the <code>Composite<code>.
   43    * </p>
   44    * 
   45    * @see GridData
   46    */
   47   public final class GridLayout extends Layout {
   48   	/**
   49   	 * marginWidth specifies the number of pixels of horizontal margin
   50   	 * that will be placed along the left and right edges of the layout.
   51   	 *
   52   	 * The default value is 5.
   53   	 */
   54    	public int marginWidth = 5;
   55   	/**
   56   	 * marginHeight specifies the number of pixels of vertical margin
   57   	 * that will be placed along the top and bottom edges of the layout.
   58   	 *
   59   	 * The default value is 5.
   60   	 */
   61    	public int marginHeight = 5;
   62    	/**
   63    	 * numColumns specifies the number of cell columns in the layout.
   64    	 *
   65    	 * The default value is 1.
   66    	 */
   67   	public int numColumns = 1;
   68   	/**
   69   	 * makeColumnsEqualWidth specifies whether all columns in the layout
   70   	 * will be forced to have the same width.
   71   	 *
   72   	 * The default value is false.
   73   	 */
   74   	public boolean makeColumnsEqualWidth = false;
   75   	/**
   76   	 * horizontalSpacing specifies the number of pixels between the right
   77   	 * edge of one cell and the left edge of its neighbouring cell to
   78   	 * the right.
   79   	 *
   80   	 * The default value is 5.
   81   	 */
   82    	public int horizontalSpacing = 5;
   83   	/**
   84   	 * verticalSpacing specifies the number of pixels between the bottom
   85   	 * edge of one cell and the top edge of its neighbouring cell underneath.
   86   	 *
   87   	 * The default value is 5.
   88   	 */
   89    	public int verticalSpacing = 5;
   90   
   91     	// Private variables.  Cached values used to cut down on grid calculations.
   92   	Vector grid = new Vector();
   93   	int [] pixelColumnWidths;
   94   	int [] pixelRowHeights;
   95   	int [] expandableColumns;
   96   	int [] expandableRows;
   97   	
   98   /**
   99    * Constructs a new instance of this class.
  100    */
  101   public GridLayout() {
  102   }
  103   
  104   /**
  105    * Constructs a new instance of this class given the
  106    * number of columns, and whether or not the columns
  107    * should be forced to have the same width.
  108    *
  109    * @param numColumns the number of columns in the grid
  110    * @param makeColumnsEqualWidth whether or not the columns will have equal width
  111    * 
  112    * @since 2.0
  113    */
  114   public GridLayout(int numColumns, boolean makeColumnsEqualWidth) {
  115   	this.numColumns = numColumns;
  116   	this.makeColumnsEqualWidth = makeColumnsEqualWidth;
  117   }
  118   
  119   void adjustGridDimensions(Composite composite, boolean flushCache) {
  120   	// Ensure that controls that span more than one row or column have enough space.
  121   	for (int row = 0; row < grid.size(); row++) {
  122   		for (int column = 0; column < numColumns; column++) {
  123   			GridData spec = ((GridData[]) grid.elementAt(row))[column];
  124   			if (spec.isItemData()) {
  125   				// Widgets spanning columns.
  126   				if (spec.hSpan > 1) {
  127   					Control child = composite.getChildren()[spec.childIndex];
  128   					Point extent = child.computeSize(spec.widthHint, spec.heightHint, flushCache);
  129   
  130   					// Calculate the size of the control's spanned columns.
  131   					int lastSpanIndex = column + spec.hSpan;
  132   					int spannedSize = 0;
  133   					for (int c = column; c < lastSpanIndex; c++) {
  134   						spannedSize = spannedSize + pixelColumnWidths[c] + horizontalSpacing;
  135   					}
  136   					spannedSize = spannedSize - horizontalSpacing;
  137   
  138   					// If the spanned columns are not large enough to display the control, adjust the column
  139   					// sizes to account for the extra space that is needed.
  140   					if (extent.x + spec.horizontalIndent > spannedSize) {
  141   						int extraSpaceNeeded = extent.x + spec.horizontalIndent - spannedSize;
  142   						int lastColumn = column + spec.hSpan - 1;
  143   						int colWidth;
  144   						if (makeColumnsEqualWidth) {
  145   							// Evenly distribute the extra space amongst all of the columns.
  146   							int columnExtra = extraSpaceNeeded / numColumns;
  147   							int columnRemainder = extraSpaceNeeded % numColumns;
  148   							for (int i = 0; i < pixelColumnWidths.length; i++) {
  149   								colWidth = pixelColumnWidths[i] + columnExtra;
  150   								pixelColumnWidths[i] = colWidth;
  151   							}
  152   							colWidth = pixelColumnWidths[lastColumn] + columnRemainder;
  153   							pixelColumnWidths[lastColumn] = colWidth;
  154   						} else {
  155   							Vector localExpandableColumns = new Vector();
  156   							for (int i = column; i <= lastColumn; i++) {
  157   								for (int j = 0; j < expandableColumns.length; j++) {
  158   									if (expandableColumns[j] == i) {
  159   										localExpandableColumns.addElement(new Integer(i));
  160   									}
  161   								}
  162   							}
  163   							if (localExpandableColumns.size() > 0) {
  164   								// If any of the control's columns grab excess space, allocate the space amongst those columns.
  165   								int columnExtra = extraSpaceNeeded / localExpandableColumns.size();
  166   								int columnRemainder = extraSpaceNeeded % localExpandableColumns.size();
  167   								for (int i = 0; i < localExpandableColumns.size(); i++) {
  168   									int expandableCol = ((Integer) localExpandableColumns.elementAt(i)).intValue();
  169   									colWidth = pixelColumnWidths[expandableCol] + columnExtra;
  170   									pixelColumnWidths[expandableCol] = colWidth;
  171   								}
  172   								colWidth = pixelColumnWidths[lastColumn] + columnRemainder;
  173   								pixelColumnWidths[lastColumn] = colWidth;
  174   							} else {
  175   								// Add the extra space to the control's last column if none of its columns grab excess space.
  176   								colWidth = pixelColumnWidths[lastColumn] + extraSpaceNeeded;
  177   								pixelColumnWidths[lastColumn] = colWidth;
  178   							}
  179   						}
  180   					}
  181   				}
  182   
  183   				// Widgets spanning rows.
  184   				if (spec.verticalSpan > 1) {
  185   					Control child = composite.getChildren()[spec.childIndex];
  186   					Point extent = child.computeSize(spec.widthHint, spec.heightHint, flushCache);
  187   
  188   					// Calculate the size of the control's spanned rows.
  189   					int lastSpanIndex = row + spec.verticalSpan;
  190   					int spannedSize = 0;
  191   					for (int r = row; r < lastSpanIndex; r++) {
  192   						spannedSize = spannedSize + pixelRowHeights[r] + verticalSpacing;
  193   					}
  194   					spannedSize = spannedSize - verticalSpacing;
  195   					// If the spanned rows are not large enough to display the control, adjust the row
  196   					// sizes to account for the extra space that is needed.
  197   					if (extent.y > spannedSize) {
  198   						int extraSpaceNeeded = extent.y - spannedSize;
  199   						int lastRow = row + spec.verticalSpan - 1;
  200   						int rowHeight;
  201   						Vector localExpandableRows = new Vector();
  202   						for (int i = row; i <= lastRow; i++) {
  203   							for (int j = 0; j < expandableRows.length; j++) {
  204   								if (expandableRows[j] == i) {
  205   									localExpandableRows.addElement(new Integer(i));
  206   								}
  207   							}
  208   						}
  209   						if (localExpandableRows.size() > 0) {
  210   							// If any of the control's rows grab excess space, allocate the space amongst those rows.
  211   							int rowExtra = extraSpaceNeeded / localExpandableRows.size();
  212   							int rowRemainder = extraSpaceNeeded % localExpandableRows.size();
  213   							for (int i = 0; i < localExpandableRows.size(); i++) {
  214   								int expandableRow = ((Integer) localExpandableRows.elementAt(i)).intValue();
  215   								rowHeight = pixelRowHeights[expandableRow] + rowExtra;
  216   								pixelRowHeights[expandableRow] = rowHeight;
  217   							}
  218   							rowHeight = pixelRowHeights[lastRow] + rowRemainder;
  219   							pixelRowHeights[lastRow] = rowHeight;
  220   						} else {
  221   							// Add the extra space to the control's last row if no rows grab excess space.
  222   							rowHeight = pixelRowHeights[lastRow] + extraSpaceNeeded;
  223   							pixelRowHeights[lastRow] = rowHeight;
  224   						}
  225   					}
  226   				}
  227   			}
  228   		}
  229   	}
  230   }
  231   void calculateGridDimensions(Composite composite, boolean flushCache) {
  232   	int maxWidth, childWidth, maxHeight, childHeight;
  233   	
  234   	//
  235   	Control[] children = composite.getChildren();
  236   	Point[] childSizes = new Point[children.length];
  237   	pixelColumnWidths = new int[numColumns];
  238   	pixelRowHeights = new int[grid.size()];
  239   	
  240   	// Loop through the grid by column to get the width that each column needs to be.
  241   	// Each column will be as wide as its widest control.
  242   	for (int column = 0; column < numColumns; column++) {
  243   		maxWidth = 0;
  244   		for (int row = 0; row < grid.size(); row++) {
  245   			GridData spec = ((GridData[]) grid.elementAt(row))[column];
  246   			if (spec.isItemData()) {
  247   				Control child = children[spec.childIndex];
  248   				childSizes[spec.childIndex] = child.computeSize(spec.widthHint, spec.heightHint, flushCache);
  249   				childWidth = childSizes[spec.childIndex].x + spec.horizontalIndent;
  250   				if (spec.hSpan == 1) {
  251   					maxWidth = Math.max(maxWidth, childWidth);
  252   				}
  253   			}
  254   		}
  255   		// Cache the values for later use.
  256   		pixelColumnWidths[column] = maxWidth;
  257   	}
  258   
  259   	// 
  260   	if (makeColumnsEqualWidth) {
  261   		maxWidth = 0;
  262   		// Find the largest column size that is necessary and make each column that size.
  263   		for (int i = 0; i < numColumns; i++) {
  264   			maxWidth = Math.max(maxWidth, pixelColumnWidths[i]);
  265   		}
  266   		maxWidth += horizontalSpacing;
  267   		for (int i = 0; i < numColumns; i++) {
  268   			pixelColumnWidths[i] = maxWidth;
  269   		}
  270   	}
  271   
  272   	// Loop through the grid by row to get the height that each row needs to be.
  273   	// Each row will be as high as its tallest control.
  274   	for (int row = 0; row < grid.size(); row++) {
  275   		maxHeight = 0;
  276   		for (int column = 0; column < numColumns; column++) {
  277   			GridData spec = ((GridData[]) grid.elementAt(row))[column];
  278   			if (spec.isItemData()) {
  279   				childHeight = childSizes[spec.childIndex].y;
  280   				if (spec.verticalSpan == 1) {
  281   					maxHeight = Math.max(maxHeight, childHeight);
  282   				}
  283   			}
  284   		}
  285   		// Cache the values for later use.
  286   		pixelRowHeights[row] = maxHeight;
  287   	}
  288   }
  289   void computeExpandableCells() {
  290   	// If a control grabs excess horizontal space, the last column that the control spans
  291   	// will be expandable.  Similarly, if a control grabs excess vertical space, the 
  292   	// last row that the control spans will be expandable.
  293   	Hashtable growColumns = new Hashtable();
  294   	Hashtable growRows = new Hashtable();
  295   	for (int col = 0; col < numColumns; col++) {
  296   		for (int row = 0; row < grid.size(); row++) {
  297   			GridData spec = ((GridData[]) grid.elementAt(row))[col];
  298   			if (spec.grabExcessHorizontalSpace) {
  299   				growColumns.put(new Integer(col + spec.hSpan - 1), new Object());
  300   			}
  301   			if (spec.grabExcessVerticalSpace) {
  302   				growRows.put(new Integer(row + spec.verticalSpan - 1), new Object());
  303   			}
  304   		}
  305   	}
  306   
  307   	// Cache the values.  These values are used later during children layout.
  308   	int i = 0;
  309   	Enumeration enum = growColumns.keys();
  310   	expandableColumns = new int[growColumns.size()];
  311   	while (enum.hasMoreElements()) {
  312   		expandableColumns[i] = ((Integer)enum.nextElement()).intValue();
  313   		i = i + 1;
  314   	}
  315   	i = 0;
  316   	enum = growRows.keys();
  317   	expandableRows = new int[growRows.size()];
  318   	while (enum.hasMoreElements()) {
  319   		expandableRows[i] = ((Integer)enum.nextElement()).intValue();
  320   		i = i + 1;
  321   	}
  322   }
  323   Point computeLayoutSize(Composite composite, int wHint, int hHint, boolean flushCache) {
  324   	int totalMarginHeight, totalMarginWidth;
  325   	int totalWidth, totalHeight;
  326   	int cols, rows;
  327   
  328   	// Initialize the grid and other cached information that help with the grid layout.
  329   	if (grid.size() == 0) {
  330   		createGrid(composite);
  331   		calculateGridDimensions(composite, flushCache);
  332   		computeExpandableCells();
  333   		adjustGridDimensions(composite, flushCache);
  334   	}
  335   
  336   	//
  337   	cols = numColumns;
  338   	rows = grid.size();
  339   	totalMarginHeight = marginHeight;
  340   	totalMarginWidth = marginWidth;
  341   
  342   	// The total width is the margin plus border width plus space between each column, 
  343   	// plus the width of each column.
  344   	totalWidth = (totalMarginWidth * 2) + ((cols - 1) * horizontalSpacing);
  345   
  346   	//Add up the width of each column. 
  347   	for (int i = 0; i < pixelColumnWidths.length; i++) {
  348   		totalWidth = totalWidth + pixelColumnWidths[i];
  349   	}
  350   
  351   	// The total height is the margin plus border height, plus space between each row, 
  352   	// plus the height of the tallest child in each row.
  353   	totalHeight = (totalMarginHeight * 2) + ((rows - 1) * verticalSpacing);
  354   
  355   	//Add up the height of each row. 
  356   	for (int i = 0; i < pixelRowHeights.length; i++) {
  357   		totalHeight = totalHeight + pixelRowHeights[i];
  358   	}
  359   
  360   	if (wHint != SWT.DEFAULT) totalWidth = wHint;
  361   	if (hHint != SWT.DEFAULT) totalHeight = hHint;
  362   	// The preferred extent is the width and height that will accomodate the grid's controls.
  363   	return new Point(totalWidth, totalHeight);
  364   }
  365   protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
  366   	Control[] children = composite.getChildren();
  367   	int numChildren = children.length;
  368   
  369   	if (numChildren == 0) return new Point(0,0);
  370   
  371   	if (flushCache) {
  372   		// Cause the grid and its related information to be calculated
  373   		// again.
  374   		grid.removeAllElements();
  375   	}
  376   	return computeLayoutSize(composite, wHint, hHint, flushCache);
  377   }
  378   Point getFirstEmptyCell(int row, int column) {
  379   	GridData[] rowData = (GridData[]) grid.elementAt(row);
  380   	while (column < numColumns && rowData[column] != null) {
  381   		column++;
  382   	}
  383   	if (column == numColumns) {
  384   		row++;
  385   		column = 0;
  386   		if (row  == grid.size()) {
  387   			grid.addElement(emptyRow());
  388   		}
  389   		return getFirstEmptyCell(row, column);
  390   	}
  391   	return new Point(row, column);
  392   }
  393   Point getLastEmptyCell(int row, int column) {
  394   	GridData[] rowData = (GridData[])grid.elementAt(row);
  395   	while (column < numColumns && rowData[column] == null ) {
  396   		column++;
  397   	}
  398   	return new Point(row, column - 1);
  399   }	
  400   Point getCell(int row, int column, int width, int height) {
  401   	Point start = getFirstEmptyCell(row, column);
  402   	Point end = getLastEmptyCell(start.x, start.y);
  403   	if (end.y + 1 - start.y >= width) return start;
  404   	GridData[] rowData = (GridData[]) grid.elementAt(start.x);
  405   	for (int j = start.y; j < end.y + 1; j++) {
  406   		GridData spacerSpec = new GridData();
  407   		spacerSpec.isItemData = false;
  408   		rowData[j] = spacerSpec;
  409   	}
  410   	return getCell(end.x, end.y, width, height);
  411   }
  412   void createGrid(Composite composite) {
  413   	int row, column, rowFill, columnFill;
  414   	Control[] children;
  415   	GridData spacerSpec;
  416   
  417   	// 
  418   	children = composite.getChildren();
  419   
  420   	// 
  421   	grid.addElement(emptyRow());
  422   	row = 0;
  423   	column = 0;
  424   
  425   	// Loop through the children and place their associated layout specs in the
  426   	// grid.  Placement occurs left to right, top to bottom (i.e., by row).
  427   	for (int i = 0; i < children.length; i++) {
  428   		// Find the first available spot in the grid.
  429   		Control child = children[i];
  430   		GridData spec = (GridData) child.getLayoutData();
  431   		if (spec == null) {
  432   			spec = new GridData();
  433   			child.setLayoutData(spec);
  434   		}
  435   		spec.hSpan = Math.min(spec.horizontalSpan, numColumns);
  436   		Point p = getCell(row, column, spec.hSpan, spec.verticalSpan);
  437   		row = p.x; column = p.y;
  438   
  439   		// The vertical span for the item will be at least 1.  If it is > 1,
  440   		// add other rows to the grid.
  441   		for (int j = 2; j <= spec.verticalSpan; j++) {
  442   			if (row + j > grid.size()) {
  443   				grid.addElement(emptyRow());
  444   			}
  445   		}
  446   
  447   		// Store the layout spec.  Also cache the childIndex.  NOTE: That we assume the children of a
  448   		// composite are maintained in the order in which they are created and added to the composite.
  449   		((GridData[]) grid.elementAt(row))[column] = spec;
  450   		spec.childIndex = i;
  451   
  452   		// Put spacers in the grid to account for the item's vertical and horizontal
  453   		// span.
  454   		rowFill = spec.verticalSpan - 1;
  455   		columnFill = spec.hSpan - 1;
  456   		for (int r = 1; r <= rowFill; r++) {
  457   			for (int c = 0; c < spec.hSpan; c++) {
  458   				spacerSpec = new GridData();
  459   				spacerSpec.isItemData = false;
  460   				((GridData[]) grid.elementAt(row + r))[column + c] = spacerSpec;
  461   			}
  462   		}
  463   		for (int c = 1; c <= columnFill; c++) {
  464   			for (int r = 0; r < spec.verticalSpan; r++) {
  465   				spacerSpec = new GridData();
  466   				spacerSpec.isItemData = false;
  467   				((GridData[]) grid.elementAt(row + r))[column + c] = spacerSpec;
  468   			}
  469   		}
  470   		column = column + spec.hSpan - 1;
  471   	}
  472   
  473   	// Fill out empty grid cells with spacers.
  474   	for (int r = row; r < grid.size(); r++) {
  475   		GridData[] rowData = (GridData[]) grid.elementAt(r);
  476   		for (int c = 0; c < numColumns; c++) {
  477   			if (rowData[c] == null) {
  478   				spacerSpec = new GridData();
  479   				spacerSpec.isItemData = false;
  480   				rowData[c] = spacerSpec;
  481   			}
  482   		}
  483   	}
  484   }
  485   GridData[] emptyRow() {
  486   	GridData[] row = new GridData[numColumns];
  487   	for (int i = 0; i < numColumns; i++) {
  488   		row[i] = null;}
  489   	return row;
  490   }
  491   protected void layout(Composite composite, boolean flushCache) {
  492   	int[] columnWidths;
  493   	int[] rowHeights;
  494   	int rowSize, rowY, columnX;
  495   	int compositeWidth, compositeHeight;
  496   	int excessHorizontal, excessVertical;
  497   	Control[] children;
  498   	if (flushCache) {
  499   		// Cause the grid and its related information to be calculated
  500   		// again.
  501   		grid.removeAllElements();
  502   	}
  503   	children = composite.getChildren();
  504   	if (children.length == 0)
  505   		return;
  506   
  507   	//
  508   	Point extent = computeSize(composite, SWT.DEFAULT, SWT.DEFAULT, flushCache);
  509   	columnWidths = new int[numColumns];
  510   	for (int i = 0; i < pixelColumnWidths.length; i++) {
  511   		columnWidths[i] = pixelColumnWidths[i];
  512   	}
  513   	rowHeights = new int[grid.size()];
  514   	for (int i = 0; i < pixelRowHeights.length; i++) {
  515   		rowHeights[i] = pixelRowHeights[i];
  516   	}
  517   	int columnWidth = 0;
  518   	rowSize = Math.max(1, grid.size());
  519   
  520   	// 
  521   	compositeWidth = extent.x;
  522   	compositeHeight = extent.y;
  523   
  524   	// Calculate whether or not there is any extra space or not enough space due to a resize 
  525   	// operation.  Then allocate/deallocate the space to columns and rows that are expandable.  
  526   	// If a control grabs excess space, its last column or row will be expandable.
  527   	excessHorizontal = composite.getClientArea().width - compositeWidth;
  528   	excessVertical = composite.getClientArea().height - compositeHeight;
  529   
  530   	// Allocate/deallocate horizontal space.
  531   	if (expandableColumns.length != 0) {
  532   		int excess, remainder, last;
  533   		int colWidth;
  534   		excess = excessHorizontal / expandableColumns.length;
  535   		remainder = excessHorizontal % expandableColumns.length;
  536   		last = 0;
  537   		for (int i = 0; i < expandableColumns.length; i++) {
  538   			int expandableCol = expandableColumns[i];
  539   			colWidth = columnWidths[expandableCol];
  540   			colWidth = colWidth + excess;
  541   			columnWidths[expandableCol] = colWidth;
  542   			last = Math.max(last, expandableCol);
  543   		}
  544   		colWidth = columnWidths[last];
  545   		colWidth = colWidth + remainder;
  546   		columnWidths[last] = colWidth;
  547   	}
  548   
  549   	// Go through all specs in each expandable column and get the maximum specified
  550   	// widthHint.  Use this as the minimumWidth for the column.
  551   	for (int i = 0; i < expandableColumns.length; i++) {
  552   		int expandableCol = expandableColumns[i];
  553   		int colWidth = columnWidths[expandableCol];
  554   		int minWidth = 0;
  555   		for (int j = 0; j < grid.size(); j++) {
  556   			GridData[] row = (GridData[]) grid.elementAt(j);
  557   			GridData spec = row[expandableCol];
  558   			if (spec.hSpan == 1) {
  559   				minWidth = Math.max(minWidth, spec.widthHint);
  560   			}
  561   		}
  562   		columnWidths[expandableCol] = Math.max(colWidth, minWidth);
  563   	}
  564   	// Allocate/deallocate vertical space.
  565   	if (expandableRows.length != 0) {
  566   		int excess, remainder, last;
  567   		int rowHeight;
  568   		excess = excessVertical / expandableRows.length;
  569   		remainder = excessVertical % expandableRows.length;
  570   		last = 0;
  571   		for (int i = 0; i < expandableRows.length; i++) {
  572   			int expandableRow = expandableRows[i];
  573   			rowHeight = rowHeights[expandableRow];
  574   			rowHeight = rowHeight + excess;
  575   			rowHeights[expandableRow] = rowHeight;
  576   			last = Math.max(last, expandableRow);
  577   		}
  578   		rowHeight = rowHeights[last];
  579   		rowHeight = rowHeight + remainder;
  580   		rowHeights[last] = rowHeight;
  581   	}
  582   	// Go through all specs in each expandable row and get the maximum specified
  583   	// heightHint.  Use this as the minimumHeight for the row.
  584   	for (int i = 0; i < expandableRows.length; i++) {
  585   		int expandableRow = expandableRows[i];
  586   		int rowHeight = rowHeights[expandableRow];
  587   		int minHeight = 0;
  588   		GridData[] row = (GridData[]) grid.elementAt(expandableRow);
  589   		for (int j = 0; j < numColumns; j++) {
  590   			GridData spec = row[j];
  591   			if (spec.verticalSpan == 1) {
  592   				minHeight = Math.max(minHeight, spec.heightHint);
  593   			}
  594   		}
  595   		rowHeights[expandableRow] = Math.max(rowHeight, minHeight);
  596   	}
  597   
  598   	// Get the starting x and y.
  599   	columnX = marginWidth + composite.getClientArea().x;
  600   	rowY = marginHeight + composite.getClientArea().y;
  601   
  602   	// Layout the control left to right, top to bottom.
  603   	for (int r = 0; r < rowSize; r++) {
  604   		int rowHeight = rowHeights[r];
  605   		GridData[] row = (GridData[]) grid.elementAt(r);
  606   
  607   		// 
  608   		for (int c = 0; c < row.length; c++) {
  609   			int spannedWidth = 0, spannedHeight = 0;
  610   			int hAlign = 0, vAlign = 0;
  611   			int widgetX = 0, widgetY = 0;
  612   			int widgetW = 0, widgetH = 0;
  613   
  614   			//
  615   			GridData spec = (GridData) row[c];
  616   			if (makeColumnsEqualWidth) {
  617   				columnWidth = composite.getClientArea().width - 2 * (marginWidth)  - ((numColumns - 1) * horizontalSpacing);
  618   				columnWidth = columnWidth / numColumns;
  619   				for (int i = 0; i < columnWidths.length; i++) {
  620   					columnWidths[i] = columnWidth;
  621   				}
  622   			} else {
  623   				columnWidth = columnWidths[c];
  624   			}
  625   
  626   			//
  627   			spannedWidth = columnWidth;
  628   			for (int k = 1; k < spec.hSpan; k++) {
  629   				if ((c + k) <= numColumns) {
  630   					if (!makeColumnsEqualWidth) {
  631   						columnWidth = columnWidths[c + k];
  632   					}
  633   					spannedWidth = spannedWidth + columnWidth + horizontalSpacing;
  634   				}
  635   			}
  636   
  637   			//
  638   			spannedHeight = rowHeight;
  639   			for (int k = 1; k < spec.verticalSpan; k++) {
  640   				if ((r + k) <= grid.size()) {
  641   					spannedHeight = spannedHeight + rowHeights[r + k] + verticalSpacing;
  642   				}
  643   			}
  644   
  645   			//
  646   			if (spec.isItemData()) {
  647   				Control child = children[spec.childIndex];
  648   				Point childExtent = child.computeSize(spec.widthHint, spec.heightHint, flushCache);
  649   				hAlign = spec.horizontalAlignment;
  650   				widgetX = columnX;
  651   
  652   				// Calculate the x and width values for the control.
  653   				if (hAlign == GridData.CENTER || hAlign == SWT.CENTER) {
  654   					widgetX = widgetX + (spannedWidth / 2) - (childExtent.x / 2);
  655   				} else
  656   					if (hAlign == GridData.END || hAlign == SWT.END || hAlign == SWT.RIGHT) {
  657   						widgetX = widgetX + spannedWidth - childExtent.x - spec.horizontalIndent;
  658   					} else {
  659   						widgetX = widgetX + spec.horizontalIndent;
  660   					}
  661   				if (hAlign == GridData.FILL) {
  662   					widgetW = spannedWidth - spec.horizontalIndent;
  663   					widgetX = columnX + spec.horizontalIndent;
  664   				} else {
  665   					widgetW = childExtent.x;
  666   				}
  667   
  668   				// Calculate the y and height values for the control.
  669   				vAlign = spec.verticalAlignment;
  670   				widgetY = rowY;
  671   				if (vAlign == GridData.CENTER || vAlign == SWT.CENTER) {
  672   					widgetY = widgetY + (spannedHeight / 2) - (childExtent.y / 2);
  673   				} else
  674   					if (vAlign == GridData.END || vAlign == SWT.END || vAlign == SWT.BOTTOM) {
  675   						widgetY = widgetY + spannedHeight - childExtent.y;
  676   					}
  677   				if (vAlign == GridData.FILL) {
  678   					widgetH = spannedHeight;
  679   					widgetY = rowY;
  680   				} else {
  681   					widgetH = childExtent.y;
  682   				}
  683   				// Place the control.
  684   				child.setBounds(widgetX, widgetY, widgetW, widgetH);
  685   			}
  686   			// Update the starting x value.
  687   			columnX = columnX + columnWidths[c] + horizontalSpacing;
  688   		}
  689   		// Update the starting y value and since we're starting a new row, reset the starting x value.
  690   		rowY = rowY + rowHeights[r] + verticalSpacing;
  691   		columnX = marginWidth + composite.getClientArea().x;
  692   	}
  693   }
  694   }

Save This Page
Home » Eclipse-SWT-3.5.1 » org.eclipse.swt.layout » [javadoc | source]