| /* |
| * 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.compiler; |
| |
| import com.intellij.uiDesigner.core.GridConstraints; |
| import com.intellij.uiDesigner.core.GridLayoutManager; |
| import com.intellij.uiDesigner.core.AbstractLayout; |
| import com.intellij.uiDesigner.core.Util; |
| import com.intellij.uiDesigner.lw.*; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| /** |
| * @author yole |
| */ |
| public class GridBagConverter { |
| private final Insets myInsets; |
| private int myHGap; |
| private int myVGap; |
| private boolean mySameSizeHorz; |
| private boolean mySameSizeVert; |
| private final ArrayList myComponents = new ArrayList(); |
| private final ArrayList myConstraints = new ArrayList(); |
| private int myLastRow = -1; |
| private int myLastCol = -1; |
| |
| public GridBagConverter() { |
| myInsets = new Insets(0, 0, 0, 0); |
| } |
| |
| public GridBagConverter(final Insets insets, final int hgap, final int vgap, final boolean sameSizeHorz, final boolean sameSizeVert) { |
| myInsets = insets; |
| myHGap = hgap; |
| myVGap = vgap; |
| mySameSizeHorz = sameSizeHorz; |
| mySameSizeVert = sameSizeVert; |
| } |
| |
| public void addComponent(final JComponent component, final GridConstraints constraints) { |
| myComponents.add(component); |
| myConstraints.add(constraints); |
| } |
| |
| public static void prepareConstraints(final LwContainer container, final Map idToConstraintsMap) { |
| GridLayoutManager gridLayout = (GridLayoutManager) container.getLayout(); |
| GridBagConverter converter = new GridBagConverter(gridLayout.getMargin(), |
| getGap(container, true), |
| getGap(container, false), |
| gridLayout.isSameSizeHorizontally(), |
| gridLayout.isSameSizeVertically()); |
| for(int i=0; i<container.getComponentCount(); i++) { |
| final LwComponent component = (LwComponent)container.getComponent(i); |
| if (component instanceof LwHSpacer || component instanceof LwVSpacer) { |
| GridConstraints constraints = component.getConstraints().store(); |
| constraints.setHSizePolicy(constraints.getHSizePolicy() & ~GridConstraints.SIZEPOLICY_WANT_GROW); |
| constraints.setVSizePolicy(constraints.getVSizePolicy() & ~GridConstraints.SIZEPOLICY_WANT_GROW); |
| converter.addComponent(null, constraints); |
| } |
| else { |
| converter.addComponent(null, component.getConstraints()); |
| } |
| } |
| Result[] results = converter.convert(); |
| int componentIndex = 0; |
| for(int i=0; i<results.length; i++) { |
| if (!results [i].isFillerPanel) { |
| final LwComponent component = (LwComponent)container.getComponent(componentIndex++); |
| idToConstraintsMap.put(component.getId(), results [i]); |
| } |
| // else generateFillerPanel(generator, componentLocal, results [i]); |
| } |
| } |
| |
| private static int getGap(LwContainer container, final boolean horizontal) { |
| while(container != null) { |
| final LayoutManager layout = container.getLayout(); |
| if (layout instanceof AbstractLayout) { |
| AbstractLayout aLayout = (AbstractLayout) layout; |
| final int gap = horizontal ? aLayout.getHGap() : aLayout.getVGap(); |
| if (gap >= 0) { |
| return gap; |
| } |
| } |
| container = container.getParent(); |
| } |
| return horizontal ? AbstractLayout.DEFAULT_HGAP : AbstractLayout.DEFAULT_VGAP; |
| } |
| |
| public static class Result { |
| public JComponent component; |
| public boolean isFillerPanel; |
| public GridBagConstraints constraints; |
| public Dimension preferredSize; |
| public Dimension minimumSize; |
| public Dimension maximumSize; |
| |
| public Result(final JComponent component) { |
| this.component = component; |
| constraints = new GridBagConstraints(); |
| } |
| } |
| |
| public Result[] convert() { |
| ArrayList results = new ArrayList(); |
| for(int i=0; i<myComponents.size(); i++) { |
| results.add(convert((JComponent) myComponents.get(i), (GridConstraints) myConstraints.get(i))); |
| } |
| //addFillerPanels(results); |
| final Result[] resultArray = (Result[])results.toArray(new Result[results.size()]); |
| if (myHGap > 0 || myVGap > 0) { |
| applyGaps(resultArray); |
| } |
| if (mySameSizeHorz) { |
| makeSameSizes(resultArray, true); |
| } |
| if (mySameSizeVert) { |
| makeSameSizes(resultArray, false); |
| } |
| |
| return resultArray; |
| } |
| |
| private void applyGaps(final Result[] resultArray) { |
| int leftGap = myHGap/2; |
| int rightGap = myHGap - myHGap/2; |
| int topGap = myVGap / 2; |
| int bottomGap = myVGap - myVGap/2; |
| for(int i=0; i<resultArray.length; i++) { |
| Result result = resultArray [i]; |
| if (result.constraints.gridx > 0) { |
| result.constraints.insets.left += leftGap; |
| } |
| if (result.constraints.gridx + result.constraints.gridwidth-1 < myLastCol) { |
| result.constraints.insets.right += rightGap; |
| } |
| if (result.constraints.gridy > 0) { |
| result.constraints.insets.top += topGap; |
| } |
| if (result.constraints.gridy + result.constraints.gridheight-1 < myLastRow) { |
| result.constraints.insets.bottom += bottomGap; |
| } |
| } |
| } |
| |
| private static void makeSameSizes(final Result[] resultArray, boolean horizontal) { |
| int minimum = -1; |
| int preferred = -1; |
| for(int i=0; i<resultArray.length; i++) { |
| Result result = resultArray [i]; |
| Dimension minSize = result.minimumSize != null || result.component == null |
| ? result.minimumSize |
| : result.component.getMinimumSize(); |
| Dimension prefSize = result.preferredSize != null || result.component == null |
| ? result.preferredSize |
| : result.component.getPreferredSize(); |
| if (minSize != null) { |
| minimum = Math.max(minimum, horizontal ? minSize.width : minSize.height); |
| } |
| if (prefSize != null) { |
| preferred = Math.max(preferred, horizontal ? prefSize.width : prefSize.height); |
| } |
| } |
| |
| if (minimum >= 0 || preferred >= 0) { |
| for(int i=0; i<resultArray.length; i++) { |
| Result result = resultArray [i]; |
| |
| if ((result.minimumSize != null || result.component != null) && minimum >= 0) { |
| if (result.minimumSize == null) { |
| result.minimumSize = result.component.getMinimumSize(); |
| } |
| if (horizontal) { |
| result.minimumSize.width = minimum; |
| } |
| else { |
| result.minimumSize.height = minimum; |
| } |
| } |
| |
| if ((result.preferredSize != null || result.component != null) && preferred >= 0) { |
| if (result.preferredSize == null) { |
| result.preferredSize = result.component.getPreferredSize(); |
| } |
| if (horizontal) { |
| result.preferredSize.width = preferred; |
| } |
| else { |
| result.preferredSize.height = preferred; |
| } |
| } |
| } |
| } |
| } |
| |
| private Result convert(final JComponent component, final GridConstraints constraints) { |
| final Result result = new Result(component); |
| |
| int endRow = constraints.getRow() + constraints.getRowSpan()-1; |
| myLastRow = Math.max(myLastRow, endRow); |
| int endCol = constraints.getColumn() + constraints.getColSpan()-1; |
| myLastCol = Math.max(myLastCol, endCol); |
| |
| int indent = Util.DEFAULT_INDENT * constraints.getIndent(); |
| |
| constraintsToGridBag(constraints, result.constraints); |
| result.constraints.weightx = getWeight(constraints, true); |
| result.constraints.weighty = getWeight(constraints, false); |
| result.constraints.insets = new Insets(myInsets.top, myInsets.left + indent, myInsets.bottom, myInsets.right); |
| |
| Dimension minSize = constraints.myMinimumSize; |
| if (component != null && minSize.width <= 0 && minSize.height <= 0) { |
| minSize = component.getMinimumSize(); |
| } |
| |
| if ((constraints.getHSizePolicy() & GridConstraints.SIZEPOLICY_CAN_SHRINK) == 0) { |
| minSize.width = constraints.myPreferredSize.width > 0 || component == null |
| ? constraints.myPreferredSize.width |
| : component.getPreferredSize().width; |
| } |
| if ((constraints.getVSizePolicy() & GridConstraints.SIZEPOLICY_CAN_SHRINK) == 0) { |
| minSize.height = constraints.myPreferredSize.height > 0 || component == null |
| ? constraints.myPreferredSize.height |
| : component.getPreferredSize().height; |
| } |
| |
| if (minSize.width != -1 || minSize.height != -1) { |
| result.minimumSize = minSize; |
| } |
| |
| if (constraints.myPreferredSize.width > 0 && constraints.myPreferredSize.height > 0) { |
| result.preferredSize = constraints.myPreferredSize; |
| } |
| if (constraints.myMaximumSize.width > 0 && constraints.myMaximumSize.height > 0) { |
| result.maximumSize = constraints.myMaximumSize; |
| } |
| |
| return result; |
| } |
| |
| public static GridBagConstraints getGridBagConstraints(IComponent component) { |
| final GridBagConstraints gbc; |
| if (component.getCustomLayoutConstraints() instanceof GridBagConstraints) { |
| gbc = (GridBagConstraints) component.getCustomLayoutConstraints(); |
| } |
| else { |
| gbc = new GridBagConstraints(); |
| } |
| constraintsToGridBag(component.getConstraints(), gbc); |
| return gbc; |
| } |
| |
| public static void constraintsToGridBag(final GridConstraints constraints, final GridBagConstraints result) { |
| result.gridx = constraints.getColumn(); |
| result.gridy = constraints.getRow(); |
| result.gridwidth = constraints.getColSpan(); |
| result.gridheight = constraints.getRowSpan(); |
| switch(constraints.getFill()) { |
| case GridConstraints.FILL_HORIZONTAL: result.fill = GridBagConstraints.HORIZONTAL; break; |
| case GridConstraints.FILL_VERTICAL: result.fill = GridBagConstraints.VERTICAL; break; |
| case GridConstraints.FILL_BOTH: result.fill = GridBagConstraints.BOTH; break; |
| default: result.fill = GridBagConstraints.NONE; break; |
| } |
| switch(constraints.getAnchor()) { |
| case GridConstraints.ANCHOR_NORTHWEST: result.anchor = GridBagConstraints.NORTHWEST; break; |
| case GridConstraints.ANCHOR_NORTH: result.anchor = GridBagConstraints.NORTH; break; |
| case GridConstraints.ANCHOR_NORTHEAST: result.anchor = GridBagConstraints.NORTHEAST; break; |
| case GridConstraints.ANCHOR_EAST: result.anchor = GridBagConstraints.EAST; break; |
| case GridConstraints.ANCHOR_SOUTHEAST: result.anchor = GridBagConstraints.SOUTHEAST; break; |
| case GridConstraints.ANCHOR_SOUTH: result.anchor = GridBagConstraints.SOUTH; break; |
| case GridConstraints.ANCHOR_SOUTHWEST: result.anchor = GridBagConstraints.SOUTHWEST; break; |
| case GridConstraints.ANCHOR_WEST: result.anchor = GridBagConstraints.WEST; break; |
| } |
| } |
| |
| private double getWeight(final GridConstraints constraints, final boolean horizontal) { |
| int policy = horizontal ? constraints.getHSizePolicy() : constraints.getVSizePolicy(); |
| if ((policy & GridConstraints.SIZEPOLICY_WANT_GROW) != 0) { |
| return 1.0; |
| } |
| boolean canGrow = ((policy & GridConstraints.SIZEPOLICY_CAN_GROW) != 0); |
| for (Iterator iterator = myConstraints.iterator(); iterator.hasNext();) { |
| GridConstraints otherConstraints = (GridConstraints)iterator.next(); |
| |
| if (!constraintsIntersect(horizontal, constraints, otherConstraints)) { |
| int otherPolicy = horizontal ? otherConstraints.getHSizePolicy() : otherConstraints.getVSizePolicy(); |
| if ((otherPolicy & GridConstraints.SIZEPOLICY_WANT_GROW) != 0) { |
| return 0.0; |
| } |
| if (!canGrow && ((otherPolicy & GridConstraints.SIZEPOLICY_CAN_GROW) != 0)) { |
| return 0.0; |
| } |
| } |
| } |
| return 1.0; |
| } |
| |
| private boolean constraintsIntersect(final boolean horizontal, |
| final GridConstraints constraints, |
| final GridConstraints otherConstraints) { |
| int start = constraints.getCell(!horizontal); |
| int end = start + constraints.getSpan(!horizontal) - 1; |
| int otherStart = otherConstraints.getCell(!horizontal); |
| int otherEnd = otherStart + otherConstraints.getSpan(!horizontal) - 1; |
| return start <= otherEnd && otherStart <= end; |
| } |
| } |