Java tutorial
/******************************************************************************* * Copyright (c) 2011 Google, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Google, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.wb.internal.swing.MigLayout.model; import com.google.common.collect.Sets; import org.eclipse.wb.draw2d.geometry.Dimension; import org.eclipse.wb.draw2d.geometry.Rectangle; import org.eclipse.wb.internal.core.model.layout.GeneralLayoutData; import org.eclipse.wb.internal.core.model.util.grid.GridConvertionHelper; import org.eclipse.wb.internal.core.model.util.grid.GridConvertionHelper.ComponentGroup; import org.eclipse.wb.internal.core.model.util.grid.GridConvertionHelper.ComponentInGroup; import org.eclipse.wb.internal.swing.MigLayout.model.MigColumnInfo.Alignment; import org.eclipse.wb.internal.swing.model.component.ComponentInfo; import org.eclipse.wb.internal.swing.model.component.ContainerInfo; import net.miginfocom.swing.MigLayout; import org.apache.commons.lang.ArrayUtils; import java.util.List; import java.util.Set; /** * Helper for converting coordinates of {@link ComponentInfo} children to {@link MigLayoutInfo}. * * @author scheglov_ke * @coverage swing.MigLayout.model */ public final class MigLayoutConverter { //////////////////////////////////////////////////////////////////////////// // // Constructor // //////////////////////////////////////////////////////////////////////////// private MigLayoutConverter() { } //////////////////////////////////////////////////////////////////////////// // // Conversion // //////////////////////////////////////////////////////////////////////////// public static void convert(ContainerInfo parent, MigLayoutInfo layout) throws Exception { // prepare columns and rows and distribute controls in them List<ComponentGroup> columns = GridConvertionHelper.buildGroups(parent.getChildrenComponents(), true); List<ComponentGroup> rows = GridConvertionHelper.buildGroups(parent.getChildrenComponents(), false); // sort components in columns and rows GridConvertionHelper.sortGroupsByTranspose(columns, rows); GridConvertionHelper.sortGroupsByTranspose(rows, columns); // ensure that columns and rows are sorted by start coordinates GridConvertionHelper.sortGroups(columns); GridConvertionHelper.sortGroups(rows); // calculate begin/end for each column/row GridConvertionHelper.updateBoundsGaps(columns, true); GridConvertionHelper.updateBoundsGaps(rows, true); // create dimensions in layout { createDimensions(layout, columns, true); createDimensions(layout, rows, false); } // prepare set of components in groups Set<ComponentInGroup> componentsInGroups = Sets.newHashSet(); for (ComponentGroup column : columns) { for (ComponentInGroup componentInGroup : column.getComponents()) { componentsInGroups.add(componentInGroup); } } // create constraints for each control for (ComponentInGroup componentInGroup : componentsInGroups) { ComponentInfo component = (ComponentInfo) componentInGroup.getComponent(); // layout data GeneralLayoutData generalLayoutData = GeneralLayoutData.getFromInfoEx(component); CellConstraintsSupport constraints = MigLayoutInfo.getConstraints(component); // prepare begin/end column/row ComponentGroup beginColumn = GridConvertionHelper.getBeginForComponent(columns, componentInGroup); ComponentGroup endColumn = GridConvertionHelper.getEndForComponent(columns, componentInGroup); ComponentGroup beginRow = GridConvertionHelper.getBeginForComponent(rows, componentInGroup); ComponentGroup endRow = GridConvertionHelper.getEndForComponent(rows, componentInGroup); // update cell coordinates { // calculate location/size int x = columns.indexOf(beginColumn); int y = rows.indexOf(beginRow); int sx = 1 + columns.indexOf(endColumn) - x; int sy = 1 + rows.indexOf(endRow) - y; // set location/size constraints.setX(x); constraints.setY(y); constraints.setWidth(sx); constraints.setHeight(sy); } // alignments constraints .setHorizontalAlignment(getHorizontalAlignment(columns, componentInGroup, generalLayoutData)); constraints.setVerticalAlignment(getVerticalAlignment(rows, componentInGroup, generalLayoutData)); // write constraints constraints.write(); } // write dimensions layout.setObject(new MigLayout()); layout.writeDimensions(); // remove empty columns for (int i = columns.size() - 1; i >= 0; i--) { if (columns.get(i).getComponents().isEmpty()) { layout.deleteColumn(i); } } // remove empty rows for (int i = rows.size() - 1; i >= 0; i--) { if (rows.get(i).getComponents().isEmpty()) { layout.deleteRow(i); } } } /** * Creates {@link MigColumnInfo} or {@link MigRowInfo} for given {@link ComponentGroup}'s. */ private static void createDimensions(MigLayoutInfo layout, List<ComponentGroup> groups, boolean horizontal) throws Exception { for (ComponentGroup group : groups) { // create new "default" dimension MigDimensionInfo dimension; if (horizontal) { MigColumnInfo column = new MigColumnInfo(layout); layout.getColumns().add(column); dimension = column; } else { MigRowInfo row = new MigRowInfo(layout); layout.getRows().add(row); dimension = row; } // set constant size dimension.setSize(group.getSize() + "px"); } } /** * Calculate horizontal alignment. */ private static MigColumnInfo.Alignment getHorizontalAlignment(List<ComponentGroup> columns, ComponentInGroup componentInGroup, GeneralLayoutData generalLayoutData) { if (generalLayoutData.horizontalAlignment != null) { // from general layout data MigColumnInfo.Alignment alignment = GeneralLayoutData .getRealValue(MigLayoutInfo.m_horizontalAlignmentMap, generalLayoutData.horizontalAlignment); if (alignment != null && alignment != MigColumnInfo.Alignment.UNKNOWN) { return alignment; } } // calculate ComponentInfo component = (ComponentInfo) componentInGroup.getComponent(); ComponentGroup beginColumn = GridConvertionHelper.getBeginForComponent(columns, componentInGroup); ComponentGroup endColumn = GridConvertionHelper.getEndForComponent(columns, componentInGroup); // Rectangle bounds = component.getBounds(); Dimension prefSize = component.getPreferredSize(); int bl = bounds.x; int br = bounds.right(); int columnLeft = beginColumn.getMin(); int columnRight = endColumn.getMax(); int columnCenter = columnLeft + (columnRight - columnLeft) / 2; // int leftOffset = Math.abs(bl - columnLeft); int rightOffset = Math.abs(columnRight - br); // prepare how much location of two sides will be changed for each alignment int leftDelta = leftOffset + Math.abs(columnLeft + prefSize.width - br); int rightDelta = rightOffset + Math.abs(columnRight - prefSize.width - bl); int fillDelta = leftOffset + rightOffset; int centerDelta = Math.abs(bl - (columnCenter - prefSize.width / 2)) + Math.abs(br - (columnCenter + prefSize.width / 2)); // set alignment return getAlignment(new int[] { leftDelta, centerDelta, rightDelta, fillDelta }, new MigColumnInfo.Alignment[] { MigColumnInfo.Alignment.LEFT, MigColumnInfo.Alignment.CENTER, MigColumnInfo.Alignment.RIGHT, MigColumnInfo.Alignment.FILL }); } /** * Calculate horizontal alignment. */ private static MigRowInfo.Alignment getVerticalAlignment(List<ComponentGroup> rows, ComponentInGroup componentInGroup, GeneralLayoutData generalLayoutData) { if (generalLayoutData.verticalAlignment != null) { // from general layout data MigRowInfo.Alignment alignment = GeneralLayoutData.getRealValue(MigLayoutInfo.m_verticalAlignmentMap, generalLayoutData.verticalAlignment); if (alignment != null && alignment != MigRowInfo.Alignment.UNKNOWN) { return alignment; } } // calculate ComponentInfo component = (ComponentInfo) componentInGroup.getComponent(); // prepare begin/end column/row ComponentGroup beginRow = GridConvertionHelper.getBeginForComponent(rows, componentInGroup); ComponentGroup endRow = GridConvertionHelper.getEndForComponent(rows, componentInGroup); Rectangle bounds = component.getBounds(); Dimension prefSize = component.getPreferredSize(); int bt = bounds.y; int bb = bounds.bottom(); int rowTop = beginRow.getMin(); int rowBottom = endRow.getMax(); int rowCenter = rowTop + (rowBottom - rowTop) / 2; // int topOffset = bt - rowTop; int bottomOffset = rowBottom - bb; // prepare how much location of two sides will be changed for each alignment int topDelta = topOffset + Math.abs(rowTop + prefSize.height - bb); int bottomDelta = bottomOffset + Math.abs(rowBottom - prefSize.height - bt); int fillDelta = topOffset + bottomOffset; int centerDelta = Math.abs(bt - (rowCenter - prefSize.height / 2)) + Math.abs(bb - (rowCenter + prefSize.height / 2)); // set alignment return getAlignment(new int[] { topDelta, centerDelta, bottomDelta, fillDelta }, new MigRowInfo.Alignment[] { MigRowInfo.Alignment.TOP, MigRowInfo.Alignment.CENTER, MigRowInfo.Alignment.BOTTOM, MigRowInfo.Alignment.FILL }); } /** * @return the {@link Alignment} corresponding to the minimum delta value. */ private static <A extends Enum<?>> A getAlignment(int[] deltas, A[] alignments) { int minimum; { minimum = Integer.MAX_VALUE; for (int i = 0; i < deltas.length; i++) { int delta = deltas[i]; minimum = Math.min(minimum, delta); } } // return corresponding alignment return alignments[ArrayUtils.indexOf(deltas, minimum)]; } }