aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-08-07 11:48:03 -0700
committerTor Norbye <tnorbye@google.com>2012-08-08 15:18:48 -0700
commit0cb8e647ef345f5c2a6b7eb08b517421131bca4e (patch)
tree0952bed29c8c937cb6a2e0a6339efbe234e3e9a7 /eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout
parent880f28a8a6f1abde140e5a201e5d38f62a8db1ae (diff)
downloadsdk-0cb8e647ef345f5c2a6b7eb08b517421131bca4e.zip
sdk-0cb8e647ef345f5c2a6b7eb08b517421131bca4e.tar.gz
sdk-0cb8e647ef345f5c2a6b7eb08b517421131bca4e.tar.bz2
Improvements to relative layout move and delete operations
This changeset improves the way the RelativeLayout editing support in the layout editor handles deletions and moves. First, during a move, if the move is simply within the same layout, then the layout constraints are left alone such that if you for example have A v B < C < D and you move B up to be next to A, you end up with A < B < C < D (It will however remove cycles if the move would result in them.) Second, it now handles deletion better where deleting a view will cause all references to any deleted views to be replaced by transitive constraints. For example, if you hve A < B < C < D and you delete B and C, you end up with A < D Change-Id: Icb9d3552e60aee20192f7941fe52be71ba52557f
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/TestNode.java47
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/relative/DeletionHandlerTest.java445
2 files changed, 491 insertions, 1 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/TestNode.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/TestNode.java
index b9176f6..372e329 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/TestNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/TestNode.java
@@ -36,8 +36,10 @@ import com.android.ide.eclipse.adt.internal.editors.formatting.XmlPrettyPrinter;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
import com.google.common.base.Splitter;
+import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
import java.io.IOException;
import java.io.StringWriter;
@@ -336,8 +338,24 @@ public class TestNode implements INode {
}
@Override
+ public @NonNull IAttribute[] getLiveAttributes() {
+ List<IAttribute> result = new ArrayList<IAttribute>();
+
+ NamedNodeMap attributes = mElement.getAttributes();
+ for (int i = 0, n = attributes.getLength(); i < n; i++) {
+ Attr attribute = (Attr) attributes.item(i);
+ result.add(new TestXmlAttribute(attribute));
+ }
+ return result.toArray(new IAttribute[result.size()]);
+ }
+
+ @Override
public boolean setAttribute(String uri, String localName, String value) {
- mElement.setAttributeNS(uri, localName, value);
+ if (value == null) {
+ mElement.removeAttributeNS(uri, localName);
+ } else {
+ mElement.setAttributeNS(uri, localName, value);
+ }
return super.setAttribute(uri, localName, value);
}
@@ -395,6 +413,33 @@ public class TestNode implements INode {
}
}
+ public static class TestXmlAttribute implements IAttribute {
+ private Attr mAttribute;
+
+ public TestXmlAttribute(Attr attribute) {
+ this.mAttribute = attribute;
+ }
+
+ @Override
+ public String getUri() {
+ return mAttribute.getNamespaceURI();
+ }
+
+ @Override
+ public String getName() {
+ String name = mAttribute.getLocalName();
+ if (name == null) {
+ name = mAttribute.getName();
+ }
+ return name;
+ }
+
+ @Override
+ public String getValue() {
+ return mAttribute.getValue();
+ }
+ }
+
// Recursively initialize this node with the bounds specified in the given hierarchy
// dump (from ViewHierarchy's DUMP_INFO flag
public void assignBounds(String bounds) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/relative/DeletionHandlerTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/relative/DeletionHandlerTest.java
new file mode 100644
index 0000000..f5ec1ba
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/relative/DeletionHandlerTest.java
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2012 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.relative;
+
+import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
+import static com.android.tools.lint.detector.api.LintConstants.ANDROID_URI;
+
+import com.android.ide.common.api.INode;
+import com.android.ide.common.layout.BaseViewRule;
+import com.android.ide.common.layout.TestNode;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class DeletionHandlerTest extends TestCase {
+ public void testSimple() {
+ String xml = "" +
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"match_parent\"\n" +
+ " tools:ignore=\"HardcodedText\" >\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignParentLeft=\"true\"\n" +
+ " android:text=\"A\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button2\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBaseline=\"@+id/button1\"\n" +
+ " android:layout_alignBottom=\"@+id/button1\"\n" +
+ " android:layout_toRightOf=\"@+id/button1\"\n" +
+ " android:text=\"B\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button3\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBottom=\"@+id/button2\"\n" +
+ " android:layout_toRightOf=\"@+id/button2\"\n" +
+ " android:text=\"C\" />\n" +
+ "\n" +
+ "</RelativeLayout>";
+ TestNode targetNode = TestNode.createFromXml(xml);
+ assertNotNull(targetNode);
+
+ TestNode button2 = TestNode.findById(targetNode, "@+id/button2");
+
+ INode layout = button2.getParent();
+ List<INode> deletedNodes = Collections.<INode>singletonList(button2);
+ List<INode> movedNodes = Collections.<INode>emptyList();
+ assertSame(layout, targetNode);
+ layout.removeChild(button2);
+
+ DeletionHandler handler = new DeletionHandler(deletedNodes, movedNodes, layout);
+ handler.updateConstraints();
+
+ String updated = TestNode.toXml(targetNode);
+ assertEquals(
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"match_parent\"\n" +
+ " tools:ignore=\"HardcodedText\">\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignParentLeft=\"true\"\n" +
+ " android:text=\"A\">\n" +
+ " </Button>\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button3\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBaseline=\"@+id/button1\"\n" +
+ " android:layout_alignBottom=\"@+id/button1\"\n" +
+ " android:layout_toRightOf=\"@+id/button1\"\n" +
+ " android:text=\"C\">\n" +
+ " </Button>\n" +
+ "\n" +
+ "</RelativeLayout>",
+ updated);
+ assertFalse(updated.contains(BaseViewRule.stripIdPrefix(button2.getStringAttr(ANDROID_URI,
+ ATTR_ID))));
+ }
+
+ public void testTransitive() {
+ String xml = "" +
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"match_parent\"\n" +
+ " tools:ignore=\"HardcodedText\" >\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignParentLeft=\"true\"\n" +
+ " android:layout_alignParentTop=\"true\"\n" +
+ " android:text=\"Above\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button2\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignParentLeft=\"true\"\n" +
+ " android:layout_below=\"@+id/button1\"\n" +
+ " android:text=\"A\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button3\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBaseline=\"@+id/button2\"\n" +
+ " android:layout_alignBottom=\"@+id/button2\"\n" +
+ " android:layout_toRightOf=\"@+id/button2\"\n" +
+ " android:text=\"B\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button4\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBottom=\"@+id/button3\"\n" +
+ " android:layout_toRightOf=\"@+id/button3\"\n" +
+ " android:text=\"C\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button5\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBaseline=\"@+id/button4\"\n" +
+ " android:layout_alignBottom=\"@+id/button4\"\n" +
+ " android:layout_toRightOf=\"@+id/button4\"\n" +
+ " android:text=\"D\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button6\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBottom=\"@+id/button5\"\n" +
+ " android:layout_toRightOf=\"@+id/button5\"\n" +
+ " android:text=\"E\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button7\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignLeft=\"@+id/button3\"\n" +
+ " android:layout_below=\"@+id/button3\"\n" +
+ " android:text=\"Button\" />\n" +
+ "\n" +
+ " <CheckBox\n" +
+ " android:id=\"@+id/checkBox1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBaseline=\"@+id/button7\"\n" +
+ " android:layout_alignBottom=\"@+id/button7\"\n" +
+ " android:layout_toRightOf=\"@+id/button7\"\n" +
+ " android:text=\"CheckBox\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button8\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_below=\"@+id/checkBox1\"\n" +
+ " android:layout_toRightOf=\"@+id/checkBox1\"\n" +
+ " android:text=\"Button\" />\n" +
+ "\n" +
+ "</RelativeLayout>";
+ TestNode targetNode = TestNode.createFromXml(xml);
+ assertNotNull(targetNode);
+ TestNode button7 = TestNode.findById(targetNode, "@+id/button7");
+ TestNode checkBox = TestNode.findById(targetNode, "@+id/checkBox1");
+
+ INode layout = button7.getParent();
+ List<INode> deletedNodes = Arrays.<INode>asList(button7, checkBox);
+ List<INode> movedNodes = Collections.<INode>emptyList();
+ assertSame(layout, targetNode);
+ layout.removeChild(button7);
+ layout.removeChild(checkBox);
+
+ DeletionHandler handler = new DeletionHandler(deletedNodes, movedNodes, layout);
+ handler.updateConstraints();
+
+ String updated = TestNode.toXml(targetNode);
+ assertEquals(
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"match_parent\"\n" +
+ " tools:ignore=\"HardcodedText\">\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignParentLeft=\"true\"\n" +
+ " android:layout_alignParentTop=\"true\"\n" +
+ " android:text=\"Above\">\n" +
+ " </Button>\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button2\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignParentLeft=\"true\"\n" +
+ " android:layout_below=\"@+id/button1\"\n" +
+ " android:text=\"A\">\n" +
+ " </Button>\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button3\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBaseline=\"@+id/button2\"\n" +
+ " android:layout_alignBottom=\"@+id/button2\"\n" +
+ " android:layout_toRightOf=\"@+id/button2\"\n" +
+ " android:text=\"B\">\n" +
+ " </Button>\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button4\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBottom=\"@+id/button3\"\n" +
+ " android:layout_toRightOf=\"@+id/button3\"\n" +
+ " android:text=\"C\">\n" +
+ " </Button>\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button5\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBaseline=\"@+id/button4\"\n" +
+ " android:layout_alignBottom=\"@+id/button4\"\n" +
+ " android:layout_toRightOf=\"@+id/button4\"\n" +
+ " android:text=\"D\">\n" +
+ " </Button>\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button6\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBottom=\"@+id/button5\"\n" +
+ " android:layout_toRightOf=\"@+id/button5\"\n" +
+ " android:text=\"E\">\n" +
+ " </Button>\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button8\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignLeft=\"@+id/button3\"\n" +
+ " android:layout_below=\"@+id/button3\"\n" +
+ " android:text=\"Button\">\n" +
+ " </Button>\n" +
+ "\n" +
+ "</RelativeLayout>",
+ updated);
+ assertFalse(updated.contains(BaseViewRule.stripIdPrefix(button7.getStringAttr(ANDROID_URI,
+ ATTR_ID))));
+ }
+
+ public void testCenter() {
+ String xml =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"match_parent\"\n" +
+ " tools:ignore=\"HardcodedText\" >\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_centerInParent=\"true\"\n" +
+ " android:text=\"Button\" />\n" +
+ "\n" +
+ " <CheckBox\n" +
+ " android:id=\"@+id/checkBox1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_below=\"@+id/button1\"\n" +
+ " android:layout_toRightOf=\"@+id/button1\"\n" +
+ " android:text=\"CheckBox\" />\n" +
+ "\n" +
+ "</RelativeLayout>";
+
+ TestNode targetNode = TestNode.createFromXml(xml);
+ assertNotNull(targetNode);
+ TestNode button1 = TestNode.findById(targetNode, "@+id/button1");
+
+ INode layout = button1.getParent();
+ List<INode> deletedNodes = Collections.<INode>singletonList(button1);
+ List<INode> movedNodes = Collections.<INode>emptyList();
+ assertSame(layout, targetNode);
+ layout.removeChild(button1);
+
+ DeletionHandler handler = new DeletionHandler(deletedNodes, movedNodes, layout);
+ handler.updateConstraints();
+
+ String updated = TestNode.toXml(targetNode);
+ assertEquals(
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"match_parent\"\n" +
+ " tools:ignore=\"HardcodedText\">\n" +
+ "\n" +
+ " <CheckBox\n" +
+ " android:id=\"@+id/checkBox1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_centerInParent=\"true\"\n" +
+ " android:text=\"CheckBox\">\n" +
+ " </CheckBox>\n" +
+ "\n" +
+ "</RelativeLayout>",
+ updated);
+ assertFalse(updated.contains(BaseViewRule.stripIdPrefix(button1.getStringAttr(ANDROID_URI,
+ ATTR_ID))));
+
+ }
+
+ public void testMove() {
+ String xml = "" +
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"match_parent\"\n" +
+ " tools:ignore=\"HardcodedText\" >\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignParentLeft=\"true\"\n" +
+ " android:text=\"A\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button2\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBaseline=\"@+id/button1\"\n" +
+ " android:layout_alignBottom=\"@+id/button1\"\n" +
+ " android:layout_toRightOf=\"@+id/button1\"\n" +
+ " android:text=\"B\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button3\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBottom=\"@+id/button2\"\n" +
+ " android:layout_toRightOf=\"@+id/button2\"\n" +
+ " android:text=\"C\" />\n" +
+ "\n" +
+ "</RelativeLayout>";
+ TestNode targetNode = TestNode.createFromXml(xml);
+ assertNotNull(targetNode);
+
+ TestNode button2 = TestNode.findById(targetNode, "@+id/button2");
+
+ INode layout = button2.getParent();
+ List<INode> deletedNodes = Collections.<INode>singletonList(button2);
+ List<INode> movedNodes = Collections.<INode>singletonList(button2);
+ assertSame(layout, targetNode);
+
+ DeletionHandler handler = new DeletionHandler(deletedNodes, movedNodes, layout);
+ handler.updateConstraints();
+
+ String updated = TestNode.toXml(targetNode);
+ assertEquals(
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"match_parent\"\n" +
+ " tools:ignore=\"HardcodedText\">\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignParentLeft=\"true\"\n" +
+ " android:text=\"A\">\n" +
+ " </Button>\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button2\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBaseline=\"@+id/button1\"\n" +
+ " android:layout_alignBottom=\"@+id/button1\"\n" +
+ " android:layout_toRightOf=\"@+id/button1\"\n" +
+ " android:text=\"B\">\n" +
+ " </Button>\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button3\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:layout_alignBottom=\"@+id/button2\"\n" +
+ " android:layout_toRightOf=\"@+id/button2\"\n" +
+ " android:text=\"C\">\n" +
+ " </Button>\n" +
+ "\n" +
+ "</RelativeLayout>",
+ updated);
+ assertTrue(updated.contains(BaseViewRule.stripIdPrefix(button2.getStringAttr(ANDROID_URI,
+ ATTR_ID))));
+ }
+}