blob: 65cc64392c978774d3001b74a0d347447d84f351 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) and others.
* 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:
* Soyatec - initial API and implementation
*******************************************************************************/
package org.eclipse.xwt.tools.ui.designer.policies.layout.grid;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.xwt.tools.ui.designer.policies.layout.GridLayoutEditPolicy;
import org.eclipse.xwt.tools.ui.designer.policies.layout.grid.GridLayoutPolicyHelper.GridComponent;
/**
* @author jliu jin.liu@soyatec.com
*/
public class GridLayoutGridFigure extends Figure {
// number of pixels either side of a row/column that will trigger showing the row/column insertion figure.
public static final int ROW_COLUMN_SENSITIVITY = 5;
private GridLayoutPolicyHelper helper;
private int marginWidth, marginHeight, verticalSpacing, horizontalSpacing;
// Note: all of these that have "model" in the name positions are relative in the model coordinate system (which may be Right-to-Left and so backwards
// from the GEF grid figure).
int[] columnModelPositions, rowModelPositions;
Point[] rowStartModelPositions, rowEndModelPositions;
Point[] columnStartModelPositions, columnEndModelPositions;
int[][] columnModelSegments, rowModelSegments;
/**
* @param copy
*/
public GridLayoutGridFigure(GridLayoutPolicyHelper helper) {
this.helper = helper;
setBounds(helper.getClientArea());
if (helper != null) {
Rectangle spacing = helper.getLayoutSpacing();
marginWidth = spacing.x;
marginHeight = spacing.y;
verticalSpacing = spacing.height;
horizontalSpacing = spacing.width;
} else {
GridLayout example = new GridLayout();
marginWidth = example.marginWidth;
marginHeight = example.marginHeight;
horizontalSpacing = example.horizontalSpacing;
verticalSpacing = example.verticalSpacing;
}
if (helper != null) {
int[][] layoutDimensions = helper.getLayoutDimensions();
GridComponent[][] cellContents = helper.getLayoutTable();
if (layoutDimensions != null) {
int[] columnWidths = layoutDimensions[0];
int[] rowHeights = layoutDimensions[1];
columnModelSegments = calculateColumnDividers(columnWidths, rowHeights, cellContents);
rowModelSegments = calculateRowDividers(columnWidths, rowHeights, cellContents);
}
}
}
protected int[][] calculateColumnDividers(int[] columnWidths, int[] rowHeights, GridComponent[][] cellContents) {
if (rowHeights == null || columnWidths == null /* || helper.getClientArea() == null */)
return null;
int spacingLeft = (int) Math.ceil((double) horizontalSpacing / 2);
int spacingRight = (int) Math.floor((double) horizontalSpacing / 2);
int spacingTop = (int) Math.ceil((double) verticalSpacing / 2);
int spacingBottom = (int) Math.floor((double) verticalSpacing / 2);
int containerHeight = 0;
columnModelPositions = new int[columnWidths.length + 1];
columnStartModelPositions = new Point[columnModelPositions.length];
columnEndModelPositions = new Point[columnModelPositions.length];
int[][] columnSegments = new int[columnModelPositions.length][];
for (int i = 0; i < rowHeights.length; i++) {
containerHeight += rowHeights[i];
}
// add height for the spacing
containerHeight += marginHeight * 2;
containerHeight += verticalSpacing * (rowHeights.length - 1);
Rectangle clientArea = /* helper.getClientArea() */getBounds().getCopy();
int xPos = clientArea.x;
int yMin = clientArea.y;
int yMax = clientArea.y + containerHeight;
int xMax = xPos + clientArea.width - 1; // This is the far right side, less one so that it draws within the box (otherwise it would be outside the box).
// draw the first divider
columnModelPositions[0] = xPos;
columnStartModelPositions[0] = new Point(xPos, yMin);
columnEndModelPositions[0] = new Point(xPos, yMax);
columnSegments[0] = new int[] { yMin, yMax }; // The left border will always be one segemnt.
// move up by the initial margin width
xPos += marginWidth;
int[] colSegs = new int[2 + rowHeights.length * 2]; // Each entry is a y position. They are in 2-tuples (start,stop) for a segment. For a col, it is max of one segment(or 2 points) + 2 for start of next.
// draw the dividers in between and at the end
for (int i = 1; i < columnModelPositions.length; i++) {
xPos += columnWidths[i - 1];
// Place the position in the middle of the the horizontal spacing gap
if (i < columnWidths.length) {
xPos += spacingLeft;
} else {
// or after the end margin, if this is the last line
xPos += marginWidth;
}
xPos = Math.min(xPos, xMax);
Point startPoint = new Point(xPos, yMin);
columnModelPositions[i] = xPos;
columnStartModelPositions[i] = startPoint;
columnEndModelPositions[i] = new Point(xPos, yMax);
// Now calculate the column segments.
if (i < columnWidths.length && i < cellContents.length) {
GridComponent[] leftColumn = cellContents[i - 1];
GridComponent[] rightColumn = cellContents[i];
int yPos = yMin;
int lastRow = leftColumn.length - 1;
int colSegsNdx = 0; // This will always point to the start index of the next segment.
colSegs[colSegsNdx] = yMin; // Will always start at yMin.
boolean prevSpan = true; // Previous was a span. (We treat first one as previous span so as not to close off an empty segment)
// Walk each row, and compare left and right column to see if spanned.
for (int j = 0; j < leftColumn.length; j++) {
int trueRowHeight = 0;
if (j < rowHeights.length)// if there is not this condition,it may cause an exception;
trueRowHeight = rowHeights[j];
if (j == 0)
trueRowHeight += marginHeight;
else
trueRowHeight += spacingTop;
if (j != lastRow)
trueRowHeight += spacingBottom;
else
trueRowHeight += marginHeight;
GridComponent leftObject, rightObject;
if ((leftObject = leftColumn[j]) != helper.EMPTY_GRID && (rightObject = rightColumn[j]) != helper.EMPTY_GRID && leftObject == rightObject) {
// We are spanning, so skip it and move start of segment to next cell.
if (!prevSpan) {
// Need to close off previous one (if not first)
colSegs[++colSegsNdx] = yPos;
colSegsNdx++; // Move to start of next.
}
yPos += trueRowHeight;
colSegs[colSegsNdx] = yPos + 1; // Start of next seg.
prevSpan = true;
} else {
// We are not spanning, continue line through it.
prevSpan = false;
yPos += trueRowHeight;
}
}
if (colSegs[colSegsNdx] < yPos) {
// We have to something to draw for last segment.
colSegs[++colSegsNdx] = yMax;
} else
colSegsNdx--; // We had a segment start that is the same as the last stop, so get rid of it.
columnSegments[i] = new int[++colSegsNdx];
System.arraycopy(colSegs, 0, columnSegments[i], 0, colSegsNdx);
} else {
columnSegments[i] = new int[] { yMin, yMax }; // The right border will always be one segemnt.
}
// add the remainder of the spacing
xPos += spacingRight;
}
return columnSegments;
}
protected int[][] calculateRowDividers(int[] columnWidths, int[] rowHeights, GridComponent[][] cellContents) {
if (columnWidths == null || rowHeights == null /* || helper.getClientArea() == null */)
return null;
int spacingLeft = (int) Math.ceil((double) horizontalSpacing / 2);
int spacingRight = (int) Math.floor((double) horizontalSpacing / 2);
int spacingTop = (int) Math.ceil((double) verticalSpacing / 2);
int spacingBottom = (int) Math.floor((double) verticalSpacing / 2);
int containerWidth = 0;
rowModelPositions = new int[rowHeights.length + 1];
rowStartModelPositions = new Point[rowModelPositions.length];
rowEndModelPositions = new Point[rowModelPositions.length];
int[][] rowSegments = new int[rowModelPositions.length][];
for (int i = 0; i < columnWidths.length; i++) {
containerWidth += columnWidths[i];
}
// add width for the spacing
containerWidth += marginWidth * 2;
containerWidth += horizontalSpacing * (columnWidths.length - 1);
Rectangle clientArea = /* helper.getClientArea() */getBounds().getCopy();
int yPos = clientArea.y;
int xMin = clientArea.x;
int xMax = clientArea.x + containerWidth;
int yMax = yPos + clientArea.height - 1; // This is the bottom side, less one so that it draws within the box (otherwise it would be outside the box).
// draw the first divider
rowModelPositions[0] = yPos;
rowStartModelPositions[0] = new Point(xMin, yPos);
rowEndModelPositions[0] = new Point(xMax, yPos);
rowSegments[0] = new int[] { xMin, xMax }; // The top border will always be one segemnt.
// move up the initial margin height
yPos += marginHeight;
int[] rowSegs = new int[2 + columnWidths.length * 2]; // Each entry is an x position. They are in 2-tuples (start,stop) for a segment. For a row, it is max of one segment(or 2 points) + 2 for start of next.
// draw the dividers in between and at the end
for (int i = 1; i < rowModelPositions.length; i++) {
yPos += rowHeights[i - 1];
// Place the position in the middle of the the vertical spacing gap
if (i < rowHeights.length) {
yPos += spacingTop;
} else {
// or after the end margin, if this is the last line
yPos += marginHeight;
}
yPos = Math.min(yPos, yMax);
Point startPoint = new Point(xMin, yPos);
Point endPoint = new Point(xMax, yPos);
rowModelPositions[i] = yPos;
rowStartModelPositions[i] = startPoint;
rowEndModelPositions[i] = endPoint;
// Now calculate the row segments.
if (i < rowHeights.length) {
int upperRow = i - 1;
int lowerRow = i;
int xPos = xMin;
int length = Math.min(cellContents.length, columnWidths.length);
int lastCol = length - 1;
int rowSegsNdx = 0; // This will always point to the start index of the next segment.
rowSegs[rowSegsNdx] = xMin; // Will always start at xMin.
boolean prevSpan = true; // Previous was a span. (We treat first one as previous span so as not to close off an empty segment)
// Walk each column comparing upper row and lower to see if spanned.
for (int j = 0; j < length; j++) {
int trueColWidth = columnWidths[j];
if (j == 0)
trueColWidth += marginWidth;
else
trueColWidth += spacingLeft;
if (j != lastCol)
trueColWidth += spacingRight;
else
trueColWidth += marginWidth;
GridComponent upperObject, lowerObject;
if ((upperObject = cellContents[j][upperRow]) != helper.EMPTY_GRID && (lowerObject = cellContents[j][lowerRow]) != helper.EMPTY_GRID && upperObject == lowerObject) {
// We are spanning, so skip it and move start of segment to next cell.
if (!prevSpan) {
// Need to close off previous one (if not first)
rowSegs[++rowSegsNdx] = xPos;
rowSegsNdx++; // Move to start of next.
}
xPos += trueColWidth;
rowSegs[rowSegsNdx] = xPos + 1; // Start of next seg.
prevSpan = true;
} else {
// We are not spanning, continue line through it.
xPos += trueColWidth;
prevSpan = false;
}
}
if (rowSegs[rowSegsNdx] < xPos) {
// We have to something to draw for last segment.
rowSegs[++rowSegsNdx] = xMax;
} else
rowSegsNdx--; // We had a segment start that is the same as the last stop, so get rid of it.
rowSegments[i] = new int[++rowSegsNdx];
System.arraycopy(rowSegs, 0, rowSegments[i], 0, rowSegsNdx);
} else {
rowSegments[i] = new int[] { xMin, xMax }; // The bottom border will always be one segemnt.
}
// add the remainder of the spacing
yPos += spacingBottom;
}
return rowSegments;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.draw2d.Figure#paintFigure(org.eclipse.draw2d.Graphics)
*/
protected void paintFigure(Graphics g) {
g.setForegroundColor(ColorConstants.gray);
g.setLineStyle(Graphics.LINE_DOT);
drawRowDividers(g);
drawColumnDividers(g);
}
protected void drawColumnDividers(Graphics g) {
if (columnModelSegments == null || columnStartModelPositions == null)
return;
Point fromPoint = new Point();
Point toPoint = new Point();
for (int i = 0; i < columnModelSegments.length; i++) {
int[] colSegs = columnModelSegments[i];
int xPos = columnStartModelPositions[i].x;
int j = -1;
while (++j < colSegs.length) {
// Map from model to figure coordinates. First map to relative to figure, and then maps to absolute (through the figure bounds upper-left).
// mapModelToFigure(fromPoint.setLocation(xPos, colSegs[j]));
// mapModelToFigure(toPoint.setLocation(xPos, colSegs[++j]));
fromPoint.setLocation(xPos, colSegs[j]);
toPoint.setLocation(xPos, colSegs[++j]);
g.drawLine(fromPoint, toPoint);
}
}
}
/**
* Draw the row dividers based on the GridBagLayout's origin and the row widths.
*/
protected void drawRowDividers(Graphics g) {
if (rowModelSegments == null || rowStartModelPositions == null)
return;
Point fromPoint = new Point();
Point toPoint = new Point();
for (int i = 0; i < rowModelSegments.length; i++) {
int[] rowSegs = rowModelSegments[i];
int yPos = rowStartModelPositions[i].y;
int j = -1;
while (++j < rowSegs.length) {
// Map from model to figure coordinates. First map to relative to figure, and then maps to absolute (through the figure bounds upper-left).
// mapModelToFigure(fromPoint.setLocation(rowSegs[j], yPos));
// mapModelToFigure(toPoint.setLocation(rowSegs[++j], yPos));
fromPoint.setLocation(rowSegs[j], yPos);
toPoint.setLocation(rowSegs[++j], yPos);
g.drawLine(fromPoint, toPoint);
}
}
}
/**
* Get the cell location (i.e. the grid x/y) that the point (in model coordinates) is within.
*
* @param p
* point to look for what cell it is in. It is in model coordinates.
* @return the cell grid x/y as a point. '-1' for a grid means the incoming dimension was to the left/above the left-most/top-most col/row.
*
* @since 1.2.0
*/
public Point getCellLocation(Point p) {
return getCellLocation(p.x, p.y);
}
/**
* Get the cell bounds for the cell that the position is within.
*
* @param pos
* position in col,row.
* @return cell bounds in model coor of the cell that the pos is in. If outside model, it will have a default size. This point may be modified.
*
* @since 1.2.0
*/
public Rectangle getCellBounds(Point pos) {
if (rowModelPositions == null || columnModelPositions == null)
return new Rectangle(0, 0, GridLayoutEditPolicy.DEFAULT_CELL_WIDTH, GridLayoutEditPolicy.DEFAULT_CELL_HEIGHT);
int cellxpos, cellypos, cellwidth, cellheight;
if (pos.x < 0)
cellxpos = columnModelPositions[0] - GridLayoutEditPolicy.DEFAULT_CELL_WIDTH;
else
cellxpos = columnModelPositions[pos.x];
if (pos.x < columnModelPositions.length - 1)
cellwidth = columnModelPositions[pos.x + 1] - cellxpos;
else
cellwidth = GridLayoutEditPolicy.DEFAULT_CELL_WIDTH;
if (pos.y < 0)
cellypos = rowModelPositions[0] - GridLayoutEditPolicy.DEFAULT_CELL_HEIGHT;
else
cellypos = rowModelPositions[pos.y];
if (pos.y < rowModelPositions.length - 1)
cellheight = rowModelPositions[pos.y + 1] - cellypos;
else
cellheight = GridLayoutEditPolicy.DEFAULT_CELL_HEIGHT;
return new Rectangle(cellxpos, cellypos, cellwidth, cellheight);
}
/**
* Get the rectangle for the column left hand side (in model terms) for the column sent in.
*
* @param col
* the column to get the rect for.
* @return rect (0 width) for the left hand side of the column. This rect can be modified by caller. It will be in model coors.
*
* @since 1.2.0
*/
public Rectangle getColumnRectangle(int col) {
if (columnStartModelPositions != null) {
return new Rectangle(columnStartModelPositions[col], columnEndModelPositions[col]).resize(-1, -1); // 1.
}
return new Rectangle();
}
/**
* Get the rectangle for the row top hand side for the row sent in.
*
* @param row
* the row to get the row rect for.
* @return rect (0 width) for the top side of the row. It will be in model coors. It can be modified.
*
* @since 1.2.0
*/
public Rectangle getRowRectangle(int row) {
if (rowStartModelPositions != null) {
return new Rectangle(rowStartModelPositions[row], rowEndModelPositions[row]).resize(-1, -1);
}
return new Rectangle();
}
/**
* Get the cell location (i.e. the grid x/y) that the point (in model coordinates) is within.
*
* @param x
* x to look for what cell it is in. It is in model coordinates.
* @param y
* y to look for what cell it is in. It is in model coordinates.
* @return the cell grid x/y as a point. '-1' for a grid means the incoming dimension was to the left/above the left-most/top-most col/row.
*
*
* @since 1.2.0
*/
public Point getCellLocation(int x, int y) {
return getCellLocation(x, y, false, false);
}
/**
* Get the cell location (i.e. the grid x/y) that the point (in model coordinates) is within.
*
* @param x
* x to look for what cell it is in. It is in model coordinates.
* @param y
* y to look for what cell it is in. It is in model coordinates.
* @param includeEmptyColumns
* @param includeEmptyRows
* @return the cell grid x/y as a point. '-1' for a grid means the incoming dimension was to the left/above the left-most/top-most col/row.
*
* @since 1.2.0
*/
public Point getCellLocation(int x, int y, boolean includeEmptyColumns, boolean includeEmptyRows) {
if (rowModelPositions == null || columnModelPositions == null)
return new Point(0, 0);
int gridx = -1, gridy = -1;
boolean foundx = false, foundy = false;
for (int i = 0; i < columnModelPositions.length - 1; i++) {
int xpos = columnModelPositions[i];
if (x >= xpos && x < columnModelPositions[i + 1]) {
gridx = i;
if (includeEmptyColumns) {
/*
* Since column positions can be equal if there are columns that don't contain components, iterate back throught the columns positions to get the first one with this position.
*/
int j;
for (j = i; j >= 0 && columnModelPositions[i] == columnModelPositions[j]; j--)
// ;
gridx = j + 1;
}
foundx = true;
break;
}
}
for (int i = 0; i < rowModelPositions.length - 1; i++) {
int ypos = rowModelPositions[i];
if (y >= ypos && y < rowModelPositions[i + 1]) {
gridy = i;
if (includeEmptyRows) {
/*
* Since row positions can be equal if there are rows that don't contain components, iterate back throught the rows to get the first one with this position.
*/
int j;
for (j = i; j >= 0 && rowModelPositions[i] == rowModelPositions[j]; j--)
gridy = j + 1;
}
foundy = true;
break;
}
}
if (!foundx && x >= columnModelPositions[columnModelPositions.length - 1])
gridx = columnModelPositions.length - 1;
if (!foundy && y >= rowModelPositions[rowModelPositions.length - 1])
gridy = rowModelPositions.length - 1;
return new Point(gridx, gridy);
}
/**
* Get the grid figure rect for the specified cell dimensions. The cells dimensions are packed into a Rectangle according to the following rules:
*
* rect.x = column position rect.y = row position rect.width = horizontal span rect.height = vertical span
*
* @param cellsBounds
* The cell area to calculate
* @return the rect in model coor. for the grid representing these cells.
*
* @since 1.0.0
*/
public Rectangle getGridBroundsForCellBounds(Rectangle cellsBounds) {
Rectangle r = new Rectangle();
if (rowModelPositions != null && columnModelPositions != null && cellsBounds.y <= rowModelPositions.length - 1 && cellsBounds.x <= columnModelPositions.length - 1) {
r.x = columnModelPositions[cellsBounds.x];
r.y = rowModelPositions[cellsBounds.y];
if (cellsBounds.x + cellsBounds.width > columnModelPositions.length - 1) {
r.width = columnModelPositions[columnModelPositions.length - 1];
} else {
r.width = columnModelPositions[cellsBounds.x + cellsBounds.width];
}
r.width -= r.x;
if (cellsBounds.y + cellsBounds.height > rowModelPositions.length - 1) {
r.height = rowModelPositions[rowModelPositions.length - 1];
} else {
r.height = rowModelPositions[cellsBounds.y + cellsBounds.height];
}
r.height -= r.y;
}
return r;
}
/**
* Get the grid layout request type from the given position in model coor.
*
* @param pos
* position in model coor.
* @param helper
* helper to use.
* @return gridlayout request for the given position.
*
* @since 1.2.0
*/
public GridLayoutRequest getGridLayoutRequest(Point pos, GridLayoutPolicyHelper helper) {
Point cell = getCellLocation(pos);// get the control position(column,row)
GridLayoutRequest req = new GridLayoutRequest();
req.column = cell.x;
req.row = cell.y;
if (req.column == -1 || req.row == -1)
req.type = GridLayoutRequest.NO_ADD; // We are above or to the left, we can't add.
else if (columnModelPositions == null || req.column >= columnModelPositions.length - 1)
if (rowModelPositions == null || req.row >= rowModelPositions.length - 1)
req.type = GridLayoutRequest.ADD_ROW_COL;
else
req.type = GridLayoutRequest.ADD_COLUMN;
else if (req.row >= rowEndModelPositions.length - 1)
req.type = GridLayoutRequest.ADD_ROW;
else {
int colSensitive;
int nextCol = req.column + 1;
int colWidth = columnModelPositions[nextCol] - columnModelPositions[req.column];
if (colWidth <= 2 * ROW_COLUMN_SENSITIVITY) {
// We are inside a cell that is too small (the row/col sensitivities would override and we couldn't drop in it)
// Reduce col sensitivity to a minimum. These reductions will mean that the col sensitivities from
// the right side and from the left side will not overlap. If they overlapped it would be difficult
// to figure which side should get the insert.
if (colWidth <= 5)
colSensitive = 0; // No sensitivity. Must be right on.
else
colSensitive = 1; // Decrease to 1.
} else
colSensitive = ROW_COLUMN_SENSITIVITY;
if (pos.x - columnModelPositions[req.column] <= colSensitive) {
if (helper.isEmptyAtCell(cell) || helper.isFillerLabelAtCell(cell))
req.type = GridLayoutRequest.INSERT_COLUMN;
else {
// We are over a control. If we are over a spanned section of the control, then it must be
// changed to insert column in row back at the left side of the control.
Rectangle childDim = helper.getChildDimensions(cell);
// If empty (childDim == null) then insert col.
if (childDim != null && childDim.x < cell.x) {
req.type = GridLayoutRequest.INSERT_COLUMN_WITHIN_ROW;
req.column = childDim.x; // Move back to start of child.
} else
req.type = GridLayoutRequest.INSERT_COLUMN; // It's ok, we are at the left side of the child.
}
} else if (columnModelPositions[nextCol] - pos.x <= colSensitive) {
cell.x = req.column = nextCol; // Nearer to next column.
if (req.column < columnModelPositions.length - 1) {
if (helper.isEmptyAtCell(cell) || helper.isFillerLabelAtCell(cell))
req.type = GridLayoutRequest.INSERT_COLUMN;
else {
// We are over a control. If we are over a spanned section of the control, then it must be
// changed to insert column in row back at the left side of the control.
Rectangle childDim = helper.getChildDimensions(cell);
// If empty (childDim == null) then insert column.
if (childDim != null && childDim.x < cell.x) {
req.type = GridLayoutRequest.INSERT_COLUMN_WITHIN_ROW;
req.column = childDim.x; // Move back to start of child.
} else
req.type = GridLayoutRequest.INSERT_COLUMN; // It's ok, we are at the left side of the child.
}
} else
req.type = GridLayoutRequest.ADD_COLUMN;
} else {
int rowSensitive;
int nextRow = req.row + 1;
int rowHeight = rowModelPositions[nextRow] - rowModelPositions[req.row];
if (rowHeight <= 2 * ROW_COLUMN_SENSITIVITY) {
// We are inside a cell that is too small (the row/col sensitivities would override and we couldn't drop in it)
// Reduce row sensitivity to a minimum. These reductions will mean that the row sensitivities from
// the top side and from the bottom side will not overlap. If they overlapped it would be difficult
// to figure which side should get the insert.
if (rowHeight <= 5)
rowSensitive = 0; // No sensitivity. Must be right on.
else
rowSensitive = 2; // Decrease to 2.
} else
rowSensitive = ROW_COLUMN_SENSITIVITY;
;
if (pos.y - rowModelPositions[req.row] <= rowSensitive) {
if (helper.isEmptyAtCell(cell) || helper.isFillerLabelAtCell(cell))
req.type = GridLayoutRequest.INSERT_ROW;
else {
// We are over a control. If we are over a spanned section of the control, then it must be
// changed to no add. Can't insert row over a vertically spanned control.
Rectangle childDim = helper.getChildDimensions(cell);
// If empty (childDim == null) then insert row.
if (childDim != null && childDim.y < cell.y) {
req.type = GridLayoutRequest.INSERT_COLUMN_WITHIN_ROW;
req.column = childDim.x; // Move back to start of child.
} else
req.type = GridLayoutRequest.INSERT_ROW; // It's ok, we are at the top side of the child.
}
} else if (rowModelPositions[nextRow] - pos.y <= rowSensitive) {
cell.y = req.row = nextRow; // Nearer to next row.
req.type = req.row < rowModelPositions.length - 1 ? GridLayoutRequest.INSERT_ROW : GridLayoutRequest.ADD_ROW; // Add if next
// row is
// actually
// outside.
if (req.row < rowModelPositions.length - 1) {
// We are over a control. If we are over a spanned section of the control, then it must be
// changed to no add. Can't insert row over a vertically spanned control.
Rectangle childDim = helper.getChildDimensions(cell);
// If empty (childDim == null) then insert row.
if (childDim != null && childDim.y < cell.y) {
req.type = GridLayoutRequest.INSERT_COLUMN_WITHIN_ROW;
req.column = childDim.x; // Move back to start of child.
} else
req.type = GridLayoutRequest.INSERT_ROW; // It's ok, we are at the top side of the child.
} else
req.type = GridLayoutRequest.ADD_ROW;
} else {
// In the cell, see if replace filler, insert column in row, or replace empty.
if (helper.isEmptyAtCell(cell))
req.type = GridLayoutRequest.ADD_TO_EMPTY_CELL;
else if (helper.isFillerLabelAtCell(cell))
req.type = GridLayoutRequest.REPLACE_FILLER;
else {
Rectangle childDim = helper.getChildDimensions(cell);
req.type = GridLayoutRequest.INSERT_COLUMN_WITHIN_ROW;
if (childDim != null && childDim.x < cell.x)
req.column = childDim.x; // Move back to start of child.
}
}
}
}
return req;
}
}