1 /*
2 * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
1440 }
1441 }, ac);
1442 if (stateSet != null) {
1443 String s = "";
1444 AccessibleState[] states = stateSet.toArray();
1445 if (states != null && states.length > 0) {
1446 s = states[0].toDisplayString(Locale.US);
1447 for (int i = 1; i < states.length; i++) {
1448 s = s + "," + states[i].toDisplayString(Locale.US);
1449 }
1450 }
1451 references.increment(s);
1452 debugString("[INFO]: Returning AccessibleStateSet en_US from Context: " + s);
1453 return s;
1454 }
1455 }
1456 debugString("[ERROR]: getAccessibleStatesStringFromContext; ac = null");
1457 return null;
1458 }
1459
1460 /**
1461 * returns the AccessibleParent from an AccessibleContext
1462 */
1463 private AccessibleContext getAccessibleParentFromContext(final AccessibleContext ac) {
1464 if (ac==null)
1465 return null;
1466 return InvocationUtils.invokeAndWait(new Callable<AccessibleContext>() {
1467 @Override
1468 public AccessibleContext call() throws Exception {
1469 Accessible a = ac.getAccessibleParent();
1470 if (a != null) {
1471 AccessibleContext apc = a.getAccessibleContext();
1472 if (apc != null) {
1473 return apc;
1474 }
1475 }
1476 return null;
1477 }
1478 }, ac);
1479 }
1480
1481 /**
1482 * returns the AccessibleIndexInParent from an AccessibleContext
1483 */
1484 private int getAccessibleIndexInParentFromContext(final AccessibleContext ac) {
1485 if (ac==null)
1486 return -1;
1487 return InvocationUtils.invokeAndWait(new Callable<Integer>() {
1488 @Override
1489 public Integer call() throws Exception {
1490 return ac.getAccessibleIndexInParent();
1491 }
1492 }, ac);
1493 }
1494
1495 /**
1496 * returns the AccessibleChild count from an AccessibleContext
1497 */
1498 private int getAccessibleChildrenCountFromContext(final AccessibleContext ac) {
1499 if (ac==null)
1500 return -1;
1501 return InvocationUtils.invokeAndWait(new Callable<Integer>() {
1502 @Override
1503 public Integer call() throws Exception {
1504 return ac.getAccessibleChildrenCount();
1505 }
1506 }, ac);
1507 }
1508
1509 /**
1510 * returns the AccessibleChild Context from an AccessibleContext
1511 */
1512 private AccessibleContext getAccessibleChildFromContext(final AccessibleContext ac, final int index) {
1513
1514 if (ac == null) {
1515 return null;
1516 }
1517
1518 final JTable table = InvocationUtils.invokeAndWait(new Callable<JTable>() {
1519 @Override
1520 public JTable call() throws Exception {
1521 // work-around for AccessibleJTable.getCurrentAccessibleContext returning
1522 // wrong renderer component when cell contains more than one component
1523 Accessible parent = ac.getAccessibleParent();
1524 if (parent != null) {
1525 int indexInParent = ac.getAccessibleIndexInParent();
1526 Accessible child =
1527 parent.getAccessibleContext().getAccessibleChild(indexInParent);
1528 if (child instanceof JTable) {
1529 return (JTable) child;
1530 }
1531 }
1532 return null;
1533 }
1534 }, ac);
1535
1536 if (table == null) {
1537 return InvocationUtils.invokeAndWait(new Callable<AccessibleContext>() {
1538 @Override
1539 public AccessibleContext call() throws Exception {
1540 Accessible a = ac.getAccessibleChild(index);
1541 if (a != null) {
1542 return a.getAccessibleContext();
1543 }
1544 return null;
1545 }
1546 }, ac);
1547 }
1548
1549 final AccessibleTable at = getAccessibleTableFromContext(ac);
1550
1551 final int row = getAccessibleTableRow(at, index);
1552 final int column = getAccessibleTableColumn(at, index);
1553
1554 return InvocationUtils.invokeAndWait(new Callable<AccessibleContext>() {
1555 @Override
1556 public AccessibleContext call() throws Exception {
1557 TableCellRenderer renderer = table.getCellRenderer(row, column);
1558 if (renderer == null) {
1559 Class<?> columnClass = table.getColumnClass(column);
1560 renderer = table.getDefaultRenderer(columnClass);
3500 }
3501 return null;
3502 }
3503 }, ac);
3504 }
3505
3506 /*
3507 * returns the number of targets in a relation in the AccessibleContext's
3508 * AccessibleRelationSet
3509 */
3510 private int getAccessibleRelationTargetCount(final AccessibleContext ac, final int i) {
3511 return InvocationUtils.invokeAndWait(new Callable<Integer>() {
3512 @Override
3513 public Integer call() throws Exception {
3514 if (ac != null) {
3515 AccessibleRelationSet ars = ac.getAccessibleRelationSet();
3516 if (ars != null) {
3517 AccessibleRelation[] relations = ars.toArray();
3518 if (relations != null && i >= 0 && i < relations.length) {
3519 Object[] targets = relations[i].getTarget();
3520 return targets.length;
3521 }
3522 }
3523 }
3524 return -1;
3525 }
3526 }, ac);
3527 }
3528
3529 /*
3530 * returns the jth target in the ith relation in the AccessibleContext's
3531 * AccessibleRelationSet
3532 */
3533 private AccessibleContext getAccessibleRelationTarget(final AccessibleContext ac,
3534 final int i, final int j) {
3535 debugString("[INFO]: ***** getAccessibleRelationTarget");
3536 return InvocationUtils.invokeAndWait(new Callable<AccessibleContext>() {
3537 @Override
3538 public AccessibleContext call() throws Exception {
3539 if (ac != null) {
3540 AccessibleRelationSet ars = ac.getAccessibleRelationSet();
3541 if (ars != null) {
3542 AccessibleRelation[] relations = ars.toArray();
3543 if (relations != null && i >= 0 && i < relations.length) {
3544 Object[] targets = relations[i].getTarget();
3545 if (targets != null && j >= 0 & j < targets.length) {
3546 Object o = targets[j];
3547 if (o instanceof Accessible) {
3548 return ((Accessible) o).getAccessibleContext();
3549 }
3550 }
3551 }
3552 }
3553 }
3554 return null;
3555 }
3556 }, ac);
3557 }
3558
3559 // ========= AccessibleHypertext =========
3560
3561 private Map<AccessibleHypertext, AccessibleContext> hyperTextContextMap = new WeakHashMap<>();
3562 private Map<AccessibleHyperlink, AccessibleContext> hyperLinkContextMap = new WeakHashMap<>();
3563
3564 /*
3565 * Returns the AccessibleHypertext
3566 */
3567 private AccessibleHypertext getAccessibleHypertext(final AccessibleContext ac) {
3568 debugString("[INFO]: getAccessibleHyperlink");
3569 if (ac==null)
3570 return null;
3571 AccessibleHypertext hypertext = InvocationUtils.invokeAndWait(new Callable<AccessibleHypertext>() {
3572 @Override
3573 public AccessibleHypertext call() throws Exception {
3574 AccessibleText at = ac.getAccessibleText();
3575 if (!(at instanceof AccessibleHypertext)) {
3576 return null;
|
1 /*
2 * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
1440 }
1441 }, ac);
1442 if (stateSet != null) {
1443 String s = "";
1444 AccessibleState[] states = stateSet.toArray();
1445 if (states != null && states.length > 0) {
1446 s = states[0].toDisplayString(Locale.US);
1447 for (int i = 1; i < states.length; i++) {
1448 s = s + "," + states[i].toDisplayString(Locale.US);
1449 }
1450 }
1451 references.increment(s);
1452 debugString("[INFO]: Returning AccessibleStateSet en_US from Context: " + s);
1453 return s;
1454 }
1455 }
1456 debugString("[ERROR]: getAccessibleStatesStringFromContext; ac = null");
1457 return null;
1458 }
1459
1460 private int getNonVisibleChildrenCountTillIndex(AccessibleContext parentAC, int index) {
1461 if (parentAC != null && index >= 0 && index < parentAC.getAccessibleChildrenCount()) {
1462 int nonVisibleChildrenCount = 0;
1463 for (int i = 0; i <= index; i++) {
1464 if (!parentAC.getAccessibleChild(i).getAccessibleContext().getAccessibleStateSet().contains(AccessibleState.VISIBLE)) {
1465 nonVisibleChildrenCount++;
1466 }
1467 }
1468 return nonVisibleChildrenCount;
1469 }
1470 return 0;
1471 }
1472
1473 private Accessible getVisibleChildAtIndex(AccessibleContext parentAC, int index) {
1474 if (parentAC != null && index >= 0 && index < parentAC.getAccessibleChildrenCount()) {
1475 int visibleIndex = -1;
1476 int childrenCount = parentAC.getAccessibleChildrenCount();
1477 for (int i = 0; i <= childrenCount; i++) {
1478 Accessible child = parentAC.getAccessibleChild(i);
1479 if (child != null) {
1480 AccessibleContext ac = child.getAccessibleContext();
1481 if (ac != null && ac.getAccessibleStateSet().contains(AccessibleState.VISIBLE)) {
1482 visibleIndex++;
1483 }
1484 if (visibleIndex == index) {
1485 return child;
1486 }
1487 }
1488 }
1489 }
1490 return null;
1491 }
1492 /**
1493 * returns the AccessibleParent from an AccessibleContext
1494 */
1495 private AccessibleContext getAccessibleParentFromContext(final AccessibleContext ac) {
1496 if (ac==null)
1497 return null;
1498 return InvocationUtils.invokeAndWait(new Callable<AccessibleContext>() {
1499 @Override
1500 public AccessibleContext call() throws Exception {
1501 Accessible a = ac.getAccessibleParent();
1502 if (a != null) {
1503 AccessibleContext apc = a.getAccessibleContext();
1504 if (apc != null) {
1505 return apc;
1506 }
1507 }
1508 return null;
1509 }
1510 }, ac);
1511 }
1512
1513 /**
1514 * returns the AccessibleIndexInParent from an AccessibleContext
1515 */
1516 private int getAccessibleIndexInParentFromContext(final AccessibleContext ac) {
1517 if (ac==null)
1518 return -1;
1519 return InvocationUtils.invokeAndWait(new Callable<Integer>() {
1520 @Override
1521 public Integer call() throws Exception {
1522 int indexInParent = ac.getAccessibleIndexInParent();
1523 Accessible parent = ac.getAccessibleParent();
1524 if (parent != null) {
1525 indexInParent -= getNonVisibleChildrenCountTillIndex(parent.getAccessibleContext(), indexInParent);
1526 }
1527 return indexInParent;
1528 }
1529 }, ac);
1530 }
1531
1532 /**
1533 * returns the AccessibleChild count from an AccessibleContext
1534 */
1535 private int getAccessibleChildrenCountFromContext(final AccessibleContext ac) {
1536 if (ac==null)
1537 return -1;
1538 return InvocationUtils.invokeAndWait(new Callable<Integer>() {
1539 @Override
1540 public Integer call() throws Exception {
1541 int childrenCount = ac.getAccessibleChildrenCount();
1542 return childrenCount - getNonVisibleChildrenCountTillIndex(ac, childrenCount - 1);
1543 }
1544 }, ac);
1545 }
1546
1547 /**
1548 * returns the AccessibleChild Context from an AccessibleContext
1549 */
1550 private AccessibleContext getAccessibleChildFromContext(final AccessibleContext ac, final int index) {
1551
1552 if (ac == null) {
1553 return null;
1554 }
1555
1556 final JTable table = InvocationUtils.invokeAndWait(new Callable<JTable>() {
1557 @Override
1558 public JTable call() throws Exception {
1559 // work-around for AccessibleJTable.getCurrentAccessibleContext returning
1560 // wrong renderer component when cell contains more than one component
1561 Accessible parent = ac.getAccessibleParent();
1562 if (parent != null) {
1563 int indexInParent = ac.getAccessibleIndexInParent();
1564 Accessible child =
1565 parent.getAccessibleContext().getAccessibleChild(indexInParent);
1566 if (child instanceof JTable) {
1567 return (JTable) child;
1568 }
1569 }
1570 return null;
1571 }
1572 }, ac);
1573
1574 if (table == null) {
1575 return InvocationUtils.invokeAndWait(new Callable<AccessibleContext>() {
1576 @Override
1577 public AccessibleContext call() throws Exception {
1578 Accessible a = getVisibleChildAtIndex(ac, index);
1579 if (a != null) {
1580 return a.getAccessibleContext();
1581 }
1582 return null;
1583 }
1584 }, ac);
1585 }
1586
1587 final AccessibleTable at = getAccessibleTableFromContext(ac);
1588
1589 final int row = getAccessibleTableRow(at, index);
1590 final int column = getAccessibleTableColumn(at, index);
1591
1592 return InvocationUtils.invokeAndWait(new Callable<AccessibleContext>() {
1593 @Override
1594 public AccessibleContext call() throws Exception {
1595 TableCellRenderer renderer = table.getCellRenderer(row, column);
1596 if (renderer == null) {
1597 Class<?> columnClass = table.getColumnClass(column);
1598 renderer = table.getDefaultRenderer(columnClass);
3538 }
3539 return null;
3540 }
3541 }, ac);
3542 }
3543
3544 /*
3545 * returns the number of targets in a relation in the AccessibleContext's
3546 * AccessibleRelationSet
3547 */
3548 private int getAccessibleRelationTargetCount(final AccessibleContext ac, final int i) {
3549 return InvocationUtils.invokeAndWait(new Callable<Integer>() {
3550 @Override
3551 public Integer call() throws Exception {
3552 if (ac != null) {
3553 AccessibleRelationSet ars = ac.getAccessibleRelationSet();
3554 if (ars != null) {
3555 AccessibleRelation[] relations = ars.toArray();
3556 if (relations != null && i >= 0 && i < relations.length) {
3557 Object[] targets = relations[i].getTarget();
3558 if (targets != null) {
3559 int targetCount = targets.length -
3560 getNonVisibleTargetCountTillIndex(targets, targets.length - 1);
3561 return targetCount;
3562 }
3563 }
3564 }
3565 }
3566 return -1;
3567 }
3568 }, ac);
3569 }
3570
3571 /*
3572 * returns the jth target in the ith relation in the AccessibleContext's
3573 * AccessibleRelationSet
3574 */
3575 private AccessibleContext getAccessibleRelationTarget(final AccessibleContext ac,
3576 final int i, final int j) {
3577 debugString("[INFO]: ***** getAccessibleRelationTarget");
3578 return InvocationUtils.invokeAndWait(new Callable<AccessibleContext>() {
3579 @Override
3580 public AccessibleContext call() throws Exception {
3581 if (ac != null) {
3582 AccessibleRelationSet ars = ac.getAccessibleRelationSet();
3583 if (ars != null) {
3584 AccessibleRelation[] relations = ars.toArray();
3585 if (relations != null && i >= 0 && i < relations.length) {
3586 Object[] targets = relations[i].getTarget();
3587 if (targets != null && j >= 0 & j < targets.length) {
3588 Object o = getVisibleTargetAtIndex(targets, j);
3589 if (o instanceof Accessible) {
3590 return ((Accessible) o).getAccessibleContext();
3591 }
3592 }
3593 }
3594 }
3595 }
3596 return null;
3597 }
3598 }, ac);
3599 }
3600
3601 private Object getVisibleTargetAtIndex(Object[] targets, int index) {
3602 if (index >= 0 && index < targets.length) {
3603 int visibleTargetIndex = -1;
3604 for (int i = 0; i < targets.length; i++) {
3605 if (targets[i] instanceof Accessible) {
3606 AccessibleContext ac = ((Accessible) targets[i]).getAccessibleContext();
3607 if (ac != null && ac.getAccessibleStateSet().contains(AccessibleState.VISIBLE)) {
3608 visibleTargetIndex++;
3609 }
3610 if (visibleTargetIndex == index) {
3611 return targets[i];
3612 }
3613 }
3614 }
3615 }
3616 return null;
3617 }
3618
3619 private int getNonVisibleTargetCountTillIndex(Object[] targets, int index) {
3620 if (index >= 0 && index < targets.length) {
3621 int nonVisibleTargetsCount = 0;
3622 for (int i = 0; i <= index; i++) {
3623 if (targets[i] instanceof Accessible) {
3624 AccessibleContext ac = ((Accessible) targets[i]).getAccessibleContext();
3625 if (ac != null && !ac.getAccessibleStateSet().contains(AccessibleState.VISIBLE)) {
3626 nonVisibleTargetsCount++;
3627 }
3628 }
3629 }
3630 return nonVisibleTargetsCount;
3631 }
3632 return 0;
3633 }
3634
3635 // ========= AccessibleHypertext =========
3636
3637 private Map<AccessibleHypertext, AccessibleContext> hyperTextContextMap = new WeakHashMap<>();
3638 private Map<AccessibleHyperlink, AccessibleContext> hyperLinkContextMap = new WeakHashMap<>();
3639
3640 /*
3641 * Returns the AccessibleHypertext
3642 */
3643 private AccessibleHypertext getAccessibleHypertext(final AccessibleContext ac) {
3644 debugString("[INFO]: getAccessibleHyperlink");
3645 if (ac==null)
3646 return null;
3647 AccessibleHypertext hypertext = InvocationUtils.invokeAndWait(new Callable<AccessibleHypertext>() {
3648 @Override
3649 public AccessibleHypertext call() throws Exception {
3650 AccessibleText at = ac.getAccessibleText();
3651 if (!(at instanceof AccessibleHypertext)) {
3652 return null;
|