1 /* 2 * Copyright (C) 2012 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.relative; 17 18 import static com.android.SdkConstants.ATTR_ID; 19 import static com.android.SdkConstants.ANDROID_URI; 20 21 import com.android.ide.common.api.INode; 22 import com.android.ide.common.layout.BaseViewRule; 23 import com.android.ide.common.layout.TestNode; 24 25 import java.util.Arrays; 26 import java.util.Collections; 27 import java.util.List; 28 29 import junit.framework.TestCase; 30 31 @SuppressWarnings("javadoc") 32 public class DeletionHandlerTest extends TestCase { 33 public void testSimple() { 34 String xml = "" + 35 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 36 "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + 37 " xmlns:tools=\"http://schemas.android.com/tools\"\n" + 38 " android:layout_width=\"match_parent\"\n" + 39 " android:layout_height=\"match_parent\"\n" + 40 " tools:ignore=\"HardcodedText\" >\n" + 41 "\n" + 42 " <Button\n" + 43 " android:id=\"@+id/button1\"\n" + 44 " android:layout_width=\"wrap_content\"\n" + 45 " android:layout_height=\"wrap_content\"\n" + 46 " android:layout_alignParentLeft=\"true\"\n" + 47 " android:text=\"A\" />\n" + 48 "\n" + 49 " <Button\n" + 50 " android:id=\"@+id/button2\"\n" + 51 " android:layout_width=\"wrap_content\"\n" + 52 " android:layout_height=\"wrap_content\"\n" + 53 " android:layout_alignBaseline=\"@+id/button1\"\n" + 54 " android:layout_alignBottom=\"@+id/button1\"\n" + 55 " android:layout_toRightOf=\"@+id/button1\"\n" + 56 " android:text=\"B\" />\n" + 57 "\n" + 58 " <Button\n" + 59 " android:id=\"@+id/button3\"\n" + 60 " android:layout_width=\"wrap_content\"\n" + 61 " android:layout_height=\"wrap_content\"\n" + 62 " android:layout_alignBottom=\"@+id/button2\"\n" + 63 " android:layout_toRightOf=\"@+id/button2\"\n" + 64 " android:text=\"C\" />\n" + 65 "\n" + 66 "</RelativeLayout>"; 67 TestNode targetNode = TestNode.createFromXml(xml); 68 assertNotNull(targetNode); 69 70 TestNode button2 = TestNode.findById(targetNode, "@+id/button2"); 71 72 INode layout = button2.getParent(); 73 List<INode> deletedNodes = Collections.<INode>singletonList(button2); 74 List<INode> movedNodes = Collections.<INode>emptyList(); 75 assertSame(layout, targetNode); 76 layout.removeChild(button2); 77 78 DeletionHandler handler = new DeletionHandler(deletedNodes, movedNodes, layout); 79 handler.updateConstraints(); 80 81 String updated = TestNode.toXml(targetNode); 82 assertEquals( 83 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 84 "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + 85 " xmlns:tools=\"http://schemas.android.com/tools\"\n" + 86 " android:layout_width=\"match_parent\"\n" + 87 " android:layout_height=\"match_parent\"\n" + 88 " tools:ignore=\"HardcodedText\">\n" + 89 "\n" + 90 " <Button\n" + 91 " android:id=\"@+id/button1\"\n" + 92 " android:layout_width=\"wrap_content\"\n" + 93 " android:layout_height=\"wrap_content\"\n" + 94 " android:layout_alignParentLeft=\"true\"\n" + 95 " android:text=\"A\">\n" + 96 " </Button>\n" + 97 "\n" + 98 " <Button\n" + 99 " android:id=\"@+id/button3\"\n" + 100 " android:layout_width=\"wrap_content\"\n" + 101 " android:layout_height=\"wrap_content\"\n" + 102 " android:layout_alignBaseline=\"@+id/button1\"\n" + 103 " android:layout_alignBottom=\"@+id/button1\"\n" + 104 " android:layout_toRightOf=\"@+id/button1\"\n" + 105 " android:text=\"C\">\n" + 106 " </Button>\n" + 107 "\n" + 108 "</RelativeLayout>", 109 updated); 110 assertFalse(updated.contains(BaseViewRule.stripIdPrefix(button2.getStringAttr(ANDROID_URI, 111 ATTR_ID)))); 112 } 113 114 public void testTransitive() { 115 String xml = "" + 116 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 117 "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + 118 " xmlns:tools=\"http://schemas.android.com/tools\"\n" + 119 " android:layout_width=\"match_parent\"\n" + 120 " android:layout_height=\"match_parent\"\n" + 121 " tools:ignore=\"HardcodedText\" >\n" + 122 "\n" + 123 " <Button\n" + 124 " android:id=\"@+id/button1\"\n" + 125 " android:layout_width=\"wrap_content\"\n" + 126 " android:layout_height=\"wrap_content\"\n" + 127 " android:layout_alignParentLeft=\"true\"\n" + 128 " android:layout_alignParentTop=\"true\"\n" + 129 " android:text=\"Above\" />\n" + 130 "\n" + 131 " <Button\n" + 132 " android:id=\"@+id/button2\"\n" + 133 " android:layout_width=\"wrap_content\"\n" + 134 " android:layout_height=\"wrap_content\"\n" + 135 " android:layout_alignParentLeft=\"true\"\n" + 136 " android:layout_below=\"@+id/button1\"\n" + 137 " android:text=\"A\" />\n" + 138 "\n" + 139 " <Button\n" + 140 " android:id=\"@+id/button3\"\n" + 141 " android:layout_width=\"wrap_content\"\n" + 142 " android:layout_height=\"wrap_content\"\n" + 143 " android:layout_alignBaseline=\"@+id/button2\"\n" + 144 " android:layout_alignBottom=\"@+id/button2\"\n" + 145 " android:layout_toRightOf=\"@+id/button2\"\n" + 146 " android:text=\"B\" />\n" + 147 "\n" + 148 " <Button\n" + 149 " android:id=\"@+id/button4\"\n" + 150 " android:layout_width=\"wrap_content\"\n" + 151 " android:layout_height=\"wrap_content\"\n" + 152 " android:layout_alignBottom=\"@+id/button3\"\n" + 153 " android:layout_toRightOf=\"@+id/button3\"\n" + 154 " android:text=\"C\" />\n" + 155 "\n" + 156 " <Button\n" + 157 " android:id=\"@+id/button5\"\n" + 158 " android:layout_width=\"wrap_content\"\n" + 159 " android:layout_height=\"wrap_content\"\n" + 160 " android:layout_alignBaseline=\"@+id/button4\"\n" + 161 " android:layout_alignBottom=\"@+id/button4\"\n" + 162 " android:layout_toRightOf=\"@+id/button4\"\n" + 163 " android:text=\"D\" />\n" + 164 "\n" + 165 " <Button\n" + 166 " android:id=\"@+id/button6\"\n" + 167 " android:layout_width=\"wrap_content\"\n" + 168 " android:layout_height=\"wrap_content\"\n" + 169 " android:layout_alignBottom=\"@+id/button5\"\n" + 170 " android:layout_toRightOf=\"@+id/button5\"\n" + 171 " android:text=\"E\" />\n" + 172 "\n" + 173 " <Button\n" + 174 " android:id=\"@+id/button7\"\n" + 175 " android:layout_width=\"wrap_content\"\n" + 176 " android:layout_height=\"wrap_content\"\n" + 177 " android:layout_alignLeft=\"@+id/button3\"\n" + 178 " android:layout_below=\"@+id/button3\"\n" + 179 " android:text=\"Button\" />\n" + 180 "\n" + 181 " <CheckBox\n" + 182 " android:id=\"@+id/checkBox1\"\n" + 183 " android:layout_width=\"wrap_content\"\n" + 184 " android:layout_height=\"wrap_content\"\n" + 185 " android:layout_alignBaseline=\"@+id/button7\"\n" + 186 " android:layout_alignBottom=\"@+id/button7\"\n" + 187 " android:layout_toRightOf=\"@+id/button7\"\n" + 188 " android:text=\"CheckBox\" />\n" + 189 "\n" + 190 " <Button\n" + 191 " android:id=\"@+id/button8\"\n" + 192 " android:layout_width=\"wrap_content\"\n" + 193 " android:layout_height=\"wrap_content\"\n" + 194 " android:layout_below=\"@+id/checkBox1\"\n" + 195 " android:layout_toRightOf=\"@+id/checkBox1\"\n" + 196 " android:text=\"Button\" />\n" + 197 "\n" + 198 "</RelativeLayout>"; 199 TestNode targetNode = TestNode.createFromXml(xml); 200 assertNotNull(targetNode); 201 TestNode button7 = TestNode.findById(targetNode, "@+id/button7"); 202 TestNode checkBox = TestNode.findById(targetNode, "@+id/checkBox1"); 203 204 INode layout = button7.getParent(); 205 List<INode> deletedNodes = Arrays.<INode>asList(button7, checkBox); 206 List<INode> movedNodes = Collections.<INode>emptyList(); 207 assertSame(layout, targetNode); 208 layout.removeChild(button7); 209 layout.removeChild(checkBox); 210 211 DeletionHandler handler = new DeletionHandler(deletedNodes, movedNodes, layout); 212 handler.updateConstraints(); 213 214 String updated = TestNode.toXml(targetNode); 215 assertEquals( 216 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 217 "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + 218 " xmlns:tools=\"http://schemas.android.com/tools\"\n" + 219 " android:layout_width=\"match_parent\"\n" + 220 " android:layout_height=\"match_parent\"\n" + 221 " tools:ignore=\"HardcodedText\">\n" + 222 "\n" + 223 " <Button\n" + 224 " android:id=\"@+id/button1\"\n" + 225 " android:layout_width=\"wrap_content\"\n" + 226 " android:layout_height=\"wrap_content\"\n" + 227 " android:layout_alignParentLeft=\"true\"\n" + 228 " android:layout_alignParentTop=\"true\"\n" + 229 " android:text=\"Above\">\n" + 230 " </Button>\n" + 231 "\n" + 232 " <Button\n" + 233 " android:id=\"@+id/button2\"\n" + 234 " android:layout_width=\"wrap_content\"\n" + 235 " android:layout_height=\"wrap_content\"\n" + 236 " android:layout_alignParentLeft=\"true\"\n" + 237 " android:layout_below=\"@+id/button1\"\n" + 238 " android:text=\"A\">\n" + 239 " </Button>\n" + 240 "\n" + 241 " <Button\n" + 242 " android:id=\"@+id/button3\"\n" + 243 " android:layout_width=\"wrap_content\"\n" + 244 " android:layout_height=\"wrap_content\"\n" + 245 " android:layout_alignBaseline=\"@+id/button2\"\n" + 246 " android:layout_alignBottom=\"@+id/button2\"\n" + 247 " android:layout_toRightOf=\"@+id/button2\"\n" + 248 " android:text=\"B\">\n" + 249 " </Button>\n" + 250 "\n" + 251 " <Button\n" + 252 " android:id=\"@+id/button4\"\n" + 253 " android:layout_width=\"wrap_content\"\n" + 254 " android:layout_height=\"wrap_content\"\n" + 255 " android:layout_alignBottom=\"@+id/button3\"\n" + 256 " android:layout_toRightOf=\"@+id/button3\"\n" + 257 " android:text=\"C\">\n" + 258 " </Button>\n" + 259 "\n" + 260 " <Button\n" + 261 " android:id=\"@+id/button5\"\n" + 262 " android:layout_width=\"wrap_content\"\n" + 263 " android:layout_height=\"wrap_content\"\n" + 264 " android:layout_alignBaseline=\"@+id/button4\"\n" + 265 " android:layout_alignBottom=\"@+id/button4\"\n" + 266 " android:layout_toRightOf=\"@+id/button4\"\n" + 267 " android:text=\"D\">\n" + 268 " </Button>\n" + 269 "\n" + 270 " <Button\n" + 271 " android:id=\"@+id/button6\"\n" + 272 " android:layout_width=\"wrap_content\"\n" + 273 " android:layout_height=\"wrap_content\"\n" + 274 " android:layout_alignBottom=\"@+id/button5\"\n" + 275 " android:layout_toRightOf=\"@+id/button5\"\n" + 276 " android:text=\"E\">\n" + 277 " </Button>\n" + 278 "\n" + 279 " <Button\n" + 280 " android:id=\"@+id/button8\"\n" + 281 " android:layout_width=\"wrap_content\"\n" + 282 " android:layout_height=\"wrap_content\"\n" + 283 " android:layout_alignLeft=\"@+id/button3\"\n" + 284 " android:layout_below=\"@+id/button3\"\n" + 285 " android:text=\"Button\">\n" + 286 " </Button>\n" + 287 "\n" + 288 "</RelativeLayout>", 289 updated); 290 assertFalse(updated.contains(BaseViewRule.stripIdPrefix(button7.getStringAttr(ANDROID_URI, 291 ATTR_ID)))); 292 } 293 294 public void testCenter() { 295 String xml = 296 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 297 "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + 298 " xmlns:tools=\"http://schemas.android.com/tools\"\n" + 299 " android:layout_width=\"match_parent\"\n" + 300 " android:layout_height=\"match_parent\"\n" + 301 " tools:ignore=\"HardcodedText\" >\n" + 302 "\n" + 303 " <Button\n" + 304 " android:id=\"@+id/button1\"\n" + 305 " android:layout_width=\"wrap_content\"\n" + 306 " android:layout_height=\"wrap_content\"\n" + 307 " android:layout_centerInParent=\"true\"\n" + 308 " android:text=\"Button\" />\n" + 309 "\n" + 310 " <CheckBox\n" + 311 " android:id=\"@+id/checkBox1\"\n" + 312 " android:layout_width=\"wrap_content\"\n" + 313 " android:layout_height=\"wrap_content\"\n" + 314 " android:layout_below=\"@+id/button1\"\n" + 315 " android:layout_toRightOf=\"@+id/button1\"\n" + 316 " android:text=\"CheckBox\" />\n" + 317 "\n" + 318 "</RelativeLayout>"; 319 320 TestNode targetNode = TestNode.createFromXml(xml); 321 assertNotNull(targetNode); 322 TestNode button1 = TestNode.findById(targetNode, "@+id/button1"); 323 324 INode layout = button1.getParent(); 325 List<INode> deletedNodes = Collections.<INode>singletonList(button1); 326 List<INode> movedNodes = Collections.<INode>emptyList(); 327 assertSame(layout, targetNode); 328 layout.removeChild(button1); 329 330 DeletionHandler handler = new DeletionHandler(deletedNodes, movedNodes, layout); 331 handler.updateConstraints(); 332 333 String updated = TestNode.toXml(targetNode); 334 assertEquals( 335 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 336 "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + 337 " xmlns:tools=\"http://schemas.android.com/tools\"\n" + 338 " android:layout_width=\"match_parent\"\n" + 339 " android:layout_height=\"match_parent\"\n" + 340 " tools:ignore=\"HardcodedText\">\n" + 341 "\n" + 342 " <CheckBox\n" + 343 " android:id=\"@+id/checkBox1\"\n" + 344 " android:layout_width=\"wrap_content\"\n" + 345 " android:layout_height=\"wrap_content\"\n" + 346 " android:layout_centerInParent=\"true\"\n" + 347 " android:text=\"CheckBox\">\n" + 348 " </CheckBox>\n" + 349 "\n" + 350 "</RelativeLayout>", 351 updated); 352 assertFalse(updated.contains(BaseViewRule.stripIdPrefix(button1.getStringAttr(ANDROID_URI, 353 ATTR_ID)))); 354 355 } 356 357 public void testMove() { 358 String xml = "" + 359 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 360 "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + 361 " xmlns:tools=\"http://schemas.android.com/tools\"\n" + 362 " android:layout_width=\"match_parent\"\n" + 363 " android:layout_height=\"match_parent\"\n" + 364 " tools:ignore=\"HardcodedText\" >\n" + 365 "\n" + 366 " <Button\n" + 367 " android:id=\"@+id/button1\"\n" + 368 " android:layout_width=\"wrap_content\"\n" + 369 " android:layout_height=\"wrap_content\"\n" + 370 " android:layout_alignParentLeft=\"true\"\n" + 371 " android:text=\"A\" />\n" + 372 "\n" + 373 " <Button\n" + 374 " android:id=\"@+id/button2\"\n" + 375 " android:layout_width=\"wrap_content\"\n" + 376 " android:layout_height=\"wrap_content\"\n" + 377 " android:layout_alignBaseline=\"@+id/button1\"\n" + 378 " android:layout_alignBottom=\"@+id/button1\"\n" + 379 " android:layout_toRightOf=\"@+id/button1\"\n" + 380 " android:text=\"B\" />\n" + 381 "\n" + 382 " <Button\n" + 383 " android:id=\"@+id/button3\"\n" + 384 " android:layout_width=\"wrap_content\"\n" + 385 " android:layout_height=\"wrap_content\"\n" + 386 " android:layout_alignBottom=\"@+id/button2\"\n" + 387 " android:layout_toRightOf=\"@+id/button2\"\n" + 388 " android:text=\"C\" />\n" + 389 "\n" + 390 "</RelativeLayout>"; 391 TestNode targetNode = TestNode.createFromXml(xml); 392 assertNotNull(targetNode); 393 394 TestNode button2 = TestNode.findById(targetNode, "@+id/button2"); 395 396 INode layout = button2.getParent(); 397 List<INode> deletedNodes = Collections.<INode>singletonList(button2); 398 List<INode> movedNodes = Collections.<INode>singletonList(button2); 399 assertSame(layout, targetNode); 400 401 DeletionHandler handler = new DeletionHandler(deletedNodes, movedNodes, layout); 402 handler.updateConstraints(); 403 404 String updated = TestNode.toXml(targetNode); 405 assertEquals( 406 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + 407 "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + 408 " xmlns:tools=\"http://schemas.android.com/tools\"\n" + 409 " android:layout_width=\"match_parent\"\n" + 410 " android:layout_height=\"match_parent\"\n" + 411 " tools:ignore=\"HardcodedText\">\n" + 412 "\n" + 413 " <Button\n" + 414 " android:id=\"@+id/button1\"\n" + 415 " android:layout_width=\"wrap_content\"\n" + 416 " android:layout_height=\"wrap_content\"\n" + 417 " android:layout_alignParentLeft=\"true\"\n" + 418 " android:text=\"A\">\n" + 419 " </Button>\n" + 420 "\n" + 421 " <Button\n" + 422 " android:id=\"@+id/button2\"\n" + 423 " android:layout_width=\"wrap_content\"\n" + 424 " android:layout_height=\"wrap_content\"\n" + 425 " android:layout_alignBaseline=\"@+id/button1\"\n" + 426 " android:layout_alignBottom=\"@+id/button1\"\n" + 427 " android:layout_toRightOf=\"@+id/button1\"\n" + 428 " android:text=\"B\">\n" + 429 " </Button>\n" + 430 "\n" + 431 " <Button\n" + 432 " android:id=\"@+id/button3\"\n" + 433 " android:layout_width=\"wrap_content\"\n" + 434 " android:layout_height=\"wrap_content\"\n" + 435 " android:layout_alignBottom=\"@+id/button2\"\n" + 436 " android:layout_toRightOf=\"@+id/button2\"\n" + 437 " android:text=\"C\">\n" + 438 " </Button>\n" + 439 "\n" + 440 "</RelativeLayout>", 441 updated); 442 assertTrue(updated.contains(BaseViewRule.stripIdPrefix(button2.getStringAttr(ANDROID_URI, 443 ATTR_ID)))); 444 } 445 } 446