diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java b/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java index de917a34e00..184ca2c2d0b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java @@ -2156,15 +2156,14 @@ public class JTabbedPane extends JComponent AccessibleStateSet states; states = parent.getAccessibleContext().getAccessibleStateSet(); states.add(AccessibleState.SELECTABLE); - int i = parent.indexOfTabComponent(tabComponent); - if (i == parent.getSelectedIndex()) { + if (getPageIndex() == parent.getSelectedIndex()) { states.add(AccessibleState.SELECTED); } return states; } public int getAccessibleIndexInParent() { - return parent.indexOfTabComponent(tabComponent); + return getPageIndex(); } public int getAccessibleChildrenCount() { @@ -2272,8 +2271,7 @@ public class JTabbedPane extends JComponent } public Rectangle getBounds() { - return parent.getUI(). - getTabBounds(parent, parent.indexOfTabComponent(tabComponent)); + return parent.getUI().getTabBounds(parent, getPageIndex()); } public void setBounds(Rectangle r) { @@ -2343,7 +2341,33 @@ public class JTabbedPane extends JComponent } private String getTitle() { - return getTitleAt(parent.indexOfComponent(component)); + return getTitleAt(getPageIndex()); + } + + /* + * getPageIndex() has three valid scenarios: + * - null component and null tabComponent: use indexOfcomponent + * - non-null component: use indexOfComponent + * - null component and non-null tabComponent: use indexOfTabComponent + * + * Note: It's valid to have have a titled tab with a null component, e.g. + * myPane.add("my title", null); + * but it's only useful to have one of those because indexOfComponent(null) + * will find the first one. + * + * Note: indexofTab(title) is not useful because there are cases, due to + * subclassing, where Page.title is not set and title is managed in a subclass + * and fetched with an overridden JTabbedPane.getTitleAt(index). + */ + private int getPageIndex() { + int index; + if (component != null || (component == null && tabComponent == null)) { + index = parent.indexOfComponent(component); + } else { + // component is null, tabComponent is non-null + index = parent.indexOfTabComponent(tabComponent); + } + return index; } } diff --git a/jdk/test/javax/swing/JTabbedPane/8134116/Bug8134116.java b/jdk/test/javax/swing/JTabbedPane/8134116/Bug8134116.java index 15aa9f43260..ed408d969d9 100644 --- a/jdk/test/javax/swing/JTabbedPane/8134116/Bug8134116.java +++ b/jdk/test/javax/swing/JTabbedPane/8134116/Bug8134116.java @@ -4,7 +4,6 @@ import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; import javax.accessibility.Accessible; -import javax.accessibility.AccessibleComponent; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleState; import javax.accessibility.AccessibleStateSet; @@ -19,6 +18,8 @@ import javax.swing.plaf.nimbus.NimbusLookAndFeel; */ public class Bug8134116 { + private static volatile Exception exception = null; + public static void main(String args[]) throws Exception { try { @@ -29,75 +30,138 @@ public class Bug8134116 { SwingUtilities.invokeAndWait(() -> { JPanel panel0 = new JPanel(); + JPanel panel2 = new JPanel(); BadPane badPane = new BadPane(); badPane.add("zero", panel0); - badPane.add("one", null); + badPane.add("one", null); // no component + badPane.add("", panel2); // no title + badPane.add("", null); // no component, no title + // but give it that via a tabComponent + JPanel tabComponent = new JPanel(); + JLabel tabComponentLabel = new JLabel("three"); + tabComponent.add(tabComponentLabel); + badPane.setTabComponentAt(3, tabComponent); JFrame frame = new JFrame(); frame.add(badPane); frame.setSize(300, 300); frame.setVisible(true); - AccessibleContext ac = badPane.getAccessibleContext(); - Accessible page0 = ac.getAccessibleChild(0); - if (page0 == null) { - // Not something being tested, but checking anyway - throw new RuntimeException("getAccessibleChild(0) is null"); - } - Accessible page1 = ac.getAccessibleChild(1); - if (page1 == null) { - // Not something being tested, but checking anyway - throw new RuntimeException("getAccessibleChild(1) is null"); - } - // page0 and page1 are a JTabbedPane.Page, a private inner class - // and is an AccessibleContext - // and implements Accessible and AccessibleComponent - AccessibleContext pac0 = page0.getAccessibleContext(); - AccessibleContext pac1 = page1.getAccessibleContext(); + try { + AccessibleContext ac = badPane.getAccessibleContext(); + Accessible page0 = ac.getAccessibleChild(0); + if (page0 == null) { + // Not something being tested, but checking anyway + throw new RuntimeException("getAccessibleChild(0) is null"); + } + Accessible page1 = ac.getAccessibleChild(1); + if (page1 == null) { + // Not something being tested, but checking anyway + throw new RuntimeException("getAccessibleChild(1) is null"); + } + Accessible page2 = ac.getAccessibleChild(2); + Accessible page3 = ac.getAccessibleChild(3); + // page0 - page3 are JTabbedPane.Page, a private inner class + // and is an AccessibleContext + // and implements Accessible and AccessibleComponent + AccessibleContext pac0 = page0.getAccessibleContext(); + AccessibleContext pac1 = page1.getAccessibleContext(); + AccessibleContext pac2 = page2.getAccessibleContext(); + AccessibleContext pac3 = page3.getAccessibleContext(); - // the following would fail if JDK-8134116 fix not present + // test Page.getBounds + // ensure no IndexOutOfBoundsException + Rectangle r0 = pac0.getAccessibleComponent().getBounds(); + // make sure second Bounds is different than first + Rectangle r1 = pac1.getAccessibleComponent().getBounds(); + if (r1.equals(r0)) { + String msg = "Second tab should not have same bounds as first tab"; + throw new RuntimeException(msg); + } - // test Page.getBounds - // ensure no IndexOutOfBoundsException - pac0.getAccessibleComponent().getBounds(); + // test Page.getAccessibleStateSet + // At this point page 0 is selected + AccessibleStateSet accSS0 = pac0.getAccessibleStateSet(); + if (!accSS0.contains(AccessibleState.SELECTED)) { + String msg = "Empty title -> AccessibleState.SELECTED not set"; + throw new RuntimeException(msg); + } + // select second tab + badPane.setSelectedIndex(1); + AccessibleStateSet accSS1 = pac1.getAccessibleStateSet(); + if (!accSS1.contains(AccessibleState.SELECTED)) { + String msg = "Second tab selected but AccessibleState.SELECTED not set"; + throw new RuntimeException(msg); + } + // select third tab + badPane.setSelectedIndex(2); + AccessibleStateSet accSS2 = pac2.getAccessibleStateSet(); + if (!accSS1.contains(AccessibleState.SELECTED)) { + String msg = "Third tab selected but AccessibleState.SELECTED not set"; + throw new RuntimeException(msg); + } + // select fourth tab + badPane.setSelectedIndex(3); + AccessibleStateSet accSS3 = pac3.getAccessibleStateSet(); + if (!accSS1.contains(AccessibleState.SELECTED)) { + String msg = "Fourth tab selected but AccessibleState.SELECTED not set"; + throw new RuntimeException(msg); + } - // test Page.getAccessibleStateSet - // At this point page 0 is selected - AccessibleStateSet accSS0 = pac0.getAccessibleStateSet(); - if (!accSS0.contains(AccessibleState.SELECTED)) { - String msg = "Empty title -> AccessibleState.SELECTED not set"; - throw new RuntimeException(msg); - } + // test Page.getAccessibleIndexInParent + if (pac0.getAccessibleIndexInParent() == -1) { + String msg = "Empty title -> negative AccessibleIndexInParent"; + throw new RuntimeException(msg); + } + if (pac0.getAccessibleIndexInParent() != 0) { + String msg = "first tab is not at index 0 in parent"; + throw new RuntimeException(msg); + } + if (pac1.getAccessibleIndexInParent() != 1) { + String msg = "second tab (null component) is not at index 1 in parent"; + throw new RuntimeException(msg); + } + if (pac2.getAccessibleIndexInParent() != 2) { + String msg = "third tab (empty title) string is not at index 2 in parent"; + throw new RuntimeException(msg); + } + if (pac3.getAccessibleIndexInParent() != 3) { + String msg = "fourth tab (empty title, null component, has tabComponent) string is not at index 3 in parent"; + throw new RuntimeException(msg); + } - // test Page.getAccessibleIndexInParent - if (pac0.getAccessibleIndexInParent() == -1) { - String msg = "Empty title -> negative AccessibleIndexInParent"; - throw new RuntimeException(msg); - } + // test Page.getAccessibleName + String accName = pac0.getAccessibleName(); + if (!accName.equals("zero")) { + String msg = "Empty title -> empty AccessibleName"; + throw new RuntimeException(msg); + } + // test Page.getAccessibleName when component is null + accName = pac1.getAccessibleName(); + if (!accName.equals("one")) { + String msg = "AccessibleName of null panel not 'one'"; + throw new RuntimeException(msg); + } - // test Page.getAccessibleName - String accName = pac0.getAccessibleName(); - if (!accName.equals("zero")) { - String msg = "Empty title -> empty AccessibleName"; - throw new RuntimeException(msg); - } - // test Page.getAccessibleName when component is null - accName = pac1.getAccessibleName(); - if (!accName.equals("one")) { - String msg = "AccessibleName of null panel not 'one'"; - throw new RuntimeException(msg); - } + // test Page.setDisplayedMnemonicIndex + // Empty title -> IllegalArgumnetException + badPane.setDisplayedMnemonicIndexAt(0, 1); - // test Page.setDisplayedMnemonicIndex - // Empty title -> IllegalArgumnetException - badPane.setDisplayedMnemonicIndexAt(0, 1); - - // test Page.updateDisplayedMnemonicIndex - badPane.setMnemonicAt(0, KeyEvent.VK_Z); - if (badPane.getDisplayedMnemonicIndexAt(0) == -1) { - String msg="Empty title -> getDisplayedMnemonicIndexAt failure"; - throw new RuntimeException(msg); + // test Page.updateDisplayedMnemonicIndex + badPane.setMnemonicAt(0, KeyEvent.VK_Z); + if (badPane.getDisplayedMnemonicIndexAt(0) == -1) { + String msg="Empty title -> getDisplayedMnemonicIndexAt failure"; + throw new RuntimeException(msg); + } + } catch (Exception e) { + exception = e; } }); + if (exception != null) { + System.out.println("Test failed: " + exception.getMessage()); + throw exception; + } else { + System.out.println("Test passed."); + } } // The following is likely what is being done in Burp Suite