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.FormLayout.model; import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.eclipse.wb.core.editor.IContextMenuConstants; import org.eclipse.wb.core.editor.actions.assistant.AbstractAssistantPage; import org.eclipse.wb.core.gef.policy.layout.grid.IGridInfo; import org.eclipse.wb.core.model.IAbstractComponentInfo; import org.eclipse.wb.core.model.JavaInfo; import org.eclipse.wb.core.model.ObjectInfo; import org.eclipse.wb.core.model.broadcast.JavaInfoAddProperties; import org.eclipse.wb.core.model.broadcast.ObjectEventListener; import org.eclipse.wb.core.model.broadcast.ObjectInfoTreeComplete; import org.eclipse.wb.draw2d.geometry.Dimension; import org.eclipse.wb.draw2d.geometry.Insets; import org.eclipse.wb.draw2d.geometry.Interval; import org.eclipse.wb.draw2d.geometry.Point; import org.eclipse.wb.draw2d.geometry.Rectangle; import org.eclipse.wb.internal.core.DesignerPlugin; import org.eclipse.wb.internal.core.model.creation.ConstructorCreationSupport; import org.eclipse.wb.internal.core.model.creation.CreationSupport; import org.eclipse.wb.internal.core.model.description.ComponentDescription; import org.eclipse.wb.internal.core.model.layout.GeneralLayoutData; import org.eclipse.wb.internal.core.model.property.Property; import org.eclipse.wb.internal.core.model.util.grid.GridAlignmentHelper; import org.eclipse.wb.internal.core.model.util.grid.GridAlignmentHelper.IAlignmentProcessor; import org.eclipse.wb.internal.core.utils.ast.AstEditor; import org.eclipse.wb.internal.core.utils.check.Assert; import org.eclipse.wb.internal.core.utils.execution.ExecutionUtils; import org.eclipse.wb.internal.core.utils.execution.RunnableEx; import org.eclipse.wb.internal.core.utils.jdt.core.CodeUtils; import org.eclipse.wb.internal.swing.FormLayout.Activator; import org.eclipse.wb.internal.swing.FormLayout.model.ui.ColumnsDialog; import org.eclipse.wb.internal.swing.FormLayout.model.ui.RowsDialog; import org.eclipse.wb.internal.swing.model.component.ComponentInfo; import org.eclipse.wb.internal.swing.model.component.ContainerInfo; import org.eclipse.wb.internal.swing.model.layout.LayoutAssistantSupport; import org.eclipse.wb.internal.swing.model.layout.LayoutInfo; import org.eclipse.jdt.core.dom.ClassInstanceCreation; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import com.jgoodies.forms.factories.FormFactory; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.ColumnSpec; import com.jgoodies.forms.layout.FormLayout; import com.jgoodies.forms.layout.FormSpec; import com.jgoodies.forms.layout.RowSpec; import com.jgoodies.forms.util.DefaultUnitConverter; import java.awt.Container; import java.text.MessageFormat; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.JTextField; /** * Model for JGoodies FormLayout. * * @author scheglov_ke * @coverage swing.FormLayout.model */ public final class FormLayoutInfo extends LayoutInfo implements IPreferenceConstants { private final List<FormColumnInfo> m_columns = Lists.newArrayList(); private final List<FormRowInfo> m_rows = Lists.newArrayList(); private final List<List<FormColumnInfo>> m_columnGroups = Lists.newArrayList(); private final List<List<FormRowInfo>> m_rowGroups = Lists.newArrayList(); //////////////////////////////////////////////////////////////////////////// // // Constructor // //////////////////////////////////////////////////////////////////////////// public FormLayoutInfo(AstEditor editor, ComponentDescription description, CreationSupport creationSupport) throws Exception { super(editor, description, creationSupport); } //////////////////////////////////////////////////////////////////////////// // // Initialize // //////////////////////////////////////////////////////////////////////////// @Override protected void initialize() throws Exception { super.initialize(); // create initial columns/rows if (m_columns.isEmpty() && m_rows.isEmpty()) { FormLayout layout = (FormLayout) getObject(); // create columns { int columnCount = layout.getColumnCount(); for (int column = 1; column <= columnCount; column++) { ColumnSpec spec = layout.getColumnSpec(column); m_columns.add(new FormColumnInfo(spec)); } } // create rows { int rowCount = layout.getRowCount(); for (int row = 1; row <= rowCount; row++) { RowSpec spec = layout.getRowSpec(row); m_rows.add(new FormRowInfo(spec)); } } } // events addBroadcastListener(new ObjectInfoTreeComplete() { public void invoke() throws Exception { FormLayout layout = (FormLayout) getObject(); fillDimensionGroups(layout.getColumnGroups(), m_columns, m_columnGroups); fillDimensionGroups(layout.getRowGroups(), m_rows, m_rowGroups); } }); addBroadcastListener(new ObjectEventListener() { @Override public void addContextMenu(List<? extends ObjectInfo> objects, ObjectInfo object, IMenuManager manager) throws Exception { addContextMenuActions(object, manager); } }); addBroadcastListener(new JavaInfoAddProperties() { public void invoke(JavaInfo javaInfo, List<Property> properties) throws Exception { if (isManagedObject(javaInfo)) { ComponentInfo component = (ComponentInfo) javaInfo; CellConstraintsSupport support = getConstraints(component); properties.add(support.getCellProperty()); } } }); // alignment new SelectionActionsSupport(this); // assistant new LayoutAssistantSupport(this) { @Override protected AbstractAssistantPage createConstraintsPage(Composite parent, List<ObjectInfo> objects) { return new CellConstraintsAssistantPage(parent, FormLayoutInfo.this, objects); } }; } @Override protected void removeComponentConstraints(ContainerInfo container, ComponentInfo component) throws Exception { m_constraints.remove(component); super.removeComponentConstraints(container, component); } //////////////////////////////////////////////////////////////////////////// // // Context menu // //////////////////////////////////////////////////////////////////////////// /** * Adds {@link FormLayoutInfo} actions into context menu. */ private void addContextMenuActions(ObjectInfo object, IMenuManager manager) throws Exception { if (object == getContainer()) { manager.appendToGroup(IContextMenuConstants.GROUP_TOP, new EditDimensionsAction(ModelMessages.FormLayoutInfo_editColumns, true)); manager.appendToGroup(IContextMenuConstants.GROUP_TOP, new EditDimensionsAction(ModelMessages.FormLayoutInfo_editRows, false)); } if (object instanceof ComponentInfo && object.getParent() == getContainer()) { ComponentInfo component = (ComponentInfo) object; CellConstraintsSupport support = getConstraints(component); support.addContextMenu(manager); } } //////////////////////////////////////////////////////////////////////////// // // Context menu: EditDimensionsAction // //////////////////////////////////////////////////////////////////////////// private final class EditDimensionsAction extends Action { private final boolean m_horizontal; public EditDimensionsAction(String text, boolean horizontal) { super(text); m_horizontal = horizontal; } @Override public void run() { Shell shell = DesignerPlugin.getShell(); if (m_horizontal) { new ColumnsDialog(shell, FormLayoutInfo.this).open(); } else { new RowsDialog(shell, FormLayoutInfo.this).open(); } } } //////////////////////////////////////////////////////////////////////////// // // Properties // //////////////////////////////////////////////////////////////////////////// @Override protected List<Property> getPropertyList() throws Exception { List<Property> properties = super.getPropertyList(); properties.add(new DimensionsProperty(this, true)); properties.add(new DimensionsProperty(this, false)); return properties; } //////////////////////////////////////////////////////////////////////////// // // CellConstraintsSupport access // //////////////////////////////////////////////////////////////////////////// private final Map<ComponentInfo, CellConstraintsSupport> m_constraints = Maps.newHashMap(); /** * @return the {@link CellConstraintsSupport} for given {@link ComponentInfo}. */ public static CellConstraintsSupport getConstraints(ComponentInfo component) { ContainerInfo container = (ContainerInfo) component.getParent(); Assert.isTrue(container.getChildrenComponents().contains(component)); Assert.instanceOf(FormLayoutInfo.class, container.getLayout()); // FormLayoutInfo layout = (FormLayoutInfo) container.getLayout(); CellConstraintsSupport support = layout.m_constraints.get(component); if (support == null) { support = new CellConstraintsSupport(layout, component); layout.m_constraints.put(component, support); } return support; } @Override public void onSet() throws Exception { super.onSet(); FormLayoutConverter.convert(getContainer(), this); } //////////////////////////////////////////////////////////////////////////// // // Access columns/rows // //////////////////////////////////////////////////////////////////////////// /** * @return the {@link List} of {@link FormColumnInfo}. */ public List<FormColumnInfo> getColumns() { return m_columns; } /** * @return the {@link List} of {@link FormRowInfo}. */ public List<FormRowInfo> getRows() { return m_rows; } /** * Sets the new {@link List} of {@link FormColumnInfo}. */ public void setColumns(List<FormColumnInfo> columns) throws Exception { m_columns.clear(); m_columns.addAll(columns); writeDimensions(); } /** * Sets the new {@link List} of {@link FormRowInfo}. */ public void setRows(List<FormRowInfo> rows) throws Exception { m_rows.clear(); m_rows.addAll(rows); writeDimensions(); } /** * @return the {@link Dimension} with minimal count of columns/rows required for this * {@link FormLayoutInfo}. */ public Dimension getMinimumSize() { final Dimension size = new Dimension(0, 0); ExecutionUtils.runLog(new RunnableEx() { public void run() throws Exception { visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception { size.width = Math.max(size.width, cell.x + cell.width - 1); size.height = Math.max(size.height, cell.y + cell.height - 1); } }); } }); return size; } /** * @return the count of components that begin in each column. */ public int[] getColumnComponentsCounts() throws Exception { final int[] counts = new int[m_columns.size()]; ExecutionUtils.runRethrow(new RunnableEx() { public void run() throws Exception { visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception { counts[cell.x - 1]++; } }); } }); return counts; } /** * @return the count of components that begin in each row. */ public int[] getRowComponentsCounts() throws Exception { final int[] counts = new int[m_rows.size()]; ExecutionUtils.runRethrow(new RunnableEx() { public void run() throws Exception { visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception { counts[cell.y - 1]++; } }); } }); return counts; } /** * If there are components that span multiple columns/rows, and no other "real" components in * these columns/rows, then removes these excess columns/rows. */ public void normalizeSpanning() throws Exception { boolean columnRowDeleted = true; while (columnRowDeleted) { columnRowDeleted = false; // prepare filled columns/rows final boolean[] filledColumns = new boolean[m_columns.size()]; final boolean[] filledRows = new boolean[m_rows.size()]; visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo bean, CellConstraintsSupport constraints) throws Exception { filledColumns[constraints.x - 1] = true; filledRows[constraints.y - 1] = true; } }); // remove empty columns for (int column = filledColumns.length - 1; column >= 0; column--) { if (!filledColumns[column] && !m_columns.get(column).isGap()) { deleteColumn(column); columnRowDeleted = true; break; } } // remove empty rows for (int row = filledRows.length - 1; row >= 0; row--) { if (!filledRows[row] && !m_rows.get(row).isGap()) { deleteRow(row); columnRowDeleted = true; break; } } } // write dimensions writeDimensions(); } /** * @return <code>true</code> if dimensions of this layout can be changed. We can change them only * if we created layout using constructor. */ public boolean canChangeDimensions() { return getCreationSupport() instanceof ConstructorCreationSupport; } /** * Writes columns/rows to the source. */ public void writeDimensions() throws Exception { // write constructor { ConstructorCreationSupport creationSupport = (ConstructorCreationSupport) getCreationSupport(); ClassInstanceCreation creation = creationSupport.getCreation(); // String[] columnsSource = getDimenstionsSource(m_columns, "com.jgoodies.forms.layout.ColumnSpec"); String[] rowsSource = getDimenstionsSource(m_rows, "com.jgoodies.forms.layout.RowSpec"); columnsSource[columnsSource.length - 1] += ","; // getEditor().replaceCreationArguments(creation, ImmutableList.copyOf(CodeUtils.join(columnsSource, rowsSource))); } // write groups writeDimensionsGroups("setColumnGroups", m_columns, m_columnGroups); writeDimensionsGroups("setRowGroups", m_rows, m_rowGroups); } /** * @return the array of source lines for given {@link List} of {@link FormDimensionInfo}. */ private static String[] getDimenstionsSource(List<? extends FormDimensionInfo> dimensions, String typeSource) throws Exception { if (dimensions.isEmpty()) { return new String[] { "\tnew " + typeSource + "[] {}" }; } else { String[] lines = new String[1 + dimensions.size()]; lines[0] = "\tnew " + typeSource + "[] {"; for (int i = 0; i < dimensions.size(); i++) { FormDimensionInfo dimension = dimensions.get(i); lines[1 + i] = "\t\t" + dimension.getSource() + ","; } // lines[lines.length - 1] += "}"; return lines; } } //////////////////////////////////////////////////////////////////////////// // // Groups // //////////////////////////////////////////////////////////////////////////// /** * @return the index of group to which belongs given {@link FormDimensionInfo} or <code>-1</code> * if it does not belong to any group. */ public int getDimensionGroupIndex(FormDimensionInfo dimension) { if (dimension instanceof FormColumnInfo) { FormColumnInfo column = (FormColumnInfo) dimension; return m_columnGroups.indexOf(getColumnGroup(column)); } else { FormRowInfo row = (FormRowInfo) dimension; return m_rowGroups.indexOf(getRowGroup(row)); } } /** * @return the {@link List} of {@link FormColumnInfo} that belong to same group or * <code>null</code> if given {@link FormColumnInfo} does not belong to any group. */ public List<FormColumnInfo> getColumnGroup(FormColumnInfo column) { return getDimensionGroup(column, m_columnGroups); } /** * @return the {@link List} of {@link FormRowInfo} that belong to same group or <code>null</code> * if given {@link FormRowInfo} does not belong to any group. */ public List<FormRowInfo> getRowGroup(FormRowInfo row) { return getDimensionGroup(row, m_rowGroups); } /** * @return the {@link List} of {@link FormDimensionInfo} that belong to same group or * <code>null</code> if given {@link FormDimensionInfo} does not belong to any group. */ private static <T extends FormDimensionInfo> List<T> getDimensionGroup(T dimension, List<List<T>> groups) { for (List<T> group : groups) { if (group.contains(dimension)) { return group; } } // no group return null; } /** * Converts "int[][]" groups into {@link FormDimensionInfo}'s groups. */ private static <T extends FormDimensionInfo> void fillDimensionGroups(int[][] intGroups, List<T> dimensions, List<List<T>> groups) { for (int groupIndex = 0; groupIndex < intGroups.length; groupIndex++) { int[] intGroup = intGroups[groupIndex]; // create group List<T> group = Lists.newArrayList(); groups.add(group); // fill group for (int groupElementIndex = 0; groupElementIndex < intGroup.length; groupElementIndex++) { int dimensionIndex = intGroup[groupElementIndex]; T dimension = dimensions.get(dimensionIndex - 1); group.add(dimension); } } } /** * Adds invocation of "set*Groups(new int[][] {...})" for given {@link FormDimensionInfo}'s and * groups. */ private <T extends FormDimensionInfo> void writeDimensionsGroups(String methodName, List<T> dimensions, List<List<T>> groups) throws Exception { // clean up groups for (Iterator<List<T>> I = groups.iterator(); I.hasNext();) { List<T> group = I.next(); // remove all "dangling" dimensions for (Iterator<T> J = group.iterator(); J.hasNext();) { T dimensionInGroup = J.next(); if (!dimensions.contains(dimensionInGroup)) { J.remove(); } } // remove empty group or group with single dimension if (group.size() < 2) { I.remove(); } } // prepare "set*Groups" invocation String methodSignature = methodName + "(int[][])"; MethodInvocation invocation = getMethodInvocation(methodSignature); // update "set*Groups" if (!groups.isEmpty()) { String groupsSource = "new int[][]{"; for (ListIterator<List<T>> I = groups.listIterator(); I.hasNext();) { List<T> group = I.next(); // open array if (I.previousIndex() != 0) { groupsSource += ", "; } groupsSource += "new int[]{"; // add separate dimensions for (ListIterator<T> J = group.listIterator(); J.hasNext();) { FormDimensionInfo dimensionInGroup = J.next(); if (J.previousIndex() != 0) { groupsSource += ", "; } groupsSource += 1 + dimensions.indexOf(dimensionInGroup); } // close array groupsSource += "}"; } groupsSource += "}"; // if (invocation != null) { Expression groupsExpression = (Expression) invocation.arguments().get(0); getEditor().replaceExpression(groupsExpression, groupsSource); } else { addMethodInvocation(methodSignature, groupsSource); } } else if (invocation != null) { getEditor().removeEnclosingStatement(invocation); } } /** * Un-groups given {@link FormColumnInfo}'s. */ public void unGroupColumns(List<FormColumnInfo> columns) throws Exception { unGroupDimensions(columns, m_columnGroups); writeDimensionsGroups("setColumnGroups", m_columns, m_columnGroups); } /** * Un-groups given {@link FormRowInfo}'s. */ public void unGroupRows(List<FormRowInfo> rows) throws Exception { unGroupDimensions(rows, m_rowGroups); writeDimensionsGroups("setRowGroups", m_rows, m_rowGroups); } /** * Un-groups given {@link FormDimensionInfo}'s. */ private static <T extends FormDimensionInfo> void unGroupDimensions(List<T> dimensions, List<List<T>> groups) throws Exception { for (List<T> group : groups) { group.removeAll(dimensions); } } /** * Groups given {@link FormColumnInfo}'s. */ public void groupColumns(List<FormColumnInfo> columns) throws Exception { groupDimensions(columns, m_columnGroups); writeDimensionsGroups("setColumnGroups", m_columns, m_columnGroups); } /** * Groups given {@link FormRowInfo}'s. */ public void groupRows(List<FormRowInfo> rows) throws Exception { groupDimensions(rows, m_rowGroups); writeDimensionsGroups("setRowGroups", m_rows, m_rowGroups); } /** * Groups given {@link FormDimensionInfo}'s. */ private static <T extends FormDimensionInfo> void groupDimensions(List<T> dimensions, List<List<T>> groups) { // remove gaps for (Iterator<T> I = dimensions.iterator(); I.hasNext();) { T dimension = I.next(); if (dimension.isGap()) { I.remove(); } } // check that at least two dimensions remain if (dimensions.size() < 2) { return; } // check there is one and only one target group List<T> targetGroup = null; for (List<T> group : groups) { for (T dimension : dimensions) { if (group.contains(dimension)) { if (targetGroup == null) { targetGroup = group; } else if (targetGroup != group) { // more than one group selected, ignore return; } } } } // if there are no existing group, create new one if (targetGroup == null) { targetGroup = Lists.newArrayList(); groups.add(targetGroup); } // add all dimensions into group for (T dimension : dimensions) { if (!targetGroup.contains(dimension)) { targetGroup.add(dimension); } } } //////////////////////////////////////////////////////////////////////////// // // Column commands // //////////////////////////////////////////////////////////////////////////// /** * Adds new {@link FormColumnInfo} and possible gap into target index. */ public void insertColumn(int targetIndex) throws Exception { boolean targetLast = targetIndex == m_columns.size(); boolean targetGap = !targetLast && m_columns.get(targetIndex).isGap(); // moveComponentsForInsert(1 + targetIndex, true, -1, false); moveComponentsForInsert(1 + targetIndex, true, -1, false); if (targetGap) { m_columns.add(targetIndex, new FormColumnInfo(FormFactory.RELATED_GAP_COLSPEC)); m_columns.add(targetIndex + 1, new FormColumnInfo(FormFactory.DEFAULT_COLSPEC)); } else if (targetLast) { if (!m_columns.isEmpty() && !m_columns.get(targetIndex - 1).isGap()) { m_columns.add(targetIndex++, new FormColumnInfo(FormFactory.RELATED_GAP_COLSPEC)); } m_columns.add(targetIndex, new FormColumnInfo(FormFactory.DEFAULT_COLSPEC)); } else { m_columns.add(targetIndex, new FormColumnInfo(FormFactory.DEFAULT_COLSPEC)); m_columns.add(targetIndex + 1, new FormColumnInfo(FormFactory.RELATED_GAP_COLSPEC)); } writeDimensions(); } /** * Deletes the {@link FormColumnInfo} with given index. */ public void deleteColumn(int index) throws Exception { // prepare context information boolean isFirst = index == 0; boolean isLast = index == m_columns.size() - 1; boolean isGap = m_columns.get(index).isGap(); boolean isPrevGap = !isFirst && m_columns.get(index - 1).isGap(); boolean isNextGap = !isLast && m_columns.get(index + 1).isGap(); // do delete if (isGap) { deleteSingleColumn(index); // gap } else { deleteSingleColumn(index); // column if (isPrevGap) { deleteSingleColumn(index - 1); // gap } else if (isNextGap) { deleteSingleColumn(index); // gap } } writeDimensions(); } /** * Deletes single {@link FormColumnInfo} with given index. */ private void deleteSingleColumn(final int index) throws Exception { visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception { if (cell.x == 1 + index) { component.delete(); } else if (cell.x > 1 + index) { cell.x--; } else if (cell.x + cell.width > 1 + index) { cell.width--; } cell.write(); } }); m_columns.remove(index); } /** * Deletes the {@link ComponentInfo}'s that located in {@link FormColumnInfo} with given index. */ public void deleteColumnContents(final int index) throws Exception { visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception { if (cell.x == 1 + index) { component.delete(); } } }); } /** * Splits the {@link FormColumnInfo} with given index, i.e. adds duplicate of this * {@link FormColumnInfo}. */ public void splitColumn(final int index) throws Exception { FormColumnInfo column = m_columns.get(index); m_columns.add(index + 1, new FormColumnInfo(FormFactory.RELATED_GAP_COLSPEC)); m_columns.add(index + 2, column.copy()); writeDimensions(); // update constraints visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception { if (cell.x > 1 + index) { cell.x += 2; } else if (cell.x + cell.width > 1 + index) { cell.width += 2; } cell.write(); } }); } /** * Moves {@link FormColumnInfo} at given index (and possible its gap) into target index. */ public void command_MOVE_COLUMN(int index, int targetIndex) throws Exception { // prepare context information for old position boolean isFirst = index == 0; boolean isLast = index == m_columns.size() - 1; boolean isGap = m_columns.get(index).isGap(); boolean isPrevGap = !isFirst && m_columns.get(index - 1).isGap(); boolean isNextGap = !isLast && m_columns.get(index + 1).isGap(); // prepare context information for new position boolean targetFirst = targetIndex == 0; boolean targetLast = targetIndex == m_columns.size(); boolean targetGap = !targetLast && m_columns.get(targetIndex).isGap(); // if (index < targetIndex) { if (isGap) { moveSingleColumn(index, targetIndex); // gap } else if (isPrevGap) { moveSingleColumn(index - 1, targetIndex); // gap moveSingleColumn(index - 1, targetIndex); // column } else if (isFirst && isNextGap) { if (targetLast) { moveSingleColumn(1, targetIndex); // gap moveSingleColumn(0, targetIndex); // column } else { if (targetGap) { targetIndex++; } moveSingleColumn(0, targetIndex); // column moveSingleColumn(0, targetIndex); // gap } } else { moveSingleColumn(index, targetIndex); // column } } else { if (isGap) { moveSingleColumn(index, targetIndex); // gap } else if (isPrevGap && targetFirst && !targetGap) { moveSingleColumn(index, 0); // column moveSingleColumn(index, 1); // gap } else if (isPrevGap) { moveSingleColumn(index, targetIndex); // column moveSingleColumn(index, targetIndex); // gap } else { moveSingleColumn(index, targetIndex); // column } } // writeDimensions(); } /** * Moves single {@link FormColumnInfo}. */ private void moveSingleColumn(final int index, final int targetIndex) throws Exception { FormColumnInfo column = m_columns.remove(index); if (index < targetIndex) { // add column m_columns.add(targetIndex - 1, column); // change constraints visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo bean, CellConstraintsSupport constraints) throws Exception { int x = constraints.x; int w = constraints.width; if (x < 1 + index) { // if component contains source and doesn't contain target, decrease size if (x + w - 1 >= 1 + index && x + w - 1 < 1 + targetIndex) { constraints.width = w - 1; } } else if (x == 1 + index) { constraints.x = targetIndex; constraints.width = 1; } else if (x > 1 + index && x < 1 + targetIndex) { constraints.x = x - 1; // if component contains target, increase size if (x + w - 1 >= 1 + targetIndex) { constraints.width = w + 1; } } else if (x >= 1 + targetIndex) { } constraints.write(); } }); } else { // add column m_columns.add(targetIndex, column); // change constraints visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo bean, CellConstraintsSupport constraints) throws Exception { int x = constraints.x; int w = constraints.width; if (x < 1 + targetIndex) { // if component doesn't contains source and contains target, increase size if (x + w - 1 >= 1 + targetIndex && x + w - 1 < 1 + index) { constraints.width = w + 1; } } else if (x < 1 + index) { constraints.x = x + 1; // if component contains source, decrease size if (x + w - 1 >= 1 + index) { constraints.width = w - 1; } } else if (x == 1 + index) { constraints.x = 1 + targetIndex; constraints.width = 1; } else if (x > 1 + index) { } constraints.write(); } }); } } //////////////////////////////////////////////////////////////////////////// // // Row commands // //////////////////////////////////////////////////////////////////////////// /** * Adds new {@link FormRowInfo} and possible gap into target index. */ public void insertRow(int targetIndex) throws Exception { boolean targetLast = targetIndex == m_rows.size(); boolean targetGap = !targetLast && m_rows.get(targetIndex).isGap(); // moveComponentsForInsert(-1, false, 1 + targetIndex, true); moveComponentsForInsert(-1, false, 1 + targetIndex, true); if (targetGap) { m_rows.add(targetIndex, new FormRowInfo(FormFactory.RELATED_GAP_ROWSPEC)); m_rows.add(targetIndex + 1, new FormRowInfo(FormFactory.DEFAULT_ROWSPEC)); } else if (targetLast) { if (!m_rows.isEmpty() && !m_rows.get(targetIndex - 1).isGap()) { m_rows.add(targetIndex++, new FormRowInfo(FormFactory.RELATED_GAP_ROWSPEC)); } m_rows.add(targetIndex, new FormRowInfo(FormFactory.DEFAULT_ROWSPEC)); } else { m_rows.add(targetIndex, new FormRowInfo(FormFactory.DEFAULT_ROWSPEC)); m_rows.add(targetIndex + 1, new FormRowInfo(FormFactory.RELATED_GAP_ROWSPEC)); } writeDimensions(); } /** * Deletes the {@link FormRowInfo} with given index. */ public void deleteRow(int index) throws Exception { // prepare context information boolean isFirst = index == 0; boolean isLast = index == m_rows.size() - 1; boolean isGap = m_rows.get(index).isGap(); boolean isPrevGap = !isFirst && m_rows.get(index - 1).isGap(); boolean isNextGap = !isLast && m_rows.get(index + 1).isGap(); // do delete if (isGap) { deleteSingleRow(index); // gap } else { deleteSingleRow(index); // row if (isPrevGap) { deleteSingleRow(index - 1); // gap } else if (isNextGap) { deleteSingleRow(index); // gap } } writeDimensions(); } /** * Deletes single {@link FormRowInfo} with given index. */ private void deleteSingleRow(final int index) throws Exception { visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception { if (cell.y == 1 + index) { component.delete(); } else if (cell.y > 1 + index) { cell.y--; } else if (cell.y + cell.height > 1 + index) { cell.height--; } cell.write(); } }); m_rows.remove(index); } /** * Deletes the {@link ComponentInfo}'s that located in {@link FormRowInfo} with given index. */ public void deleteRowContents(final int index) throws Exception { visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception { if (cell.y == 1 + index) { component.delete(); } } }); } /** * Splits the {@link FormRowInfo} with given index, i.e. adds duplicate of this * {@link FormRowInfo}. */ public void splitRow(final int index) throws Exception { FormRowInfo row = m_rows.get(index); m_rows.add(index + 1, new FormRowInfo(FormFactory.RELATED_GAP_ROWSPEC)); m_rows.add(index + 2, row.copy()); writeDimensions(); // update constraints visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception { if (cell.y > 1 + index) { cell.y += 2; } else if (cell.y + cell.height > 1 + index) { cell.height += 2; } cell.write(); } }); } /** * Moves {@link FormRowInfo} at given index (and possible its gap) into target index. */ public void command_MOVE_ROW(int index, int targetIndex) throws Exception { // prepare context information for old position boolean isFirst = index == 0; boolean isLast = index == m_rows.size() - 1; boolean isGap = m_rows.get(index).isGap(); boolean isPrevGap = !isFirst && m_rows.get(index - 1).isGap(); boolean isNextGap = !isLast && m_rows.get(index + 1).isGap(); // prepare context information for new position boolean targetFirst = targetIndex == 0; boolean targetLast = targetIndex == m_rows.size(); boolean targetGap = !targetLast && m_rows.get(targetIndex).isGap(); // if (index < targetIndex) { if (isGap) { moveSingleRow(index, targetIndex); // gap } else if (isPrevGap) { moveSingleRow(index - 1, targetIndex); // gap moveSingleRow(index - 1, targetIndex); // row } else if (isFirst && isNextGap) { if (targetLast) { moveSingleRow(1, targetIndex); // gap moveSingleRow(0, targetIndex); // row } else { if (targetGap) { targetIndex++; } moveSingleRow(0, targetIndex); // row moveSingleRow(0, targetIndex); // gap } } else { moveSingleRow(index, targetIndex); // row } } else { if (isGap) { moveSingleRow(index, targetIndex); // gap } else if (isPrevGap && targetFirst && !targetGap) { moveSingleRow(index, 0); // row moveSingleRow(index, 1); // gap } else if (isPrevGap) { moveSingleRow(index, targetIndex); // row moveSingleRow(index, targetIndex); // gap } else { moveSingleRow(index, targetIndex); // row } } // writeDimensions(); } /** * Moves single {@link FormRowInfo}. */ private void moveSingleRow(final int index, final int targetIndex) throws Exception { FormRowInfo row = m_rows.remove(index); if (index < targetIndex) { // add row m_rows.add(targetIndex - 1, row); // change constraints visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo bean, CellConstraintsSupport constraints) throws Exception { int y = constraints.y; int h = constraints.height; if (y < 1 + index) { // if component contains source and doesn't contain target, decrease size if (y + h - 1 >= 1 + index && y + h - 1 < 1 + targetIndex) { constraints.height = h - 1; } } else if (y == 1 + index) { constraints.y = targetIndex; constraints.height = 1; } else if (y > 1 + index && y < 1 + targetIndex) { constraints.y = y - 1; // if component contains target, increase size if (y + h - 1 >= 1 + targetIndex) { constraints.height = h + 1; } } else if (y >= 1 + targetIndex) { } constraints.write(); } }); } else { // add row m_rows.add(targetIndex, row); // change constraints visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo bean, CellConstraintsSupport constraints) throws Exception { int y = constraints.y; int h = constraints.height; if (y < 1 + targetIndex) { // if component doesn't contains source and contains target, increase size if (y + h - 1 >= 1 + targetIndex && y + h - 1 < 1 + index) { constraints.height = h + 1; } } else if (y < 1 + index) { constraints.y = y + 1; // if component contains source, decrease size if (y + h - 1 >= 1 + index) { constraints.height = h - 1; } } else if (y == 1 + index) { constraints.y = 1 + targetIndex; constraints.height = 1; } else if (y > 1 + index) { } constraints.write(); } }); } } //////////////////////////////////////////////////////////////////////////// // // Commands // //////////////////////////////////////////////////////////////////////////// /** * Creates new {@link ComponentInfo} in given cell. * * @param newComponent * the new {@link ComponentInfo} to create. * @param column * the column in {@link FormLayout} terms (1 based). * @param row * the row in {@link FormLayout} terms (1 based). */ public void command_CREATE(ComponentInfo newComponent, int column, boolean insertColumn, int row, boolean insertRow) throws Exception { Point cell = prepareCell(column, insertColumn, row, insertRow); // do add ComponentInfo nextComponent = getReference(column, row, null); add(newComponent, "\"" + cell.x + ", " + cell.y + "\"", nextComponent); { CellConstraintsSupport constraints = getConstraints(newComponent); constraints.x = cell.x; constraints.y = cell.y; } doAutomaticAlignment(newComponent); } /** * Moves existing {@link ComponentInfo} into new cell. */ public void command_MOVE(ComponentInfo component, int column, boolean insertColumn, int row, boolean insertRow) throws Exception { Point cell = prepareCell(column, insertColumn, row, insertRow); // move in components { ComponentInfo nextComponent = getReference(column, row, component); move(component, null, nextComponent); } // move in grid { CellConstraintsSupport constraints = getConstraints(component); constraints.x = cell.x; constraints.y = cell.y; constraints.width = 1; constraints.height = 1; constraints.write(); } } /** * Adds {@link ComponentInfo} from other parent into cell. */ public void command_ADD(ComponentInfo component, int column, boolean insertColumn, int row, boolean insertRow) throws Exception { Point cell = prepareCell(column, insertColumn, row, insertRow); // move in components { ComponentInfo nextComponent = getReference(column, row, component); move(component, "\"" + cell.x + ", " + cell.y + "\"", nextComponent); } // move in grid { CellConstraintsSupport constraints = getConstraints(component); constraints.x = cell.x; constraints.y = cell.y; constraints.write(); } } /** * @return the {@link ComponentInfo} that should be used as reference of adding into given cell. * * @param exclude * the {@link ComponentInfo} that should not be checked, for example because we move it * now. */ private ComponentInfo getReference(int column, int row, ComponentInfo exclude) throws Exception { for (ComponentInfo component : getContainer().getChildrenComponents()) { if (component != exclude) { CellConstraintsSupport constraints = getConstraints(component); if (constraints.y > row || constraints.y == row && constraints.x >= column) { return component; } } } // no reference return null; } /** * Prepares cell with given column/row - inserts columns/rows if necessary. */ private Point prepareCell(int column, boolean insertColumn, int row, boolean insertRow) throws Exception { boolean writeDimensions = false; if (insertColumn || insertRow) { // move existing components { moveComponentsForInsert(column, insertColumn, row, insertRow); moveComponentsForInsert(column, insertColumn, row, insertRow); } // insert gap and empty column/row if (insertColumn) { m_columns.add(column - 1, new FormColumnInfo(FormFactory.RELATED_GAP_COLSPEC)); m_columns.add(column - 1 + 1, new FormColumnInfo(FormFactory.DEFAULT_COLSPEC)); column += 1; } if (insertRow) { m_rows.add(row - 1, new FormRowInfo(FormFactory.RELATED_GAP_ROWSPEC)); m_rows.add(row - 1 + 1, new FormRowInfo(FormFactory.DEFAULT_ROWSPEC)); row += 1; } // write dimensions writeDimensions = true; } // add columns { int addColumns = column - m_columns.size(); if (addColumns > 0) { Assert.isTrue(addColumns % 2 == 0, MessageFormat.format(ModelMessages.FormLayoutInfo_evenDiffNumColumns, addColumns)); for (int i = 0; i < addColumns / 2; i++) { m_columns.add(new FormColumnInfo(FormFactory.RELATED_GAP_COLSPEC)); m_columns.add(new FormColumnInfo(FormFactory.DEFAULT_COLSPEC)); } writeDimensions = true; } } // add rows { int addRows = row - m_rows.size(); if (addRows > 0) { Assert.isTrue(addRows % 2 == 0, MessageFormat.format(ModelMessages.FormLayoutInfo_evenDiffNumRows, addRows)); for (int i = 0; i < addRows / 2; i++) { m_rows.add(new FormRowInfo(FormFactory.RELATED_GAP_ROWSPEC)); m_rows.add(new FormRowInfo(FormFactory.DEFAULT_ROWSPEC)); } writeDimensions = true; } } // write dimensions if (writeDimensions) { writeDimensions(); } // return new cell return new Point(column, row); } /** * Moves/resizes components constraints for inserting single column/row. */ private void moveComponentsForInsert(final int column, final boolean insertColumn, final int row, final boolean insertRow) throws Exception { visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception { if (insertColumn) { if (cell.x >= column) { cell.x++; } else if (cell.x + cell.width > column) { cell.width++; } } if (insertRow) { if (cell.y >= row) { cell.y++; } else if (cell.y + cell.height > row) { cell.height++; } } cell.write(); } }); } //////////////////////////////////////////////////////////////////////////// // // Visiting // //////////////////////////////////////////////////////////////////////////// /** * Visitor for {@link ComponentInfo} and their {@link CellConstraintsSupport}. */ private interface FormComponentVisitor { void visit(ComponentInfo component, CellConstraintsSupport cell) throws Exception; } /** * Visits all {@link ComponentInfo} of this {@link ContainerInfo}. */ private void visitComponents(FormComponentVisitor visitor) throws Exception { for (ComponentInfo component : getContainer().getChildrenComponents()) { CellConstraintsSupport cell = getConstraints(component); visitor.visit(component, cell); } } //////////////////////////////////////////////////////////////////////////// // // Automatic alignment // //////////////////////////////////////////////////////////////////////////// /** * Performs automatic alignment, such as grab/fill for {@link JTextField} or {@link JTable}, right * alignment for {@link JLabel}. */ private void doAutomaticAlignment(ComponentInfo component) throws Exception { final IPreferenceStore preferences = Activator.getDefault().getPreferenceStore(); GridAlignmentHelper.doAutomaticAlignment(component, new IAlignmentProcessor<ComponentInfo>() { public boolean grabEnabled() { return preferences.getBoolean(P_ENABLE_GRAB); } public boolean rightEnabled() { return preferences.getBoolean(P_ENABLE_RIGHT_ALIGNMENT); } public ComponentInfo getComponentAtLeft(ComponentInfo component) { CellConstraintsSupport constraints = getConstraints(component); int x = constraints.x - 1; if (x > 0 && m_columns.get(x - 1).isGap()) { x--; } return getComponentAt(x, constraints.y); } public ComponentInfo getComponentAtRight(ComponentInfo component) { CellConstraintsSupport constraints = getConstraints(component); int x = constraints.x + 1; if (x < m_columns.size() && m_columns.get(x - 1).isGap()) { x++; } return getComponentAt(x, constraints.y); } public void setGrabFill(ComponentInfo component, boolean horizontal) throws Exception { boolean canChangeDimensions = canChangeDimensions(); CellConstraintsSupport constraints = getConstraints(component); if (horizontal) { if (canChangeDimensions) { getColumns().get(constraints.x - 1).setWeight(FormSpec.DEFAULT_GROW); } constraints.setAlignH(CellConstraints.FILL); } else { if (canChangeDimensions) { getRows().get(constraints.y - 1).setWeight(FormSpec.DEFAULT_GROW); } constraints.setAlignV(CellConstraints.FILL); } if (canChangeDimensions) { writeDimensions(); } constraints.write(); } public void setRightAlignment(ComponentInfo component) throws Exception { CellConstraintsSupport constraints = getConstraints(component); constraints.setAlignH(CellConstraints.RIGHT); constraints.write(); } }); } /** * @return the {@link ComponentInfo} with given top-left cell, may be <code>null</code>. */ private ComponentInfo getComponentAt(int x, int y) { for (ComponentInfo component : getContainer().getChildrenComponents()) { CellConstraintsSupport constraints = getConstraints(component); if (constraints.x == x && constraints.y == y) { return component; } } // no such component return null; } //////////////////////////////////////////////////////////////////////////// // // Refresh // //////////////////////////////////////////////////////////////////////////// private static final int DEFAULT_SIZE = 5; private int m_defaultColumnSize; private int m_gapColumnSize; private int m_defaultRowSize; private int m_gapRowSize; @Override public void refresh_dispose() throws Exception { m_gridInfo = null; super.refresh_dispose(); } @Override protected void refresh_afterCreate2() throws Exception { super.refresh_afterCreate2(); FormLayout layout = (FormLayout) getObject(); Container container = getContainer().getContainer(); // prepare origins int[] columnOrigins; int[] rowOrigins; { com.jgoodies.forms.layout.FormLayout.LayoutInfo layoutInfo = layout.getLayoutInfo(container); columnOrigins = layoutInfo.columnOrigins; rowOrigins = layoutInfo.rowOrigins; } // initialize default sizes in pixels { DefaultUnitConverter converter = DefaultUnitConverter.getInstance(); // m_defaultColumnSize = converter.millimeterAsPixel(DEFAULT_SIZE, container); m_defaultRowSize = converter.millimeterAsPixel(DEFAULT_SIZE, container); m_gapColumnSize = new FormSizeInfo(FormFactory.RELATED_GAP_COLSPEC.getSize(), true).getConstantSize() .getAsPixels(); m_gapRowSize = new FormSizeInfo(FormFactory.RELATED_GAP_ROWSPEC.getSize(), false).getConstantSize() .getAsPixels(); } // set constant size for empty columns/rows { int columnCount = layout.getColumnCount(); int rowCount = layout.getRowCount(); // update columns for (int column = 1; column <= columnCount; column++) { ColumnSpec spec = layout.getColumnSpec(column); if (columnOrigins[column] - columnOrigins[column - 1] == 0) { spec = ColumnSpec.decode(DEFAULT_SIZE + "mm"); layout.setColumnSpec(column, spec); } } // update rows for (int row = 1; row <= rowCount; row++) { RowSpec spec = layout.getRowSpec(row); if (rowOrigins[row] - rowOrigins[row - 1] == 0) { spec = RowSpec.decode(DEFAULT_SIZE + "mm"); layout.setRowSpec(row, spec); } } // may be column/row specs were updated, force layout container.doLayout(); } } //////////////////////////////////////////////////////////////////////////// // // IGridInfo support // //////////////////////////////////////////////////////////////////////////// private IGridInfo m_gridInfo; /** * @return the {@link IGridInfo} that describes this layout. */ public IGridInfo getGridInfo() { if (m_gridInfo == null) { ExecutionUtils.runRethrow(new RunnableEx() { public void run() throws Exception { createGridInfo(); } }); } return m_gridInfo; } /** * Initializes {@link #m_gridInfo}. */ private void createGridInfo() throws Exception { // prepare intervals final Interval[] columnIntervals; final Interval[] rowIntervals; { // prepare origins int[] columnOrigins; int[] rowOrigins; { FormLayout layout = (FormLayout) getObject(); Container container = getContainer().getContainer(); com.jgoodies.forms.layout.FormLayout.LayoutInfo layoutInfo = layout.getLayoutInfo(container); // columnOrigins = layoutInfo.columnOrigins; rowOrigins = layoutInfo.rowOrigins; } // convert origins into intervals columnIntervals = getIntervalsForOrigins(columnOrigins); rowIntervals = getIntervalsForOrigins(rowOrigins); } // prepare cells final Map<ComponentInfo, Rectangle> componentToCells = Maps.newHashMap(); final Map<Point, ComponentInfo> occupiedCells = Maps.newHashMap(); visitComponents(new FormComponentVisitor() { public void visit(ComponentInfo component, CellConstraintsSupport support) throws Exception { Rectangle cells = new Rectangle(support.x - 1, support.y - 1, support.width, support.height); // fill map: ComponentInfo -> cells Rectangle componentToCells.put(component, cells); // fill occupied cells map for (int x = cells.x; x < cells.right(); x++) { for (int y = cells.y; y < cells.bottom(); y++) { occupiedCells.put(new Point(x, y), component); } } } }); // create IGridInfo instance m_gridInfo = new IGridInfo() { //////////////////////////////////////////////////////////////////////////// // // Dimensions // //////////////////////////////////////////////////////////////////////////// public int getColumnCount() { return columnIntervals.length; } public int getRowCount() { return rowIntervals.length; } //////////////////////////////////////////////////////////////////////////// // // Intervals // //////////////////////////////////////////////////////////////////////////// public Interval[] getColumnIntervals() { return columnIntervals; } public Interval[] getRowIntervals() { return rowIntervals; } //////////////////////////////////////////////////////////////////////////// // // Cells // //////////////////////////////////////////////////////////////////////////// public Rectangle getComponentCells(IAbstractComponentInfo component) { Assert.instanceOf(ComponentInfo.class, component); return componentToCells.get(component); } public Rectangle getCellsRectangle(Rectangle cells) { int x = columnIntervals[cells.x].begin; int y = rowIntervals[cells.y].begin; int w = columnIntervals[cells.right() - 1].end() - x; int h = rowIntervals[cells.bottom() - 1].end() - y; return new Rectangle(x, y, w + 1, h + 1); } //////////////////////////////////////////////////////////////////////////// // // Feedback // //////////////////////////////////////////////////////////////////////////// public boolean isRTL() { return false; } public Insets getInsets() { return getContainer().getInsets(); } //////////////////////////////////////////////////////////////////////////// // // Virtual columns // //////////////////////////////////////////////////////////////////////////// public boolean hasVirtualColumns() { return true; } public int getVirtualColumnSize() { return m_defaultColumnSize; } public int getVirtualColumnGap() { return m_gapColumnSize; } //////////////////////////////////////////////////////////////////////////// // // Virtual rows // //////////////////////////////////////////////////////////////////////////// public boolean hasVirtualRows() { return true; } public int getVirtualRowSize() { return m_defaultRowSize; } public int getVirtualRowGap() { return m_gapRowSize; } //////////////////////////////////////////////////////////////////////////// // // Checks // //////////////////////////////////////////////////////////////////////////// public ComponentInfo getOccupied(int column, int row) { return occupiedCells.get(new Point(column, row)); } }; } //////////////////////////////////////////////////////////////////////////// // // Manage general layout data. // //////////////////////////////////////////////////////////////////////////// public static final BiMap<GeneralLayoutData.HorizontalAlignment, CellConstraints.Alignment> m_horizontalAlignmentMap = ImmutableBiMap .of(GeneralLayoutData.HorizontalAlignment.LEFT, CellConstraints.LEFT, GeneralLayoutData.HorizontalAlignment.CENTER, CellConstraints.CENTER, GeneralLayoutData.HorizontalAlignment.RIGHT, CellConstraints.RIGHT, GeneralLayoutData.HorizontalAlignment.FILL, CellConstraints.FILL, GeneralLayoutData.HorizontalAlignment.NONE, CellConstraints.DEFAULT); public static final BiMap<GeneralLayoutData.VerticalAlignment, CellConstraints.Alignment> m_verticalAlignmentMap = ImmutableBiMap .of(GeneralLayoutData.VerticalAlignment.TOP, CellConstraints.TOP, GeneralLayoutData.VerticalAlignment.CENTER, CellConstraints.CENTER, GeneralLayoutData.VerticalAlignment.BOTTOM, CellConstraints.BOTTOM, GeneralLayoutData.VerticalAlignment.FILL, CellConstraints.FILL, GeneralLayoutData.VerticalAlignment.NONE, CellConstraints.DEFAULT); @Override protected void storeLayoutData(ComponentInfo component) throws Exception { CellConstraintsSupport gridData = getConstraints(component); if (gridData != null) { GeneralLayoutData generalLayoutData = new GeneralLayoutData(); int x = gridData.x - 1; int y = gridData.y - 1; int width = gridData.width; int height = gridData.height; int dx = 0; int dy = 0; // correct position for (int i = 0; i < x; i++) { if (m_columns.get(i).isGap()) { dx--; } } for (int j = 0; j < y; j++) { if (m_rows.get(j).isGap()) { dy--; } } // correct size for (int i = 1; i < width; i++) { if (m_columns.get(x + i).isGap()) { width--; } } for (int j = 1; j < height; j++) { if (m_rows.get(y + j).isGap()) { height--; } } // cell generalLayoutData.gridX = x + dx; generalLayoutData.gridY = y + dy; generalLayoutData.spanX = width; generalLayoutData.spanY = height; // grab generalLayoutData.horizontalGrab = m_columns.get(gridData.x - 1).hasGrow(); generalLayoutData.verticalGrab = m_rows.get(gridData.y - 1).hasGrow(); // alignments generalLayoutData.horizontalAlignment = GeneralLayoutData.getGeneralValue(m_horizontalAlignmentMap, gridData.alignH); generalLayoutData.verticalAlignment = GeneralLayoutData.getGeneralValue(m_verticalAlignmentMap, gridData.alignV); generalLayoutData.putToInfo(component); } } //////////////////////////////////////////////////////////////////////////// // // Utils // //////////////////////////////////////////////////////////////////////////// /** * @return the array of {@link Interval}'s for given array of origins. */ private static Interval[] getIntervalsForOrigins(int origins[]) { Assert.isTrue(origins.length != 0); Interval[] intervals = new Interval[origins.length - 1]; for (int i = 0; i < intervals.length; i++) { int begin = origins[i]; int end = origins[i + 1]; intervals[i] = new Interval(begin, end - begin); } return intervals; } }