1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 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 17 package com.android.gallery3d.ui; 18 19 import android.graphics.Rect; 20 import android.test.suitebuilder.annotation.SmallTest; 21 import android.view.MotionEvent; 22 23 import junit.framework.TestCase; 24 25 @SmallTest 26 public class GLViewTest extends TestCase { 27 @SuppressWarnings("unused") 28 private static final String TAG = "GLViewTest"; 29 30 @SmallTest testVisibility()31 public void testVisibility() { 32 GLViewMock a = new GLViewMock(); 33 assertEquals(GLView.VISIBLE, a.getVisibility()); 34 assertEquals(0, a.mOnVisibilityChangedCalled); 35 a.setVisibility(GLView.INVISIBLE); 36 assertEquals(GLView.INVISIBLE, a.getVisibility()); 37 assertEquals(1, a.mOnVisibilityChangedCalled); 38 a.setVisibility(GLView.VISIBLE); 39 assertEquals(GLView.VISIBLE, a.getVisibility()); 40 assertEquals(2, a.mOnVisibilityChangedCalled); 41 } 42 43 @SmallTest testComponents()44 public void testComponents() { 45 GLView view = new GLView(); 46 assertEquals(0, view.getComponentCount()); 47 try { 48 view.getComponent(0); 49 fail(); 50 } catch (IndexOutOfBoundsException ex) { 51 // expected 52 } 53 54 GLView x = new GLView(); 55 GLView y = new GLView(); 56 view.addComponent(x); 57 view.addComponent(y); 58 assertEquals(2, view.getComponentCount()); 59 assertSame(x, view.getComponent(0)); 60 assertSame(y, view.getComponent(1)); 61 view.removeComponent(x); 62 assertSame(y, view.getComponent(0)); 63 try { 64 view.getComponent(1); 65 fail(); 66 } catch (IndexOutOfBoundsException ex) { 67 // expected 68 } 69 try { 70 view.addComponent(y); 71 fail(); 72 } catch (IllegalStateException ex) { 73 // expected 74 } 75 view.addComponent(x); 76 view.removeAllComponents(); 77 assertEquals(0, view.getComponentCount()); 78 } 79 80 @SmallTest testBounds()81 public void testBounds() { 82 GLView view = new GLView(); 83 84 assertEquals(0, view.getWidth()); 85 assertEquals(0, view.getHeight()); 86 87 Rect b = view.bounds(); 88 assertEquals(0, b.left); 89 assertEquals(0, b.top); 90 assertEquals(0, b.right); 91 assertEquals(0, b.bottom); 92 93 view.layout(10, 20, 30, 100); 94 assertEquals(20, view.getWidth()); 95 assertEquals(80, view.getHeight()); 96 97 b = view.bounds(); 98 assertEquals(10, b.left); 99 assertEquals(20, b.top); 100 assertEquals(30, b.right); 101 assertEquals(100, b.bottom); 102 } 103 104 @SmallTest testParent()105 public void testParent() { 106 GLView a = new GLView(); 107 GLView b = new GLView(); 108 assertNull(b.mParent); 109 a.addComponent(b); 110 assertSame(a, b.mParent); 111 a.removeComponent(b); 112 assertNull(b.mParent); 113 } 114 115 @SmallTest testRoot()116 public void testRoot() { 117 GLViewMock a = new GLViewMock(); 118 GLViewMock b = new GLViewMock(); 119 GLRoot r = new GLRootStub(); 120 GLRoot r2 = new GLRootStub(); 121 a.addComponent(b); 122 123 // Attach to root r 124 assertEquals(0, a.mOnAttachCalled); 125 assertEquals(0, b.mOnAttachCalled); 126 a.attachToRoot(r); 127 assertEquals(1, a.mOnAttachCalled); 128 assertEquals(1, b.mOnAttachCalled); 129 assertSame(r, a.getGLRoot()); 130 assertSame(r, b.getGLRoot()); 131 132 // Detach from r 133 assertEquals(0, a.mOnDetachCalled); 134 assertEquals(0, b.mOnDetachCalled); 135 a.detachFromRoot(); 136 assertEquals(1, a.mOnDetachCalled); 137 assertEquals(1, b.mOnDetachCalled); 138 139 // Attach to another root r2 140 assertEquals(1, a.mOnAttachCalled); 141 assertEquals(1, b.mOnAttachCalled); 142 a.attachToRoot(r2); 143 assertEquals(2, a.mOnAttachCalled); 144 assertEquals(2, b.mOnAttachCalled); 145 assertSame(r2, a.getGLRoot()); 146 assertSame(r2, b.getGLRoot()); 147 148 // Detach from r2 149 assertEquals(1, a.mOnDetachCalled); 150 assertEquals(1, b.mOnDetachCalled); 151 a.detachFromRoot(); 152 assertEquals(2, a.mOnDetachCalled); 153 assertEquals(2, b.mOnDetachCalled); 154 } 155 156 @SmallTest testRoot2()157 public void testRoot2() { 158 GLView a = new GLViewMock(); 159 GLViewMock b = new GLViewMock(); 160 GLRoot r = new GLRootStub(); 161 162 a.attachToRoot(r); 163 164 assertEquals(0, b.mOnAttachCalled); 165 a.addComponent(b); 166 assertEquals(1, b.mOnAttachCalled); 167 168 assertEquals(0, b.mOnDetachCalled); 169 a.removeComponent(b); 170 assertEquals(1, b.mOnDetachCalled); 171 } 172 173 @SmallTest testInvalidate()174 public void testInvalidate() { 175 GLView a = new GLView(); 176 GLRootMock r = new GLRootMock(); 177 a.attachToRoot(r); 178 assertEquals(0, r.mRequestRenderCalled); 179 a.invalidate(); 180 assertEquals(1, r.mRequestRenderCalled); 181 } 182 183 @SmallTest testRequestLayout()184 public void testRequestLayout() { 185 GLView a = new GLView(); 186 GLView b = new GLView(); 187 GLRootMock r = new GLRootMock(); 188 a.attachToRoot(r); 189 a.addComponent(b); 190 assertEquals(0, r.mRequestLayoutContentPaneCalled); 191 b.requestLayout(); 192 assertEquals(1, r.mRequestLayoutContentPaneCalled); 193 } 194 195 @SmallTest testLayout()196 public void testLayout() { 197 GLViewMock a = new GLViewMock(); 198 GLViewMock b = new GLViewMock(); 199 GLViewMock c = new GLViewMock(); 200 GLRootMock r = new GLRootMock(); 201 202 a.attachToRoot(r); 203 a.addComponent(b); 204 a.addComponent(c); 205 206 assertEquals(0, a.mOnLayoutCalled); 207 a.layout(10, 20, 60, 100); 208 assertEquals(1, a.mOnLayoutCalled); 209 assertEquals(1, b.mOnLayoutCalled); 210 assertEquals(1, c.mOnLayoutCalled); 211 assertTrue(a.mOnLayoutChangeSize); 212 assertTrue(b.mOnLayoutChangeSize); 213 assertTrue(c.mOnLayoutChangeSize); 214 215 // same size should not trigger onLayout 216 a.layout(10, 20, 60, 100); 217 assertEquals(1, a.mOnLayoutCalled); 218 219 // unless someone requested it, but only those on the path 220 // to the requester. 221 assertEquals(0, r.mRequestLayoutContentPaneCalled); 222 b.requestLayout(); 223 a.layout(10, 20, 60, 100); 224 assertEquals(1, r.mRequestLayoutContentPaneCalled); 225 assertEquals(2, a.mOnLayoutCalled); 226 assertEquals(2, b.mOnLayoutCalled); 227 assertEquals(1, c.mOnLayoutCalled); 228 } 229 230 @SmallTest testRender()231 public void testRender() { 232 GLViewMock a = new GLViewMock(); 233 GLViewMock b = new GLViewMock(); 234 235 a.addComponent(b); 236 GLCanvasStub canvas = new GLCanvasStub(); 237 assertEquals(0, a.mRenderBackgroundCalled); 238 assertEquals(0, b.mRenderBackgroundCalled); 239 a.render(canvas); 240 assertEquals(1, a.mRenderBackgroundCalled); 241 assertEquals(1, b.mRenderBackgroundCalled); 242 } 243 244 @SmallTest testMeasure()245 public void testMeasure() { 246 GLViewMock a = new GLViewMock(); 247 GLViewMock b = new GLViewMock(); 248 GLViewMock c = new GLViewMock(); 249 GLRootMock r = new GLRootMock(); 250 251 a.addComponent(b); 252 a.addComponent(c); 253 a.attachToRoot(r); 254 255 assertEquals(0, a.mOnMeasureCalled); 256 a.measure(100, 200); 257 assertEquals(1, a.mOnMeasureCalled); 258 assertEquals(1, b.mOnMeasureCalled); 259 assertEquals(100, a.mOnMeasureWidthSpec); 260 assertEquals(200, a.mOnMeasureHeightSpec); 261 assertEquals(100, b.mOnMeasureWidthSpec); 262 assertEquals(200, b.mOnMeasureHeightSpec); 263 assertEquals(100, a.getMeasuredWidth()); 264 assertEquals(200, b.getMeasuredHeight()); 265 266 // same spec should not trigger onMeasure 267 a.measure(100, 200); 268 assertEquals(1, a.mOnMeasureCalled); 269 270 // unless someone requested it, but only those on the path 271 // to the requester. 272 b.requestLayout(); 273 a.measure(100, 200); 274 assertEquals(2, a.mOnMeasureCalled); 275 assertEquals(2, b.mOnMeasureCalled); 276 assertEquals(1, c.mOnMeasureCalled); 277 } 278 279 class MyGLView extends GLView { 280 private int mWidth; 281 int mOnTouchCalled; 282 int mOnTouchX; 283 int mOnTouchY; 284 int mOnTouchAction; 285 MyGLView(int width)286 public MyGLView(int width) { 287 mWidth = width; 288 } 289 290 @Override onLayout(boolean changeSize, int left, int top, int right, int bottom)291 protected void onLayout(boolean changeSize, int left, int top, 292 int right, int bottom) { 293 // layout children from left to right 294 // call children's layout. 295 int x = 0; 296 for (int i = 0, n = getComponentCount(); i < n; ++i) { 297 GLView item = getComponent(i); 298 item.measure(0, 0); 299 int w = item.getMeasuredWidth(); 300 int h = item.getMeasuredHeight(); 301 item.layout(x, 0, x + w, h); 302 x += w; 303 } 304 } 305 306 @Override onMeasure(int widthSpec, int heightSpec)307 protected void onMeasure(int widthSpec, int heightSpec) { 308 setMeasuredSize(mWidth, 100); 309 } 310 311 @Override onTouch(MotionEvent event)312 protected boolean onTouch(MotionEvent event) { 313 mOnTouchCalled++; 314 mOnTouchX = (int) event.getX(); 315 mOnTouchY = (int) event.getY(); 316 mOnTouchAction = event.getAction(); 317 return true; 318 } 319 } 320 NewMotionEvent(int action, int x, int y)321 private MotionEvent NewMotionEvent(int action, int x, int y) { 322 return MotionEvent.obtain(0, 0, action, x, y, 0); 323 } 324 325 @SmallTest testTouchEvent()326 public void testTouchEvent() { 327 // We construct a tree with four nodes. Only the x coordinate is used: 328 // A = [0..............................300) 329 // B = [0......100) 330 // C = [100......200) 331 // D = [100..150) 332 333 MyGLView a = new MyGLView(300); 334 MyGLView b = new MyGLView(100); 335 MyGLView c = new MyGLView(100); 336 MyGLView d = new MyGLView(50); 337 GLRoot r = new GLRootStub(); 338 339 a.addComponent(b); 340 a.addComponent(c); 341 c.addComponent(d); 342 a.attachToRoot(r); 343 a.layout(0, 0, 300, 100); 344 345 int DOWN = MotionEvent.ACTION_DOWN; 346 int UP = MotionEvent.ACTION_UP; 347 int MOVE = MotionEvent.ACTION_MOVE; 348 int CANCEL = MotionEvent.ACTION_CANCEL; 349 350 // simple case 351 assertEquals(0, a.mOnTouchCalled); 352 a.dispatchTouchEvent(NewMotionEvent(DOWN, 250, 0)); 353 assertEquals(DOWN, a.mOnTouchAction); 354 a.dispatchTouchEvent(NewMotionEvent(UP, 250, 0)); 355 assertEquals(UP, a.mOnTouchAction); 356 assertEquals(2, a.mOnTouchCalled); 357 358 // pass to a child, check the location is offseted. 359 assertEquals(0, c.mOnTouchCalled); 360 a.dispatchTouchEvent(NewMotionEvent(DOWN, 175, 0)); 361 a.dispatchTouchEvent(NewMotionEvent(UP, 175, 0)); 362 assertEquals(75, c.mOnTouchX); 363 assertEquals(0, c.mOnTouchY); 364 assertEquals(2, c.mOnTouchCalled); 365 assertEquals(2, a.mOnTouchCalled); 366 367 // motion target cancel event 368 assertEquals(0, d.mOnTouchCalled); 369 a.dispatchTouchEvent(NewMotionEvent(DOWN, 125, 0)); 370 assertEquals(1, d.mOnTouchCalled); 371 a.dispatchTouchEvent(NewMotionEvent(MOVE, 250, 0)); 372 assertEquals(2, d.mOnTouchCalled); 373 a.dispatchTouchEvent(NewMotionEvent(MOVE, 50, 0)); 374 assertEquals(3, d.mOnTouchCalled); 375 a.dispatchTouchEvent(NewMotionEvent(DOWN, 175, 0)); 376 assertEquals(4, d.mOnTouchCalled); 377 assertEquals(CANCEL, d.mOnTouchAction); 378 assertEquals(3, c.mOnTouchCalled); 379 assertEquals(DOWN, c.mOnTouchAction); 380 a.dispatchTouchEvent(NewMotionEvent(UP, 175, 0)); 381 382 // motion target is removed 383 assertEquals(4, d.mOnTouchCalled); 384 a.dispatchTouchEvent(NewMotionEvent(DOWN, 125, 0)); 385 assertEquals(5, d.mOnTouchCalled); 386 a.removeComponent(c); 387 assertEquals(6, d.mOnTouchCalled); 388 assertEquals(CANCEL, d.mOnTouchAction); 389 390 // invisible component should not get events 391 assertEquals(2, a.mOnTouchCalled); 392 assertEquals(0, b.mOnTouchCalled); 393 b.setVisibility(GLView.INVISIBLE); 394 a.dispatchTouchEvent(NewMotionEvent(DOWN, 50, 0)); 395 assertEquals(3, a.mOnTouchCalled); 396 assertEquals(0, b.mOnTouchCalled); 397 } 398 } 399