/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org 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 Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ package org.openoffice.java.accessibility; import java.lang.ref.WeakReference; import javax.accessibility.Accessible; import javax.accessibility.AccessibleStateSet; import com.sun.star.uno.*; import com.sun.star.accessibility.*; import org.openoffice.java.accessibility.logging.XAccessibleEventLog; /** */ public class AccessibleObjectFactory { // This type is needed for conversions from/to uno Any public static final Type XAccessibleType = new Type(XAccessible.class); private static java.util.Hashtable objectList = new java.util.Hashtable(); private static java.awt.FocusTraversalPolicy focusTraversalPolicy = new FocusTraversalPolicy(); private static java.awt.EventQueue theEventQueue = java.awt.Toolkit.getDefaultToolkit(). getSystemEventQueue(); public static java.awt.EventQueue getEventQueue() { return theEventQueue; } public static void postFocusGained(java.awt.Component c) { getEventQueue().postEvent(new java.awt.event.FocusEvent(c, java.awt.event.FocusEvent.FOCUS_GAINED)); } public static void postWindowGainedFocus(java.awt.Window w) { postWindowEvent(w, java.awt.event.WindowEvent.WINDOW_GAINED_FOCUS); } public static void postWindowLostFocus(java.awt.Window w) { postWindowEvent(w, java.awt.event.WindowEvent.WINDOW_LOST_FOCUS); } public static void postWindowActivated(java.awt.Window w) { postWindowEvent(w, java.awt.event.WindowEvent.WINDOW_ACTIVATED); } public static void postWindowDeactivated(java.awt.Window w) { postWindowEvent(w, java.awt.event.WindowEvent.WINDOW_DEACTIVATED); } public static void postWindowOpened(java.awt.Window w) { postWindowEvent(w, java.awt.event.WindowEvent.WINDOW_OPENED); } public static void postWindowClosed(java.awt.Window w) { postWindowEvent(w, java.awt.event.WindowEvent.WINDOW_CLOSED); } public static void invokeAndWait() { try { theEventQueue.invokeAndWait( new java.lang.Runnable () { public void run() { } }); } catch (java.lang.reflect.InvocationTargetException e) { } catch (java.lang.InterruptedException e) { } } private static void postWindowEvent(java.awt.Window w, int i) { theEventQueue.postEvent(new java.awt.event.WindowEvent(w, i)); } public static java.awt.Component getAccessibleComponent(XAccessible xAccessible) { java.awt.Component c = null; if (xAccessible != null) { // Retrieve unique id for the original UNO object to be used as a hash key String oid = UnoRuntime.generateOid(xAccessible); // Check if we already have a wrapper object for this context synchronized (objectList) { WeakReference r = (WeakReference) objectList.get(oid); if(r != null) { c = (java.awt.Component) r.get(); } } } return c; } public static void addChild(java.awt.Container parent, Object any) { try { addChild(parent, (XAccessible) AnyConverter.toObject(XAccessibleType, any)); } catch (com.sun.star.lang.IllegalArgumentException e) { System.err.println(e.getClass().getName() + " caught: " + e.getMessage()); } } public static void addChild(java.awt.Container parent, XAccessible child) { try { if (child != null) { XAccessibleContext childAC = child.getAccessibleContext(); if (childAC != null) { XAccessibleStateSet stateSet = childAC.getAccessibleStateSet(); if (stateSet != null) { java.awt.Component c = getAccessibleComponent(child); // Re-use existing wrapper if possible, create a new one otherwise if (c != null) { // Seems to be already in child list if (parent.equals(c.getParent())) return; // Update general component states c.setEnabled(stateSet.contains(AccessibleStateType.ENABLED)); c.setVisible(stateSet.contains(AccessibleStateType.VISIBLE)); } else { c = createAccessibleComponentImpl(child, childAC, stateSet); } if (c != null) { if (c instanceof java.awt.Container) { populateContainer((java.awt.Container) c, childAC); } parent.add(c); // Simulate focus gained event for new child if (stateSet.contains(AccessibleStateType.FOCUSED)) { postFocusGained(c); } } } } } } catch (com.sun.star.uno.RuntimeException e) { System.err.println(e.getClass().getName() + " caught: " + e.getMessage()); e.printStackTrace(); } } protected static void removeChild(java.awt.Container parent, Object any) { try { XAccessible xAccessible = (XAccessible) AnyConverter.toObject(XAccessibleType, any); java.awt.Component c = getAccessibleComponent(xAccessible); if (c != null) { parent.remove(c); if (c instanceof java.awt.Container) { clearContainer((java.awt.Container) c); } } } catch (com.sun.star.lang.IllegalArgumentException e) { System.err.println(e.getClass().getName() + " caught: " + e.getMessage()); } } /** * Removes all children from the container parent */ protected static void clearContainer(java.awt.Container parent) { // Purge all children from this container int count = parent.getComponentCount(); for (int i = 0; i < count; i++) { java.awt.Component c = parent.getComponent(i); if (c instanceof java.awt.Container) { clearContainer((java.awt.Container) c); } } parent.removeAll(); } /** * Populates the given Container parent with wrapper objects for all children of parentAC. This method is * intended to be called when a container is added using a CHILDREN_CHANGED event. */ protected static void populateContainer(java.awt.Container parent, XAccessibleContext parentAC) { if (parentAC != null) { try { int childCount = parentAC.getAccessibleChildCount(); for (int i=0; i 0 ) c = new Container(javax.accessibility.AccessibleRole.PANEL, xAccessible, xAccessibleContext); else c = new Label(xAccessible, xAccessibleContext); break; case AccessibleRole.TEXT: c = new TextComponent(xAccessible, xAccessibleContext); break; case AccessibleRole.TEXT_FRAME: c = new Container(javax.accessibility.AccessibleRole.PANEL, xAccessible, xAccessibleContext); break; case AccessibleRole.TOGGLE_BUTTON: c = new ToggleButton(xAccessible, xAccessibleContext); break; case AccessibleRole.TOOL_BAR: c = new Container(javax.accessibility.AccessibleRole.TOOL_BAR, xAccessible, xAccessibleContext); break; case AccessibleRole.TOOL_TIP: c = new ToolTip(xAccessible, xAccessibleContext); break; case AccessibleRole.TREE: c = new Tree(xAccessible, xAccessibleContext); break; case AccessibleRole.VIEW_PORT: c = new Container(javax.accessibility.AccessibleRole.VIEWPORT, xAccessible, xAccessibleContext); break; default: System.err.println("Unmapped accessible object " + role); System.err.println("usually mapped to " + AccessibleRoleAdapter.getAccessibleRole(role)); c = new Container(AccessibleRoleAdapter.getAccessibleRole(role), xAccessible, xAccessibleContext); break; } if (c != null) { // Add the newly created object to the cache list synchronized (objectList) { objectList.put(c.toString(), new WeakReference(c)); if (Build.DEBUG) { // System.out.println("Object cache now contains " + objectList.size() + " objects."); } } AccessibleStateAdapter.setComponentState(c, xAccessibleStateSet); if (! Build.PRODUCT) { String property = System.getProperty("AccessBridgeLogging"); if ((property != null) && (property.indexOf("event") != -1)) { XAccessibleEventLog.addEventListener(xAccessibleContext, c); } } } return c; } protected static void disposing(java.awt.Component c) { if (c != null) { synchronized (objectList) { objectList.remove(c.toString()); } } } public static java.awt.Window getTopWindow(XAccessible xAccessible) { XAccessibleContext xAccessibleContext = xAccessible.getAccessibleContext(); if (xAccessibleContext != null) { short role = xAccessibleContext.getAccessibleRole(); XAccessibleStateSet xAccessibleStateSet = xAccessibleContext.getAccessibleStateSet(); XAccessibleComponent xAccessibleComponent = (XAccessibleComponent) UnoRuntime.queryInterface(XAccessibleComponent.class, xAccessibleContext); java.awt.Window w; if (role == AccessibleRole.DIALOG) { w = new Dialog(new Application(), xAccessibleContext.getAccessibleName(), xAccessibleStateSet.contains(AccessibleStateType.MODAL), xAccessibleComponent); } else if (role == AccessibleRole.ALERT) { w = new Alert(new Application(), xAccessibleContext.getAccessibleName(), xAccessibleStateSet.contains(AccessibleStateType.MODAL), xAccessibleComponent); } else if (role == AccessibleRole.FRAME) { w = new Frame(xAccessibleContext.getAccessibleName(), xAccessibleComponent); } else if (role == AccessibleRole.WINDOW) { java.awt.Window activeWindow = java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); if (activeWindow != null) { w = new Window(activeWindow, xAccessibleComponent); } else { if (Build.DEBUG) { System.err.println("no active frame found for Window: " + role); } return null; } } else { if (Build.DEBUG) { System.err.println("invalid role for toplevel window: " + role); } return null; } populateContainer(w, xAccessibleContext, w); w.setFocusTraversalPolicy(focusTraversalPolicy); w.setVisible(true); // Make the new window the focused one if it has an initialy focused object set. java.awt.Component c = ((NativeFrame) w).getInitialComponent(); if (c != null) { postWindowGainedFocus(w); } return w; } return null; } }