| /* |
| * 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 java.awt.*; |
| import java.util.ArrayList; |
| |
| /** |
| * public for test purposes |
| * @noinspection AbstractMethodCallInConstructor,RedundantCast |
| */ |
| public abstract class DimensionInfo { |
| private final int[] myCell; |
| private final int[] mySpan; |
| protected final LayoutState myLayoutState; |
| private final int[] myStretches; |
| private final int[] mySpansAfterElimination; |
| private final int[] myCellSizePolicies; |
| private final int myGap; |
| |
| public DimensionInfo(final LayoutState layoutState, final int gap){ |
| if (layoutState == null){ |
| throw new IllegalArgumentException("layoutState cannot be null"); |
| } |
| if (gap < 0){ |
| throw new IllegalArgumentException("invalid gap: " + gap); |
| } |
| myLayoutState = layoutState; |
| myGap = gap; |
| |
| myCell = new int[layoutState.getComponentCount()]; |
| mySpan = new int[layoutState.getComponentCount()]; |
| |
| for (int i = 0; i < layoutState.getComponentCount(); i++) { |
| final GridConstraints c = layoutState.getConstraints(i); |
| myCell[i] = getOriginalCell(c); |
| mySpan[i] = getOriginalSpan(c); |
| } |
| |
| myStretches = new int[getCellCount()]; |
| for (int i = 0; i < myStretches.length; i++) { |
| myStretches[i] = 1; |
| } |
| //TODO[anton,vova] handle stretches |
| |
| final ArrayList elimitated = new ArrayList(); |
| mySpansAfterElimination = (int[])mySpan.clone(); |
| Util.eliminate((int[])myCell.clone(), mySpansAfterElimination, elimitated); |
| |
| myCellSizePolicies = new int[getCellCount()]; |
| for (int i = 0; i < myCellSizePolicies.length; i++) { |
| myCellSizePolicies[i] = getCellSizePolicyImpl(i, elimitated); |
| } |
| } |
| |
| public final int getComponentCount(){ |
| return myLayoutState.getComponentCount(); |
| } |
| |
| public final Component getComponent(final int componentIndex){ |
| return myLayoutState.getComponent(componentIndex); |
| } |
| |
| public final GridConstraints getConstraints(int componentIndex) { |
| return myLayoutState.getConstraints(componentIndex); |
| } |
| |
| public abstract int getCellCount(); |
| |
| public abstract int getPreferredWidth(int componentIndex); |
| public abstract int getMinimumWidth(int componentIndex); |
| public abstract DimensionInfo getDimensionInfo(GridLayoutManager grid); |
| |
| public final int getCell(final int componentIndex){ |
| return myCell[componentIndex]; |
| } |
| |
| public final int getSpan(final int componentIndex){ |
| return mySpan[componentIndex]; |
| } |
| |
| public final int getStretch(final int cellIndex){ |
| return myStretches[cellIndex]; |
| } |
| |
| protected abstract int getOriginalCell(GridConstraints constraints); |
| protected abstract int getOriginalSpan(GridConstraints constraints); |
| |
| abstract int getSizePolicy(int componentIndex); |
| |
| abstract int getChildLayoutCellCount(final GridLayoutManager childLayout); |
| |
| public final int getGap(){ |
| return myGap; |
| } |
| |
| public boolean componentBelongsCell(final int componentIndex, final int cellIndex) { |
| final int componentStartCell = getCell(componentIndex); |
| final int span = getSpan(componentIndex); |
| return componentStartCell <= cellIndex && cellIndex < componentStartCell + span; |
| } |
| |
| public final int getCellSizePolicy(final int cellIndex){ |
| return myCellSizePolicies[cellIndex]; |
| } |
| |
| private int getCellSizePolicyImpl(final int cellIndex, final ArrayList eliminatedCells){ |
| int policyFromChild = getCellSizePolicyFromInheriting(cellIndex); |
| if (policyFromChild != -1) { |
| return policyFromChild; |
| } |
| for (int i = eliminatedCells.size() - 1; i >= 0; i--) { |
| if (cellIndex == ((Integer)eliminatedCells.get(i)).intValue()) { |
| return GridConstraints.SIZEPOLICY_CAN_SHRINK; |
| } |
| } |
| |
| return calcCellSizePolicy(cellIndex); |
| } |
| |
| private int calcCellSizePolicy(final int cellIndex) { |
| boolean canShrink = true; |
| boolean canGrow = false; |
| boolean wantGrow = false; |
| |
| boolean weakCanGrow = true; |
| boolean weakWantGrow = true; |
| |
| int countOfBelongingComponents = 0; |
| |
| for (int i = 0; i < getComponentCount(); i++) { |
| if (!componentBelongsCell(i, cellIndex)){ |
| continue; |
| } |
| |
| countOfBelongingComponents++; |
| |
| final int p = getSizePolicy(i); |
| |
| final boolean thisCanShrink = (p & GridConstraints.SIZEPOLICY_CAN_SHRINK) != 0; |
| final boolean thisCanGrow = (p & GridConstraints.SIZEPOLICY_CAN_GROW) != 0; |
| final boolean thisWantGrow = (p & GridConstraints.SIZEPOLICY_WANT_GROW) != 0; |
| |
| if (getCell(i) == cellIndex && mySpansAfterElimination[i] == 1) { |
| canShrink &= thisCanShrink; |
| canGrow |= thisCanGrow; |
| wantGrow |= thisWantGrow; |
| } |
| |
| if (!thisCanGrow) { |
| weakCanGrow = false; |
| } |
| if (!thisWantGrow) { |
| weakWantGrow = false; |
| } |
| } |
| |
| return |
| (canShrink ? GridConstraints.SIZEPOLICY_CAN_SHRINK : 0) | |
| (canGrow || (countOfBelongingComponents > 0 && weakCanGrow) ? GridConstraints.SIZEPOLICY_CAN_GROW : 0) | |
| (wantGrow || (countOfBelongingComponents > 0 && weakWantGrow) ? GridConstraints.SIZEPOLICY_WANT_GROW : 0); |
| } |
| |
| private int getCellSizePolicyFromInheriting(final int cellIndex) { |
| int nonInheritingComponentsInCell = 0; |
| int policyFromInheriting = -1; |
| for(int i=getComponentCount() - 1; i >= 0; i--) { |
| if (!componentBelongsCell(i, cellIndex)) { |
| continue; |
| } |
| Component child = getComponent(i); |
| GridConstraints c = getConstraints(i); |
| Container container = findAlignedChild(child, c); |
| if (container != null) { |
| GridLayoutManager grid = (GridLayoutManager) container.getLayout(); |
| grid.validateInfos(container); |
| DimensionInfo info = getDimensionInfo(grid); |
| final int policy = info.calcCellSizePolicy(cellIndex - getOriginalCell(c)); |
| if (policyFromInheriting == -1) { |
| policyFromInheriting = policy; |
| } |
| else { |
| policyFromInheriting |= policy; |
| } |
| } |
| else if (getOriginalCell(c) == cellIndex && getOriginalSpan(c) == 1 && !(child instanceof Spacer)) { |
| nonInheritingComponentsInCell++; |
| } |
| } |
| if (nonInheritingComponentsInCell > 0) { |
| return -1; |
| } |
| return policyFromInheriting; |
| } |
| |
| public static Container findAlignedChild(final Component child, final GridConstraints c) { |
| if (c.isUseParentLayout() && child instanceof Container) { |
| Container container = (Container) child; |
| if (container.getLayout() instanceof GridLayoutManager) { |
| return container; |
| } |
| 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) { |
| return childContainer; |
| } |
| } |
| } |
| return null; |
| } |
| |
| protected final Dimension getPreferredSize(final int componentIndex){ |
| Dimension size = myLayoutState.myPreferredSizes[componentIndex]; |
| if (size == null) { |
| size = Util.getPreferredSize(myLayoutState.getComponent(componentIndex), myLayoutState.getConstraints(componentIndex), true); |
| myLayoutState.myPreferredSizes[componentIndex] = size; |
| } |
| return size; |
| } |
| |
| protected final Dimension getMinimumSize(final int componentIndex){ |
| Dimension size = myLayoutState.myMinimumSizes[componentIndex]; |
| if (size == null) { |
| size = Util.getMinimumSize(myLayoutState.getComponent(componentIndex), myLayoutState.getConstraints(componentIndex), true); |
| myLayoutState.myMinimumSizes[componentIndex] = size; |
| } |
| return size; |
| } |
| } |