aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-12-05 16:27:41 -0800
committerGerrit Code Review <noreply-gerritcodereview@google.com>2012-12-05 16:27:41 -0800
commitedbef6adcb0528e209bab1574f3e3c30106d92fc (patch)
tree2f68f9836d05d5c9d644d030d3e7cd63faf4bed4
parent4c98d876bb9160de6df30dd580b39bb1973eb945 (diff)
parent06757bc6d04cd72024e20ef7438273d8635b4b6d (diff)
downloadsdk-edbef6adcb0528e209bab1574f3e3c30106d92fc.zip
sdk-edbef6adcb0528e209bab1574f3e3c30106d92fc.tar.gz
sdk-edbef6adcb0528e209bab1574f3e3c30106d92fc.tar.bz2
Merge "Grid Layout tweaks"
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/GridLayoutRule.java65
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridDropHandler.java120
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java27
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridMatch.java1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridModel.java24
5 files changed, 204 insertions, 33 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/GridLayoutRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/GridLayoutRule.java
index a197e23..80a23c6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/GridLayoutRule.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/GridLayoutRule.java
@@ -28,6 +28,7 @@ import static com.android.SdkConstants.GRAVITY_VALUE_FILL;
import static com.android.SdkConstants.GRAVITY_VALUE_FILL_HORIZONTAL;
import static com.android.SdkConstants.GRAVITY_VALUE_FILL_VERTICAL;
import static com.android.SdkConstants.GRAVITY_VALUE_LEFT;
+import static com.android.SdkConstants.GRID_LAYOUT;
import static com.android.SdkConstants.VALUE_HORIZONTAL;
import static com.android.SdkConstants.VALUE_TRUE;
@@ -53,6 +54,7 @@ import com.android.ide.common.api.SegmentType;
import com.android.ide.common.layout.grid.GridDropHandler;
import com.android.ide.common.layout.grid.GridLayoutPainter;
import com.android.ide.common.layout.grid.GridModel;
+import com.android.ide.common.layout.grid.GridModel.ViewData;
import com.android.utils.Pair;
import java.net.URL;
@@ -143,7 +145,7 @@ public class GridLayoutRule extends BaseLayoutRule {
* Whether the grid is edited in "grid mode" where the operations are row/column based
* rather than free-form
*/
- public static boolean sGridMode = false;
+ public static boolean sGridMode = true;
/** Constructs a new {@link GridLayoutRule} */
public GridLayoutRule() {
@@ -228,6 +230,9 @@ public class GridLayoutRule extends BaseLayoutRule {
// Add and Remove Column actions only apply in Grid Mode
if (sGridMode) {
+ actions.add(RuleAction.createToggle(ACTION_SHOW_STRUCTURE, "Show Structure",
+ sShowStructure, actionCallback, ICON_SHOW_STRUCT, 147, false));
+
// Add Row and Add Column
actions.add(RuleAction.createSeparator(150));
actions.add(RuleAction.createAction(ACTION_ADD_COL, "Add Column", actionCallback,
@@ -366,7 +371,8 @@ public class GridLayoutRule extends BaseLayoutRule {
public String getNamespace(INode layout) {
String namespace = ANDROID_URI;
- if (!layout.getFqcn().equals(FQCN_GRID_LAYOUT)) {
+ String fqcn = layout.getFqcn();
+ if (!fqcn.equals(GRID_LAYOUT) && !fqcn.equals(FQCN_GRID_LAYOUT)) {
namespace = mRulesEngine.getAppNameSpace();
}
@@ -407,10 +413,12 @@ public class GridLayoutRule extends BaseLayoutRule {
boolean moved) {
super.onRemovingChildren(deleted, parent, moved);
- // Attempt to clean up spacer objects for any newly-empty rows or columns
- // as the result of this deletion
- GridModel grid = GridModel.get(mRulesEngine, parent, null);
- grid.onDeleted(deleted);
+ if (!sGridMode) {
+ // Attempt to clean up spacer objects for any newly-empty rows or columns
+ // as the result of this deletion
+ GridModel grid = GridModel.get(mRulesEngine, parent, null);
+ grid.onDeleted(deleted);
+ }
}
@Override
@@ -454,6 +462,35 @@ public class GridLayoutRule extends BaseLayoutRule {
Rect oldBounds, Rect newBounds, SegmentType horizontalEdge, SegmentType verticalEdge) {
if (resizingWidget(state)) {
+ if (state.fillWidth || state.fillHeight || state.wrapWidth || state.wrapHeight) {
+ GridModel grid = getGrid(state);
+ ViewData view = grid.getView(node);
+ if (view != null) {
+ String gravityString = grid.getGridAttribute(view.node, ATTR_LAYOUT_GRAVITY);
+ int gravity = GravityHelper.getGravity(gravityString, 0);
+ if (view.column > 0 && verticalEdge != null && state.fillWidth) {
+ state.fillWidth = false;
+ state.wrapWidth = true;
+ gravity &= ~GravityHelper.GRAVITY_HORIZ_MASK;
+ gravity |= GravityHelper.GRAVITY_FILL_HORIZ;
+ } else if (verticalEdge != null && state.wrapWidth) {
+ gravity &= ~GravityHelper.GRAVITY_HORIZ_MASK;
+ gravity |= GravityHelper.GRAVITY_LEFT;
+ }
+ if (view.row > 0 && horizontalEdge != null && state.fillHeight) {
+ state.fillHeight = false;
+ state.wrapHeight = true;
+ gravity &= ~GravityHelper.GRAVITY_VERT_MASK;
+ gravity |= GravityHelper.GRAVITY_FILL_VERT;
+ } else if (horizontalEdge != null && state.wrapHeight) {
+ gravity &= ~GravityHelper.GRAVITY_VERT_MASK;
+ gravity |= GravityHelper.GRAVITY_TOP;
+ }
+ gravityString = GravityHelper.getGravity(gravity);
+ grid.setGridAttribute(view.node, ATTR_LAYOUT_GRAVITY, gravityString);
+ // Fall through and set layout_width and/or layout_height to wrap_content
+ }
+ }
super.setNewSizeBounds(state, node, layout, oldBounds, newBounds, horizontalEdge,
verticalEdge);
} else {
@@ -463,6 +500,22 @@ public class GridLayoutRule extends BaseLayoutRule {
GridModel grid = getGrid(state);
grid.setColumnSpanAttribute(node, columnSpan);
grid.setRowSpanAttribute(node, rowSpan);
+
+ ViewData view = grid.getView(node);
+ if (view != null) {
+ String gravityString = grid.getGridAttribute(view.node, ATTR_LAYOUT_GRAVITY);
+ int gravity = GravityHelper.getGravity(gravityString, 0);
+ if (verticalEdge != null && columnSpan > 1) {
+ gravity &= ~GravityHelper.GRAVITY_HORIZ_MASK;
+ gravity |= GravityHelper.GRAVITY_FILL_HORIZ;
+ }
+ if (horizontalEdge != null && rowSpan > 1) {
+ gravity &= ~GravityHelper.GRAVITY_VERT_MASK;
+ gravity |= GravityHelper.GRAVITY_FILL_VERT;
+ }
+ gravityString = GravityHelper.getGravity(gravity);
+ grid.setGridAttribute(view.node, ATTR_LAYOUT_GRAVITY, gravityString);
+ }
}
}
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
index 8a6fdef..8bdb56b 100644
--- 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
@@ -15,17 +15,17 @@
*/
package com.android.ide.common.layout.grid;
-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.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;
@@ -46,6 +46,7 @@ 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
@@ -83,8 +84,10 @@ public class GridDropHandler {
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) {
- Rect dragBounds = feedback.dragBounds;
if (dragBounds != null) {
// Sometimes the items are centered under the mouse so
// offset by the top left corner distance
@@ -92,8 +95,6 @@ public class GridDropHandler {
y1 += dragBounds.y;
}
- int w = dragBounds != null ? dragBounds.w : 0;
- int h = dragBounds != null ? dragBounds.h : 0;
int x2 = x1 + w;
int y2 = y1 + h;
@@ -185,19 +186,72 @@ public class GridDropHandler {
int SLOP = 2;
int radius = mRule.getNewCellSize();
if (rightDistance < radius + SLOP) {
- column++;
+ column = Math.min(column + 1, mGrid.actualColumnCount);
leftDistance = rightDistance;
}
if (bottomDistance < radius + SLOP) {
- row++;
+ row = Math.min(row + 1, mGrid.actualRowCount);
topDistance = bottomDistance;
}
- boolean matchLeft = leftDistance < radius + SLOP;
- boolean matchTop = topDistance < radius + SLOP;
+ boolean createColumn = leftDistance < radius + SLOP;
+ boolean createRow = topDistance < radius + SLOP;
+ if (x1 >= bounds.x2()) {
+ createColumn = true;
+ }
+ if (y1 >= bounds.y2()) {
+ createRow = true;
+ }
- mColumnMatch = new GridMatch(SegmentType.LEFT, 0, x1, column, matchLeft, 0);
- mRowMatch = new GridMatch(SegmentType.TOP, 0, y1, row, matchTop, 0);
+ 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();
}
}
@@ -713,16 +767,46 @@ public class GridDropHandler {
String fqcn = element.getFqcn();
INode newChild = targetNode.appendChild(fqcn);
+ int column = mColumnMatch.cellIndex;
if (mColumnMatch.createCell) {
- mGrid.addColumn(mColumnMatch.cellIndex,
+ mGrid.addColumn(column,
newChild, UNDEFINED, false, UNDEFINED, UNDEFINED);
}
+ int row = mRowMatch.cellIndex;
if (mRowMatch.createCell) {
- mGrid.addRow(mRowMatch.cellIndex, newChild, UNDEFINED, false, UNDEFINED, UNDEFINED);
+ mGrid.addRow(row, newChild, UNDEFINED, false, UNDEFINED, UNDEFINED);
}
- mGrid.setGridAttribute(newChild, ATTR_LAYOUT_COLUMN, mColumnMatch.cellIndex);
- mGrid.setGridAttribute(newChild, ATTR_LAYOUT_ROW, mRowMatch.cellIndex);
+ 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;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java
index 9e7cfae..7e2d3a7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridLayoutPainter.java
@@ -282,10 +282,12 @@ public class GridLayoutPainter {
gc.drawRect(b.x + 2 * radius, b.y + 2 * radius,
b.x2() - 2 * radius, b.y2() - 2 * radius);
- int column = data.getColumnMatch().cellIndex;
- int row = data.getRowMatch().cellIndex;
- boolean createColumn = data.getColumnMatch().createCell;
- boolean createRow = data.getRowMatch().createCell;
+ GridMatch columnMatch = data.getColumnMatch();
+ GridMatch rowMatch = data.getRowMatch();
+ int column = columnMatch.cellIndex;
+ int row = rowMatch.cellIndex;
+ boolean createColumn = columnMatch.createCell;
+ boolean createRow = rowMatch.createCell;
Rect cellBounds = grid.getCellBounds(row, column, 1, 1);
@@ -312,7 +314,22 @@ public class GridLayoutPainter {
}
gc.useStyle(DrawingStyle.DROP_PREVIEW);
- mRule.drawElement(gc, first, offsetX, offsetY);
+
+ Rect bounds = first.getBounds();
+ int x = offsetX;
+ int y = offsetY;
+ if (columnMatch.type == SegmentType.RIGHT) {
+ x += cellBounds.w - bounds.w;
+ } else if (columnMatch.type == SegmentType.CENTER_HORIZONTAL) {
+ x += cellBounds.w / 2 - bounds.w / 2;
+ }
+ if (rowMatch.type == SegmentType.BOTTOM) {
+ y += cellBounds.h - bounds.h;
+ } else if (rowMatch.type == SegmentType.CENTER_VERTICAL) {
+ y += cellBounds.h / 2 - bounds.h / 2;
+ }
+
+ mRule.drawElement(gc, first, x, y);
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridMatch.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridMatch.java
index 186e7d0..9bee343 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridMatch.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridMatch.java
@@ -124,6 +124,7 @@ class GridMatch implements Comparable<GridMatch> {
}
return String.format("Align bottom at y=%1d", matchedLine - layout.getBounds().y);
case CENTER_VERTICAL:
+ return "Center vertically";
case UNKNOWN:
default:
return null;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridModel.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridModel.java
index fa9a11f..a453147 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridModel.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridModel.java
@@ -80,7 +80,7 @@ public class GridModel {
static final int UNDEFINED = Integer.MIN_VALUE;
/** The size of spacers in the dimension that they are not defining */
- private static final int SPACER_SIZE_DP = 1;
+ static final int SPACER_SIZE_DP = 1;
/** Attribute value used for {@link #SPACER_SIZE_DP} */
private static final String SPACER_SIZE = String.format(VALUE_N_DP, SPACER_SIZE_DP);
@@ -361,7 +361,8 @@ public class GridModel {
if (mNamespace == null) {
mNamespace = ANDROID_URI;
- if (!layout.getFqcn().equals(FQCN_GRID_LAYOUT)) {
+ String fqcn = layout.getFqcn();
+ if (!fqcn.equals(GRID_LAYOUT) && !fqcn.equals(FQCN_GRID_LAYOUT)) {
mNamespace = mRulesEngine.getAppNameSpace();
}
}
@@ -681,11 +682,26 @@ public class GridModel {
if (cellBounds != null) {
int[] xs = cellBounds.getFirst();
int[] ys = cellBounds.getSecond();
+ Rect layoutBounds = layout.getBounds();
+
+ // Handle "blank" grid layouts: insert a fake grid of CELL_COUNT^2 cells
+ // where the user can do initial placement
+ if (actualColumnCount <= 1 && actualRowCount <= 1 && mChildViews.isEmpty()) {
+ final int CELL_COUNT = 1;
+ xs = new int[CELL_COUNT + 1];
+ ys = new int[CELL_COUNT + 1];
+ int cellWidth = layoutBounds.w / CELL_COUNT;
+ int cellHeight = layoutBounds.h / CELL_COUNT;
+
+ for (int i = 0; i <= CELL_COUNT; i++) {
+ xs[i] = i * cellWidth;
+ ys[i] = i * cellHeight;
+ }
+ }
actualColumnCount = xs.length - 1;
actualRowCount = ys.length - 1;
- Rect layoutBounds = layout.getBounds();
int layoutBoundsX = layoutBounds.x;
int layoutBoundsY = layoutBounds.y;
mLeft = new int[xs.length];
@@ -1810,7 +1826,7 @@ public class GridModel {
* Data about a view in a table; this is not the same as a cell because multiple views
* can share a single cell, and a view can span many cells.
*/
- class ViewData {
+ public class ViewData {
public final INode node;
public final int index;
public int row;