aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfoTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfoTest.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfoTest.java797
1 files changed, 797 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfoTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfoTest.java
new file mode 100644
index 000000000..5996f01c0
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfoTest.java
@@ -0,0 +1,797 @@
+/*
+ * Copyright (C) 2010 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.eclipse.adt.internal.editors.layout.gle2;
+
+import com.android.ide.common.rendering.api.Capability;
+import com.android.ide.common.rendering.api.DataBindingItem;
+import com.android.ide.common.rendering.api.MergeCookie;
+import com.android.ide.common.rendering.api.ViewInfo;
+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.uimodel.UiViewElementNode;
+import com.android.utils.Pair;
+
+import org.eclipse.swt.graphics.Rectangle;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class CanvasViewInfoTest extends TestCase {
+
+ public static ViewElementDescriptor createDesc(String name, String fqn, boolean hasChildren) {
+ if (hasChildren) {
+ return new ViewElementDescriptor(name, name, fqn, "", "", new AttributeDescriptor[0],
+ new AttributeDescriptor[0], new ElementDescriptor[1], false);
+ } else {
+ return new ViewElementDescriptor(name, fqn);
+ }
+ }
+
+ public static UiViewElementNode createNode(UiViewElementNode parent, String fqn,
+ boolean hasChildren) {
+ String name = fqn.substring(fqn.lastIndexOf('.') + 1);
+ ViewElementDescriptor descriptor = createDesc(name, fqn, hasChildren);
+ if (parent == null) {
+ // All node hierarchies should be wrapped inside a document node at the root
+ parent = new UiViewElementNode(createDesc("doc", "doc", true));
+ }
+ return (UiViewElementNode) parent.appendNewUiChild(descriptor);
+ }
+
+ public static UiViewElementNode createNode(String fqn, boolean hasChildren) {
+ return createNode(null, fqn, hasChildren);
+ }
+
+ public void testNormalCreate() throws Exception {
+ normal(true);
+ }
+
+ public void testNormalCreateLayoutLib5() throws Exception {
+ normal(false);
+ }
+
+ private void normal(boolean layoutlib5) {
+
+ // Normal view hierarchy, no null keys anywhere
+
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("LinearLayout", rootNode, 10, 10, 100, 100);
+ UiViewElementNode child1Node = createNode(rootNode, "android.widget.Button", false);
+ ViewInfo child1 = new ViewInfo("Button", child1Node, 0, 0, 50, 20);
+ UiViewElementNode child2Node = createNode(rootNode, "android.widget.Button", false);
+ ViewInfo child2 = new ViewInfo("Button", child2Node, 0, 20, 70, 25);
+ root.setChildren(Arrays.asList(child1, child2));
+
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, layoutlib5).getFirst();
+ assertNotNull(rootView);
+ assertEquals("LinearLayout", rootView.getName());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getSelectionRect());
+ assertNull(rootView.getParent());
+ assertSame(rootView.getUiViewNode(), rootNode);
+ assertEquals(2, rootView.getChildren().size());
+ CanvasViewInfo childView1 = rootView.getChildren().get(0);
+ CanvasViewInfo childView2 = rootView.getChildren().get(1);
+
+ assertEquals("Button", childView1.getName());
+ assertSame(rootView, childView1.getParent());
+ assertEquals(new Rectangle(10, 10, 49, 19), childView1.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 49, 19), childView1.getSelectionRect());
+ assertSame(childView1.getUiViewNode(), child1Node);
+
+ assertEquals("Button", childView2.getName());
+ assertSame(rootView, childView2.getParent());
+ assertEquals(new Rectangle(10, 30, 69, 4), childView2.getAbsRect());
+ assertEquals(new Rectangle(10, 30, 69, 5), childView2.getSelectionRect());
+ assertSame(childView2.getUiViewNode(), child2Node);
+ }
+
+ public void testShowIn() throws Exception {
+ showIn(false);
+ }
+
+ public void testShowInLayoutLib5() throws Exception {
+ showIn(true);
+ }
+
+ public void showIn(boolean layoutlib5) throws Exception {
+
+ // Test rendering of "Show Included In" (included content rendered
+ // within an outer content that has null keys)
+
+ ViewInfo root = new ViewInfo("LinearLayout", null, 10, 10, 100, 100);
+ ViewInfo child1 = new ViewInfo("CheckBox", null, 0, 0, 50, 20);
+ UiViewElementNode child2Node = createNode("android.widget.RelativeLayout", true);
+ ViewInfo child2 = new ViewInfo("RelativeLayout", child2Node, 0, 20, 70, 25);
+ root.setChildren(Arrays.asList(child1, child2));
+ UiViewElementNode child21Node = createNode("android.widget.Button", false);
+ ViewInfo child21 = new ViewInfo("RadioButton", child21Node, 0, 20, 70, 25);
+ child2.setChildren(Arrays.asList(child21));
+
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, layoutlib5).getFirst();
+ assertNotNull(rootView);
+ assertEquals("LinearLayout", rootView.getName());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getSelectionRect());
+ assertNull(rootView.getParent());
+ assertNull(rootView.getUiViewNode());
+ assertEquals(1, rootView.getChildren().size());
+ CanvasViewInfo includedView = rootView.getChildren().get(0);
+
+ assertEquals("RelativeLayout", includedView.getName());
+ assertSame(rootView, includedView.getParent());
+ assertEquals(new Rectangle(10, 30, 69, 4), includedView.getAbsRect());
+ assertEquals(new Rectangle(10, 30, 69, 5), includedView.getSelectionRect());
+ assertSame(includedView.getUiViewNode(), child2Node);
+
+ CanvasViewInfo grandChild = includedView.getChildren().get(0);
+ assertNotNull(grandChild);
+ assertEquals("RadioButton", grandChild.getName());
+ assertSame(child21Node, grandChild.getUiViewNode());
+ assertEquals(new Rectangle(10, 50, 69, 4), grandChild.getAbsRect());
+ assertEquals(new Rectangle(10, 50, 69, 5), grandChild.getSelectionRect());
+ }
+
+ public void testIncludeTag() throws Exception {
+ boolean layoutlib5 = true;
+
+ // Test rendering of included views on layoutlib 5+ (e.g. has <include> tag)
+
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("LinearLayout", rootNode, 10, 10, 100, 100);
+ UiViewElementNode child1Node = createNode(rootNode, "android.widget.Button", false);
+ ViewInfo child1 = new ViewInfo("CheckBox", child1Node, 0, 0, 50, 20);
+ UiViewElementNode child2Node = createNode(rootNode, "include", true);
+ ViewInfo child2 = new ViewInfo("RelativeLayout", child2Node, 0, 20, 70, 25);
+ root.setChildren(Arrays.asList(child1, child2));
+ ViewInfo child21 = new ViewInfo("RadioButton", null, 0, 20, 70, 25);
+ child2.setChildren(Arrays.asList(child21));
+
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, layoutlib5).getFirst();
+ assertNotNull(rootView);
+ assertEquals("LinearLayout", rootView.getName());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getSelectionRect());
+ assertNull(rootView.getParent());
+ assertSame(rootNode, rootView.getUiViewNode());
+ assertEquals(2, rootView.getChildren().size());
+
+ CanvasViewInfo childView1 = rootView.getChildren().get(0);
+ CanvasViewInfo includedView = rootView.getChildren().get(1);
+
+ assertEquals("CheckBox", childView1.getName());
+ assertSame(rootView, childView1.getParent());
+ assertEquals(new Rectangle(10, 10, 49, 19), childView1.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 49, 19), childView1.getSelectionRect());
+ assertSame(childView1.getUiViewNode(), child1Node);
+
+ assertEquals("RelativeLayout", includedView.getName());
+ assertSame(rootView, includedView.getParent());
+ assertEquals(new Rectangle(10, 30, 69, 4), includedView.getAbsRect());
+ assertEquals(new Rectangle(10, 30, 69, 5), includedView.getSelectionRect());
+ assertSame(includedView.getUiViewNode(), child2Node);
+ assertEquals(0, includedView.getChildren().size());
+ }
+
+ public void testNoIncludeTag() throws Exception {
+ boolean layoutlib5 = false;
+
+ // Test rendering of included views on layoutlib 4- (e.g. no <include> tag cookie
+ // in view info)
+
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("LinearLayout", rootNode, 10, 10, 100, 100);
+ UiViewElementNode child1Node = createNode(rootNode, "android.widget.Button", false);
+ ViewInfo child1 = new ViewInfo("CheckBox", child1Node, 0, 0, 50, 20);
+ UiViewElementNode child2Node = createNode(rootNode, "include", true);
+ ViewInfo child2 = new ViewInfo("RelativeLayout", null /* layoutlib 4 */, 0, 20, 70, 25);
+ root.setChildren(Arrays.asList(child1, child2));
+ ViewInfo child21 = new ViewInfo("RadioButton", null, 0, 20, 70, 25);
+ child2.setChildren(Arrays.asList(child21));
+
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, layoutlib5).getFirst();
+ assertNotNull(rootView);
+ assertEquals("LinearLayout", rootView.getName());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getSelectionRect());
+ assertNull(rootView.getParent());
+ assertSame(rootNode, rootView.getUiViewNode());
+ assertEquals(2, rootView.getChildren().size());
+
+ CanvasViewInfo childView1 = rootView.getChildren().get(0);
+ CanvasViewInfo includedView = rootView.getChildren().get(1);
+
+ assertEquals("CheckBox", childView1.getName());
+ assertSame(rootView, childView1.getParent());
+ assertEquals(new Rectangle(10, 10, 49, 19), childView1.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 49, 19), childView1.getSelectionRect());
+ assertSame(childView1.getUiViewNode(), child1Node);
+
+ assertEquals("RelativeLayout", includedView.getName());
+ assertSame(rootView, includedView.getParent());
+ assertEquals(new Rectangle(10, 30, 69, 4), includedView.getAbsRect());
+ assertEquals(new Rectangle(10, 30, 69, 5), includedView.getSelectionRect());
+ assertSame(includedView.getUiViewNode(), child2Node);
+ assertEquals(0, includedView.getChildren().size());
+ }
+
+ public void testMergeMatching() throws Exception {
+ boolean layoutlib5 = false;
+
+ // Test rendering of MULTIPLE included views or when there is no simple match
+ // between view info and ui element node children
+
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("LinearLayout", rootNode, 10, 10, 100, 100);
+ UiViewElementNode child1Node = createNode(rootNode, "android.widget.Button", false);
+ ViewInfo child1 = new ViewInfo("CheckBox", child1Node, 0, 0, 50, 20);
+ UiViewElementNode multiChildNode1 = createNode(rootNode, "foo", true);
+ UiViewElementNode multiChildNode2 = createNode(rootNode, "bar", true);
+ ViewInfo child2 = new ViewInfo("RelativeLayout", null, 0, 20, 70, 25);
+ ViewInfo child3 = new ViewInfo("AbsoluteLayout", null, 10, 40, 50, 15);
+ root.setChildren(Arrays.asList(child1, child2, child3));
+ ViewInfo child21 = new ViewInfo("RadioButton", null, 0, 20, 70, 25);
+ child2.setChildren(Arrays.asList(child21));
+
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, layoutlib5).getFirst();
+ assertNotNull(rootView);
+ assertEquals("LinearLayout", rootView.getName());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getSelectionRect());
+ assertNull(rootView.getParent());
+ assertTrue(rootView.isRoot());
+ assertSame(rootNode, rootView.getUiViewNode());
+ assertEquals(3, rootView.getChildren().size());
+
+ CanvasViewInfo childView1 = rootView.getChildren().get(0);
+ assertFalse(childView1.isRoot());
+ CanvasViewInfo includedView1 = rootView.getChildren().get(1);
+ assertFalse(includedView1.isRoot());
+ CanvasViewInfo includedView2 = rootView.getChildren().get(2);
+ assertFalse(includedView1.isRoot());
+
+ assertEquals("CheckBox", childView1.getName());
+ assertSame(rootView, childView1.getParent());
+ assertEquals(new Rectangle(10, 10, 49, 19), childView1.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 49, 19), childView1.getSelectionRect());
+ assertSame(childView1.getUiViewNode(), child1Node);
+
+ assertEquals("RelativeLayout", includedView1.getName());
+ assertSame(multiChildNode1, includedView1.getUiViewNode());
+ assertEquals("foo", includedView1.getUiViewNode().getDescriptor().getXmlName());
+ assertSame(multiChildNode2, includedView2.getUiViewNode());
+ assertEquals("AbsoluteLayout", includedView2.getName());
+ assertEquals("bar", includedView2.getUiViewNode().getDescriptor().getXmlName());
+ assertSame(rootView, includedView1.getParent());
+ assertSame(rootView, includedView2.getParent());
+ assertEquals(new Rectangle(10, 30, 69, 4), includedView1.getAbsRect());
+ assertEquals(new Rectangle(10, 30, 69, 5), includedView1.getSelectionRect());
+ assertEquals(new Rectangle(20, 50, 39, -26), includedView2.getAbsRect());
+ assertEquals(new Rectangle(20, 35, 39, 5), includedView2.getSelectionRect());
+ assertEquals(0, includedView1.getChildren().size());
+ assertEquals(0, includedView2.getChildren().size());
+ }
+
+ public void testMerge() throws Exception {
+ boolean layoutlib5 = false;
+
+ // Test rendering of MULTIPLE included views or when there is no simple match
+ // between view info and ui element node children
+
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("LinearLayout", rootNode, 10, 10, 100, 100);
+ UiViewElementNode child1Node = createNode(rootNode, "android.widget.Button", false);
+ ViewInfo child1 = new ViewInfo("CheckBox", child1Node, 0, 0, 50, 20);
+ UiViewElementNode multiChildNode = createNode(rootNode, "foo", true);
+ ViewInfo child2 = new ViewInfo("RelativeLayout", null, 0, 20, 70, 25);
+ ViewInfo child3 = new ViewInfo("AbsoluteLayout", null, 10, 40, 50, 15);
+ root.setChildren(Arrays.asList(child1, child2, child3));
+ ViewInfo child21 = new ViewInfo("RadioButton", null, 0, 20, 70, 25);
+ child2.setChildren(Arrays.asList(child21));
+
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, layoutlib5).getFirst();
+ assertNotNull(rootView);
+ assertEquals("LinearLayout", rootView.getName());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getSelectionRect());
+ assertNull(rootView.getParent());
+ assertSame(rootNode, rootView.getUiViewNode());
+ assertEquals(2, rootView.getChildren().size());
+
+ CanvasViewInfo childView1 = rootView.getChildren().get(0);
+ CanvasViewInfo includedView = rootView.getChildren().get(1);
+
+ assertEquals("CheckBox", childView1.getName());
+ assertSame(rootView, childView1.getParent());
+ assertEquals(new Rectangle(10, 10, 49, 19), childView1.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 49, 19), childView1.getSelectionRect());
+ assertSame(childView1.getUiViewNode(), child1Node);
+
+ assertEquals("RelativeLayout", includedView.getName());
+ assertSame(rootView, includedView.getParent());
+ assertEquals(new Rectangle(10, 30, 69, 4), includedView.getAbsRect());
+ assertEquals(new Rectangle(10, 30, 69, 5), includedView.getSelectionRect());
+ assertEquals(0, includedView.getChildren().size());
+ assertSame(multiChildNode, includedView.getUiViewNode());
+ }
+
+ public void testInsertMerge() throws Exception {
+ boolean layoutlib5 = false;
+
+ // Test rendering of MULTIPLE included views or when there is no simple match
+ // between view info and ui element node children
+
+ UiViewElementNode mergeNode = createNode("merge", true);
+ UiViewElementNode rootNode = createNode(mergeNode, "android.widget.Button", false);
+ ViewInfo root = new ViewInfo("Button", rootNode, 10, 10, 100, 100);
+
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, layoutlib5).getFirst();
+ assertNotNull(rootView);
+ assertEquals("merge", rootView.getName());
+ assertSame(rootView.getUiViewNode(), mergeNode);
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 89, 89), rootView.getSelectionRect());
+ assertNull(rootView.getParent());
+ assertSame(mergeNode, rootView.getUiViewNode());
+ assertEquals(1, rootView.getChildren().size());
+
+ CanvasViewInfo childView1 = rootView.getChildren().get(0);
+
+ assertEquals("Button", childView1.getName());
+ assertSame(rootView, childView1.getParent());
+ assertEquals(new Rectangle(10, 10, 89, 89), childView1.getAbsRect());
+ assertEquals(new Rectangle(10, 10, 89, 89), childView1.getSelectionRect());
+ assertSame(childView1.getUiViewNode(), rootNode);
+ }
+
+ public void testUnmatchedMissing() throws Exception {
+ boolean layoutlib5 = false;
+
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("LinearLayout", rootNode, 0, 0, 100, 100);
+ List<ViewInfo> children = new ArrayList<ViewInfo>();
+ // Should be matched up with corresponding node:
+ Set<Integer> missingKeys = new HashSet<Integer>();
+ // Should not be matched with any views, but should get view created:
+ Set<Integer> extraKeys = new HashSet<Integer>();
+ // Should not be matched with any nodes
+ Set<Integer> extraViews = new HashSet<Integer>();
+ int numViews = 30;
+ missingKeys.add(0);
+ missingKeys.add(4);
+ missingKeys.add(14);
+ missingKeys.add(29);
+ extraKeys.add(9);
+ extraKeys.add(20);
+ extraKeys.add(22);
+ extraViews.add(18);
+ extraViews.add(24);
+
+ List<String> expectedViewNames = new ArrayList<String>();
+ List<String> expectedNodeNames = new ArrayList<String>();
+
+ for (int i = 0; i < numViews; i++) {
+ UiViewElementNode childNode = null;
+ if (!extraViews.contains(i)) {
+ childNode = createNode(rootNode, "childNode" + i, false);
+ }
+ Object cookie = missingKeys.contains(i) || extraViews.contains(i) ? null : childNode;
+ ViewInfo childView = new ViewInfo("childView" + i, cookie,
+ 0, i * 20, 50, (i + 1) * 20);
+ children.add(childView);
+
+ if (!extraViews.contains(i)) {
+ expectedViewNames.add("childView" + i);
+ expectedNodeNames.add("childNode" + i);
+ }
+
+ if (extraKeys.contains(i)) {
+ createNode(rootNode, "extraNodeAt" + i, false);
+
+ expectedViewNames.add("extraNodeAt" + i);
+ expectedNodeNames.add("extraNodeAt" + i);
+ }
+ }
+ root.setChildren(children);
+
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, layoutlib5).getFirst();
+ assertNotNull(rootView);
+
+ // dump(root, 0);
+ // dump(rootView, 0);
+
+ assertEquals("LinearLayout", rootView.getName());
+ assertNull(rootView.getParent());
+ assertSame(rootNode, rootView.getUiViewNode());
+ assertEquals(numViews + extraKeys.size() - extraViews.size(), rootNode.getUiChildren()
+ .size());
+ assertEquals(numViews + extraKeys.size() - extraViews.size(),
+ rootView.getChildren().size());
+ assertEquals(expectedViewNames.size(), rootView.getChildren().size());
+ for (int i = 0, n = rootView.getChildren().size(); i < n; i++) {
+ CanvasViewInfo childView = rootView.getChildren().get(i);
+ String expectedViewName = expectedViewNames.get(i);
+ String expectedNodeName = expectedNodeNames.get(i);
+ assertEquals(expectedViewName, childView.getName());
+ assertNotNull(childView.getUiViewNode());
+ assertEquals(expectedNodeName, childView.getUiViewNode().getDescriptor().getXmlName());
+ }
+ }
+
+ public void testMergeCookies() throws Exception {
+ boolean layoutlib5 = true;
+
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("LinearLayout", rootNode, 0, 0, 100, 100);
+
+ // Create the merge cookies in the opposite order to ensure that we don't
+ // apply our own logic when matching up views with nodes
+ LinkedList<MergeCookie> cookies = new LinkedList<MergeCookie>();
+ for (int i = 0; i < 10; i++) {
+ UiViewElementNode node = createNode(rootNode, "childNode" + i, false);
+ cookies.addFirst(new MergeCookie(node));
+ }
+ Iterator<MergeCookie> it = cookies.iterator();
+ ArrayList<ViewInfo> children = new ArrayList<ViewInfo>();
+ for (int i = 0; i < 10; i++) {
+ ViewInfo childView = new ViewInfo("childView" + i, it.next(), 0, i * 20, 50,
+ (i + 1) * 20);
+ children.add(childView);
+ }
+ root.setChildren(children);
+
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, layoutlib5).getFirst();
+ assertNotNull(rootView);
+
+ assertEquals("LinearLayout", rootView.getName());
+ assertNull(rootView.getParent());
+ assertSame(rootNode, rootView.getUiViewNode());
+ for (int i = 0, n = rootView.getChildren().size(); i < n; i++) {
+ CanvasViewInfo childView = rootView.getChildren().get(i);
+ assertEquals("childView" + i, childView.getName());
+ assertEquals("childNode" + (9 - i), childView.getUiViewNode().getDescriptor()
+ .getXmlName());
+ }
+ }
+
+ public void testMergeCookies2() throws Exception {
+ boolean layoutlib5 = true;
+
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("LinearLayout", rootNode, 0, 0, 100, 100);
+
+ UiViewElementNode node1 = createNode(rootNode, "childNode1", false);
+ UiViewElementNode node2 = createNode(rootNode, "childNode2", false);
+ MergeCookie cookie1 = new MergeCookie(node1);
+ MergeCookie cookie2 = new MergeCookie(node2);
+
+ // Sets alternating merge cookies and checks whether the node sibling lists are
+ // okay and merged correctly
+
+ ArrayList<ViewInfo> children = new ArrayList<ViewInfo>();
+ for (int i = 0; i < 10; i++) {
+ Object cookie = (i % 2) == 0 ? cookie1 : cookie2;
+ ViewInfo childView = new ViewInfo("childView" + i, cookie, 0, i * 20, 50,
+ (i + 1) * 20);
+ children.add(childView);
+ }
+ root.setChildren(children);
+
+ Pair<CanvasViewInfo, List<Rectangle>> result = CanvasViewInfo.create(root, layoutlib5);
+ CanvasViewInfo rootView = result.getFirst();
+ List<Rectangle> bounds = result.getSecond();
+ assertNull(bounds);
+ assertNotNull(rootView);
+
+ assertEquals("LinearLayout", rootView.getName());
+ assertNull(rootView.getParent());
+ assertSame(rootNode, rootView.getUiViewNode());
+ assertEquals(10, rootView.getChildren().size());
+ assertEquals(2, rootView.getUniqueChildren().size());
+ for (int i = 0, n = rootView.getChildren().size(); i < n; i++) {
+ CanvasViewInfo childView = rootView.getChildren().get(i);
+ assertEquals("childView" + i, childView.getName());
+ Object cookie = (i % 2) == 0 ? node1 : node2;
+ assertSame(cookie, childView.getUiViewNode());
+ List<CanvasViewInfo> nodeSiblings = childView.getNodeSiblings();
+ assertEquals(5, nodeSiblings.size());
+ }
+ List<CanvasViewInfo> nodeSiblings = rootView.getChildren().get(0).getNodeSiblings();
+ for (int j = 0; j < 5; j++) {
+ assertEquals("childView" + (j * 2), nodeSiblings.get(j).getName());
+ }
+ nodeSiblings = rootView.getChildren().get(1).getNodeSiblings();
+ for (int j = 0; j < 5; j++) {
+ assertEquals("childView" + (j * 2 + 1), nodeSiblings.get(j).getName());
+ }
+ }
+
+ public void testIncludeBounds() throws Exception {
+ boolean layoutlib5 = true;
+
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("included", null, 0, 0, 100, 100);
+
+ UiViewElementNode node1 = createNode(rootNode, "childNode1", false);
+ UiViewElementNode node2 = createNode(rootNode, "childNode2", false);
+ MergeCookie cookie1 = new MergeCookie(node1);
+ MergeCookie cookie2 = new MergeCookie(node2);
+
+ // Sets alternating merge cookies and checks whether the node sibling lists are
+ // okay and merged correctly
+
+ ArrayList<ViewInfo> children = new ArrayList<ViewInfo>();
+ for (int i = 0; i < 10; i++) {
+ Object cookie = (i % 2) == 0 ? cookie1 : cookie2;
+ ViewInfo childView = new ViewInfo("childView" + i, cookie, 0, i * 20, 50,
+ (i + 1) * 20);
+ children.add(childView);
+ }
+ root.setChildren(children);
+
+ Pair<CanvasViewInfo, List<Rectangle>> result = CanvasViewInfo.create(root, layoutlib5);
+ CanvasViewInfo rootView = result.getFirst();
+ List<Rectangle> bounds = result.getSecond();
+ assertNotNull(rootView);
+
+ assertEquals("included", rootView.getName());
+ assertNull(rootView.getParent());
+ assertNull(rootView.getUiViewNode());
+ assertEquals(10, rootView.getChildren().size());
+ assertEquals(2, rootView.getUniqueChildren().size());
+ for (int i = 0, n = rootView.getChildren().size(); i < n; i++) {
+ CanvasViewInfo childView = rootView.getChildren().get(i);
+ assertEquals("childView" + i, childView.getName());
+ Object cookie = (i % 2) == 0 ? node1 : node2;
+ assertSame(cookie, childView.getUiViewNode());
+ List<CanvasViewInfo> nodeSiblings = childView.getNodeSiblings();
+ assertEquals(5, nodeSiblings.size());
+ }
+ List<CanvasViewInfo> nodeSiblings = rootView.getChildren().get(0).getNodeSiblings();
+ for (int j = 0; j < 5; j++) {
+ assertEquals("childView" + (j * 2), nodeSiblings.get(j).getName());
+ }
+ nodeSiblings = rootView.getChildren().get(1).getNodeSiblings();
+ for (int j = 0; j < 5; j++) {
+ assertEquals("childView" + (j * 2 + 1), nodeSiblings.get(j).getName());
+ }
+
+ // Only show the primary bounds as included
+ assertEquals(2, bounds.size());
+ assertEquals(new Rectangle(0, 0, 49, 19), bounds.get(0));
+ assertEquals(new Rectangle(0, 20, 49, 19), bounds.get(1));
+ }
+
+ public void testIncludeBounds2() throws Exception {
+ includeBounds2(false);
+ }
+
+ public void testIncludeBounds2LayoutLib5() throws Exception {
+ includeBounds2(true);
+ }
+
+ public void includeBounds2(boolean layoutlib5) throws Exception {
+
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("included", null, 0, 0, 100, 100);
+
+ UiViewElementNode node1 = createNode(rootNode, "childNode1", false);
+ UiViewElementNode node2 = createNode(rootNode, "childNode2", false);
+
+ ViewInfo childView1 = new ViewInfo("childView1", node1, 0, 20, 50, 40);
+ ViewInfo childView2 = new ViewInfo("childView2", node2, 0, 40, 50, 60);
+
+ root.setChildren(Arrays.asList(childView1, childView2));
+
+ Pair<CanvasViewInfo, List<Rectangle>> result = CanvasViewInfo.create(root, layoutlib5);
+ CanvasViewInfo rootView = result.getFirst();
+ List<Rectangle> bounds = result.getSecond();
+ assertNotNull(rootView);
+
+ assertEquals("included", rootView.getName());
+ assertNull(rootView.getParent());
+ assertNull(rootView.getUiViewNode());
+ assertEquals(2, rootView.getChildren().size());
+ assertEquals(2, rootView.getUniqueChildren().size());
+
+ Rectangle bounds1 = bounds.get(0);
+ Rectangle bounds2 = bounds.get(1);
+ assertEquals(new Rectangle(0, 20, 49, 19), bounds1);
+ assertEquals(new Rectangle(0, 40, 49, 19), bounds2);
+ }
+
+ public void testCookieWorkaround() throws Exception {
+ UiViewElementNode rootNode = createNode("android.widget.LinearLayout", true);
+ ViewInfo root = new ViewInfo("included", null, 0, 0, 100, 100);
+
+ UiViewElementNode node2 = createNode(rootNode, "childNode2", false);
+ MergeCookie mergeCookie = new MergeCookie(root);
+
+ ViewInfo childView1 = new ViewInfo("childView1", mergeCookie, 0, 20, 50, 40);
+ ViewInfo childView2 = new ViewInfo("childView2", node2, 0, 40, 50, 60);
+
+ root.setChildren(Arrays.asList(childView1, childView2));
+
+ Pair<CanvasViewInfo, List<Rectangle>> result = CanvasViewInfo.create(root, true);
+ CanvasViewInfo rootView = result.getFirst();
+ List<Rectangle> bounds = result.getSecond();
+ assertNotNull(rootView);
+
+ assertEquals("included", rootView.getName());
+ assertNull(rootView.getParent());
+ assertNull(rootView.getUiViewNode());
+ // childView1 should have been removed since it has the wrong merge cookie
+ assertEquals(1, rootView.getChildren().size());
+ assertEquals(1, rootView.getUniqueChildren().size());
+
+ Rectangle bounds1 = bounds.get(0);
+ assertEquals(new Rectangle(0, 40, 49, 19), bounds1);
+ }
+
+ public void testGestureOverlayView() throws Exception {
+ boolean layoutlib5 = true;
+
+ // Test rendering of included views on layoutlib 5+ (e.g. has <include> tag)
+
+ UiViewElementNode rootNode = createNode("android.gesture.GestureOverlayView", true);
+ UiViewElementNode childNode = createNode(rootNode, "android.widget.LinearLayout", false);
+ UiViewElementNode grandChildNode = createNode(childNode, "android.widget.Button", false);
+ ViewInfo root = new ViewInfo("GestureOverlayView", rootNode, 10, 10, 100, 100);
+ ViewInfo child = new ViewInfo("LinearLayout", childNode, 0, 0, 50, 20);
+ root.setChildren(Collections.singletonList(child));
+ ViewInfo grandChild = new ViewInfo("Button", grandChildNode, 0, 20, 70, 25);
+ child.setChildren(Collections.singletonList(grandChild));
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, layoutlib5).getFirst();
+ assertNotNull(rootView);
+ assertEquals("GestureOverlayView", rootView.getName());
+
+ assertTrue(rootView.isRoot());
+ assertNull(rootView.getParent());
+ assertSame(rootNode, rootView.getUiViewNode());
+ assertEquals(1, rootView.getChildren().size());
+
+ CanvasViewInfo childView = rootView.getChildren().get(0);
+ assertEquals("LinearLayout", childView.getName());
+
+ // This should also be a root for the special case that the root is
+ assertTrue(childView.isRoot());
+
+ assertEquals(1, childView.getChildren().size());
+ CanvasViewInfo grandChildView = childView.getChildren().get(0);
+ assertEquals("Button", grandChildView.getName());
+ assertFalse(grandChildView.isRoot());
+ }
+
+ public void testListView() throws Exception {
+ // For ListViews we get AdapterItemReferences as cookies. Ensure that this
+ // works properly.
+ //
+ // android.widget.FrameLayout [0,50,320,480] <FrameLayout>
+ // android.widget.ListView [0,0,320,430] <ListView>
+ // android.widget.LinearLayout [0,0,320,17] SessionParams$AdapterItemReference
+ // android.widget.TextView [0,0,73,17]
+ // android.widget.LinearLayout [0,18,320,35] SessionParams$AdapterItemReference
+ // android.widget.TextView [0,0,73,17]
+ // android.widget.LinearLayout [0,36,320,53] SessionParams$AdapterItemReference
+ // android.widget.TextView [0,0,73,17]
+ // ...
+
+ UiViewElementNode rootNode = createNode("FrameLayout", true);
+ UiViewElementNode childNode = createNode(rootNode, "ListView", false);
+ /*UiViewElementNode grandChildNode =*/ createNode(childNode, "LinearLayout", false);
+ /*UiViewElementNode greatGrandChildNode =*/ createNode(childNode, "TextView", false);
+ DataBindingItem dataBindingItem = new DataBindingItem("foo");
+
+ ViewInfo root = new ViewInfo("FrameLayout", rootNode, 0, 50, 320, 480);
+ ViewInfo child = new ViewInfo("ListView", childNode, 0, 0, 320, 430);
+ root.setChildren(Collections.singletonList(child));
+ ViewInfo grandChild = new ViewInfo("LinearLayout", dataBindingItem, 0, 0, 320, 17);
+ child.setChildren(Collections.singletonList(grandChild));
+ ViewInfo greatGrandChild = new ViewInfo("Button", null, 0, 0, 73, 17);
+ grandChild.setChildren(Collections.singletonList(greatGrandChild));
+ CanvasViewInfo rootView = CanvasViewInfo.create(root, true /*layoutlib5*/).getFirst();
+ assertNotNull(rootView);
+
+ assertEquals("FrameLayout", rootView.getName());
+ assertEquals(1, rootView.getChildren().size());
+ assertSame(rootNode, rootView.getUiViewNode());
+
+ CanvasViewInfo childView = rootView.getChildren().get(0);
+ assertEquals("ListView", childView.getName());
+ assertEquals(0, childView.getChildren().size());
+ assertSame(childNode, childView.getUiViewNode());
+ }
+
+ /**
+ * Dumps out the given {@link ViewInfo} hierarchy to standard out.
+ * Useful during development.
+ *
+ * @param graphicalEditor the editor associated with this hierarchy
+ * @param root the root of the {@link ViewInfo} hierarchy
+ */
+ public static void dump(GraphicalEditorPart graphicalEditor, ViewInfo root) {
+ System.out.println("\n\nRendering:");
+ boolean supportsEmbedding = graphicalEditor.renderingSupports(Capability.EMBEDDED_LAYOUT);
+ System.out.println("Supports Embedded Layout=" + supportsEmbedding);
+ System.out.println("Rendering context=" + graphicalEditor.getIncludedWithin());
+ dump(root, 0);
+ }
+
+ /** Helper for {@link #dump(GraphicalEditorPart, ViewInfo)} */
+ public static void dump(ViewInfo info, int depth) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < depth; i++) {
+ sb.append(" ");
+ }
+ sb.append(info.getClassName());
+ sb.append(" [");
+ sb.append(info.getLeft());
+ sb.append(",");
+ sb.append(info.getTop());
+ sb.append(",");
+ sb.append(info.getRight());
+ sb.append(",");
+ sb.append(info.getBottom());
+ sb.append("] ");
+ Object cookie = info.getCookie();
+ if (cookie instanceof UiViewElementNode) {
+ sb.append(" ");
+ UiViewElementNode node = (UiViewElementNode) cookie;
+ sb.append("<");
+ sb.append(node.getDescriptor().getXmlName());
+ sb.append("> ");
+ } else if (cookie != null) {
+ sb.append(" cookie=" + cookie);
+ }
+
+ System.out.println(sb.toString());
+
+ for (ViewInfo child : info.getChildren()) {
+ dump(child, depth + 1);
+ }
+ }
+
+ /** Helper for {@link #dump(GraphicalEditorPart, ViewInfo)} */
+ public static void dump(CanvasViewInfo info, int depth) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < depth; i++) {
+ sb.append(" ");
+ }
+ sb.append(info.getName());
+ sb.append(" [");
+ sb.append(info.getAbsRect());
+ sb.append("], node=");
+ sb.append(info.getUiViewNode());
+
+ System.out.println(sb.toString());
+
+ for (CanvasViewInfo child : info.getChildren()) {
+ dump(child, depth + 1);
+ }
+ }
+
+}