1 /* 2 * This file is part of the LibreOffice project. 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 * 8 * This file incorporates work covered by the following license notice: 9 * 10 * Licensed to the Apache Software Foundation (ASF) under one or more 11 * contributor license agreements. See the NOTICE file distributed 12 * with this work for additional information regarding copyright 13 * ownership. The ASF licenses this file to you under the Apache 14 * License, Version 2.0 (the "License"); you may not use this file 15 * except in compliance with the License. You may obtain a copy of 16 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 17 */ 18 package ifc.accessibility; 19 20 import java.util.ArrayList; 21 import lib.MultiMethodTest; 22 23 import com.sun.star.accessibility.XAccessible; 24 import com.sun.star.accessibility.XAccessibleComponent; 25 import com.sun.star.accessibility.XAccessibleContext; 26 import com.sun.star.awt.Point; 27 import com.sun.star.awt.Rectangle; 28 import com.sun.star.awt.Size; 29 import com.sun.star.uno.UnoRuntime; 30 31 32 /** 33 * Testing <code>com.sun.star.accessibility.XAccessibleComponent</code> 34 * interface methods : 35 * <ul> 36 * <li><code> containsPoint()</code></li> 37 * <li><code> getAccessibleAtPoint()</code></li> 38 * <li><code> getBounds()</code></li> 39 * <li><code> getLocation()</code></li> 40 * <li><code> getLocationOnScreen()</code></li> 41 * <li><code> getSize()</code></li> 42 * <li><code> grabFocus()</code></li> 43 * <li><code> getAccessibleKeyBinding()</code></li> 44 * </ul> <p> 45 * 46 * @see com.sun.star.accessibility.XAccessibleComponent 47 */ 48 public class _XAccessibleComponent extends MultiMethodTest { 49 50 public XAccessibleComponent oObj = null; 51 private final ArrayList<Rectangle> KnownBounds = new ArrayList<Rectangle>(); 52 53 54 /** 55 * First checks 4 inner bounds (upper, lower, left and right) 56 * of component bounding box to contain 57 * at least one point of the component. Second 4 outer bounds 58 * are checked to not contain any component points.<p> 59 * 60 * Has <b> OK </b> status if inner bounds contain component points 61 * and outer bounds don't contain any component points. <p> 62 * 63 * The following method tests are to be completed successfully before : 64 * <ul> 65 * <li> <code> getBounds() </code> : to have size of a component.</li> 66 * </ul> 67 */ _containsPoint()68 public void _containsPoint() { 69 Rectangle bounds = oObj.getBounds(); 70 71 boolean result = true; 72 73 int curX = 0; 74 75 while (!oObj.containsPoint(new Point(curX, 0)) && 76 (curX < bounds.Width)) { 77 curX++; 78 } 79 80 if (curX < bounds.Width) { 81 log.println("Upper bound of box containsPoint point (" + curX + 82 ",0) - OK"); 83 } else { 84 log.println( 85 "Upper bound of box containsPoint no component points - FAILED"); 86 result = false; 87 } 88 89 curX = 0; 90 91 while (!oObj.containsPoint(new Point(curX, bounds.Height - 1)) && 92 (curX < bounds.Width)) { 93 log.println("containsPoint returns false for (" + curX + "," + 94 bounds.Height + ")"); 95 curX++; 96 } 97 98 if (curX < bounds.Width) { 99 log.println("Lower bound of box containsPoint point (" + curX + 100 "," + (bounds.Height - 1) + ") - OK"); 101 } else { 102 log.println( 103 "Lower bound of box containsPoint no component points - FAILED"); 104 result = false; 105 } 106 107 int curY = 0; 108 109 while (!oObj.containsPoint(new Point(0, curY)) && 110 (curY < bounds.Height)) { 111 curY++; 112 } 113 114 if (curY < bounds.Height) { 115 log.println("Left bound of box containsPoint point (0," + curY + 116 ") - OK"); 117 } else { 118 log.println( 119 "Left bound of box containsPoint no component points - FAILED"); 120 result = false; 121 } 122 123 curY = 0; 124 125 while (!oObj.containsPoint(new Point(bounds.Width - 1, curY)) && 126 (curY < bounds.Height)) { 127 curY++; 128 } 129 130 if (curY < bounds.Height) { 131 log.println("Right bound of box containsPoint point (" + 132 (bounds.Width - 1) + "," + curY + ") - OK"); 133 } else { 134 log.println( 135 "Right bound of box containsPoint no component points - FAILED"); 136 result = false; 137 } 138 139 boolean locRes = true; 140 141 for (int x = -1; x <= bounds.Width; x++) { 142 if (oObj.containsPoint(new Point(x, -1))) { 143 log.println( 144 "Outer upper and lower bounds CONTAIN some component point" 145 + " (" + x + ", -1) - FAILED"); 146 locRes = false; 147 break; 148 } 149 if (oObj.containsPoint(new Point(x, bounds.Height + bounds.Y))) { 150 log.println( 151 "Outer upper and lower bounds CONTAIN some component point" 152 + " (" + x + ", " + (bounds.Height + bounds.Y) 153 + ") - FAILED"); 154 locRes = false; 155 break; 156 } 157 } 158 159 if (locRes) { 160 log.println("Outer upper and lower bounds contain no component " + 161 "points - OK"); 162 } else { 163 result = false; 164 } 165 166 locRes = true; 167 168 for (int y = -1; y <= bounds.Height; y++) { 169 if (oObj.containsPoint(new Point(-1, y))) { 170 log.println( 171 "Outer left and right bounds CONTAIN some component point" 172 + " (-1, " + y + ") - FAILED"); 173 locRes = false; 174 break; 175 } 176 if (oObj.containsPoint(new Point(bounds.X + bounds.Width, y))) { 177 log.println( 178 "Outer left and right bounds CONTAIN some component point" 179 + " (" + (bounds.X + bounds.Width) + ", " + y + ") - FAILED"); 180 locRes = false; 181 break; 182 } 183 } 184 185 if (locRes) { 186 log.println("Outer left and right bounds contain no component " + 187 "points - OK"); 188 } else { 189 result = false; 190 } 191 192 tRes.tested("containsPoint()", result); 193 } 194 195 /** 196 * Iterates through all children which implement 197 * <code>XAccessibleComponent</code> (if they exist) determines their 198 * boundaries and tries to get each child by <code>getAccessibleAtPoint</code> 199 * passing point which belongs to the child. 200 * Also the point is checked which doesn't belong to child boundary 201 * box. <p> 202 * 203 * Has <b> OK </b> status if in the first cases the right children 204 * are returned, and in the second <code>null</code> or 205 * another child is returned. 206 */ _getAccessibleAtPoint()207 public void _getAccessibleAtPoint() { 208 boolean result = true; 209 XAccessibleComponent[] children = getChildrenComponents(); 210 211 if (children.length == 0) { 212 log.println("There are no children supporting XAccessibleComponent"); 213 tRes.tested("getAccessibleAtPoint()", result); 214 return; 215 } 216 217 for (int i = 0; i < children.length; i++) { 218 Rectangle chBnd = children[i].getBounds(); 219 220 if (chBnd.X == -1) { 221 continue; 222 } 223 224 log.println("Checking child with bounds " + "(" + chBnd.X + 225 "," + chBnd.Y + "),(" + chBnd.Width + "," + 226 chBnd.Height + "): " + 227 util.AccessibilityTools.accessibleToString( 228 children[i])); 229 230 XAccessibleContext xAc = UnoRuntime.queryInterface( 231 XAccessibleContext.class, 232 children[i]); 233 234 boolean MightBeCovered = false; 235 boolean isShowing = xAc.getAccessibleStateSet() 236 .contains(com.sun.star.accessibility.AccessibleStateType.SHOWING); 237 log.println("\tStateType containsPoint SHOWING: " + 238 isShowing); 239 240 if (!isShowing) { 241 log.println("Child is invisible - OK"); 242 continue; 243 } 244 245 log.println("finding the point which lies on the component"); 246 247 int curX = chBnd.Width / 2; 248 int curY = chBnd.Height / 2; 249 250 while (!children[i].containsPoint(new Point(curX, curY)) && 251 (curX > 0) && (curY > 0)) { 252 curX--; 253 curY--; 254 } 255 256 if (curX == chBnd.Width) { 257 log.println("Couldn't find a point with containsPoint"); 258 259 continue; 260 } 261 262 // trying the point laying on child 263 XAccessible xAcc = oObj.getAccessibleAtPoint( 264 new Point(chBnd.X + curX, 265 chBnd.Y + curY)); 266 267 268 Point p = new Point(chBnd.X + curX,chBnd.X + curX); 269 270 if (isCovered(p)) { 271 log.println( 272 "Child might be covered by another and can't be reached"); 273 MightBeCovered = true; 274 } 275 276 KnownBounds.add(chBnd); 277 278 if (xAcc == null) { 279 log.println("The child not found at point (" + 280 (chBnd.X + curX) + "," + (chBnd.Y + curY) + 281 ") - FAILED"); 282 283 result = false; 284 } else { 285 XAccessible xAccCh = UnoRuntime.queryInterface( 286 XAccessible.class, 287 children[i]); 288 XAccessibleContext xAccC = UnoRuntime.queryInterface( 289 XAccessibleContext.class, 290 children[i]); 291 log.println("Child found at point (" + (chBnd.X + curX) + 292 "," + (chBnd.Y + curY) + ") - OK"); 293 294 boolean res = false; 295 int expIndex; 296 String expName; 297 String expDesc; 298 299 if (xAccCh != null) { 300 res = util.AccessibilityTools.equals(xAccCh, xAcc); 301 expIndex = xAccCh.getAccessibleContext() 302 .getAccessibleIndexInParent(); 303 expName = xAccCh.getAccessibleContext() 304 .getAccessibleName(); 305 expDesc = xAccCh.getAccessibleContext() 306 .getAccessibleDescription(); 307 } else { 308 res = xAccC.getAccessibleName() 309 .equals(xAcc.getAccessibleContext() 310 .getAccessibleName()); 311 expIndex = xAccC.getAccessibleIndexInParent(); 312 expName = xAccC.getAccessibleName(); 313 expDesc = xAccC.getAccessibleDescription(); 314 } 315 316 if (!res) { 317 int gotIndex = xAcc.getAccessibleContext() 318 .getAccessibleIndexInParent(); 319 320 if (expIndex < gotIndex) { 321 log.println("The children found is not the same"); 322 log.println("The expected child " + expName); 323 log.print("is hidden behind the found Child "); 324 log.println(xAcc.getAccessibleContext() 325 .getAccessibleName() + " - OK"); 326 } else { 327 log.println( 328 "The children found is not the same"); 329 log.println("Expected: " + expName); 330 log.println("Description: " + expDesc); 331 log.println("Found: " + 332 xAcc.getAccessibleContext() 333 .getAccessibleName()); 334 log.println("Description: " + 335 xAcc.getAccessibleContext() 336 .getAccessibleDescription()); 337 if (MightBeCovered) { 338 log.println("... Child is covered by another - OK"); 339 } else { 340 log.println("... FAILED"); 341 result = false; 342 } 343 344 } 345 } 346 } 347 348 349 // trying the point NOT laying on child 350 xAcc = oObj.getAccessibleAtPoint( 351 new Point(chBnd.X - 1, chBnd.Y - 1)); 352 353 if (xAcc == null) { 354 log.println("No children found at point (" + 355 (chBnd.X - 1) + "," + (chBnd.Y - 1) + 356 ") - OK"); 357 result &= true; 358 } else { 359 XAccessible xAccCh = UnoRuntime.queryInterface( 360 XAccessible.class, 361 children[i]); 362 boolean res = util.AccessibilityTools.equals(xAccCh, xAcc); 363 364 if (res) { 365 log.println("The same child found outside " + 366 "its bounds at (" + (chBnd.X - 1) + "," + 367 (chBnd.Y - 1) + ") - FAILED"); 368 result = false; 369 } 370 } 371 } 372 373 tRes.tested("getAccessibleAtPoint()", result); 374 } 375 376 /** 377 * Retrieves the component bounds and discards it. <p> 378 * 379 * Has <b> OK </b> status if boundary position (x,y) is not negative 380 * and size (Width, Height) is greater than 0. 381 */ _getBounds()382 public void _getBounds() { 383 boolean result = true; 384 385 Rectangle bounds = oObj.getBounds(); 386 result &= ((bounds != null) && (bounds.X >= 0) && (bounds.Y >= 0) && (bounds.Width > 0) && (bounds.Height > 0)); 387 388 log.println("Bounds = " + 389 ((bounds != null) 390 ? ("(" + bounds.X + "," + bounds.Y + "),(" + 391 bounds.Width + "," + bounds.Height + ")") : "null")); 392 393 tRes.tested("getBounds()", result); 394 } 395 396 /** 397 * Gets the location. <p> 398 * 399 * Has <b> OK </b> status if the location is the same as location 400 * of boundary obtained by <code>getBounds()</code> method. 401 */ _getLocation()402 public void _getLocation() { 403 Rectangle bounds = oObj.getBounds(); 404 Point loc = oObj.getLocation(); 405 boolean result = loc.X == bounds.X && loc.Y == bounds.Y; 406 log.println( 407 "loc.X=" + loc.X + " vs. bounds.X=" + bounds.X + ", loc.Y=" 408 + loc.Y + " vs. bounds.Y=" + bounds.Y); 409 tRes.tested("getLocation()", result); 410 } 411 412 /** 413 * Get the screen location of the component and its parent 414 * (if it exists and supports <code>XAccessibleComponent</code>). <p> 415 * 416 * Has <b> OK </b> status if component screen location equals 417 * to screen location of its parent plus location of the component 418 * relative to the parent. <p> 419 */ _getLocationOnScreen()420 public void _getLocationOnScreen() { 421 XAccessibleComponent parent = getParentComponent(); 422 423 boolean result = true; 424 Rectangle bounds = oObj.getBounds(); 425 Point loc = oObj.getLocationOnScreen(); 426 log.println("Location is (" + loc.X + "," + loc.Y + ")"); 427 428 if (parent != null) { 429 Point parLoc = parent.getLocationOnScreen(); 430 log.println("Parent location is (" + parLoc.X + "," + parLoc.Y + 431 ")"); 432 433 result &= ((parLoc.X + bounds.X) == loc.X); 434 result &= ((parLoc.Y + bounds.Y) == loc.Y); 435 } 436 437 tRes.tested("getLocationOnScreen()", result); 438 } 439 440 /** 441 * Obtains the size of the component. <p> 442 * 443 * Has <b> OK </b> status if the size is the same as in bounds. <p> 444 */ _getSize()445 public void _getSize() { 446 requiredMethod("getBounds()"); 447 448 boolean result = true; 449 Rectangle bounds = oObj.getBounds(); 450 Size size = oObj.getSize(); 451 452 result &= (size.Width == bounds.Width); 453 result &= (size.Height == bounds.Height); 454 455 tRes.tested("getSize()", result); 456 } 457 458 /** 459 * Just calls the method. <p> 460 * 461 * Has <b> OK </b> status if no runtime exceptions occurred. 462 */ _grabFocus()463 public void _grabFocus() { 464 boolean result = true; 465 oObj.grabFocus(); 466 467 tRes.tested("grabFocus()", result); 468 } 469 470 /** 471 * Retrieves all children (not more than 50) of the current 472 * component which support <code>XAccessibleComponent</code>. 473 * 474 * @return The array of children. Empty array returned if 475 * such children were not found or some error occurred. 476 */ getChildrenComponents()477 private XAccessibleComponent[] getChildrenComponents() { 478 XAccessible xAcc = UnoRuntime.queryInterface( 479 XAccessible.class, oObj); 480 481 if (xAcc == null) { 482 log.println("Component doesn't support XAccessible."); 483 484 return new XAccessibleComponent[0]; 485 } 486 487 XAccessibleContext xAccCon = xAcc.getAccessibleContext(); 488 int cnt = xAccCon.getAccessibleChildCount(); 489 490 // for cases when too many children exist checking only first 50 491 if (cnt > 50) { 492 cnt = 50; 493 } 494 495 ArrayList<XAccessibleComponent> childComp = new ArrayList<XAccessibleComponent>(); 496 497 for (int i = 0; i < cnt; i++) { 498 try { 499 XAccessible child = xAccCon.getAccessibleChild(i); 500 XAccessibleContext xAccConCh = child.getAccessibleContext(); 501 XAccessibleComponent xChAccComp = UnoRuntime.queryInterface( 502 XAccessibleComponent.class, 503 xAccConCh); 504 505 if (xChAccComp != null) { 506 childComp.add(xChAccComp); 507 } 508 } catch (com.sun.star.lang.IndexOutOfBoundsException e) { 509 } 510 } 511 512 return childComp.toArray( 513 new XAccessibleComponent[childComp.size()]); 514 } 515 516 /** 517 * Gets the parent of the current component which support 518 * <code>XAccessibleComponent</code>. 519 * 520 * @return The parent or <code>null</code> if the component 521 * has no parent or some errors occurred. 522 */ getParentComponent()523 private XAccessibleComponent getParentComponent() { 524 XAccessible xAcc = UnoRuntime.queryInterface( 525 XAccessible.class, oObj); 526 527 if (xAcc == null) { 528 log.println("Component doesn't support XAccessible."); 529 530 return null; 531 } 532 533 XAccessibleContext xAccCon = xAcc.getAccessibleContext(); 534 XAccessible xAccPar = xAccCon.getAccessibleParent(); 535 536 if (xAccPar == null) { 537 log.println("Component has no accessible parent."); 538 539 return null; 540 } 541 542 XAccessibleContext xAccConPar = xAccPar.getAccessibleContext(); 543 XAccessibleComponent parent = UnoRuntime.queryInterface( 544 XAccessibleComponent.class, 545 xAccConPar); 546 547 if (parent == null) { 548 log.println( 549 "Accessible parent doesn't support XAccessibleComponent"); 550 551 return null; 552 } 553 554 return parent; 555 } 556 557 /** 558 * Just calls the method. 559 */ _getForeground()560 public void _getForeground() { 561 int forColor = oObj.getForeground(); 562 log.println("getForeground(): " + forColor); 563 tRes.tested("getForeground()", true); 564 } 565 566 /** 567 * Just calls the method. 568 */ _getBackground()569 public void _getBackground() { 570 int backColor = oObj.getBackground(); 571 log.println("getBackground(): " + backColor); 572 tRes.tested("getBackground()", true); 573 } 574 575 /** 576 * Restores initial component text. 577 */ 578 @Override after()579 protected void after() { 580 if (tEnv.getObjRelation("Destroy") != null) { 581 disposeEnvironment(); 582 } 583 } 584 isCovered(Point p)585 private boolean isCovered(Point p) { 586 int elements = KnownBounds.size(); 587 boolean Covered = false; 588 for (int k=0;k<elements;k++) { 589 Rectangle known = KnownBounds.get(k); 590 Covered = (known.X < p.X); 591 Covered &= (known.Y < p.Y); 592 Covered &= (p.Y < known.Y+known.Height); 593 Covered &= (p.X < known.X+known.Width); 594 595 if (Covered) { 596 break; 597 } 598 } 599 return Covered; 600 } 601 } 602