Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   package net.miginfocom.layout;
   
   
   import java.util.*;
   /*
    * License (BSD):
    * ==============
    *
    * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (miglayout (at) miginfocom (dot) com)
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without modification,
   * are permitted provided that the following conditions are met:
   * Redistributions of source code must retain the above copyright notice, this list
   * of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, this
   * list of conditions and the following disclaimer in the documentation and/or other
   * materials provided with the distribution.
   * Neither the name of the MiG InfoCom AB nor the names of its contributors may be
   * used to endorse or promote products derived from this software without specific
   * prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
   * OF SUCH DAMAGE.
   *
   * @version 1.0
   * @author Mikael Grev, MiG InfoCom AB
   *         Date: 2006-sep-08
   */

Holds components in a grid. Does most of the logic behind the layout manager.
  
  public final class Grid
  {
  	public static final boolean TEST_GAPS = true;
  
  	private static final Float[] GROW_100 = new Float[] {.};
  
  	private static final DimConstraint DOCK_DIM_CONSTRAINT = new DimConstraint();
  	static {
  	}

This is the maximum grid position for "normal" components. Docking components use the space out to MAX_DOCK_GRID and below 0.
  
  	private static final int MAX_GRID = 30000;

Docking components will use the grid coordinates -MAX_DOCK_GRID -> 0 and MAX_GRID -> MAX_DOCK_GRID.
  
  	private static final int MAX_DOCK_GRID = 32767;

A constraint used for gaps.
  
  	private static final ResizeConstraint GAP_RC_CONST = new ResizeConstraint(200, ., 50, null);
The constraints. Never null.
  
  	private final LC lc;

The parent that is layout out and this grid is done for. Never null.
  
  	private final ContainerWrapper container;

An x, y array implemented as a sparse array to accommodate for any grid size without wasting memory (or rather 15 bit (0-MAX_GRID * 0-MAX_GRID).
  
  	private final LinkedHashMap<IntegerCellgrid = new LinkedHashMap<IntegerCell>();   // [(y << 16) + x] -> Cell. null key for absolute positioned compwraps
  
  	private HashMap<IntegerBoundSizewrapGapMap = null;   // Row or Column index depending in the dimension that "wraps". Normally row indexes but may be column indexes if "flowy". 0 means before first row/col.
  
The size of the grid. Row count and column count.
  
  	private final TreeSet<IntegerrowIndexes = new TreeSet<Integer>(), colIndexes = new TreeSet<Integer>();

The row and column specifications.
  
  	private final AC rowConstrcolConstr;

The in the constructor calculated min/pref/max sizes of the rows and columns.
  
  	private FlowSizeSpec colFlowSpecs = nullrowFlowSpecs = null;

Components that are connections in one dimension (such as baseline alignment for instance) are grouped together and stored here. One for each row/column.
  
  	private final ArrayList<LinkedDimGroup>[] colGroupListsrowGroupLists;   //[(start)row/col number]
  
The in the constructor calculated min/pref/max size of the whole grid.
  
  	private int[] width = nullheight = null;

If debug is on contains the bounds for things to paint when calling ContainerWrapper.paintDebugCell(int,int,int,int)
 
 	private ArrayList<int[]> debugRects = null// [x, y, width, height]
 
If any of the absolute coordinates for component bounds has links the name of the target is in this Set. Since it requires some memory and computations this is checked at the creation so that the link information is only created if needed later.

The boolean is true for groups id:s and null for normal id:s.

 
 	private HashMap<StringBooleanlinkTargetIDs = null;
 
 	private final int dockOffYdockOffX;
 
 	private final Float[] pushXspushYs;
 
Constructor.

Parameters:
container The container that will be laid out.
lc The form flow constraints.
rowConstr The rows specifications. If more cell rows are required, the last element will be used for when there is no corresponding element in this array.
colConstr The columns specifications. If more cell rows are required, the last element will be used for when there is no corresponding element in this array.
ccMap The map containing the parsed constraints for each child component of parent. Will not be alterted.
callbackList A list of callbacks or null if none. Will not be alterted.
 
 	public Grid(ContainerWrapper containerLC lcAC rowConstrAC colConstrMap<ComponentWrapperCCccMapArrayList<LayoutCallbackcallbackList)
 	{
 		this. = lc;
 		this. = rowConstr;
 		this. = colConstr;
 		this. = container;
 		this. = callbackList;
 
 		int wrap = lc.getWrapAfter() != 0 ? lc.getWrapAfter() : (lc.isFlowX() ? colConstr : rowConstr).getConstaints().length;
 
 		final ComponentWrapper[] comps = container.getComponents();
 
 		boolean hasTagged = false;  // So we do not have to sort if it will not do any good
 		boolean hasPushX = falsehasPushY = false;
 		boolean hitEndOfRow = false;
 		final int[] cellXY = new int[2];
 		final ArrayList<int[]> spannedRects = new ArrayList<int[]>(2);
 
 		final DimConstraint[] specs = (lc.isFlowX() ? rowConstr : colConstr).getConstaints();
 
 		int sizeGroupsX = 0, sizeGroupsY = 0;
 		int[] dockInsets = null;    // top, left, bottom, right insets for docks.
 
 		LinkHandler.clearTemporaryBounds(container.getLayout());
 
 		for (int i = 0; i < comps.length;) {
 			ComponentWrapper comp = comps[i];
 			CC rootCc = getCC(compccMap);
 
 			addLinkIDs(rootCc);
 
 			int hideMode = comp.isVisible() ? -1 : rootCc.getHideMode() != -1 ? rootCc.getHideMode() : lc.getHideMode();
 
 			if (hideMode == 3) { // To work with situations where there are components that does not have a layout manager, or not this one.
 				setLinkedBounds(comprootCccomp.getX(), comp.getY(), comp.getWidth(), comp.getHeight(), rootCc.isExternal());
 				i++;
 				continue;   // The "external" component should not be handled further.
 			}
 
 			if (rootCc.getHorizontal().getSizeGroup() != null)
 				sizeGroupsX++;
 			if (rootCc.getVertical().getSizeGroup() != null)
 				sizeGroupsY++;
 
 			// Special treatment of absolute positioned components.
 			UnitValue[] pos = getPos(comprootCc);
 			BoundSize[] cbSz = getCallbackSize(comp);
 			if (pos != null || rootCc.isExternal()) {
 
 				CompWrap cw = new CompWrap(comprootCchideModeposcbSz);
 				Cell cell = .get(null);
 				if (cell == null) {
 					.put(nullnew Cell(cw));
 				} else {
 					cell.compWraps.add(cw);
 				}
 
 				if (rootCc.isBoundsInGrid() == false || rootCc.isExternal()) {
 					setLinkedBounds(comprootCccomp.getX(), comp.getY(), comp.getWidth(), comp.getHeight(), rootCc.isExternal());
 					i++;
 					continue;
 				}
 			}
 
 			if (rootCc.getDockSide() != -1) {
 				if (dockInsets == null)
 					dockInsets = new int[] {-, -};
 
 				addDockingCell(dockInsetsrootCc.getDockSide(), new CompWrap(comprootCchideModeposcbSz));
 				i++;
 				continue;
 			}
 
 			Boolean cellFlowX = rootCc.getFlowX();
 			Cell cell = null;
 
 			if (rootCc.isNewline()) {
 				wrap(cellXYrootCc.getNewlineGapSize());
 			} else if (hitEndOfRow) {
 				wrap(cellXYnull);
 			}
 			hitEndOfRow = false;
 
 			final boolean rowNoGrid = lc.isNoGrid() || ((DimConstraint) LayoutUtil.getIndexSafe(specslc.isFlowX() ? cellXY[1] : cellXY[0])).isNoGrid();
 
 			// Move to a free y, x  if no absolute grid specified
 			int cx = rootCc.getCellX();
 			int cy = rootCc.getCellY();
 			if ((cx < 0 || cy < 0) && rowNoGrid == false && rootCc.getSkip() == 0) { // 3.7.2: If skip, don't find an empty cell first.
 				while (isCellFree(cellXY[1], cellXY[0], spannedRects) == false) {
 					if (Math.abs(increase(cellXY, 1)) >= wrap)
 						wrap(cellXYnull);
 				}
 			} else {
 				if (cx >= 0 && cy >= 0) {
 					if (cy >= 0) {
 						cellXY[0] = cx;
 						cellXY[1] = cy;
 					} else {    // Only one coordinate is specified. Use the current row (flowx) or column (flowy) to fill in.
 						if (lc.isFlowX()) {
 							cellXY[0] = cx;
 						} else {
 							cellXY[1] = cx;
 						}
 					}
 				}
 				cell = getCell(cellXY[1], cellXY[0]);   // Might be null
 			}
 
 			// Skip a number of cells. Changed for 3.6.1 to take wrap into account and thus "skip" to the next and possibly more rows.
 			for (int s = 0, skipCount = rootCc.getSkip(); s < skipCounts++) {
 				do {
 					if (Math.abs(increase(cellXY, 1)) >= wrap)
 						wrap(cellXYnull);
 				} while (isCellFree(cellXY[1], cellXY[0], spannedRects) == false);
 			}
 
 			// If cell is not created yet, create it and set it.
 			if (cell == null) {
 				int spanx = Math.min(rowNoGrid && lc.isFlowX() ? . : rootCc.getSpanX(),  - cellXY[0]);
 				int spany = Math.min(rowNoGrid && !lc.isFlowX() ? . : rootCc.getSpanY(),  - cellXY[1]);
 
 				cell = new Cell(spanxspanycellFlowX != null ? cellFlowX : lc.isFlowX());
 
 				setCell(cellXY[1], cellXY[0], cell);
 
 				// Add a rectangle so we can know that spanned cells occupy more space.
 				if (spanx > 1 || spany > 1)
 					spannedRects.add(new int[] {cellXY[0], cellXY[1], spanxspany});
 			}
 
 			// Add the one, or all, components that split the grid position to the same Cell.
 			boolean wrapHandled = false;
 			int splitLeft = rowNoGrid ? . : rootCc.getSplit() - 1;
 			boolean splitExit = false;
 			final boolean spanRestOfRow = (lc.isFlowX() ? rootCc.getSpanX() : rootCc.getSpanY()) == .;
 
 			for (; splitLeft >= 0 && i < comps.lengthsplitLeft--) {
 				ComponentWrapper compAdd = comps[i];
 				CC cc = getCC(compAddccMap);
 
 
 				boolean visible = compAdd.isVisible();
 				hideMode = visible ? -1 : cc.getHideMode() != -1 ? cc.getHideMode() : lc.getHideMode();
 
 				if (cc.isExternal() || hideMode == 3) {
 					i++;
 					splitLeft++;    // Added for 3.5.5 so that these components does not "take" a split slot.
 					continue;       // To work with situations where there are components that does not have a layout manager, or not this one.
 				}
 
 				hasPushX |= (visible || hideMode > 1) && (cc.getPushX() != null);
 				hasPushY |= (visible || hideMode > 1) && (cc.getPushY() != null);
 
 				if (cc != rootCc) { // If not first in a cell
 					if (cc.isNewline() || cc.isBoundsInGrid() == false || cc.getDockSide() != -1)
 						break;
 
 					if (splitLeft > 0 && cc.getSkip() > 0) {
 						splitExit = true;
 						break;
 					}
 
 					pos = getPos(compAddcc);
 					cbSz = getCallbackSize(compAdd);
 				}
 
 				CompWrap cw = new CompWrap(compAddcchideModeposcbSz);
 				cell.compWraps.add(cw);
 				cell.hasTagged |= cc.getTag() != null;
 				hasTagged |= cell.hasTagged;
 
 				if (cc != rootCc) {
 					if (cc.getHorizontal().getSizeGroup() != null)
 						sizeGroupsX++;
 					if (cc.getVertical().getSizeGroup() != null)
 						sizeGroupsY++;
 				}
 
 				i++;
 
 				if ((cc.isWrap() || (spanRestOfRow && splitLeft == 0))) {
 					if (cc.isWrap()) {
 						wrap(cellXYcc.getWrapGapSize());
 					} else {
 						hitEndOfRow = true;
 					}
 					wrapHandled = true;
 					break;
 				}
 			}
 
 			if (wrapHandled == false && rowNoGrid == false) {
 				int span = lc.isFlowX() ? cell.spanx : cell.spany;
 				if (Math.abs((lc.isFlowX() ? cellXY[0] : cellXY[1])) + span >= wrap) {
 					hitEndOfRow = true;
 				} else {
 					increase(cellXYsplitExit ? span - 1 : span);
 				}
 			}
 		}
 
 		// If there were size groups, calculate the largest values in the groups (for min/pref/max) and enforce them on the rest in the group.
 		if (sizeGroupsX > 0 || sizeGroupsY > 0) {
 			HashMap<Stringint[]> sizeGroupMapX = sizeGroupsX > 0 ? new HashMap<Stringint[]>(sizeGroupsX) : null;
 			HashMap<Stringint[]> sizeGroupMapY = sizeGroupsY > 0 ? new HashMap<Stringint[]>(sizeGroupsY) : null;
 			ArrayList<CompWrapsizeGroupCWs = new ArrayList<CompWrap>(Math.max(sizeGroupsXsizeGroupsY));
 
 			for (Cell cell : .values()) {
 				for (int i = 0; i < cell.compWraps.size(); i++) {
 					CompWrap cw = cell.compWraps.get(i);
 					String sgx = cw.cc.getHorizontal().getSizeGroup();
 					String sgy = cw.cc.getVertical().getSizeGroup();
 
 					if (sgx != null || sgy != null) {
 						if (sgx != null && sizeGroupMapX != null)
 							addToSizeGroup(sizeGroupMapXsgxcw.horSizes);
 						if (sgy != null && sizeGroupMapY != null)
 							addToSizeGroup(sizeGroupMapYsgycw.verSizes);
 						sizeGroupCWs.add(cw);
 					}
 				}
 			}
 
 			// Set/equalize the sizeGroups to same the values.
 			for (CompWrap cw : sizeGroupCWs) {
 				if (sizeGroupMapX != null)
 					cw.setSizes(sizeGroupMapX.get(cw.cc.getHorizontal().getSizeGroup()), true);  // Target method handles null sizes
 				if (sizeGroupMapY != null)
 					cw.setSizes(sizeGroupMapY.get(cw.cc.getVertical().getSizeGroup()), false); // Target method handles null sizes
 			}
 		} // Component loop
 
 		// If there were size groups, calculate the largest values in the groups (for min/pref/max) and enforce them on the rest in the group.
 		if (sizeGroupsX > 0 || sizeGroupsY > 0) {
 			HashMap<Stringint[]> sizeGroupMapX = sizeGroupsX > 0 ? new HashMap<Stringint[]>(sizeGroupsX) : null;
 			HashMap<Stringint[]> sizeGroupMapY = sizeGroupsY > 0 ? new HashMap<Stringint[]>(sizeGroupsY) : null;
 			ArrayList<CompWrapsizeGroupCWs = new ArrayList<CompWrap>(Math.max(sizeGroupsXsizeGroupsY));
 
 			for (Cell cell : .values()) {
 				for (int i = 0; i < cell.compWraps.size(); i++) {
 					CompWrap cw = cell.compWraps.get(i);
 					String sgx = cw.cc.getHorizontal().getSizeGroup();
 					String sgy = cw.cc.getVertical().getSizeGroup();
 
 					if (sgx != null || sgy != null) {
 						if (sgx != null && sizeGroupMapX != null)
 							addToSizeGroup(sizeGroupMapXsgxcw.horSizes);
 						if (sgy != null && sizeGroupMapY != null)
 							addToSizeGroup(sizeGroupMapYsgycw.verSizes);
 						sizeGroupCWs.add(cw);
 					}
 				}
 			}
 
 			// Set/equalize the sizeGroups to same the values.
 			for (CompWrap cw : sizeGroupCWs) {
 				if (sizeGroupMapX != null)
 					cw.setSizes(sizeGroupMapX.get(cw.cc.getHorizontal().getSizeGroup()), true);  // Target method handles null sizes
 				if (sizeGroupMapY != null)
 					cw.setSizes(sizeGroupMapY.get(cw.cc.getVertical().getSizeGroup()), false); // Target method handles null sizes
 			}
 		}
 
 		if (hasTagged)
 
 		// Calculate gaps now that the cells are filled and we know all adjacent components.
 		boolean ltr = LayoutUtil.isLeftToRight(lccontainer);
 		for (Cell cell : .values()) {
 			ArrayList<CompWrapcws = cell.compWraps;
 
 			for (int i = 0, lastI = cws.size() - 1; i <= lastIi++) {
 				CompWrap cw = cws.get(i);
 				ComponentWrapper cwBef = i > 0 ? cws.get(i - 1). : null;
 				ComponentWrapper cwAft = i < lastI ? cws.get(i + 1). : null;
 
 				String tag = getCC(cw.compccMap).getTag();
 				CC ccBef = cwBef != null ? getCC(cwBefccMap) : null;
 				CC ccAft = cwAft != null ? getCC(cwAftccMap) : null;
 
 				cw.calcGaps(cwBefccBefcwAftccAfttagcell.flowxltr);
 			}
 		}
 
 
 		// Add synthetic indexes for empty rows and columns so they can get a size
 		for (int i = 0, iSz = rowConstr.getCount(); i < iSzi++)
 		for (int i = 0, iSz = colConstr.getCount(); i < iSzi++)
 
 
 		 = hasPushX || lc.isFillX() ? getDefaultPushWeights(false) : null;
 		 = hasPushY || lc.isFillY() ? getDefaultPushWeights(true) : null;
 
 		if (LayoutUtil.isDesignTime(container))
 			saveGrid(container);
 	}
 
 	private static CC getCC(ComponentWrapper compMap<ComponentWrapperCCccMap)
 	{
 		CC cc = ccMap.get(comp);
 		return cc != null ? cc : new CC();
 	}
 
 	private void addLinkIDs(CC cc)
 	{
 		String[] linkIDs = cc.getLinkTargets();
 		for (String linkID : linkIDs) {
 			if ( == null)
 			.put(linkIDnull);
 		}
 	}

If the container (parent) that this grid is laying out has changed its bounds, call this method to clear any cached values.
 
 	public void invalidateContainerSize()
 	{
 		 = null;
 	}

Does the actual layout. Uses many values calculated in the constructor.

Parameters:
bounds The bounds to layout against. Normally that of the parent. [x, y, width, height].
alignX The alignment for the x-axis.
alignY The alignment for the y-axis.
debug If debug information should be saved in debugRects.
checkPrefChange If a check should be done to see if the setting of any new bounds changes the preferred size of a component.
Returns:
If the layout has probably changed the preferred size and there is need for a new layout (normally only SWT).
 
 	public boolean layout(int[] boundsUnitValue alignXUnitValue alignYboolean debugboolean checkPrefChange)
 	{
 		if (debug)
 			 = new ArrayList<int[]>();
 
 
 		resetLinkValues(truetrue);
 
 		layoutInOneDim(bounds[2], alignXfalse);
 		layoutInOneDim(bounds[3], alignYtrue);
 
 		HashMap<StringIntegerendGrpXMap = nullendGrpYMap = null;
 		int compCount = .getComponentCount();
 
 		// Transfer the calculated bound from the ComponentWrappers to the actual Components.
 		boolean layoutAgain = false;
 		if (compCount > 0) {
 			for (int j = 0; j < ( != null ? 2 : 1); j++) {   // First do the calculations (maybe more than once) then set the bounds when done
 				boolean doAgain;
 				int count = 0;
 				do {
 					doAgain = false;
 					for (Cell cell : .values()) {
 						ArrayList<CompWrapcompWraps = cell.compWraps;
 						for (int i = 0, iSz = compWraps.size(); i < iSzi++) {
 							CompWrap cw = compWraps.get(i);
 
 							if (j == 0) {
 								doAgain |= doAbsoluteCorrections(cwbounds);
 								if (doAgain == false) { // If we are going to do this again, do not bother this time around
 									if (cw.cc.getHorizontal().getEndGroup() != null)
 										endGrpXMap = addToEndGroup(endGrpXMapcw.cc.getHorizontal().getEndGroup(), cw.x + cw.w);
 									if (cw.cc.getVertical().getEndGroup() != null)
 										endGrpYMap = addToEndGroup(endGrpYMapcw.cc.getVertical().getEndGroup(), cw.y + cw.h);
 								}
 
 								// @since 3.7.2 Needed or absolute "pos" pointing to "visual" or "container" didn't work if
 								// their bounds changed during the layout cycle. At least not in SWT.
 								if ( != null && (.containsKey("visual") || .containsKey("container")))
 									layoutAgain = true;
 							}
 
 							if ( == null || j == 1) {
 								if (cw.cc.getHorizontal().getEndGroup() != null)
 									cw.w = endGrpXMap.get(cw.cc.getHorizontal().getEndGroup()) - cw.x;
 								if (cw.cc.getVertical().getEndGroup() != null)
 									cw.h = endGrpYMap.get(cw.cc.getVertical().getEndGroup()) - cw.y;
 
 								cw.x += bounds[0];
 								cw.y += bounds[1];
 								layoutAgain |= cw.transferBounds(checkPrefChange && !layoutAgain);
 
 								if ( != null) {
 									for (LayoutCallback callback : )
 										callback.correctBounds(cw.comp);
 								}
 							}
 						}
 					}
 					if (++count > ((compCount << 3) + 10)) {
 						..println("Unstable cyclic dependency in absolute linked values!");
 						break;
 					}
 
 				} while (doAgain);
 			}
 		}
 
 		// Add debug shapes for the "cells". Use the CompWraps as base for inding the cells.
 		if (debug) {
 			for (Cell cell : .values()) {
 				ArrayList<CompWrapcompWraps = cell.compWraps;
 				for (int i = 0, iSz = compWraps.size(); i < iSzi++) {
 					CompWrap cw = compWraps.get(i);
 
 					if (hGrp != null && vGrp != null)
 						.add(new int[]{hGrp.lStart + bounds[0] - (hGrp.fromEnd ? hGrp.lSize : 0), vGrp.lStart + bounds[1] - (vGrp.fromEnd ? vGrp.lSize : 0), hGrp.lSizevGrp.lSize});
 				}
 			}
 		}
 		return layoutAgain;
 	}
 
 	public void paintDebug()
 	{
 		if ( != null) {
 
 			ArrayList<int[]> painted = new ArrayList<int[]>();
 			for (int i = 0, iSz = .size(); i < iSzi++) {
 				int[] r = .get(i);
 				if (painted.contains(r) == false) {
 					.paintDebugCell(r[0], r[1], r[2], r[3]);
 					painted.add(r);
 				}
 			}
 
 			for (Cell cell : .values()) {
 				ArrayList<CompWrapcompWraps = cell.compWraps;
 				for (int i = 0, iSz = compWraps.size(); i < iSzi++)
 					compWraps.get(i)..paintDebugOutline();
 			}
 		}
 	}
 
 	{
 		return ;
 	}
 
 	public final int[] getWidth()
 	{
 		return .clone();
 	}
 
 	public final int[] getHeight()
 	{
 		return .clone();
 	}
 
 	private void checkSizeCalcs()
 	{
 		if ( == null) {
 
 
 
 			if ( == null) {
 				resetLinkValues(falsetrue);
 			} else {
 				// This call makes some components flicker on SWT. They get their bounds changed twice since
 				// the change might affect the absolute size adjustment below. There's no way around this that
 				// I know of.
 				layout(new int[4], nullnullfalsefalse);
 				resetLinkValues(falsefalse);
 			}
 
 		}
 	}
 
 	private UnitValue[] getPos(ComponentWrapper cwCC cc)
 	{
 		UnitValue[] cbPos = null;
 		if ( != null) {
 			for (int i = 0; i < .size() && cbPos == nulli++)
 				cbPos = .get(i).getPosition(cw);   // NOT a copy!
 		}
 
 		// If one is null, return the other (which many also be null)
 		UnitValue[] ccPos = cc.getPos();    // A copy!!
 		if (cbPos == null || ccPos == null)
 			return cbPos != null ? cbPos : ccPos;
 
 		// Merge
 		for (int i = 0; i < 4; i++) {
 			UnitValue cbUv = cbPos[i];
 			if (cbUv != null)
 				ccPos[i] = cbUv;
 		}
 
 		return ccPos;
 	}
 
 	{
 		if ( != null) {
 			for (LayoutCallback callback : ) {
 				BoundSize[] bs = callback.getSize(cw);   // NOT a copy!
 				if (bs != null)
 					return bs;
 			}
 		}
 		return null;
 	}
 
 	private static int getDockInsets(TreeSet<Integerset)
 	{
 		int c = 0;
 		for (Integer i : set) {
 			if (i < -) {
 				c++;
 			} else {
 				break;  // Since they are sorted we can break
 			}
 		}
 		return c;
 	}

Parameters:
cw Never null.
cc Never null.
external The bounds should be stored even if they are not in linkTargetIDs.
Returns:
If a change has been made.
 
 	private boolean setLinkedBounds(ComponentWrapper cwCC ccint xint yint wint hboolean external)
 	{
 		String id = cc.getId() != null ? cc.getId() : cw.getLinkId();
 		if (id == null)
 			return false;
 
 		String gid = null;
 		int grIx = id.indexOf('.');
 		if (grIx != -1 ) {
 			gid = id.substring(0, grIx);
 			id = id.substring(grIx + 1);
 		}
 
 		boolean changed = false;
 		if (external || ( != null && .containsKey(id)))
 			changed = LinkHandler.setBounds(layidxywh, !externalfalse);
 
 		if (gid != null && (external || ( != null && .containsKey(gid)))) {
 			if ( == null)
 
 			changed |= LinkHandler.setBounds(laygidxywh, !externaltrue);
 		}
 
 		return changed;
 	}

Go to next cell.

Parameters:
p The point to increase
cnt How many cells to advance.
Returns:
The new value in the "incresing" dimension.
 
 	private int increase(int[] pint cnt)
 	{
 		return .isFlowX() ? (p[0] += cnt) : (p[1] += cnt);
 	}

Wraps to the next row or column depending on if horizontal flow or vertical flow is used.

Parameters:
cellXY The point to wrap and thus set either x or y to 0 and increase the other one.
gapSize The gaps size specified in a "wrap XXX" or "newline XXX" or null if none.
 
 	private void wrap(int[] cellXYBoundSize gapSize)
 	{
 		boolean flowx = .isFlowX();
 		cellXY[0] = flowx ? 0 : cellXY[0] + 1;
 		cellXY[1] = flowx ? cellXY[1] + 1 : 0;
 
 		if (gapSize != null) {
 			if ( == null)
 
 			.put(cellXY[flowx ? 1 : 0], gapSize);
 		}
 
 		// add the row/column so that the gap in the last row/col will not be removed.
 		if (flowx) {
 			.add(cellXY[1]);
 		} else {
 			.add(cellXY[0]);
 		}
 	}

Sort components (normally buttons in a button bar) so they appear in the correct order.

Parameters:
cells The cells to sort.
parent The parent.
 
 	private static void sortCellsByPlatform(Collection<CellcellsContainerWrapper parent)
 	{
 		String order = PlatformDefaults.getButtonOrder();
 		String orderLo = order.toLowerCase();
 
 		int unrelSize = PlatformDefaults.convertToPixels(1, "u"true, 0, parentnull);
 
 		if (unrelSize == .)
 			throw new IllegalArgumentException("'unrelated' not recognized by PlatformDefaults!");
 
 		int[] gapUnrel = new int[] {unrelSizeunrelSize.};
 		int[] flGap = new int[] {0, 0, .};
 
 		for (Cell cell : cells) {
 			if (cell.hasTagged == false)
 				continue;
 
 			CompWrap prevCW = null;
 			boolean nextUnrel = false;
 			boolean nextPush = false;
 			ArrayList<CompWrapsortedList = new ArrayList<CompWrap>(cell.compWraps.size());
 
 			for (int i = 0, iSz = orderLo.length(); i < iSzi++) {
 				char c = orderLo.charAt(i);
 				if (c == '+' || c == '_') {
 					nextUnrel = true;
 					if (c == '+')
 						nextPush = true;
 				} else {
 					String tag = PlatformDefaults.getTagForChar(c);
 					if (tag != null) {
 						for (int j = 0, jSz = cell.compWraps.size(); j < jSzj++) {
 							CompWrap cw = cell.compWraps.get(j);
 							if (tag.equals(cw.cc.getTag())) {
 								if (Character.isUpperCase(order.charAt(i))) {
 									int min = PlatformDefaults.getMinimumButtonWidth().getPixels(0, parentcw.comp);
 									if (min > cw.horSizes[.])
 										cw.horSizes[.] = min;
 
 									correctMinMax(cw.horSizes);
 								}
 
 								sortedList.add(cw);
 
 								if (nextUnrel) {
 									(prevCW != null ? prevCW : cw).mergeGapSizes(gapUnrelcell.flowxprevCW == null);
 									if (nextPush) {
 										cw.forcedPushGaps = 1;
 										nextUnrel = false;
 										nextPush = false;
 									}
 								}
 
 								// "unknown" components will always get an Unrelated gap.
 								if (c == 'u')
 									nextUnrel = true;
 								prevCW = cw;
 							}
 						}
 					}
 				}
 			}
 
 			// If we have a gap that was supposed to push but no more components was found to but the "gap before" then compensate.
 			if (sortedList.size() > 0) {
 				CompWrap cw = sortedList.get(sortedList.size() - 1);
 				if (nextUnrel) {
 					cw.mergeGapSizes(gapUnrelcell.flowxfalse);
 					if (nextPush)
 						cw.forcedPushGaps |= 2;
 				}
 
 				// Remove first and last gap if not set explicitly.
 				if (cw.cc.getHorizontal().getGapAfter() == null)
 					cw.setGaps(flGap, 3);
 
 				cw = sortedList.get(0);
 				if (cw.cc.getHorizontal().getGapBefore() == null)
 					cw.setGaps(flGap, 1);
 			}
 
 			// Exchange the unsorted CompWraps for the sorted one.
 			if (cell.compWraps.size() == sortedList.size()) {
 				cell.compWraps.clear();
 			} else {
 				cell.compWraps.removeAll(sortedList);
 			}
 			cell.compWraps.addAll(sortedList);
 		}
 	}
 
 	private Float[] getDefaultPushWeights(boolean isRows)
 	{
 		ArrayList<LinkedDimGroup>[] groupLists = isRows ?  : ;
 
 		Float[] pushWeightArr = ;   // Only create specific if any of the components have grow.
 		for (int i = 0, ix = 1; i < groupLists.lengthi++, ix += 2) {
 			ArrayList<LinkedDimGroupgrps = groupLists[i];
 			Float rowPushWeight = null;
 			for (LinkedDimGroup grp : grps) {
 				for (int c = 0; c < grp._compWraps.size(); c++) {
 					CompWrap cw = grp._compWraps.get(c);
 					int hideMode = cw.comp.isVisible() ? -1 : cw.cc.getHideMode() != -1 ? cw.cc.getHideMode() : .getHideMode();
 
 					Float pushWeight = hideMode < 2 ? (isRows ? cw.cc.getPushY() : cw.cc.getPushX()) : null;
 					if (rowPushWeight == null || (pushWeight != null && pushWeight.floatValue() > rowPushWeight.floatValue()))
 						rowPushWeight = pushWeight;
 				}
 			}
 
 			if (rowPushWeight != null) {
 				if (pushWeightArr == )
 					pushWeightArr = new Float[(groupLists.length << 1) + 1];
 				pushWeightArr[ix] = rowPushWeight;
 			}
 		}
 
 		return pushWeightArr;
 	}
 
 	private void clearGroupLinkBounds()
 	{
 		if ( == null)
 			return;
 
 		for (Map.Entry<StringBooleano : .entrySet()) {
 			if (o.getValue() == .)
 				LinkHandler.clearBounds(.getLayout(), o.getKey());
 		}
 	}
 
 	private void resetLinkValues(boolean parentSizeboolean compLinks)
 	{
 		if (compLinks)
 			LinkHandler.clearTemporaryBounds(lay);
 
 		boolean defIns = !hasDocks();
 
 		int parW = parentSize ? .getWidth().constrain(.getWidth(), getParentSize(true), ) : 0;
 		int parH = parentSize ? .getHeight().constrain(.getHeight(), getParentSize(false), ) : 0;
 
 		int insX = LayoutUtil.getInsets(, 0, defIns).getPixels(0, null);
 		int insY = LayoutUtil.getInsets(, 1, defIns).getPixels(0, null);
 		int visW = parW - insX - LayoutUtil.getInsets(, 2, defIns).getPixels(0, null);
 		int visH = parH - insY - LayoutUtil.getInsets(, 3, defIns).getPixels(0, null);
 
 		LinkHandler.setBounds(lay"visual"insXinsYvisWvisHtruefalse);
 		LinkHandler.setBounds(lay"container", 0, 0, parWparHtruefalse);
 	}

Returns the Grid.LinkedDimGroup that has the Grid.CompWrap cw.

Parameters:
groupLists The lists to search in.
cw The component wrap to find.
Returns:
The linked group or null if none had the component wrap.
 
 	private static LinkedDimGroup getGroupContaining(ArrayList<LinkedDimGroup>[] groupListsCompWrap cw)
 	{
 		for (ArrayList<LinkedDimGroupgroups : groupLists) {
 			for (int j = 0, jSz = groups.size(); j < jSzj++) {
 				ArrayList<CompWrapcwList = groups.get(j).;
 				for (int k = 0, kSz = cwList.size(); k < kSzk++) {
 					if (cwList.get(k) == cw)
 						return groups.get(j);
 				}
 			}
 		}
 		return null;
 	}
 
 	private boolean doAbsoluteCorrections(CompWrap cwint[] bounds)
 	{
 		boolean changed = false;
 
 		int[] stSz = getAbsoluteDimBounds(cwbounds[2], true);
 		if (stSz != null)
 			cw.setDimBounds(stSz[0], stSz[1], true);
 
 		stSz = getAbsoluteDimBounds(cwbounds[3], false);
 		if (stSz != null)
 			cw.setDimBounds(stSz[0], stSz[1], false);
 
 		// If there is a link id, store the new bounds.
 		if ( != null)
 			changed = setLinkedBounds(cw.compcw.cccw.xcw.ycw.wcw.hfalse);
 
 		return changed;
 	}
 
 	private void adjustSizeForAbsolute(boolean isHor)
 	{
 		int[] curSizes = isHor ?  : ;
 
 		Cell absCell = .get(null);
 		if (absCell == null || absCell.compWraps.size() == 0)
 			return;
 
 		ArrayList<CompWrapcws = absCell.compWraps;
 
 		int maxEnd = 0;
 		for (int j = 0, cwSz = absCell.compWraps.size(); j < cwSz + 3; j++) {  // "Do Again" max absCell.compWraps.size() + 3 times.
 			boolean doAgain = false;
 			for (int i = 0; i < cwSzi++) {
 				CompWrap cw = cws.get(i);
 				int[] stSz = getAbsoluteDimBounds(cw, 0, isHor);
 				int end = stSz[0] + stSz[1];
 				if (maxEnd < end)
 					maxEnd = end;
 
 				// If there is a link id, store the new bounds.
 				if ( != null)
 					doAgain |= setLinkedBounds(cw.compcw.ccstSz[0], stSz[0], stSz[1], stSz[1], false);
 			}
 			if (doAgain == false)
 				break;
 
 			// We need to check this again since the coords may be smaller this round.
 			maxEnd = 0;
 		}
 
 		maxEnd += LayoutUtil.getInsets(isHor ? 3 : 2, !hasDocks()).getPixels(0, null);
 
 		if (curSizes[.] < maxEnd)
 			curSizes[.] = maxEnd;
 		if (curSizes[.] < maxEnd)
 			curSizes[.] = maxEnd;
 	}
 
 	private int[] getAbsoluteDimBounds(CompWrap cwint refSizeboolean isHor)
 	{
 		if (cw.cc.isExternal()) {
 			if (isHor) {
 				return new int[] {cw.comp.getX(), cw.comp.getWidth()};
 			} else {
 				return new int[] {cw.comp.getY(), cw.comp.getHeight()};
 			}
 		}
 
 		int[] plafPad = .isVisualPadding() ? cw.comp.getVisualPadding() : null;
 		UnitValue[] pad = cw.cc.getPadding();
 
 		// If no changes do not create a lot of objects
 		if (cw.pos == null && plafPad == null && pad == null)
 			return null;
 
 		// Set start
 		int st = isHor ? cw.x : cw.y;
 		int sz = isHor ? cw.w : cw.h;
 
 		// If absolute, use those coordinates instead.
 		if (cw.pos != null) {
 			UnitValue stUV = cw.pos != null ? cw.pos[isHor ? 0 : 1] : null;
 			UnitValue endUV = cw.pos != null ? cw.pos[isHor ? 2 : 3] : null;
 
 			int minSz = cw.getSize(.isHor);
 			int maxSz = cw.getSize(.isHor);
 			sz = Math.min(Math.max(cw.getSize(.isHor), minSz), maxSz);
 
 			if (stUV != null) {
 				st = stUV.getPixels(stUV.getUnit() == . ? sz : refSizecw.comp);
				if (endUV != null)  // if (endUV == null && cw.cc.isBoundsIsGrid() == true)
					sz = Math.min(Math.max((isHor ? (cw.x + cw.w) : (cw.y + cw.h)) - stminSz), maxSz);
			if (endUV != null) {
				if (stUV != null) {   // if (stUV != null || cw.cc.isBoundsIsGrid()) {
					sz = Math.min(Math.max(endUV.getPixels(refSizecw.comp) - stminSz), maxSz);
else {
					st = endUV.getPixels(refSizecw.comp) - sz;
		// If constraint has padding -> correct the start/size
		if (pad != null) {
			UnitValue uv = pad[isHor ? 1 : 0];
			int p = uv != null ? uv.getPixels(refSizecw.comp) : 0;
			st += p;
			uv = pad[isHor ? 3 : 2];
			sz += -p + (uv != null ? uv.getPixels(refSizecw.comp) : 0);
		// If the plaf converter has padding -> correct the start/size
		if (plafPad != null) {
			int p = plafPad[isHor ? 1 : 0];
			st += p;
			sz += -p + (plafPad[isHor ? 3 : 2]);
		return new int[] {stsz};
	private void layoutInOneDim(int refSizeUnitValue alignboolean isRowsFloat[] defaultPushWeights)
		boolean fromEnd = !(isRows ? .isTopToBottom() : LayoutUtil.isLeftToRight());
		DimConstraint[] primDCs = (isRows ?  : ).getConstaints();
		FlowSizeSpec fss = isRows ?  : ;
		ArrayList<LinkedDimGroup>[] rowCols = isRows ?  : ;
		int[] rowColSizes = LayoutUtil.calculateSerial(fss.sizesfss.resConstsInclGapsdefaultPushWeights.refSize);
		if (LayoutUtil.isDesignTime()) {
			TreeSet<Integerindexes = isRows ?  : ;
			int[] ixArr = new int[indexes.size()];
			int ix = 0;
			for (Integer i : indexes)
				ixArr[ix++] = i;
			putSizesAndIndexes(.getComponent(), rowColSizesixArrisRows);
		int curPos = align != null ? align.getPixels(refSize - LayoutUtil.sum(rowColSizes), null) : 0;
		if (fromEnd)
			curPos = refSize - curPos;
		for (int i = 0 ; i < rowCols.lengthi++) {
			ArrayList<LinkedDimGrouplinkedGroups = rowCols[i];
			int scIx = i - (isRows ?  : );
			int bIx = i << 1;
			int bIx2 = bIx + 1;
			curPos += (fromEnd ? -rowColSizes[bIx] : rowColSizes[bIx]);
			DimConstraint primDC = scIx >= 0 ? primDCs[scIx >= primDCs.length ? primDCs.length - 1 : scIx] : ;
			int rowSize = rowColSizes[bIx2];
			for (LinkedDimGroup group : linkedGroups) {
				int groupSize = rowSize;
				if (group.span > 1)
					groupSize = LayoutUtil.sum(rowColSizesbIx2, Math.min((group.span << 1) - 1, rowColSizes.length - bIx2 - 1));
				group.layout(primDCcurPosgroupSizegroup.span);
			curPos += (fromEnd ? -rowSize : rowSize);
	private static void addToSizeGroup(HashMap<Stringint[]> sizeGroupsString sizeGroupint[] size)
		int[] sgSize = sizeGroups.get(sizeGroup);
		if (sgSize == null) {
			sizeGroups.put(sizeGroupnew int[] {size[.],