blob: 6a971ff9a779b8757bbec1b6822bb44418ac47cd [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.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;
}
}