aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LinearLayoutRuleTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LinearLayoutRuleTest.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LinearLayoutRuleTest.java466
1 files changed, 466 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LinearLayoutRuleTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LinearLayoutRuleTest.java
new file mode 100644
index 000000000..9c4c934c0
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LinearLayoutRuleTest.java
@@ -0,0 +1,466 @@
+/*
+ * 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.common.layout;
+
+import static com.android.SdkConstants.ANDROID_URI;
+import static com.android.SdkConstants.ATTR_ID;
+import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT;
+import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH;
+import static com.android.SdkConstants.ATTR_ORIENTATION;
+import static com.android.SdkConstants.VALUE_HORIZONTAL;
+import static com.android.SdkConstants.VALUE_VERTICAL;
+
+import com.android.ide.common.api.DropFeedback;
+import com.android.ide.common.api.IAttributeInfo.Format;
+import com.android.ide.common.api.IDragElement;
+import com.android.ide.common.api.IMenuCallback;
+import com.android.ide.common.api.INode;
+import com.android.ide.common.api.IViewRule;
+import com.android.ide.common.api.Point;
+import com.android.ide.common.api.Rect;
+import com.android.ide.common.api.RuleAction;
+import com.android.ide.common.api.RuleAction.NestedAction;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/** Test the {@link LinearLayoutRule} */
+public class LinearLayoutRuleTest extends LayoutTestBase {
+ // Utility for other tests
+ protected void dragIntoEmpty(Rect dragBounds) {
+ boolean haveBounds = dragBounds.isValid();
+
+ IViewRule rule = new LinearLayoutRule();
+
+ INode targetNode = TestNode.create("android.widget.LinearLayout").id(
+ "@+id/LinearLayout01").bounds(new Rect(0, 0, 240, 480));
+ Point dropPoint = new Point(10, 5);
+
+ IDragElement[] elements = TestDragElement.create(TestDragElement.create(
+ "android.widget.Button", dragBounds).id("@+id/Button01"));
+
+ // Enter target
+ DropFeedback feedback = rule.onDropEnter(targetNode, null/*targetView*/, elements);
+ assertNotNull(feedback);
+ assertFalse(feedback.invalidTarget);
+ assertNotNull(feedback.painter);
+
+ feedback = rule.onDropMove(targetNode, elements, feedback, dropPoint);
+ assertNotNull(feedback);
+ assertFalse(feedback.invalidTarget);
+
+ // Paint feedback and make sure it's what we expect
+ TestGraphics graphics = new TestGraphics();
+ assertNotNull(feedback.painter);
+ feedback.painter.paint(graphics, targetNode, feedback);
+ assertEquals(
+ // Expect to see a recipient rectangle around the bounds of the
+ // LinearLayout,
+ // as well as a single vertical line as a drop preview located
+ // along the left
+ // edge (for this horizontal linear layout) showing insert
+ // position at index 0,
+ // and finally a rectangle for the bounds of the inserted button
+ // centered over
+ // the middle
+ "[useStyle(DROP_RECIPIENT), "
+ +
+ // Bounds rectangle
+ "drawRect(Rect[0,0,240,480]), "
+ + "useStyle(DROP_ZONE), drawLine(1,0,1,480), "
+ + "useStyle(DROP_ZONE_ACTIVE), " + "useStyle(DROP_PREVIEW), " +
+ // Insert position line
+ "drawLine(1,0,1,480)" + (haveBounds ?
+ // Outline of dragged node centered over position line
+ ", useStyle(DROP_PREVIEW), " + "drawRect(1,0,101,80)"
+ // Nothing when we don't have bounds
+ : "") + "]", graphics.getDrawn().toString());
+
+ // Attempt a drop
+ assertEquals(0, targetNode.getChildren().length);
+ rule.onDropped(targetNode, elements, feedback, dropPoint);
+ assertEquals(1, targetNode.getChildren().length);
+ assertEquals("@+id/Button01", targetNode.getChildren()[0].getStringAttr(
+ ANDROID_URI, ATTR_ID));
+ }
+
+ // Utility for other tests
+ protected INode dragInto(boolean vertical, Rect dragBounds, Point dragPoint,
+ int insertIndex, int currentIndex,
+ String... graphicsFragments) {
+ INode linearLayout = TestNode.create("android.widget.LinearLayout").id(
+ "@+id/LinearLayout01").bounds(new Rect(0, 0, 240, 480)).set(ANDROID_URI,
+ ATTR_ORIENTATION,
+ vertical ? VALUE_VERTICAL : VALUE_HORIZONTAL)
+ .add(
+ TestNode.create("android.widget.Button").id("@+id/Button01").bounds(
+ new Rect(0, 0, 100, 80)),
+ TestNode.create("android.widget.Button").id("@+id/Button02").bounds(
+ new Rect(0, 100, 100, 80)),
+ TestNode.create("android.widget.Button").id("@+id/Button03").bounds(
+ new Rect(0, 200, 100, 80)),
+ TestNode.create("android.widget.Button").id("@+id/Button04").bounds(
+ new Rect(0, 300, 100, 80)));
+
+ return super.dragInto(new LinearLayoutRule(), linearLayout, dragBounds, dragPoint, null,
+ insertIndex, currentIndex, graphicsFragments);
+ }
+
+ // Check that the context menu registers the expected menu items
+ public void testContextMenu() {
+ LinearLayoutRule rule = new LinearLayoutRule();
+ initialize(rule, "android.widget.LinearLayout");
+ INode node = TestNode.create("android.widget.Button").id("@+id/Button012");
+
+ List<RuleAction> contextMenu = new ArrayList<RuleAction>();
+ rule.addContextMenuActions(contextMenu, node);
+ assertEquals(6, contextMenu.size());
+ assertEquals("Edit ID...", contextMenu.get(0).getTitle());
+ assertTrue(contextMenu.get(1) instanceof RuleAction.Separator);
+ assertEquals("Layout Width", contextMenu.get(2).getTitle());
+ assertEquals("Layout Height", contextMenu.get(3).getTitle());
+ assertTrue(contextMenu.get(4) instanceof RuleAction.Separator);
+ assertEquals("Other Properties", contextMenu.get(5).getTitle());
+
+ RuleAction propertiesMenu = contextMenu.get(5);
+ assertTrue(propertiesMenu.getClass().getName(),
+ propertiesMenu instanceof NestedAction);
+ }
+
+ public void testContextMenuCustom() {
+ LinearLayoutRule rule = new LinearLayoutRule();
+ initialize(rule, "android.widget.LinearLayout");
+ INode node = TestNode.create("android.widget.LinearLayout").id("@+id/LinearLayout")
+ .set(ANDROID_URI, ATTR_LAYOUT_WIDTH, "42dip")
+ .set(ANDROID_URI, ATTR_LAYOUT_HEIGHT, "50sp");
+
+ List<RuleAction> contextMenu = new ArrayList<RuleAction>();
+ rule.addContextMenuActions(contextMenu, node);
+ assertEquals(6, contextMenu.size());
+ assertEquals("Layout Width", contextMenu.get(2).getTitle());
+ RuleAction menuAction = contextMenu.get(2);
+ assertTrue(menuAction instanceof RuleAction.Choices);
+ RuleAction.Choices choices = (RuleAction.Choices) menuAction;
+ List<String> titles = choices.getTitles();
+ List<String> ids = choices.getIds();
+ assertEquals("Wrap Content", titles.get(0));
+ assertEquals("wrap_content", ids.get(0));
+ assertEquals("Match Parent", titles.get(1));
+ assertEquals("match_parent", ids.get(1));
+ assertEquals("42dip", titles.get(2));
+ assertEquals("42dip", ids.get(2));
+ assertEquals("42dip", choices.getCurrent());
+ }
+
+ // Check that the context menu manipulates the orientation attribute
+ public void testOrientation() {
+ LinearLayoutRule rule = new LinearLayoutRule();
+ initialize(rule, "android.widget.LinearLayout");
+ TestNode node = TestNode.create("android.widget.LinearLayout").id("@+id/LinearLayout012");
+ node.putAttributeInfo(ANDROID_URI, "orientation",
+ new TestAttributeInfo(ATTR_ORIENTATION, Format.ENUM_SET,
+ "android.widget.LinearLayout",
+ new String[] {"horizontal", "vertical"}, null, null));
+
+ assertNull(node.getStringAttr(ANDROID_URI, ATTR_ORIENTATION));
+
+ List<RuleAction> contextMenu = new ArrayList<RuleAction>();
+ rule.addContextMenuActions(contextMenu, node);
+ assertEquals(7, contextMenu.size());
+ RuleAction orientationAction = contextMenu.get(1);
+ assertEquals("Orientation", orientationAction.getTitle());
+
+ assertTrue(orientationAction.getClass().getName(),
+ orientationAction instanceof RuleAction.Choices);
+
+ RuleAction.Choices choices = (RuleAction.Choices) orientationAction;
+ IMenuCallback callback = choices.getCallback();
+ callback.action(orientationAction, Collections.singletonList(node), VALUE_VERTICAL, true);
+
+ String orientation = node.getStringAttr(ANDROID_URI,
+ ATTR_ORIENTATION);
+ assertEquals(VALUE_VERTICAL, orientation);
+ callback.action(orientationAction, Collections.singletonList(node), VALUE_HORIZONTAL,
+ true);
+ orientation = node.getStringAttr(ANDROID_URI, ATTR_ORIENTATION);
+ assertEquals(VALUE_HORIZONTAL, orientation);
+ }
+
+ // Check that the context menu manipulates the orientation attribute
+ public void testProperties() {
+ LinearLayoutRule rule = new LinearLayoutRule();
+ initialize(rule, "android.widget.LinearLayout");
+ TestNode node = TestNode.create("android.widget.LinearLayout").id("@+id/LinearLayout012");
+ node.putAttributeInfo(ANDROID_URI, "orientation",
+ new TestAttributeInfo(ATTR_ORIENTATION, Format.ENUM_SET,
+ "android.widget.LinearLayout",
+ new String[] {"horizontal", "vertical"}, null, null));
+ node.setAttributeSources(Arrays.asList("android.widget.LinearLayout",
+ "android.view.ViewGroup", "android.view.View"));
+ node.putAttributeInfo(ANDROID_URI, "gravity",
+ new TestAttributeInfo("gravity", Format.INTEGER_SET,
+ "android.widget.LinearLayout", null, null, null));
+
+
+ assertNull(node.getStringAttr(ANDROID_URI, ATTR_ORIENTATION));
+
+ List<RuleAction> contextMenu = new ArrayList<RuleAction>();
+ rule.addContextMenuActions(contextMenu, node);
+ assertEquals(8, contextMenu.size());
+
+ assertEquals("Orientation", contextMenu.get(1).getTitle());
+ assertEquals("Edit Gravity...", contextMenu.get(2).getTitle());
+
+ assertEquals("Other Properties", contextMenu.get(7).getTitle());
+
+ RuleAction propertiesMenu = contextMenu.get(7);
+ assertTrue(propertiesMenu.getClass().getName(),
+ propertiesMenu instanceof NestedAction);
+ NestedAction nested = (NestedAction) propertiesMenu;
+ List<RuleAction> nestedActions = nested.getNestedActions(node);
+ assertEquals(9, nestedActions.size());
+ assertEquals("Recent", nestedActions.get(0).getTitle());
+ assertTrue(nestedActions.get(1) instanceof RuleAction.Separator);
+ assertEquals("Defined by LinearLayout", nestedActions.get(2).getTitle());
+ assertEquals("Inherited from ViewGroup", nestedActions.get(3).getTitle());
+ assertEquals("Inherited from View", nestedActions.get(4).getTitle());
+ assertTrue(nestedActions.get(5) instanceof RuleAction.Separator);
+ assertEquals("Layout Parameters", nestedActions.get(6).getTitle());
+ assertTrue(nestedActions.get(7) instanceof RuleAction.Separator);
+ assertEquals("All By Name", nestedActions.get(8).getTitle());
+
+ BaseViewRule.editedProperty(ATTR_ORIENTATION);
+
+ RuleAction recentAction = nestedActions.get(0);
+ assertTrue(recentAction instanceof NestedAction);
+ NestedAction recentChoices = (NestedAction) recentAction;
+ List<RuleAction> recentItems = recentChoices.getNestedActions(node);
+
+ assertEquals(1, recentItems.size());
+ assertEquals("Orientation", recentItems.get(0).getTitle());
+
+ BaseViewRule.editedProperty("gravity");
+ recentItems = recentChoices.getNestedActions(node);
+ assertEquals(2, recentItems.size());
+ assertEquals("Gravity...", recentItems.get(0).getTitle());
+ assertEquals("Orientation", recentItems.get(1).getTitle());
+
+ BaseViewRule.editedProperty(ATTR_ORIENTATION);
+ recentItems = recentChoices.getNestedActions(node);
+ assertEquals(2, recentItems.size());
+ assertEquals("Orientation", recentItems.get(0).getTitle());
+ assertEquals("Gravity...", recentItems.get(1).getTitle());
+
+ // Lots of other properties -- flushes out properties that apply to this view
+ for (int i = 0; i < 30; i++) {
+ BaseViewRule.editedProperty("dummy_" + i);
+ }
+ recentItems = recentChoices.getNestedActions(node);
+ assertEquals(0, recentItems.size());
+
+ BaseViewRule.editedProperty("gravity");
+ recentItems = recentChoices.getNestedActions(node);
+ assertEquals(1, recentItems.size());
+ assertEquals("Gravity...", recentItems.get(0).getTitle());
+ }
+
+ public void testDragInEmptyWithBounds() {
+ dragIntoEmpty(new Rect(0, 0, 100, 80));
+ }
+
+ public void testDragInEmptyWithoutBounds() {
+ dragIntoEmpty(new Rect(0, 0, 0, 0));
+ }
+
+ public void testDragInVerticalTop() {
+ dragInto(true,
+ // Bounds of the dragged item
+ new Rect(0, 0, 105, 80),
+ // Drag point
+ new Point(30, -10),
+ // Expected insert location
+ 0,
+ // Not dragging one of the existing children
+ -1,
+ // Bounds rectangle
+ "useStyle(DROP_RECIPIENT), drawRect(Rect[0,0,240,480])",
+
+ // Drop zones
+ "useStyle(DROP_ZONE), drawLine(0,0,240,0), drawLine(0,90,240,90), "
+ + "drawLine(0,190,240,190), drawLine(0,290,240,290), "
+ + "drawLine(0,381,240,381)",
+
+ // Active nearest line
+ "useStyle(DROP_ZONE_ACTIVE), useStyle(DROP_PREVIEW), drawLine(0,0,240,0)",
+
+ // Preview of the dropped rectangle
+ "useStyle(DROP_PREVIEW), drawRect(0,-40,105,40)");
+
+ // Without drag bounds it should be identical except no preview
+ // rectangle
+ dragInto(true,
+ new Rect(0, 0, 0, 0), // Invalid
+ new Point(30, -10), 0, -1,
+ "useStyle(DROP_ZONE_ACTIVE), useStyle(DROP_PREVIEW), drawLine(0,0,240,0)");
+ }
+
+ public void testDragInVerticalBottom() {
+ dragInto(true,
+ // Bounds of the dragged item
+ new Rect(0, 0, 105, 80),
+ // Drag point
+ new Point(30, 500),
+ // Expected insert location
+ 4,
+ // Not dragging one of the existing children
+ -1,
+ // Bounds rectangle
+ "useStyle(DROP_RECIPIENT), drawRect(Rect[0,0,240,480])",
+
+ // Drop zones
+ "useStyle(DROP_ZONE), drawLine(0,0,240,0), drawLine(0,90,240,90), "
+ + "drawLine(0,190,240,190), drawLine(0,290,240,290), drawLine(0,381,240,381), ",
+
+ // Active nearest line
+ "useStyle(DROP_ZONE_ACTIVE), useStyle(DROP_PREVIEW), drawLine(0,381,240,381)",
+
+ // Preview of the dropped rectangle
+ "useStyle(DROP_PREVIEW), drawRect(0,381,105,461)");
+
+ // Check without bounds too
+ dragInto(true, new Rect(0, 0, 105, 80), new Point(30, 500), 4, -1,
+ "useStyle(DROP_PREVIEW), drawRect(0,381,105,461)");
+ }
+
+ public void testDragInVerticalMiddle() {
+ dragInto(true,
+ // Bounds of the dragged item
+ new Rect(0, 0, 105, 80),
+ // Drag point
+ new Point(0, 170),
+ // Expected insert location
+ 2,
+ // Not dragging one of the existing children
+ -1,
+ // Bounds rectangle
+ "useStyle(DROP_RECIPIENT), drawRect(Rect[0,0,240,480])",
+
+ // Drop zones
+ "useStyle(DROP_ZONE), drawLine(0,0,240,0), drawLine(0,90,240,90), "
+ + "drawLine(0,190,240,190), drawLine(0,290,240,290)",
+
+ // Active nearest line
+ "useStyle(DROP_ZONE_ACTIVE), useStyle(DROP_PREVIEW), drawLine(0,190,240,190)",
+
+ // Preview of the dropped rectangle
+ "useStyle(DROP_PREVIEW), drawRect(0,150,105,230)");
+
+ // Check without bounds too
+ dragInto(true, new Rect(0, 0, 105, 80), new Point(0, 170), 2, -1,
+ "useStyle(DROP_PREVIEW), drawRect(0,150,105,230)");
+ }
+
+ public void testDragInVerticalMiddleSelfPos() {
+ // Drag the 2nd button, down to the position between 3rd and 4th
+ dragInto(true,
+ // Bounds of the dragged item
+ new Rect(0, 100, 100, 80),
+ // Drag point
+ new Point(0, 250),
+ // Expected insert location
+ 2,
+ // Dragging 1st item
+ 1,
+ // Bounds rectangle
+
+ "useStyle(DROP_RECIPIENT), drawRect(Rect[0,0,240,480])",
+
+ // Drop zones - these are different because we exclude drop
+ // zones around the
+ // dragged item itself (it doesn't make sense to insert directly
+ // before or after
+ // myself
+ "useStyle(DROP_ZONE), drawLine(0,0,240,0), drawLine(0,290,240,290), "
+ + "drawLine(0,381,240,381)",
+
+ // Preview line along insert axis
+ "useStyle(DROP_ZONE_ACTIVE), useStyle(DROP_PREVIEW), drawLine(0,290,240,290)",
+
+ // Preview of dropped rectangle
+ "useStyle(DROP_PREVIEW), drawRect(0,250,100,330)");
+
+ // Test dropping on self (no position change):
+ dragInto(true,
+ // Bounds of the dragged item
+ new Rect(0, 100, 100, 80),
+ // Drag point
+ new Point(0, 210),
+ // Expected insert location
+ 1,
+ // Dragging from same pos
+ 1,
+ // Bounds rectangle
+ "useStyle(DROP_RECIPIENT), drawRect(Rect[0,0,240,480])",
+
+ // Drop zones - these are different because we exclude drop
+ // zones around the
+ // dragged item itself (it doesn't make sense to insert directly
+ // before or after
+ // myself
+ "useStyle(DROP_ZONE), drawLine(0,0,240,0), drawLine(0,290,240,290), "
+ + "drawLine(0,381,240,381)",
+
+ // No active nearest line when you're over the self pos!
+
+ // Preview of the dropped rectangle
+ "useStyle(DROP_ZONE_ACTIVE), useStyle(DROP_PREVIEW), drawRect(0,100,100,180)");
+ }
+
+ public void testDragToLastPosition() {
+ // Drag a button to the last position -- and confirm that the preview rectangle
+ // is now shown midway between the second to last and last positions, but fully
+ // below the drop zone line:
+ dragInto(true,
+ // Bounds of the dragged item
+ new Rect(0, 100, 100, 80),
+ // Drag point
+ new Point(0, 400),
+ // Expected insert location
+ 3,
+ // Dragging 1st item
+ 1,
+
+ // Bounds rectangle
+ "useStyle(DROP_RECIPIENT), drawRect(Rect[0,0,240,480])",
+
+ // Drop Zones
+ "useStyle(DROP_ZONE), drawLine(0,0,240,0), drawLine(0,290,240,290), " +
+ "drawLine(0,381,240,381), ",
+
+ // Active Drop Zone
+ "useStyle(DROP_ZONE_ACTIVE), useStyle(DROP_PREVIEW), drawLine(0,381,240,381)",
+
+ // Drop Preview
+ "useStyle(DROP_PREVIEW), drawRect(0,381,100,461)");
+ }
+
+ // Left to test:
+ // Check inserting at last pos with multiple children
+ // Check inserting with no bounds rectangle for dragged element
+}