aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2011-09-07 11:28:54 -0700
committerTor Norbye <tnorbye@google.com>2011-09-28 16:15:25 -0700
commit4cd282c7b21dc06c2d2d02748278f07c94282fc1 (patch)
tree02096910dedd4f271e87426d63548cb0b588415b /eclipse
parentfc0cd95e9802d56b35331cb337c04e6dc29d4eff (diff)
downloadsdk-4cd282c7b21dc06c2d2d02748278f07c94282fc1.zip
sdk-4cd282c7b21dc06c2d2d02748278f07c94282fc1.tar.gz
sdk-4cd282c7b21dc06c2d2d02748278f07c94282fc1.tar.bz2
Grid Layout and Convert to Grid Layout improvements
First, some improvements to Grid Layout handling: (1) When dropping a new widget, look up the sizing metadata and use it to determine what fill gravity to set. For example, a button will use gravity left, and a text field will use gravity fill_horizontal. (2) Don't warn about reflection problems when failing to find GridLayout layout data; this probably means the layout is being attempted opened in an unsupporting SDK. There's a fallback case to compute the data instead already. Second, improvements to the conversion to GridLayout handling: (1) It now looks at the layout_gravity values to see whether each row and column is flexible, and if there's no flexible column in each of the horizontal and vertical dimensions, it will insert a special <Space> element to absorb any available extra space. This avoids constraints warnings from GridLayout. (2) It treats layout_width or layout_height attributes of match_parent or fill_parent as the same as a fill gravity (and removes it) and uses this in the flexibility computation above. (3) It removes unsupported layout params for all children (earlier this would only remove unsupported layout params on the direct children of the layout, which isn't enough when a hierarchy is being flattened.) (4) It's smarter about computing implicit rows and columns, so it avoids writing out redundant layout_row and layout_column attributes in some cases. (5) It avoids throwing refactoring errors in cases where an attribute is removed twice (6) Fixes a bug where the root layout was included when computing the set of used x and y coordinates, which means you'd often end up with a blank row and column 0. (7) Various refactoring to make the code cleaner. (8) More unit tests and updates to existing unit tests to reflect the new behavior such as an absorbing spacer and removal of redundant attributes. Change-Id: Iee44c3ca749eefc107b83545669cc9d7f84615b1
Diffstat (limited to 'eclipse')
-rw-r--r--eclipse/dictionary.txt1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/GridLayoutRule.java68
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridDropHandler.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridModel.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeLayoutRefactoring.java58
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/GridLayoutConverter.java305
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RelativeLayoutConversionHelper.java42
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeLayoutRefactoringTest.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11-expected-insertSpacer.xml59
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11.info11
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11.xml92
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1a-expected-gridLayout1.xml18
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample2-expected-gridLayout2.xml15
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample5-expected-gridLayout5.xml3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample9-expected-convertToGrid.xml13
15 files changed, 611 insertions, 90 deletions
diff --git a/eclipse/dictionary.txt b/eclipse/dictionary.txt
index b9f3106..65a89b3 100644
--- a/eclipse/dictionary.txt
+++ b/eclipse/dictionary.txt
@@ -232,6 +232,7 @@ stateful
stateless
stderr
stdout
+stretchable
stretchiness
struct
styleable
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 0633aa7..baebfad 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
@@ -20,7 +20,12 @@ import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI;
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_GRAVITY;
import static com.android.ide.common.layout.LayoutConstants.ATTR_ORIENTATION;
import static com.android.ide.common.layout.LayoutConstants.FQCN_SPACE;
+import static com.android.ide.common.layout.LayoutConstants.GRAVITY_VALUE_FILL;
+import static com.android.ide.common.layout.LayoutConstants.GRAVITY_VALUE_FILL_HORIZONTAL;
+import static com.android.ide.common.layout.LayoutConstants.GRAVITY_VALUE_FILL_VERTICAL;
+import static com.android.ide.common.layout.LayoutConstants.GRAVITY_VALUE_LEFT;
import static com.android.ide.common.layout.LayoutConstants.VALUE_HORIZONTAL;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_TRUE;
import com.android.ide.common.api.DrawingStyle;
import com.android.ide.common.api.DropFeedback;
@@ -30,7 +35,10 @@ import com.android.ide.common.api.IGraphics;
import com.android.ide.common.api.IMenuCallback;
import com.android.ide.common.api.INode;
import com.android.ide.common.api.INodeHandler;
+import com.android.ide.common.api.IViewMetadata;
+import com.android.ide.common.api.IViewMetadata.FillPreference;
import com.android.ide.common.api.IViewRule;
+import com.android.ide.common.api.InsertType;
import com.android.ide.common.api.Point;
import com.android.ide.common.api.Rect;
import com.android.ide.common.api.RuleAction;
@@ -89,6 +97,10 @@ public class GridLayoutRule extends BaseLayoutRule {
*/
public static final double MAX_CELL_DIFFERENCE = 1.2;
+ /** Whether debugging diagnostics is available in the toolbar */
+ private static final boolean CAN_DEBUG =
+ VALUE_TRUE.equals(System.getenv("ADT_DEBUG_GRIDLAYOUT")); //$NON-NLS-1$
+
private static final String ACTION_ADD_ROW = "_addrow"; //$NON-NLS-1$
private static final String ACTION_REMOVE_ROW = "_removerow"; //$NON-NLS-1$
private static final String ACTION_ADD_COL = "_addcol"; //$NON-NLS-1$
@@ -219,8 +231,10 @@ public class GridLayoutRule extends BaseLayoutRule {
sShowStructure, actionCallback, ICON_SHOW_GRID, 200, false));
// Temporary: Diagnostics for GridLayout
- actions.add(RuleAction.createToggle(ACTION_DEBUG, "Debug",
- sDebugGridLayout, actionCallback, null, 210, false));
+ if (CAN_DEBUG) {
+ actions.add(RuleAction.createToggle(ACTION_DEBUG, "Debug",
+ sDebugGridLayout, actionCallback, null, 210, false));
+ }
}
/**
@@ -287,6 +301,56 @@ public class GridLayoutRule extends BaseLayoutRule {
}
@Override
+ public void onChildInserted(INode node, INode parent, InsertType insertType) {
+ if (insertType == InsertType.MOVE_WITHIN) {
+ // Don't adjust widths/heights/weights when just moving within a single layout
+ return;
+ }
+
+ // Attempt to set "fill" properties on newly added views such that for example
+ // a text field will stretch horizontally.
+ String fqcn = node.getFqcn();
+ IViewMetadata metadata = mRulesEngine.getMetadata(fqcn);
+ if (metadata == null) {
+ return;
+ }
+ FillPreference fill = metadata.getFillPreference();
+ String gravity = computeDefaultGravity(fill);
+ if (gravity != null) {
+ node.setAttribute(ANDROID_URI, ATTR_LAYOUT_GRAVITY, gravity);
+ }
+ }
+
+ /**
+ * Computes the default gravity to be used for a widget of the given fill
+ * preference when added to a grid layout
+ *
+ * @param fill the fill preference for the widget
+ * @return the gravity value, or null, to be set on the widget
+ */
+ public static String computeDefaultGravity(FillPreference fill) {
+ String horizontal = GRAVITY_VALUE_LEFT;
+ String vertical = null;
+ if (fill.fillHorizontally(true /*verticalContext*/)) {
+ horizontal = GRAVITY_VALUE_FILL_HORIZONTAL;
+ }
+ if (fill.fillVertically(true /*verticalContext*/)) {
+ vertical = GRAVITY_VALUE_FILL_VERTICAL;
+ }
+ String gravity;
+ if (horizontal == GRAVITY_VALUE_FILL_HORIZONTAL
+ && vertical == GRAVITY_VALUE_FILL_VERTICAL) {
+ gravity = GRAVITY_VALUE_FILL;
+ } else if (vertical != null) {
+ gravity = horizontal + '|' + vertical;
+ } else {
+ gravity = horizontal;
+ }
+
+ return gravity;
+ }
+
+ @Override
public void onRemovingChildren(List<INode> deleted, INode parent) {
super.onRemovingChildren(deleted, parent);
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 dba9ce7..9f8e0b1 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
@@ -679,6 +679,11 @@ public class GridDropHandler {
newChild.setAttribute(ANDROID_URI, ATTR_LAYOUT_ROW_SPAN, Integer.toString(rowSpan));
}
+ // Ensure that we don't store columnCount=0
+ if (mGrid.actualColumnCount == 0) {
+ mGrid.layout.setAttribute(ANDROID_URI, ATTR_COLUMN_COUNT, VALUE_1);
+ }
+
return newChild;
}
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 4924cc0..a54d467 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
@@ -44,7 +44,6 @@ import com.android.ide.common.api.IViewMetadata;
import com.android.ide.common.api.Margins;
import com.android.ide.common.api.Rect;
import com.android.ide.common.layout.GridLayoutRule;
-import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.util.Pair;
import java.io.PrintWriter;
@@ -697,10 +696,10 @@ public class GridModel {
int[] ys = (int[]) verticalLocations;
return Pair.of(xs, ys);
} catch (Throwable t) {
- AdtPlugin.log(t, null); // TODO: Add to API!
+ // Probably trying to show a GridLayout on a platform that does not support it.
+ // Return null to indicate that the grid bounds must be computed from view bounds.
+ return null;
}
-
- return null;
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeLayoutRefactoring.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeLayoutRefactoring.java
index d95efcf..d95bf2c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeLayoutRefactoring.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeLayoutRefactoring.java
@@ -40,6 +40,7 @@ import static com.android.ide.common.layout.LayoutConstants.VALUE_WRAP_CONTENT;
import static com.android.ide.eclipse.adt.AdtConstants.EXT_XML;
import com.android.annotations.VisibleForTesting;
+import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.formatting.XmlFormatStyle;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor;
@@ -53,6 +54,7 @@ import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ITreeSelection;
@@ -60,6 +62,7 @@ import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.TextFileChange;
+import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
@@ -276,7 +279,9 @@ public class ChangeLayoutRefactoring extends VisualRefactoring {
}
} else if (newType.equals(FQCN_GRID_LAYOUT)) {
convertAnyToGridLayout(rootEdit);
- removeUndefinedAttrs(rootEdit, layout);
+ // Layout attributes on children have already been removed as part of conversion
+ // during the flattening
+ removeUndefinedAttrs(rootEdit, layout, false /*removeLayoutAttrs*/);
} else if (oldType.equals(FQCN_RELATIVE_LAYOUT) && newType.equals(FQCN_LINEAR_LAYOUT)) {
convertRelativeToLinear(rootEdit);
removeUndefinedAttrs(rootEdit, layout);
@@ -497,29 +502,46 @@ public class ChangeLayoutRefactoring extends VisualRefactoring {
* children
*/
private void removeUndefinedAttrs(MultiTextEdit rootEdit, Element layout) {
+ removeUndefinedAttrs(rootEdit, layout, true /*removeLayoutAttrs*/);
+ }
+
+ private void removeUndefinedAttrs(MultiTextEdit rootEdit, Element layout,
+ boolean removeLayoutAttrs) {
ViewElementDescriptor descriptor = getElementDescriptor(mTypeFqcn);
if (descriptor == null) {
return;
}
- Set<String> defined = new HashSet<String>();
- AttributeDescriptor[] layoutAttributes = descriptor.getLayoutAttributes();
- for (AttributeDescriptor attribute : layoutAttributes) {
- defined.add(attribute.getXmlLocalName());
- }
+ if (removeLayoutAttrs) {
+ Set<String> defined = new HashSet<String>();
+ AttributeDescriptor[] layoutAttributes = descriptor.getLayoutAttributes();
+ for (AttributeDescriptor attribute : layoutAttributes) {
+ defined.add(attribute.getXmlLocalName());
+ }
- NodeList children = layout.getChildNodes();
- for (int i = 0, n = children.getLength(); i < n; i++) {
- Node node = children.item(i);
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- Element child = (Element) node;
+ NodeList children = layout.getChildNodes();
+ for (int i = 0, n = children.getLength(); i < n; i++) {
+ Node node = children.item(i);
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ Element child = (Element) node;
- List<Attr> attributes = findLayoutAttributes(child);
- for (Attr attribute : attributes) {
- String name = attribute.getLocalName();
- if (!defined.contains(name)) {
- // Remove it
- removeAttribute(rootEdit, child, attribute.getNamespaceURI(), name);
+ List<Attr> attributes = findLayoutAttributes(child);
+ for (Attr attribute : attributes) {
+ String name = attribute.getLocalName();
+ if (!defined.contains(name)) {
+ // Remove it
+ try {
+ removeAttribute(rootEdit, child, attribute.getNamespaceURI(), name);
+ } catch (MalformedTreeException mte) {
+ // Sometimes refactoring has modified attribute; not removing
+ // it is non-fatal so just warn instead of letting refactoring
+ // operation abort
+ AdtPlugin.log(IStatus.WARNING,
+ "Could not remove unsupported attribute %1$s; " + //$NON-NLS-1$
+ "already modified during refactoring?", //$NON-NLS-1$
+ attribute.getLocalName());
+ }
+ }
}
}
}
@@ -527,7 +549,7 @@ public class ChangeLayoutRefactoring extends VisualRefactoring {
// Also remove the unavailable attributes (not layout attributes) on the
// converted element
- defined = new HashSet<String>();
+ Set<String> defined = new HashSet<String>();
AttributeDescriptor[] attributes = descriptor.getAttributes();
for (AttributeDescriptor attribute : attributes) {
defined.add(attribute.getXmlLocalName());
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/GridLayoutConverter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/GridLayoutConverter.java
index e33a123..6dca1dd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/GridLayoutConverter.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/GridLayoutConverter.java
@@ -25,32 +25,48 @@ import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_ALIGN_RI
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_ALIGN_TOP;
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_COLUMN;
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_COLUMN_SPAN;
+import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_GRAVITY;
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_HEIGHT;
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_PREFIX;
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_ROW;
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_ROW_SPAN;
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_WIDTH;
import static com.android.ide.common.layout.LayoutConstants.ATTR_ORIENTATION;
+import static com.android.ide.common.layout.LayoutConstants.FQCN_GRID_LAYOUT;
+import static com.android.ide.common.layout.LayoutConstants.GRAVITY_VALUE_FILL;
+import static com.android.ide.common.layout.LayoutConstants.GRAVITY_VALUE_FILL_HORIZONTAL;
+import static com.android.ide.common.layout.LayoutConstants.GRAVITY_VALUE_FILL_VERTICAL;
import static com.android.ide.common.layout.LayoutConstants.ID_PREFIX;
import static com.android.ide.common.layout.LayoutConstants.LINEAR_LAYOUT;
import static com.android.ide.common.layout.LayoutConstants.NEW_ID_PREFIX;
import static com.android.ide.common.layout.LayoutConstants.RADIO_GROUP;
import static com.android.ide.common.layout.LayoutConstants.RELATIVE_LAYOUT;
+import static com.android.ide.common.layout.LayoutConstants.SPACE;
import static com.android.ide.common.layout.LayoutConstants.TABLE_LAYOUT;
import static com.android.ide.common.layout.LayoutConstants.TABLE_ROW;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_FILL_PARENT;
import static com.android.ide.common.layout.LayoutConstants.VALUE_HORIZONTAL;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_MATCH_PARENT;
import static com.android.ide.common.layout.LayoutConstants.VALUE_VERTICAL;
import static com.android.ide.common.layout.LayoutConstants.VALUE_WRAP_CONTENT;
+import com.android.ide.common.api.IViewMetadata.FillPreference;
import com.android.ide.common.layout.BaseLayoutRule;
+import com.android.ide.common.layout.GridLayoutRule;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
+import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
@@ -91,6 +107,10 @@ class GridLayoutConverter {
private final ChangeLayoutRefactoring mRefactoring;
private final CanvasViewInfo mRootView;
+ private List<View> mViews;
+ private String mNamespace;
+ private int mColumnCount;
+
/** Creates a new {@link GridLayoutConverter} */
GridLayoutConverter(ChangeLayoutRefactoring refactoring,
Element layout, boolean flatten, MultiTextEdit rootEdit, CanvasViewInfo rootView) {
@@ -115,12 +135,158 @@ class GridLayoutConverter {
}
// Study the layout and get information about how to place individual elements
- GridModel edgeList = new GridModel(layoutView);
- List<View> views = edgeList.getViews();
- deleteRemovedElements(edgeList.getDeletedElements());
+ GridModel gridModel = new GridModel(layoutView, mLayout, mFlatten);
+ mViews = gridModel.getViews();
+ mColumnCount = gridModel.computeColumnCount();
+
+ deleteRemovedElements(gridModel.getDeletedElements());
+ mNamespace = mRefactoring.getAndroidNamespacePrefix();
+
+ processGravities();
+
+ // Insert space views if necessary
+ insertStretchableSpans();
// Create/update relative layout constraints
- assignGridAttributes(views);
+ assignGridAttributes();
+
+ removeUndefinedAttrs();
+
+ if (mColumnCount > 0) {
+ mRefactoring.setAttribute(mRootEdit, mLayout, ANDROID_URI,
+ mNamespace, ATTR_COLUMN_COUNT, Integer.toString(mColumnCount));
+ }
+ }
+
+ private void insertStretchableSpans() {
+ // Look at the rows and columns and determine if we need to have a stretchable
+ // row and/or a stretchable column in the layout.
+ // In a GridLayout, a row or column is stretchable if it defines a gravity (regardless
+ // of what the gravity is -- in other words, a column is not just stretchable if it
+ // has gravity=fill but also if it has gravity=left). Furthermore, ALL the elements
+ // in the row/column have to be stretchable for the overall row/column to be
+ // considered stretchable.
+
+ // Map from row index to boolean for "is the row fixed/inflexible?"
+ Map<Integer, Boolean> rowFixed = new HashMap<Integer, Boolean>();
+ Map<Integer, Boolean> columnFixed = new HashMap<Integer, Boolean>();
+ for (View view : mViews) {
+ if (view.mElement == mLayout) {
+ continue;
+ }
+
+ int gravity = RelativeLayoutConversionHelper.getGravity(view.mGravity, 0);
+ if ((gravity & RelativeLayoutConversionHelper.GRAVITY_HORIZ_MASK) == 0) {
+ columnFixed.put(view.mCol, true);
+ } else if (!columnFixed.containsKey(view.mCol)) {
+ columnFixed.put(view.mCol, false);
+ }
+ if ((gravity & RelativeLayoutConversionHelper.GRAVITY_VERT_MASK) == 0) {
+ rowFixed.put(view.mRow, true);
+ } else if (!rowFixed.containsKey(view.mRow)) {
+ rowFixed.put(view.mRow, false);
+ }
+ }
+
+ boolean hasStretchableRow = false;
+ boolean hasStretchableColumn = false;
+ for (boolean fixed : rowFixed.values()) {
+ if (!fixed) {
+ hasStretchableRow = true;
+ }
+ }
+ for (boolean fixed : columnFixed.values()) {
+ if (!fixed) {
+ hasStretchableColumn = true;
+ }
+ }
+
+ if (!hasStretchableRow || !hasStretchableColumn) {
+ // Insert <Space> to hold stretchable space
+ // TODO: May also have to increment column count!
+ int offset = 0; // WHERE?
+
+ if (mLayout instanceof IndexedRegion) {
+ IndexedRegion region = (IndexedRegion) mLayout;
+ int end = region.getEndOffset();
+ // TODO: Look backwards for the "</"
+ // (and can it ever be <foo/>) ?
+ end -= (mLayout.getTagName().length() + 3); // 3: <, /, >
+ offset = end;
+ }
+
+ int row = rowFixed.size();
+ int column = columnFixed.size();
+ StringBuilder sb = new StringBuilder(64);
+ String tag = SPACE;
+ sb.append('<').append(tag).append(' ');
+ String gravity;
+ if (!hasStretchableRow && !hasStretchableColumn) {
+ gravity = GRAVITY_VALUE_FILL;
+ } else if (!hasStretchableRow) {
+ gravity = GRAVITY_VALUE_FILL_VERTICAL;
+ } else {
+ assert !hasStretchableColumn;
+ gravity = GRAVITY_VALUE_FILL_HORIZONTAL;
+ }
+
+ sb.append(mNamespace).append(':');
+ sb.append(ATTR_LAYOUT_GRAVITY).append('=').append('"').append(gravity);
+ sb.append('"').append(' ');
+
+ sb.append(mNamespace).append(':');
+ sb.append(ATTR_LAYOUT_ROW).append('=').append('"').append(Integer.toString(row));
+ sb.append('"').append(' ');
+
+ sb.append(mNamespace).append(':');
+ sb.append(ATTR_LAYOUT_COLUMN).append('=').append('"').append(Integer.toString(column));
+ sb.append('"').append('/').append('>');
+
+ String space = sb.toString();
+ InsertEdit replace = new InsertEdit(offset, space);
+ mRootEdit.addChild(replace);
+
+ mColumnCount++;
+ }
+ }
+
+ private void removeUndefinedAttrs() {
+ ViewElementDescriptor descriptor = mRefactoring.getElementDescriptor(FQCN_GRID_LAYOUT);
+ if (descriptor == null) {
+ return;
+ }
+
+ Set<String> defined = new HashSet<String>();
+ AttributeDescriptor[] layoutAttributes = descriptor.getLayoutAttributes();
+ for (AttributeDescriptor attribute : layoutAttributes) {
+ defined.add(attribute.getXmlLocalName());
+ }
+
+ for (View view : mViews) {
+ Element child = view.mElement;
+
+ List<Attr> attributes = mRefactoring.findLayoutAttributes(child);
+ for (Attr attribute : attributes) {
+ String name = attribute.getLocalName();
+ if (!defined.contains(name)) {
+ // Remove it
+ try {
+ mRefactoring.removeAttribute(mRootEdit, child, attribute.getNamespaceURI(),
+ name);
+ } catch (MalformedTreeException mte) {
+ // Sometimes refactoring has modified attribute; not
+ // removing
+ // it is non-fatal so just warn instead of letting
+ // refactoring
+ // operation abort
+ AdtPlugin.log(IStatus.WARNING,
+ "Could not remove unsupported attribute %1$s; " + //$NON-NLS-1$
+ "already modified during refactoring?", //$NON-NLS-1$
+ attribute.getLocalName());
+ }
+ }
+ }
+ }
}
/** Removes any elements targeted for deletion */
@@ -136,31 +302,23 @@ class GridLayoutConverter {
/**
* Creates refactoring edits which adds or updates the grid attributes
*/
- private void assignGridAttributes(List<View> views) {
- String namespace = mRefactoring.getAndroidNamespacePrefix();
-
+ private void assignGridAttributes() {
// We always convert to horizontal grid layouts for now
mRefactoring.setAttribute(mRootEdit, mLayout, ANDROID_URI,
- namespace, ATTR_ORIENTATION, VALUE_HORIZONTAL);
-
- int columnCount = computeColumnCount(views);
- if (columnCount > 0) {
- mRefactoring.setAttribute(mRootEdit, mLayout, ANDROID_URI,
- namespace, ATTR_COLUMN_COUNT, Integer.toString(columnCount));
- }
+ mNamespace, ATTR_ORIENTATION, VALUE_HORIZONTAL);
- assignCellAttributes(views, namespace, columnCount);
+ assignCellAttributes();
}
/**
* Assign cell attributes to the table, skipping those that will be implied
* by the grid model
*/
- private void assignCellAttributes(List<View> views, String namespace, int columnCount) {
+ private void assignCellAttributes() {
int implicitRow = 0;
int implicitColumn = 0;
int nextRow = 0;
- for (View view : views) {
+ for (View view : mViews) {
Element element = view.getElement();
if (element == mLayout) {
continue;
@@ -169,15 +327,18 @@ class GridLayoutConverter {
int row = view.getRow();
int column = view.getColumn();
- if (row != implicitRow) {
+ if (column != implicitColumn && (implicitColumn > 0 || implicitRow > 0)) {
mRefactoring.setAttribute(mRootEdit, element, ANDROID_URI,
- namespace, ATTR_LAYOUT_ROW, Integer.toString(row));
- implicitRow = row;
+ mNamespace, ATTR_LAYOUT_COLUMN, Integer.toString(column));
+ if (column < implicitColumn) {
+ implicitRow++;
+ }
+ implicitColumn = column;
}
- if (column != implicitColumn) {
+ if (row != implicitRow) {
mRefactoring.setAttribute(mRootEdit, element, ANDROID_URI,
- namespace, ATTR_LAYOUT_COLUMN, Integer.toString(column));
- implicitColumn = column;
+ mNamespace, ATTR_LAYOUT_ROW, Integer.toString(row));
+ implicitRow = row;
}
int rowSpan = view.getRowSpan();
@@ -186,11 +347,11 @@ class GridLayoutConverter {
if (rowSpan > 1) {
mRefactoring.setAttribute(mRootEdit, element, ANDROID_URI,
- namespace, ATTR_LAYOUT_ROW_SPAN, Integer.toString(rowSpan));
+ mNamespace, ATTR_LAYOUT_ROW_SPAN, Integer.toString(rowSpan));
}
if (columnSpan > 1) {
mRefactoring.setAttribute(mRootEdit, element, ANDROID_URI,
- namespace, ATTR_LAYOUT_COLUMN_SPAN,
+ mNamespace, ATTR_LAYOUT_COLUMN_SPAN,
Integer.toString(columnSpan));
}
nextRow = Math.max(nextRow, row + rowSpan);
@@ -212,7 +373,7 @@ class GridLayoutConverter {
}
implicitColumn += columnSpan;
- if (implicitColumn >= columnCount) {
+ if (implicitColumn >= mColumnCount) {
implicitColumn = 0;
assert nextRow > implicitRow;
implicitRow = nextRow;
@@ -220,23 +381,56 @@ class GridLayoutConverter {
}
}
- /** Compute column count */
- private int computeColumnCount(List<View> views) {
- int columnCount = 0;
- for (View view : views) {
- if (view.getElement() == mLayout) {
+ private void processGravities() {
+ for (View view : mViews) {
+ Element element = view.getElement();
+ if (element == mLayout) {
continue;
}
- int column = view.getColumn();
- int columnSpan = view.getColumnSpan();
- if (column + columnSpan > columnCount) {
- columnCount = column + columnSpan;
+ Attr width = element.getAttributeNodeNS(ANDROID_URI, ATTR_LAYOUT_WIDTH);
+ Attr height = element.getAttributeNodeNS(ANDROID_URI, ATTR_LAYOUT_HEIGHT);
+ String gravity = element.getAttributeNS(ANDROID_URI, ATTR_LAYOUT_GRAVITY);
+ String newGravity = null;
+ if (width != null && (VALUE_MATCH_PARENT.equals(width.getValue()) ||
+ VALUE_FILL_PARENT.equals(width.getValue()))) {
+ mRefactoring.removeAttribute(mRootEdit, width);
+ newGravity = gravity = GRAVITY_VALUE_FILL_HORIZONTAL;
+ }
+ if (height != null && (VALUE_MATCH_PARENT.equals(height.getValue()) ||
+ VALUE_FILL_PARENT.equals(height.getValue()))) {
+ mRefactoring.removeAttribute(mRootEdit, height);
+ if (newGravity == GRAVITY_VALUE_FILL_HORIZONTAL) {
+ newGravity = GRAVITY_VALUE_FILL;
+ } else {
+ newGravity = GRAVITY_VALUE_FILL_VERTICAL;
+ }
+ gravity = newGravity;
}
+
+ if (gravity == null || gravity.length() == 0) {
+ ElementDescriptor descriptor = view.mInfo.getUiViewNode().getDescriptor();
+ if (descriptor instanceof ViewElementDescriptor) {
+ ViewElementDescriptor viewDescriptor = (ViewElementDescriptor) descriptor;
+ String fqcn = viewDescriptor.getFullClassName();
+ FillPreference fill = ViewMetadataRepository.get().getFillPreference(fqcn);
+ gravity = GridLayoutRule.computeDefaultGravity(fill);
+ if (gravity != null) {
+ newGravity = gravity;
+ }
+ }
+ }
+
+ if (newGravity != null) {
+ mRefactoring.setAttribute(mRootEdit, element, ANDROID_URI,
+ mNamespace, ATTR_LAYOUT_GRAVITY, newGravity);
+ }
+
+ view.mGravity = newGravity != null ? newGravity : gravity;
}
- return columnCount;
}
+
/** Converts 0dip values in layout_width and layout_height to wrap_content instead */
private void convert0dipToWrapContent(Element child) {
// Must convert layout_height="0dip" to layout_height="wrap_content".
@@ -304,6 +498,7 @@ class GridLayoutConverter {
private int mX2;
private int mY2;
private CanvasViewInfo mInfo;
+ private String mGravity;
public View(CanvasViewInfo view, Element element) {
mInfo = view;
@@ -404,12 +599,17 @@ class GridLayoutConverter {
}
/** Grid model for the views found in the view hierarchy, partitioned into rows and columns */
- private class GridModel {
+ private static class GridModel {
private final List<View> mViews = new ArrayList<View>();
private final List<Element> mDelete = new ArrayList<Element>();
private final Map<Element, View> mElementToView = new HashMap<Element, View>();
+ private Element mLayout;
+ private boolean mFlatten;
+
+ GridModel(CanvasViewInfo view, Element layout, boolean flatten) {
+ mLayout = layout;
+ mFlatten = flatten;
- GridModel(CanvasViewInfo view) {
scan(view, true);
analyzeKnownLayouts();
initializeColumns();
@@ -437,13 +637,34 @@ class GridLayoutConverter {
}
/**
+ * Compute and return column count
+ *
+ * @return the column count
+ */
+ public int computeColumnCount() {
+ int columnCount = 0;
+ for (View view : mViews) {
+ if (view.getElement() == mLayout) {
+ continue;
+ }
+
+ int column = view.getColumn();
+ int columnSpan = view.getColumnSpan();
+ if (column + columnSpan > columnCount) {
+ columnCount = column + columnSpan;
+ }
+ }
+ return columnCount;
+ }
+
+ /**
* Initializes the column and columnSpan attributes of the views
*/
private void initializeColumns() {
// Now initialize table view row, column and spans
Map<Integer, List<View>> mColumnViews = new HashMap<Integer, List<View>>();
for (View view : mViews) {
- if (view == mLayout) {
+ if (view.mElement == mLayout) {
continue;
}
int x = view.getLeftEdge();
@@ -470,7 +691,7 @@ class GridLayoutConverter {
}
// Initialize column spans
for (View view : mViews) {
- if (view == mLayout) {
+ if (view.mElement == mLayout) {
continue;
}
int index = Collections.binarySearch(columnOffsets, view.getRightEdge());
@@ -494,7 +715,7 @@ class GridLayoutConverter {
private void initializeRows() {
Map<Integer, List<View>> mRowViews = new HashMap<Integer, List<View>>();
for (View view : mViews) {
- if (view == mLayout) {
+ if (view.mElement == mLayout) {
continue;
}
int y = view.getTopEdge();
@@ -522,7 +743,7 @@ class GridLayoutConverter {
// Initialize row spans
for (View view : mViews) {
- if (view == mLayout) {
+ if (view.mElement == mLayout) {
continue;
}
int index = Collections.binarySearch(rowOffsets, view.getBottomEdge());
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RelativeLayoutConversionHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RelativeLayoutConversionHelper.java
index dabbca8..4344cda 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RelativeLayoutConversionHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RelativeLayoutConversionHelper.java
@@ -334,23 +334,39 @@ class RelativeLayoutConversionHelper {
}
}
- private static final int GRAVITY_LEFT = 1 << 0;
- private static final int GRAVITY_RIGHT = 1<< 1;
- private static final int GRAVITY_CENTER_HORIZ = 1 << 2;
- private static final int GRAVITY_FILL_HORIZ = 1 << 3;
- private static final int GRAVITY_CENTER_VERT = 1 << 4;
- private static final int GRAVITY_FILL_VERT = 1 << 5;
- private static final int GRAVITY_TOP = 1 << 6;
- private static final int GRAVITY_BOTTOM = 1 << 7;
- private static final int GRAVITY_HORIZ_MASK = GRAVITY_CENTER_HORIZ | GRAVITY_FILL_HORIZ
+ public static final int GRAVITY_LEFT = 1 << 0;
+ public static final int GRAVITY_RIGHT = 1<< 1;
+ public static final int GRAVITY_CENTER_HORIZ = 1 << 2;
+ public static final int GRAVITY_FILL_HORIZ = 1 << 3;
+ public static final int GRAVITY_CENTER_VERT = 1 << 4;
+ public static final int GRAVITY_FILL_VERT = 1 << 5;
+ public static final int GRAVITY_TOP = 1 << 6;
+ public static final int GRAVITY_BOTTOM = 1 << 7;
+ public static final int GRAVITY_HORIZ_MASK = GRAVITY_CENTER_HORIZ | GRAVITY_FILL_HORIZ
| GRAVITY_LEFT | GRAVITY_RIGHT;
- private static final int GRAVITY_VERT_MASK = GRAVITY_CENTER_VERT | GRAVITY_FILL_VERT
+ public static final int GRAVITY_VERT_MASK = GRAVITY_CENTER_VERT | GRAVITY_FILL_VERT
| GRAVITY_TOP | GRAVITY_BOTTOM;
- /** Returns the gravity of the given element */
- private static int getGravity(Element element) {
- int gravity = GRAVITY_LEFT | GRAVITY_TOP;
+ /**
+ * Returns the gravity of the given element
+ *
+ * @param element the element to look up the gravity for
+ * @return a bit mask corresponding to the selected gravities
+ */
+ public static int getGravity(Element element) {
String gravityString = element.getAttributeNS(ANDROID_URI, ATTR_LAYOUT_GRAVITY);
+ return getGravity(gravityString, GRAVITY_LEFT | GRAVITY_TOP);
+ }
+
+ /**
+ * Returns the gravity bitmask for the given gravity string description
+ *
+ * @param gravityString the gravity string description
+ * @param defaultMask the default/initial bitmask to start with
+ * @return a bitmask corresponding to the gravity description
+ */
+ public static int getGravity(String gravityString, int defaultMask) {
+ int gravity = defaultMask;
if (gravityString != null && gravityString.length() > 0) {
String[] anchors = gravityString.split("\\|"); //$NON-NLS-1$
for (String anchor : anchors) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeLayoutRefactoringTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeLayoutRefactoringTest.java
index 5236dc2..bcbf461 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeLayoutRefactoringTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ChangeLayoutRefactoringTest.java
@@ -98,6 +98,10 @@ public class ChangeLayoutRefactoringTest extends RefactoringTest {
checkRefactoring(FQCN_LINEAR_LAYOUT, "sample10.xml", true, "android:orientation=vertical");
}
+ public void testInsertSpacer() throws Exception {
+ checkRefactoring(FQCN_GRID_LAYOUT, "sample11.xml", true);
+ }
+
private void checkRefactoring(String newLayoutType, String basename,
boolean flatten) throws Exception {
checkRefactoring(newLayoutType, basename, flatten, null);
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11-expected-insertSpacer.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11-expected-insertSpacer.xml
new file mode 100644
index 0000000..d10626a
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11-expected-insertSpacer.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2010 Google Inc.
+
+ Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+
+ 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.
+-->
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/home_root"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:columnCount="3"
+ android:orientation="horizontal" >
+
+ <Button
+ android:layout_gravity="fill_horizontal"
+ android:layout_weight="1" />
+
+ <Button
+ android:layout_gravity="fill_horizontal"
+ android:layout_weight="1" />
+
+ <Button
+ android:layout_column="0"
+ android:layout_gravity="fill_horizontal"
+ android:layout_weight="1"
+ android:gravity="center_horizontal" />
+
+ <Button
+ android:layout_gravity="fill_horizontal"
+ android:layout_weight="1"
+ android:gravity="center_horizontal" />
+
+ <Button
+ android:layout_column="0"
+ android:layout_gravity="fill_horizontal"
+ android:layout_weight="1"
+ android:gravity="center_horizontal" />
+
+ <Button
+ android:layout_gravity="fill_horizontal"
+ android:layout_weight="1"
+ android:gravity="center_horizontal" />
+
+ <Space
+ android:layout_column="2"
+ android:layout_gravity="fill_vertical"
+ android:layout_row="3" />
+
+</GridLayout> \ No newline at end of file
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11.info b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11.info
new file mode 100644
index 0000000..560e8a8
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11.info
@@ -0,0 +1,11 @@
+android.widget.LinearLayout [0,50,480,320] <LinearLayout>
+ android.widget.LinearLayout [0,0,480,270] <LinearLayout>
+ android.widget.LinearLayout [6,6,474,92] <LinearLayout>
+ android.widget.Button [0,19,234,67] <Button>
+ android.widget.Button [234,19,468,67] <Button>
+ android.widget.LinearLayout [6,92,474,178] <LinearLayout>
+ android.widget.Button [0,19,234,67] <Button>
+ android.widget.Button [234,19,468,67] <Button>
+ android.widget.LinearLayout [6,178,474,264] <LinearLayout>
+ android.widget.Button [0,19,234,67] <Button>
+ android.widget.Button [234,19,468,67] <Button>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11.xml
new file mode 100644
index 0000000..4df91a1
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample11.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2010 Google Inc.
+
+ Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+
+ 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/home_root"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:padding="6dip" >
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal" >
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1" />
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal" >
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:gravity="center_horizontal" />
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:gravity="center_horizontal" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal" >
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:gravity="center_horizontal" />
+
+ <Button
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:gravity="center_horizontal" />
+ </LinearLayout>
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1a-expected-gridLayout1.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1a-expected-gridLayout1.xml
index a5cbc35..72fe214 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1a-expected-gridLayout1.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample1a-expected-gridLayout1.xml
@@ -3,40 +3,45 @@
android:id="@+id/GridLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:columnCount="3"
+ android:columnCount="4"
android:orientation="horizontal" >
<Button
android:id="@+id/button1"
+ android:layout_gravity="left"
android:text="FirstButton" >
</Button>
<Button
android:id="@+id/button2"
android:layout_column="0"
- android:layout_row="1"
+ android:layout_gravity="left"
android:text="SecondButton" >
</Button>
<Button
android:id="@+id/button3"
+ android:layout_gravity="left"
android:text="ThirdButton" >
</Button>
<CheckBox
android:id="@+id/checkBox1"
+ android:layout_gravity="left"
android:text="CheckBox" >
</CheckBox>
<Button
android:id="@+id/button4"
- android:layout_width="match_parent"
+ android:layout_column="0"
android:layout_columnSpan="3"
+ android:layout_gravity="fill_horizontal"
android:text="FourthButton" >
</Button>
<Button
android:id="@+id/button5"
+ android:layout_column="0"
android:layout_gravity="right"
android:text="FifthButton" >
</Button>
@@ -44,8 +49,13 @@
<Button
android:id="@+id/button6"
android:layout_column="0"
- android:layout_row="4"
+ android:layout_gravity="left"
android:text="Button" >
</Button>
+ <Space
+ android:layout_column="3"
+ android:layout_gravity="fill_vertical"
+ android:layout_row="5" />
+
</GridLayout> \ No newline at end of file
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample2-expected-gridLayout2.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample2-expected-gridLayout2.xml
index 40031a6..8b90562 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample2-expected-gridLayout2.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample2-expected-gridLayout2.xml
@@ -3,12 +3,13 @@
android:id="@+id/GridLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:columnCount="5"
+ android:columnCount="6"
android:orientation="horizontal" >
<Button
android:id="@+id/button1"
android:layout_columnSpan="2"
+ android:layout_gravity="left"
android:text="Button" >
</Button>
@@ -17,13 +18,14 @@
android:layout_alignParentLeft="true"
android:layout_column="0"
android:layout_columnSpan="2"
- android:layout_row="1"
+ android:layout_gravity="left"
android:text="Button" >
</Button>
<Button
android:id="@+id/button3"
android:layout_below="@+id/button2"
+ android:layout_gravity="left"
android:layout_row="2"
android:layout_toRightOf="@+id/button2"
android:text="Button" >
@@ -32,6 +34,7 @@
<Button
android:id="@+id/button4"
android:layout_below="@+id/button3"
+ android:layout_gravity="left"
android:layout_row="3"
android:layout_toRightOf="@+id/button3"
android:text="Button" >
@@ -42,7 +45,7 @@
android:layout_below="@+id/button4"
android:layout_column="1"
android:layout_columnSpan="2"
- android:layout_row="4"
+ android:layout_gravity="left"
android:layout_toLeftOf="@+id/button4"
android:text="CheckBox" >
</CheckBox>
@@ -51,8 +54,14 @@
android:id="@+id/button5"
android:layout_alignParentRight="true"
android:layout_column="4"
+ android:layout_gravity="left"
android:layout_row="1"
android:text="Button" >
</Button>
+ <Space
+ android:layout_column="5"
+ android:layout_gravity="fill_vertical"
+ android:layout_row="5" />
+
</GridLayout> \ No newline at end of file
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample5-expected-gridLayout5.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample5-expected-gridLayout5.xml
index 09f8d36..dd9f18c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample5-expected-gridLayout5.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample5-expected-gridLayout5.xml
@@ -8,7 +8,6 @@
<Button
android:id="@+id/button1"
- android:layout_column="2"
android:layout_columnSpan="2"
android:layout_gravity="center_horizontal"
android:text="Button" >
@@ -16,9 +15,9 @@
<Button
android:id="@+id/button2"
- android:layout_column="2"
android:layout_columnSpan="2"
android:layout_gravity="center"
+ android:layout_row="1"
android:text="Button" >
</Button>
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample9-expected-convertToGrid.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample9-expected-convertToGrid.xml
index 15f1c3b..03ffac7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample9-expected-convertToGrid.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/sample9-expected-convertToGrid.xml
@@ -3,26 +3,35 @@
android:id="@+id/GridLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:columnCount="2"
+ android:columnCount="3"
android:orientation="horizontal" >
<Button
android:id="@+id/button1"
+ android:layout_gravity="left"
android:text="Button" />
<RadioButton
android:id="@+id/radioButton1"
android:layout_width="150dp"
android:layout_column="0"
- android:layout_row="1"
+ android:layout_gravity="left"
android:text="RadioButton" />
<RadioButton
android:id="@+id/radioButton2"
+ android:layout_gravity="left"
android:text="RadioButton" />
<CheckBox
android:id="@+id/checkBox1"
+ android:layout_column="0"
+ android:layout_gravity="left"
android:text="CheckBox" />
+ <Space
+ android:layout_column="2"
+ android:layout_gravity="fill_vertical"
+ android:layout_row="3" />
+
</GridLayout> \ No newline at end of file