diff --git a/jdk/make/copy/Copy-java.base.gmk b/jdk/make/copy/Copy-java.base.gmk
index 296442e0f13..157bfb31ef6 100644
--- a/jdk/make/copy/Copy-java.base.gmk
+++ b/jdk/make/copy/Copy-java.base.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -168,9 +168,6 @@ POLICY_SRC_LIST :=
ifeq ($(OPENJDK_TARGET_OS), windows)
POLICY_SRC_LIST += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/conf/security/java.policy
- ifndef OPENJDK
- POLICY_SRC_LIST += $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/conf/security/java.policy
- endif
endif
POLICY_SRC_LIST += $(POLICY_SRC)
diff --git a/jdk/make/copy/Copy-jdk.accessibility.gmk b/jdk/make/copy/Copy-jdk.accessibility.gmk
new file mode 100644
index 00000000000..4c089c16883
--- /dev/null
+++ b/jdk/make/copy/Copy-jdk.accessibility.gmk
@@ -0,0 +1,47 @@
+#
+# Copyright (c) 2104, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include CopyCommon.gmk
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+ TARGETS += $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgeCallbacks.h \
+ $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgeCalls.h \
+ $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgePackages.h \
+ $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgeCalls.c \
+ $(CONF_DST_DIR)/accessibility.properties
+
+ $(INCLUDE_DST_OS_DIR)/bridge/%: \
+ $(JDK_TOPDIR)/src/jdk.accessibility/windows/native/include/bridge/%
+ $(install-file)
+
+ $(CONF_DST_DIR)/accessibility.properties: \
+ $(JDK_TOPDIR)/src/jdk.accessibility/windows/conf/accessibility.properties
+ $(install-file)
+
+endif
+
+################################################################################
diff --git a/jdk/make/launcher/Launcher-jdk.accessibility.gmk b/jdk/make/launcher/Launcher-jdk.accessibility.gmk
new file mode 100644
index 00000000000..5dfd6e999b3
--- /dev/null
+++ b/jdk/make/launcher/Launcher-jdk.accessibility.gmk
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LauncherCommon.gmk
+
+################################################################################
+# jabswitch
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+
+ JABSWITCH_SRC := $(JDK_TOPDIR)/src/jdk.accessibility/windows/native/jabswitch
+ ACCESSBRIDGE_SRC := $(JDK_TOPDIR)/src/jdk.accessibility/windows/native/common
+
+ $(eval $(call SetupNativeCompilation,BUILD_JABSWITCH, \
+ SRC := $(JABSWITCH_SRC), \
+ INCLUDE_FILES := jabswitch.cpp, \
+ LANG := C++, \
+ CFLAGS := $(filter-out -Zc:wchar_t-, $(CFLAGS_JDKEXE)) -Zc:wchar_t \
+ -analyze- -Od -Gd -D_WINDOWS \
+ -D_UNICODE -DUNICODE -RTC1 -EHsc, \
+ DISABLED_WARNINGS_microsoft := 4267, \
+ LDFLAGS := $(LDFLAGS_JDKEXE) \
+ Advapi32.lib Version.lib User32.lib, \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/jdk.accessibility/jabswitch, \
+ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_cmds/jdk.accessibility, \
+ PROGRAM := jabswitch, \
+ DEBUG_SYMBOLS := true, \
+ VERSIONINFO_RESOURCE := $(ACCESSBRIDGE_SRC)/AccessBridgeStatusWindow.RC, \
+ RC_FLAGS := $(RC_FLAGS) \
+ -D "JDK_FNAME=jabswitch.exe" \
+ -D "JDK_INTERNAL_NAME=jabswitch" \
+ -D "JDK_FTYPE=0x01L", \
+ MANIFEST := $(JABSWITCH_SRC)/jabswitch.manifest))
+
+ TARGETS += $(BUILD_JABSWITCH)
+endif
+
+################################################################################
diff --git a/jdk/make/lib/Lib-jdk.accessibility.gmk b/jdk/make/lib/Lib-jdk.accessibility.gmk
new file mode 100644
index 00000000000..cee8d0ed191
--- /dev/null
+++ b/jdk/make/lib/Lib-jdk.accessibility.gmk
@@ -0,0 +1,138 @@
+#
+# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LibCommon.gmk
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+
+ ROOT_SRCDIR := $(JDK_TOPDIR)/src/jdk.accessibility/windows/native
+ JAVA_AB_SRCDIR := $(ROOT_SRCDIR)/libjavaaccessbridge $(ROOT_SRCDIR)/common
+ WIN_AB_SRCDIR := $(ROOT_SRCDIR)/libwindowsaccessbridge $(ROOT_SRCDIR)/common
+ SYSINFO_SRCDIR := $(ROOT_SRCDIR)/libjabsysinfo
+ ACCESSBRIDGE_CFLAGS := -I$(SUPPORT_OUTPUTDIR)/headers/jdk.accessibility \
+ -I$(JDK_TOPDIR)/src/java.desktop/windows/native/include \
+ -I$(JDK_TOPDIR)/src/java.desktop/share/native/include
+
+ define SetupJavaDLL
+ # Parameter 1 Suffix
+ # Parameter 2 ACCESSBRIDGE_ARCH_ suffix
+
+ $(call SetupNativeCompilation,BUILD_JAVAACCESSBRIDGE$1, \
+ LIBRARY = javaaccessbridge$1, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(JAVA_AB_SRCDIR), \
+ LANG := C++, \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) $(ACCESSBRIDGE_CFLAGS) \
+ $(addprefix -I,$(JAVA_AB_SRCDIR)) \
+ -I$(JDK_TOPDIR)/src/jdk.accessibility/windows/native/include/bridge \
+ -DACCESSBRIDGE_ARCH_$2, \
+ LDFLAGS := $(LDFLAGS_JDKLIB) kernel32.lib user32.lib gdi32.lib \
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib \
+ $(SUPPORT_OUTPUTDIR)/native/java.desktop/libjawt/jawt.lib \
+ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib \
+ -subsystem:windows, \
+ VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \
+ RC_FLAGS := $(RC_FLAGS) \
+ -D "JDK_FNAME=javaaccessbridge$1.dll" \
+ -D "JDK_INTERNAL_NAME=javaaccessbridge$1" \
+ -D "JDK_FTYPE=0x02L", \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjavaaccessbridge$1, \
+ DEBUG_SYMBOLS := true)
+
+ $$(BUILD_JAVAACCESSBRIDGE$1): $(SUPPORT_OUTPUTDIR)/native/java.desktop/libjawt/jawt.lib
+
+ TARGETS += $$(BUILD_JAVAACCESSBRIDGE$1)
+ endef
+
+ define SetupWinDLL
+ # Parameter 1 Suffix
+ # Parameter 2 ACCESSBRIDGE_ARCH_ suffix
+ $(call SetupNativeCompilation,BUILD_WINDOWSACCESSBRIDGE$1, \
+ LIBRARY = windowsaccessbridge$1, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(WIN_AB_SRCDIR), \
+ LANG := C++, \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(filter-out -MD, $(CFLAGS_JDKLIB)) -MT $(ACCESSBRIDGE_CFLAGS) \
+ $(addprefix -I,$(WIN_AB_SRCDIR)) \
+ -I$(JDK_TOPDIR)/src/jdk.accessibility/windows/native/include/bridge \
+ -DACCESSBRIDGE_ARCH_$2, \
+ LDFLAGS := $(LDFLAGS_JDKLIB) kernel32.lib user32.lib gdi32.lib \
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib \
+ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib \
+ -subsystem:windows \
+ -def:$(ROOT_SRCDIR)/libwindowsaccessbridge/WinAccessBridge.DEF, \
+ VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \
+ RC_FLAGS := $(RC_FLAGS) \
+ -D "JDK_FNAME=windowsaccessbridge$1.dll" \
+ -D "JDK_INTERNAL_NAME=windowsaccessbridge$1" \
+ -D "JDK_FTYPE=0x02L", \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libwindowsaccessbridge$1, \
+ DEBUG_SYMBOLS := true)
+
+ TARGETS += $$(BUILD_WINDOWSACCESSBRIDGE$1)
+
+ endef
+
+ define SetupAccessBridgeSysInfo
+
+ $(call SetupNativeCompilation,BUILD_ACCESSBRIDGESYSINFO, \
+ LIBRARY = jabsysinfo, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(SYSINFO_SRCDIR), \
+ LANG := C++, \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) $(ACCESSBRIDGE_CFLAGS), \
+ LDFLAGS := $(LDFLAGS_JDKLIB) \
+ -subsystem:windows -machine:I386, \
+ VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \
+ RC_FLAGS := $(RC_FLAGS) \
+ -D "JDK_FNAME=jabsysinfo.dll" \
+ -D "JDK_INTERNAL_NAME=jabsysinfo" \
+ -D "JDK_FTYPE=0x02L", \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/lib/libjabsysinfo, \
+ DEBUG_SYMBOLS := true)
+
+ TARGETS += $$(BUILD_ACCESSBRIDGESYSINFO)
+
+ endef
+
+ ifeq ($(OPENJDK_TARGET_CPU_BITS), 32)
+ $(eval $(call SetupAccessBridgeSysInfo))
+ $(eval $(call SetupJavaDLL,-32,32))
+ $(eval $(call SetupJavaDLL,,LEGACY))
+ $(eval $(call SetupWinDLL,-32,32))
+ $(eval $(call SetupWinDLL,,LEGACY))
+ else
+ $(eval $(call SetupJavaDLL,,64))
+ $(eval $(call SetupWinDLL,-64,64))
+ endif
+
+endif
+
+################################################################################
diff --git a/jdk/make/src/classes/build/tools/module/ext.modules b/jdk/make/src/classes/build/tools/module/ext.modules
index 934d4e9ba16..70e3bf49b0c 100644
--- a/jdk/make/src/classes/build/tools/module/ext.modules
+++ b/jdk/make/src/classes/build/tools/module/ext.modules
@@ -4,7 +4,7 @@ java.corba
java.transaction
java.xml.bind
java.xml.ws
-jdk.accessbridge
+jdk.accessibility
jdk.crypto.ec
jdk.crypto.mscapi
jdk.crypto.pkcs11
diff --git a/jdk/src/java.base/windows/conf/security/java.policy b/jdk/src/java.base/windows/conf/security/java.policy
index 01d7bef3f43..cff0be5af98 100644
--- a/jdk/src/java.base/windows/conf/security/java.policy
+++ b/jdk/src/java.base/windows/conf/security/java.policy
@@ -6,3 +6,7 @@ grant codeBase "jrt:/jdk.crypto.mscapi" {
permission java.security.SecurityPermission "clearProviderProperties.SunMSCAPI";
permission java.security.SecurityPermission "removeProviderProperty.SunMSCAPI";
};
+
+grant codeBase "jrt:/jdk.accessibility" {
+ permission java.security.AllPermission;
+};
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java
new file mode 100644
index 00000000000..7b0f8c29e06
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java
@@ -0,0 +1,1526 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.accessibility.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import sun.awt.AWTPermissions;
+
+/**
+ *
The {@code AWTEventMonitor} implements a suite of listeners that are
+ * conditionally installed on every AWT component instance in the Java
+ * Virtual Machine. The events captured by these listeners are made
+ * available through a unified set of listeners supported by {@code AWTEventMonitor}.
+ * With this, all the individual events on each of the AWT component
+ * instances are funneled into one set of listeners broken down by category
+ * (see {@link EventID} for the categories).
+ *
This class depends upon {@link EventQueueMonitor}, which provides the base
+ * level support for capturing the top-level containers as they are created.
+ */
+
+@jdk.Exported
+public class AWTEventMonitor {
+
+ static private boolean runningOnJDK1_4 = false;
+
+ /**
+ * The current component with keyboard focus.
+ *
+ * @see #getComponentWithFocus
+ *
+ * @deprecated This field is unused; to get the component with focus use the
+ * getComponentWithFocus method.
+ */
+ @Deprecated
+ static protected Component componentWithFocus = null;
+
+ static private Component componentWithFocus_private = null;
+
+ // Low-level listeners
+ /**
+ * The current list of registered ComponentListener classes.
+ *
+ * @see #addComponentListener
+ * @see #removeComponentListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected ComponentListener componentListener = null;
+
+ static private ComponentListener componentListener_private = null;
+
+ /**
+ * The current list of registered ContainerListener classes.
+ *
+ * @see #addContainerListener
+ * @see #removeContainerListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected ContainerListener containerListener = null;
+
+ static private ContainerListener containerListener_private = null;
+
+ /**
+ * The current list of registered FocusListener classes.
+ *
+ * @see #addFocusListener
+ * @see #removeFocusListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected FocusListener focusListener = null;
+
+ static private FocusListener focusListener_private = null;
+
+ /**
+ * The current list of registered KeyListener classes.
+ *
+ * @see #addKeyListener
+ * @see #removeKeyListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected KeyListener keyListener = null;
+
+ static private KeyListener keyListener_private = null;
+
+ /**
+ * The current list of registered MouseListener classes.
+ *
+ * @see #addMouseListener
+ * @see #removeMouseListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected MouseListener mouseListener = null;
+
+ static private MouseListener mouseListener_private = null;
+
+ /**
+ * The current list of registered MouseMotionListener classes.
+ *
+ * @see #addMouseMotionListener
+ * @see #removeMouseMotionListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected MouseMotionListener mouseMotionListener = null;
+
+ static private MouseMotionListener mouseMotionListener_private = null;
+
+ /**
+ * The current list of registered WindowListener classes.
+ *
+ * @see #addWindowListener
+ * @see #removeWindowListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected WindowListener windowListener = null;
+
+ static private WindowListener windowListener_private = null;
+
+
+ // Semantic listeners
+ /**
+ * The current list of registered ActionListener classes.
+ *
+ * @see #addActionListener
+ * @see #removeActionListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected ActionListener actionListener = null;
+
+ static private ActionListener actionListener_private = null;
+
+ /**
+ * The current list of registered AdjustmentListener classes.
+ *
+ * @see #addAdjustmentListener
+ * @see #removeAdjustmentListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected AdjustmentListener adjustmentListener = null;
+
+ static private AdjustmentListener adjustmentListener_private = null;
+
+ /**
+ * The current list of registered ItemListener classes.
+ *
+ * @see #addItemListener
+ * @see #removeItemListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected ItemListener itemListener = null;
+
+ static private ItemListener itemListener_private = null;
+
+ /**
+ * The current list of registered TextListener classes.
+ *
+ * @see #addTextListener
+ * @see #removeTextListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected TextListener textListener = null;
+
+ static private TextListener textListener_private = null;
+
+
+ /**
+ * The actual listener that is installed on the component instances.
+ * This listener calls the other registered listeners when an event
+ * occurs. By doing things this way, the actual number of listeners
+ * installed on a component instance is drastically reduced.
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected AWTEventsListener awtListener = new AWTEventsListener();
+
+ static private final AWTEventsListener awtListener_private = new AWTEventsListener();
+
+ /**
+ * Returns the component that currently has keyboard focus. The return
+ * value can be null.
+ *
+ * @return the component that has keyboard focus
+ */
+ static public Component getComponentWithFocus() {
+ return componentWithFocus_private;
+ }
+
+ /*
+ * Check permissions
+ */
+ static private void checkInstallPermission() {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkPermission(AWTPermissions.ALL_AWT_EVENTS_PERMISSION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#COMPONENT COMPONENT}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeComponentListener
+ */
+ static public void addComponentListener(ComponentListener l) {
+ if (componentListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.COMPONENT);
+ }
+ componentListener_private = AWTEventMulticaster.add(componentListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#COMPONENT COMPONENT} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addComponentListener
+ */
+ static public void removeComponentListener(ComponentListener l) {
+ componentListener_private = AWTEventMulticaster.remove(componentListener_private, l);
+ if (componentListener_private == null) {
+ awtListener_private.removeListeners(EventID.COMPONENT);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#CONTAINER CONTAINER}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeContainerListener
+ */
+ static public void addContainerListener(ContainerListener l) {
+ containerListener_private = AWTEventMulticaster.add(containerListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#CONTAINER CONTAINER} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addContainerListener
+ */
+ static public void removeContainerListener(ContainerListener l) {
+ containerListener_private = AWTEventMulticaster.remove(containerListener_private, l);
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#FOCUS FOCUS} events
+ * on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeFocusListener
+ */
+ static public void addFocusListener(FocusListener l) {
+ focusListener_private = AWTEventMulticaster.add(focusListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives {@link EventID#FOCUS FOCUS}
+ * events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addFocusListener
+ */
+ static public void removeFocusListener(FocusListener l) {
+ focusListener_private = AWTEventMulticaster.remove(focusListener_private, l);
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#KEY KEY} events on each
+ * component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeKeyListener
+ */
+ static public void addKeyListener(KeyListener l) {
+ if (keyListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.KEY);
+ }
+ keyListener_private = AWTEventMulticaster.add(keyListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives {@link EventID#KEY KEY}
+ * events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addKeyListener
+ */
+ static public void removeKeyListener(KeyListener l) {
+ keyListener_private = AWTEventMulticaster.remove(keyListener_private, l);
+ if (keyListener_private == null) {
+ awtListener_private.removeListeners(EventID.KEY);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#MOUSE MOUSE} events
+ * on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeMouseListener
+ */
+ static public void addMouseListener(MouseListener l) {
+ if (mouseListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.MOUSE);
+ }
+ mouseListener_private = AWTEventMulticaster.add(mouseListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#MOUSE MOUSE} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addMouseListener
+ */
+ static public void removeMouseListener(MouseListener l) {
+ mouseListener_private = AWTEventMulticaster.remove(mouseListener_private, l);
+ if (mouseListener_private == null) {
+ awtListener_private.removeListeners(EventID.MOUSE);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all mouse {@link EventID#MOTION MOTION}
+ * events on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeMouseMotionListener
+ */
+ static public void addMouseMotionListener(MouseMotionListener l) {
+ if (mouseMotionListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.MOTION);
+ }
+ mouseMotionListener_private = AWTEventMulticaster.add(mouseMotionListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#MOTION MOTION} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addMouseMotionListener
+ */
+ static public void removeMouseMotionListener(MouseMotionListener l) {
+ mouseMotionListener_private = AWTEventMulticaster.remove(mouseMotionListener_private, l);
+ if (mouseMotionListener_private == null) {
+ awtListener_private.removeListeners(EventID.MOTION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#WINDOW WINDOW}
+ * events on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeWindowListener
+ */
+ static public void addWindowListener(WindowListener l) {
+ if (windowListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.WINDOW);
+ }
+ windowListener_private = AWTEventMulticaster.add(windowListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#WINDOW WINDOW} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addWindowListener
+ */
+ static public void removeWindowListener(WindowListener l) {
+ windowListener_private = AWTEventMulticaster.remove(windowListener_private, l);
+ if (windowListener_private == null) {
+ awtListener_private.removeListeners(EventID.WINDOW);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#ACTION ACTION}
+ * events on each component instance in the Java Virtual Machine when they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeActionListener
+ */
+ static public void addActionListener(ActionListener l) {
+ if (actionListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.ACTION);
+ }
+ actionListener_private = AWTEventMulticaster.add(actionListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#ACTION ACTION} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addActionListener
+ */
+ static public void removeActionListener(ActionListener l) {
+ actionListener_private = AWTEventMulticaster.remove(actionListener_private, l);
+ if (actionListener_private == null) {
+ awtListener_private.removeListeners(EventID.ACTION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all
+ * {@link EventID#ADJUSTMENT ADJUSTMENT} events on each component instance
+ * in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeAdjustmentListener
+ */
+ static public void addAdjustmentListener(AdjustmentListener l) {
+ if (adjustmentListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.ADJUSTMENT);
+ }
+ adjustmentListener_private = AWTEventMulticaster.add(adjustmentListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#ADJUSTMENT ADJUSTMENT} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addAdjustmentListener
+ */
+ static public void removeAdjustmentListener(AdjustmentListener l) {
+ adjustmentListener_private = AWTEventMulticaster.remove(adjustmentListener_private, l);
+ if (adjustmentListener_private == null) {
+ awtListener_private.removeListeners(EventID.ADJUSTMENT);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#ITEM ITEM} events
+ * on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeItemListener
+ */
+ static public void addItemListener(ItemListener l) {
+ if (itemListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.ITEM);
+ }
+ itemListener_private = AWTEventMulticaster.add(itemListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives {@link EventID#ITEM ITEM}
+ * events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addItemListener
+ */
+ static public void removeItemListener(ItemListener l) {
+ itemListener_private = AWTEventMulticaster.remove(itemListener_private, l);
+ if (itemListener_private == null) {
+ awtListener_private.removeListeners(EventID.ITEM);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#TEXT TEXT} events
+ * on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeTextListener
+ */
+ static public void addTextListener(TextListener l) {
+ if (textListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.TEXT);
+ }
+ textListener_private = AWTEventMulticaster.add(textListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives {@link EventID#TEXT TEXT}
+ * events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addTextListener
+ */
+ static public void removeTextListener(TextListener l) {
+ textListener_private = AWTEventMulticaster.remove(textListener_private, l);
+ if (textListener_private == null) {
+ awtListener_private.removeListeners(EventID.TEXT);
+ }
+ }
+
+
+ /**
+ * AWTEventsListener is the class that does all the work for AWTEventMonitor.
+ * It is not intended for use by any other class except AWTEventMonitor.
+ *
+ */
+
+ static class AWTEventsListener implements TopLevelWindowListener,
+ ActionListener, AdjustmentListener, ComponentListener,
+ ContainerListener, FocusListener, ItemListener, KeyListener,
+ MouseListener, MouseMotionListener, TextListener, WindowListener,
+ ChangeListener {
+
+ /**
+ * internal variables for Action introspection
+ */
+ private java.lang.Class>[] actionListeners;
+ private java.lang.reflect.Method removeActionMethod;
+ private java.lang.reflect.Method addActionMethod;
+ private java.lang.Object[] actionArgs;
+
+ /**
+ * internal variables for Item introspection
+ */
+ private java.lang.Class>[] itemListeners;
+ private java.lang.reflect.Method removeItemMethod;
+ private java.lang.reflect.Method addItemMethod;
+ private java.lang.Object[] itemArgs;
+
+ /**
+ * internal variables for Text introspection
+ */
+ private java.lang.Class>[] textListeners;
+ private java.lang.reflect.Method removeTextMethod;
+ private java.lang.reflect.Method addTextMethod;
+ private java.lang.Object[] textArgs;
+
+ /**
+ * internal variables for Window introspection
+ */
+ private java.lang.Class>[] windowListeners;
+ private java.lang.reflect.Method removeWindowMethod;
+ private java.lang.reflect.Method addWindowMethod;
+ private java.lang.Object[] windowArgs;
+
+ /**
+ * Create a new instance of this class and install it on each component
+ * instance in the virtual machine that supports any of the currently
+ * registered listeners in AWTEventMonitor. Also registers itself
+ * as a TopLevelWindowListener with EventQueueMonitor so it can
+ * automatically add new listeners to new components.
+ *
+ * @see EventQueueMonitor
+ * @see AWTEventMonitor
+ */
+ public AWTEventsListener() {
+ String version = System.getProperty("java.version");
+ if (version != null) {
+ runningOnJDK1_4 = (version.compareTo("1.4") >= 0);
+ }
+ initializeIntrospection();
+ installListeners();
+ if (runningOnJDK1_4) {
+ MenuSelectionManager.defaultManager().addChangeListener(this);
+ }
+ EventQueueMonitor.addTopLevelWindowListener(this);
+ }
+
+ /**
+ * Set up all of the variables needed for introspection
+ */
+ private boolean initializeIntrospection() {
+ actionListeners = new java.lang.Class>[1];
+ actionArgs = new java.lang.Object[1];
+ actionListeners[0] = java.awt.event.ActionListener.class;
+ actionArgs[0] = this;
+
+ itemListeners = new java.lang.Class>[1];
+ itemArgs = new java.lang.Object[1];
+ itemListeners[0] = java.awt.event.ItemListener.class;
+ itemArgs[0] = this;
+
+ textListeners = new java.lang.Class>[1];
+ textArgs = new java.lang.Object[1];
+ textListeners[0] = java.awt.event.TextListener.class;
+ textArgs[0] = this;
+
+ windowListeners = new java.lang.Class>[1];
+ windowArgs = new java.lang.Object[1];
+ windowListeners[0] = java.awt.event.WindowListener.class;
+ windowArgs[0] = this;
+
+ return true;
+ }
+
+ /**
+ * Installs all currently registered listeners on all components based
+ * upon the current topLevelWindows cached by EventQueueMonitor.
+ *
+ * @see EventQueueMonitor
+ * @see AWTEventMonitor
+ */
+ protected void installListeners() {
+ Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
+ if (topLevelWindows != null) {
+ for (int i = 0; i < topLevelWindows.length; i++) {
+ installListeners(topLevelWindows[i]);
+ }
+ }
+ }
+
+ /**
+ * Installs listeners for the given event ID on all components based
+ * upon the current topLevelWindows cached by EventQueueMonitor.
+ *
+ * @param eventID the event ID
+ * @see EventID
+ */
+ protected void installListeners(int eventID) {
+ Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
+ if (topLevelWindows != null) {
+ for (int i = 0; i < topLevelWindows.length; i++) {
+ installListeners(topLevelWindows[i], eventID);
+ }
+ }
+ }
+
+ /**
+ * Installs all currently registered listeners to just the component.
+ * @param c the component to add listeners to
+ */
+ protected void installListeners(Component c) {
+
+ // Container and focus listeners are always installed for our own use.
+ //
+ installListeners(c,EventID.CONTAINER);
+ installListeners(c,EventID.FOCUS);
+
+ // conditionally install low-level listeners
+ //
+ if (AWTEventMonitor.componentListener_private != null) {
+ installListeners(c,EventID.COMPONENT);
+ }
+ if (AWTEventMonitor.keyListener_private != null) {
+ installListeners(c,EventID.KEY);
+ }
+ if (AWTEventMonitor.mouseListener_private != null) {
+ installListeners(c,EventID.MOUSE);
+ }
+ if (AWTEventMonitor.mouseMotionListener_private != null) {
+ installListeners(c,EventID.MOTION);
+ }
+ if (AWTEventMonitor.windowListener_private != null) {
+ installListeners(c,EventID.WINDOW);
+ }
+
+ // conditionally install Semantic listeners
+ //
+ if (AWTEventMonitor.actionListener_private != null) {
+ installListeners(c,EventID.ACTION);
+ }
+ if (AWTEventMonitor.adjustmentListener_private != null) {
+ installListeners(c,EventID.ADJUSTMENT);
+ }
+ if (AWTEventMonitor.itemListener_private != null) {
+ installListeners(c,EventID.ITEM);
+ }
+ if (AWTEventMonitor.textListener_private != null) {
+ installListeners(c,EventID.TEXT);
+ }
+ }
+
+ public void stateChanged(ChangeEvent e) {
+ processFocusGained();
+ }
+
+ private void processFocusGained() {
+ Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
+ if (focusOwner == null) {
+ return;
+ }
+ MenuSelectionManager.defaultManager().removeChangeListener(this);
+ MenuSelectionManager.defaultManager().addChangeListener(this);
+
+ // Only menus and popup selections are handled by the JRootPane.
+ if (focusOwner instanceof JRootPane) {
+ MenuElement [] path =
+ MenuSelectionManager.defaultManager().getSelectedPath();
+ if (path.length > 1) {
+ Component penult = path[path.length-2].getComponent();
+ Component last = path[path.length-1].getComponent();
+
+ if (last instanceof JPopupMenu ||
+ last instanceof JMenu) {
+ // This is a popup with nothing in the popup
+ // selected. The menu itself is selected.
+ componentWithFocus_private = last;
+ } else if (penult instanceof JPopupMenu) {
+ // This is a popup with an item selected
+ componentWithFocus_private = penult;
+ }
+ }
+ } else {
+ // The focus owner has the selection.
+ componentWithFocus_private = focusOwner;
+ }
+ }
+
+ /**
+ * Installs the given listener on the component and any of its children.
+ * As a precaution, it always attempts to remove itself as a listener
+ * first so it's always guaranteed to have installed itself just once.
+ *
+ * @param c the component to add listeners to
+ * @param eventID the eventID to add listeners for
+ * @see EventID
+ */
+ protected void installListeners(Component c, int eventID) {
+
+ // install the appropriate listener hook into this component
+ //
+ switch (eventID) {
+
+ case EventID.ACTION:
+ try {
+ removeActionMethod = c.getClass().getMethod(
+ "removeActionListener", actionListeners);
+ addActionMethod = c.getClass().getMethod(
+ "addActionListener", actionListeners);
+ try {
+ removeActionMethod.invoke(c, actionArgs);
+ addActionMethod.invoke(c, actionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.ADJUSTMENT:
+ if (c instanceof Adjustable) {
+ ((Adjustable) c).removeAdjustmentListener(this);
+ ((Adjustable) c).addAdjustmentListener(this);
+ }
+ break;
+
+ case EventID.COMPONENT:
+ c.removeComponentListener(this);
+ c.addComponentListener(this);
+ break;
+
+ case EventID.CONTAINER:
+ if (c instanceof Container) {
+ ((Container) c).removeContainerListener(this);
+ ((Container) c).addContainerListener(this);
+ }
+ break;
+
+ case EventID.FOCUS:
+ c.removeFocusListener(this);
+ c.addFocusListener(this);
+
+ if (runningOnJDK1_4) {
+ processFocusGained();
+
+ } else { // not runningOnJDK1_4
+ if ((c != componentWithFocus_private) && c.hasFocus()) {
+ componentWithFocus_private = c;
+ }
+ }
+ break;
+
+ case EventID.ITEM:
+ try {
+ removeItemMethod = c.getClass().getMethod(
+ "removeItemListener", itemListeners);
+ addItemMethod = c.getClass().getMethod(
+ "addItemListener", itemListeners);
+ try {
+ removeItemMethod.invoke(c, itemArgs);
+ addItemMethod.invoke(c, itemArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ // [PK] CheckboxMenuItem isn't a component but it does
+ // implement Interface ItemSelectable!!
+ // if (c instanceof CheckboxMenuItem) {
+ // ((CheckboxMenuItem) c).removeItemListener(this);
+ // ((CheckboxMenuItem) c).addItemListener(this);
+ break;
+
+ case EventID.KEY:
+ c.removeKeyListener(this);
+ c.addKeyListener(this);
+ break;
+
+ case EventID.MOUSE:
+ c.removeMouseListener(this);
+ c.addMouseListener(this);
+ break;
+
+ case EventID.MOTION:
+ c.removeMouseMotionListener(this);
+ c.addMouseMotionListener(this);
+ break;
+
+ case EventID.TEXT:
+ try {
+ removeTextMethod = c.getClass().getMethod(
+ "removeTextListener", textListeners);
+ addTextMethod = c.getClass().getMethod(
+ "addTextListener", textListeners);
+ try {
+ removeTextMethod.invoke(c, textArgs);
+ addTextMethod.invoke(c, textArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.WINDOW:
+ try {
+ removeWindowMethod = c.getClass().getMethod(
+ "removeWindowListener", windowListeners);
+ addWindowMethod = c.getClass().getMethod(
+ "addWindowListener", windowListeners);
+ try {
+ removeWindowMethod.invoke(c, windowArgs);
+ addWindowMethod.invoke(c, windowArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ // Don't bother recursing the children if this isn't going to
+ // accomplish anything.
+ //
+ default:
+ return;
+ }
+
+ // if this component is a container, recurse through children
+ //
+ if (c instanceof Container) {
+ int count = ((Container) c).getComponentCount();
+ for (int i = 0; i < count; i++) {
+ installListeners(((Container) c).getComponent(i), eventID);
+ }
+ }
+ }
+
+ /**
+ * Removes all listeners for the given event ID on all components based
+ * upon the topLevelWindows cached by EventQueueMonitor.
+ *
+ * @param eventID the event ID
+ * @see EventID
+ */
+ protected void removeListeners(int eventID) {
+ Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
+ if (topLevelWindows != null) {
+ for (int i = 0; i < topLevelWindows.length; i++) {
+ removeListeners(topLevelWindows[i], eventID);
+ }
+ }
+ }
+
+ /**
+ * Removes all listeners for the given component and all its children.
+ * @param c the component
+ */
+ protected void removeListeners(Component c) {
+
+ // conditionally remove low-level listeners
+ //
+ if (AWTEventMonitor.componentListener_private != null) {
+ removeListeners(c,EventID.COMPONENT);
+ }
+ if (AWTEventMonitor.keyListener_private != null) {
+ removeListeners(c,EventID.KEY);
+ }
+ if (AWTEventMonitor.mouseListener_private != null) {
+ removeListeners(c,EventID.MOUSE);
+ }
+ if (AWTEventMonitor.mouseMotionListener_private != null) {
+ removeListeners(c,EventID.MOTION);
+ }
+ if (AWTEventMonitor.windowListener_private != null) {
+ removeListeners(c,EventID.WINDOW);
+ }
+
+ // Remove semantic listeners
+ //
+ if (AWTEventMonitor.actionListener_private != null) {
+ removeListeners(c,EventID.ACTION);
+ }
+ if (AWTEventMonitor.adjustmentListener_private != null) {
+ removeListeners(c,EventID.ADJUSTMENT);
+ }
+ if (AWTEventMonitor.itemListener_private != null) {
+ removeListeners(c,EventID.ITEM);
+ }
+ if (AWTEventMonitor.textListener_private != null) {
+ removeListeners(c,EventID.TEXT);
+ }
+ }
+
+ /**
+ * Removes all listeners for the event ID from the component and all
+ * of its children.
+ *
+ * @param c the component to remove listeners from
+ * @see EventID
+ */
+ protected void removeListeners(Component c, int eventID) {
+
+ // remove the appropriate listener hook into this component
+ //
+ switch (eventID) {
+
+ case EventID.ACTION:
+ try {
+ removeActionMethod = c.getClass().getMethod(
+ "removeActionListener",
+ actionListeners);
+ try {
+ removeActionMethod.invoke(c, actionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.ADJUSTMENT:
+ if (c instanceof Adjustable) {
+ ((Adjustable) c).removeAdjustmentListener(this);
+ }
+ break;
+
+ case EventID.COMPONENT:
+ c.removeComponentListener(this);
+ break;
+
+ // Never remove these because we're always interested in them
+ // for our own use.
+ //case EventID.CONTAINER:
+ // if (c instanceof Container) {
+ // ((Container) c).removeContainerListener(this);
+ // }
+ // break;
+ //
+ //case EventID.FOCUS:
+ // c.removeFocusListener(this);
+ // break;
+
+ case EventID.ITEM:
+ try {
+ removeItemMethod = c.getClass().getMethod(
+ "removeItemListener", itemListeners);
+ try {
+ removeItemMethod.invoke(c, itemArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ // [PK] CheckboxMenuItem isn't a component but it does
+ // implement Interface ItemSelectable!!
+ // if (c instanceof CheckboxMenuItem) {
+ // ((CheckboxMenuItem) c).removeItemListener(this);
+ break;
+
+ case EventID.KEY:
+ c.removeKeyListener(this);
+ break;
+
+ case EventID.MOUSE:
+ c.removeMouseListener(this);
+ break;
+
+ case EventID.MOTION:
+ c.removeMouseMotionListener(this);
+ break;
+
+ case EventID.TEXT:
+ try {
+ removeTextMethod = c.getClass().getMethod(
+ "removeTextListener", textListeners);
+ try {
+ removeTextMethod.invoke(c, textArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.WINDOW:
+ try {
+ removeWindowMethod = c.getClass().getMethod(
+ "removeWindowListener", windowListeners);
+ try {
+ removeWindowMethod.invoke(c, windowArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ if (c instanceof Container) {
+ int count = ((Container) c).getComponentCount();
+ for (int i = 0; i < count; i++) {
+ removeListeners(((Container) c).getComponent(i), eventID);
+ }
+ }
+ }
+
+ /********************************************************************/
+ /* */
+ /* Listener Interface Methods */
+ /* */
+ /********************************************************************/
+
+ /* TopLevelWindow Methods ***************************************/
+
+ /**
+ * Called when top level window is created.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ */
+ public void topLevelWindowCreated(Window w) {
+ installListeners(w);
+ }
+
+ /**
+ * Called when top level window is destroyed.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ */
+ public void topLevelWindowDestroyed(Window w) {
+ }
+
+ /* ActionListener Methods ***************************************/
+
+ /**
+ * Called when an action is performed.
+ *
+ * @see AWTEventMonitor#addActionListener
+ */
+ public void actionPerformed(ActionEvent e) {
+ if (AWTEventMonitor.actionListener_private != null) {
+ AWTEventMonitor.actionListener_private.actionPerformed(e);
+ }
+ }
+
+ /* AdjustmentListener Methods ***********************************/
+
+ /**
+ * Called when an adjustment is made.
+ *
+ * @see AWTEventMonitor#addAdjustmentListener
+ */
+ public void adjustmentValueChanged(AdjustmentEvent e) {
+ if (AWTEventMonitor.adjustmentListener_private != null) {
+ AWTEventMonitor.adjustmentListener_private.adjustmentValueChanged(e);
+ }
+ }
+
+ /* ComponentListener Methods ************************************/
+
+ /**
+ * Called when a component is hidden.
+ *
+ * @see AWTEventMonitor#addComponentListener
+ */
+ public void componentHidden(ComponentEvent e) {
+ if (AWTEventMonitor.componentListener_private != null) {
+ AWTEventMonitor.componentListener_private.componentHidden(e);
+ }
+ }
+
+ /**
+ * Called when a component is moved.
+ *
+ * @see AWTEventMonitor#addComponentListener
+ */
+ public void componentMoved(ComponentEvent e) {
+ if (AWTEventMonitor.componentListener_private != null) {
+ AWTEventMonitor.componentListener_private.componentMoved(e);
+ }
+ }
+
+ /**
+ * Called when a component is resized.
+ *
+ * @see AWTEventMonitor#addComponentListener
+ */
+ public void componentResized(ComponentEvent e) {
+ if (AWTEventMonitor.componentListener_private != null) {
+ AWTEventMonitor.componentListener_private.componentResized(e);
+ }
+ }
+
+ /**
+ * Called when a component is shown.
+ *
+ * @see AWTEventMonitor#addComponentListener
+ */
+ public void componentShown(ComponentEvent e) {
+ if (AWTEventMonitor.componentListener_private != null) {
+ AWTEventMonitor.componentListener_private.componentShown(e);
+ }
+ }
+
+ /* ContainerListener Methods ************************************/
+
+ /**
+ * Called when a component is added to a container.
+ *
+ * @see AWTEventMonitor#addContainerListener
+ */
+ public void componentAdded(ContainerEvent e) {
+ installListeners(e.getChild());
+ if (AWTEventMonitor.containerListener_private != null) {
+ AWTEventMonitor.containerListener_private.componentAdded(e);
+ }
+ }
+
+ /**
+ * Called when a component is removed from a container.
+ *
+ * @see AWTEventMonitor#addContainerListener
+ */
+ public void componentRemoved(ContainerEvent e) {
+ removeListeners(e.getChild());
+ if (AWTEventMonitor.containerListener_private != null) {
+ AWTEventMonitor.containerListener_private.componentRemoved(e);
+ }
+ }
+
+ /* FocusListener Methods ****************************************/
+
+ /**
+ * Called when a component gains keyboard focus.
+ *
+ * @see AWTEventMonitor#addFocusListener
+ */
+ public void focusGained(FocusEvent e) {
+ AWTEventMonitor.componentWithFocus_private = (Component) e.getSource();
+ if (AWTEventMonitor.focusListener_private != null) {
+ AWTEventMonitor.focusListener_private.focusGained(e);
+ }
+ }
+
+ /**
+ * Called when a component loses keyboard focus.
+ *
+ * @see AWTEventMonitor#addFocusListener
+ */
+ public void focusLost(FocusEvent e) {
+ AWTEventMonitor.componentWithFocus_private = null;
+ if (AWTEventMonitor.focusListener_private != null) {
+ AWTEventMonitor.focusListener_private.focusLost(e);
+ }
+ }
+
+ /* ItemListener Methods *****************************************/
+
+ /**
+ * Called when an item's state changes.
+ *
+ * @see AWTEventMonitor#addItemListener
+ */
+ public void itemStateChanged(ItemEvent e) {
+ if (AWTEventMonitor.itemListener_private != null) {
+ AWTEventMonitor.itemListener_private.itemStateChanged(e);
+ }
+ }
+
+ /* KeyListener Methods ******************************************/
+
+ /**
+ * Called when a key is pressed.
+ *
+ * @see AWTEventMonitor#addKeyListener
+ */
+ public void keyPressed(KeyEvent e) {
+ if (AWTEventMonitor.keyListener_private != null) {
+ AWTEventMonitor.keyListener_private.keyPressed(e);
+ }
+ }
+
+ /**
+ * Called when a key is typed.
+ *
+ * @see AWTEventMonitor#addKeyListener
+ */
+ public void keyReleased(KeyEvent e) {
+ if (AWTEventMonitor.keyListener_private != null) {
+ AWTEventMonitor.keyListener_private.keyReleased(e);
+ }
+ }
+
+ /**
+ * Called when a key is released.
+ *
+ * @see AWTEventMonitor#addKeyListener
+ */
+ public void keyTyped(KeyEvent e) {
+ if (AWTEventMonitor.keyListener_private != null) {
+ AWTEventMonitor.keyListener_private.keyTyped(e);
+ }
+ }
+
+ /* MouseListener Methods ****************************************/
+
+ /**
+ * Called when the mouse is clicked.
+ *
+ * @see AWTEventMonitor#addMouseListener
+ */
+ public void mouseClicked(MouseEvent e) {
+ if (AWTEventMonitor.mouseListener_private != null) {
+ AWTEventMonitor.mouseListener_private.mouseClicked(e);
+ }
+ }
+
+ /**
+ * Called when the mouse enters a component.
+ *
+ * @see AWTEventMonitor#addMouseListener
+ */
+ public void mouseEntered(MouseEvent e) {
+ if (AWTEventMonitor.mouseListener_private != null) {
+ AWTEventMonitor.mouseListener_private.mouseEntered(e);
+ }
+ }
+
+ /**
+ * Called when the mouse leaves a component.
+ *
+ * @see AWTEventMonitor#addMouseListener
+ */
+ public void mouseExited(MouseEvent e) {
+ if (AWTEventMonitor.mouseListener_private != null) {
+ AWTEventMonitor.mouseListener_private.mouseExited(e);
+ }
+ }
+
+ /**
+ * Called when the mouse is pressed.
+ *
+ * @see AWTEventMonitor#addMouseListener
+ */
+ public void mousePressed(MouseEvent e) {
+ if (AWTEventMonitor.mouseListener_private != null) {
+ AWTEventMonitor.mouseListener_private.mousePressed(e);
+ }
+ }
+
+ /**
+ * Called when the mouse is released.
+ *
+ * @see AWTEventMonitor#addMouseListener
+ */
+ public void mouseReleased(MouseEvent e) {
+ if (AWTEventMonitor.mouseListener_private != null) {
+ AWTEventMonitor.mouseListener_private.mouseReleased(e);
+ }
+ }
+
+ /* MouseMotionListener Methods **********************************/
+
+ /**
+ * Called when the mouse is dragged.
+ *
+ * @see AWTEventMonitor#addMouseMotionListener
+ */
+ public void mouseDragged(MouseEvent e) {
+ if (AWTEventMonitor.mouseMotionListener_private != null) {
+ AWTEventMonitor.mouseMotionListener_private.mouseDragged(e);
+ }
+ }
+
+ /**
+ * Called when the mouse is moved.
+ *
+ * @see AWTEventMonitor#addMouseMotionListener
+ */
+ public void mouseMoved(MouseEvent e) {
+ if (AWTEventMonitor.mouseMotionListener_private != null) {
+ AWTEventMonitor.mouseMotionListener_private.mouseMoved(e);
+ }
+ }
+
+ /* TextListener Methods *****************************************/
+
+ /**
+ * Called when a component's text value changed.
+ *
+ * @see AWTEventMonitor#addTextListener
+ */
+ public void textValueChanged(TextEvent e) {
+ if (AWTEventMonitor.textListener_private != null) {
+ AWTEventMonitor.textListener_private.textValueChanged(e);
+ }
+ }
+
+ /* WindowListener Methods ***************************************/
+
+ /**
+ * Called when a window is opened.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowOpened(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowOpened(e);
+ }
+ }
+
+ /**
+ * Called when a window is in the process of closing.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowClosing(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowClosing(e);
+ }
+ }
+
+ /**
+ * Called when a window is closed.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowClosed(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowClosed(e);
+ }
+ }
+
+ /**
+ * Called when a window is iconified.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowIconified(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowIconified(e);
+ }
+ }
+
+ /**
+ * Called when a window is deiconified.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowDeiconified(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowDeiconified(e);
+ }
+ }
+
+ /**
+ * Called when a window is activated.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowActivated(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowActivated(e);
+ }
+ }
+
+ /**
+ * Called when a window is deactivated.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowDeactivated(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowDeactivated(e);
+ }
+ }
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityEventMonitor.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityEventMonitor.java
new file mode 100644
index 00000000000..4719e7c12de
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityEventMonitor.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.util.*;
+import java.beans.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.accessibility.*;
+
+/**
+ *
{@code AccessibilityEventMonitor} implements a PropertyChange listener
+ * on every UI object that implements interface {@code Accessible} in the Java
+ * Virtual Machine. The events captured by these listeners are made available
+ * through listeners supported by {@code AccessibilityEventMonitor}.
+ * With this, all the individual events on each of the UI object
+ * instances are funneled into one set of PropertyChange listeners.
+ *
This class depends upon {@link EventQueueMonitor}, which provides the base
+ * level support for capturing the top-level containers as they are created.
+ *
+ */
+
+@jdk.Exported
+public class AccessibilityEventMonitor {
+
+ // listeners
+ /**
+ * The current list of registered {@link java.beans.PropertyChangeListener
+ * PropertyChangeListener} classes.
+ *
+ * @see #addPropertyChangeListener
+ * @see #removePropertyChangeListener
+ */
+ static protected final AccessibilityListenerList listenerList =
+ new AccessibilityListenerList();
+
+
+ /**
+ * The actual listener that is installed on the component instances.
+ * This listener calls the other registered listeners when an event
+ * occurs. By doing things this way, the actual number of listeners
+ * installed on a component instance is drastically reduced.
+ */
+ static protected final AccessibilityEventListener accessibilityListener =
+ new AccessibilityEventListener();
+
+ /**
+ * Adds the specified listener to receive all PropertyChange events on
+ * each UI object instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to UI object instances that support this listener type.
+ *
+ * @param l the listener to add
+ *
+ * @see #removePropertyChangeListener
+ */
+ static public void addPropertyChangeListener(PropertyChangeListener l) {
+ if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
+ accessibilityListener.installListeners();
+ }
+ listenerList.add(PropertyChangeListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives PropertyChange
+ * events when they occur.
+ * @see #addPropertyChangeListener
+ * @param l the listener to remove
+ */
+ static public void removePropertyChangeListener(PropertyChangeListener l) {
+ listenerList.remove(PropertyChangeListener.class, l);
+ if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
+ accessibilityListener.removeListeners();
+ }
+ }
+
+
+ /**
+ * AccessibilityEventListener is the class that does all the work for
+ * AccessibilityEventMonitor. It is not intended for use by any other
+ * class except AccessibilityEventMonitor.
+ *
+ */
+
+ static class AccessibilityEventListener implements TopLevelWindowListener,
+ PropertyChangeListener {
+
+ /**
+ * Create a new instance of this class and install it on each component
+ * instance in the virtual machine that supports any of the currently
+ * registered listeners in AccessibilityEventMonitor. Also registers
+ * itself as a TopLevelWindowListener with EventQueueMonitor so it can
+ * automatically add new listeners to new components.
+ * @see EventQueueMonitor
+ * @see AccessibilityEventMonitor
+ */
+ public AccessibilityEventListener() {
+ EventQueueMonitor.addTopLevelWindowListener(this);
+ }
+
+ /**
+ * Installs PropertyChange listeners on all Accessible objects based
+ * upon the current topLevelWindows cached by EventQueueMonitor.
+ * @see EventQueueMonitor
+ * @see AWTEventMonitor
+ */
+ protected void installListeners() {
+ Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
+ if (topLevelWindows != null) {
+ for (int i = 0; i < topLevelWindows.length; i++) {
+ if (topLevelWindows[i] instanceof Accessible) {
+ installListeners((Accessible) topLevelWindows[i]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Installs PropertyChange listeners to the Accessible object, and it's
+ * children (so long as the object isn't of TRANSIENT state).
+ * @param a the Accessible object to add listeners to
+ */
+ protected void installListeners(Accessible a) {
+ installListeners(a.getAccessibleContext());
+ }
+
+ /**
+ * Installs PropertyChange listeners to the AccessibleContext object,
+ * and it's * children (so long as the object isn't of TRANSIENT state).
+ * @param a the Accessible object to add listeners to
+ */
+ private void installListeners(AccessibleContext ac) {
+
+ if (ac != null) {
+ AccessibleStateSet states = ac.getAccessibleStateSet();
+ if (!states.contains(AccessibleState.TRANSIENT)) {
+ ac.addPropertyChangeListener(this);
+ /*
+ * Don't add listeners to transient children. Components
+ * with transient children should return an AccessibleStateSet
+ * containing AccessibleState.MANAGES_DESCENDANTS. Components
+ * may not explicitly return the MANAGES_DESCENDANTS state.
+ * In this case, don't add listeners to the children of
+ * lists, tables and trees.
+ */
+ AccessibleStateSet set = ac.getAccessibleStateSet();
+ if (set.contains(_AccessibleState.MANAGES_DESCENDANTS)) {
+ return;
+ }
+ AccessibleRole role = ac.getAccessibleRole();
+ if (role == AccessibleRole.LIST ||
+ role == AccessibleRole.TREE) {
+ return;
+ }
+ if (role == AccessibleRole.TABLE) {
+ // handle Oracle tables containing tables
+ Accessible child = ac.getAccessibleChild(0);
+ if (child != null) {
+ AccessibleContext ac2 = child.getAccessibleContext();
+ if (ac2 != null) {
+ role = ac2.getAccessibleRole();
+ if (role != null && role != AccessibleRole.TABLE) {
+ return;
+ }
+ }
+ }
+ }
+ int count = ac.getAccessibleChildrenCount();
+ for (int i = 0; i < count; i++) {
+ Accessible child = ac.getAccessibleChild(i);
+ if (child != null) {
+ installListeners(child);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes PropertyChange listeners on all Accessible objects based
+ * upon the topLevelWindows cached by EventQueueMonitor.
+ * @param eventID the event ID
+ * @see EventID
+ */
+ protected void removeListeners() {
+ Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
+ if (topLevelWindows != null) {
+ for (int i = 0; i < topLevelWindows.length; i++) {
+ if (topLevelWindows[i] instanceof Accessible) {
+ removeListeners((Accessible) topLevelWindows[i]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes PropertyChange listeners for the given Accessible object,
+ * it's children (so long as the object isn't of TRANSIENT state).
+ * @param a the Accessible object to remove listeners from
+ */
+ protected void removeListeners(Accessible a) {
+ removeListeners(a.getAccessibleContext());
+ }
+
+ /**
+ * Removes PropertyChange listeners for the given AccessibleContext
+ * object, it's children (so long as the object isn't of TRANSIENT
+ * state).
+ * @param a the Accessible object to remove listeners from
+ */
+ private void removeListeners(AccessibleContext ac) {
+
+
+ if (ac != null) {
+ // Listeners are not added to transient components.
+ AccessibleStateSet states = ac.getAccessibleStateSet();
+ if (!states.contains(AccessibleState.TRANSIENT)) {
+ ac.removePropertyChangeListener(this);
+ /*
+ * Listeners are not added to transient children. Components
+ * with transient children should return an AccessibleStateSet
+ * containing AccessibleState.MANAGES_DESCENDANTS. Components
+ * may not explicitly return the MANAGES_DESCENDANTS state.
+ * In this case, don't remove listeners from the children of
+ * lists, tables and trees.
+ */
+ if (states.contains(_AccessibleState.MANAGES_DESCENDANTS)) {
+ return;
+ }
+ AccessibleRole role = ac.getAccessibleRole();
+ if (role == AccessibleRole.LIST ||
+ role == AccessibleRole.TABLE ||
+ role == AccessibleRole.TREE) {
+ return;
+ }
+ int count = ac.getAccessibleChildrenCount();
+ for (int i = 0; i < count; i++) {
+ Accessible child = ac.getAccessibleChild(i);
+ if (child != null) {
+ removeListeners(child);
+ }
+ }
+ }
+ }
+ }
+
+ /********************************************************************/
+ /* */
+ /* Listener Interface Methods */
+ /* */
+ /********************************************************************/
+
+ /* TopLevelWindow Methods ***************************************/
+
+ /**
+ * Called when top level window is created.
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ */
+ public void topLevelWindowCreated(Window w) {
+ if (w instanceof Accessible) {
+ installListeners((Accessible) w);
+ }
+ }
+
+ /**
+ * Called when top level window is destroyed.
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ */
+ public void topLevelWindowDestroyed(Window w) {
+ if (w instanceof Accessible) {
+ removeListeners((Accessible) w);
+ }
+ }
+
+
+ /* PropertyChangeListener Methods **************************************/
+
+ public void propertyChange(PropertyChangeEvent e) {
+ // propogate the event
+ Object[] listeners =
+ AccessibilityEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PropertyChangeListener.class) {
+ ((PropertyChangeListener)listeners[i+1]).propertyChange(e);
+ }
+ }
+
+ // handle childbirth/death
+ String name = e.getPropertyName();
+ if (name.compareTo(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY) == 0) {
+ Object oldValue = e.getOldValue();
+ Object newValue = e.getNewValue();
+
+ if ((oldValue == null) ^ (newValue == null)) { // one null, not both
+ if (oldValue != null) {
+ // this Accessible is a child that's going away
+ if (oldValue instanceof Accessible) {
+ Accessible a = (Accessible) oldValue;
+ removeListeners(a.getAccessibleContext());
+ } else if (oldValue instanceof AccessibleContext) {
+ removeListeners((AccessibleContext) oldValue);
+ }
+ } else if (newValue != null) {
+ // this Accessible is a child was just born
+ if (newValue instanceof Accessible) {
+ Accessible a = (Accessible) newValue;
+ installListeners(a.getAccessibleContext());
+ } else if (newValue instanceof AccessibleContext) {
+ installListeners((AccessibleContext) newValue);
+ }
+ }
+ } else {
+ System.out.println("ERROR in usage of PropertyChangeEvents for: " + e.toString());
+ }
+ }
+ }
+ }
+}
+
+/*
+ * workaround for no public AccessibleState constructor
+ */
+class _AccessibleState extends AccessibleState {
+ /**
+ * Indicates this object is responsible for managing its
+ * subcomponents. This is typically used for trees and tables
+ * that have a large number of subcomponents and where the
+ * objects are created only when needed and otherwise remain virtual.
+ * The application should not manage the subcomponents directly.
+ */
+ public static final _AccessibleState MANAGES_DESCENDANTS
+ = new _AccessibleState ("managesDescendants");
+
+ /**
+ * Creates a new AccessibleState using the given locale independent key.
+ * This should not be a public method. Instead, it is used to create
+ * the constants in this file to make it a strongly typed enumeration.
+ * Subclasses of this class should enforce similar policy.
+ *
+ * The key String should be a locale independent key for the state.
+ * It is not intended to be used as the actual String to display
+ * to the user. To get the localized string, use toDisplayString.
+ *
+ * @param key the locale independent name of the state.
+ * @see AccessibleBundle#toDisplayString
+ */
+ protected _AccessibleState(String key) {
+ super(key);
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityListenerList.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityListenerList.java
new file mode 100644
index 00000000000..76c7147ea09
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityListenerList.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.util.*;
+import java.beans.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.accessibility.*;
+
+/**
+ *
The {@code AccessibilityListenerList} is a copy of the Swing
+ * {@link javax.swing.event.EventListenerList EventListerList} class.
+ *
+ */
+
+@jdk.Exported
+public class AccessibilityListenerList {
+ /* A null array to be shared by all empty listener lists */
+ private final static Object[] NULL_ARRAY = new Object[0];
+
+ /**
+ * The list of listener type, listener pairs
+ */
+ protected transient Object[] listenerList = NULL_ARRAY;
+
+ /**
+ * Passes back the event listener list as an array of listener type, listener pairs.
+ * Note that for performance reasons, this implementation passes back the actual
+ * data structure in which the listener data is stored internally. This method
+ * is guaranteed to pass back a non-null array, so that no null-checking
+ * is required in fire methods. A zero-length array of Object is returned if
+ * there are currently no listeners.
+ *
+ * Absolutely no modification of the data contained in this array should be
+ * made. If any such manipulation is necessary, it should be done on a copy
+ * of the array returned rather than the array itself.
+ *
+ * @return an array of listener type, listener pairs.
+ */
+ public Object[] getListenerList() {
+ return listenerList;
+ }
+
+ /**
+ * Returns the total number of listeners for this listener list.
+ *
+ * @return the total number of listeners for this listener list.
+ */
+ public int getListenerCount() {
+ return listenerList.length/2;
+ }
+
+ /**
+ * Return the total number of listeners of the supplied type
+ * for this listener list.
+ *
+ * @param t the type of the listener to be counted
+ * @return the number of listeners found
+ */
+ public int getListenerCount(Class extends EventListener> t) {
+ int count = 0;
+ Object[] lList = listenerList;
+ for (int i = 0; i < lList.length; i+=2) {
+ if (t == (Class)lList[i])
+ count++;
+ }
+ return count;
+ }
+
+ /**
+ * Add the listener as a listener of the specified type.
+ *
+ * @param t the type of the listener to be added
+ * @param l the listener to be added
+ */
+ public synchronized void add(Class extends EventListener> t, EventListener l) {
+ if (!t.isInstance(l)) {
+ throw new IllegalArgumentException("Listener " + l +
+ " is not of type " + t);
+ }
+ if (l ==null) {
+ throw new IllegalArgumentException("Listener " + l +
+ " is null");
+ }
+ if (listenerList == NULL_ARRAY) {
+ // if this is the first listener added,
+ // initialize the lists
+ listenerList = new Object[] { t, l };
+ } else {
+ // Otherwise copy the array and add the new listener
+ int i = listenerList.length;
+ Object[] tmp = new Object[i+2];
+ System.arraycopy(listenerList, 0, tmp, 0, i);
+
+ tmp[i] = t;
+ tmp[i+1] = l;
+
+ listenerList = tmp;
+ }
+ }
+
+ /**
+ * Remove the listener as a listener of the specified type.
+ *
+ * @param t the type of the listener to be removed
+ * @param l the listener to be removed
+ */
+ public synchronized void remove(Class extends EventListener> t, EventListener l) {
+ if (!t.isInstance(l)) {
+ throw new IllegalArgumentException("Listener " + l +
+ " is not of type " + t);
+ }
+ if (l ==null) {
+ throw new IllegalArgumentException("Listener " + l +
+ " is null");
+ }
+
+ // Is l on the list?
+ int index = -1;
+ for (int i = listenerList.length-2; i>=0; i-=2) {
+ if ((listenerList[i]==t) && (listenerList[i+1] == l)) {
+ index = i;
+ break;
+ }
+ }
+
+ // If so, remove it
+ if (index != -1) {
+ Object[] tmp = new Object[listenerList.length-2];
+ // Copy the list up to index
+ System.arraycopy(listenerList, 0, tmp, 0, index);
+ // Copy from two past the index, up to
+ // the end of tmp (which is two elements
+ // shorter than the old list)
+ if (index < tmp.length)
+ System.arraycopy(listenerList, index+2, tmp, index,
+ tmp.length - index);
+ // set the listener array to the new array or null
+ listenerList = (tmp.length == 0) ? NULL_ARRAY : tmp;
+ }
+ }
+
+ /**
+ * Return a string representation of the {@code AccessibilityListenerList}.
+ *
+ * @return a string representation of the {@code AccessibilityListenerList}.
+ */
+ public String toString() {
+ Object[] lList = listenerList;
+ String s = "EventListenerList: ";
+ s += lList.length/2 + " listeners: ";
+ for (int i = 0 ; i <= lList.length-2 ; i+=2) {
+ s += " type " + ((Class)lList[i]).getName();
+ s += " listener " + lList[i+1];
+ }
+ return s;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventID.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventID.java
new file mode 100644
index 00000000000..bbd08f534e9
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventID.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+/**
+ * EventID contains integer constants that map to event support in
+ * AWT and Swing. They are used by primarily by AWTEventMonitor,
+ * AWTEventsListener, SwingEventMonitor, and SwingEventListener, but
+ * can be freely used by any other class.
+ *
+ * @see AWTEventMonitor
+ * @see SwingEventMonitor
+ *
+ */
+@jdk.Exported
+public class EventID {
+
+ /**
+ * Maps to AWT Action support (i.e., ActionListener and ActionEvent)
+ */
+ static public final int ACTION = 0;
+
+ /**
+ * Maps to AWT Adjustment support (i.e., AdjustmentListener
+ * and AdjustmentEvent)
+ */
+ static public final int ADJUSTMENT = 1;
+
+ /**
+ * Maps to AWT Component support (i.e., ComponentListener
+ * and ComponentEvent)
+ */
+ static public final int COMPONENT = 2;
+
+ /**
+ * Maps to AWT Container support (i.e., ContainerListener
+ * and ContainerEvent)
+ */
+ static public final int CONTAINER = 3;
+
+ /**
+ * Maps to AWT Focus support (i.e., FocusListener and FocusEvent)
+ */
+ static public final int FOCUS = 4;
+
+ /**
+ * Maps to AWT Item support (i.e., ItemListener and ItemEvent)
+ */
+ static public final int ITEM = 5;
+
+ /**
+ * Maps to AWT Key support (i.e., KeyListener and KeyEvent)
+ */
+ static public final int KEY = 6;
+
+ /**
+ * Maps to AWT Mouse support (i.e., MouseListener and MouseEvent)
+ */
+ static public final int MOUSE = 7;
+
+ /**
+ * Maps to AWT MouseMotion support (i.e., MouseMotionListener
+ * and MouseMotionEvent)
+ */
+ static public final int MOTION = 8;
+
+ /**
+ * Maps to AWT Text support (i.e., TextListener and TextEvent)
+ */
+ static public final int TEXT = 10;
+
+ /**
+ * Maps to AWT Window support (i.e., WindowListener and WindowEvent)
+ */
+ static public final int WINDOW = 11;
+
+ /**
+ * Maps to Swing Ancestor support (i.e., AncestorListener and
+ * AncestorEvent)
+ */
+ static public final int ANCESTOR = 12;
+
+ /**
+ * Maps to Swing Text Caret support (i.e., CaretListener and
+ * CaretEvent)
+ */
+ static public final int CARET = 13;
+
+ /**
+ * Maps to Swing CellEditor support (i.e., CellEditorListener and
+ * CellEditorEvent)
+ */
+ static public final int CELLEDITOR = 14;
+
+ /**
+ * Maps to Swing Change support (i.e., ChangeListener and
+ * ChangeEvent)
+ */
+ static public final int CHANGE = 15;
+
+ /**
+ * Maps to Swing TableColumnModel support (i.e.,
+ * TableColumnModelListener and TableColumnModelEvent)
+ */
+ static public final int COLUMNMODEL = 16;
+
+ /**
+ * Maps to Swing Document support (i.e., DocumentListener and
+ * DocumentEvent)
+ */
+ static public final int DOCUMENT = 17;
+
+ /**
+ * Maps to Swing ListData support (i.e., ListDataListener and
+ * ListDataEvent)
+ */
+ static public final int LISTDATA = 18;
+
+ /**
+ * Maps to Swing ListSelection support (i.e., ListSelectionListener and
+ * ListSelectionEvent)
+ */
+ static public final int LISTSELECTION = 19;
+
+ /**
+ * Maps to Swing Menu support (i.e., MenuListener and
+ * MenuEvent)
+ */
+ static public final int MENU = 20;
+
+ /**
+ * Maps to Swing PopupMenu support (i.e., PopupMenuListener and
+ * PopupMenuEvent)
+ */
+ static public final int POPUPMENU = 21;
+
+ /**
+ * Maps to Swing TableModel support (i.e., TableModelListener and
+ * TableModelEvent)
+ */
+ static public final int TABLEMODEL = 22;
+
+ /**
+ * Maps to Swing TreeExpansion support (i.e., TreeExpansionListener and
+ * TreeExpansionEvent)
+ */
+ static public final int TREEEXPANSION = 23;
+
+ /**
+ * Maps to Swing TreeModel support (i.e., TreeModelListener and
+ * TreeModelEvent)
+ */
+ static public final int TREEMODEL = 24;
+
+ /**
+ * Maps to Swing TreeSelection support (i.e., TreeSelectionListener and
+ * TreeSelectionEvent)
+ */
+ static public final int TREESELECTION = 25;
+
+ /**
+ * Maps to Swing UndoableEdit support (i.e., UndoableEditListener and
+ * UndoableEditEvent)
+ */
+ static public final int UNDOABLEEDIT = 26;
+
+ /**
+ * Maps to Beans PropertyChange support (i.e., PropertyChangeListener
+ * and PropertyChangeEvent)
+ */
+ static public final int PROPERTYCHANGE = 27;
+
+ /**
+ * Maps to Beans VetoableChange support (i.e., VetoableChangeListener
+ * and VetoableChangeEvent)
+ */
+ static public final int VETOABLECHANGE = 28;
+
+ /**
+ * Maps to Swing InternalFrame support (i.e., InternalFrameListener)
+ */
+ static public final int INTERNALFRAME = 29;
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventQueueMonitor.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventQueueMonitor.java
new file mode 100644
index 00000000000..aa87860bb48
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventQueueMonitor.java
@@ -0,0 +1,619 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.accessibility.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * The {@code EventQueueMonitor} class provides key core functionality for Assistive
+ * Technologies (and other system-level technologies that need some of the same
+ * things that Assistive Technology needs).
+ *
+ * @see AWTEventMonitor
+ * @see SwingEventMonitor
+ */
+@jdk.Exported
+public class EventQueueMonitor
+ implements AWTEventListener {
+
+ // NOTE: All of the following properties are static. The reason
+ // for this is that there may be multiple EventQueue instances
+ // in use in the same VM. By making these properties static,
+ // we can guarantee we get the information from all of the
+ // EventQueue instances.
+
+ // The stuff that is cached.
+ //
+ static VectortopLevelWindows = new Vector<>();
+ static Window topLevelWindowWithFocus = null;
+ static Point currentMousePosition = null;
+ static Component currentMouseComponent = null;
+
+ // Low-level listener interfaces
+ //
+ static GUIInitializedListener guiInitializedListener = null;
+ static TopLevelWindowListener topLevelWindowListener = null;
+ static MouseMotionListener mouseMotionListener = null;
+
+ /**
+ * Class variable stating whether the assistive technologies have
+ * been loaded yet or not. The assistive technologies won't be
+ * loaded until the first event is posted to the EventQueue. This
+ * gives the toolkit a chance to do all the necessary initialization
+ * it needs to do.
+ */
+
+ /**
+ * Class variable stating whether the GUI subsystem has been initialized
+ * or not.
+ *
+ * @see #isGUIInitialized
+ */
+ static boolean guiInitialized = false;
+
+ /**
+ * Queue that holds events for later processing.
+ */
+ static EventQueueMonitorItem componentEventQueue = null;
+
+ /**
+ * Class that tells us what the component event dispatch thread is.
+ */
+ static private ComponentEvtDispatchThread cedt = null;
+
+ /**
+ * Handle the synchronization between the thing that populates the
+ * component event dispatch thread ({@link #queueComponentEvent})
+ * and the thing that processes the events ({@link ComponentEvtDispatchThread}).
+ */
+ static Object componentEventQueueLock = new Object();
+
+ /**
+ * Create a new {@code EventQueueMonitor} instance. Normally, this will
+ * be called only by the AWT Toolkit during initialization time.
+ * Assistive technologies should not create instances of
+ * EventQueueMonitor by themselves. Instead, they should either
+ * refer to it directly via the static methods in this class, e.g.,
+ * {@link #getCurrentMousePosition} or obtain the instance by asking the
+ * Toolkit, e.g., {@link java.awt.Toolkit#getSystemEventQueue}.
+ */
+ public EventQueueMonitor() {
+ if (cedt == null) {
+ cedt = new ComponentEvtDispatchThread("EventQueueMonitor-ComponentEvtDispatch");
+
+ cedt.setDaemon(true);
+ cedt.start();
+ }
+ }
+
+ /**
+ * Queue up a {@link java.awt.event.ComponentEvent ComponentEvent} for later
+ * processing by the {@link ComponentEvtDispatch} thread.
+ *
+ * @param e a {@code ComponentEvent}
+ */
+ static void queueComponentEvent(ComponentEvent e) {
+ synchronized(componentEventQueueLock) {
+ EventQueueMonitorItem eqi = new EventQueueMonitorItem(e);
+ if (componentEventQueue == null) {
+ componentEventQueue = eqi;
+ } else {
+ EventQueueMonitorItem q = componentEventQueue;
+ while (true) {
+ if (q.next != null) {
+ q = q.next;
+ } else {
+ break;
+ }
+ }
+ q.next = eqi;
+ }
+ componentEventQueueLock.notifyAll();
+ }
+ }
+
+ /**
+ * Tell the {@code EventQueueMonitor} to start listening for events.
+ */
+ public static void maybeInitialize() {
+ if (cedt == null) {
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Void run() {
+ try {
+ long eventMask = AWTEvent.WINDOW_EVENT_MASK |
+ AWTEvent.FOCUS_EVENT_MASK |
+ AWTEvent.MOUSE_MOTION_EVENT_MASK;
+
+ Toolkit.getDefaultToolkit().addAWTEventListener(new EventQueueMonitor(), eventMask);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+ }
+ );
+ }
+ }
+
+ /**
+ * Handle events as a result of registering a listener
+ * on the {@link java.awt.EventQueue EventQueue} in {@link #maybeInitialize}.
+ */
+ public void eventDispatched(AWTEvent theEvent) {
+ processEvent(theEvent);
+ }
+
+ /**
+ * Assisitive technologies that have
+ * registered a {@link GUIInitializedListener} will be notified.
+ *
+ * @see #addGUIInitializedListener
+ */
+ static void maybeNotifyAssistiveTechnologies() {
+
+ if (!guiInitialized) {
+ guiInitialized = true;
+ if (guiInitializedListener != null) {
+ guiInitializedListener.guiInitialized();
+ }
+ }
+
+ }
+
+ /********************************************************************/
+ /* */
+ /* Package Private Methods */
+ /* */
+ /********************************************************************/
+
+ /**
+ * Add a Container to the list of top-level containers
+ * in the cache. This follows the object's hierarchy up the
+ * tree until it finds the top most parent. If the parent is
+ * not already in the list of Containers, it adds it to the list.
+ *
+ * @param c the Container
+ */
+ static void addTopLevelWindow(Component c) {
+ Container parent;
+
+ if (c == null) {
+ return;
+ }
+
+ if (!(c instanceof Window)) {
+ addTopLevelWindow(c.getParent());
+ return;
+ }
+
+ if ((c instanceof Dialog) || (c instanceof Window)) {
+ parent = (Container) c;
+ } else {
+ parent = c.getParent();
+ if (parent != null) {
+ addTopLevelWindow(parent);
+ return;
+ }
+ }
+
+ if (parent == null) {
+ parent = (Container) c;
+ }
+
+ // Because this method is static, do not make it synchronized because
+ // it can lock the whole class. Instead, just lock what needs to be
+ // locked.
+ //
+ synchronized (topLevelWindows) {
+ if ((parent != null) && !topLevelWindows.contains(parent)) {
+ topLevelWindows.addElement(parent);
+ if (topLevelWindowListener != null) {
+ topLevelWindowListener.topLevelWindowCreated((Window) parent);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes a container from the list of top level containers in the cache.
+ *
+ * @param c the top level container to remove
+ */
+ static void removeTopLevelWindow(Window w) {
+
+ // Because this method is static, do not make it synchronized because
+ // it can lock the whole class. Instead, just lock what needs to be
+ // locked.
+ //
+ synchronized (topLevelWindows) {
+ if (topLevelWindows.contains(w)) {
+ topLevelWindows.removeElement(w);
+ if (topLevelWindowListener != null) {
+ topLevelWindowListener.topLevelWindowDestroyed(w);
+ }
+ }
+ }
+ }
+
+ /**
+ * Update current mouse position.
+ *
+ * @param mouseEvent the MouseEvent that holds the new mouse position.
+ */
+ static void updateCurrentMousePosition(MouseEvent mouseEvent) {
+ Point oldMousePos = currentMousePosition;
+ // Be careful here. The component in the event might be
+ // hidden by the time we process the event.
+ try {
+ Point eventPoint = mouseEvent.getPoint();
+ currentMouseComponent = (Component) (mouseEvent.getSource());
+ currentMousePosition = currentMouseComponent.getLocationOnScreen();
+ currentMousePosition.translate(eventPoint.x,eventPoint.y);
+ } catch (Exception e) {
+ currentMousePosition = oldMousePos;
+ }
+ }
+
+ /**
+ * Process the event. This maintains the event cache in addition
+ * to calling all the registered listeners. NOTE: The events that
+ * come through here are from peered Components.
+ *
+ * @param theEvent the AWTEvent
+ */
+ static void processEvent(AWTEvent theEvent) {
+ switch (theEvent.getID()) {
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ case FocusEvent.FOCUS_GAINED:
+ case WindowEvent.WINDOW_DEACTIVATED:
+ queueComponentEvent((ComponentEvent) theEvent);
+ break;
+
+ case WindowEvent.WINDOW_ACTIVATED:
+ // Dialogs fire WINDOW_ACTIVATED and FOCUS_GAINED events
+ // before WINDOW_OPENED so we need to add topLevelListeners
+ // for the dialog when it is first activated to get a
+ // focus gained event for the focus component in the dialog.
+ if (theEvent instanceof ComponentEvent) {
+ ComponentEvent ce = (ComponentEvent)theEvent;
+ if (ce.getComponent() instanceof Window) {
+ EventQueueMonitor.addTopLevelWindow(ce.getComponent());
+ EventQueueMonitor.maybeNotifyAssistiveTechnologies();
+ } else {
+ EventQueueMonitor.maybeNotifyAssistiveTechnologies();
+ EventQueueMonitor.addTopLevelWindow(ce.getComponent());
+ }
+ }
+ queueComponentEvent((ComponentEvent) theEvent);
+ break;
+
+ // handle WINDOW_OPENED and WINDOW_CLOSED events synchronously
+ case WindowEvent.WINDOW_OPENED:
+ if (theEvent instanceof ComponentEvent) {
+ ComponentEvent ce = (ComponentEvent)theEvent;
+ if (ce.getComponent() instanceof Window) {
+ EventQueueMonitor.addTopLevelWindow(ce.getComponent());
+ EventQueueMonitor.maybeNotifyAssistiveTechnologies();
+ } else {
+ EventQueueMonitor.maybeNotifyAssistiveTechnologies();
+ EventQueueMonitor.addTopLevelWindow(ce.getComponent());
+ }
+ }
+ break;
+ case WindowEvent.WINDOW_CLOSED:
+ if (theEvent instanceof ComponentEvent) {
+ ComponentEvent ce = (ComponentEvent)theEvent;
+ EventQueueMonitor.removeTopLevelWindow((Window) (ce.getComponent()));
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Internal test
+ */
+ static synchronized Component getShowingComponentAt(Container c, int x, int y) {
+ if (!c.contains(x, y)) {
+ return null;
+ }
+ int ncomponents = c.getComponentCount();
+ for (int i = 0 ; i < ncomponents ; i++) {
+ Component comp = c.getComponent(i);
+ if (comp != null && comp.isShowing()) {
+ Point location = comp.getLocation();
+ if (comp.contains(x - location.x, y - location.y)) {
+ return comp;
+ }
+ }
+ }
+ return c;
+ }
+
+ /**
+ * Return the Component at the given Point on the screen in the
+ * given Container.
+ *
+ * @param c the Container to search
+ * @param p the Point in screen coordinates
+ * @return the Component at the given Point on the screen in the
+ * given Container -- can be null if no Component is at that Point
+ */
+ static synchronized Component getComponentAt(Container c, Point p) {
+ if (!c.isShowing()) {
+ return null;
+ }
+
+ Component comp;
+ Point containerLoc = c.getLocationOnScreen();
+ Point containerPoint = new Point(p.x - containerLoc.x,
+ p.y - containerLoc.y);
+
+ comp = getShowingComponentAt(c, containerPoint.x, containerPoint.y);
+
+ if ((comp != c) && (comp instanceof Container)) {
+ return getComponentAt((Container)comp,p);
+ } else {
+ return comp;
+ }
+ }
+
+ /**
+ * Obtain the {@link javax.accessibility.Accessible Accessible} object at the given point on the Screen.
+ * The return value may be null if an {@code Accessible} object cannot be
+ * found at the particular point.
+ *
+ * @param p the point to be accessed
+ * @return the {@code Accessible} at the specified point
+ */
+ static public Accessible getAccessibleAt(Point p) {
+ Window w = getTopLevelWindowWithFocus();
+ Window[] wins = getTopLevelWindows();
+ Component c = null;
+
+ // See if the point we're being asked about is the
+ // currentMousePosition. If so, start with the component
+ // that we know the currentMousePostion is over
+ //
+ if (currentMousePosition == null) {
+ return null;
+ }
+ if (currentMousePosition.equals(p)) {
+ if (currentMouseComponent instanceof Container) {
+ c = getComponentAt((Container) currentMouseComponent, p);
+ }
+ }
+
+ // Try the window with focus next
+ //
+ if (c == null && w != null) {
+ c = getComponentAt(w,p);
+ }
+
+ // Try the other windows next. [[[WDW: Stacking order???]]]
+ if (c == null) {
+ for (int i = 0; i < wins.length; i++) {
+ c = getComponentAt(wins[i],p);
+ if (c != null) {
+ break;
+ }
+ }
+ }
+
+ if (c instanceof Accessible) {
+ AccessibleContext ac = ((Accessible) c).getAccessibleContext();
+ if (ac != null) {
+ AccessibleComponent acmp = ac.getAccessibleComponent();
+ if ((acmp != null) && (ac.getAccessibleChildrenCount() != 0)) {
+ Point location = acmp.getLocationOnScreen();
+ location.move(p.x - location.x, p.y - location.y);
+ return acmp.getAccessibleAt(location);
+ }
+ }
+ return (Accessible) c;
+ } else {
+ return Translator.getAccessible(c);
+ }
+ }
+
+ /********************************************************************/
+ /* */
+ /* Public Methods */
+ /* */
+ /********************************************************************/
+
+ /**
+ * Says whether the GUI subsystem has been initialized or not.
+ * If this returns true, the assistive technology can freely
+ * create GUI component instances. If the return value is false,
+ * the assistive technology should register a {@link GUIInitializedListener}
+ * and wait to create GUI component instances until the listener is
+ * called.
+ *
+ * @return true if the GUI subsystem has been initialized
+ * @see #addGUIInitializedListener
+ */
+ static public boolean isGUIInitialized() {
+ maybeInitialize();
+ return guiInitialized;
+ }
+
+ /**
+ * Adds the specified listener to be notified when the GUI subsystem
+ * is initialized. Assistive technologies should get the results of
+ * {@link #isGUIInitialized} before calling this method.
+ *
+ * @param l the listener to add
+ * @see #isGUIInitialized
+ * @see #removeTopLevelWindowListener
+ */
+ static public void addGUIInitializedListener(GUIInitializedListener l) {
+ maybeInitialize();
+ guiInitializedListener =
+ GUIInitializedMulticaster.add(guiInitializedListener,l);
+ }
+
+ /**
+ * Removes the specified listener to be notified when the GUI subsystem
+ * is initialized.
+ *
+ * @param l the listener to remove
+ * @see #addGUIInitializedListener
+ */
+ static public void removeGUIInitializedListener(GUIInitializedListener l) {
+ guiInitializedListener =
+ GUIInitializedMulticaster.remove(guiInitializedListener,l);
+ }
+
+ /**
+ * Adds the specified listener to be notified when a top level window
+ * is created or destroyed.
+ *
+ * @param l the listener to add
+ * @see #removeTopLevelWindowListener
+ */
+ static public void addTopLevelWindowListener(TopLevelWindowListener l) {
+ topLevelWindowListener =
+ TopLevelWindowMulticaster.add(topLevelWindowListener,l);
+ }
+
+ /**
+ * Removes the specified listener to be notified when a top level window
+ * is created or destroyed.
+ *
+ * @param l the listener to remove
+ * @see #addTopLevelWindowListener
+ */
+ static public void removeTopLevelWindowListener(TopLevelWindowListener l) {
+ topLevelWindowListener =
+ TopLevelWindowMulticaster.remove(topLevelWindowListener,l);
+ }
+
+ /**
+ * Return the last recorded position of the mouse in screen coordinates.
+ *
+ * @return the last recorded position of the mouse in screen coordinates
+ */
+ static public Point getCurrentMousePosition() {
+ return currentMousePosition;
+ }
+
+ /**
+ * Return the list of top level Windows in use in the Java Virtual Machine.
+ *
+ * @return an array of top level {@code Window}s in use in the Java Virtual Machine
+ */
+ static public Window[] getTopLevelWindows() {
+
+ // Because this method is static, do not make it synchronized because
+ // it can lock the whole class. Instead, just lock what needs to be
+ // locked.
+ //
+ synchronized (topLevelWindows) {
+ int count = topLevelWindows.size();
+ if (count > 0) {
+ Window[] w = new Window[count];
+ for (int i = 0; i < count; i++) {
+ w[i] = (Window)topLevelWindows.elementAt(i);
+ }
+ return w;
+ } else {
+ return new Window[0];
+ }
+ }
+ }
+
+ /**
+ * Return the top level {@code Window} that currently has keyboard focus.
+ *
+ * @return the top level {@code Window} that currently has keyboard focus
+ */
+ static public Window getTopLevelWindowWithFocus() {
+ return topLevelWindowWithFocus;
+ }
+}
+
+/**
+ * Handle all Component events in a separate thread. The reason for this is
+ * that WindowEvents tend to be used to do lots of processing on the Window
+ * hierarchy. As a result, it can frequently result in deadlock situations.
+ */
+class ComponentEvtDispatchThread extends Thread {
+ public ComponentEvtDispatchThread(String name) {
+ super(name);
+ }
+ public void run() {
+ ComponentEvent ce = null;
+ while (true) {
+ synchronized(EventQueueMonitor.componentEventQueueLock) {
+ while (EventQueueMonitor.componentEventQueue == null) {
+ try {
+ EventQueueMonitor.componentEventQueueLock.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ ce = (ComponentEvent)EventQueueMonitor.componentEventQueue.event;
+ EventQueueMonitor.componentEventQueue =
+ EventQueueMonitor.componentEventQueue.next;
+ }
+ switch (ce.getID()) {
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ EventQueueMonitor.updateCurrentMousePosition((MouseEvent) ce);
+ break;
+ case WindowEvent.WINDOW_ACTIVATED:
+ EventQueueMonitor.maybeNotifyAssistiveTechnologies();
+ EventQueueMonitor.topLevelWindowWithFocus = ((WindowEvent) ce).getWindow();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * EventQueueMonitorItem is the basic type that handles the
+ * queue for queueComponentEvent and the ComponentEvtDispatchThread.
+ */
+class EventQueueMonitorItem {
+ AWTEvent event;
+ EventQueueMonitorItem next;
+
+ EventQueueMonitorItem(AWTEvent evt) {
+ event = evt;
+ next = null;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedListener.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedListener.java
new file mode 100644
index 00000000000..9a4474d3e6b
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedListener.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.awt.*;
+import java.util.*;
+import javax.accessibility.*;
+
+/**
+ * The {@code GUIInitializedListener} interface is used by the {@link EventQueueMonitor}
+ * class to notify an interested party when the GUI subsystem has been
+ * initialized. This is necessary because assistive technologies can
+ * be loaded before the GUI subsystem is initialized. As a result,
+ * assistive technologies should check the
+ * {@link EventQueueMonitor#isGUIInitialized isGUIInitialized} method
+ * of {@code EventQueueMonitor} before creating any GUI components. If the
+ * return value is true, assistive technologies can create GUI components
+ * following the same thread restrictions as any other application. If
+ * the return value is false, the assistive technology should register
+ * a {@code GUIInitializedListener} with the {@code EventQueueMonitor} to be notified
+ * when the GUI subsystem is initialized.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#isGUIInitialized
+ * @see EventQueueMonitor#addGUIInitializedListener
+ * @see EventQueueMonitor#removeGUIInitializedListener
+ *
+ */
+@jdk.Exported
+public interface GUIInitializedListener extends EventListener {
+
+ /**
+ * Invoked when the GUI subsystem is initialized and it's OK for
+ * the assisitive technology to create instances of GUI objects.
+ */
+ public void guiInitialized();
+
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedMulticaster.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedMulticaster.java
new file mode 100644
index 00000000000..900b6078f7e
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedMulticaster.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.awt.*;
+import java.util.EventListener;
+import javax.accessibility.*;
+
+
+/**
+ * The GUIInitializedMulticaster class is used to maintain a list of
+ * GUIInitializedListener classes. It is intended to be used primarily
+ * for internal support in the EventQueueMonitor class, and is not intended
+ * to be used by classes outside the Java Accessibility Utility package.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addGUIInitializedListener
+ * @see EventQueueMonitor#removeGUIInitializedListener
+ *
+ */
+class GUIInitializedMulticaster
+ extends AWTEventMulticaster implements GUIInitializedListener
+{
+ protected GUIInitializedMulticaster(EventListener a, EventListener b) {
+ super(a, b);
+ }
+
+ public void guiInitialized() {
+ ((GUIInitializedListener)a).guiInitialized();
+ ((GUIInitializedListener)b).guiInitialized();
+ }
+
+ public static GUIInitializedListener add(GUIInitializedListener a, GUIInitializedListener b) {
+ return (GUIInitializedListener)addInternal(a, b);
+ }
+
+ public static GUIInitializedListener remove(GUIInitializedListener l, GUIInitializedListener oldl) {
+ return (GUIInitializedListener)removeInternal(l, oldl);
+ }
+
+ protected static EventListener addInternal(EventListener a, EventListener b) {
+ if (a == null) return b;
+ if (b == null) return a;
+ return new GUIInitializedMulticaster(a, b);
+ }
+
+ protected static EventListener removeInternal(EventListener l, EventListener oldl) {
+ if (l == oldl || l == null) {
+ return null;
+ } else if (l instanceof GUIInitializedMulticaster) {
+ return ((GUIInitializedMulticaster)l).remove(oldl);
+ } else {
+ return l; // it's not here
+ }
+ }
+
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/SwingEventMonitor.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/SwingEventMonitor.java
new file mode 100644
index 00000000000..c2150cd78f8
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/SwingEventMonitor.java
@@ -0,0 +1,2530 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.util.*;
+import java.beans.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.table.*;
+import javax.swing.tree.*;
+import javax.swing.text.*;
+import javax.swing.undo.*;
+import javax.accessibility.*;
+
+
+/**
+ *
{@code SwingEventMonitor} extends {@link AWTEventMonitor} by adding a suite of
+ * listeners conditionally installed on every Swing component instance
+ * in the Java Virtual Machine. The events captured by these listeners
+ * are made available through a unified set of listeners supported by
+ * {@code SwingEventMonitor}. With this, all the individual events on each of the
+ * AWT and Swing component instances are funneled into one set of listeners
+ * broken down by category (see {@link EventID} for the categories).
+ *
This class depends upon {@link EventQueueMonitor}, which provides the base
+ * level support for capturing the top-level containers as they are created.
+ *
Because this class extends {@code AWTEventMonitor}, it is not
+ * necessary to use this class and {@code AWTEventMonitor} at the same time.
+ * If you want to monitor both AWT and Swing components, you should
+ * use just this class.
+ *
+ * @see AWTEventMonitor
+ *
+ */
+@jdk.Exported
+public class SwingEventMonitor extends AWTEventMonitor {
+
+ /**
+ * The master list of all listeners registered by other classes.
+ * This can only be publicly modified by calling the add or
+ * remove listener methods in this class.
+ */
+ static protected final EventListenerList listenerList = new EventListenerList();
+
+ /**
+ * The actual listener that is installed on the component instances.
+ * This listener calls the other registered listeners when an event
+ * occurs. By doing things this way, the actual number of listeners
+ * installed on a component instance is drastically reduced.
+ */
+ static protected final SwingEventListener swingListener = new SwingEventListener();
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#ANCESTOR ANCESTOR}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeAncestorListener
+ */
+ static public void addAncestorListener(AncestorListener l) {
+ if (listenerList.getListenerCount(AncestorListener.class) == 0) {
+ swingListener.installListeners(EventID.ANCESTOR);
+ }
+ listenerList.add(AncestorListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#ANCESTOR ANCESTOR} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addAncestorListener
+ */
+ static public void removeAncestorListener(AncestorListener l) {
+ listenerList.remove(AncestorListener.class, l);
+ if (listenerList.getListenerCount(AncestorListener.class) == 0) {
+ swingListener.removeListeners(EventID.ANCESTOR);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#CARET CARET} events
+ * on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeCaretListener
+ */
+ static public void addCaretListener(CaretListener l) {
+ if (listenerList.getListenerCount(CaretListener.class) == 0) {
+ swingListener.installListeners(EventID.CARET);
+ }
+ listenerList.add(CaretListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#CARET CARET} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addCaretListener
+ */
+ static public void removeCaretListener(CaretListener l) {
+ listenerList.remove(CaretListener.class, l);
+ if (listenerList.getListenerCount(CaretListener.class) == 0) {
+ swingListener.removeListeners(EventID.CARET);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all
+ * {@link EventID#CELLEDITOR CELLEDITOR} events on each
+ * component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeCellEditorListener
+ */
+ static public void addCellEditorListener(CellEditorListener l) {
+ if (listenerList.getListenerCount(CellEditorListener.class) == 0) {
+ swingListener.installListeners(EventID.CELLEDITOR);
+ }
+ listenerList.add(CellEditorListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#CELLEDITOR CELLEDITOR} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addCellEditorListener
+ */
+ static public void removeCellEditorListener(CellEditorListener l) {
+ listenerList.remove(CellEditorListener.class, l);
+ if (listenerList.getListenerCount(CellEditorListener.class) == 0) {
+ swingListener.removeListeners(EventID.CELLEDITOR);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#CHANGE CHANGE}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeChangeListener
+ */
+ static public void addChangeListener(ChangeListener l) {
+ if (listenerList.getListenerCount(ChangeListener.class) == 0) {
+ swingListener.installListeners(EventID.CHANGE);
+ }
+ listenerList.add(ChangeListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#CHANGE CHANGE} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addChangeListener
+ */
+ static public void removeChangeListener(ChangeListener l) {
+ listenerList.remove(ChangeListener.class, l);
+ if (listenerList.getListenerCount(ChangeListener.class) == 0) {
+ swingListener.removeListeners(EventID.CHANGE);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#COLUMNMODEL COLUMNMODEL}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeColumnModelListener
+ */
+ static public void addColumnModelListener(TableColumnModelListener l) {
+ if (listenerList.getListenerCount(TableColumnModelListener.class) == 0) {
+ swingListener.installListeners(EventID.COLUMNMODEL);
+ }
+ listenerList.add(TableColumnModelListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#COLUMNMODEL COLUMNMODEL} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addColumnModelListener
+ */
+ static public void removeColumnModelListener(TableColumnModelListener l) {
+ listenerList.remove(TableColumnModelListener.class, l);
+ if (listenerList.getListenerCount(TableColumnModelListener.class) == 0) {
+ swingListener.removeListeners(EventID.COLUMNMODEL);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#DOCUMENT DOCUMENT}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeDocumentListener
+ */
+ static public void addDocumentListener(DocumentListener l) {
+ if (listenerList.getListenerCount(DocumentListener.class) == 0) {
+ swingListener.installListeners(EventID.DOCUMENT);
+ }
+ listenerList.add(DocumentListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#DOCUMENT DOCUMENT} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addDocumentListener
+ */
+ static public void removeDocumentListener(DocumentListener l) {
+ listenerList.remove(DocumentListener.class, l);
+ if (listenerList.getListenerCount(DocumentListener.class) == 0) {
+ swingListener.removeListeners(EventID.DOCUMENT);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#LISTDATA LISTDATA}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeListDataListener
+ */
+ static public void addListDataListener(ListDataListener l) {
+ if (listenerList.getListenerCount(ListDataListener.class) == 0) {
+ swingListener.installListeners(EventID.LISTDATA);
+ }
+ listenerList.add(ListDataListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#LISTDATA LISTDATA} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addListDataListener
+ */
+ static public void removeListDataListener(ListDataListener l) {
+ listenerList.remove(ListDataListener.class, l);
+ if (listenerList.getListenerCount(ListDataListener.class) == 0) {
+ swingListener.removeListeners(EventID.LISTDATA);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#LISTSELECTION LISTSELECTION}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeListSelectionListener
+ */
+ static public void addListSelectionListener(ListSelectionListener l) {
+ if (listenerList.getListenerCount(ListSelectionListener.class) == 0) {
+ swingListener.installListeners(EventID.LISTSELECTION);
+ }
+ listenerList.add(ListSelectionListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#LISTSELECTION LISTSELECTION} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addListSelectionListener
+ */
+ static public void removeListSelectionListener(ListSelectionListener l) {
+ listenerList.remove(ListSelectionListener.class, l);
+ if (listenerList.getListenerCount(ListSelectionListener.class) == 0) {
+ swingListener.removeListeners(EventID.LISTSELECTION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#MENU MENU} events
+ * on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeMenuListener
+ */
+ static public void addMenuListener(MenuListener l) {
+ if (listenerList.getListenerCount(MenuListener.class) == 0) {
+ swingListener.installListeners(EventID.MENU);
+ }
+ listenerList.add(MenuListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#MENU MENU} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addMenuListener
+ */
+ static public void removeMenuListener(MenuListener l) {
+ listenerList.remove(MenuListener.class, l);
+ if (listenerList.getListenerCount(MenuListener.class) == 0) {
+ swingListener.removeListeners(EventID.MENU);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#POPUPMENU POPUPMENU}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removePopupMenuListener
+ */
+ static public void addPopupMenuListener(PopupMenuListener l) {
+ if (listenerList.getListenerCount(PopupMenuListener.class) == 0) {
+ swingListener.installListeners(EventID.POPUPMENU);
+ }
+ listenerList.add(PopupMenuListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#POPUPMENU POPUPMENU} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addPopupMenuListener
+ */
+ static public void removePopupMenuListener(PopupMenuListener l) {
+ listenerList.remove(PopupMenuListener.class, l);
+ if (listenerList.getListenerCount(PopupMenuListener.class) == 0) {
+ swingListener.removeListeners(EventID.POPUPMENU);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#TABLEMODEL TABLEMODEL}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeTableModelListener
+ */
+ static public void addTableModelListener(TableModelListener l) {
+ if (listenerList.getListenerCount(TableModelListener.class) == 0) {
+ swingListener.installListeners(EventID.TABLEMODEL);
+ }
+ listenerList.add(TableModelListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#TABLEMODEL TABLEMODEL} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addTableModelListener
+ */
+ static public void removeTableModelListener(TableModelListener l) {
+ listenerList.remove(TableModelListener.class, l);
+ if (listenerList.getListenerCount(TableModelListener.class) == 0) {
+ swingListener.removeListeners(EventID.TABLEMODEL);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#TREEEXPANSION TREEEXPANSION}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeTreeExpansionListener
+ */
+ static public void addTreeExpansionListener(TreeExpansionListener l) {
+ if (listenerList.getListenerCount(TreeExpansionListener.class) == 0) {
+ swingListener.installListeners(EventID.TREEEXPANSION);
+ }
+ listenerList.add(TreeExpansionListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#TREEEXPANSION TREEEXPANSION} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addTreeExpansionListener
+ */
+ static public void removeTreeExpansionListener(TreeExpansionListener l) {
+ listenerList.remove(TreeExpansionListener.class, l);
+ if (listenerList.getListenerCount(TreeExpansionListener.class) == 0) {
+ swingListener.removeListeners(EventID.TREEEXPANSION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#TREEMODEL TREEMODEL}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeTreeModelListener
+ */
+ static public void addTreeModelListener(TreeModelListener l) {
+ if (listenerList.getListenerCount(TreeModelListener.class) == 0) {
+ swingListener.installListeners(EventID.TREEMODEL);
+ }
+ listenerList.add(TreeModelListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#TREEMODEL TREEMODEL} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addTreeModelListener
+ */
+ static public void removeTreeModelListener(TreeModelListener l) {
+ listenerList.remove(TreeModelListener.class, l);
+ if (listenerList.getListenerCount(TreeModelListener.class) == 0) {
+ swingListener.removeListeners(EventID.TREEMODEL);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#TREESELECTION TREESELECTION}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeTreeSelectionListener
+ */
+ static public void addTreeSelectionListener(TreeSelectionListener l) {
+ if (listenerList.getListenerCount(TreeSelectionListener.class) == 0) {
+ swingListener.installListeners(EventID.TREESELECTION);
+ }
+ listenerList.add(TreeSelectionListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#TREESELECTION TREESELECTION} events when they occur.
+ * @see #addTreeSelectionListener
+ * @param l the listener to remove
+ */
+ static public void removeTreeSelectionListener(TreeSelectionListener l) {
+ listenerList.remove(TreeSelectionListener.class, l);
+ if (listenerList.getListenerCount(TreeSelectionListener.class) == 0) {
+ swingListener.removeListeners(EventID.TREESELECTION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#UNDOABLEEDIT UNDOABLEEDIT}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeUndoableEditListener
+ */
+ static public void addUndoableEditListener(UndoableEditListener l) {
+ if (listenerList.getListenerCount(UndoableEditListener.class) == 0) {
+ swingListener.installListeners(EventID.UNDOABLEEDIT);
+ }
+ listenerList.add(UndoableEditListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#UNDOABLEEDIT UNDOABLEEDIT} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addUndoableEditListener
+ */
+ static public void removeUndoableEditListener(UndoableEditListener l) {
+ listenerList.remove(UndoableEditListener.class, l);
+ if (listenerList.getListenerCount(UndoableEditListener.class) == 0) {
+ swingListener.removeListeners(EventID.UNDOABLEEDIT);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#INTERNALFRAME INTERNALFRAME}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeInternalFrameListener
+ */
+ static public void addInternalFrameListener(InternalFrameListener l) {
+ if (listenerList.getListenerCount(InternalFrameListener.class) == 0) {
+ swingListener.installListeners(EventID.INTERNALFRAME);
+ }
+ listenerList.add(InternalFrameListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#INTERNALFRAME INTERNALFRAME} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addInternalFrameListener
+ */
+ static public void removeInternalFrameListener(InternalFrameListener l) {
+ listenerList.remove(InternalFrameListener.class, l);
+ if (listenerList.getListenerCount(InternalFrameListener.class) == 0) {
+ swingListener.removeListeners(EventID.INTERNALFRAME);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#PROPERTYCHANGE PROPERTYCHANGE}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removePropertyChangeListener
+ */
+ static public void addPropertyChangeListener(PropertyChangeListener l) {
+ if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
+ swingListener.installListeners(EventID.PROPERTYCHANGE);
+ }
+ listenerList.add(PropertyChangeListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#PROPERTYCHANGE PROPERTYCHANGE} events when they occur.
+ * @see #addPropertyChangeListener
+ * @param l the listener to remove
+ */
+ static public void removePropertyChangeListener(PropertyChangeListener l) {
+ listenerList.remove(PropertyChangeListener.class, l);
+ if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
+ swingListener.removeListeners(EventID.PROPERTYCHANGE);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#VETOABLECHANGE VETOABLECHANGE}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeVetoableChangeListener
+ */
+ static public void addVetoableChangeListener(VetoableChangeListener l) {
+ if (listenerList.getListenerCount(VetoableChangeListener.class) == 0) {
+ swingListener.installListeners(EventID.VETOABLECHANGE);
+ }
+ listenerList.add(VetoableChangeListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#VETOABLECHANGE VETOABLECHANGE} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addVetoableChangeListener
+ */
+ static public void removeVetoableChangeListener(VetoableChangeListener l) {
+ listenerList.remove(VetoableChangeListener.class, l);
+ if (listenerList.getListenerCount(VetoableChangeListener.class) == 0) {
+ swingListener.removeListeners(EventID.VETOABLECHANGE);
+ }
+ }
+
+
+ /**
+ * SwingEventListener is the class that does all the work for
+ * SwingEventMonitor. It is not intended for use by any other class
+ * except SwingEventMonitor.
+ *
+ */
+ static class SwingEventListener extends AWTEventsListener
+ implements AncestorListener, CaretListener, CellEditorListener,
+ ChangeListener, DocumentListener, ListDataListener,
+ ListSelectionListener, MenuListener, PopupMenuListener,
+ TableColumnModelListener, TableModelListener, TreeExpansionListener,
+ TreeModelListener, TreeSelectionListener, UndoableEditListener,
+ InternalFrameListener,
+ PropertyChangeListener, VetoableChangeListener {
+
+ /**
+ * internal variables for Caret introspection
+ */
+ private java.lang.Class>[] caretListeners;
+ private java.lang.reflect.Method removeCaretMethod;
+ private java.lang.reflect.Method addCaretMethod;
+ private java.lang.Object[] caretArgs;
+
+ /**
+ * internal variables for CellEditor introspection
+ */
+ private java.lang.Class>[] cellEditorListeners;
+ private java.lang.reflect.Method removeCellEditorMethod;
+ private java.lang.reflect.Method addCellEditorMethod;
+ private java.lang.Object[] cellEditorArgs;
+ private java.lang.reflect.Method getCellEditorMethod;
+
+ /**
+ * internal variables for Change introspection
+ */
+ private java.lang.Class>[] changeListeners;
+ private java.lang.reflect.Method removeChangeMethod;
+ private java.lang.reflect.Method addChangeMethod;
+ private java.lang.Object[] changeArgs;
+
+ /**
+ * internal variable for ColumnModel introspection
+ */
+ private java.lang.reflect.Method getColumnModelMethod;
+
+ /**
+ * internal variables for Document introspection
+ */
+ private java.lang.Class>[] documentListeners;
+ private java.lang.reflect.Method removeDocumentMethod;
+ private java.lang.reflect.Method addDocumentMethod;
+ private java.lang.Object[] documentArgs;
+ private java.lang.reflect.Method getDocumentMethod;
+
+ /**
+ * internal variable for ListData, Table, and Tree introspection
+ */
+ private java.lang.reflect.Method getModelMethod;
+
+ /**
+ * internal variables for ListSelection introspection
+ */
+ private java.lang.Class>[] listSelectionListeners;
+ private java.lang.reflect.Method removeListSelectionMethod;
+ private java.lang.reflect.Method addListSelectionMethod;
+ private java.lang.Object[] listSelectionArgs;
+ private java.lang.reflect.Method getSelectionModelMethod;
+
+ /**
+ * internal variables for Menu introspection
+ */
+ private java.lang.Class>[] menuListeners;
+ private java.lang.reflect.Method removeMenuMethod;
+ private java.lang.reflect.Method addMenuMethod;
+ private java.lang.Object[] menuArgs;
+
+ /**
+ * internal variables for PopupMenu introspection
+ */
+ private java.lang.Class>[] popupMenuListeners;
+ private java.lang.reflect.Method removePopupMenuMethod;
+ private java.lang.reflect.Method addPopupMenuMethod;
+ private java.lang.Object[] popupMenuArgs;
+ private java.lang.reflect.Method getPopupMenuMethod;
+
+ /**
+ * internal variables for TreeExpansion introspection
+ */
+ private java.lang.Class>[] treeExpansionListeners;
+ private java.lang.reflect.Method removeTreeExpansionMethod;
+ private java.lang.reflect.Method addTreeExpansionMethod;
+ private java.lang.Object[] treeExpansionArgs;
+
+ /**
+ * internal variables for TreeSelection introspection
+ */
+ private java.lang.Class>[] treeSelectionListeners;
+ private java.lang.reflect.Method removeTreeSelectionMethod;
+ private java.lang.reflect.Method addTreeSelectionMethod;
+ private java.lang.Object[] treeSelectionArgs;
+
+ /**
+ * internal variables for UndoableEdit introspection
+ */
+ private java.lang.Class>[] undoableEditListeners;
+ private java.lang.reflect.Method removeUndoableEditMethod;
+ private java.lang.reflect.Method addUndoableEditMethod;
+ private java.lang.Object[] undoableEditArgs;
+
+ /**
+ * internal variables for InternalFrame introspection
+ */
+ private java.lang.Class>[] internalFrameListeners;
+ private java.lang.reflect.Method removeInternalFrameMethod;
+ private java.lang.reflect.Method addInternalFrameMethod;
+ private java.lang.Object[] internalFrameArgs;
+
+ /**
+ * internal variables for PropertyChange introspection
+ */
+ private java.lang.Class>[] propertyChangeListeners;
+ private java.lang.reflect.Method removePropertyChangeMethod;
+ private java.lang.reflect.Method addPropertyChangeMethod;
+ private java.lang.Object[] propertyChangeArgs;
+
+ /**
+ * internal variables for a variety of change introspections
+ */
+ private java.lang.Class>[] nullClass;
+ private java.lang.Object[] nullArgs;
+
+ /**
+ * Create a new instance of this class and install it on each component
+ * instance in the virtual machine that supports any of the currently
+ * registered listeners in SwingEventMonitor. Also registers itself
+ * as a TopLevelWindowListener with EventQueueMonitor so it can
+ * automatically add new listeners to new components.
+ * @see EventQueueMonitor
+ * @see SwingEventMonitor
+ */
+ public SwingEventListener() {
+ initializeIntrospection();
+ installListeners();
+ EventQueueMonitor.addTopLevelWindowListener(this);
+ }
+
+ /**
+ * Set up all of the variables needed for introspection
+ */
+ private boolean initializeIntrospection() {
+ caretListeners = new java.lang.Class>[1];
+ caretArgs = new java.lang.Object[1];
+ caretListeners[0] = javax.swing.event.CaretListener.class;
+ caretArgs[0] = this;
+
+ cellEditorListeners = new java.lang.Class>[1];
+ cellEditorArgs = new java.lang.Object[1];
+ cellEditorListeners[0] = javax.swing.event.CellEditorListener.class;
+ cellEditorArgs[0] = this;
+
+ changeListeners = new java.lang.Class>[1];
+ changeArgs = new java.lang.Object[1];
+ changeListeners[0] = javax.swing.event.ChangeListener.class;
+ changeArgs[0] = this;
+
+ documentListeners = new java.lang.Class>[1];
+ documentArgs = new java.lang.Object[1];
+ documentListeners[0] = javax.swing.event.DocumentListener.class;
+ documentArgs[0] = this;
+
+ listSelectionListeners = new java.lang.Class>[1];
+ listSelectionArgs = new java.lang.Object[1];
+ listSelectionListeners[0] = javax.swing.event.ListSelectionListener.class;
+ listSelectionArgs[0] = this;
+
+ menuListeners = new java.lang.Class>[1];
+ menuArgs = new java.lang.Object[1];
+ menuListeners[0] = javax.swing.event.MenuListener.class;
+ menuArgs[0] = this;
+
+ popupMenuListeners = new java.lang.Class>[1];
+ popupMenuArgs = new java.lang.Object[1];
+ popupMenuListeners[0] = javax.swing.event.PopupMenuListener.class;
+ popupMenuArgs[0] = this;
+
+ treeExpansionListeners = new java.lang.Class>[1];
+ treeExpansionArgs = new java.lang.Object[1];
+ treeExpansionListeners[0] = javax.swing.event.TreeExpansionListener.class;
+ treeExpansionArgs[0] = this;
+
+ treeSelectionListeners = new java.lang.Class>[1];
+ treeSelectionArgs = new java.lang.Object[1];
+ treeSelectionListeners[0] = javax.swing.event.TreeSelectionListener.class;
+ treeSelectionArgs[0] = this;
+
+ undoableEditListeners = new java.lang.Class>[1];
+ undoableEditArgs = new java.lang.Object[1];
+ undoableEditListeners[0] = javax.swing.event.UndoableEditListener.class;
+ undoableEditArgs[0] = this;
+
+ internalFrameListeners = new java.lang.Class>[1];
+ internalFrameArgs = new java.lang.Object[1];
+ internalFrameListeners[0] = javax.swing.event.InternalFrameListener.class;
+ internalFrameArgs[0] = this;
+
+ nullClass = new java.lang.Class>[0];
+ nullArgs = new java.lang.Object[0];
+
+ propertyChangeListeners = new java.lang.Class>[1];
+ propertyChangeArgs = new java.lang.Object[1];
+ propertyChangeListeners[0] = java.beans.PropertyChangeListener.class;
+ propertyChangeArgs[0] = this;
+
+ return true;
+ }
+
+ /**
+ * Installs all appropriate Swing listeners to just the component.
+ * Also calls super (AWTEventsListener.installListeners()) to install
+ * the requested AWT listeners.
+ * @param c the component to add listeners to
+ */
+ protected void installListeners(Component c) {
+
+ // This SwingEventListener needs to be notified when a new
+ // Swing component has been added so it can add Swing listeners
+ // to these components. As a result, we always need a Container
+ // listener on every Container.
+ //
+ installListeners(c,EventID.CONTAINER);
+
+ // conditionally install Swing listeners
+ //
+ if (SwingEventMonitor.listenerList.getListenerCount(AncestorListener.class) > 0) {
+ installListeners(c,EventID.ANCESTOR);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(CaretListener.class) > 0) {
+ installListeners(c,EventID.CARET);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(CellEditorListener.class) > 0) {
+ installListeners(c,EventID.CELLEDITOR);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ChangeListener.class) > 0) {
+ installListeners(c,EventID.CHANGE);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TableColumnModelListener.class) > 0) {
+ installListeners(c,EventID.COLUMNMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(DocumentListener.class) > 0) {
+ installListeners(c,EventID.DOCUMENT);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ListDataListener.class) > 0) {
+ installListeners(c,EventID.LISTDATA);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ListSelectionListener.class) > 0) {
+ installListeners(c,EventID.LISTSELECTION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(MenuListener.class) > 0) {
+ installListeners(c,EventID.MENU);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(PopupMenuListener.class) > 0) {
+ installListeners(c,EventID.POPUPMENU);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TableModelListener.class) > 0) {
+ installListeners(c,EventID.TABLEMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeExpansionListener.class) > 0) {
+ installListeners(c,EventID.TREEEXPANSION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeModelListener.class) > 0) {
+ installListeners(c,EventID.TREEMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeSelectionListener.class) > 0) {
+ installListeners(c,EventID.TREESELECTION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(UndoableEditListener.class) > 0) {
+ installListeners(c,EventID.UNDOABLEEDIT);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(InternalFrameListener.class) > 0) {
+ installListeners(c,EventID.INTERNALFRAME);
+ }
+
+ // Conditionally install Beans listeners
+ //
+ if (SwingEventMonitor.listenerList.getListenerCount(PropertyChangeListener.class) > 0) {
+ installListeners(c,EventID.PROPERTYCHANGE);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(VetoableChangeListener.class) > 0) {
+ installListeners(c,EventID.VETOABLECHANGE);
+ }
+
+ // Now install the AWT listeners if needed.
+ //
+ super.installListeners(c);
+ }
+
+ /**
+ * Installs all appropriate Swing listeners to the component and all its
+ * children. As a precaution, it always attempts to remove itself as
+ * a listener first so we're always guaranteed it will installed itself
+ * just once.
+ * @param c the component to add listeners to
+ * @param eventID the eventID to add listeners for
+ */
+ protected void installListeners(Component c, int eventID) {
+
+ // install the appropriate listener hook into this component
+ //
+ switch (eventID) {
+
+ case EventID.CONTAINER:
+ if (c instanceof Container) {
+ ((Container) c).removeContainerListener(this);
+ ((Container) c).addContainerListener(this);
+ }
+ break;
+
+ case EventID.ANCESTOR:
+ if (c instanceof JComponent) {
+ ((JComponent) c).removeAncestorListener(this);
+ ((JComponent) c).addAncestorListener(this);
+ }
+ break;
+
+ case EventID.CARET:
+ try {
+ removeCaretMethod = c.getClass().getMethod(
+ "removeCaretListener", caretListeners);
+ addCaretMethod = c.getClass().getMethod(
+ "addCaretListener", caretListeners);
+ try {
+ removeCaretMethod.invoke(c, caretArgs);
+ addCaretMethod.invoke(c, caretArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.CELLEDITOR:
+ // Look for components which support the getCellEditor method
+ // (e.g. JTable, JTree)
+ //
+ try {
+ getCellEditorMethod = c.getClass().getMethod(
+ "getCellEditorMethod", nullClass);
+ try {
+ Object o = getCellEditorMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof CellEditor) {
+ ((CellEditor) o).removeCellEditorListener(this);
+ ((CellEditor) o).addCellEditorListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support CellEditor listeners
+ // (no current example)
+ //
+ try {
+ removeCellEditorMethod = c.getClass().getMethod(
+ "removeCellEditorListener", cellEditorListeners);
+ addCellEditorMethod = c.getClass().getMethod(
+ "addCellEditorListener", cellEditorListeners);
+ try {
+ removeCellEditorMethod.invoke(c, cellEditorArgs);
+ addCellEditorMethod.invoke(c, cellEditorArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.CHANGE:
+ // [[[FIXME: Need to add support for Style, StyleContext -pk]]]
+
+ // Look for components which support Change listeners
+ // (e.g. AbstractButton, Caret, JProgressBar, JSlider,
+ // JTabbedpane, JTextComponent, JViewport)
+ //
+ try {
+ removeChangeMethod = c.getClass().getMethod(
+ "removeChangeListener", changeListeners);
+ addChangeMethod = c.getClass().getMethod(
+ "addChangeListener", changeListeners);
+ try {
+ removeChangeMethod.invoke(c, changeArgs);
+ addChangeMethod.invoke(c, changeArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support the getModel method
+ // whose model supports Change listeners
+ // (e.g. BoundedRangeModel, ButtonModel, SingleSelectionModel)
+ //
+ try {
+ getModelMethod = c.getClass().getMethod(
+ "getModel", nullClass);
+ try {
+ Object o = getModelMethod.invoke(c, nullArgs);
+ if (o != null) {
+ removeChangeMethod = o.getClass().getMethod(
+ "removeChangeListener", changeListeners);
+ addChangeMethod = o.getClass().getMethod(
+ "addChangeListener", changeListeners);
+ removeChangeMethod.invoke(o, changeArgs);
+ addChangeMethod.invoke(o, changeArgs);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ break;
+
+ case EventID.COLUMNMODEL:
+ try {
+ getColumnModelMethod = c.getClass().getMethod(
+ "getTableColumnModel", nullClass);
+ try {
+ Object o = getColumnModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof TableColumnModel) {
+ ((TableColumnModel) o).removeColumnModelListener(this);
+ ((TableColumnModel) o).addColumnModelListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.DOCUMENT:
+ // Look for components which support the getDocument method
+ // (e.g. JTextComponent)
+ //
+ try {
+ getDocumentMethod = c.getClass().getMethod(
+ "getDocument", nullClass);
+ try {
+ Object o = getDocumentMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof Document) {
+ ((Document) o).removeDocumentListener(this);
+ ((Document) o).addDocumentListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support Document listeners
+ // (no current example)
+ //
+ try {
+ removeDocumentMethod = c.getClass().getMethod(
+ "removeDocumentListener", documentListeners);
+ addDocumentMethod = c.getClass().getMethod(
+ "addDocumentListener", documentListeners);
+ try {
+ removeDocumentMethod.invoke(c, documentArgs);
+ addDocumentMethod.invoke(c, documentArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ // Add the monitor as a PropertyChangeListener for document
+ // change events from text components.
+ //
+ if (c instanceof JTextComponent) {
+ try {
+ removePropertyChangeMethod = c.getClass().getMethod(
+ "removePropertyChangeListener",
+ propertyChangeListeners);
+ addPropertyChangeMethod = c.getClass().getMethod(
+ "addPropertyChangeListener",
+ propertyChangeListeners);
+ try {
+ removePropertyChangeMethod.invoke(c,
+ propertyChangeArgs);
+ addPropertyChangeMethod.invoke(c,
+ propertyChangeArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ }
+ break;
+
+ case EventID.LISTDATA:
+ case EventID.TABLEMODEL:
+ case EventID.TREEMODEL:
+ try {
+ getModelMethod = c.getClass().getMethod(
+ "getModel", nullClass);
+ try {
+ Object o = getModelMethod.invoke(c, nullArgs);
+ if (o != null) {
+ if (eventID == EventID.LISTDATA &&
+ o instanceof ListModel) {
+ ((ListModel) o).removeListDataListener(this);
+ ((ListModel) o).addListDataListener(this);
+ } else if (eventID == EventID.TABLEMODEL &&
+ o instanceof TableModel) {
+ ((TableModel) o).removeTableModelListener(this);
+ ((TableModel) o).addTableModelListener(this);
+ } else if (
+ o instanceof TreeModel) {
+ ((TreeModel) o).removeTreeModelListener(this);
+ ((TreeModel) o).addTreeModelListener(this);
+ }
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.LISTSELECTION:
+ // Look for components which support ListSelectionListeners
+ // (e.g. JList)
+ //
+ try {
+ removeListSelectionMethod = c.getClass().getMethod(
+ "removeListSelectionListener", listSelectionListeners);
+ addListSelectionMethod = c.getClass().getMethod(
+ "addListSelectionListener", listSelectionListeners);
+ try {
+ removeListSelectionMethod.invoke(c, listSelectionArgs);
+ addListSelectionMethod.invoke(c, listSelectionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for selection models which support ListSelectionListeners
+ // (e.g. JTable's selection model)
+ //
+ try {
+ getSelectionModelMethod = c.getClass().getMethod(
+ "getSelectionModel", nullClass);
+ try {
+ Object o = getSelectionModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof ListSelectionModel) {
+ ((ListSelectionModel) o).removeListSelectionListener(this);
+ ((ListSelectionModel) o).addListSelectionListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.MENU:
+ try {
+ removeMenuMethod = c.getClass().getMethod(
+ "removeMenuListener", menuListeners);
+ addMenuMethod = c.getClass().getMethod(
+ "addMenuListener", menuListeners);
+ try {
+ removeMenuMethod.invoke(c, menuArgs);
+ addMenuMethod.invoke(c, menuArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.POPUPMENU:
+ // Look for components which support PopupMenuListeners
+ // (e.g. JPopupMenu)
+ //
+ try {
+ removePopupMenuMethod = c.getClass().getMethod(
+ "removePopupMenuListener", popupMenuListeners);
+ addPopupMenuMethod = c.getClass().getMethod(
+ "addPopupMenuListener", popupMenuListeners);
+ try {
+ removePopupMenuMethod.invoke(c, popupMenuArgs);
+ addPopupMenuMethod.invoke(c, popupMenuArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support getPopupMenu
+ // (e.g. JMenu)
+ //
+ try {
+ getPopupMenuMethod = c.getClass().getMethod(
+ "getPopupMenu", nullClass);
+ try {
+ Object o = getPopupMenuMethod.invoke(c, nullArgs);
+ if (o != null) {
+ removePopupMenuMethod = o.getClass().getMethod(
+ "removePopupMenuListener", popupMenuListeners);
+ addPopupMenuMethod = o.getClass().getMethod(
+ "addPopupMenuListener", popupMenuListeners);
+ removePopupMenuMethod.invoke(o, popupMenuArgs);
+ addPopupMenuMethod.invoke(o, popupMenuArgs);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.TREEEXPANSION:
+ try {
+ removeTreeExpansionMethod = c.getClass().getMethod(
+ "removeTreeExpansionListener", treeExpansionListeners);
+ addTreeExpansionMethod = c.getClass().getMethod(
+ "addTreeExpansionListener", treeExpansionListeners);
+ try {
+ removeTreeExpansionMethod.invoke(c, treeExpansionArgs);
+ addTreeExpansionMethod.invoke(c, treeExpansionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.TREESELECTION:
+ try {
+ removeTreeSelectionMethod = c.getClass().getMethod(
+ "removeTreeSelectionListener", treeSelectionListeners);
+ addTreeSelectionMethod = c.getClass().getMethod(
+ "addTreeSelectionListener", treeSelectionListeners);
+ try {
+ removeTreeSelectionMethod.invoke(c, treeSelectionArgs);
+ addTreeSelectionMethod.invoke(c, treeSelectionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.UNDOABLEEDIT:
+ // Look for components which support the getDocument method
+ // (e.g. JTextComponent)
+ //
+ try {
+ getDocumentMethod = c.getClass().getMethod(
+ "getDocument", nullClass);
+ try {
+ Object o = getDocumentMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof Document) {
+ ((Document) o).removeUndoableEditListener(this);
+ ((Document) o).addUndoableEditListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support UndoableEdit listeners
+ // (no current example)
+ //
+ try {
+ removeUndoableEditMethod = c.getClass().getMethod(
+ "removeUndoableEditListener", undoableEditListeners);
+ addUndoableEditMethod = c.getClass().getMethod(
+ "addUndoableEditListener", undoableEditListeners);
+ try {
+ removeUndoableEditMethod.invoke(c, undoableEditArgs);
+ addUndoableEditMethod.invoke(c, undoableEditArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.INTERNALFRAME:
+ // Look for components which support InternalFrame listeners
+ // (e.g. JInternalFrame)
+ //
+ try {
+ removeInternalFrameMethod = c.getClass().getMethod(
+ "removeInternalFrameListener", internalFrameListeners);
+ addInternalFrameMethod = c.getClass().getMethod(
+ "addInternalFrameListener", internalFrameListeners);
+ try {
+ removeInternalFrameMethod.invoke(c, internalFrameArgs);
+ addInternalFrameMethod.invoke(c, internalFrameArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.PROPERTYCHANGE:
+ // Look for components which support PropertyChange listeners
+ // (e.g. JComponent)
+ //
+ try {
+ removePropertyChangeMethod = c.getClass().getMethod(
+ "removePropertyChangeListener", propertyChangeListeners);
+ addPropertyChangeMethod = c.getClass().getMethod(
+ "addPropertyChangeListener", propertyChangeListeners);
+ try {
+ removePropertyChangeMethod.invoke(c, propertyChangeArgs);
+ addPropertyChangeMethod.invoke(c, propertyChangeArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support the getSelectionModel method
+ // (e.g. JTextComponent)
+ //
+ try {
+ getSelectionModelMethod = c.getClass().getMethod(
+ "getSelectionModel", nullClass);
+ try {
+ Object o = getSelectionModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof TreeSelectionModel) {
+ ((TreeSelectionModel) o).removePropertyChangeListener(this);
+ ((TreeSelectionModel) o).addPropertyChangeListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.VETOABLECHANGE:
+ if (c instanceof JComponent) {
+ ((JComponent) c).removeVetoableChangeListener(this);
+ ((JComponent) c).addVetoableChangeListener(this);
+ }
+ break;
+
+ // Don't bother recursing the children if this isn't going to
+ // accomplish anything.
+ //
+ default:
+ return;
+ }
+
+ if (c instanceof Container) {
+ int count = ((Container) c).getComponentCount();
+ for (int i = 0; i < count; i++) {
+ installListeners(((Container) c).getComponent(i), eventID);
+ }
+ }
+ }
+
+ /**
+ * Removes all listeners for the given component and all its children.
+ * @param c the component
+ */
+ protected void removeListeners(Component c) {
+
+ // conditionaly remove the Swing listeners
+ //
+ if (SwingEventMonitor.listenerList.getListenerCount(AncestorListener.class) > 0) {
+ removeListeners(c,EventID.ANCESTOR);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(CaretListener.class) > 0) {
+ removeListeners(c,EventID.CARET);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(CellEditorListener.class) > 0) {
+ removeListeners(c,EventID.CELLEDITOR);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ChangeListener.class) > 0) {
+ removeListeners(c,EventID.CHANGE);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TableColumnModelListener.class) > 0) {
+ removeListeners(c,EventID.COLUMNMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(DocumentListener.class) > 0) {
+ removeListeners(c,EventID.DOCUMENT);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ListDataListener.class) > 0) {
+ removeListeners(c,EventID.LISTDATA);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ListSelectionListener.class) > 0) {
+ removeListeners(c,EventID.LISTSELECTION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(MenuListener.class) > 0) {
+ removeListeners(c,EventID.MENU);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(PopupMenuListener.class) > 0) {
+ removeListeners(c,EventID.POPUPMENU);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TableModelListener.class) > 0) {
+ removeListeners(c,EventID.TABLEMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeExpansionListener.class) > 0) {
+ removeListeners(c,EventID.TREEEXPANSION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeModelListener.class) > 0) {
+ removeListeners(c,EventID.TREEMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeSelectionListener.class) > 0) {
+ removeListeners(c,EventID.TREESELECTION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(UndoableEditListener.class) > 0) {
+ removeListeners(c,EventID.UNDOABLEEDIT);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(InternalFrameListener.class) > 0) {
+ removeListeners(c,EventID.INTERNALFRAME);
+ }
+
+ // conditionaly remove the beans listeners
+ //
+ if (SwingEventMonitor.listenerList.getListenerCount(PropertyChangeListener.class) > 0) {
+ removeListeners(c,EventID.PROPERTYCHANGE);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(VetoableChangeListener.class) > 0) {
+ removeListeners(c,EventID.VETOABLECHANGE);
+ }
+
+ // Now remove the AWT listeners if needed.
+ //
+ super.removeListeners(c);
+ }
+
+ /**
+ * Removes all Swing listeners for the event ID from the component and
+ * all of its children.
+ * @param c the component to remove listeners from
+ */
+ protected void removeListeners(Component c, int eventID) {
+
+ // remove the appropriate listener hook into this component
+ //
+ switch (eventID) {
+
+ case EventID.CONTAINER:
+ //Never remove these because we're always interested in them
+ // for our own use.
+ break;
+
+ case EventID.ANCESTOR:
+ if (c instanceof JComponent) {
+ ((JComponent) c).removeAncestorListener(this);
+ }
+ break;
+
+ case EventID.CARET:
+ try {
+ removeCaretMethod = c.getClass().getMethod(
+ "removeCaretListener", caretListeners);
+ try {
+ removeCaretMethod.invoke(c, caretArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.CELLEDITOR:
+ // Look for components which support the getCellEditor method
+ // (e.g. JTable, JTree)
+ //
+ try {
+ getCellEditorMethod = c.getClass().getMethod(
+ "getCellEditorMethod", nullClass);
+ try {
+ Object o = getCellEditorMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof CellEditor) {
+ ((CellEditor) o).removeCellEditorListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support CellEditor listeners
+ // (no current example)
+ //
+ try {
+ removeCellEditorMethod = c.getClass().getMethod(
+ "removeCellEditorListener", cellEditorListeners);
+ try {
+ removeCellEditorMethod.invoke(c, cellEditorArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.CHANGE:
+ // [[[FIXME: Need to add support for Style, StyleContext -pk ]]]
+
+ // Look for components which support Change listeners
+ // (e.g. AbstractButton, Caret, JProgressBar, JSlider,
+ // JTabbedpane, JTextComponent, JViewport)
+ //
+ try {
+ removeChangeMethod = c.getClass().getMethod(
+ "removeChangeListener", changeListeners);
+ try {
+ removeChangeMethod.invoke(c, changeArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support the getModel method
+ // whose model supports Change listeners
+ // (e.g. BoundedRangeModel, ButtonModel, SingleSelectionModel)
+ //
+ try {
+ getModelMethod = c.getClass().getMethod(
+ "getModel", nullClass);
+ try {
+ Object o = getModelMethod.invoke(c, nullArgs);
+ if (o != null) {
+ removeChangeMethod = o.getClass().getMethod(
+ "removeChangeListener", changeListeners);
+ removeChangeMethod.invoke(o, changeArgs);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.COLUMNMODEL:
+ try {
+ getColumnModelMethod = c.getClass().getMethod(
+ "getTableColumnModel", nullClass);
+ try {
+ Object o = getColumnModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof TableColumnModel) {
+ ((TableColumnModel) o).removeColumnModelListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.DOCUMENT:
+ // Look for components which support the getDocument method
+ // (e.g. JTextComponent)
+ //
+ try {
+ getDocumentMethod = c.getClass().getMethod(
+ "getDocument", nullClass);
+ try {
+ Object o = getDocumentMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof Document) {
+ ((Document) o).removeDocumentListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support Document listeners
+ // (no current example)
+ //
+ try {
+ removeDocumentMethod = c.getClass().getMethod(
+ "removeDocumentListener", documentListeners);
+ try {
+ removeDocumentMethod.invoke(c, documentArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.LISTDATA:
+ case EventID.TABLEMODEL:
+ case EventID.TREEMODEL:
+ try {
+ getModelMethod = c.getClass().getMethod(
+ "getModel", nullClass);
+ try {
+ Object o = getModelMethod.invoke(c, nullArgs);
+ if (o != null) {
+ if (eventID == EventID.LISTDATA &&
+ o instanceof ListModel) {
+ ((ListModel) o).removeListDataListener(this);
+ } else if (eventID == EventID.TABLEMODEL &&
+ o instanceof TableModel) {
+ ((TableModel) o).removeTableModelListener(this);
+ } else if (
+ o instanceof TreeModel) {
+ ((TreeModel) o).removeTreeModelListener(this);
+ }
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.LISTSELECTION:
+ // Look for components which support ListSelectionListeners
+ // (e.g. JList)
+ //
+ try {
+ removeListSelectionMethod = c.getClass().getMethod(
+ "removeListSelectionListener", listSelectionListeners);
+ try {
+ removeListSelectionMethod.invoke(c, listSelectionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for selection models which support
+ // ListSelectionListeners (e.g. JTable's selection model)
+ //
+ try {
+ getSelectionModelMethod = c.getClass().getMethod(
+ "getSelectionModel", nullClass);
+ try {
+ Object o = getSelectionModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof ListSelectionModel) {
+ ((ListSelectionModel) o).removeListSelectionListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.MENU:
+ try {
+ removeMenuMethod = c.getClass().getMethod(
+ "removeMenuListener", menuListeners);
+ try {
+ removeMenuMethod.invoke(c, menuArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.POPUPMENU:
+ // Look for components which support PopupMenuListeners
+ // (e.g. JPopupMenu)
+ //
+ try {
+ removePopupMenuMethod = c.getClass().getMethod(
+ "removePopupMenuListener", popupMenuListeners);
+ try {
+ removePopupMenuMethod.invoke(c, popupMenuArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support getPopupMenu
+ // (e.g. JMenu)
+ //
+ try {
+ getPopupMenuMethod = c.getClass().getMethod(
+ "getPopupMenu", nullClass);
+ try {
+ Object o = getPopupMenuMethod.invoke(c, nullArgs);
+ if (o != null) {
+ removePopupMenuMethod = o.getClass().getMethod(
+ "removePopupMenuListener", popupMenuListeners);
+ removePopupMenuMethod.invoke(o, popupMenuArgs);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.TREEEXPANSION:
+ try {
+ removeTreeExpansionMethod = c.getClass().getMethod(
+ "removeTreeExpansionListener", treeExpansionListeners);
+ try {
+ removeTreeExpansionMethod.invoke(c, treeExpansionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.TREESELECTION:
+ try {
+ removeTreeSelectionMethod = c.getClass().getMethod(
+ "removeTreeSelectionListener", treeSelectionListeners);
+ try {
+ removeTreeSelectionMethod.invoke(c, treeSelectionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.UNDOABLEEDIT:
+ // Look for components which support the getDocument method
+ // (e.g. JTextComponent)
+ //
+ try {
+ getDocumentMethod = c.getClass().getMethod(
+ "getDocument", nullClass);
+ try {
+ Object o = getDocumentMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof Document) {
+ ((Document) o).removeUndoableEditListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support UndoableEdit listeners
+ // (no current example)
+ //
+ try {
+ removeUndoableEditMethod = c.getClass().getMethod(
+ "removeUndoableEditListener", undoableEditListeners);
+ try {
+ removeUndoableEditMethod.invoke(c, undoableEditArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.INTERNALFRAME:
+ try {
+ removeInternalFrameMethod = c.getClass().getMethod(
+ "removeInternalFrameListener", internalFrameListeners);
+ try {
+ removeInternalFrameMethod.invoke(c, internalFrameArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.PROPERTYCHANGE:
+ // Look for components which support PropertyChange listeners
+ // (e.g. JComponent)
+ //
+ try {
+ removePropertyChangeMethod = c.getClass().getMethod(
+ "removePropertyChangeListener", propertyChangeListeners);
+ try {
+ removePropertyChangeMethod.invoke(c, propertyChangeArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support the getSelectionModel
+ // method (e.g. JTextComponent)
+ //
+ try {
+ getSelectionModelMethod = c.getClass().getMethod(
+ "getSelectionModel", nullClass);
+ try {
+ Object o = getSelectionModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof TreeSelectionModel) {
+ ((TreeSelectionModel) o).removePropertyChangeListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.VETOABLECHANGE:
+ if (c instanceof JComponent) {
+ ((JComponent) c).removeVetoableChangeListener(this);
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ if (c instanceof Container) {
+ int count = ((Container) c).getComponentCount();
+ for (int i = 0; i < count; i++) {
+ removeListeners(((Container) c).getComponent(i), eventID);
+ }
+ }
+ }
+
+ /********************************************************************/
+ /* */
+ /* Listener Interface Methods */
+ /* */
+ /********************************************************************/
+
+ /* ContainerListener Methods ************************************/
+
+ public void componentAdded(ContainerEvent e) {
+ installListeners(e.getChild());
+ }
+ public void componentRemoved(ContainerEvent e) {
+ removeListeners(e.getChild());
+ }
+
+ /* AncestorListener Methods ******************************************/
+
+ public void ancestorAdded(AncestorEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==AncestorListener.class) {
+ ((AncestorListener)listeners[i+1]).ancestorAdded(e);
+ }
+ }
+ }
+
+ public void ancestorRemoved(AncestorEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==AncestorListener.class) {
+ ((AncestorListener)listeners[i+1]).ancestorRemoved(e);
+ }
+ }
+ }
+
+ public void ancestorMoved(AncestorEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==AncestorListener.class) {
+ ((AncestorListener)listeners[i+1]).ancestorMoved(e);
+ }
+ }
+ }
+
+ /* CaretListener Methods ******************************************/
+
+ public void caretUpdate(CaretEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==CaretListener.class) {
+ ((CaretListener)listeners[i+1]).caretUpdate(e);
+ }
+ }
+ }
+
+ /* CellEditorListener Methods *****************************************/
+
+ public void editingStopped(ChangeEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==CellEditorListener.class) {
+ ((CellEditorListener)listeners[i+1]).editingStopped(e);
+ }
+ }
+ }
+
+ public void editingCanceled(ChangeEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==CellEditorListener.class) {
+ ((CellEditorListener)listeners[i+1]).editingCanceled(e);
+ }
+ }
+ }
+
+ /* ChangeListener Methods *****************************************/
+
+ public void stateChanged(ChangeEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==ChangeListener.class) {
+ ((ChangeListener)listeners[i+1]).stateChanged(e);
+ }
+ }
+ }
+
+ /* TableColumnModelListener Methods *******************************/
+
+ public void columnAdded(TableColumnModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableColumnModelListener.class) {
+ ((TableColumnModelListener)listeners[i+1]).columnAdded(e);
+ }
+ }
+ }
+ public void columnMarginChanged(ChangeEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableColumnModelListener.class) {
+ ((TableColumnModelListener)listeners[i+1]).columnMarginChanged(e);
+ }
+ }
+ }
+ public void columnMoved(TableColumnModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableColumnModelListener.class) {
+ ((TableColumnModelListener)listeners[i+1]).columnMoved(e);
+ }
+ }
+ }
+ public void columnRemoved(TableColumnModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableColumnModelListener.class) {
+ ((TableColumnModelListener)listeners[i+1]).columnRemoved(e);
+ }
+ }
+ }
+ public void columnSelectionChanged(ListSelectionEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableColumnModelListener.class) {
+ ((TableColumnModelListener)listeners[i+1]).columnSelectionChanged(e);
+ }
+ }
+ }
+
+ /* DocumentListener Methods **************************************/
+
+ public void changedUpdate(DocumentEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==DocumentListener.class) {
+ ((DocumentListener)listeners[i+1]).changedUpdate(e);
+ }
+ }
+ }
+ public void insertUpdate(DocumentEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==DocumentListener.class) {
+ ((DocumentListener)listeners[i+1]).insertUpdate(e);
+ }
+ }
+ }
+ public void removeUpdate(DocumentEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==DocumentListener.class) {
+ ((DocumentListener)listeners[i+1]).removeUpdate(e);
+ }
+ }
+ }
+
+ /* ListDataListener Methods *****************************************/
+
+ public void contentsChanged(ListDataEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==ListDataListener.class) {
+ ((ListDataListener)listeners[i+1]).contentsChanged(e);
+ }
+ }
+ }
+ public void intervalAdded(ListDataEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==ListDataListener.class) {
+ ((ListDataListener)listeners[i+1]).intervalAdded(e);
+ }
+ }
+ }
+ public void intervalRemoved(ListDataEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==ListDataListener.class) {
+ ((ListDataListener)listeners[i+1]).intervalRemoved(e);
+ }
+ }
+ }
+
+ /* ListSelectionListener Methods ***********************************/
+
+ public void valueChanged(ListSelectionEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==ListSelectionListener.class) {
+ ((ListSelectionListener)listeners[i+1]).valueChanged(e);
+ }
+ }
+ }
+
+ /* MenuListener Methods *****************************************/
+
+ public void menuCanceled(MenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==MenuListener.class) {
+ ((MenuListener)listeners[i+1]).menuCanceled(e);
+ }
+ }
+ }
+ public void menuDeselected(MenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==MenuListener.class) {
+ ((MenuListener)listeners[i+1]).menuDeselected(e);
+ }
+ }
+ }
+ public void menuSelected(MenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==MenuListener.class) {
+ ((MenuListener)listeners[i+1]).menuSelected(e);
+ }
+ }
+ }
+
+ /* PopupMenuListener Methods **************************************/
+
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PopupMenuListener.class) {
+ ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeVisible(e);
+ }
+ }
+ }
+
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PopupMenuListener.class) {
+ ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeInvisible(e);
+ }
+ }
+ }
+
+ public void popupMenuCanceled(PopupMenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PopupMenuListener.class) {
+ ((PopupMenuListener)listeners[i+1]).popupMenuCanceled(e);
+ }
+ }
+ }
+
+ /* TableModelListener Methods **************************************/
+
+ public void tableChanged(TableModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableModelListener.class) {
+ ((TableModelListener)listeners[i+1]).tableChanged(e);
+ }
+ }
+ }
+
+ /* TreeExpansionListener Methods **********************************/
+
+ public void treeCollapsed(TreeExpansionEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeExpansionListener.class) {
+ ((TreeExpansionListener)listeners[i+1]).treeCollapsed(e);
+ }
+ }
+ }
+ public void treeExpanded(TreeExpansionEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeExpansionListener.class) {
+ ((TreeExpansionListener)listeners[i+1]).treeExpanded(e);
+ }
+ }
+ }
+
+ /* TreeModelListener Methods **********************************/
+
+ public void treeNodesChanged(TreeModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeModelListener.class) {
+ ((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
+ }
+ }
+ }
+ public void treeNodesInserted(TreeModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeModelListener.class) {
+ ((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
+ }
+ }
+ }
+ public void treeNodesRemoved(TreeModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeModelListener.class) {
+ ((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
+ }
+ }
+ }
+ public void treeStructureChanged(TreeModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeModelListener.class) {
+ ((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
+ }
+ }
+ }
+
+ /* TreeSelectionListener Methods ***********************************/
+
+ public void valueChanged(TreeSelectionEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeSelectionListener.class) {
+ ((TreeSelectionListener)listeners[i+1]).valueChanged(e);
+ }
+ }
+ }
+
+ /* UndoableEditListener Methods **************************************/
+
+ public void undoableEditHappened(UndoableEditEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==UndoableEditListener.class) {
+ ((UndoableEditListener)listeners[i+1]).undoableEditHappened(e);
+ }
+ }
+ }
+
+ /* InternalFrame Methods **********************************/
+
+ public void internalFrameOpened(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameOpened(e);
+ }
+ }
+ }
+
+ public void internalFrameActivated(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameActivated(e);
+ }
+ }
+ }
+
+ public void internalFrameDeactivated(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameDeactivated(e);
+ }
+ }
+ }
+
+ public void internalFrameIconified(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameIconified(e);
+ }
+ }
+ }
+
+ public void internalFrameDeiconified(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameDeiconified(e);
+ }
+ }
+ }
+
+ public void internalFrameClosing(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameClosing(e);
+ }
+ }
+ }
+
+ public void internalFrameClosed(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameClosed(e);
+ }
+ }
+ }
+
+ /* PropertyChangeListener Methods **********************************/
+
+ public void propertyChange(PropertyChangeEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PropertyChangeListener.class) {
+ ((PropertyChangeListener)listeners[i+1]).propertyChange(e);
+ }
+ }
+ // Re-add the monitor as a DocumentChangeListener if
+ // the document changed in the text component.
+ if (e.getSource() instanceof JTextComponent) {
+ Document c = ((JTextComponent)e.getSource()).getDocument();
+ if (c == null) {
+ return;
+ }
+ try {
+ removeDocumentMethod = c.getClass().getMethod(
+ "removeDocumentListener", documentListeners);
+ addDocumentMethod = c.getClass().getMethod(
+ "addDocumentListener", documentListeners);
+ try {
+ removeDocumentMethod.invoke(c, documentArgs);
+ addDocumentMethod.invoke(c, documentArgs);
+ } catch (java.lang.reflect.InvocationTargetException e2) {
+ System.out.println("Exception: " + e2.toString());
+ } catch (IllegalAccessException e2) {
+ System.out.println("Exception: " + e2.toString());
+ }
+ } catch (NoSuchMethodException e2) {
+ // System.out.println("Exception: " + e2.toString());
+ } catch (SecurityException e2) {
+ System.out.println("Exception: " + e2.toString());
+ }
+ }
+
+ }
+
+ /* VetoableChangeListener Methods **********************************/
+
+ public void vetoableChange(PropertyChangeEvent e)
+ throws PropertyVetoException {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==VetoableChangeListener.class) {
+ ((VetoableChangeListener)listeners[i+1]).vetoableChange(e);
+ }
+ }
+ }
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowListener.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowListener.java
new file mode 100644
index 00000000000..94d03307a7a
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowListener.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.awt.*;
+import java.util.*;
+import javax.accessibility.*;
+
+/**
+ * The {@code TopLevelWindowListener} interface is used by the {@link EventQueueMonitor}
+ * class to notify an interested party when a top level window is created
+ * or destroyed in the Java Virtual Machine. Classes wishing to express
+ * an interest in top level window events should implement this interface
+ * and register themselves with the {@code EventQueueMonitor} by calling the
+ * {@link EventQueueMonitor#addTopLevelWindowListener EventQueueMonitor.addTopLevelWindowListener}
+ * class method.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ * @see EventQueueMonitor#removeTopLevelWindowListener
+ *
+ */
+@jdk.Exported
+public interface TopLevelWindowListener extends EventListener {
+
+ /**
+ * Invoked when a new top level window has been created.
+ *
+ * @param w the Window that was created
+ */
+ public void topLevelWindowCreated(Window w);
+
+ /**
+ * Invoked when a top level window has been destroyed.
+ *
+ * @param w the Window that was destroyed
+ */
+ public void topLevelWindowDestroyed(Window w);
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowMulticaster.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowMulticaster.java
new file mode 100644
index 00000000000..31ca38020ea
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowMulticaster.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.awt.*;
+import java.util.EventListener;
+import javax.accessibility.*;
+
+
+/**
+ * The TopLevelWindowMulticaster class is used to maintain a list of
+ * TopLevelWindowListener classes. It is intended to be used primarily
+ * for internal support in the EventQueueMonitor class, and is not intended
+ * to be used by classes outside the Java Accessibility Utility package.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ * @see EventQueueMonitor#removeTopLevelWindowListener
+ *
+ */
+class TopLevelWindowMulticaster
+ extends AWTEventMulticaster implements TopLevelWindowListener
+{
+ protected TopLevelWindowMulticaster(EventListener a, EventListener b) {
+ super(a, b);
+ }
+
+ public void topLevelWindowCreated(Window w) {
+ ((TopLevelWindowListener)a).topLevelWindowCreated(w);
+ ((TopLevelWindowListener)b).topLevelWindowCreated(w);
+ }
+
+ public void topLevelWindowDestroyed(Window w) {
+ ((TopLevelWindowListener)a).topLevelWindowDestroyed(w);
+ ((TopLevelWindowListener)b).topLevelWindowDestroyed(w);
+ }
+
+ public static TopLevelWindowListener add(TopLevelWindowListener a, TopLevelWindowListener b) {
+ return (TopLevelWindowListener)addInternal(a, b);
+ }
+
+ public static TopLevelWindowListener remove(TopLevelWindowListener l, TopLevelWindowListener oldl) {
+ return (TopLevelWindowListener)removeInternal(l, oldl);
+ }
+
+ protected static EventListener addInternal(EventListener a, EventListener b) {
+ if (a == null) return b;
+ if (b == null) return a;
+ return new TopLevelWindowMulticaster(a, b);
+ }
+
+ protected static EventListener removeInternal(EventListener l, EventListener oldl) {
+ if (l == oldl || l == null) {
+ return null;
+ } else if (l instanceof TopLevelWindowMulticaster) {
+ return ((TopLevelWindowMulticaster)l).remove(oldl);
+ } else {
+ return l; // it's not here
+ }
+ }
+
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java
new file mode 100644
index 00000000000..2112bd2ea3b
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java
@@ -0,0 +1,744 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package com.sun.java.accessibility.util;
+
+import java.lang.*;
+import java.beans.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+// Do not import Swing classes. This module is intended to work
+// with both Swing and AWT.
+// import javax.swing.*;
+import javax.accessibility.*;
+
+/**
+ *
The {@code Translator} class provides a translation to interface
+ * {@link javax.accessibility.Accessible Accessible}
+ * for objects that do not implement interface {@code Accessible}. Assistive
+ * technologies can use the {@link #getAccessible getAccessible} class method of
+ * {@code Translator} to obtain an object that implements interface {@code Accessible}.
+ * If the object passed in already implements interface {@code Accessible},
+ * {@code getAccessible} merely returns the object.
+ *
+ *
An example of how an assistive technology might use the {@code Translator}
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
Note: This implementation is missing many things and is not a recommended way
+ * to implement accessibility features for a toolkit. Instead of relying upon this
+ * code, a toolkit's components should implement interface {@code Accessible} directly.
+ */
+@jdk.Exported
+public class Translator extends AccessibleContext
+ implements Accessible, AccessibleComponent {
+
+ /** The source object needing translating. */
+ protected Object source;
+
+ /**
+ * Find a translator for this class. If one doesn't exist for this
+ * class explicitly, try its superclass and so on.
+ *
+ * @param c a Class
+ * @return the {@code Translator} Class for the Class passed in
+ */
+ protected static Class> getTranslatorClass(Class> c) {
+ Class> t = null;
+ if (c == null) {
+ return null;
+ }
+ try {
+ t = Class.forName("com.sun.java.accessibility.util."
+ + c.getName()
+ + "Translator");
+ return t;
+ } catch (Exception e) {
+ return getTranslatorClass(c.getSuperclass());
+ }
+ }
+
+ /**
+ * Obtain an object that implements interface {@code Accessible}. If the object
+ * passed in already implements interface {@code Accessible}, {@code getAccessible}
+ * merely returns the object.
+ *
+ * @param o an Object; if a null is passed in a null is returned
+ * @return an {@code Object}, possibly the {@code Object} passed in, that
+ * implements the {@code Accessible} interface for the {@code Object}
+ * which was passed in
+ */
+ public static Accessible getAccessible(Object o) {
+ Accessible a = null;
+
+ if (o == null) {
+ return null;
+ }
+ if (o instanceof Accessible) {
+ a = (Accessible)o;
+ } else {
+ Class> translatorClass = getTranslatorClass(o.getClass());
+ if (translatorClass != null) {
+ try {
+ Translator t = (Translator)translatorClass.newInstance();
+ t.setSource(o);
+ a = t;
+ } catch (Exception e) {
+ }
+ }
+ }
+ if (a == null) {
+ a = new Translator(o);
+ }
+ return a;
+ }
+
+ /**
+ * Create a new {@code Translator}. You must call the {@link #setSource setSource}
+ * method to set the object to be translated after calling this constructor.
+ */
+ public Translator() {
+ }
+
+ /**
+ * Create a new {@code Translator} with the source object o.
+ *
+ * @param o the Component that does not implement interface
+ * {@link javax.accessibility.Accessible Accessible}
+ */
+ public Translator(Object o) {
+ source = o;
+ }
+
+ /**
+ * Get the source {@code Object} of the {@code Translator}.
+ *
+ * @return the source {@code Object} of the {@code Translator}
+ */
+ public Object getSource() {
+ return source;
+ }
+
+ /**
+ * Set the source object of the {@code Translator}.
+ *
+ * @param o the Component that does not implement interface Accessible
+ */
+ public void setSource(Object o) {
+ source = o;
+ }
+
+ /**
+ * Returns true if this object is the same as the one passed in.
+ *
+ * @param o the {@code Object} to check against
+ * @return true if this is the same object
+ */
+ public boolean equals(Object o) {
+ if (o instanceof Translator) {
+ return java.util.Objects.equals(source, o);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Return hashcode.
+ *
+ * @return hashcode
+ */
+ public int hashCode() {
+ return java.util.Objects.hashCode(source);
+ }
+
+
+// Accessible methods
+
+ /**
+ * Returns this object.
+ */
+ public AccessibleContext getAccessibleContext() {
+ return this;
+ }
+
+// AccessibleContext methods
+
+ /**
+ * Get the accessible name of this object.
+ *
+ * @return the localized name of the object; can be null if this object
+ * does not have a name
+ */
+ public String getAccessibleName() {
+ if (source instanceof MenuItem) {
+ return ((MenuItem) source).getLabel();
+ } else if (source instanceof Component) {
+ return ((Component) source).getName();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the name of this object.
+ */
+ public void setAccessibleName(String s) {
+ if (source instanceof MenuItem) {
+ ((MenuItem) source).setLabel(s);
+ } else if (source instanceof Component) {
+ ((Component) source).setName(s);
+ }
+ }
+
+ /**
+ * Get the accessible description of this object.
+ *
+ * @return the description of the object; can be null if this object does
+ * not have a description
+ */
+ public String getAccessibleDescription() {
+ return null;
+ }
+
+ /**
+ * Set the accessible description of this object.
+ *
+ * @param s the new localized description of the object
+ */
+ public void setAccessibleDescription(String s) {
+ }
+
+ /**
+ * Get the role of this object.
+ *
+ * @return an instance of AccessibleRole describing the role of the object
+ */
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.UNKNOWN;
+ }
+
+
+ /**
+ * Get the state of this object, given an already populated state.
+ * This method is intended for use by subclasses so they don't have
+ * to check for everything.
+ *
+ * @return an instance of {@code AccessibleStateSet}
+ * containing the current state of the object
+ */
+ public AccessibleStateSet getAccessibleStateSet() {
+ AccessibleStateSet states = new AccessibleStateSet();
+ if (source instanceof Component) {
+ Component c = (Component) source;
+ for (Container p = c.getParent(); p != null; p = p.getParent()) {
+ if (p instanceof Window) {
+ if (((Window)p).getFocusOwner() == c) {
+ states.add(AccessibleState.FOCUSED);
+ }
+ }
+ }
+ }
+ if (isEnabled()) {
+ states.add(AccessibleState.ENABLED);
+ }
+ if (isFocusTraversable()) {
+ states.add(AccessibleState.FOCUSABLE);
+ }
+ if (source instanceof MenuItem) {
+ states.add(AccessibleState.FOCUSABLE);
+ }
+ return states;
+ }
+
+ /**
+ * Get the accessible parent of this object.
+ *
+ * @return the accessible parent of this object; can be null if this
+ * object does not have an accessible parent
+ */
+ public Accessible getAccessibleParent() {
+ if (accessibleParent != null) {
+ return accessibleParent;
+ } else if (source instanceof Component) {
+ return getAccessible(((Component) source).getParent());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the index of this object in its accessible parent.
+ *
+ * @return -1 of this object does not have an accessible parent; otherwise,
+ * the index of the child in its accessible parent
+ */
+ public int getAccessibleIndexInParent() {
+ if (source instanceof Component) {
+ Container parent = ((Component) source).getParent();
+ if (parent != null) {
+ Component ca[] = parent.getComponents();
+ for (int i = 0; i < ca.length; i++) {
+ if (source.equals(ca[i])) {
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the number of accessible children in the object.
+ *
+ * @return the number of accessible children in the object
+ */
+ public int getAccessibleChildrenCount() {
+ if (source instanceof Container) {
+ Component[] children = ((Container) source).getComponents();
+ int count = 0;
+ for (int i = 0; i < children.length; i++) {
+ Accessible a = getAccessible(children[i]);
+ if (a != null) {
+ count++;
+ }
+ }
+ return count;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Return the nth accessible child of the object.
+ *
+ * @param i zero-based index of child
+ * @return the nth accessible child of the object
+ */
+ public Accessible getAccessibleChild(int i) {
+ if (source instanceof Container) {
+ Component[] children = ((Container) source).getComponents();
+ int count = 0;
+
+ for (int j = 0; j < children.length; j++) {
+ Accessible a = getAccessible(children[j]);
+ if (a != null) {
+ if (count == i) {
+ AccessibleContext ac = a.getAccessibleContext();
+ if (ac != null) {
+ ac.setAccessibleParent(this);
+ }
+ return a;
+ } else {
+ count++;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the {@code Locale} of the component. If the component does not have a
+ * locale, the locale of its parent is returned.
+ *
+ * @return the {@code Locale} of the object
+ */
+ public Locale getLocale() throws IllegalComponentStateException {
+ if (source instanceof Component) {
+ return ((Component) source).getLocale();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Add a {@code PropertyChangeListener} to the listener list. The listener
+ * is registered for all properties.
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l) {
+ }
+
+ /**
+ * Remove the {@code PropertyChangeListener} from the listener list.
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l) {
+ }
+
+// AccessibleComponent methods
+
+ /**
+ * Get the background {@code Color} of this object.
+ *
+ * @return if supported, the background {@code Color} of the object;
+ * otherwise, null
+ *
+ */
+ public Color getBackground() {
+ if (source instanceof Component) { // MenuComponent doesn't do background
+ return ((Component) source).getBackground();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the background {@code Color} of this object.
+ *
+ * @param c the new {@code Color} for the background
+ */
+ public void setBackground(Color c) {
+ if (source instanceof Component) { // MenuComponent doesn't do background
+ ((Component) source).setBackground(c);
+ }
+ }
+
+ /**
+ * Get the foreground {@code Color} of this object.
+ *
+ * @return if supported, the foreground {@code Color} of the object; otherwise, null
+ */
+ public Color getForeground() {
+ if (source instanceof Component) { // MenuComponent doesn't do foreground
+ return ((Component) source).getForeground();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the foreground {@code Color} of this object.
+ *
+ * @param c the new {@code Color} for the foreground
+ */
+ public void setForeground(Color c) {
+ if (source instanceof Component) { // MenuComponent doesn't do foreground
+ ((Component) source).setForeground(c);
+ }
+ }
+
+ /**
+ * Get the {@code Cursor} of this object.
+ *
+ * @return if supported, the Cursor of the object; otherwise, null
+ */
+ public Cursor getCursor() {
+ if (source instanceof Component) { // MenuComponent doesn't do cursor
+ return ((Component) source).getCursor();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the {@code Cursor} of this object.
+ * @param c the new {@code Cursor} for the object
+ */
+ public void setCursor(Cursor c) {
+ if (source instanceof Component) { // MenuComponent doesn't do cursor
+ ((Component) source).setCursor(c);
+ }
+ }
+
+ /**
+ * Get the {@code Font} of this object.
+ *
+ * @return if supported, the {@code Font} for the object; otherwise, null
+ */
+ public Font getFont() {
+ if (source instanceof Component) {
+ return ((Component) source).getFont();
+ } else if (source instanceof MenuComponent) {
+ return ((MenuComponent) source).getFont();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the {@code Font} of this object.
+ *
+ * @param f the new {@code Font} for the object
+ */
+ public void setFont(Font f) {
+ if (source instanceof Component) {
+ ((Component) source).setFont(f);
+ } else if (source instanceof MenuComponent) {
+ ((MenuComponent) source).setFont(f);
+ }
+ }
+
+ /**
+ * Get the {@code FontMetrics} of this object.
+ *
+ * @param f the {@code Font}
+ * @return if supported, the {@code FontMetrics} the object; otherwise, null
+ * @see #getFont
+ */
+ public FontMetrics getFontMetrics(Font f) {
+ if (source instanceof Component) {
+ return ((Component) source).getFontMetrics(f);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Determine if the object is enabled.
+ *
+ * @return true if object is enabled; otherwise, false
+ */
+ public boolean isEnabled() {
+ if (source instanceof Component) {
+ return ((Component) source).isEnabled();
+ } else if (source instanceof MenuItem) {
+ return ((MenuItem) source).isEnabled();
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Set the enabled state of the object.
+ *
+ * @param b if true, enables this object; otherwise, disables it
+ */
+ public void setEnabled(boolean b) {
+ if (source instanceof Component) {
+ ((Component) source).setEnabled(b);
+ } else if (source instanceof MenuItem) {
+ ((MenuItem) source).setEnabled(b);
+ }
+ }
+
+ /**
+ * Determine if the object is visible.
+ *
+ * @return true if object is visible; otherwise, false
+ */
+ public boolean isVisible() {
+ if (source instanceof Component) {
+ return ((Component) source).isVisible();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Set the visible state of the object.
+ *
+ * @param b if true, shows this object; otherwise, hides it
+ */
+ public void setVisible(boolean b) {
+ if (source instanceof Component) {
+ ((Component) source).setVisible(b);
+ }
+ }
+
+ /**
+ * Determine if the object is showing. This is determined by checking
+ * the visibility of the object and ancestors of the object.
+ *
+ * @return true if object is showing; otherwise, false
+ */
+ public boolean isShowing() {
+ if (source instanceof Component) {
+ return ((Component) source).isShowing();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Checks whether the specified {@code Point} is within this
+ * object's bounds, where the {@code Point} is relative to the coordinate
+ * system of the object.
+ *
+ * @param p the {@code Point} relative to the coordinate system of the object
+ * @return true if object contains {@code Point}; otherwise false
+ */
+ public boolean contains(Point p) {
+ if (source instanceof Component) {
+ return ((Component) source).contains(p);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the location of the object on the screen.
+ *
+ * @return location of object on screen; can be null if this object
+ * is not on the screen
+ */
+ public Point getLocationOnScreen() {
+ if (source instanceof Component) {
+ return ((Component) source).getLocationOnScreen();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the location of the object relative to parent.
+ *
+ * @return location of object relative to parent; can be null if
+ * this object or its parent are not on the screen
+ */
+ public Point getLocation() {
+ if (source instanceof Component) {
+ return ((Component) source).getLocation();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the location of the object relative to parent.
+ */
+ public void setLocation(Point p) {
+ if (source instanceof Component) {
+ ((Component) source).setLocation(p);
+ }
+ }
+
+ /**
+ * Returns the current bounds of this object.
+ *
+ * @return current bounds of object; can be null if this object
+ * is not on the screen
+ */
+ public Rectangle getBounds() {
+ if (source instanceof Component) {
+ return ((Component) source).getBounds();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the current bounds of this object.
+ */
+ public void setBounds(Rectangle r) {
+ if (source instanceof Component) {
+ ((Component) source).setBounds(r);
+ }
+ }
+
+ /**
+ * Returns the current size of this object.
+ *
+ * @return current size of object; can be null if this object is
+ * not on the screen
+ */
+ public Dimension getSize() {
+ if (source instanceof Component) {
+ return ((Component) source).getSize();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the current size of this object.
+ */
+ public void setSize(Dimension d) {
+ if (source instanceof Component) {
+ ((Component) source).setSize(d);
+ }
+ }
+
+ /**
+ * Returns the accessible child contained at the local coordinate
+ * Point, if one exists.
+ *
+ * @return the Accessible at the specified location, if it exists
+ */
+ public Accessible getAccessibleAt(Point p) {
+ if (source instanceof Component) {
+ Component c = ((Component) source).getComponentAt(p);
+ if (c != null) {
+ return (getAccessible(c));
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns whether this object can accept focus or not.
+ *
+ * @return true if object can accept focus; otherwise false
+ */
+ @SuppressWarnings("deprecation")
+ public boolean isFocusTraversable() {
+ if (source instanceof Component) {
+ return ((Component) source).isFocusTraversable();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Requests focus for this object.
+ */
+ public void requestFocus() {
+ if (source instanceof Component) {
+ ((Component) source).requestFocus();
+ }
+ }
+
+ /**
+ * Adds the specified {@code FocusListener} to receive focus events from
+ * this component.
+ *
+ * @param l the focus listener
+ */
+ public synchronized void addFocusListener(FocusListener l) {
+ if (source instanceof Component) {
+ ((Component) source).addFocusListener(l);
+ }
+ }
+
+ /**
+ * Removes the specified focus listener so it no longer receives focus
+ * events from this component.
+ *
+ * @param l the focus listener; this method performs no function, nor does it
+ * throw an exception if the listener specified was not previously added
+ * to this component; if listener is null, no exception is thrown and no
+ * action is performed.
+ */
+ public synchronized void removeFocusListener(FocusListener l) {
+ if (source instanceof Component) {
+ ((Component) source).removeFocusListener(l);
+ }
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ButtonTranslator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ButtonTranslator.java
new file mode 100644
index 00000000000..d775e6e475e
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ButtonTranslator.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util.java.awt;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+
+/**
+ *
The Translator class provides a translation to interface Accessible
+ * for objects that do not implement interface Accessible. Assistive
+ * technologies can use the 'getAccessible' class method of Translator to
+ * obtain an object that implements interface Accessible. If the object
+ * passed in already implements interface Accessible, getAccessible merely
+ * returns the object.
+ *
+ *
An example of how an assistive technology might use the Translator
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
This class extends the Translator class to provide specific support
+ * for the Button class. Translator.getAccessible() will automatically
+ * load this class when an assistive technology asks for an accessible
+ * translator for Button.
+ *
+ */
+public class ButtonTranslator extends Translator {
+
+ /**
+ * Get the name of this object.
+ * @return the name of the object -- can be null if this object does
+ * not have a name
+ */
+ public String getAccessibleName() {
+ return ((Button) source).getLabel();
+ }
+
+ /**
+ * Set the name of this object.
+ */
+ public void setAccessibleName(String s) {
+ ((Button) source).setLabel(s);
+ }
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.PUSH_BUTTON;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/CheckboxTranslator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/CheckboxTranslator.java
new file mode 100644
index 00000000000..2f131e2c733
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/CheckboxTranslator.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util.java.awt;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+
+/**
+ *
The Translator class provides a translation to interface Accessible
+ * for objects that do not implement interface Accessible. Assistive
+ * technologies can use the 'getAccessible' class method of Translator to
+ * obtain an object that implements interface Accessible. If the object
+ * passed in already implements interface Accessible, getAccessible merely
+ * returns the object.
+ *
+ *
An example of how an assistive technology might use the Translator
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
This class extends the Translator class to provide specific support
+ * for the Checkbox class. Translator.getAccessible() will automatically
+ * load this class when an assistive technology asks for an accessible
+ * translator for Checkbox.
+ *
+ */
+public class CheckboxTranslator extends Translator {
+
+ /**
+ * Get the state of this object.
+ * @return an instance of AccessibleState containing the current state of the object
+ * @see AccessibleState
+ */
+ public AccessibleStateSet getAccessibleStateSet() {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (((Checkbox) source).getState()) {
+ states.add(AccessibleState.CHECKED);
+ }
+ return states;
+ }
+
+ /**
+ * Get the name of this object.
+ * @return the name of the object -- can be null if this object does
+ * not have a name
+ */
+ public String getAccessibleName() {
+ return ((Checkbox) source).getLabel();
+ }
+
+ /**
+ * Set the name of this object.
+ */
+ public void setAccessibleName(String s) {
+ ((Checkbox) source).setLabel(s);
+ }
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.CHECK_BOX;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/LabelTranslator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/LabelTranslator.java
new file mode 100644
index 00000000000..33a27897c78
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/LabelTranslator.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util.java.awt;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+
+/**
+ *
The Translator class provides a translation to interface Accessible
+ * for objects that do not implement interface Accessible. Assistive
+ * technologies can use the 'getAccessible' class method of Translator to
+ * obtain an object that implements interface Accessible. If the object
+ * passed in already implements interface Accessible, getAccessible merely
+ * returns the object.
+ *
+ *
An example of how an assistive technology might use the Translator
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
This class extends the Translator class to provide specific support
+ * for the Label class. Translator.getAccessible() will automatically
+ * load this class when an assistive technology asks for an accessible
+ * translator for Label.
+ *
+ */
+public class LabelTranslator extends Translator {
+
+ public String getAccessibleName() {
+ return ((Label) source).getText();
+ }
+
+ /**
+ * Set the name of this object.
+ */
+ public void setAccessibleName(String s) {
+ ((Label) source).setText(s);
+ }
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.LABEL;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ListTranslator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ListTranslator.java
new file mode 100644
index 00000000000..de1c469928e
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ListTranslator.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util.java.awt;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+
+/**
+ *
The Translator class provides a translation to interface Accessible
+ * for objects that do not implement interface Accessible. Assistive
+ * technologies can use the 'getAccessible' class method of Translator to
+ * obtain an object that implements interface Accessible. If the object
+ * passed in already implements interface Accessible, getAccessible merely
+ * returns the object.
+ *
+ *
An example of how an assistive technology might use the Translator
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
This class extends the Translator class to provide specific support
+ * for the List class. Translator.getAccessible() will automatically
+ * load this class when an assistive technology asks for an accessible
+ * translator for List.
+ *
+ */
+public class ListTranslator extends Translator {
+
+ /**
+ * Get the state of this object.
+ * @return an instance of AccessibleState containing the current state of the object
+ * @see AccessibleState
+ */
+ public AccessibleStateSet getAccessibleStateSet() {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (((java.awt.List) source).isMultipleMode()) {
+ states.add(AccessibleState.MULTISELECTABLE);
+ }
+ if (((java.awt.List) source).getSelectedItems().length > 0) {
+ states.add(AccessibleState.SELECTED);
+ }
+ return states;
+ }
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.LIST;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/TextComponentTranslator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/TextComponentTranslator.java
new file mode 100644
index 00000000000..3ac3fabb708
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/TextComponentTranslator.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util.java.awt;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+
+/**
+ *
The Translator class provides a translation to interface Accessible
+ * for objects that do not implement interface Accessible. Assistive
+ * technologies can use the 'getAccessible' class method of Translator to
+ * obtain an object that implements interface Accessible. If the object
+ * passed in already implements interface Accessible, getAccessible merely
+ * returns the object.
+ *
+ *
An example of how an assistive technology might use the Translator
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
This class extends the Translator class to provide specific support
+ * for the TextComponent class. Translator.getAccessible() will automatically
+ * load this class when an assistive technology asks for an accessible
+ * translator for TextComponent.
+ *
+ */
+public class TextComponentTranslator extends Translator {
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.TEXT;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/package-info.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/package-info.java
new file mode 100644
index 00000000000..f3b0a62dd36
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/package-info.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Provides a collection of interfaces and classes that compose the Java Accessibility
+ * Utilities. The classes are used by Assistive Technologies, such as the screen
+ * readers which are used by those who are blind, and help provide access to GUI
+ * toolkits that implement the Java Accessibility API. An overview of the important
+ * classes follows.
+ *
+ *
The class {@code AccessibilityEventMonitor} implements a PropertyChange
+ * listener on every UI object that implements interface {@code Accessible} in the Java
+ * Virtual Machine.
+ *
+ *
The class {@code AWTEventMonitor} implements a suite of listeners that are
+ * conditionally installed on every AWT component instance in the Java Virtual Machine.
+ *
+ *
The class {@code EventQueueMonitor} provides key core functionality for
+ * Assistive Technologies (and other system-level technologies that need some of
+ * the same things that Assistive Technology needs).
+ *
+ *
The class {@code GUIInitializedMulticaster} is used to maintain a list of
+ * {@code GUIInitializedListener} classes which are used by the {@code EventQueueMonitor}
+ * class to notify an interested party when the GUI subsystem has been initialized.
+ * Note that this class is intended to be used primarily for internal support in
+ * the {@code EventQueueMonitor} class, and is not intended to be used by classes
+ * outside the Java Accessibility Utility package.
+ *
+ *
The class {@code SwingEventMonitor} extends {@code AWTEventMonitor} by adding
+ * a suite of listeners conditionally installed on every Swing component instance
+ * in the Java Virtual Machine.
+ *
+ *
The class {@code TopLevelWindowMulticaster} is used to maintain a list of
+ * {@code TopLevelWindowListener} classes which are used by the {@code EventQueueMonitor}
+ * class to notify an interested party when a top level window is created or destroyed
+ * in the Java Virtual Machine Note that this class is intended to be used primarily
+ * for internal support in the {@code EventQueueMonitor} class, and is not intended
+ * to be used by classes outside the Java Accessibility Utility package.
+ *
+ *
The class {@code Translator} provides a translation to interface {@code Accessible}
+ * for objects that do not implement interface {@code Accessible}.
+ *
+ * @since JDK1.7
+ */
+package com.sun.java.accessibility.util;
diff --git a/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/AccessBridge.java b/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/AccessBridge.java
new file mode 100644
index 00000000000..5c47d382324
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/AccessBridge.java
@@ -0,0 +1,7170 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.lang.*;
+import java.lang.reflect.*;
+
+import java.beans.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import javax.swing.tree.*;
+import javax.swing.table.*;
+import javax.swing.plaf.TreeUI;
+
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+import sun.awt.AWTAccessor;
+import sun.awt.AppContext;
+import sun.awt.SunToolkit;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+
+/*
+ * Note: This class has to be public. It's loaded from the VM like this:
+ * Class.forName(atName).newInstance();
+ */
+@jdk.Exported(false)
+final public class AccessBridge {
+
+ private static AccessBridge theAccessBridge;
+ private ObjectReferences references;
+ private EventHandler eventHandler;
+
+ // Maps AccessibleRoles strings to AccessibleRoles.
+ private ConcurrentHashMap accessibleRoleMap = new ConcurrentHashMap<>();
+
+ /**
+ If the object's role is in the following array getVirtualAccessibleName
+ will use the extended search algorithm.
+ */
+ private ArrayList extendedVirtualNameSearchRoles = new ArrayList<>();
+ /**
+ If the role of the object's parent is in the following array
+ getVirtualAccessibleName will NOT use the extended search
+ algorithm even if the object's role is in the
+ extendedVirtualNameSearchRoles array.
+ */
+ private ArrayList noExtendedVirtualNameSearchParentRoles = new ArrayList<>();
+
+ private static native boolean isSysWow();
+
+
+ /**
+ * Load DLLs
+ */
+ static {
+ // Load the appropriate DLLs
+ boolean is32on64 = false;
+ if (System.getProperty("os.arch").equals("x86")) {
+ // 32 bit JRE
+ // Load jabsysinfo.dll so can determine Win bitness
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Void run() {
+ System.loadLibrary("jabsysinfo");
+ return null;
+ }
+ }, null, new java.lang.RuntimePermission("loadLibrary.jabsysinfo")
+ );
+ if (isSysWow()) {
+ // 32 bit JRE on 64 bit OS
+ is32on64 = true;
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Void run() {
+ System.loadLibrary("javaaccessbridge-32");
+ return null;
+ }
+ }, null, new java.lang.RuntimePermission("loadLibrary.javaaccessbridge-32")
+ );
+ }
+ }
+ if (!is32on64) {
+ // 32 bit JRE on 32 bit OS or 64 bit JRE on 64 bit OS
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Void run() {
+ System.loadLibrary("javaaccessbridge");
+ return null;
+ }
+ }, null, new java.lang.RuntimePermission("loadLibrary.javaaccessbridge")
+ );
+ }
+ }
+
+ /**
+ * AccessBridge constructor
+ *
+ * Note: This constructor has to be public. It's called from the VM like this:
+ * Class.forName(atName).newInstance();
+ */
+ public AccessBridge() {
+ theAccessBridge = this;
+ references = new ObjectReferences();
+
+ // initialize shutdown hook
+ Runtime runTime = Runtime.getRuntime();
+ shutdownHook hook = new shutdownHook();
+ runTime.addShutdownHook(new Thread(hook));
+
+ // initialize AccessibleRole map
+ initAccessibleRoleMap();
+
+ // determine which version of the JDK is running
+ String version = getJavaVersionProperty();
+ debugString("JDK version = "+version);
+
+ // initialize the methods that map HWNDs and Java top-level
+ // windows
+ initHWNDcalls();
+
+ // is this a JVM we can use?
+ // install JDK 1.2 and later Swing ToolKit listener
+ EventQueueMonitor.isGUIInitialized();
+
+ // start the Java event handler
+ eventHandler = new EventHandler(this);
+
+ // register for menu selection events
+ MenuSelectionManager.defaultManager().addChangeListener(eventHandler);
+
+ // register as a NativeWindowHandler
+ addNativeWindowHandler(new DefaultNativeWindowHandler());
+
+ // start in a new thread
+ Thread abthread = new Thread(new dllRunner());
+ abthread.setDaemon(true);
+ abthread.start();
+ debugString("AccessBridge started");
+ }
+
+ /*
+ * adaptor to run the AccessBridge DLL
+ */
+ private class dllRunner implements Runnable {
+ public void run() {
+ runDLL();
+ }
+ }
+
+ /*
+ * shutdown hook
+ */
+ private class shutdownHook implements Runnable {
+
+ public void run() {
+ debugString("***** shutdownHook: shutting down...");
+ javaShutdown();
+ }
+ }
+
+
+ /*
+ * Initialize the hashtable that maps Strings to AccessibleRoles.
+ */
+ private void initAccessibleRoleMap() {
+ /*
+ * Initialize the AccessibleRoles map. This code uses methods in
+ * java.lang.reflect.* to build the map.
+ */
+ try {
+ Class> clAccessibleRole = Class.forName ("javax.accessibility.AccessibleRole");
+ if (null != clAccessibleRole) {
+ AccessibleRole roleUnknown = AccessibleRole.UNKNOWN;
+ Field [] fields = clAccessibleRole.getFields ();
+ int i = 0;
+ for (i = 0; i < fields.length; i ++) {
+ Field f = fields [i];
+ if (javax.accessibility.AccessibleRole.class == f.getType ()) {
+ AccessibleRole nextRole = (AccessibleRole) (f.get (roleUnknown));
+ String nextRoleString = nextRole.toDisplayString (Locale.US);
+ accessibleRoleMap.put (nextRoleString, nextRole);
+ }
+ }
+ }
+ } catch (Exception e) {}
+
+ /*
+ Build the extendedVirtualNameSearchRoles array list. I chose this method
+ because some of the Accessible Roles that need to be added to it are not
+ available in all versions of the J2SE that we want to support.
+ */
+ extendedVirtualNameSearchRoles.add (AccessibleRole.COMBO_BOX);
+ try {
+ /*
+ Added in J2SE 1.4
+ */
+ extendedVirtualNameSearchRoles.add (AccessibleRole.DATE_EDITOR);
+ } catch (NoSuchFieldError e) {}
+ extendedVirtualNameSearchRoles.add (AccessibleRole.LIST);
+ extendedVirtualNameSearchRoles.add (AccessibleRole.PASSWORD_TEXT);
+ extendedVirtualNameSearchRoles.add (AccessibleRole.SLIDER);
+ try {
+ /*
+ Added in J2SE 1.3
+ */
+ extendedVirtualNameSearchRoles.add (AccessibleRole.SPIN_BOX);
+ } catch (NoSuchFieldError e) {}
+ extendedVirtualNameSearchRoles.add (AccessibleRole.TABLE);
+ extendedVirtualNameSearchRoles.add (AccessibleRole.TEXT);
+ extendedVirtualNameSearchRoles.add (AccessibleRole.UNKNOWN);
+
+ noExtendedVirtualNameSearchParentRoles.add (AccessibleRole.TABLE);
+ noExtendedVirtualNameSearchParentRoles.add (AccessibleRole.TOOL_BAR);
+ }
+
+ /**
+ * start the AccessBridge DLL running in its own thread
+ */
+ private native void runDLL();
+
+ /**
+ * debugging output (goes to OutputDebugStr())
+ */
+ private native void sendDebugString(String debugStr);
+
+ /**
+ * debugging output (goes to OutputDebugStr())
+ */
+ private void debugString(String debugStr) {
+ sendDebugString(debugStr);
+ }
+
+ /* ===== utility methods ===== */
+
+ /**
+ * decrement the reference to the object (called by native code)
+ */
+ private void decrementReference(Object o) {
+ references.decrement(o);
+ }
+
+ /**
+ * get the java.version property from the JVM
+ */
+ private String getJavaVersionProperty() {
+ String s = System.getProperty("java.version");
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ return null;
+ }
+
+ /* ===== HWND/Java window mapping methods ===== */
+
+ // Java toolkit methods for mapping HWNDs to Java components
+ private Method javaGetComponentFromNativeWindowHandleMethod;
+ private Method javaGetNativeWindowHandleFromComponentMethod;
+
+ // native jawt methods for mapping HWNDs to Java components
+ private native int jawtGetNativeWindowHandleFromComponent(Component comp);
+
+ private native Component jawtGetComponentFromNativeWindowHandle(int handle);
+
+ Toolkit toolkit;
+
+ /**
+ * map an HWND to an AWT Component
+ */
+ private void initHWNDcalls() {
+ Class> integerParemter[] = new Class>[1];
+ integerParemter[0] = Integer.TYPE;
+ Class> componentParemter[] = new Class>[1];
+ try {
+ componentParemter[0] = Class.forName("java.awt.Component");
+ } catch (ClassNotFoundException e) {
+ debugString("Exception: " + e.toString());
+ }
+ toolkit = Toolkit.getDefaultToolkit();
+ return;
+ }
+
+ // native window handler interface
+ private interface NativeWindowHandler {
+ public Accessible getAccessibleFromNativeWindowHandle(int nativeHandle);
+ }
+
+ // hash table of native window handle to AccessibleContext mappings
+ static private ConcurrentHashMap windowHandleToContextMap = new ConcurrentHashMap<>();
+
+ // hash table of AccessibleContext to native window handle mappings
+ static private ConcurrentHashMap contextToWindowHandleMap = new ConcurrentHashMap<>();
+
+ /*
+ * adds a virtual window handler to our hash tables
+ */
+ static private void registerVirtualFrame(final Accessible a,
+ Integer nativeWindowHandle ) {
+ if (a != null) {
+ AccessibleContext ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return a.getAccessibleContext();
+ }
+ }, a);
+ windowHandleToContextMap.put(nativeWindowHandle, ac);
+ contextToWindowHandleMap.put(ac, nativeWindowHandle);
+ }
+ }
+
+ /*
+ * removes a virtual window handler to our hash tables
+ */
+ static private void revokeVirtualFrame(final Accessible a,
+ Integer nativeWindowHandle ) {
+ AccessibleContext ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return a.getAccessibleContext();
+ }
+ }, a);
+ windowHandleToContextMap.remove(nativeWindowHandle);
+ contextToWindowHandleMap.remove(ac);
+ }
+
+ // vector of native window handlers
+ private static Vector nativeWindowHandlers = new Vector<>();
+
+ /*
+ * adds a native window handler to our list
+ */
+ private static void addNativeWindowHandler(NativeWindowHandler handler) {
+ if (handler == null) {
+ throw new IllegalArgumentException();
+ }
+ nativeWindowHandlers.addElement(handler);
+ }
+
+ /*
+ * removes a native window handler to our list
+ */
+ private static boolean removeNativeWindowHandler(NativeWindowHandler handler) {
+ if (handler == null) {
+ throw new IllegalArgumentException();
+ }
+ return nativeWindowHandlers.removeElement(handler);
+ }
+
+ /**
+ * verifies that a native window handle is a Java window
+ */
+ private boolean isJavaWindow(int nativeHandle) {
+ AccessibleContext ac = getContextFromNativeWindowHandle(nativeHandle);
+ if (ac != null) {
+ saveContextToWindowHandleMapping(ac, nativeHandle);
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * saves the mapping between an AccessibleContext and a window handle
+ */
+ private void saveContextToWindowHandleMapping(AccessibleContext ac,
+ int nativeHandle) {
+ debugString("saveContextToWindowHandleMapping...");
+ if (ac == null) {
+ return;
+ }
+ if (! contextToWindowHandleMap.containsKey(ac)) {
+ debugString("saveContextToWindowHandleMapping: ac = "+ac+"; handle = "+nativeHandle);
+ contextToWindowHandleMap.put(ac, nativeHandle);
+ }
+ }
+
+ /**
+ * maps a native window handle to an Accessible Context
+ */
+ private AccessibleContext getContextFromNativeWindowHandle(int nativeHandle) {
+ // First, look for the Accessible in our hash table of
+ // virtual window handles.
+ AccessibleContext ac = windowHandleToContextMap.get(nativeHandle);
+ if(ac!=null) {
+ saveContextToWindowHandleMapping(ac, nativeHandle);
+ return ac;
+ }
+
+ // Next, look for the native window handle in our vector
+ // of native window handles.
+ int numHandlers = nativeWindowHandlers.size();
+ for (int i = 0; i < numHandlers; i++) {
+ NativeWindowHandler nextHandler = nativeWindowHandlers.elementAt(i);
+ final Accessible a = nextHandler.getAccessibleFromNativeWindowHandle(nativeHandle);
+ if (a != null) {
+ ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return a.getAccessibleContext();
+ }
+ }, a);
+ saveContextToWindowHandleMapping(ac, nativeHandle);
+ return ac;
+ }
+ }
+ // Not found.
+ return null;
+ }
+
+ /**
+ * maps an AccessibleContext to a native window handle
+ * returns 0 on error
+ */
+ private int getNativeWindowHandleFromContext(AccessibleContext ac) {
+ debugString("getNativeWindowHandleFromContext: ac = "+ac);
+ try {
+ return contextToWindowHandleMap.get(ac);
+ } catch (Exception ex) {
+ return 0;
+ }
+ }
+
+ private class DefaultNativeWindowHandler implements NativeWindowHandler {
+ /*
+ * returns the Accessible associated with a native window
+ */
+ public Accessible getAccessibleFromNativeWindowHandle(int nativeHandle) {
+ final Component c = jawtGetComponentFromNativeWindowHandle(nativeHandle);
+ if (c instanceof Accessible) {
+ AccessibleContext ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return c.getAccessibleContext();
+ }
+ }, c);
+ saveContextToWindowHandleMapping(ac, nativeHandle);
+ return (Accessible)c;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /* ===== AccessibleContext methods =====*/
+
+ /*
+ * returns the inner-most AccessibleContext in parent at Point(x, y)
+ */
+ private AccessibleContext getAccessibleContextAt(int x, int y,
+ AccessibleContext parent) {
+ if (parent == null) {
+ return null;
+ }
+ if (windowHandleToContextMap != null &&
+ windowHandleToContextMap.containsValue(getRootAccessibleContext(parent))) {
+ // Path for applications that register their top-level
+ // windows with the AccessBridge (e.g., StarOffice 6.1)
+ return getAccessibleContextAt_1(x, y, parent);
+ } else {
+ // Path for applications that do not register
+ // their top-level windows with the AccessBridge
+ // (e.g., Swing/AWT applications)
+ return getAccessibleContextAt_2(x, y, parent);
+ }
+ }
+
+ /*
+ * returns the root accessible context
+ */
+ private AccessibleContext getRootAccessibleContext(final AccessibleContext ac) {
+ if (ac == null) {
+ return null;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible parent = ac.getAccessibleParent();
+ if (parent == null) {
+ return ac;
+ }
+ Accessible tmp = parent.getAccessibleContext().getAccessibleParent();
+ while (tmp != null) {
+ parent = tmp;
+ tmp = parent.getAccessibleContext().getAccessibleParent();
+ }
+ return parent.getAccessibleContext();
+ }
+ }, ac);
+ }
+
+ /*
+ * StarOffice version that does not use the EventQueueMonitor
+ */
+ private AccessibleContext getAccessibleContextAt_1(final int x, final int y,
+ final AccessibleContext parent) {
+ debugString(" : getAccessibleContextAt_1 called");
+ debugString(" -> x = " + x + " y = " + y + " parent = " + parent);
+
+ if (parent == null) return null;
+ final AccessibleComponent acmp = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleComponent call() throws Exception {
+ return parent.getAccessibleComponent();
+ }
+ }, parent);
+ if (acmp!=null) {
+ final Point loc = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Point call() throws Exception {
+ return acmp.getLocation();
+ }
+ }, parent);
+ final Accessible a = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return acmp.getAccessibleAt(new Point(x - loc.x, y - loc.y));
+ }
+ }, parent);
+ if (a != null) {
+ AccessibleContext foundAC = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return a.getAccessibleContext();
+ }
+ }, parent);
+ if (foundAC != null) {
+ if (foundAC != parent) {
+ // recurse down into the child
+ return getAccessibleContextAt_1(x - loc.x, y - loc.y,
+ foundAC);
+ } else
+ return foundAC;
+ }
+ }
+ }
+ return parent;
+ }
+
+ /*
+ * AWT/Swing version
+ */
+ private AccessibleContext getAccessibleContextAt_2(final int x, final int y,
+ AccessibleContext parent) {
+ debugString("getAccessibleContextAt_2 called");
+ debugString(" -> x = " + x + " y = " + y + " parent = " + parent);
+
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible a = EventQueueMonitor.getAccessibleAt(new Point(x, y));
+ if (a != null) {
+ AccessibleContext childAC = a.getAccessibleContext();
+ if (childAC != null) {
+ debugString(" returning childAC = " + childAC);
+ return childAC;
+ }
+ }
+ return null;
+ }
+ }, parent);
+ }
+
+ /**
+ * returns the Accessible that has focus
+ */
+ private AccessibleContext getAccessibleContextWithFocus() {
+ Component c = AWTEventMonitor.getComponentWithFocus();
+ if (c != null) {
+ final Accessible a = Translator.getAccessible(c);
+ if (a != null) {
+ AccessibleContext ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return a.getAccessibleContext();
+ }
+ }, c);
+ if (ac != null) {
+ return ac;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * returns the AccessibleName from an AccessibleContext
+ */
+ private String getAccessibleNameFromContext(final AccessibleContext ac) {
+ debugString("***** ac = "+ac.getClass());
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleName();
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ debugString("Returning AccessibleName from Context: " + s);
+ return s;
+ } else {
+ return null;
+ }
+ } else {
+ debugString("getAccessibleNameFromContext; ac = null!");
+ return null;
+ }
+ }
+
+ /**
+ * Returns an AccessibleName for a component using an algorithm optimized
+ * for the JAWS screen reader. This method is only intended for JAWS. All
+ * other uses are entirely optional.
+ */
+ private String getVirtualAccessibleNameFromContext(final AccessibleContext ac) {
+ if (null != ac) {
+ /*
+ Step 1:
+ =======
+ Determine if we can obtain the Virtual Accessible Name from the
+ Accessible Name or Accessible Description of the object.
+ */
+ String nameString = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleName();
+ }
+ }, ac);
+ if ( ( null != nameString ) && ( 0 != nameString.length () ) ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from AccessibleContext::getAccessibleName.");
+ references.increment (nameString);
+ return nameString;
+ }
+ String descriptionString = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleDescription();
+ }
+ }, ac);
+ if ( ( null != descriptionString ) && ( 0 != descriptionString.length () ) ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from AccessibleContext::getAccessibleDescription.");
+ references.increment (descriptionString);
+ return descriptionString;
+ }
+
+ debugString ("The Virtual Accessible Name was not found using AccessibleContext::getAccessibleDescription. or getAccessibleName");
+ /*
+ Step 2:
+ =======
+ Decide whether the extended name search algorithm should be
+ used for this object.
+ */
+ boolean bExtendedSearch = false;
+ AccessibleRole role = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return ac.getAccessibleRole();
+ }
+ }, ac);
+ AccessibleContext parentContext = null;
+ AccessibleRole parentRole = AccessibleRole.UNKNOWN;
+
+ if ( extendedVirtualNameSearchRoles.contains (role) ) {
+ parentContext = getAccessibleParentFromContext (ac);
+ if ( null != parentContext ) {
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ parentRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return parentContextInnerTemp.getAccessibleRole();
+ }
+ }, ac);
+ if ( AccessibleRole.UNKNOWN != parentRole ) {
+ bExtendedSearch = true;
+ if ( noExtendedVirtualNameSearchParentRoles.contains (parentRole) ) {
+ bExtendedSearch = false;
+ }
+ }
+ }
+ }
+
+ if (false == bExtendedSearch) {
+ debugString ("bk -- getVirtualAccessibleNameFromContext will not use the extended name search algorithm. role = " + role.toDisplayString (Locale.US) );
+ /*
+ Step 3:
+ =======
+ We have determined that we should not use the extended name
+ search algorithm for this object (we must obtain the name of
+ the object from the object itself and not from neighboring
+ objects). However the object name cannot be obtained from
+ the Accessible Name or Accessible Description of the object.
+
+ Handle several special cases here that might yield a value for
+ the Virtual Accessible Name. Return null if the object does
+ not match the criteria for any of these special cases.
+ */
+ if (AccessibleRole.LABEL == role) {
+ /*
+ Does the label support the Accessible Text Interface?
+ */
+ final AccessibleText at = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleText call() throws Exception {
+ return ac.getAccessibleText();
+ }
+ }, ac);
+ if (null != at) {
+ int charCount = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return at.getCharCount();
+ }
+ }, ac);
+ String text = getAccessibleTextRangeFromContext (ac, 0, charCount);
+ if (null != text) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from the Accessible Text of the LABEL object.");
+ references.increment (text);
+ return text;
+ }
+ }
+ /*
+ Does the label support the Accessible Icon Interface?
+ */
+ debugString ("bk -- Attempting to obtain the Virtual Accessible Name from the Accessible Icon information.");
+ final AccessibleIcon [] ai = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleIcon[] call() throws Exception {
+ return ac.getAccessibleIcon();
+ }
+ }, ac);
+ if ( (null != ai) && (ai.length > 0) ) {
+ String iconDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ai[0].getAccessibleIconDescription();
+ }
+ }, ac);
+ if (iconDescription != null){
+ debugString ("bk -- The Virtual Accessible Name was obtained from the description of the first Accessible Icon found in the LABEL object.");
+ references.increment (iconDescription);
+ return iconDescription;
+ }
+ } else {
+ parentContext = getAccessibleParentFromContext (ac);
+ if ( null != parentContext ) {
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ parentRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return parentContextInnerTemp.getAccessibleRole();
+ }
+ }, ac);
+ if ( AccessibleRole.TABLE == parentRole ) {
+ int indexInParent = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return ac.getAccessibleIndexInParent();
+ }
+ }, ac);
+ final AccessibleContext acTableCell = getAccessibleChildFromContext (parentContext, indexInParent);
+ debugString ("bk -- Making a second attempt to obtain the Virtual Accessible Name from the Accessible Icon information for the Table Cell.");
+ if (acTableCell != null) {
+ final AccessibleIcon [] aiRet =InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleIcon[] call() throws Exception {
+ return acTableCell.getAccessibleIcon();
+ }
+ }, ac);
+ if ( (null != aiRet) && (aiRet.length > 0) ) {
+ String iconDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return aiRet[0].getAccessibleIconDescription();
+ }
+ }, ac);
+ if (iconDescription != null){
+ debugString ("bk -- The Virtual Accessible Name was obtained from the description of the first Accessible Icon found in the Table Cell object.");
+ references.increment (iconDescription);
+ return iconDescription;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if ( (AccessibleRole.TOGGLE_BUTTON == role) ||
+ (AccessibleRole.PUSH_BUTTON == role) ) {
+ /*
+ Does the button support the Accessible Icon Interface?
+ */
+ debugString ("bk -- Attempting to obtain the Virtual Accessible Name from the Accessible Icon information.");
+ final AccessibleIcon [] ai = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleIcon[] call() throws Exception {
+ return ac.getAccessibleIcon();
+ }
+ }, ac);
+ if ( (null != ai) && (ai.length > 0) ) {
+ String iconDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ai[0].getAccessibleIconDescription();
+ }
+ }, ac);
+ if (iconDescription != null){
+ debugString ("bk -- The Virtual Accessible Name was obtained from the description of the first Accessible Icon found in the TOGGLE_BUTTON or PUSH_BUTTON object.");
+ references.increment (iconDescription);
+ return iconDescription;
+ }
+ }
+ } else if ( AccessibleRole.CHECK_BOX == role ) {
+ /*
+ NOTE: The only case I know of in which a check box does not
+ have a name is when that check box is contained in a table.
+
+ In this case it would be appropriate to use the display string
+ of the check box object as the name (in US English the display
+ string is typically either "true" or "false").
+
+ I am using the AccessibleValue interface to obtain the display
+ string of the check box. If the Accessible Value is 1, I am
+ returning Boolean.TRUE.toString (), If the Accessible Value is
+ 0, I am returning Boolean.FALSE.toString (). If the Accessible
+ Value is some other number, I will return the display string of
+ the current numerical value of the check box.
+ */
+ final AccessibleValue av = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleValue call() throws Exception {
+ return ac.getAccessibleValue();
+ }
+ }, ac);
+ if ( null != av ) {
+ nameString = null;
+ Number value = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Number call() throws Exception {
+ return av.getCurrentAccessibleValue();
+ }
+ }, ac);
+ if ( null != value ) {
+ if ( 1 == value.intValue () ) {
+ nameString = Boolean.TRUE.toString ();
+ } else if ( 0 == value.intValue () ) {
+ nameString = Boolean.FALSE.toString ();
+ } else {
+ nameString = value.toString ();
+ }
+ if ( null != nameString ) {
+ references.increment (nameString);
+ return nameString;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ +
+ Beginning of the extended name search
+ +
+ */
+ final AccessibleContext parentContextOuterTemp = parentContext;
+ String parentName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return parentContextOuterTemp.getAccessibleName();
+ }
+ }, ac);
+ String parentDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return parentContextOuterTemp.getAccessibleDescription();
+ }
+ }, ac);
+
+ /*
+ Step 4:
+ =======
+ Special case for Slider Bar objects.
+ */
+ if ( (AccessibleRole.SLIDER == role) &&
+ (AccessibleRole.PANEL == parentRole) &&
+ (null != parentName) ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from the Accessible Name of the SLIDER object's parent object.");
+ references.increment (parentName);
+ return parentName;
+ }
+
+ boolean bIsEditCombo = false;
+
+ AccessibleContext testContext = ac;
+ /*
+ Step 5:
+ =======
+ Special case for Edit Combo Boxes
+ */
+ if ( (AccessibleRole.TEXT == role) &&
+ (AccessibleRole.COMBO_BOX == parentRole) ) {
+ bIsEditCombo = true;
+ if (null != parentName) {
+ debugString ("bk -- The Virtual Accessible Name for this Edit Combo box was obtained from the Accessible Name of the object's parent object.");
+ references.increment (parentName);
+ return parentName;
+ } else if (null != parentDescription) {
+ debugString ("bk -- The Virtual Accessible Name for this Edit Combo box was obtained from the Accessible Description of the object's parent object.");
+ references.increment (parentDescription);
+ return parentDescription;
+ }
+ testContext = parentContext;
+ parentRole = AccessibleRole.UNKNOWN;
+ parentContext = getAccessibleParentFromContext (testContext);
+ if ( null != parentContext ) {
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ parentRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return parentContextInnerTemp.getAccessibleRole();
+ }
+ }, ac);
+ }
+ }
+
+ /*
+ Step 6:
+ =======
+ Attempt to get the Virtual Accessible Name of the object using the
+ Accessible Relation Set Info (the LABELED_BY Accessible Relation).
+ */
+ {
+ final AccessibleContext parentContextTempInner = parentContext;
+ AccessibleRelationSet ars = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRelationSet call() throws Exception {
+ return parentContextTempInner.getAccessibleRelationSet();
+ }
+ }, ac);
+ if ( ars != null && (ars.size () > 0) && (ars.contains (AccessibleRelation.LABELED_BY)) ) {
+ AccessibleRelation labeledByRelation = ars.get (AccessibleRelation.LABELED_BY);
+ if (labeledByRelation != null) {
+ Object [] targets = labeledByRelation.getTarget ();
+ Object o = targets [0];
+ if (o instanceof Accessible) {
+ AccessibleContext labelContext = ((Accessible)o).getAccessibleContext ();
+ if (labelContext != null) {
+ String labelName = labelContext.getAccessibleName ();
+ String labelDescription = labelContext.getAccessibleDescription ();
+ if (null != labelName) {
+ debugString ("bk -- The Virtual Accessible Name was obtained using the LABELED_BY AccessibleRelation -- Name Case.");
+ references.increment (labelName);
+ return labelName;
+ } else if (null != labelDescription) {
+ debugString ("bk -- The Virtual Accessible Name was obtained using the LABELED_BY AccessibleRelation -- Description Case.");
+ references.increment (labelDescription);
+ return labelDescription;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //Note: add AccessibleContext to use InvocationUtils.invokeAndWait
+ /*
+ Step 7:
+ =======
+ Search for a label object that is positioned either just to the left
+ or just above the object and get the Accessible Name of the Label
+ object.
+ */
+ int testIndexMax = 0;
+ int testX = 0;
+ int testY = 0;
+ int testWidth = 0;
+ int testHeight = 0;
+ int targetX = 0;
+ int targetY = 0;
+ final AccessibleContext tempContext = testContext;
+ int testIndex = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return tempContext.getAccessibleIndexInParent();
+ }
+ }, ac);
+ if ( null != parentContext ) {
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ testIndexMax = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return parentContextInnerTemp.getAccessibleChildrenCount() - 1;
+ }
+ }, ac);
+ }
+ testX = getAccessibleXcoordFromContext (testContext);
+ testY = getAccessibleYcoordFromContext (testContext);
+ testWidth = getAccessibleWidthFromContext (testContext);
+ testHeight = getAccessibleHeightFromContext (testContext);
+ targetX = testX + 2;
+ targetY = testY + 2;
+
+ int childIndex = testIndex - 1;
+ /*Accessible child = null;
+ AccessibleContext childContext = null;
+ AccessibleRole childRole = AccessibleRole.UNKNOWN;*/
+ int childX = 0;
+ int childY = 0;
+ int childWidth = 0;
+ int childHeight = 0;
+ String childName = null;
+ String childDescription = null;
+ while (childIndex >= 0) {
+ final int childIndexTemp = childIndex;
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ final Accessible child = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return parentContextInnerTemp.getAccessibleChild(childIndexTemp);
+ }
+ }, ac);
+ if ( null != child ) {
+ final AccessibleContext childContext = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return child.getAccessibleContext();
+ }
+ }, ac);
+ if ( null != childContext ) {
+ AccessibleRole childRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return childContext.getAccessibleRole();
+ }
+ }, ac);
+ if ( AccessibleRole.LABEL == childRole ) {
+ childX = getAccessibleXcoordFromContext (childContext);
+ childY = getAccessibleYcoordFromContext (childContext);
+ childWidth = getAccessibleWidthFromContext (childContext);
+ childHeight = getAccessibleHeightFromContext (childContext);
+ if ( (childX < testX) &&
+ ((childY <= targetY) && (targetY <= (childY + childHeight))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a LABEL object positioned to the left of the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a LABEL object positioned to the left of the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ } else if ( (childY < targetY) &&
+ ((childX <= targetX) && (targetX <= (childX + childWidth))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a LABEL object positioned above the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a LABEL object positioned above the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ }
+ }
+ }
+ }
+ childIndex --;
+ }
+ childIndex = testIndex + 1;
+ while (childIndex <= testIndexMax) {
+ final int childIndexTemp = childIndex;
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ final Accessible child = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return parentContextInnerTemp.getAccessibleChild(childIndexTemp);
+ }
+ }, ac);
+ if ( null != child ) {
+ final AccessibleContext childContext = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return child.getAccessibleContext();
+ }
+ }, ac);
+ if ( null != childContext ) {
+ AccessibleRole childRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return childContext.getAccessibleRole();
+ }
+ }, ac);
+ if ( AccessibleRole.LABEL == childRole ) {
+ childX = getAccessibleXcoordFromContext (childContext);
+ childY = getAccessibleYcoordFromContext (childContext);
+ childWidth = getAccessibleWidthFromContext (childContext);
+ childHeight = getAccessibleHeightFromContext (childContext);
+ if ( (childX < testX) &&
+ ((childY <= targetY) && (targetY <= (childY + childHeight))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a LABEL object positioned to the left of the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a LABEL object positioned to the left of the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ } else if ( (childY < targetY) &&
+ ((childX <= targetX) && (targetX <= (childX + childWidth))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a LABEL object positioned above the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a LABEL object positioned above the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ }
+ }
+ }
+ }
+ childIndex ++;
+ }
+ /*
+ Step 8:
+ =======
+ Special case for combo boxes and text objects, based on a
+ similar special case I found in some of our internal JAWS code.
+
+ Search for a button object that is positioned either just to the left
+ or just above the object and get the Accessible Name of the button
+ object.
+ */
+ if ( (AccessibleRole.TEXT == role) ||
+ (AccessibleRole.COMBO_BOX == role) ||
+ (bIsEditCombo) ) {
+ childIndex = testIndex - 1;
+ while (childIndex >= 0) {
+ final int childIndexTemp = childIndex;
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ final Accessible child = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return parentContextInnerTemp.getAccessibleChild(childIndexTemp);
+ }
+ }, ac);
+ if ( null != child ) {
+ final AccessibleContext childContext = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return child.getAccessibleContext();
+ }
+ }, ac);
+ if ( null != childContext ) {
+ AccessibleRole childRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return childContext.getAccessibleRole();
+ }
+ }, ac);
+ if ( ( AccessibleRole.PUSH_BUTTON == childRole ) ||
+ ( AccessibleRole.TOGGLE_BUTTON == childRole )) {
+ childX = getAccessibleXcoordFromContext (childContext);
+ childY = getAccessibleYcoordFromContext (childContext);
+ childWidth = getAccessibleWidthFromContext (childContext);
+ childHeight = getAccessibleHeightFromContext (childContext);
+ if ( (childX < testX) &&
+ ((childY <= targetY) && (targetY <= (childY + childHeight))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a PUSH_BUTTON or TOGGLE_BUTTON object positioned to the left of the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a PUSH_BUTTON or TOGGLE_BUTTON object positioned to the left of the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ }
+ }
+ }
+ }
+ childIndex --;
+ }
+ childIndex = testIndex + 1;
+ while (childIndex <= testIndexMax) {
+ final int childIndexTemp = childIndex;
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ final Accessible child = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return parentContextInnerTemp.getAccessibleChild(childIndexTemp);
+ }
+ }, ac);
+ if ( null != child ) {
+ final AccessibleContext childContext = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return child.getAccessibleContext();
+ }
+ }, ac);
+ if ( null != childContext ) {
+ AccessibleRole childRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return childContext.getAccessibleRole();
+ }
+ }, ac);
+ if ( ( AccessibleRole.PUSH_BUTTON == childRole ) ||
+ ( AccessibleRole.TOGGLE_BUTTON == childRole ) ) {
+ childX = getAccessibleXcoordFromContext (childContext);
+ childY = getAccessibleYcoordFromContext (childContext);
+ childWidth = getAccessibleWidthFromContext (childContext);
+ childHeight = getAccessibleHeightFromContext (childContext);
+ if ( (childX < testX) &&
+ ((childY <= targetY) && (targetY <= (childY + childHeight))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a PUSH_BUTTON or TOGGLE_BUTTON object positioned to the left of the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a PUSH_BUTTON or TOGGLE_BUTTON object positioned to the left of the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ }
+ }
+ }
+ }
+ childIndex ++;
+ }
+ }
+ return null;
+ } else {
+ debugString ("AccessBridge::getVirtualAccessibleNameFromContext error - ac == null.");
+ return null;
+ }
+ }
+
+ /**
+ * returns the AccessibleDescription from an AccessibleContext
+ */
+ private String getAccessibleDescriptionFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleDescription();
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ debugString("Returning AccessibleDescription from Context: " + s);
+ return s;
+ }
+ } else {
+ debugString("getAccessibleDescriptionFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * returns the AccessibleRole from an AccessibleContext
+ */
+ private String getAccessibleRoleStringFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ AccessibleRole role = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return ac.getAccessibleRole();
+ }
+ }, ac);
+ if (role != null) {
+ String s = role.toDisplayString(Locale.US);
+ if (s != null) {
+ references.increment(s);
+ debugString("Returning AccessibleRole from Context: " + s);
+ return s;
+ }
+ }
+ } else {
+ debugString("getAccessibleRoleStringFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the AccessibleRole from an AccessibleContext in the en_US locale
+ */
+ private String getAccessibleRoleStringFromContext_en_US(final AccessibleContext ac) {
+ return getAccessibleRoleStringFromContext(ac);
+ }
+
+ /**
+ * return the AccessibleStates from an AccessibleContext
+ */
+ private String getAccessibleStatesStringFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ AccessibleStateSet stateSet = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleStateSet call() throws Exception {
+ return ac.getAccessibleStateSet();
+ }
+ }, ac);
+ if (stateSet != null) {
+ String s = stateSet.toString();
+ if (s != null &&
+ s.indexOf(AccessibleState.MANAGES_DESCENDANTS.toDisplayString(Locale.US)) == -1) {
+ // Indicate whether this component manages its own
+ // children
+ AccessibleRole role = ac.getAccessibleRole();
+ if (role == AccessibleRole.LIST ||
+ role == AccessibleRole.TABLE ||
+ role == AccessibleRole.TREE) {
+ s += ",";
+ s += AccessibleState.MANAGES_DESCENDANTS.toDisplayString(Locale.US);
+ }
+ references.increment(s);
+ debugString("Returning AccessibleStateSet from Context: " + s);
+ return s;
+ }
+ }
+ } else {
+ debugString("getAccessibleStatesStringFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * returns the AccessibleStates from an AccessibleContext in the en_US locale
+ */
+ private String getAccessibleStatesStringFromContext_en_US(final AccessibleContext ac) {
+ if (ac != null) {
+ AccessibleStateSet stateSet = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleStateSet call() throws Exception {
+ return ac.getAccessibleStateSet();
+ }
+ }, ac);
+ if (stateSet != null) {
+ String s = "";
+ AccessibleState[] states = stateSet.toArray();
+ if (states != null && states.length > 0) {
+ s = states[0].toDisplayString(Locale.US);
+ for (int i = 1; i < states.length; i++) {
+ s = s + "," + states[i].toDisplayString(Locale.US);
+ }
+ }
+ references.increment(s);
+ debugString("Returning AccessibleStateSet en_US from Context: " + s);
+ return s;
+ }
+ }
+ debugString("getAccessibleStatesStringFromContext; ac = null");
+ return null;
+ }
+
+ /**
+ * returns the AccessibleParent from an AccessibleContext
+ */
+ private AccessibleContext getAccessibleParentFromContext(final AccessibleContext ac) {
+ if (ac==null)
+ return null;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible a = ac.getAccessibleParent();
+ if (a != null) {
+ AccessibleContext apc = a.getAccessibleContext();
+ if (apc != null) {
+ return apc;
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleIndexInParent from an AccessibleContext
+ */
+ private int getAccessibleIndexInParentFromContext(final AccessibleContext ac) {
+ if (ac==null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return ac.getAccessibleIndexInParent();
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleChild count from an AccessibleContext
+ */
+ private int getAccessibleChildrenCountFromContext(final AccessibleContext ac) {
+ if (ac==null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return ac.getAccessibleChildrenCount();
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleChild Context from an AccessibleContext
+ */
+ private AccessibleContext getAccessibleChildFromContext(final AccessibleContext ac, final int index) {
+
+ if (ac == null) {
+ return null;
+ }
+
+ final JTable table = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public JTable call() throws Exception {
+ // work-around for AccessibleJTable.getCurrentAccessibleContext returning
+ // wrong renderer component when cell contains more than one component
+ Accessible parent = ac.getAccessibleParent();
+ if (parent != null) {
+ int indexInParent = ac.getAccessibleIndexInParent();
+ Accessible child =
+ parent.getAccessibleContext().getAccessibleChild(indexInParent);
+ if (child instanceof JTable) {
+ return (JTable) child;
+ }
+ }
+ return null;
+ }
+ }, ac);
+
+ if (table == null) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible a = ac.getAccessibleChild(index);
+ if (a != null) {
+ return a.getAccessibleContext();
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ final AccessibleTable at = getAccessibleTableFromContext(ac);
+
+ final int row = getAccessibleTableRow(at, index);
+ final int column = getAccessibleTableColumn(at, index);
+
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ TableCellRenderer renderer = table.getCellRenderer(row, column);
+ if (renderer == null) {
+ Class> columnClass = table.getColumnClass(column);
+ renderer = table.getDefaultRenderer(columnClass);
+ }
+ Component component =
+ renderer.getTableCellRendererComponent(table, table.getValueAt(row, column),
+ false, false, row, column);
+ if (component instanceof Accessible) {
+ return component.getAccessibleContext();
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleComponent bounds on screen from an AccessibleContext
+ */
+ private Rectangle getAccessibleBoundsOnScreenFromContext(final AccessibleContext ac) {
+ if(ac==null)
+ return null;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Rectangle call() throws Exception {
+ AccessibleComponent acmp = ac.getAccessibleComponent();
+ if (acmp != null) {
+ Rectangle r = acmp.getBounds();
+ if (r != null) {
+ try {
+ Point p = acmp.getLocationOnScreen();
+ if (p != null) {
+ r.x = p.x;
+ r.y = p.y;
+ return r;
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleComponent x-coord from an AccessibleContext
+ */
+ private int getAccessibleXcoordFromContext(AccessibleContext ac) {
+ if (ac != null) {
+ Rectangle r = getAccessibleBoundsOnScreenFromContext(ac);
+ if (r != null) {
+ debugString(" - Returning Accessible x coord from Context: " + r.x);
+ return r.x;
+ }
+ } else {
+ debugString("getAccessibleXcoordFromContext ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * returns the AccessibleComponent y-coord from an AccessibleContext
+ */
+ private int getAccessibleYcoordFromContext(AccessibleContext ac) {
+ debugString("getAccessibleYcoordFromContext() called");
+ if (ac != null) {
+ Rectangle r = getAccessibleBoundsOnScreenFromContext(ac);
+ if (r != null) {
+ return r.y;
+ }
+ } else {
+ debugString("getAccessibleYcoordFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * returns the AccessibleComponent height from an AccessibleContext
+ */
+ private int getAccessibleHeightFromContext(AccessibleContext ac) {
+ if (ac != null) {
+ Rectangle r = getAccessibleBoundsOnScreenFromContext(ac);
+ if (r != null) {
+ return r.height;
+ }
+ } else {
+ debugString("getAccessibleHeightFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * returns the AccessibleComponent width from an AccessibleContext
+ */
+ private int getAccessibleWidthFromContext(AccessibleContext ac) {
+ if (ac != null) {
+ Rectangle r = getAccessibleBoundsOnScreenFromContext(ac);
+ if (r != null) {
+ return r.width;
+ }
+ } else {
+ debugString("getAccessibleWidthFromContext; ac = null");
+ }
+ return -1;
+ }
+
+
+ /**
+ * returns the AccessibleComponent from an AccessibleContext
+ */
+ private AccessibleComponent getAccessibleComponentFromContext(AccessibleContext ac) {
+ if (ac != null) {
+ AccessibleComponent acmp = ac.getAccessibleComponent();
+ if (acmp != null) {
+ debugString("Returning AccessibleComponent Context");
+ return acmp;
+ }
+ } else {
+ debugString("getAccessibleComponentFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * returns the AccessibleAction from an AccessibleContext
+ */
+ private AccessibleAction getAccessibleActionFromContext(final AccessibleContext ac) {
+ debugString("Returning AccessibleAction Context");
+ return ac == null ? null : InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleAction call() throws Exception {
+ return ac.getAccessibleAction();
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleSelection from an AccessibleContext
+ */
+ private AccessibleSelection getAccessibleSelectionFromContext(final AccessibleContext ac) {
+ return ac == null ? null : InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleSelection call() throws Exception {
+ return ac.getAccessibleSelection();
+ }
+ }, ac);
+ }
+
+ /**
+ * return the AccessibleText from an AccessibleContext
+ */
+ private AccessibleText getAccessibleTextFromContext(final AccessibleContext ac) {
+ return ac == null ? null : InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleText call() throws Exception {
+ return ac.getAccessibleText();
+ }
+ }, ac);
+ }
+
+ /**
+ * return the AccessibleComponent from an AccessibleContext
+ */
+ private AccessibleValue getAccessibleValueFromContext(final AccessibleContext ac) {
+ return ac == null ? null : InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleValue call() throws Exception {
+ return ac.getAccessibleValue();
+ }
+ }, ac);
+ }
+
+ /* ===== AccessibleText methods ===== */
+
+ /**
+ * returns the bounding rectangle for the text cursor
+ * XXX
+ */
+ private Rectangle getCaretLocation(final AccessibleContext ac) {
+ debugString("getCaretLocation");
+ if (ac==null)
+ return null;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Rectangle call() throws Exception {
+ // workaround for JAAPI not returning cursor bounding rectangle
+ Rectangle r = null;
+ Accessible parent = ac.getAccessibleParent();
+ if (parent instanceof Accessible) {
+ int indexInParent = ac.getAccessibleIndexInParent();
+ Accessible child =
+ parent.getAccessibleContext().getAccessibleChild(indexInParent);
+
+ if (child instanceof JTextComponent) {
+ JTextComponent text = (JTextComponent) child;
+ try {
+ r = text.modelToView(text.getCaretPosition());
+ if (r != null) {
+ Point p = text.getLocationOnScreen();
+ r.translate(p.x, p.y);
+ }
+ } catch (BadLocationException ble) {
+ }
+ }
+ }
+ return r;
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the x-coordinate for the text cursor rectangle
+ */
+ private int getCaretLocationX(AccessibleContext ac) {
+ Rectangle r = getCaretLocation(ac);
+ if (r != null) {
+ return r.x;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * returns the y-coordinate for the text cursor rectangle
+ */
+ private int getCaretLocationY(AccessibleContext ac) {
+ Rectangle r = getCaretLocation(ac);
+ if (r != null) {
+ return r.y;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * returns the height for the text cursor rectangle
+ */
+ private int getCaretLocationHeight(AccessibleContext ac) {
+ Rectangle r = getCaretLocation(ac);
+ if (r != null) {
+ return r.height;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * returns the width for the text cursor rectangle
+ */
+ private int getCaretLocationWidth(AccessibleContext ac) {
+ Rectangle r = getCaretLocation(ac);
+ if (r != null) {
+ return r.width;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * returns the character count from an AccessibleContext
+ */
+ private int getAccessibleCharCountFromContext(final AccessibleContext ac) {
+ if (ac==null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ return at.getCharCount();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the caret position from an AccessibleContext
+ */
+ private int getAccessibleCaretPositionFromContext(final AccessibleContext ac) {
+ if (ac==null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ return at.getCaretPosition();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * Return the index at a specific point from an AccessibleContext
+ * Point(x, y) is in screen coordinates.
+ */
+ private int getAccessibleIndexAtPointFromContext(final AccessibleContext ac,
+ final int x, final int y) {
+ debugString("getAccessibleIndexAtPointFromContext: x = "+x+"; y = "+y);
+ if (ac==null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ AccessibleComponent acomp = ac.getAccessibleComponent();
+ if (at != null && acomp != null) {
+ // Convert x and y from screen coordinates to
+ // local coordinates.
+ try {
+ Point p = acomp.getLocationOnScreen();
+ int x1, y1;
+ if (p != null) {
+ x1 = x - p.x;
+ if (x1 < 0) {
+ x1 = 0;
+ }
+ y1 = y - p.y;
+ if (y1 < 0) {
+ y1 = 0;
+ }
+
+ Point newPoint = new Point(x1, y1);
+ int indexAtPoint = at.getIndexAtPoint(new Point(x1, y1));
+ return indexAtPoint;
+ }
+ } catch (Exception e) {
+ }
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * return the letter at a specific point from an AccessibleContext
+ */
+ private String getAccessibleLetterAtIndexFromContext(final AccessibleContext ac, final int index) {
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at == null) return null;
+ return at.getAtIndex(AccessibleText.CHARACTER, index);
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getAccessibleLetterAtIndexFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the word at a specific point from an AccessibleContext
+ */
+ private String getAccessibleWordAtIndexFromContext(final AccessibleContext ac, final int index) {
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at == null) return null;
+ return at.getAtIndex(AccessibleText.WORD, index);
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getAccessibleWordAtIndexFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the sentence at a specific point from an AccessibleContext
+ */
+ private String getAccessibleSentenceAtIndexFromContext(final AccessibleContext ac, final int index) {
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at == null) return null;
+ return at.getAtIndex(AccessibleText.SENTENCE, index);
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getAccessibleSentenceAtIndexFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the text selection start from an AccessibleContext
+ */
+ private int getAccessibleTextSelectionStartFromContext(final AccessibleContext ac) {
+ if (ac == null) return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ return at.getSelectionStart();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * return the text selection end from an AccessibleContext
+ */
+ private int getAccessibleTextSelectionEndFromContext(final AccessibleContext ac) {
+ if (ac == null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ return at.getSelectionEnd();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * return the selected text from an AccessibleContext
+ */
+ private String getAccessibleTextSelectedTextFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at == null) return null;
+ return at.getSelectedText();
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getAccessibleTextSelectedTextFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the attribute string at a given index from an AccessibleContext
+ */
+ private String getAccessibleAttributesAtIndexFromContext(final AccessibleContext ac,
+ final int index) {
+ if (ac == null)
+ return null;
+ AttributeSet as = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AttributeSet call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ return at.getCharacterAttribute(index);
+ }
+ return null;
+ }
+ }, ac);
+ String s = expandStyleConstants(as);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ return null;
+ }
+
+ /**
+ * Get line info: left index of line
+ *
+ * algorithm: cast back, doubling each time,
+ * 'till find line boundaries
+ *
+ * return -1 if we can't get the info (e.g. index or at passed in
+ * is bogus; etc.)
+ */
+ private int getAccessibleTextLineLeftBoundsFromContext(final AccessibleContext ac,
+ final int index) {
+ if (ac == null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ int lineStart;
+ int offset;
+ Rectangle charRect;
+ Rectangle indexRect = at.getCharacterBounds(index);
+ int textLen = at.getCharCount();
+ if (indexRect == null) {
+ return -1;
+ }
+ // find the start of the line
+ //
+ offset = 1;
+ lineStart = index - offset < 0 ? 0 : index - offset;
+ charRect = at.getCharacterBounds(lineStart);
+ // slouch behind beginning of line
+ while (charRect != null
+ && charRect.y >= indexRect.y
+ && lineStart > 0) {
+ offset = offset << 1;
+ lineStart = index - offset < 0 ? 0 : index - offset;
+ charRect = at.getCharacterBounds(lineStart);
+ }
+ if (lineStart == 0) { // special case: we're on the first line!
+ // we found it!
+ } else {
+ offset = offset >> 1; // know boundary within last expansion
+ // ground forward to beginning of line
+ while (offset > 0) {
+ charRect = at.getCharacterBounds(lineStart + offset);
+ if (charRect.y < indexRect.y) { // still before line
+ lineStart += offset;
+ } else {
+ // leave lineStart alone, it's close!
+ }
+ offset = offset >> 1;
+ }
+ // subtract one 'cause we're already too far...
+ lineStart += 1;
+ }
+ return lineStart;
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * Get line info: right index of line
+ *
+ * algorithm: cast back, doubling each time,
+ * 'till find line boundaries
+ *
+ * return -1 if we can't get the info (e.g. index or at passed in
+ * is bogus; etc.)
+ */
+ private int getAccessibleTextLineRightBoundsFromContext(final AccessibleContext ac, final int index) {
+ if(ac == null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ int lineEnd;
+ int offset;
+ Rectangle charRect;
+ Rectangle indexRect = at.getCharacterBounds(index);
+ int textLen = at.getCharCount();
+ if (indexRect == null) {
+ return -1;
+ }
+ // find the end of the line
+ //
+ offset = 1;
+ lineEnd = index + offset > textLen - 1
+ ? textLen - 1 : index + offset;
+ charRect = at.getCharacterBounds(lineEnd);
+ // push past end of line
+ while (charRect != null &&
+ charRect.y <= indexRect.y &&
+ lineEnd < textLen - 1) {
+ offset = offset << 1;
+ lineEnd = index + offset > textLen - 1
+ ? textLen - 1 : index + offset;
+ charRect = at.getCharacterBounds(lineEnd);
+ }
+ if (lineEnd == textLen - 1) { // special case: on the last line!
+ // we found it!
+ } else {
+ offset = offset >> 1; // know boundary within last expansion
+ // pull back to end of line
+ while (offset > 0) {
+ charRect = at.getCharacterBounds(lineEnd - offset);
+ if (charRect.y > indexRect.y) { // still beyond line
+ lineEnd -= offset;
+ } else {
+ // leave lineEnd alone, it's close!
+ }
+ offset = offset >> 1;
+ }
+ // subtract one 'cause we're already too far...
+ lineEnd -= 1;
+ }
+ return lineEnd;
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * Get a range of text; null if indicies are bogus
+ */
+ private String getAccessibleTextRangeFromContext(final AccessibleContext ac,
+ final int start, final int end) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ if (ac != null) {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ // start - end is inclusive
+ if (start > end) {
+ return null;
+ }
+ if (end >= at.getCharCount()) {
+ return null;
+ }
+ StringBuffer buf = new StringBuffer(end - start + 1);
+ for (int i = start; i <= end; i++) {
+ buf.append(at.getAtIndex(AccessibleText.CHARACTER, i));
+ }
+ return buf.toString();
+ }
+ }
+ return null;
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * return the AttributeSet object at a given index from an AccessibleContext
+ */
+ private AttributeSet getAccessibleAttributeSetAtIndexFromContext(final AccessibleContext ac,
+ final int index) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AttributeSet call() throws Exception {
+ if (ac != null) {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ AttributeSet as = at.getCharacterAttribute(index);
+ if (as != null) {
+ AccessBridge.this.references.increment(as);
+ return as;
+ }
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+
+ /**
+ * return the bounding rectangle at index from an AccessibleContext
+ */
+ private Rectangle getAccessibleTextRectAtIndexFromContext(final AccessibleContext ac,
+ final int index) {
+ // want to do this in global coords, so need to combine w/ac global coords
+ Rectangle r = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Rectangle call() throws Exception {
+ // want to do this in global coords, so need to combine w/ac global coords
+ if (ac != null) {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ Rectangle rect = at.getCharacterBounds(index);
+ if (rect != null) {
+ String s = at.getAtIndex(AccessibleText.CHARACTER, index);
+ if (s != null && s.equals("\n")) {
+ rect.width = 0;
+ }
+ return rect;
+ }
+ }
+ }
+ return null;
+ }
+ }, ac);
+ Rectangle acRect = getAccessibleBoundsOnScreenFromContext(ac);
+ if (r != null && acRect != null) {
+ r.translate(acRect.x, acRect.y);
+ return r;
+ }
+ return null;
+ }
+
+ /**
+ * return the AccessibleText character x-coord at index from an AccessibleContext
+ */
+ private int getAccessibleXcoordTextRectAtIndexFromContext(AccessibleContext ac, int index) {
+ if (ac != null) {
+ Rectangle r = getAccessibleTextRectAtIndexFromContext(ac, index);
+ if (r != null) {
+ return r.x;
+ }
+ } else {
+ debugString("getAccessibleXcoordTextRectAtIndexFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the AccessibleText character y-coord at index from an AccessibleContext
+ */
+ private int getAccessibleYcoordTextRectAtIndexFromContext(AccessibleContext ac, int index) {
+ if (ac != null) {
+ Rectangle r = getAccessibleTextRectAtIndexFromContext(ac, index);
+ if (r != null) {
+ return r.y;
+ }
+ } else {
+ debugString("getAccessibleYcoordTextRectAtIndexFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the AccessibleText character height at index from an AccessibleContext
+ */
+ private int getAccessibleHeightTextRectAtIndexFromContext(AccessibleContext ac, int index) {
+ if (ac != null) {
+ Rectangle r = getAccessibleTextRectAtIndexFromContext(ac, index);
+ if (r != null) {
+ return r.height;
+ }
+ } else {
+ debugString("getAccessibleHeightTextRectAtIndexFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the AccessibleText character width at index from an AccessibleContext
+ */
+ private int getAccessibleWidthTextRectAtIndexFromContext(AccessibleContext ac, int index) {
+ if (ac != null) {
+ Rectangle r = getAccessibleTextRectAtIndexFromContext(ac, index);
+ if (r != null) {
+ return r.width;
+ }
+ } else {
+ debugString("getAccessibleWidthTextRectAtIndexFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /* ===== AttributeSet methods for AccessibleText ===== */
+
+ /**
+ * return the bold setting from an AttributeSet
+ */
+ private boolean getBoldFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isBold(as);
+ } else {
+ debugString("getBoldFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the italic setting from an AttributeSet
+ */
+ private boolean getItalicFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isItalic(as);
+ } else {
+ debugString("getItalicFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the underline setting from an AttributeSet
+ */
+ private boolean getUnderlineFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isUnderline(as);
+ } else {
+ debugString("getUnderlineFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the strikethrough setting from an AttributeSet
+ */
+ private boolean getStrikethroughFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isStrikeThrough(as);
+ } else {
+ debugString("getStrikethroughFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the superscript setting from an AttributeSet
+ */
+ private boolean getSuperscriptFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isSuperscript(as);
+ } else {
+ debugString("getSuperscriptFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the subscript setting from an AttributeSet
+ */
+ private boolean getSubscriptFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isSubscript(as);
+ } else {
+ debugString("getSubscriptFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the background color from an AttributeSet
+ */
+ private String getBackgroundColorFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ String s = StyleConstants.getBackground(as).toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getBackgroundColorFromAttributeSet; as = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the foreground color from an AttributeSet
+ */
+ private String getForegroundColorFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ String s = StyleConstants.getForeground(as).toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getForegroundColorFromAttributeSet; as = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the font family from an AttributeSet
+ */
+ private String getFontFamilyFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ String s = StyleConstants.getFontFamily(as).toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getFontFamilyFromAttributeSet; as = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the font size from an AttributeSet
+ */
+ private int getFontSizeFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getFontSize(as);
+ } else {
+ debugString("getFontSizeFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the alignment from an AttributeSet
+ */
+ private int getAlignmentFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getAlignment(as);
+ } else {
+ debugString("getAlignmentFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the BiDi level from an AttributeSet
+ */
+ private int getBidiLevelFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getBidiLevel(as);
+ } else {
+ debugString("getBidiLevelFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+
+ /**
+ * return the first line indent from an AttributeSet
+ */
+ private float getFirstLineIndentFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getFirstLineIndent(as);
+ } else {
+ debugString("getFirstLineIndentFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the left indent from an AttributeSet
+ */
+ private float getLeftIndentFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getLeftIndent(as);
+ } else {
+ debugString("getLeftIndentFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the right indent from an AttributeSet
+ */
+ private float getRightIndentFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getRightIndent(as);
+ } else {
+ debugString("getRightIndentFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the line spacing from an AttributeSet
+ */
+ private float getLineSpacingFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getLineSpacing(as);
+ } else {
+ debugString("getLineSpacingFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the space above from an AttributeSet
+ */
+ private float getSpaceAboveFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getSpaceAbove(as);
+ } else {
+ debugString("getSpaceAboveFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the space below from an AttributeSet
+ */
+ private float getSpaceBelowFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getSpaceBelow(as);
+ } else {
+ debugString("getSpaceBelowFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * Enumerate all StyleConstants in the AttributeSet
+ *
+ * We need to check explicitly, 'cause of the HTML package conversion
+ * mechanism (they may not be stored as StyleConstants, just translated
+ * to them when asked).
+ *
+ * (Use convenience methods where they are defined...)
+ *
+ * Not checking the following (which the IBM SNS guidelines says
+ * should be defined):
+ * - ComponentElementName
+ * - IconElementName
+ * - NameAttribute
+ * - ResolveAttribute
+ */
+ private String expandStyleConstants(AttributeSet as) {
+ Color c;
+ Object o;
+ String attrString = "";
+
+ // ---------- check for various Character Constants
+
+ attrString += "BidiLevel = " + StyleConstants.getBidiLevel(as);
+
+ final Component comp = StyleConstants.getComponent(as);
+ if (comp != null) {
+ if (comp instanceof Accessible) {
+ final AccessibleContext ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return comp.getAccessibleContext();
+ }
+ }, comp);
+ if (ac != null) {
+ attrString += "; Accessible Component = " + InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleName();
+ }
+ }, ac);
+ } else {
+ attrString += "; Innaccessible Component = " + comp;
+ }
+ } else {
+ attrString += "; Innaccessible Component = " + comp;
+ }
+ }
+
+ Icon i = StyleConstants.getIcon(as);
+ if (i != null) {
+ if (i instanceof ImageIcon) {
+ attrString += "; ImageIcon = " + ((ImageIcon) i).getDescription();
+ } else {
+ attrString += "; Icon = " + i;
+ }
+ }
+
+ attrString += "; FontFamily = " + StyleConstants.getFontFamily(as);
+
+ attrString += "; FontSize = " + StyleConstants.getFontSize(as);
+
+ if (StyleConstants.isBold(as)) {
+ attrString += "; bold";
+ }
+
+ if (StyleConstants.isItalic(as)) {
+ attrString += "; italic";
+ }
+
+ if (StyleConstants.isUnderline(as)) {
+ attrString += "; underline";
+ }
+
+ if (StyleConstants.isStrikeThrough(as)) {
+ attrString += "; strikethrough";
+ }
+
+ if (StyleConstants.isSuperscript(as)) {
+ attrString += "; superscript";
+ }
+
+ if (StyleConstants.isSubscript(as)) {
+ attrString += "; subscript";
+ }
+
+ c = StyleConstants.getForeground(as);
+ if (c != null) {
+ attrString += "; Foreground = " + c;
+ }
+
+ c = StyleConstants.getBackground(as);
+ if (c != null) {
+ attrString += "; Background = " + c;
+ }
+
+ attrString += "; FirstLineIndent = " + StyleConstants.getFirstLineIndent(as);
+
+ attrString += "; RightIndent = " + StyleConstants.getRightIndent(as);
+
+ attrString += "; LeftIndent = " + StyleConstants.getLeftIndent(as);
+
+ attrString += "; LineSpacing = " + StyleConstants.getLineSpacing(as);
+
+ attrString += "; SpaceAbove = " + StyleConstants.getSpaceAbove(as);
+
+ attrString += "; SpaceBelow = " + StyleConstants.getSpaceBelow(as);
+
+ attrString += "; Alignment = " + StyleConstants.getAlignment(as);
+
+ TabSet ts = StyleConstants.getTabSet(as);
+ if (ts != null) {
+ attrString += "; TabSet = " + ts;
+ }
+
+ return attrString;
+ }
+
+
+ /* ===== AccessibleValue methods ===== */
+
+ /**
+ * return the AccessibleValue current value from an AccessibleContext
+ * returned using a String 'cause the value is a java Number
+ *
+ */
+ private String getCurrentAccessibleValueFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ final Number value = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Number call() throws Exception {
+ AccessibleValue av = ac.getAccessibleValue();
+ if (av == null) return null;
+ return av.getCurrentAccessibleValue();
+ }
+ }, ac);
+ if (value != null) {
+ String s = value.toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ }
+ } else {
+ debugString("getCurrentAccessibleValueFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the AccessibleValue maximum value from an AccessibleContext
+ * returned using a String 'cause the value is a java Number
+ *
+ */
+ private String getMaximumAccessibleValueFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ final Number value = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Number call() throws Exception {
+ AccessibleValue av = ac.getAccessibleValue();
+ if (av == null) return null;
+ return av.getMaximumAccessibleValue();
+ }
+ }, ac);
+ if (value != null) {
+ String s = value.toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ }
+ } else {
+ debugString("getMaximumAccessibleValueFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the AccessibleValue minimum value from an AccessibleContext
+ * returned using a String 'cause the value is a java Number
+ *
+ */
+ private String getMinimumAccessibleValueFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ final Number value = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Number call() throws Exception {
+ AccessibleValue av = ac.getAccessibleValue();
+ if (av == null) return null;
+ return av.getMinimumAccessibleValue();
+ }
+ }, ac);
+ if (value != null) {
+ String s = value.toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ }
+ } else {
+ debugString("getMinimumAccessibleValueFromContext; ac = null");
+ }
+ return null;
+ }
+
+
+ /* ===== AccessibleSelection methods ===== */
+
+ /**
+ * add to the AccessibleSelection of an AccessibleContext child i
+ *
+ */
+ private void addAccessibleSelectionFromContext(final AccessibleContext ac, final int i) {
+ try {
+ InvocationUtils.invokeAndWait(new Callable