aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridDropHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridDropHandler.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridDropHandler.java840
1 files changed, 0 insertions, 840 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridDropHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridDropHandler.java
deleted file mode 100644
index 8bdb56bfe..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridDropHandler.java
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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.android.ide.common.layout.grid;
-
-import static com.android.SdkConstants.ATTR_COLUMN_COUNT;
-import static com.android.SdkConstants.ATTR_LAYOUT_COLUMN;
-import static com.android.SdkConstants.ATTR_LAYOUT_COLUMN_SPAN;
-import static com.android.SdkConstants.ATTR_LAYOUT_GRAVITY;
-import static com.android.SdkConstants.ATTR_LAYOUT_ROW;
-import static com.android.SdkConstants.ATTR_LAYOUT_ROW_SPAN;
-import static com.android.ide.common.layout.GravityHelper.getGravity;
-import static com.android.ide.common.layout.GridLayoutRule.GRID_SIZE;
-import static com.android.ide.common.layout.GridLayoutRule.MARGIN_SIZE;
-import static com.android.ide.common.layout.GridLayoutRule.MAX_CELL_DIFFERENCE;
-import static com.android.ide.common.layout.GridLayoutRule.SHORT_GAP_DP;
-import static com.android.ide.common.layout.grid.GridModel.UNDEFINED;
-import static java.lang.Math.abs;
-
-import com.android.ide.common.api.DropFeedback;
-import com.android.ide.common.api.IDragElement;
-import com.android.ide.common.api.INode;
-import com.android.ide.common.api.IViewMetadata;
-import com.android.ide.common.api.Margins;
-import com.android.ide.common.api.Point;
-import com.android.ide.common.api.Rect;
-import com.android.ide.common.api.SegmentType;
-import com.android.ide.common.layout.BaseLayoutRule;
-import com.android.ide.common.layout.GravityHelper;
-import com.android.ide.common.layout.GridLayoutRule;
-import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * The {@link GridDropHandler} handles drag and drop operations into and within a
- * GridLayout, computing guidelines, handling drops to edit the grid model, and so on.
- */
-public class GridDropHandler {
- private final GridModel mGrid;
- private final GridLayoutRule mRule;
- private GridMatch mColumnMatch;
- private GridMatch mRowMatch;
-
- /**
- * Creates a new {@link GridDropHandler} for
- * @param gridLayoutRule the corresponding {@link GridLayoutRule}
- * @param layout the GridLayout node
- * @param view the view instance of the grid layout receiving the drop
- */
- public GridDropHandler(GridLayoutRule gridLayoutRule, INode layout, Object view) {
- mRule = gridLayoutRule;
- mGrid = GridModel.get(mRule.getRulesEngine(), layout, view);
- }
-
- /**
- * Computes the best horizontal and vertical matches for a drag to the given position.
- *
- * @param feedback a {@link DropFeedback} object containing drag state like the drag
- * bounds and the drag baseline
- * @param p the mouse position
- */
- public void computeMatches(DropFeedback feedback, Point p) {
- mRowMatch = mColumnMatch = null;
- feedback.tooltip = null;
-
- Rect bounds = mGrid.layout.getBounds();
- int x1 = p.x;
- int y1 = p.y;
-
- Rect dragBounds = feedback.dragBounds;
- int w = dragBounds != null ? dragBounds.w : 0;
- int h = dragBounds != null ? dragBounds.h : 0;
- if (!GridLayoutRule.sGridMode) {
- if (dragBounds != null) {
- // Sometimes the items are centered under the mouse so
- // offset by the top left corner distance
- x1 += dragBounds.x;
- y1 += dragBounds.y;
- }
-
- int x2 = x1 + w;
- int y2 = y1 + h;
-
- if (x2 < bounds.x || y2 < bounds.y || x1 > bounds.x2() || y1 > bounds.y2()) {
- return;
- }
-
- List<GridMatch> columnMatches = new ArrayList<GridMatch>();
- List<GridMatch> rowMatches = new ArrayList<GridMatch>();
- int max = BaseLayoutRule.getMaxMatchDistance();
-
- // Column matches:
- addLeftSideMatch(x1, columnMatches, max);
- addRightSideMatch(x2, columnMatches, max);
- addCenterColumnMatch(bounds, x1, y1, x2, y2, columnMatches, max);
-
- // Row matches:
- int row = (mGrid.getViewCount() == 0) ? 0 : mGrid.getClosestRow(y1);
- int rowY = mGrid.getRowY(row);
- addTopMatch(y1, rowMatches, max, row, rowY);
- addBaselineMatch(feedback.dragBaseline, y1, rowMatches, max, row, rowY);
- addBottomMatch(y2, rowMatches, max);
-
- // Look for gap-matches: Predefined spacing between widgets.
- // TODO: Make this use metadata for predefined spacing between
- // pairs of types of components. For example, buttons have certain
- // inserts in their 9-patch files (depending on the theme) that should
- // be considered and subtracted from the overall proposed distance!
- addColumnGapMatch(bounds, x1, x2, columnMatches, max);
- addRowGapMatch(bounds, y1, y2, rowMatches, max);
-
- // Fallback: Split existing cell. Also do snap-to-grid.
- if (GridLayoutRule.sSnapToGrid) {
- x1 = ((x1 - MARGIN_SIZE - bounds.x) / GRID_SIZE) * GRID_SIZE
- + MARGIN_SIZE + bounds.x;
- y1 = ((y1 - MARGIN_SIZE - bounds.y) / GRID_SIZE) * GRID_SIZE
- + MARGIN_SIZE + bounds.y;
- x2 = x1 + w;
- y2 = y1 + h;
- }
-
-
- if (columnMatches.size() == 0 && x1 >= bounds.x) {
- // Split the current cell since we have no matches
- // TODO: Decide whether it should be gravity left or right...
- columnMatches.add(new GridMatch(SegmentType.LEFT, 0, x1, mGrid.getColumn(x1),
- true /* createCell */, UNDEFINED));
- }
- if (rowMatches.size() == 0 && y1 >= bounds.y) {
- rowMatches.add(new GridMatch(SegmentType.TOP, 0, y1, mGrid.getRow(y1),
- true /* createCell */, UNDEFINED));
- }
-
- // Pick best matches
- Collections.sort(rowMatches);
- Collections.sort(columnMatches);
-
- mColumnMatch = null;
- mRowMatch = null;
- String columnDescription = null;
- String rowDescription = null;
- if (columnMatches.size() > 0) {
- mColumnMatch = columnMatches.get(0);
- columnDescription = mColumnMatch.getDisplayName(mGrid.layout);
- }
- if (rowMatches.size() > 0) {
- mRowMatch = rowMatches.get(0);
- rowDescription = mRowMatch.getDisplayName(mGrid.layout);
- }
-
- if (columnDescription != null && rowDescription != null) {
- feedback.tooltip = columnDescription + '\n' + rowDescription;
- }
-
- feedback.invalidTarget = mColumnMatch == null || mRowMatch == null;
- } else {
- // Find which cell we're inside.
-
- // TODO: Find out where within the cell we are, and offer to tweak the gravity
- // based on the position.
- int column = mGrid.getColumn(x1);
- int row = mGrid.getRow(y1);
-
- int leftDistance = mGrid.getColumnDistance(column, x1);
- int rightDistance = mGrid.getColumnDistance(column + 1, x1);
- int topDistance = mGrid.getRowDistance(row, y1);
- int bottomDistance = mGrid.getRowDistance(row + 1, y1);
-
- int SLOP = 2;
- int radius = mRule.getNewCellSize();
- if (rightDistance < radius + SLOP) {
- column = Math.min(column + 1, mGrid.actualColumnCount);
- leftDistance = rightDistance;
- }
- if (bottomDistance < radius + SLOP) {
- row = Math.min(row + 1, mGrid.actualRowCount);
- topDistance = bottomDistance;
- }
-
- boolean createColumn = leftDistance < radius + SLOP;
- boolean createRow = topDistance < radius + SLOP;
- if (x1 >= bounds.x2()) {
- createColumn = true;
- }
- if (y1 >= bounds.y2()) {
- createRow = true;
- }
-
- int cellWidth = leftDistance + rightDistance;
- int cellHeight = topDistance + bottomDistance;
- SegmentType horizontalType = SegmentType.LEFT;
- SegmentType verticalType = SegmentType.TOP;
- int minDistance = 10; // Don't center or right/bottom align in tiny cells
- if (!createColumn && leftDistance > minDistance
- && dragBounds != null && dragBounds.w < cellWidth - 10) {
- if (rightDistance < leftDistance) {
- horizontalType = SegmentType.RIGHT;
- }
-
- int centerDistance = Math.abs(cellWidth / 2 - leftDistance);
- if (centerDistance < leftDistance / 2 && centerDistance < rightDistance / 2) {
- horizontalType = SegmentType.CENTER_HORIZONTAL;
- }
- }
- if (!createRow && topDistance > minDistance
- && dragBounds != null && dragBounds.h < cellHeight - 10) {
- if (bottomDistance < topDistance) {
- verticalType = SegmentType.BOTTOM;
- }
- int centerDistance = Math.abs(cellHeight / 2 - topDistance);
- if (centerDistance < topDistance / 2 && centerDistance < bottomDistance / 2) {
- verticalType = SegmentType.CENTER_VERTICAL;
- }
- }
-
- mColumnMatch = new GridMatch(horizontalType, 0, x1, column, createColumn, 0);
- mRowMatch = new GridMatch(verticalType, 0, y1, row, createRow, 0);
-
- StringBuilder description = new StringBuilder(50);
- String rowString = Integer.toString(mColumnMatch.cellIndex + 1);
- String columnString = Integer.toString(mRowMatch.cellIndex + 1);
- if (mRowMatch.createCell && mRowMatch.cellIndex < mGrid.actualRowCount) {
- description.append(String.format("Shift row %1$d down", mRowMatch.cellIndex + 1));
- description.append('\n');
- }
- if (mColumnMatch.createCell && mColumnMatch.cellIndex < mGrid.actualColumnCount) {
- description.append(String.format("Shift column %1$d right",
- mColumnMatch.cellIndex + 1));
- description.append('\n');
- }
- description.append(String.format("Insert into cell (%1$s,%2$s)",
- rowString, columnString));
- description.append('\n');
- description.append(String.format("Align %1$s, %2$s",
- horizontalType.name().toLowerCase(Locale.US),
- verticalType.name().toLowerCase(Locale.US)));
- feedback.tooltip = description.toString();
- }
- }
-
- /**
- * Adds a match to align the left edge with some other edge.
- */
- private void addLeftSideMatch(int x1, List<GridMatch> columnMatches, int max) {
- int column = (mGrid.getViewCount() == 0) ? 0 : mGrid.getClosestColumn(x1);
- int columnX = mGrid.getColumnX(column);
- int distance = abs(columnX - x1);
- if (distance <= max) {
- columnMatches.add(new GridMatch(SegmentType.LEFT, distance, columnX, column,
- false, UNDEFINED));
- }
- }
-
- /**
- * Adds a match to align the right edge with some other edge.
- */
- private void addRightSideMatch(int x2, List<GridMatch> columnMatches, int max) {
- // TODO: Only match the right hand side if the drag bounds fit fully within the
- // cell! Ditto for match below.
- int columnRight = (mGrid.getViewCount() == 0) ? 0 : mGrid.getClosestColumn(x2);
- int rightDistance = mGrid.getColumnDistance(columnRight, x2);
- if (rightDistance < max) {
- int columnX = mGrid.getColumnX(columnRight);
- if (columnX > mGrid.layout.getBounds().x) {
- columnMatches.add(new GridMatch(SegmentType.RIGHT, rightDistance, columnX,
- columnRight, false, UNDEFINED));
- }
- }
- }
-
- /**
- * Adds a horizontal match with the center axis of the GridLayout
- */
- private void addCenterColumnMatch(Rect bounds, int x1, int y1, int x2, int y2,
- List<GridMatch> columnMatches, int max) {
- Collection<INode> intersectsRow = mGrid.getIntersectsRow(y1, y2);
- if (intersectsRow.size() == 0) {
- // Offer centering on this row since there isn't anything there
- int matchedLine = bounds.centerX();
- int distance = abs((x1 + x2) / 2 - matchedLine);
- if (distance <= 2 * max) {
- boolean createCell = false; // always just put in column 0
- columnMatches.add(new GridMatch(SegmentType.CENTER_HORIZONTAL, distance,
- matchedLine, 0 /* column */, createCell, UNDEFINED));
- }
- }
- }
-
- /**
- * Adds a match to align the top edge with some other edge.
- */
- private void addTopMatch(int y1, List<GridMatch> rowMatches, int max, int row, int rowY) {
- int distance = mGrid.getRowDistance(row, y1);
- if (distance <= max) {
- rowMatches.add(new GridMatch(SegmentType.TOP, distance, rowY, row, false,
- UNDEFINED));
- }
- }
-
- /**
- * Adds a match to align the bottom edge with some other edge.
- */
- private void addBottomMatch(int y2, List<GridMatch> rowMatches, int max) {
- int rowBottom = (mGrid.getViewCount() == 0) ? 0 : mGrid.getClosestRow(y2);
- int distance = mGrid.getRowDistance(rowBottom, y2);
- if (distance < max) {
- int rowY = mGrid.getRowY(rowBottom);
- if (rowY > mGrid.layout.getBounds().y) {
- rowMatches.add(new GridMatch(SegmentType.BOTTOM, distance, rowY,
- rowBottom, false, UNDEFINED));
- }
- }
- }
-
- /**
- * Adds a baseline match, if applicable.
- */
- private void addBaselineMatch(int dragBaseline, int y1, List<GridMatch> rowMatches, int max,
- int row, int rowY) {
- int dragBaselineY = y1 + dragBaseline;
- int rowBaseline = mGrid.getBaseline(row);
- if (rowBaseline != -1) {
- int rowBaselineY = rowY + rowBaseline;
- int distance = abs(dragBaselineY - rowBaselineY);
- if (distance < max) {
- rowMatches.add(new GridMatch(SegmentType.BASELINE, distance, rowBaselineY, row,
- false, UNDEFINED));
- }
- }
- }
-
- /**
- * Computes a horizontal "gap" match - a preferred distance from the nearest edge,
- * including margin edges
- */
- private void addColumnGapMatch(Rect bounds, int x1, int x2, List<GridMatch> columnMatches,
- int max) {
- if (x1 < bounds.x + MARGIN_SIZE + max) {
- int matchedLine = bounds.x + MARGIN_SIZE;
- int distance = abs(matchedLine - x1);
- if (distance <= max) {
- boolean createCell = mGrid.getColumnX(mGrid.getColumn(matchedLine)) != matchedLine;
- columnMatches.add(new GridMatch(SegmentType.LEFT, distance, matchedLine,
- 0, createCell, MARGIN_SIZE));
- }
- } else if (x2 > bounds.x2() - MARGIN_SIZE - max) {
- int matchedLine = bounds.x2() - MARGIN_SIZE;
- int distance = abs(matchedLine - x2);
- if (distance <= max) {
- // This does not yet work properly; we need to use columnWeights to achieve this
- //boolean createCell = mGrid.getColumnX(mGrid.getColumn(matchedLine)) != matchedLine;
- //columnMatches.add(new GridMatch(SegmentType.RIGHT, distance, matchedLine,
- // mGrid.actualColumnCount - 1, createCell, MARGIN_SIZE));
- }
- } else {
- int columnRight = mGrid.getColumn(x1 - SHORT_GAP_DP);
- int columnX = mGrid.getColumnMaxX(columnRight);
- int matchedLine = columnX + SHORT_GAP_DP;
- int distance = abs(matchedLine - x1);
- if (distance <= max) {
- boolean createCell = mGrid.getColumnX(mGrid.getColumn(matchedLine)) != matchedLine;
- columnMatches.add(new GridMatch(SegmentType.LEFT, distance, matchedLine,
- columnRight, createCell, SHORT_GAP_DP));
- }
-
- // Add a column directly adjacent (no gap)
- columnRight = mGrid.getColumn(x1);
- columnX = mGrid.getColumnMaxX(columnRight);
- matchedLine = columnX;
- distance = abs(matchedLine - x1);
-
- // Let's say you have this arrangement:
- // [button1][button2]
- // This is two columns, where the right hand side edge of column 1 is
- // flush with the left side edge of column 2, because in fact the width of
- // button1 is what defines the width of column 1, and that in turn is what
- // defines the left side position of column 2.
- //
- // In this case we don't want to consider inserting a new column at the
- // right hand side of button1 a better match than matching left on column 2.
- // Therefore, to ensure that this doesn't happen, we "penalize" right column
- // matches such that they don't get preferential treatment when the matching
- // line is on the left side of the column.
- distance += 2;
-
- if (distance <= max) {
- boolean createCell = mGrid.getColumnX(mGrid.getColumn(matchedLine)) != matchedLine;
- columnMatches.add(new GridMatch(SegmentType.LEFT, distance, matchedLine,
- columnRight, createCell, 0));
- }
- }
- }
-
- /**
- * Computes a vertical "gap" match - a preferred distance from the nearest edge,
- * including margin edges
- */
- private void addRowGapMatch(Rect bounds, int y1, int y2, List<GridMatch> rowMatches, int max) {
- if (y1 < bounds.y + MARGIN_SIZE + max) {
- int matchedLine = bounds.y + MARGIN_SIZE;
- int distance = abs(matchedLine - y1);
- if (distance <= max) {
- boolean createCell = mGrid.getRowY(mGrid.getRow(matchedLine)) != matchedLine;
- rowMatches.add(new GridMatch(SegmentType.TOP, distance, matchedLine,
- 0, createCell, MARGIN_SIZE));
- }
- } else if (y2 > bounds.y2() - MARGIN_SIZE - max) {
- int matchedLine = bounds.y2() - MARGIN_SIZE;
- int distance = abs(matchedLine - y2);
- if (distance <= max) {
- // This does not yet work properly; we need to use columnWeights to achieve this
- //boolean createCell = mGrid.getRowY(mGrid.getRow(matchedLine)) != matchedLine;
- //rowMatches.add(new GridMatch(SegmentType.BOTTOM, distance, matchedLine,
- // mGrid.actualRowCount - 1, createCell, MARGIN_SIZE));
- }
- } else {
- int rowBottom = mGrid.getRow(y1 - SHORT_GAP_DP);
- int rowY = mGrid.getRowMaxY(rowBottom);
- int matchedLine = rowY + SHORT_GAP_DP;
- int distance = abs(matchedLine - y1);
- if (distance <= max) {
- boolean createCell = mGrid.getRowY(mGrid.getRow(matchedLine)) != matchedLine;
- rowMatches.add(new GridMatch(SegmentType.TOP, distance, matchedLine,
- rowBottom, createCell, SHORT_GAP_DP));
- }
-
- // Add a row directly adjacent (no gap)
- rowBottom = mGrid.getRow(y1);
- rowY = mGrid.getRowMaxY(rowBottom);
- matchedLine = rowY;
- distance = abs(matchedLine - y1);
- distance += 2; // See explanation in addColumnGapMatch
- if (distance <= max) {
- boolean createCell = mGrid.getRowY(mGrid.getRow(matchedLine)) != matchedLine;
- rowMatches.add(new GridMatch(SegmentType.TOP, distance, matchedLine,
- rowBottom, createCell, 0));
- }
-
- }
- }
-
- /**
- * Called when a node is dropped in free-form mode. This will insert the dragged
- * element into the grid and returns the newly created node.
- *
- * @param targetNode the GridLayout node
- * @param element the dragged element
- * @return the newly created {@link INode}
- */
- public INode handleFreeFormDrop(INode targetNode, IDragElement element) {
- assert mRowMatch != null;
- assert mColumnMatch != null;
-
- String fqcn = element.getFqcn();
-
- INode newChild = null;
-
- Rect bounds = element.getBounds();
- int row = mRowMatch.cellIndex;
- int column = mColumnMatch.cellIndex;
-
- if (targetNode.getChildren().length == 0) {
- //
- // Set up the initial structure:
- //
- //
- // Fixed Fixed
- // Size Size
- // Column Expanding Column Column
- // +-----+-------------------------------+-----+
- // | | | |
- // | 0,0 | 0,1 | 0,2 | Fixed Size Row
- // | | | |
- // +-----+-------------------------------+-----+
- // | | | |
- // | | | |
- // | | | |
- // | 1,0 | 1,1 | 1,2 | Expanding Row
- // | | | |
- // | | | |
- // | | | |
- // +-----+-------------------------------+-----+
- // | | | |
- // | 2,0 | 2,1 | 2,2 | Fixed Size Row
- // | | | |
- // +-----+-------------------------------+-----+
- //
- // This is implemented in GridLayout by the following grid, where
- // SC1 has columnWeight=1 and SR1 has rowWeight=1.
- // (SC=Space for Column, SR=Space for Row)
- //
- // +------+-------------------------------+------+
- // | | | |
- // | SCR0 | SC1 | SC2 |
- // | | | |
- // +------+-------------------------------+------+
- // | | | |
- // | | | |
- // | | | |
- // | SR1 | | |
- // | | | |
- // | | | |
- // | | | |
- // +------+-------------------------------+------+
- // | | | |
- // | SR2 | | |
- // | | | |
- // +------+-------------------------------+------+
- //
- // Note that when we split columns and rows here, if splitting the expanding
- // row or column then the row or column weight should be moved to the right or
- // bottom half!
-
-
- //int columnX = mGrid.getColumnX(column);
- //int rowY = mGrid.getRowY(row);
-
- mGrid.setGridAttribute(targetNode, ATTR_COLUMN_COUNT, 2);
- //mGrid.setGridAttribute(targetNode, ATTR_COLUMN_COUNT, 3);
- //INode scr0 = addSpacer(targetNode, -1, 0, 0, 1, 1);
- //INode sc1 = addSpacer(targetNode, -1, 0, 1, 0, 0);
- //INode sc2 = addSpacer(targetNode, -1, 0, 2, 1, 0);
- //INode sr1 = addSpacer(targetNode, -1, 1, 0, 0, 0);
- //INode sr2 = addSpacer(targetNode, -1, 2, 0, 0, 1);
- //mGrid.setGridAttribute(sc1, ATTR_LAYOUT_GRAVITY, VALUE_FILL_HORIZONTAL);
- //mGrid.setGridAttribute(sr1, ATTR_LAYOUT_GRAVITY, VALUE_FILL_VERTICAL);
- //
- //mGrid.loadFromXml();
- //column = mGrid.getColumn(columnX);
- //row = mGrid.getRow(rowY);
- }
-
- int startX, endX;
- if (mColumnMatch.type == SegmentType.RIGHT) {
- endX = mColumnMatch.matchedLine - 1;
- startX = endX - bounds.w;
- column = mGrid.getColumn(startX);
- } else {
- startX = mColumnMatch.matchedLine; // TODO: What happens on type=RIGHT?
- endX = startX + bounds.w;
- }
- int startY, endY;
- if (mRowMatch.type == SegmentType.BOTTOM) {
- endY = mRowMatch.matchedLine - 1;
- startY = endY - bounds.h;
- row = mGrid.getRow(startY);
- } else if (mRowMatch.type == SegmentType.BASELINE) {
- // TODO: The rowSpan should always be 1 for baseline alignments, since
- // otherwise the alignment won't work!
- startY = endY = mRowMatch.matchedLine;
- } else {
- startY = mRowMatch.matchedLine;
- endY = startY + bounds.h;
- }
- int endColumn = mGrid.getColumn(endX);
- int endRow = mGrid.getRow(endY);
- int columnSpan = endColumn - column + 1;
- int rowSpan = endRow - row + 1;
-
- // Make sure my math was right:
- assert mRowMatch.type != SegmentType.BASELINE || rowSpan == 1 : rowSpan;
-
- // If the item almost fits into the row (at most N % bigger) then just enlarge
- // the row; don't add a rowspan since that will defeat baseline alignment etc
- if (!mRowMatch.createCell && bounds.h <= MAX_CELL_DIFFERENCE * mGrid.getRowHeight(
- mRowMatch.type == SegmentType.BOTTOM ? endRow : row, 1)) {
- if (mRowMatch.type == SegmentType.BOTTOM) {
- row += rowSpan - 1;
- }
- rowSpan = 1;
- }
- if (!mColumnMatch.createCell && bounds.w <= MAX_CELL_DIFFERENCE * mGrid.getColumnWidth(
- mColumnMatch.type == SegmentType.RIGHT ? endColumn : column, 1)) {
- if (mColumnMatch.type == SegmentType.RIGHT) {
- column += columnSpan - 1;
- }
- columnSpan = 1;
- }
-
- if (mColumnMatch.type == SegmentType.CENTER_HORIZONTAL) {
- column = 0;
- columnSpan = mGrid.actualColumnCount;
- }
-
- // Temporary: Ensure we don't get in trouble with implicit positions
- mGrid.applyPositionAttributes();
-
- // Split cells to make a new column
- if (mColumnMatch.createCell) {
- int columnWidthPx = mGrid.getColumnDistance(column, mColumnMatch.matchedLine);
- //assert columnWidthPx == columnMatch.distance; // TBD? IF so simplify
- int columnWidthDp = mRule.getRulesEngine().pxToDp(columnWidthPx);
-
- int maxX = mGrid.getColumnMaxX(column);
- boolean insertMarginColumn = false;
- if (mColumnMatch.margin == 0) {
- columnWidthDp = 0;
- } else if (mColumnMatch.margin != UNDEFINED) {
- int distance = abs(mColumnMatch.matchedLine - (maxX + mColumnMatch.margin));
- insertMarginColumn = column > 0 && distance < 2;
- if (insertMarginColumn) {
- int margin = mColumnMatch.margin;
- if (ViewMetadataRepository.INSETS_SUPPORTED) {
- IViewMetadata metadata = mRule.getRulesEngine().getMetadata(fqcn);
- if (metadata != null) {
- Margins insets = metadata.getInsets();
- if (insets != null) {
- // TODO:
- // Consider left or right side attachment
- // TODO: Also consider inset of element on cell to the left
- margin -= insets.left;
- }
- }
- }
-
- columnWidthDp = mRule.getRulesEngine().pxToDp(margin);
- }
- }
-
- column++;
- mGrid.splitColumn(column, insertMarginColumn, columnWidthDp, mColumnMatch.matchedLine);
- if (insertMarginColumn) {
- column++;
- }
- }
-
- // Split cells to make a new row
- if (mRowMatch.createCell) {
- int rowHeightPx = mGrid.getRowDistance(row, mRowMatch.matchedLine);
- //assert rowHeightPx == rowMatch.distance; // TBD? If so simplify
- int rowHeightDp = mRule.getRulesEngine().pxToDp(rowHeightPx);
-
- int maxY = mGrid.getRowMaxY(row);
- boolean insertMarginRow = false;
- if (mRowMatch.margin == 0) {
- rowHeightDp = 0;
- } else if (mRowMatch.margin != UNDEFINED) {
- int distance = abs(mRowMatch.matchedLine - (maxY + mRowMatch.margin));
- insertMarginRow = row > 0 && distance < 2;
- if (insertMarginRow) {
- int margin = mRowMatch.margin;
- IViewMetadata metadata = mRule.getRulesEngine().getMetadata(element.getFqcn());
- if (metadata != null) {
- Margins insets = metadata.getInsets();
- if (insets != null) {
- // TODO:
- // Consider left or right side attachment
- // TODO: Also consider inset of element on cell to the left
- margin -= insets.top;
- }
- }
-
- rowHeightDp = mRule.getRulesEngine().pxToDp(margin);
- }
- }
-
- row++;
- mGrid.splitRow(row, insertMarginRow, rowHeightDp, mRowMatch.matchedLine);
- if (insertMarginRow) {
- row++;
- }
- }
-
- // Figure out where to insert the new child
-
- int index = mGrid.getInsertIndex(row, column);
- if (index == -1) {
- // Couldn't find a later place to insert
- newChild = targetNode.appendChild(fqcn);
- } else {
- GridModel.ViewData next = mGrid.getView(index);
-
- newChild = targetNode.insertChildAt(fqcn, index);
-
- // Must also apply positions to the following child to ensure
- // that the new child doesn't affect the implicit numbering!
- // TODO: We can later check whether the implied number is equal to
- // what it already is such that we don't need this
- next.applyPositionAttributes();
- }
-
- // Set the cell position (gravity) of the new widget
- int gravity = 0;
- if (mColumnMatch.type == SegmentType.RIGHT) {
- gravity |= GravityHelper.GRAVITY_RIGHT;
- } else if (mColumnMatch.type == SegmentType.CENTER_HORIZONTAL) {
- gravity |= GravityHelper.GRAVITY_CENTER_HORIZ;
- }
- mGrid.setGridAttribute(newChild, ATTR_LAYOUT_COLUMN, column);
- if (mRowMatch.type == SegmentType.BASELINE) {
- // There *is* no baseline gravity constant, instead, leave the
- // vertical gravity unspecified and GridLayout will treat it as
- // baseline alignment
- //gravity |= GravityHelper.GRAVITY_BASELINE;
- } else if (mRowMatch.type == SegmentType.BOTTOM) {
- gravity |= GravityHelper.GRAVITY_BOTTOM;
- } else if (mRowMatch.type == SegmentType.CENTER_VERTICAL) {
- gravity |= GravityHelper.GRAVITY_CENTER_VERT;
- }
- // Ensure that we have at least one horizontal and vertical constraint, otherwise
- // the new item will be fixed. As an example, if we have a single button in the
- // table which we inserted *without* a gravity, and we then insert a button
- // above it with a vertical gravity, then only the top column would be considered
- // stretchable, and it will fill all available vertical space and the previous
- // button will jump to the bottom.
- if (!GravityHelper.isConstrainedHorizontally(gravity)) {
- gravity |= GravityHelper.GRAVITY_LEFT;
- }
- /* This causes problems: Try placing two buttons vertically from the top of the layout.
- We need to solve the free column/free row problem first.
- if (!GravityHelper.isConstrainedVertically(gravity)
- // There is no baseline constant, so we have to leave it unconstrained instead
- && mRowMatch.type != SegmentType.BASELINE
- // You also can't baseline align one element with another that has vertical
- // alignment top or bottom, so when we first "freely" place views (e.g.
- // at a particular y location), also place it freely (no constraint).
- && !mRowMatch.createCell) {
- gravity |= GravityHelper.GRAVITY_TOP;
- }
- */
- mGrid.setGridAttribute(newChild, ATTR_LAYOUT_GRAVITY, getGravity(gravity));
-
- mGrid.setGridAttribute(newChild, ATTR_LAYOUT_ROW, row);
-
- // Apply spans to ensure that the widget can fit without pushing columns
- if (columnSpan > 1) {
- mGrid.setGridAttribute(newChild, ATTR_LAYOUT_COLUMN_SPAN, columnSpan);
- }
- if (rowSpan > 1) {
- mGrid.setGridAttribute(newChild, ATTR_LAYOUT_ROW_SPAN, rowSpan);
- }
-
- // Ensure that we don't store columnCount=0
- if (mGrid.actualColumnCount == 0) {
- mGrid.setGridAttribute(mGrid.layout, ATTR_COLUMN_COUNT, Math.max(1, column + 1));
- }
-
- return newChild;
- }
-
- /**
- * Called when a drop is completed and we're in grid-editing mode. This will insert
- * the dragged element into the target cell.
- *
- * @param targetNode the GridLayout node
- * @param element the dragged element
- * @return the newly created node
- */
- public INode handleGridModeDrop(INode targetNode, IDragElement element) {
- String fqcn = element.getFqcn();
- INode newChild = targetNode.appendChild(fqcn);
-
- int column = mColumnMatch.cellIndex;
- if (mColumnMatch.createCell) {
- mGrid.addColumn(column,
- newChild, UNDEFINED, false, UNDEFINED, UNDEFINED);
- }
- int row = mRowMatch.cellIndex;
- if (mRowMatch.createCell) {
- mGrid.addRow(row, newChild, UNDEFINED, false, UNDEFINED, UNDEFINED);
- }
-
- mGrid.setGridAttribute(newChild, ATTR_LAYOUT_COLUMN, column);
- mGrid.setGridAttribute(newChild, ATTR_LAYOUT_ROW, row);
-
- int gravity = 0;
- if (mColumnMatch.type == SegmentType.RIGHT) {
- gravity |= GravityHelper.GRAVITY_RIGHT;
- } else if (mColumnMatch.type == SegmentType.CENTER_HORIZONTAL) {
- gravity |= GravityHelper.GRAVITY_CENTER_HORIZ;
- }
- if (mRowMatch.type == SegmentType.BASELINE) {
- // There *is* no baseline gravity constant, instead, leave the
- // vertical gravity unspecified and GridLayout will treat it as
- // baseline alignment
- //gravity |= GravityHelper.GRAVITY_BASELINE;
- } else if (mRowMatch.type == SegmentType.BOTTOM) {
- gravity |= GravityHelper.GRAVITY_BOTTOM;
- } else if (mRowMatch.type == SegmentType.CENTER_VERTICAL) {
- gravity |= GravityHelper.GRAVITY_CENTER_VERT;
- }
- if (!GravityHelper.isConstrainedHorizontally(gravity)) {
- gravity |= GravityHelper.GRAVITY_LEFT;
- }
- if (!GravityHelper.isConstrainedVertically(gravity)) {
- gravity |= GravityHelper.GRAVITY_TOP;
- }
- mGrid.setGridAttribute(newChild, ATTR_LAYOUT_GRAVITY, getGravity(gravity));
-
- if (mGrid.declaredColumnCount == UNDEFINED || mGrid.declaredColumnCount < column + 1) {
- mGrid.setGridAttribute(mGrid.layout, ATTR_COLUMN_COUNT, column + 1);
- }
-
- return newChild;
- }
-
- /**
- * Returns the best horizontal match
- *
- * @return the best horizontal match, or null if there is no match
- */
- public GridMatch getColumnMatch() {
- return mColumnMatch;
- }
-
- /**
- * Returns the best vertical match
- *
- * @return the best vertical match, or null if there is no match
- */
- public GridMatch getRowMatch() {
- return mRowMatch;
- }
-
- /**
- * Returns the grid used by the drop handler
- *
- * @return the grid used by the drop handler, never null
- */
- public GridModel getGrid() {
- return mGrid;
- }
-}