blob: da10e04e16c1c8a96e85cdda3464a108fb5803ec [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.uiDesigner.core;
import javax.swing.*;
import java.awt.*;
import java.util.Arrays;
public final class GridLayoutManager extends AbstractLayout {
/**
* Minimum size of the cell (row/column). In design mode this constant should be greater than zero
*/
private int myMinCellSize = 20;
/**
* Rows' stretches. These are positive integer values. The default value for
* any row is <code>1</code>.
*/
private final int[] myRowStretches;
/**
* Columns' stretches. These are positive integer values. The default value for
* any column is <code>1</code>.
*/
private final int[] myColumnStretches;
/**
* Arrays of rows' heights. Method layoutContainer sets this member each time
* it's invoked.
* This is <code>getRowCount()x2</code> two dimensional array. <code>[i][0]</code>
* is top <code>y</code> coordinate of row with index <code>i</code>. This <code>y</code>
* coordinate is in the container coordinate system.
* <code>[i][1]</code> is width of the row with index <code>i</code>.
*/
private final int[] myYs;
private final int[] myHeights;
/**
* Arrays of columns' widths. Method layoutContainer sets this member each time
* it's invoked.
* This is <code>getColumnCount()x2</code> two dimensional array. <code>[i][0]</code>
* is left <code>x</code> coordinate of row with index <code>i</code>. This <code>x</code>
* coordinate is in the container coordinate system.
* <code>[i][1]</code> is width of the column with index <code>i</code>.
*/
private final int[] myXs;
private final int[] myWidths;
private LayoutState myLayoutState;
/**
* package local because is used in tests
*/
DimensionInfo myHorizontalInfo;
/**
* package local because is used in tests
*/
DimensionInfo myVerticalInfo;
private boolean mySameSizeHorizontally;
private boolean mySameSizeVertically;
/**
* Key for accessing client property which is set on the root Swing component of the design-time component
* hierarchy and specifies the value of extra insets added to all components.
*/
public static Object DESIGN_TIME_INSETS = new Object();
private static final int SKIP_ROW = 1;
private static final int SKIP_COL = 2;
public GridLayoutManager(final int rowCount, final int columnCount) {
if (columnCount < 1) {
throw new IllegalArgumentException("wrong columnCount: " + columnCount);
}
if (rowCount < 1) {
throw new IllegalArgumentException("wrong rowCount: " + rowCount);
}
myRowStretches = new int[rowCount];
for (int i = 0; i < rowCount; i++) {
myRowStretches[i] = 1;
}
myColumnStretches = new int[columnCount];
for (int i = 0; i < columnCount; i++) {
myColumnStretches[i] = 1;
}
myXs = new int[columnCount];
myWidths = new int[columnCount];
myYs = new int[rowCount];
myHeights = new int[rowCount];
}
/**
* don't delete this constructor! don't use this constructor!!! should be used ONLY in generated code or in tests
*/
public GridLayoutManager(final int rowCount, final int columnCount, final Insets margin, final int hGap, final int vGap) {
this(rowCount, columnCount);
setMargin(margin);
setHGap(hGap);
setVGap(vGap);
myMinCellSize = 0;
}
/**
* don't delete this constructor! don't use this constructor!!! should be used ONLY in generated code or in tests
*/
public GridLayoutManager(
final int rowCount,
final int columnCount,
final Insets margin,
final int hGap,
final int vGap,
final boolean sameSizeHorizontally,
final boolean sameSizeVertically
) {
this(rowCount, columnCount, margin, hGap, vGap);
mySameSizeHorizontally = sameSizeHorizontally;
mySameSizeVertically = sameSizeVertically;
}
public void addLayoutComponent(final Component comp, final Object constraints) {
final GridConstraints c = (GridConstraints)constraints;
final int row = c.getRow();
final int rowSpan = c.getRowSpan();
final int rowCount = getRowCount();
if (row < 0 || row >= rowCount) {
throw new IllegalArgumentException("wrong row: " + row);
}
if (row + rowSpan - 1 >= rowCount) {
throw new IllegalArgumentException("wrong row span: " + rowSpan + "; row=" + row + " rowCount=" + rowCount);
}
final int column = c.getColumn();
final int colSpan = c.getColSpan();
final int columnCount = getColumnCount();
if (column < 0 || column >= columnCount) {
throw new IllegalArgumentException("wrong column: " + column);
}
if (column + colSpan - 1 >= columnCount) {
throw new IllegalArgumentException(
"wrong col span: " + colSpan + "; column=" + column + " columnCount=" + columnCount);
}
super.addLayoutComponent(comp, constraints);
}
/**
* @return number of rows in the grid.
*/
public int getRowCount() {
return myRowStretches.length;
}
/**
* @return number of columns in the grid.
*/
public int getColumnCount() {
return myColumnStretches.length;
}
/**
* @return vertical stretch for the row with specified index. The returned
* values is in range <code>[1..Integer.MAX_VALUE]</code>.
*/
public int getRowStretch(final int rowIndex) {
return myRowStretches[rowIndex];
}
/**
* @throws IllegalArgumentException if <code>stretch</code> is less
* then <code>1</code>.
*/
public void setRowStretch(final int rowIndex, final int stretch) {
if (stretch < 1) {
throw new IllegalArgumentException("wrong stretch: " + stretch);
}
myRowStretches[rowIndex] = stretch;
}
/**
* @return maximum horizontal stretch for the component which are located
* at the specified column.
*/
public int getColumnStretch(final int columnIndex) {
return myColumnStretches[columnIndex];
}
/**
* @throws IllegalArgumentException if <code>stretch</code> is less
* then <code>1</code>.
*/
public void setColumnStretch(final int columnIndex, final int stretch) {
if (stretch < 1) {
throw new IllegalArgumentException("wrong stretch: " + stretch);
}
myColumnStretches[columnIndex] = stretch;
}
public Dimension maximumLayoutSize(final Container target) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
public Dimension minimumLayoutSize(final Container container) {
validateInfos(container);
// IMPORTANT!!! DO NOT INLINE!!!
final DimensionInfo horizontalInfo = myHorizontalInfo;
final DimensionInfo verticalInfo = myVerticalInfo;
final Dimension result = getTotalGap(container, horizontalInfo, verticalInfo);
final int[] widths = getMinSizes(horizontalInfo);
if (mySameSizeHorizontally) {
makeSameSizes(widths);
}
result.width += sum(widths);
final int[] heights = getMinSizes(verticalInfo);
if (mySameSizeVertically) {
makeSameSizes(heights);
}
result.height += sum(heights);
return result;
}
private static void makeSameSizes(int[] widths) {
int max = widths[0];
for (int i = 0; i < widths.length; i++) {
int width = widths[i];
max = Math.max(width, max);
}
for (int i = 0; i < widths.length; i++) {
widths[i] = max;
}
}
private static int[] getSameSizes(DimensionInfo info, int totalWidth) {
int[] widths = new int[info.getCellCount()];
int average = totalWidth / widths.length;
int rest = totalWidth % widths.length;
for (int i = 0; i < widths.length; i++) {
widths[i] = average;
if (rest > 0) {
widths[i]++;
rest--;
}
}
return widths;
}
public Dimension preferredLayoutSize(final Container container) {
validateInfos(container);
// IMPORTANT!!! DO NOT INLINE!!!
final DimensionInfo horizontalInfo = myHorizontalInfo;
final DimensionInfo verticalInfo = myVerticalInfo;
final Dimension result = getTotalGap(container, horizontalInfo, verticalInfo);
final int[] widths = getPrefSizes(horizontalInfo);
if (mySameSizeHorizontally) {
makeSameSizes(widths);
}
result.width += sum(widths);
final int[] heights = getPrefSizes(verticalInfo);
if (mySameSizeVertically) {
makeSameSizes(heights);
}
result.height += sum(heights);
return result;
}
private static int sum(final int[] ints) {
int result = 0;
for (int i = ints.length - 1; i >= 0; i--) {
result += ints[i];
}
return result;
}
private Dimension getTotalGap(final Container container, final DimensionInfo hInfo, final DimensionInfo vInfo) {
final Insets insets = getInsets(container);
return new Dimension(
insets.left + insets.right + countGap(hInfo, 0, hInfo.getCellCount()) + myMargin.left + myMargin.right,
insets.top + insets.bottom + countGap(vInfo, 0, vInfo.getCellCount()) + myMargin.top + myMargin.bottom);
}
private static int getDesignTimeInsets(Container container) {
while(container != null) {
if (container instanceof JComponent) {
Integer designTimeInsets = (Integer)((JComponent) container).getClientProperty(DESIGN_TIME_INSETS);
if (designTimeInsets != null) {
return designTimeInsets.intValue();
}
}
container = container.getParent();
}
return 0;
}
private static Insets getInsets(Container container) {
final Insets insets = container.getInsets();
int insetsValue = getDesignTimeInsets(container);
if (insetsValue != 0) {
return new Insets(insets.top+insetsValue, insets.left+insetsValue,
insets.bottom+insetsValue, insets.right+insetsValue);
}
return insets;
}
private static int countGap(final DimensionInfo info, final int startCell, final int cellCount) {
int counter = 0;
for (int cellIndex = startCell + cellCount - 2 /*gap after last cell should not be counted*/;
cellIndex >= startCell;
cellIndex--) {
if (shouldAddGapAfterCell(info, cellIndex)) {
counter++;
}
}
return counter * info.getGap();
}
private static boolean shouldAddGapAfterCell(final DimensionInfo info, final int cellIndex) {
if (cellIndex < 0 || cellIndex >= info.getCellCount()) {
throw new IllegalArgumentException("wrong cellIndex: " + cellIndex + "; cellCount=" + info.getCellCount());
}
boolean endsInThis = false;
boolean startsInNext = false;
int indexOfNextNotEmpty = -1;
for (int i = cellIndex + 1; i < info.getCellCount(); i++) {
if (!isCellEmpty(info, i)) {
indexOfNextNotEmpty = i;
break;
}
}
for (int i = 0; i < info.getComponentCount(); i++) {
final Component component = info.getComponent(i);
if (component instanceof Spacer) {
continue;
}
if (info.componentBelongsCell(i, cellIndex) &&
DimensionInfo.findAlignedChild(component, info.getConstraints(i)) != null) {
return true;
}
if (info.getCell(i) == indexOfNextNotEmpty) {
startsInNext = true;
}
if (info.getCell(i) + info.getSpan(i) - 1 == cellIndex) {
endsInThis = true;
}
}
return startsInNext && endsInThis;
}
private static boolean isCellEmpty(final DimensionInfo info, final int cellIndex) {
if (cellIndex < 0 || cellIndex >= info.getCellCount()) {
throw new IllegalArgumentException("wrong cellIndex: " + cellIndex + "; cellCount=" + info.getCellCount());
}
for (int i = 0; i < info.getComponentCount(); i++) {
final Component component = info.getComponent(i);
if (info.getCell(i) == cellIndex && !(component instanceof Spacer)) {
return false;
}
}
return true;
}
public void layoutContainer(final Container container) {
validateInfos(container);
// IMPORTANT!!! DO NOT INLINE!!!
final LayoutState layoutState = myLayoutState;
final DimensionInfo horizontalInfo = myHorizontalInfo;
final DimensionInfo verticalInfo = myVerticalInfo;
Insets insets = getInsets(container);
int skipLayout = checkSetSizesFromParent(container, insets);
final Dimension gap = getTotalGap(container, horizontalInfo, verticalInfo);
final Dimension size = container.getSize();
size.width -= gap.width;
size.height -= gap.height;
final Dimension prefSize = preferredLayoutSize(container);
prefSize.width -= gap.width;
prefSize.height -= gap.height;
final Dimension minSize = minimumLayoutSize(container);
minSize.width -= gap.width;
minSize.height -= gap.height;
// Calculate rows' heights
if ((skipLayout & SKIP_ROW) == 0) {
final int[] heights;
if (mySameSizeVertically) {
heights = getSameSizes(verticalInfo, Math.max(size.height, minSize.height));
}
else {
if (size.height < prefSize.height) {
heights = getMinSizes(verticalInfo);
new_doIt(heights, 0, verticalInfo.getCellCount(), size.height, verticalInfo, true);
}
else {
heights = getPrefSizes(verticalInfo);
new_doIt(heights, 0, verticalInfo.getCellCount(), size.height, verticalInfo, false);
}
}
// Calculate rows' bounds
int y = insets.top + myMargin.top;
for (int i = 0; i < heights.length; i++) {
myYs[i] = y;
myHeights[i] = heights[i];
y += heights[i];
if (shouldAddGapAfterCell(verticalInfo, i)) {
y += verticalInfo.getGap();
}
}
}
if ((skipLayout & SKIP_COL) == 0) {
// Calculate columns' widths
final int[] widths;
if (mySameSizeHorizontally) {
widths = getSameSizes(horizontalInfo, Math.max(size.width, minSize.width));
}
else {
if (size.width < prefSize.width) {
widths = getMinSizes(horizontalInfo);
new_doIt(widths, 0, horizontalInfo.getCellCount(), size.width, horizontalInfo, true);
}
else {
widths = getPrefSizes(horizontalInfo);
new_doIt(widths, 0, horizontalInfo.getCellCount(), size.width, horizontalInfo, false);
}
}
// Calculate columns' bounds
int x = insets.left + myMargin.left;
for (int i = 0; i < widths.length; i++) {
myXs[i] = x;
myWidths[i] = widths[i];
x += widths[i];
if (shouldAddGapAfterCell(horizontalInfo, i)) {
x += horizontalInfo.getGap();
}
}
}
// Set bounds of components
for (int i = 0; i < layoutState.getComponentCount(); i++) {
final GridConstraints c = layoutState.getConstraints(i);
final Component component = layoutState.getComponent(i);
final int column = horizontalInfo.getCell(i);
final int colSpan = horizontalInfo.getSpan(i);
final int row = verticalInfo.getCell(i);
final int rowSpan = verticalInfo.getSpan(i);
final int cellWidth = myXs[column + colSpan - 1] + myWidths[column + colSpan - 1] - myXs[column];
final int cellHeight = myYs[row + rowSpan - 1] + myHeights[row + rowSpan - 1] - myYs[row];
final Dimension componentSize = new Dimension(cellWidth, cellHeight);
if ((c.getFill() & GridConstraints.FILL_HORIZONTAL) == 0) {
componentSize.width = Math.min(componentSize.width, horizontalInfo.getPreferredWidth(i));
}
if ((c.getFill() & GridConstraints.FILL_VERTICAL) == 0) {
componentSize.height = Math.min(componentSize.height, verticalInfo.getPreferredWidth(i));
}
Util.adjustSize(component, c, componentSize);
int dx = 0;
int dy = 0;
if ((c.getAnchor() & GridConstraints.ANCHOR_EAST) != 0) {
dx = cellWidth - componentSize.width;
}
else if ((c.getAnchor() & GridConstraints.ANCHOR_WEST) == 0) {
dx = (cellWidth - componentSize.width) / 2;
}
if ((c.getAnchor() & GridConstraints.ANCHOR_SOUTH) != 0) {
dy = cellHeight - componentSize.height;
}
else if ((c.getAnchor() & GridConstraints.ANCHOR_NORTH) == 0) {
dy = (cellHeight - componentSize.height) / 2;
}
int indent = Util.DEFAULT_INDENT * c.getIndent();
componentSize.width -= indent;
dx += indent;
component.setBounds(myXs[column] + dx, myYs[row] + dy, componentSize.width, componentSize.height);
}
}
private int checkSetSizesFromParent(final Container container, final Insets insets) {
int skipLayout = 0;
GridLayoutManager parentGridLayout = null;
GridConstraints parentGridConstraints = null;
// "use parent layout" also needs to work in cases where a grid is the only control in a non-grid panel
// which is contained in a grid
Container parent = container.getParent();
if (parent != null) {
if (parent.getLayout() instanceof GridLayoutManager) {
parentGridLayout = (GridLayoutManager) parent.getLayout();
parentGridConstraints = parentGridLayout.getConstraintsForComponent(container);
}
else {
Container parent2 = parent.getParent();
if (parent2 != null && parent2.getLayout() instanceof GridLayoutManager) {
parentGridLayout = (GridLayoutManager) parent2.getLayout();
parentGridConstraints = parentGridLayout.getConstraintsForComponent(parent);
}
}
}
if (parentGridLayout != null && parentGridConstraints.isUseParentLayout()) {
if (myRowStretches.length == parentGridConstraints.getRowSpan()) {
int row = parentGridConstraints.getRow();
myYs[0] = insets.top + myMargin.top;
myHeights[0] = parentGridLayout.myHeights[row] - myYs[0];
for (int i = 1; i < myRowStretches.length; i++) {
myYs[i] = parentGridLayout.myYs[i + row] - parentGridLayout.myYs[row];
myHeights[i] = parentGridLayout.myHeights[i + row];
}
myHeights[myRowStretches.length - 1] -= insets.bottom + myMargin.bottom;
skipLayout |= SKIP_ROW;
}
if (myColumnStretches.length == parentGridConstraints.getColSpan()) {
int col = parentGridConstraints.getColumn();
myXs[0] = insets.left + myMargin.left;
myWidths[0] = parentGridLayout.myWidths[col] - myXs[0];
for (int i = 1; i < myColumnStretches.length; i++) {
myXs[i] = parentGridLayout.myXs[i + col] - parentGridLayout.myXs[col];
myWidths[i] = parentGridLayout.myWidths[i + col];
}
myWidths[myColumnStretches.length - 1] -= insets.right + myMargin.right;
skipLayout |= SKIP_COL;
}
}
return skipLayout;
}
public void invalidateLayout(final Container container) {
myLayoutState = null;
myHorizontalInfo = null;
myVerticalInfo = null;
}
void validateInfos(final Container container) {
if (myLayoutState == null) {
// TODO[yole]: Implement cleaner way of determining whether invisible components should be ignored
myLayoutState = new LayoutState(this, getDesignTimeInsets(container) == 0);
myHorizontalInfo = new HorizontalInfo(myLayoutState, getHGapImpl(container));
myVerticalInfo = new VerticalInfo(myLayoutState, getVGapImpl(container));
}
}
/**
* for design time only
*/
public int[] getXs() {
return myXs;
}
/**
* for design time only
*/
public int[] getWidths() {
return myWidths;
}
/**
* for design time only
*/
public int[] getYs() {
return myYs;
}
/**
* for design time only
*/
public int[] getHeights() {
return myHeights;
}
public int[] getCoords(boolean isRow) {
return isRow ? myYs : myXs;
}
public int[] getSizes(boolean isRow) {
return isRow ? myHeights : myWidths;
}
private int[] getMinSizes(final DimensionInfo info) {
return getMinOrPrefSizes(info, true);
}
private int[] getPrefSizes(final DimensionInfo info) {
return getMinOrPrefSizes(info, false);
}
private int[] getMinOrPrefSizes(final DimensionInfo info, final boolean min) {
final int[] widths = new int[info.getCellCount()];
for (int i = 0; i < widths.length; i++) {
widths[i] = myMinCellSize;
}
// single spaned components
for (int i = info.getComponentCount() - 1; i >= 0; i--) {
if (info.getSpan(i) != 1) {
continue;
}
int size = min ? getMin2(info, i) : Math.max(info.getMinimumWidth(i), info.getPreferredWidth(i));
int cell = info.getCell(i);
final int gap = countGap(info, cell, info.getSpan(i));
size = Math.max(size - gap, 0);
widths[cell] = Math.max(widths[cell], size);
}
// components inheriting layout from us
updateSizesFromChildren(info, min, widths);
// multispanned components
final boolean[] toProcess = new boolean[info.getCellCount()];
for (int i = info.getComponentCount() - 1; i >= 0; i--) {
int size = min ? getMin2(info, i) : Math.max(info.getMinimumWidth(i), info.getPreferredWidth(i));
final int span = info.getSpan(i);
final int cell = info.getCell(i);
final int gap = countGap(info, cell, span);
size = Math.max(size - gap, 0);
Arrays.fill(toProcess, false);
int curSize = 0;
for (int j=0; j < span; j++){
curSize += widths[j + cell];
toProcess[j + cell] = true;
}
if (curSize >= size) {
continue;
}
final boolean[] higherPriorityCells = new boolean[toProcess.length];
getCellsWithHigherPriorities(info, toProcess, higherPriorityCells, false, widths);
distribute(higherPriorityCells, info, size - curSize, widths);
}
return widths;
}
private static void updateSizesFromChildren(final DimensionInfo info, final boolean min, final int[] widths) {
for(int i=info.getComponentCount() - 1; i >= 0; i--) {
Component child = info.getComponent(i);
GridConstraints c = info.getConstraints(i);
if (c.isUseParentLayout() && child instanceof Container) {
Container container = (Container) child;
if (container.getLayout() instanceof GridLayoutManager) {
updateSizesFromChild(info, min, widths, container, i);
}
else if (container.getComponentCount() == 1 && container.getComponent(0) instanceof Container) {
// "use parent layout" also needs to work in cases where a grid is the only control in a non-grid panel
// which is contained in a grid
Container childContainer = (Container) container.getComponent(0);
if (childContainer.getLayout() instanceof GridLayoutManager) {
updateSizesFromChild(info, min, widths, childContainer, i);
}
}
}
}
}
private static void updateSizesFromChild(final DimensionInfo info,
final boolean min,
final int[] widths,
final Container container,
final int childIndex) {
GridLayoutManager childLayout = (GridLayoutManager) container.getLayout();
if (info.getSpan(childIndex) == info.getChildLayoutCellCount(childLayout)) {
childLayout.validateInfos(container);
DimensionInfo childInfo = (info instanceof HorizontalInfo)
? childLayout.myHorizontalInfo
: childLayout.myVerticalInfo;
int[] sizes = childLayout.getMinOrPrefSizes(childInfo, min);
int cell = info.getCell(childIndex);
for(int j=0; j<sizes.length; j++) {
widths [cell+j] = Math.max(widths [cell+j], sizes [j]);
}
}
}
private static int getMin2(final DimensionInfo info, final int componentIndex) {
final int s;
if ((info.getSizePolicy(componentIndex) & GridConstraints.SIZEPOLICY_CAN_SHRINK) != 0) {
s = info.getMinimumWidth(componentIndex);
}
else {
// it might be possible that minSize > prefSize (for example, only min is set in constraints to 100 and
// JComponent's preferred size returned is 20)
s = Math.max(info.getMinimumWidth(componentIndex), info.getPreferredWidth(componentIndex));
}
return s;
}
/**
* @param widths in/out parameter
*/
private void new_doIt(final int[] widths, final int cell, final int span, final int minWidth, final DimensionInfo info, final boolean checkPrefs) {
int toDistribute = minWidth;
for (int i = cell; i < cell + span; i++) {
toDistribute -= widths[i];
}
if (toDistribute <= 0) {
return;
}
final boolean[] allowedCells = new boolean[info.getCellCount()];
for (int i = cell; i < cell + span; i++) {
allowedCells[i] = true;
}
final boolean[] higherPriorityCells = new boolean[info.getCellCount()];
getCellsWithHigherPriorities(info, allowedCells, higherPriorityCells, checkPrefs, widths);
distribute(higherPriorityCells, info, toDistribute, widths);
}
private static void distribute(final boolean[] higherPriorityCells, final DimensionInfo info, int toDistribute, final int[] widths) {
int stretches = 0;
for (int i = 0; i < info.getCellCount(); i++) {
if (higherPriorityCells[i]) {
stretches += info.getStretch(i);
}
}
{
final int toDistributeFrozen = toDistribute;
for (int i = 0; i < info.getCellCount(); i++) {
if (!higherPriorityCells[i]) {
continue;
}
final int addon = toDistributeFrozen * info.getStretch(i) / stretches;
widths[i] += addon;
toDistribute -= addon;
}
}
if (toDistribute != 0) {
for (int i = 0; i < info.getCellCount(); i++) {
if (!higherPriorityCells[i]) {
continue;
}
widths[i]++;
toDistribute--;
if (toDistribute == 0) {
break;
}
}
}
if (toDistribute != 0) {
throw new IllegalStateException("toDistribute = " + toDistribute);
}
}
private void getCellsWithHigherPriorities(
final DimensionInfo info,
final boolean[] allowedCells,
final boolean[] higherPriorityCells,
final boolean checkPrefs,
final int[] widths
) {
Arrays.fill(higherPriorityCells, false);
int foundCells = 0;
if (checkPrefs) {
// less that preferred size
final int[] prefs = getMinOrPrefSizes(info, false);
for (int cell = 0; cell < allowedCells.length; cell++) {
if (!allowedCells[cell]) {
continue;
}
if (!isCellEmpty(info, cell) && prefs[cell] > widths[cell]) {
higherPriorityCells[cell] = true;
foundCells++;
}
}
if (foundCells > 0) {
return;
}
}
// want grow
for (int cell = 0; cell < allowedCells.length; cell++) {
if (!allowedCells[cell]) {
continue;
}
if ((info.getCellSizePolicy(cell) & GridConstraints.SIZEPOLICY_WANT_GROW) != 0) {
higherPriorityCells[cell] = true;
foundCells++;
}
}
if (foundCells > 0) {
return;
}
// can grow
for (int cell = 0; cell < allowedCells.length; cell++) {
if (!allowedCells[cell]) {
continue;
}
if ((info.getCellSizePolicy(cell) & GridConstraints.SIZEPOLICY_CAN_GROW) != 0) {
higherPriorityCells[cell] = true;
foundCells++;
}
}
if (foundCells > 0) {
return;
}
// non empty
for (int cell = 0; cell < allowedCells.length; cell++) {
if (!allowedCells[cell]) {
continue;
}
if (!isCellEmpty(info, cell)) {
higherPriorityCells[cell] = true;
foundCells++;
}
}
if (foundCells > 0) {
return;
}
// any
for (int cell = 0; cell < allowedCells.length; cell++) {
if (!allowedCells[cell]) {
continue;
}
higherPriorityCells[cell] = true;
}
}
public boolean isSameSizeHorizontally() {
return mySameSizeHorizontally;
}
public boolean isSameSizeVertically() {
return mySameSizeVertically;
}
public void setSameSizeHorizontally(boolean sameSizeHorizontally) {
mySameSizeHorizontally = sameSizeHorizontally;
}
public void setSameSizeVertically(boolean sameSizeVertically) {
mySameSizeVertically = sameSizeVertically;
}
public int[] getHorizontalGridLines() {
int[] result = new int [myYs.length+1];
result [0] = myYs [0];
for(int i=0; i<myYs.length-1; i++) {
result [i+1] = (myYs[i] + myHeights[i] + myYs[i + 1]) / 2;
}
result [myYs.length] = myYs [myYs.length-1] + myHeights [myYs.length-1];
return result;
}
public int[] getVerticalGridLines() {
int[] result = new int [myXs.length+1];
result [0] = myXs [0];
for(int i=0; i<myXs.length-1; i++) {
result [i+1] = (myXs[i] + myWidths[i] + myXs[i + 1]) / 2;
}
result [myXs.length] = myXs [myXs.length-1] + myWidths [myXs.length-1];
return result;
}
public int getCellCount(final boolean isRow) {
return isRow ? getRowCount() : getColumnCount();
}
public int getCellSizePolicy(final boolean isRow, final int cellIndex) {
DimensionInfo info = isRow ? myVerticalInfo : myHorizontalInfo;
if (info == null) {
// not laid out yet
return 0;
}
return info.getCellSizePolicy(cellIndex);
}
}