Home | History | Annotate | Download | only in grid
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.ide.common.layout.grid;
     17 
     18 import static com.android.SdkConstants.ANDROID_URI;
     19 import static com.android.SdkConstants.ATTR_COLUMN_COUNT;
     20 import static com.android.SdkConstants.ATTR_LAYOUT_COLUMN;
     21 import static com.android.SdkConstants.ATTR_LAYOUT_COLUMN_SPAN;
     22 import static com.android.SdkConstants.ATTR_LAYOUT_ROW;
     23 import static com.android.SdkConstants.FQCN_BUTTON;
     24 
     25 import com.android.ide.common.api.INode;
     26 import com.android.ide.common.api.Rect;
     27 import com.android.ide.common.layout.LayoutTestBase;
     28 import com.android.ide.common.layout.TestNode;
     29 import com.android.ide.common.layout.grid.GridModel.ViewData;
     30 
     31 import java.util.Arrays;
     32 import java.util.Collections;
     33 
     34 
     35 @SuppressWarnings("javadoc")
     36 public class GridModelTest extends LayoutTestBase {
     37     public void testRemoveFlag() {
     38         assertEquals("left", GridModel.removeFlag("top", "top|left"));
     39         assertEquals("left", GridModel.removeFlag("top", "top | left"));
     40         assertEquals("top", GridModel.removeFlag("left", "top|left"));
     41         assertEquals("top", GridModel.removeFlag("left", "top | left"));
     42         assertEquals("left | center", GridModel.removeFlag("top", "top | left | center"));
     43         assertEquals(null, GridModel.removeFlag("top", "top"));
     44     }
     45 
     46     public void testReadModel1() {
     47         TestNode targetNode = TestNode.create("android.widget.GridLayout").id("@+id/GridLayout1")
     48                 .bounds(new Rect(0, 0, 240, 480)).set(ANDROID_URI, ATTR_COLUMN_COUNT, "3");
     49 
     50         GridModel model = GridModel.get(null, targetNode, null);
     51         assertEquals(3, model.declaredColumnCount);
     52         assertEquals(1, model.actualColumnCount);
     53         assertEquals(1, model.actualRowCount);
     54 
     55         targetNode.add(TestNode.create(FQCN_BUTTON).id("@+id/Button1"));
     56         targetNode.add(TestNode.create(FQCN_BUTTON).id("@+id/Button2"));
     57         targetNode.add(TestNode.create(FQCN_BUTTON).id("@+id/Button3"));
     58         targetNode.add(TestNode.create(FQCN_BUTTON).id("@+id/Button4"));
     59 
     60         model = GridModel.get(null, targetNode, null);
     61         assertEquals(3, model.declaredColumnCount);
     62         assertEquals(3, model.actualColumnCount);
     63         assertEquals(2, model.actualRowCount);
     64     }
     65 
     66     public void testSplitColumn() {
     67         TestNode targetNode = TestNode.create("android.widget.GridLayout").id("@+id/GridLayout1")
     68                 .bounds(new Rect(0, 0, 240, 480)).set(ANDROID_URI, ATTR_COLUMN_COUNT, "3");
     69         TestNode b1 = TestNode.create(FQCN_BUTTON).id("@+id/Button1");
     70         TestNode b2 = TestNode.create(FQCN_BUTTON).id("@+id/Button2");
     71         TestNode b3 = TestNode.create(FQCN_BUTTON).id("@+id/Button3");
     72         TestNode b4 = TestNode.create(FQCN_BUTTON).id("@+id/Button4");
     73         targetNode.add(b1);
     74         targetNode.add(b2);
     75         targetNode.add(b3);
     76         targetNode.add(b4);
     77         b4.setAttribute(ANDROID_URI, ATTR_LAYOUT_COLUMN_SPAN, "2");
     78 
     79         GridModel model = GridModel.get(new LayoutTestBase.TestRulesEngine(targetNode.getFqcn()),
     80                 targetNode, null);
     81         assertEquals(3, model.declaredColumnCount);
     82         assertEquals(3, model.actualColumnCount);
     83         assertEquals(2, model.actualRowCount);
     84 
     85         model.applyPositionAttributes();
     86         assertEquals("0", b1.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN));
     87         assertEquals("0", b1.getStringAttr(ANDROID_URI, ATTR_LAYOUT_ROW));
     88 
     89         assertEquals("1", b2.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN));
     90         assertEquals("0", b2.getStringAttr(ANDROID_URI, ATTR_LAYOUT_ROW));
     91 
     92         assertEquals("2", b3.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN));
     93         assertEquals("0", b3.getStringAttr(ANDROID_URI, ATTR_LAYOUT_ROW));
     94 
     95         assertEquals("0", b4.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN));
     96         assertEquals("1", b4.getStringAttr(ANDROID_URI, ATTR_LAYOUT_ROW));
     97         assertEquals("2", b4.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN_SPAN));
     98 
     99         model.splitColumn(1, false /*insertMarginColumn*/, 100 /*columnWidthDp*/, 300 /* x */);
    100         model.applyPositionAttributes();
    101 
    102         assertEquals(4, model.declaredColumnCount);
    103         assertEquals(4, model.actualColumnCount);
    104         assertEquals(2, model.actualRowCount);
    105 
    106         assertEquals("0", b1.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN));
    107         assertEquals("0", b1.getStringAttr(ANDROID_URI, ATTR_LAYOUT_ROW));
    108 
    109         assertEquals("1", b2.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN));
    110         assertEquals("2", b2.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN_SPAN));
    111         assertEquals("0", b2.getStringAttr(ANDROID_URI, ATTR_LAYOUT_ROW));
    112 
    113         assertEquals("3", b3.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN));
    114         assertEquals("0", b3.getStringAttr(ANDROID_URI, ATTR_LAYOUT_ROW));
    115 
    116         assertEquals("0", b4.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN));
    117         assertEquals("1", b4.getStringAttr(ANDROID_URI, ATTR_LAYOUT_ROW));
    118         assertEquals("3", b4.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN_SPAN));
    119     }
    120 
    121     public void testDeletion1() {
    122         String xml =
    123             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    124             "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    125             "    android:layout_width=\"match_parent\"\n" +
    126             "    android:layout_height=\"match_parent\"\n" +
    127             "    android:columnCount=\"4\" >\n" +
    128             "\n" +
    129             "    <Button\n" +
    130             "        android:id=\"@+id/button1\"\n" +
    131             "        android:layout_column=\"1\"\n" +
    132             "        android:layout_gravity=\"left|top\"\n" +
    133             "        android:layout_row=\"1\"\n" +
    134             "        android:text=\"Button\" />\n" +
    135             "\n" +
    136             "    <TextView\n" +
    137             "        android:id=\"@+id/TextView1\"\n" +
    138             "        android:layout_column=\"3\"\n" +
    139             "        android:layout_gravity=\"left|top\"\n" +
    140             "        android:layout_row=\"1\"\n" +
    141             "        android:text=\"Text\" />\n" +
    142             "\n" +
    143             "    <Space\n" +
    144             "        android:id=\"@+id/wspace1\"\n" +
    145             "        android:layout_width=\"21dp\"\n" +
    146             "        android:layout_height=\"1dp\"\n" +
    147             "        android:layout_column=\"0\"\n" +
    148             "        android:layout_row=\"0\" />\n" +
    149             "\n" +
    150             "    <Space\n" +
    151             "        android:id=\"@+id/hspace1\"\n" +
    152             "        android:layout_width=\"1dp\"\n" +
    153             "        android:layout_height=\"55dp\"\n" +
    154             "        android:layout_column=\"0\"\n" +
    155             "        android:layout_row=\"0\" />\n" +
    156             "\n" +
    157             "    <Space\n" +
    158             "        android:id=\"@+id/wspace2\"\n" +
    159             "        android:layout_width=\"10dp\"\n" +
    160             "        android:layout_height=\"1dp\"\n" +
    161             "        android:layout_column=\"2\"\n" +
    162             "        android:layout_row=\"0\" />\n" +
    163             "\n" +
    164             "</GridLayout>";
    165 
    166         TestNode targetNode = TestNode.createFromXml(xml);
    167         assertNotNull(targetNode);
    168 
    169         TestNode button1 = TestNode.findById(targetNode, "@+id/button1");
    170         TestNode textView1 = TestNode.findById(targetNode, "@+id/TextView1");
    171         TestNode wspace1 = TestNode.findById(targetNode, "@+id/wspace1");
    172         TestNode wspace2 = TestNode.findById(targetNode, "@+id/wspace2");
    173         TestNode hspace1 = TestNode.findById(targetNode, "@+id/hspace1");
    174         assertNotNull(wspace1);
    175         assertNotNull(hspace1);
    176         assertNotNull(wspace2);
    177         assertNotNull(button1);
    178         assertNotNull(textView1);
    179 
    180         // Assign some bounds such that the model makes sense when merging spacer sizes
    181         // TODO: MAke test utility method to automatically assign half divisions!!
    182         button1.bounds(new Rect(90, 10, 100, 40));
    183         textView1.bounds(new Rect(200, 10, 100, 40));
    184         wspace1.bounds(new Rect(0, 0, 90, 1));
    185         wspace1.bounds(new Rect(190, 0, 10, 1));
    186         hspace1.bounds(new Rect(0, 0, 1, 10));
    187 
    188         GridModel model = GridModel.get(new LayoutTestBase.TestRulesEngine(targetNode.getFqcn()),
    189                 targetNode, null);
    190         assertEquals(4, model.declaredColumnCount);
    191         assertEquals(4, model.actualColumnCount);
    192         assertEquals(2, model.actualRowCount);
    193 
    194         ViewData textViewData = model.getView(textView1);
    195         assertEquals(3, textViewData.column);
    196 
    197         // Delete button1
    198         button1.getParent().removeChild(button1);
    199         model.onDeleted(Arrays.<INode>asList(button1));
    200         model.applyPositionAttributes();
    201 
    202         assertEquals(2, model.declaredColumnCount);
    203         assertEquals(2, model.actualColumnCount);
    204         assertEquals(2, model.actualRowCount);
    205         assertNotNull(model.getView(textView1));
    206         assertNull(model.getView(button1));
    207 
    208         assertEquals(
    209                 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    210                 "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    211                 "    android:layout_width=\"match_parent\"\n" +
    212                 "    android:layout_height=\"match_parent\"\n" +
    213                 "    android:columnCount=\"2\">\n" +
    214                 "\n" +
    215                 "    <TextView\n" +
    216                 "        android:id=\"@+id/TextView1\"\n" +
    217                 "        android:layout_column=\"1\"\n" +
    218                 "        android:layout_gravity=\"left|top\"\n" +
    219                 "        android:layout_row=\"1\"\n" +
    220                 "        android:text=\"Text\">\n" +
    221                 "    </TextView>\n" +
    222                 "\n" +
    223                 "    <Space\n" +
    224                 "        android:id=\"@+id/wspace1\"\n" +
    225                 "        android:layout_width=\"66dp\"\n" +
    226                 "        android:layout_height=\"1dp\"\n" +
    227                 "        android:layout_column=\"0\"\n" +
    228                 "        android:layout_row=\"0\">\n" +
    229                 "    </Space>\n" +
    230                 "\n" +
    231                 "    <Space\n" +
    232                 "        android:id=\"@+id/hspace1\"\n" +
    233                 "        android:layout_width=\"1dp\"\n" +
    234                 "        android:layout_height=\"55dp\"\n" +
    235                 "        android:layout_column=\"0\"\n" +
    236                 "        android:layout_row=\"0\">\n" +
    237                 "    </Space>\n" +
    238                 "\n" +
    239                 "</GridLayout>", TestNode.toXml(targetNode));
    240 
    241         // Delete textView1
    242 
    243         textView1.getParent().removeChild(textView1);
    244         model.onDeleted(Arrays.<INode>asList(textView1));
    245         model.applyPositionAttributes();
    246 
    247         assertEquals(2, model.declaredColumnCount);
    248         assertEquals(0, model.actualColumnCount);
    249         assertEquals(0, model.actualRowCount);
    250         assertNull(model.getView(textView1));
    251         assertNull(model.getView(button1));
    252 
    253         assertEquals(
    254                 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    255                 "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    256                 "    android:layout_width=\"match_parent\"\n" +
    257                 "    android:layout_height=\"match_parent\"\n" +
    258                 "    android:columnCount=\"0\">\n" +
    259                 "\n" +
    260                 "</GridLayout>", TestNode.toXml(targetNode));
    261 
    262     }
    263 
    264     public void testDelete2() throws Exception {
    265         String xml =
    266             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    267             "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    268             "    android:layout_width=\"match_parent\"\n" +
    269             "    android:layout_height=\"match_parent\"\n" +
    270             "    android:columnCount=\"4\"\n" +
    271             "    android:orientation=\"vertical\" >\n" +
    272             "\n" +
    273             "    <Button\n" +
    274             "        android:id=\"@+id/button1\"\n" +
    275             "        android:layout_column=\"0\"\n" +
    276             "        android:layout_columnSpan=\"2\"\n" +
    277             "        android:layout_gravity=\"left|top\"\n" +
    278             "        android:layout_row=\"0\"\n" +
    279             "        android:text=\"Button1\" />\n" +
    280             "\n" +
    281             "    <Button\n" +
    282             "        android:id=\"@+id/button3\"\n" +
    283             "        android:layout_column=\"1\"\n" +
    284             "        android:layout_columnSpan=\"2\"\n" +
    285             "        android:layout_gravity=\"left|top\"\n" +
    286             "        android:layout_row=\"1\"\n" +
    287             "        android:text=\"Button2\" />\n" +
    288             "\n" +
    289             "    <Button\n" +
    290             "        android:id=\"@+id/button2\"\n" +
    291             "        android:layout_column=\"2\"\n" +
    292             "        android:layout_gravity=\"left|top\"\n" +
    293             "        android:layout_row=\"0\"\n" +
    294             "        android:text=\"Button3\" />\n" +
    295             "\n" +
    296             "    <Space\n" +
    297             "        android:id=\"@+id/spacer_177\"\n" +
    298             "        android:layout_width=\"46dp\"\n" +
    299             "        android:layout_height=\"1dp\"\n" +
    300             "        android:layout_column=\"0\"\n" +
    301             "        android:layout_row=\"0\" />\n" +
    302             "\n" +
    303             "</GridLayout>";
    304 
    305         TestNode targetNode = TestNode.createFromXml(xml);
    306         assertNotNull(targetNode);
    307 
    308         TestNode button1 = TestNode.findById(targetNode, "@+id/button1");
    309         TestNode button2 = TestNode.findById(targetNode, "@+id/button2");
    310         TestNode button3 = TestNode.findById(targetNode, "@+id/button3");
    311         TestNode hspacer = TestNode.findById(targetNode, "@+id/spacer_177");
    312         assertNotNull(button1);
    313         assertNotNull(button2);
    314         assertNotNull(button3);
    315         assertNotNull(hspacer);
    316 
    317         // Assign some bounds such that the model makes sense when merging spacer sizes
    318         // TODO: MAke test utility method to automatically assign half divisions!!
    319         button1.bounds(new Rect(0, 0, 100, 40));
    320         button2.bounds(new Rect(100, 0, 100, 40));
    321         button3.bounds(new Rect(50, 40, 100, 40));
    322         hspacer.bounds(new Rect(0, 0, 50, 1));
    323 
    324         GridModel model = GridModel.get(new LayoutTestBase.TestRulesEngine(targetNode.getFqcn()),
    325                 targetNode, null);
    326         assertEquals(4, model.declaredColumnCount);
    327         assertEquals(3, model.actualColumnCount);
    328         assertEquals(2, model.actualRowCount);
    329 
    330         ViewData buttonData = model.getView(button1);
    331         assertEquals(0, buttonData.column);
    332 
    333         // Delete button1
    334         button1.getParent().removeChild(button1);
    335         model.onDeleted(Arrays.<INode>asList(button1));
    336         model.applyPositionAttributes();
    337 
    338         assertEquals(3, model.declaredColumnCount);
    339         assertEquals(3, model.actualColumnCount);
    340         assertEquals(2, model.actualRowCount);
    341         assertNull(model.getView(button1));
    342 
    343         assertEquals(
    344                 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    345                 "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    346                 "    android:layout_width=\"match_parent\"\n" +
    347                 "    android:layout_height=\"match_parent\"\n" +
    348                 "    android:columnCount=\"3\"\n" +
    349                 "    android:orientation=\"vertical\">\n" +
    350                 "\n" +
    351                 "    <Button\n" +
    352                 "        android:id=\"@+id/button3\"\n" +
    353                 "        android:layout_column=\"1\"\n" +
    354                 "        android:layout_columnSpan=\"2\"\n" +
    355                 "        android:layout_gravity=\"left|top\"\n" +
    356                 "        android:layout_row=\"1\"\n" +
    357                 "        android:text=\"Button2\">\n" +
    358                 "    </Button>\n" +
    359                 "\n" +
    360                 "    <Button\n" +
    361                 "        android:id=\"@+id/button2\"\n" +
    362                 "        android:layout_column=\"2\"\n" +
    363                 "        android:layout_gravity=\"left|top\"\n" +
    364                 "        android:layout_row=\"0\"\n" +
    365                 "        android:text=\"Button3\">\n" +
    366                 "    </Button>\n" +
    367                 "\n" +
    368                 "    <Space\n" +
    369                 "        android:id=\"@+id/spacer_177\"\n" +
    370                 "        android:layout_width=\"46dp\"\n" +
    371                 "        android:layout_height=\"1dp\"\n" +
    372                 "        android:layout_column=\"0\"\n" +
    373                 "        android:layout_row=\"0\">\n" +
    374                 "    </Space>\n" +
    375                 "\n" +
    376                 "</GridLayout>", TestNode.toXml(targetNode));
    377     }
    378 
    379     public void testDelete3_INCOMPLETE() throws Exception {
    380         String xml =
    381             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    382             "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    383             "  android:layout_width=\"match_parent\" android:layout_height=\"match_parent\"\n" +
    384             "  android:columnCount=\"6\">\n" +
    385             "  <Button android:id=\"@+id/button1\" android:layout_column=\"1\"\n" +
    386             "    android:layout_columnSpan=\"2\" android:layout_gravity=\"left|top\"\n" +
    387             "    android:layout_row=\"1\" android:layout_rowSpan=\"2\" android:text=\"Button\" />\n" +
    388             "  <TextView android:id=\"@+id/TextView1\" android:layout_column=\"4\"\n" +
    389             "    android:layout_gravity=\"left|top\" android:layout_row=\"1\"\n" +
    390             "    android:text=\"Text\" />\n" +
    391             "  <Button android:id=\"@+id/button3\" android:layout_column=\"5\"\n" +
    392             "    android:layout_gravity=\"left|top\" android:layout_row=\"2\"\n" +
    393             "    android:layout_rowSpan=\"2\" android:text=\"Button\" />\n" +
    394             "  <Button android:id=\"@+id/button2\" android:layout_column=\"2\"\n" +
    395             "    android:layout_columnSpan=\"3\" android:layout_gravity=\"left|top\"\n" +
    396             "    android:layout_row=\"4\" android:text=\"Button\" />\n" +
    397             "  <Space android:id=\"@+id/wspace1\" android:layout_width=\"21dp\"\n" +
    398             "    android:layout_height=\"1dp\" android:layout_column=\"0\"\n" +
    399             "    android:layout_row=\"0\" />\n" +
    400             "  <Space android:id=\"@+id/spacer_630\" android:layout_width=\"1dp\"\n" +
    401             "    android:layout_height=\"55dp\" android:layout_column=\"0\"\n" +
    402             "    android:layout_row=\"0\" />\n" +
    403             "  <Space android:id=\"@+id/wspace2\" android:layout_width=\"10dp\"\n" +
    404             "    android:layout_height=\"1dp\" android:layout_column=\"3\"\n" +
    405             "    android:layout_row=\"0\" />\n" +
    406             "  <Space android:id=\"@+id/spacer_619\" android:layout_width=\"59dp\"\n" +
    407             "    android:layout_height=\"1dp\" android:layout_column=\"1\"\n" +
    408             "    android:layout_row=\"0\" />\n" +
    409             "  <Space android:id=\"@+id/spacer_102\" android:layout_width=\"1dp\"\n" +
    410             "    android:layout_height=\"30dp\" android:layout_column=\"0\"\n" +
    411             "    android:layout_row=\"1\" />\n" +
    412             "  <Space android:id=\"@+id/spacer_109\" android:layout_width=\"1dp\"\n" +
    413             "    android:layout_height=\"28dp\" android:layout_column=\"0\"\n" +
    414             "    android:layout_row=\"2\" />\n" +
    415             "  <Space android:id=\"@+id/spacer_146\" android:layout_width=\"1dp\"\n" +
    416             "    android:layout_height=\"70dp\" android:layout_column=\"0\"\n" +
    417             "    android:layout_row=\"3\" />\n" +
    418             "</GridLayout>";
    419         TestNode targetNode = TestNode.createFromXml(xml);
    420         assertNotNull(targetNode);
    421         targetNode.assignBounds(
    422             "android.widget.GridLayout [0,109,480,800] <GridLayout>\n" +
    423             "    android.widget.Button [32,83,148,155] <Button> @+id/button1\n" +
    424             "    android.widget.TextView [163,83,205,109] <TextView> @+id/TextView1\n" +
    425             "    android.widget.Button [237,128,353,200] <Button> @+id/button3\n" +
    426             "    android.widget.Button [121,275,237,347] <Button> @+id/button2\n" +
    427             "    android.widget.Space [0,0,32,2] <Space> @+id/wspace1\n" +
    428             "    android.widget.Space [0,0,2,83] <Space> @+id/spacer_630\n" +
    429             "    android.widget.Space [148,0,163,2] <Space> @+id/wspace2\n" +
    430             "    android.widget.Space [32,0,121,2] <Space> @+id/spacer_619\n" +
    431             "    android.widget.Space [0,83,2,128] <Space> @+id/spacer_102\n" +
    432             "    android.widget.Space [0,128,2,170] <Space> @+id/spacer_109\n" +
    433             "    android.widget.Space [0,170,2,275] <Space> @+id/spacer_146\n");
    434         TestNode layout = TestNode.findById(targetNode, "@+id/GridLayout1");
    435         //TestNode button1 = TestNode.findById(targetNode, "@+id/button1");
    436         TestNode button2 = TestNode.findById(targetNode, "@+id/button2");
    437         TestNode button3 = TestNode.findById(targetNode, "@+id/button3");
    438 
    439         GridModel model = GridModel.get(new LayoutTestBase.TestRulesEngine(targetNode.getFqcn()),
    440                 targetNode, null);
    441         assertEquals(6, model.declaredColumnCount);
    442         assertEquals(6, model.actualColumnCount);
    443         assertEquals(5, model.actualRowCount);
    444 
    445         // TODO: Delete button2 or button3: bad stuff happens visually
    446         fail("Finish test");
    447     }
    448 
    449     public void testDelete4_INCOMPLETE() {
    450         String xml = "" +
    451             "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    452             "  xmlns:tools=\"http://schemas.android.com/tools\" " +
    453             "  android:layout_width=\"match_parent\"\n" +
    454             "  android:layout_height=\"match_parent\" android:columnCount=\"3\"\n" +
    455             "  android:gravity=\"center\" android:text=\"@string/hello_world\"\n" +
    456             "  tools:context=\".MainActivity\">\n" +
    457             "  <Button android:id=\"@+id/button2\" android:layout_column=\"1\"\n" +
    458             "    android:layout_columnSpan=\"2\" android:layout_gravity=\"left|top\"\n" +
    459             "    android:layout_row=\"1\" android:text=\"Button\" />\n" +
    460             "  <Button android:id=\"@+id/button1\" android:layout_column=\"1\"\n" +
    461             "    android:layout_columnSpan=\"2\" android:layout_gravity=\"left|top\"\n" +
    462             "    android:layout_row=\"3\" android:text=\"Button\" />\n" +
    463             "  <Space android:id=\"@+id/spacer_167\" android:layout_width=\"74dp\"\n" +
    464             "    android:layout_height=\"1dp\" android:layout_column=\"0\"\n" +
    465             "    android:layout_row=\"0\" />\n" +
    466             "  <Space android:id=\"@+id/spacer_133\" android:layout_width=\"1dp\"\n" +
    467             "    android:layout_height=\"21dp\" android:layout_column=\"0\"\n" +
    468             "    android:layout_row=\"0\" />\n" +
    469             "  <Space android:id=\"@+id/spacer_142\" android:layout_width=\"1dp\"\n" +
    470             "    android:layout_height=\"26dp\" android:layout_column=\"0\"\n" +
    471             "    android:layout_row=\"2\" />\n" +
    472             "  <Space android:id=\"@+id/spacer_673\" android:layout_width=\"43dp\"\n" +
    473             "    android:layout_height=\"1dp\" android:layout_column=\"1\"\n" +
    474             "    android:layout_row=\"0\" />\n" +
    475             "  <Space android:id=\"@+id/spacer_110\" android:layout_width=\"202dp\"\n" +
    476             "    android:layout_height=\"15dp\" android:layout_column=\"2\" />\n" +
    477             "</GridLayout>";
    478         TestNode targetNode = TestNode.createFromXml(xml);
    479         assertNotNull(targetNode);
    480         targetNode.assignBounds(
    481                 "android.widget.GridLayout [0,109,480,800] <GridLayout>\n" +
    482                 "    android.widget.Button [111,32,227,104] <Button> @+id/button2\n" +
    483                 "    android.widget.Button [111,143,227,215] <Button> @+id/button1\n" +
    484                 "    android.widget.Space [0,0,111,2] <Space> @+id/spacer_167\n" +
    485                 "    android.widget.Space [0,0,2,32] <Space> @+id/spacer_133\n" +
    486                 "    android.widget.Space [0,104,2,143] <Space> @+id/spacer_142\n" +
    487                 "    android.widget.Space [111,0,176,2] <Space> @+id/spacer_673\n" +
    488                 "    android.widget.Space [176,668,479,691] <Space> @+id/spacer_110");
    489 
    490 
    491         // Remove button2; button1 shifts to the right!
    492 
    493         //TestNode layout = TestNode.findById(targetNode, "@+id/GridLayout1");
    494         //TestNode button1 = TestNode.findById(targetNode, "@+id/button1");
    495         TestNode button2 = TestNode.findById(targetNode, "@+id/button2");
    496         TestNode button3 = TestNode.findById(targetNode, "@+id/button3");
    497         assertEquals(new Rect(111, 32, 227 - 111, 104 - 32), button2.getBounds());
    498 
    499         GridModel model = GridModel.get(new LayoutTestBase.TestRulesEngine(targetNode.getFqcn()),
    500                 targetNode, null);
    501         assertEquals(3, model.declaredColumnCount);
    502         assertEquals(3, model.actualColumnCount);
    503         assertEquals(4, model.actualRowCount);
    504         fail("Finish test");
    505     }
    506 
    507     public void testDelete5_INCOMPLETE() {
    508         String xml =
    509                 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    510                 "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    511                 "  android:id=\"@+id/GridLayout1\" android:layout_width=\"match_parent\"\n" +
    512                 "  android:layout_height=\"match_parent\" android:columnCount=\"4\"\n" +
    513                 "  android:orientation=\"vertical\">\n" +
    514                 "  <Button android:id=\"@+id/button1\" android:layout_column=\"0\"\n" +
    515                 "    android:layout_gravity=\"center_horizontal|bottom\"\n" +
    516                 "    android:layout_row=\"0\" android:text=\"Button\" />\n" +
    517                 "  <Space android:layout_width=\"66dp\" android:layout_height=\"1dp\"\n" +
    518                 "    android:layout_column=\"0\" android:layout_row=\"0\" />\n" +
    519                 "  <Button android:id=\"@+id/button3\" android:layout_column=\"2\"\n" +
    520                 "    android:layout_gravity=\"left|bottom\" android:layout_row=\"0\"\n" +
    521                 "    android:text=\"Button\" />\n" +
    522                 "  <Button android:id=\"@+id/button2\" android:layout_column=\"3\"\n" +
    523                 "    android:layout_columnSpan=\"2\" android:layout_gravity=\"left|bottom\"\n" +
    524                 "    android:layout_row=\"0\" android:text=\"Button\" />\n" +
    525                 "  <Space android:id=\"@+id/spacer_109\" android:layout_width=\"51dp\"\n" +
    526                 "    android:layout_height=\"1dp\" android:layout_column=\"1\"\n" +
    527                 "    android:layout_row=\"0\" />\n" +
    528                 "  <Space android:layout_width=\"129dp\" android:layout_height=\"1dp\"\n" +
    529                 "    android:layout_column=\"2\" android:layout_row=\"0\" />\n" +
    530                 "  <Space android:layout_width=\"62dp\" android:layout_height=\"1dp\"\n" +
    531                 "    android:layout_column=\"3\" android:layout_row=\"0\" />\n" +
    532                 "  <Space android:id=\"@+id/spacer_397\" android:layout_width=\"1dp\"\n" +
    533                 "    android:layout_height=\"103dp\" android:layout_column=\"0\"\n" +
    534                 "    android:layout_row=\"0\" />\n" +
    535                 "  <Space android:layout_width=\"1dp\" android:layout_height=\"356dp\"\n" +
    536                 "    android:layout_column=\"0\" android:layout_row=\"1\" />\n" +
    537                 "</GridLayout>";
    538         TestNode targetNode = TestNode.createFromXml(xml);
    539         assertNotNull(targetNode);
    540 
    541         targetNode.assignBounds(
    542                 "android.widget.GridLayout [0,109,480,800] <GridLayout> @+id/GridLayout1\n" +
    543                 "    android.widget.Button [0,83,116,155] <Button> @+id/button1\n" +
    544                 "    android.widget.Space [0,0,99,2] <Space>\n" +
    545                 "    android.widget.Button [193,83,309,155] <Button> @+id/button3\n" +
    546                 "    android.widget.Button [387,83,503,155] <Button> @+id/button2\n" +
    547                 "    android.widget.Space [116,0,193,2] <Space> @+id/spacer_109\n" +
    548                 "    android.widget.Space [193,0,387,2] <Space>\n" +
    549                 "    android.widget.Space [387,0,480,2] <Space>\n" +
    550                 "    android.widget.Space [0,0,2,155] <Space> @+id/spacer_397\n" +
    551                 "    android.widget.Space [0,155,2,689] <Space>");
    552 
    553         // Delete button3. This causes an array out of bounds exception currently.
    554 
    555         //TestNode layout = TestNode.findById(targetNode, "@+id/GridLayout1");
    556         //TestNode button1 = TestNode.findById(targetNode, "@+id/button1");
    557         TestNode button2 = TestNode.findById(targetNode, "@+id/button2");
    558         TestNode button3 = TestNode.findById(targetNode, "@+id/button3");
    559         assertEquals(new Rect(387, 83, 503 - 387, 155- 83), button2.getBounds());
    560 
    561         GridModel model = GridModel.get(new LayoutTestBase.TestRulesEngine(targetNode.getFqcn()),
    562                 targetNode, null);
    563         assertEquals(4, model.declaredColumnCount);
    564         assertEquals(4, model.actualColumnCount);
    565         assertEquals(2, model.actualRowCount);
    566 
    567         model.onDeleted(Collections.<INode>singletonList(button3));
    568         // Exception fixed; todo: Test that the model updates are correct.
    569 
    570         assertEquals(3, model.declaredColumnCount);
    571         assertEquals(3, model.actualColumnCount);
    572         assertEquals(2, model.actualRowCount);
    573 
    574         fail("Finish test");
    575     }
    576 
    577     public void testInsert1() throws Exception {
    578         String xml =
    579             "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    580             "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    581             "    android:id=\"@+id/GridLayout1\"\n" +
    582             "    android:layout_width=\"match_parent\"\n" +
    583             "    android:layout_height=\"match_parent\"\n" +
    584             "    android:columnCount=\"4\"\n" +
    585             "    android:orientation=\"vertical\" >\n" +
    586             "\n" +
    587             "    <Button\n" +
    588             "        android:id=\"@+id/button1\"\n" +
    589             "        android:layout_column=\"0\"\n" +
    590             "        android:layout_columnSpan=\"4\"\n" +
    591             "        android:layout_gravity=\"center_horizontal|bottom\"\n" +
    592             "        android:layout_row=\"0\"\n" +
    593             "        android:text=\"Button\" />\n" +
    594             "\n" +
    595             "    <Button\n" +
    596             "        android:id=\"@+id/button2\"\n" +
    597             "        android:layout_column=\"2\"\n" +
    598             "        android:layout_gravity=\"left|top\"\n" +
    599             "        android:layout_row=\"1\"\n" +
    600             "        android:text=\"Button\" />\n" +
    601             "\n" +
    602             "    <Button\n" +
    603             "        android:id=\"@+id/button3\"\n" +
    604             "        android:layout_column=\"3\"\n" +
    605             "        android:layout_gravity=\"left|top\"\n" +
    606             "        android:layout_row=\"1\"\n" +
    607             "        android:text=\"Button\" />\n" +
    608             "\n" +
    609             "    <Space\n" +
    610             "        android:id=\"@+id/spacer_393\"\n" +
    611             "        android:layout_width=\"81dp\"\n" +
    612             "        android:layout_height=\"1dp\"\n" +
    613             "        android:layout_column=\"1\"\n" +
    614             "        android:layout_row=\"0\" />\n" +
    615             "\n" +
    616             "    <Space\n" +
    617             "        android:id=\"@+id/spacer_397\"\n" +
    618             "        android:layout_width=\"1dp\"\n" +
    619             "        android:layout_height=\"103dp\"\n" +
    620             "        android:layout_column=\"0\"\n" +
    621             "        android:layout_row=\"0\" />\n" +
    622             "\n" +
    623             "</GridLayout>";
    624 
    625         TestNode targetNode = TestNode.createFromXml(xml);
    626         assertNotNull(targetNode);
    627 
    628         TestNode layout = TestNode.findById(targetNode, "@+id/GridLayout1");
    629         TestNode button1 = TestNode.findById(targetNode, "@+id/button1");
    630         TestNode button2 = TestNode.findById(targetNode, "@+id/button2");
    631         TestNode button3 = TestNode.findById(targetNode, "@+id/button3");
    632         TestNode hspacer = TestNode.findById(targetNode, "@+id/spacer_393");
    633         TestNode vspacer = TestNode.findById(targetNode, "@+id/spacer_397");
    634         assertNotNull(layout);
    635         assertNotNull(button1);
    636         assertNotNull(button2);
    637         assertNotNull(button3);
    638         assertNotNull(hspacer);
    639 
    640         // Obtained by setting ViewHierarchy.DUMP_INFO=true:
    641         layout.bounds(new Rect(0, 109, 480, 800-109));
    642         button1.bounds(new Rect(182, 83, 298-182, 155-83));
    643         button2.bounds(new Rect(124, 155, 240-124, 227-155));
    644         button3.bounds(new Rect(240, 155, 356-240, 227-155));
    645         hspacer.bounds(new Rect(2, 0, 124-2, 2));
    646         vspacer.bounds(new Rect(0, 0, 2, 155));
    647 
    648         GridModel model = GridModel.get(new LayoutTestBase.TestRulesEngine(targetNode.getFqcn()),
    649                 targetNode, null);
    650         assertEquals(4, model.declaredColumnCount);
    651         assertEquals(4, model.actualColumnCount);
    652         assertEquals(2, model.actualRowCount);
    653 
    654 
    655         model.splitColumn(1, false, 21, 32);
    656         int index = model.getInsertIndex(2, 1);
    657         GridModel.ViewData next = model.getView(index);
    658         INode newChild = targetNode.insertChildAt(FQCN_BUTTON, index);
    659         next.applyPositionAttributes();
    660         model.setGridAttribute(newChild, ATTR_LAYOUT_COLUMN, 1);
    661         model.setGridAttribute(newChild, ATTR_LAYOUT_COLUMN_SPAN, 3);
    662     }
    663 
    664     public void testInsert2() throws Exception {
    665         // Drop into a view where there is a centered view: when dropping to the right of
    666         // it (on a row further down), ensure that the row span is increased for the
    667         // non-left-justified centered view which does not horizontally overlap the view
    668         String xml =
    669                 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    670                 "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    671                 "    android:id=\"@+id/GridLayout1\"\n" +
    672                 "    android:layout_width=\"match_parent\"\n" +
    673                 "    android:layout_height=\"match_parent\"\n" +
    674                 "    android:columnCount=\"3\"\n" +
    675                 "    android:orientation=\"vertical\" >\n" +
    676                 "\n" +
    677                 "    <Button\n" +
    678                 "        android:id=\"@+id/button1\"\n" +
    679                 "        android:layout_column=\"0\"\n" +
    680                 "        android:layout_columnSpan=\"3\"\n" +
    681                 "        android:layout_gravity=\"center_horizontal|bottom\"\n" +
    682                 "        android:layout_row=\"0\"\n" +
    683                 "        android:text=\"Button\" />\n" +
    684                 "\n" +
    685                 "    <Button\n" +
    686                 "        android:id=\"@+id/button2\"\n" +
    687                 "        android:layout_column=\"1\"\n" +
    688                 "        android:layout_gravity=\"left|top\"\n" +
    689                 "        android:layout_row=\"1\"\n" +
    690                 "        android:text=\"Button\" />\n" +
    691                 "\n" +
    692                 "    <Button\n" +
    693                 "        android:id=\"@+id/button3\"\n" +
    694                 "        android:layout_column=\"2\"\n" +
    695                 "        android:layout_gravity=\"left|top\"\n" +
    696                 "        android:layout_row=\"1\"\n" +
    697                 "        android:text=\"Button\" />\n" +
    698                 "\n" +
    699                 "    <Space\n" +
    700                 "        android:id=\"@+id/spacer_393\"\n" +
    701                 "        android:layout_width=\"81dp\"\n" +
    702                 "        android:layout_height=\"1dp\"\n" +
    703                 "        android:layout_column=\"0\"\n" +
    704                 "        android:layout_row=\"0\" />\n" +
    705                 "\n" +
    706                 "    \n" +
    707                 "    <Space\n" +
    708                 "        android:id=\"@+id/spacer_397\"\n" +
    709                 "        android:layout_width=\"1dp\"\n" +
    710                 "        android:layout_height=\"103dp\"\n" +
    711                 "        android:layout_column=\"0\"\n" +
    712                 "        android:layout_row=\"0\" />\n" +
    713                 "\n" +
    714                 "    \n" +
    715                 "</GridLayout>";
    716 
    717         TestNode targetNode = TestNode.createFromXml(xml);
    718         assertNotNull(targetNode);
    719 
    720         TestNode layout = TestNode.findById(targetNode, "@+id/GridLayout1");
    721         TestNode button1 = TestNode.findById(targetNode, "@+id/button1");
    722         TestNode button2 = TestNode.findById(targetNode, "@+id/button2");
    723         TestNode button3 = TestNode.findById(targetNode, "@+id/button3");
    724         TestNode hspacer = TestNode.findById(targetNode, "@+id/spacer_393");
    725         TestNode vspacer = TestNode.findById(targetNode, "@+id/spacer_397");
    726         assertNotNull(layout);
    727         assertNotNull(button1);
    728         assertNotNull(button2);
    729         assertNotNull(button3);
    730         assertNotNull(hspacer);
    731 
    732         // Obtained by setting ViewHierarchy.DUMP_INFO=true:
    733         layout.bounds(new Rect(0, 109, 480, 800-109));
    734         button1.bounds(new Rect(182, 83, 298-182, 155-83));
    735         button2.bounds(new Rect(122, 155, 238-122, 227-155));
    736         button3.bounds(new Rect(238, 155, 354-238, 227-155));
    737         hspacer.bounds(new Rect(0, 0, 122, 2));
    738         vspacer.bounds(new Rect(0, 0, 2, 155));
    739 
    740         GridModel model = GridModel.get(new LayoutTestBase.TestRulesEngine(targetNode.getFqcn()),
    741                 targetNode, null);
    742         assertEquals(3, model.declaredColumnCount);
    743         assertEquals(3, model.actualColumnCount);
    744         assertEquals(2, model.actualRowCount);
    745 
    746         ViewData view = model.getView(button1);
    747         assertNotNull(view);
    748         assertEquals(0, view.column);
    749         assertEquals(3, view.columnSpan);
    750         assertEquals("3", view.node.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN_SPAN));
    751 
    752         model.splitColumn(3, false, 53, 318);
    753         assertEquals(0, view.column);
    754         assertEquals(4, view.columnSpan);
    755         assertEquals("4", view.node.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN_SPAN));
    756     }
    757 
    758     public void testInsert3_BROKEN() throws Exception {
    759         // Check that when we insert a new gap column near an existing column, the
    760         // view in that new column does not get moved
    761         String xml =
    762                 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
    763                 "<GridLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
    764                 "    android:id=\"@+id/GridLayout1\"\n" +
    765                 "    android:layout_width=\"match_parent\"\n" +
    766                 "    android:layout_height=\"match_parent\"\n" +
    767                 "    android:columnCount=\"3\"\n" +
    768                 "    android:orientation=\"vertical\" >\n" +
    769                 "\n" +
    770                 "    <Button\n" +
    771                 "        android:id=\"@+id/button1\"\n" +
    772                 "        android:layout_column=\"0\"\n" +
    773                 "        android:layout_columnSpan=\"3\"\n" +
    774                 "        android:layout_gravity=\"center_horizontal|bottom\"\n" +
    775                 "        android:layout_row=\"0\"\n" +
    776                 "        android:text=\"Button\" />\n" +
    777                 "\n" +
    778                 "    <Button\n" +
    779                 "        android:id=\"@+id/button2\"\n" +
    780                 "        android:layout_column=\"1\"\n" +
    781                 "        android:layout_gravity=\"left|top\"\n" +
    782                 "        android:layout_row=\"1\"\n" +
    783                 "        android:text=\"Button\" />\n" +
    784                 "\n" +
    785                 "    <Button\n" +
    786                 "        android:id=\"@+id/button3\"\n" +
    787                 "        android:layout_column=\"2\"\n" +
    788                 "        android:layout_gravity=\"left|top\"\n" +
    789                 "        android:layout_row=\"1\"\n" +
    790                 "        android:text=\"Button\" />\n" +
    791                 "\n" +
    792                 "    <Space\n" +
    793                 "        android:id=\"@+id/spacer_393\"\n" +
    794                 "        android:layout_width=\"81dp\"\n" +
    795                 "        android:layout_height=\"1dp\"\n" +
    796                 "        android:layout_column=\"0\"\n" +
    797                 "        android:layout_row=\"0\" />\n" +
    798                 "\n" +
    799                 "    \n" +
    800                 "    <Space\n" +
    801                 "        android:id=\"@+id/spacer_397\"\n" +
    802                 "        android:layout_width=\"1dp\"\n" +
    803                 "        android:layout_height=\"103dp\"\n" +
    804                 "        android:layout_column=\"0\"\n" +
    805                 "        android:layout_row=\"0\" />\n" +
    806                 "\n" +
    807                 "    \n" +
    808                 "</GridLayout>";
    809 
    810         TestNode targetNode = TestNode.createFromXml(xml);
    811         assertNotNull(targetNode);
    812 
    813         TestNode layout = TestNode.findById(targetNode, "@+id/GridLayout1");
    814         TestNode button1 = TestNode.findById(targetNode, "@+id/button1");
    815         TestNode button2 = TestNode.findById(targetNode, "@+id/button2");
    816         TestNode button3 = TestNode.findById(targetNode, "@+id/button3");
    817         TestNode hspacer = TestNode.findById(targetNode, "@+id/spacer_393");
    818         TestNode vspacer = TestNode.findById(targetNode, "@+id/spacer_397");
    819         assertNotNull(layout);
    820         assertNotNull(button1);
    821         assertNotNull(button2);
    822         assertNotNull(button3);
    823         assertNotNull(hspacer);
    824 
    825         // Obtained by setting ViewHierarchy.DUMP_INFO=true:
    826         layout.bounds(new Rect(0, 109, 480, 800-109));
    827         button1.bounds(new Rect(182, 83, 298-182, 155-83));
    828         button2.bounds(new Rect(122, 155, 238-122, 227-155));
    829         button3.bounds(new Rect(238, 155, 354-238, 227-155));
    830         hspacer.bounds(new Rect(0, 0, 122, 2));
    831         vspacer.bounds(new Rect(0, 0, 2, 155));
    832 
    833         GridModel model = GridModel.get(new LayoutTestBase.TestRulesEngine(targetNode.getFqcn()),
    834                 targetNode, null);
    835         assertEquals(3, model.declaredColumnCount);
    836         assertEquals(3, model.actualColumnCount);
    837         assertEquals(2, model.actualRowCount);
    838 
    839         ViewData view = model.getView(button3);
    840         assertNotNull(view);
    841         assertEquals(2, view.column);
    842         assertEquals(1, view.columnSpan);
    843         assertNull("1", view.node.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN_SPAN));
    844 
    845         model.splitColumn(2, true, 10, 253);
    846         // TODO: Finish this test: Assert that the cells are in the right place
    847         //assertEquals(4, view.column);
    848         //assertEquals(1, view.columnSpan);
    849         //assertEquals("4", view.node.getStringAttr(ANDROID_URI, ATTR_LAYOUT_COLUMN_SPAN));
    850         fail("Finish test");
    851     }
    852 }
    853