diff options
Diffstat (limited to 'accessibility/workben/org/openoffice/accessibility/awb/tree')
10 files changed, 1179 insertions, 0 deletions
diff --git a/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityModel.java b/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityModel.java new file mode 100644 index 000000000000..159467778554 --- /dev/null +++ b/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityModel.java @@ -0,0 +1,154 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package org.openoffice.accessibility.awb.tree; + +import javax.swing.SwingUtilities; +import javax.swing.tree.TreeNode; +import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.DefaultMutableTreeNode; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.awt.XExtendedToolkit; +import com.sun.star.awt.XTopWindow; +import com.sun.star.awt.XTopWindowListener; +import com.sun.star.accessibility.AccessibleRole; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleEventBroadcaster; +import com.sun.star.accessibility.XAccessibleEventListener; + +/** + * + */ +public abstract class AccessibilityModel extends javax.swing.tree.DefaultTreeModel { + + protected java.util.Hashtable nodeList; + protected static DefaultMutableTreeNode disconnectedRootNode = + new DefaultMutableTreeNode("<not connected>"); + + /** Creates a new instance of AccessibilityModel */ + public AccessibilityModel() { + super(disconnectedRootNode, false); + nodeList = new java.util.Hashtable(); + } + + /* Convenience method that creates a new Toolkit node from xToolkit + * and sets as the new root object of the tree. + */ + public synchronized void setRoot(XExtendedToolkit xToolkit) { + if (xToolkit != null) { + try { + // remove old root node as topwindow listener + if (getRoot() instanceof ToolkitNode) { + ToolkitNode tn = (ToolkitNode) getRoot(); + if (tn.xToolkit != null) { + tn.xToolkit.removeTopWindowListener(tn); + } + } + nodeList.clear(); + setRoot(new ToolkitNode(xToolkit, this)); + xToolkit.addTopWindowListener((ToolkitNode) getRoot()); + } catch (com.sun.star.uno.RuntimeException e) { + // FIXME: error message ! + } + } + } + + /* Appends the new child to parent's child list */ + public void addNodeInto(MutableTreeNode newChild, MutableTreeNode parent) { + int index = parent.getChildCount(); + if (newChild != null && newChild.getParent() == parent) { + index -= 1; + } + insertNodeInto(newChild, parent, index); + } + + /** Adds listener to the listener chain of node */ + public static void addEventListener(TreeNode node, XAccessibleEventListener listener) { + if (node instanceof AccessibilityNode) { + ((AccessibilityNode) node).addEventListener(listener); + } + } + + /** Removes listener from the listener chain of node */ + public static void removeEventListener(TreeNode node, XAccessibleEventListener listener) { + if (node instanceof AccessibilityNode) { + ((AccessibilityNode) node).removeEventListener(listener); + } + } + + protected abstract AccessibilityNode createWindowNode(XAccessible xAccessible, + XAccessibleContext xAccessibleContext); + protected abstract AccessibilityNode createNode(XAccessible xAccessible); + + /** Adds xAccessible,node to the internal hashtable */ + public AccessibilityNode putNode(XAccessible xAccessible, AccessibilityNode node) { + if (xAccessible != null) { + String oid = UnoRuntime.generateOid(xAccessible); + java.lang.ref.WeakReference ref = (java.lang.ref.WeakReference) + nodeList.put(oid, new java.lang.ref.WeakReference(node)); + if (ref != null) { + return (AccessibilityNode) ref.get(); + } + } + return null; + } + + /** Returns the AccessibilityNode for xAccessible */ + public AccessibilityNode findNode(XAccessible xAccessible) { + if (xAccessible != null) { + String oid = UnoRuntime.generateOid(xAccessible); + java.lang.ref.WeakReference ref = + (java.lang.ref.WeakReference) nodeList.get(oid); + if (ref != null) { + return (AccessibilityNode) ref.get(); + } + } + return null; + } + + /** Removes the AccessibilityNode for xAccessible from the internal hashtable */ + public AccessibilityNode removeNode(XAccessible xAccessible) { + if (xAccessible != null) { + String oid = UnoRuntime.generateOid(xAccessible); + java.lang.ref.WeakReference ref = + (java.lang.ref.WeakReference) nodeList.remove(oid); + if (ref != null) { + return (AccessibilityNode) ref.get(); + } + } + return null; + } + + public AccessibilityNode removeNode(Object o) { + if (o instanceof XAccessible) { + return removeNode((XAccessible) o); + } + return null; + } +} diff --git a/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityNode.java b/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityNode.java new file mode 100644 index 000000000000..81a499aabf0d --- /dev/null +++ b/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityNode.java @@ -0,0 +1,163 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package org.openoffice.accessibility.awb.tree; + +import org.openoffice.accessibility.misc.AccessibleEventMulticaster; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.SwingUtilities; + +import com.sun.star.accessibility.AccessibleEventId; +import com.sun.star.accessibility.AccessibleEventObject; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleEventBroadcaster; +import com.sun.star.accessibility.XAccessibleEventListener; + +import com.sun.star.uno.UnoRuntime; + +class AccessibilityNode extends DefaultMutableTreeNode implements XAccessible, + XAccessibleEventListener, XAccessibleEventBroadcaster { + + protected AccessibilityModel treeModel; + protected XAccessibleContext unoAccessibleContext; + + private XAccessibleEventListener listener; + + public AccessibilityNode(AccessibilityModel treeModel) { + this.treeModel = treeModel; + } + + protected void finalize() throws java.lang.Throwable { + if (userObject != null) { + treeModel.removeNode(userObject); + } + } + + /** Sets the XAccessibleContext object of this node */ + public void setAccessibleContext(XAccessibleContext xAccessibleContext) { + unoAccessibleContext = xAccessibleContext; + } + + /** Returns the XAccessibleContext object of this node */ + public XAccessibleContext getAccessibleContext() { + return unoAccessibleContext; + } + + /** Attaches or Detaches the itself as listener to unoAccessibleContext */ + protected void setAttached(boolean attach) { + XAccessibleContext xAccessibleContext = unoAccessibleContext; + if (xAccessibleContext != null) { + try { + XAccessibleEventBroadcaster xAccessibleEventBroadcaster = + UnoRuntime.queryInterface( XAccessibleEventBroadcaster.class, xAccessibleContext ); + if (xAccessibleEventBroadcaster != null) { + if (attach) { + xAccessibleEventBroadcaster.addEventListener(this); + } else { + xAccessibleEventBroadcaster.removeEventListener(this); + } + } + } catch (com.sun.star.uno.RuntimeException e) { + // FIXME: error message ! + } + } + } + + public void disposing(com.sun.star.lang.EventObject eventObject) { + XAccessibleEventListener localListener = this.listener; + if (localListener != null) { + localListener.disposing(eventObject); + } + + treeModel.removeNode(userObject); + userObject = null; + unoAccessibleContext = null; + // FIXME: mark the object as being disposed in the tree view ! + } + + protected void handleChildRemoved(XAccessible xAccessible) { + final AccessibilityNode node = treeModel.findNode(xAccessible); + if (node != null) { + SwingUtilities.invokeLater(new java.lang.Runnable() { + public void run() { + treeModel.removeNodeFromParent(node); + } + }); + } + } + + protected void handleChildAdded(XAccessible xAccessible) { + final AccessibilityNode parent = this; + final AccessibilityNode node = treeModel.createNode(xAccessible); + if (node != null) { + SwingUtilities.invokeLater(new java.lang.Runnable() { + public void run() { + try { + XAccessibleContext xAC = node.getAccessibleContext(); + if (xAC != null) { + treeModel.insertNodeInto(node, parent, + xAC.getAccessibleIndexInParent()); + } + } catch (com.sun.star.uno.RuntimeException e) { + // FIXME: output + } + } + }); + } + } + + public void notifyEvent(AccessibleEventObject accessibleEventObject) { + if (accessibleEventObject.EventId == AccessibleEventId.CHILD) { + XAccessible xAccessible = UnoRuntime.queryInterface( XAccessible.class, accessibleEventObject.OldValue ); + if (xAccessible != null) { + handleChildRemoved(xAccessible); + } + + xAccessible = UnoRuntime.queryInterface( XAccessible.class, accessibleEventObject.NewValue ); + if (xAccessible != null) { + handleChildAdded(xAccessible); + } + } + + XAccessibleEventListener localListener = this.listener; + if (localListener != null) { + localListener.notifyEvent(accessibleEventObject); + } + } + + public synchronized void addEventListener(com.sun.star.accessibility.XAccessibleEventListener xAccessibleEventListener) { + listener = AccessibleEventMulticaster.add(listener, xAccessibleEventListener); + } + + public synchronized void removeEventListener(com.sun.star.accessibility.XAccessibleEventListener xAccessibleEventListener) { + listener = AccessibleEventMulticaster.remove(listener, xAccessibleEventListener); + } +} + + diff --git a/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityTree.java b/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityTree.java new file mode 100644 index 000000000000..e485c993706a --- /dev/null +++ b/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityTree.java @@ -0,0 +1,89 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package org.openoffice.accessibility.awb.tree; + +import org.openoffice.accessibility.misc.NameProvider; + +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.DefaultMutableTreeNode; + +import com.sun.star.awt.XExtendedToolkit; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; + +/** + * + */ +public class AccessibilityTree extends javax.swing.JTree { + + /** Creates a new instance of AccessibilityTree */ + public AccessibilityTree(javax.swing.tree.TreeModel model) { + super(model); + // always show handles to indicate expandable / collapsable + showsRootHandles = true; + } + + public void setToolkit(XExtendedToolkit xToolkit) { + AccessibilityModel model = (AccessibilityModel) getModel(); + if (model != null) { + // hide the root node when connected + setRootVisible(xToolkit == null); + // update the root node + model.setRoot(xToolkit); + model.reload(); + } + } + + public String convertValueToText(Object value, boolean selected, + boolean expanded, boolean leaf, int row, boolean hasFocus) { + + if (value instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; + + Object userObject = node.getUserObject(); + if (userObject != null && userObject instanceof XAccessible) { + XAccessible xAccessible = (XAccessible) userObject; + try { + XAccessibleContext xAC = xAccessible.getAccessibleContext(); + if (xAC != null) { + String name = xAC.getAccessibleName(); + if (name.length() == 0) { + name = new String ("<no name>"); + } + value = name + " / " + NameProvider.getRoleName(xAC.getAccessibleRole()); + } + } catch (com.sun.star.uno.RuntimeException e) { + value = "???"; + } + } + } + + return super.convertValueToText(value, selected, expanded, leaf, row, hasFocus); + } + +} diff --git a/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityTreeModel.java b/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityTreeModel.java new file mode 100644 index 000000000000..6069c8f5f5ee --- /dev/null +++ b/accessibility/workben/org/openoffice/accessibility/awb/tree/AccessibilityTreeModel.java @@ -0,0 +1,217 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package org.openoffice.accessibility.awb.tree; + +import com.sun.star.accessibility.XAccessible; +import com.sun.star.awt.XExtendedToolkit; +import com.sun.star.lang.DisposedException; +import com.sun.star.lang.IndexOutOfBoundsException; + +import org.openoffice.accessibility.misc.OfficeConnection; +import org.openoffice.accessibility.awb.event.EventQueue; + +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; + + +public class AccessibilityTreeModel + extends DefaultTreeModel +{ + public AccessibilityTreeModel () + { + super (null); + setAsksAllowsChildren (false); + + SetRootNode(); + } + + + + /** Release all resources. + */ + synchronized public void Dispose () + { + Clear (); + } + + + + /** Calls to this method are dispatched to the given node but are + observed for exceptions. + */ + synchronized public boolean isLeaf (Object aObject) + { + boolean bIsLeaf = true; + + if (aObject != null) + { + AccessibilityNode aNode = (AccessibilityNode)aObject; + try + { + bIsLeaf = aNode.isLeaf(); + } + catch (DisposedException aException) + { + System.out.println ("node is disposed. removing it"); + /* TreeNode aParent = aNode.GetParent(); + int nIndexInParent = aParent.getIndex (aNode); + aNode.removeFromParent (); + System.out.println ("" + aParent + " # " + aNode + " # "+ nIndexInParent); + nodesWereRemoved ( + aParent, new int[]{nIndexInParent}, new + Object[]{aNode}); + */ + } + catch (Exception aException) + { + System.err.println ("caught exception in AccessibilityTreeModel.isLeaf():" + + aException); + aException.printStackTrace (System.err); + } + } + + return bIsLeaf; + } + + + + + synchronized public int getChildCount (Object aObject) + { + AccessibilityNode aNode = (AccessibilityNode)aObject; + return aNode.getChildCount(); + } + + + + + /** Return the requested child of aParent. If that child is not yet + known to the parent then try to create it. + */ + synchronized public Object getChild (Object aParent, final int nIndex) + { + AccessibilityNode aChild = null; + + final AccessibilityNode aParentNode = (AccessibilityNode)aParent; + + // Try to get an existing child from the super class object. + aChild = aParentNode.GetChildNoCreate (nIndex); + + // When the requested child does not yet exist and this node is not a + // special node then create a new node. + if (aChild == null) + { + aChild = aParentNode.CreateChild (nIndex); + aParentNode.SetChild ((AccessibilityNode)aChild, nIndex); + /* EventQueue.Instance().AddEvent (new Runnable() { public void run() { + AccessibilityTreeModel.this.nodeWasInserted ( + aParentNode, nIndex); + }}); + */ } + + return aChild; + } + + + synchronized public void nodeWasInserted (AccessibilityNode aParent, int nIndex) + { + nodesWereInserted (aParent, new int[]{nIndex}); + nodeStructureChanged (aParent); + + } + + + + + /** Clear the tree so that afterwards it has only the root node. + */ + public void Clear () + { + AccessibilityNode aRoot = (AccessibilityNode)getRoot(); + aRoot.RemoveAllChildren(); + SetRootNode(); + nodeStructureChanged (aRoot); + } + + + + + private void SetRootNode () + { + OfficeConnection aConnection = OfficeConnection.Instance(); + AccessibilityNode aRoot; + if (aConnection!=null && aConnection.IsValid()) + aRoot = new AccessibilityNode ("<connected>"); + else + aRoot = new AccessibilityNode ("<not connected>"); + setRoot (aRoot); + } + + + + + /** Add a new child to the root node. + */ + public synchronized void AddTopLevelNode (AccessibilityNode aNode) + { + if (aNode != null) + { + if ( ! OfficeConnection.Instance().IsValid()) + { + setRoot (null); + } + + AccessibilityNode aRoot = (AccessibilityNode)getRoot(); + if (aRoot == null) + { + aRoot = new AccessibilityNode ("<connected>"); + setRoot (aRoot); + } + + aNode.SetParent (aRoot); + aRoot.Append (aNode); + nodesWereInserted (aRoot, new int[]{aRoot.getIndex (aNode)}); + } + } + + + + + /** Remove a node that is a direct child of the root. + */ + public synchronized void RemoveTopLevelNode (AccessibilityNode aNode) + { + AccessibilityNode aRoot = (AccessibilityNode)getRoot(); + if (aRoot != null) + { + int nIndex = aRoot.getIndex (aNode); + aRoot.Remove (aNode); + nodesWereRemoved (aRoot, new int[]{nIndex}, new Object[]{aNode}); + } + } +} diff --git a/accessibility/workben/org/openoffice/accessibility/awb/tree/DynamicAccessibilityModel.java b/accessibility/workben/org/openoffice/accessibility/awb/tree/DynamicAccessibilityModel.java new file mode 100644 index 000000000000..f2b4c6f0e97f --- /dev/null +++ b/accessibility/workben/org/openoffice/accessibility/awb/tree/DynamicAccessibilityModel.java @@ -0,0 +1,123 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package org.openoffice.accessibility.awb.tree; + +import javax.swing.tree.TreeNode; +import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeWillExpandListener; + +import com.sun.star.accessibility.AccessibleRole; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; + +/** + * + */ +public class DynamicAccessibilityModel extends AccessibilityModel implements TreeExpansionListener, TreeWillExpandListener { + + /* Creates a AccessibilityNode object for a window */ + protected AccessibilityNode createWindowNode(XAccessible xAccessible, + XAccessibleContext xAccessibleContext) { + if (xAccessible != null) { + // Some objects inherit XAccessible, but should not appear in + // the hierarchy as toplevels (like sub-menus), so they don't + // return an accessible context. + if (xAccessibleContext != null) { + AccessibilityNode node = new AccessibilityNode(this); + node.setUserObject(xAccessible); + node.setAccessibleContext(xAccessibleContext); + putNode(xAccessible, node); + return node; + } + } + return null; + } + + /* Creates a DynamicAccessibilityNode object */ + protected AccessibilityNode createNode(XAccessible xAccessible) { + if (xAccessible != null) { + try { + // Some objects inherit XAccessible, but should not appear in + // the hierarchy as toplevels (like sub-menus), so they don't + // return an accessible context. + XAccessibleContext xAccessibleContext = xAccessible.getAccessibleContext(); + if (xAccessibleContext != null) { + AccessibilityNode node = new DynamicAccessibilityNode(this); + node.setUserObject(xAccessible); + node.setAccessibleContext(xAccessibleContext); + putNode(xAccessible, node); + return node; + } + } catch (com.sun.star.uno.RuntimeException e) { + } + } + return null; + } + + public void treeCollapsed(javax.swing.event.TreeExpansionEvent treeExpansionEvent) { + TreeNode node = (TreeNode) treeExpansionEvent.getPath().getLastPathComponent(); + if (node instanceof DynamicAccessibilityNode) { + DynamicAccessibilityNode dynode = (DynamicAccessibilityNode) node; + dynode.clear(); + } + } + + public void treeExpanded(javax.swing.event.TreeExpansionEvent treeExpansionEvent) { + TreeNode node = (TreeNode) treeExpansionEvent.getPath().getLastPathComponent(); + if (node instanceof AccessibilityNode) { + // Calling oneway methods from an UNO thread may cause + // deadlocks, so adding the listeners here. + for (java.util.Enumeration e = node.children(); e.hasMoreElements(); ) { + ((AccessibilityNode) e.nextElement()).setAttached(true); + } + } + } + + public void treeWillCollapse(javax.swing.event.TreeExpansionEvent treeExpansionEvent) + throws javax.swing.tree.ExpandVetoException { + TreeNode node = (TreeNode) treeExpansionEvent.getPath().getLastPathComponent(); + if (node instanceof AccessibilityNode) { + // Calling oneway methods from an UNO thread may cause + // deadlocks, so adding the listeners here. + for (java.util.Enumeration e = node.children(); e.hasMoreElements(); ) { + ((AccessibilityNode) e.nextElement()).setAttached(false); + } + } + } + + public void treeWillExpand(javax.swing.event.TreeExpansionEvent treeExpansionEvent) + throws javax.swing.tree.ExpandVetoException { + TreeNode node = (TreeNode) treeExpansionEvent.getPath().getLastPathComponent(); + if (node instanceof DynamicAccessibilityNode) { + DynamicAccessibilityNode dynode = (DynamicAccessibilityNode) node; + dynode.populate(); + } + } +} diff --git a/accessibility/workben/org/openoffice/accessibility/awb/tree/DynamicAccessibilityNode.java b/accessibility/workben/org/openoffice/accessibility/awb/tree/DynamicAccessibilityNode.java new file mode 100644 index 000000000000..a982ad71c4d5 --- /dev/null +++ b/accessibility/workben/org/openoffice/accessibility/awb/tree/DynamicAccessibilityNode.java @@ -0,0 +1,92 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package org.openoffice.accessibility.awb.tree; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; + +/* + * This class is dynamic in the way that it does not contain any children + * until the node is going to be expanded. It also releases all children + * as soon as the node is collapsed again. + */ +class DynamicAccessibilityNode extends AccessibilityNode { + + public DynamicAccessibilityNode(AccessibilityModel treeModel) { + super(treeModel); + } + + // Populates the child list. Called by AccessibilityMode.treeWillExpand(). + protected void populate() { + try { + XAccessibleContext xAC = getAccessibleContext(); + if (xAC != null) { + int n = xAC.getAccessibleChildCount(); + for (int i=0; i<n; i++) { + XAccessible xAccessible = xAC.getAccessibleChild(i); + AccessibilityNode node = treeModel.findNode(xAccessible); + if (node == null) { + node = treeModel.createNode(xAccessible); + } + if (node != null) { + // NOTE: do not send any tree notifications here ! + add(node); + } + } + } + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + // This should never happen since we previously checked the child + // count. + // FIXME: error message + } catch (com.sun.star.uno.RuntimeException e) { + // FIXME: error message + } + } + + // Clears the child list. Called by AccessibilityModel.treeCollapsed(). + protected void clear() { + removeAllChildren(); + } + + /* This is called whenever the node is painted, no matter if collapsed + * or expanded. Making this a "life" value seems to be appropriate. + */ + public boolean isLeaf() { + try { + XAccessibleContext xAC = getAccessibleContext(); + if (xAC != null) { + return xAC.getAccessibleChildCount() == 0; + } + return true; + } catch (com.sun.star.uno.RuntimeException e) { + return true; + } + } + +} diff --git a/accessibility/workben/org/openoffice/accessibility/awb/tree/Makefile b/accessibility/workben/org/openoffice/accessibility/awb/tree/Makefile new file mode 100644 index 000000000000..579b8822ce76 --- /dev/null +++ b/accessibility/workben/org/openoffice/accessibility/awb/tree/Makefile @@ -0,0 +1,40 @@ +#************************************************************************* +# +# 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 +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +all : package + +ROOT=../../../../.. +PACKAGE = org.openoffice.accessibility.awb.tree +SUBDIRS = +include makefile.common + +include $(ROOT)/makefile.in + + +package : $(CLASS_FILES) + + diff --git a/accessibility/workben/org/openoffice/accessibility/awb/tree/ToolkitNode.java b/accessibility/workben/org/openoffice/accessibility/awb/tree/ToolkitNode.java new file mode 100644 index 000000000000..8eaa9dab6c02 --- /dev/null +++ b/accessibility/workben/org/openoffice/accessibility/awb/tree/ToolkitNode.java @@ -0,0 +1,215 @@ +/************************************************************************* + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package org.openoffice.accessibility.awb.tree; + +import com.sun.star.accessibility.AccessibleRole; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; + +import com.sun.star.awt.XExtendedToolkit; +import com.sun.star.awt.XTopWindow; + +import com.sun.star.uno.UnoRuntime; + +import javax.swing.SwingUtilities; +import javax.swing.tree.DefaultMutableTreeNode; + +/** + * + */ +public class ToolkitNode extends DefaultMutableTreeNode + implements com.sun.star.awt.XTopWindowListener { + + protected XExtendedToolkit xToolkit; + + private AccessibilityModel treeModel; + + /** Creates a new instance of TopWindowListener */ + public ToolkitNode(XExtendedToolkit xToolkit, AccessibilityModel treeModel) { + super("<connected>"); + this.xToolkit = xToolkit; + this.treeModel = treeModel; + + // Initially fill the child list + try { + for (int i=0,j=xToolkit.getTopWindowCount(); i<j; i++) { + XTopWindow xTopWindow = xToolkit.getTopWindow(i); + if (xTopWindow != null) { + AccessibilityNode an = getTopWindowNode(xTopWindow); + if (an != null) { + add(an); + // Calling oneway methods from an UNO thread may cause + // deadlocks, so adding the listeners here. + an.setAttached(true); + } + } + } + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + // This should never happen since we properly check the count + // before - anyway returning what we got so far. + } + } + + /** Returns an AccessibilityNode if xAccessible has a valid toplevel */ + private AccessibilityNode getTopWindowNode(XAccessible xAccessible) { + XAccessibleContext xAC = xAccessible.getAccessibleContext(); + if (xAC != null) { + short role = xAC.getAccessibleRole(); + if ((role == AccessibleRole.FRAME) || (role == AccessibleRole.DIALOG) || (role == AccessibleRole.WINDOW)) { + return treeModel.createWindowNode(xAccessible, xAC); + } + } + return null; + } + + /** Returns an AccessibilityNode if xAccessible has a valid toplevel */ + private AccessibilityNode getTopWindowNode(XAccessible xAccessible, XAccessibleContext xAC) { + if (xAC != null) { + short role = xAC.getAccessibleRole(); + if ((role == AccessibleRole.FRAME) || (role == AccessibleRole.DIALOG) || (role == AccessibleRole.WINDOW)) { + AccessibilityNode parent = treeModel.createWindowNode(xAccessible, xAC); + if (parent != null) { + try { + int n = xAC.getAccessibleChildCount(); + for (int i=0; i<n; i++) { + AccessibilityNode child = treeModel.createNode(xAC.getAccessibleChild(i)); + if (child != null) { + parent.add(child); + } + } + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + + } + } + return parent; + } + } + return null; + } + + /** Returns the XAccessible interface corresponding to the toplevel window */ + private AccessibilityNode getTopWindowNode(XTopWindow w) { + XAccessible xAccessible = (XAccessible) + UnoRuntime.queryInterface(XAccessible.class, w); + if (xAccessible != null) { + // XTopWindows usually have an accessible parent, which is the + // native container window .. + XAccessibleContext xAC = xAccessible.getAccessibleContext(); + if (xAC != null) { + XAccessible xParent = xAC.getAccessibleParent(); + if (xParent != null) { + AccessibilityNode parent = getTopWindowNode(xParent); + AccessibilityNode child = treeModel.createNode(xAccessible); + if (parent != null && child != null) { + parent.add(child); + } + return parent; + } else { + return getTopWindowNode(xAccessible, xAC); + } + } + } + return null; + } + + public void disposing(com.sun.star.lang.EventObject eventObject) { + // FIXME : message + // prevent setRoot from removing this as event listener + xToolkit = null; + treeModel.setRoot(treeModel.disconnectedRootNode); + } + + public void windowActivated(com.sun.star.lang.EventObject eventObject) { + } + + public void windowClosed(com.sun.star.lang.EventObject eventObject) { + XAccessible xAccessible = (XAccessible) UnoRuntime.queryInterface( + XAccessible.class, eventObject.Source); + if (xAccessible != null) { + AccessibilityNode node = treeModel.findNode(xAccessible); + + // The object implementing XTopWindow is often not the toplevel + // accessible object. + if (node != null && node.getParent() != this) { + node = (AccessibilityNode) node.getParent(); + } + + if (node != null) { + final AccessibilityNode an = node; + Runnable removeRun = new Runnable() { + public void run() { + try { + treeModel.removeNodeFromParent(an); + // Calling oneway methods from an UNO thread may cause + // deadlocks, so removing the listeners here. + an.setAttached(false); + } catch (IllegalArgumentException e) { + // for some toplevel we get more than one event - + // ignoring + } + } + }; + SwingUtilities.invokeLater(removeRun); + } + } + } + + public void windowClosing(com.sun.star.lang.EventObject eventObject) { + } + + public void windowDeactivated(com.sun.star.lang.EventObject eventObject) { + } + + public void windowMinimized(com.sun.star.lang.EventObject eventObject) { + } + + public void windowNormalized(com.sun.star.lang.EventObject eventObject) { + } + + public void windowOpened(com.sun.star.lang.EventObject eventObject) { + final XTopWindow xTopWindow = (XTopWindow) UnoRuntime.queryInterface( + XTopWindow.class, eventObject.Source); + if (xTopWindow != null) { + final ToolkitNode tn = this; + Runnable addNodeRun = new Runnable() { + public void run() { + // Note: UNO does not allow to make synchronous callbacks + // to oneway calls, so we have to fetch the node here. + AccessibilityNode an = getTopWindowNode(xTopWindow); + if (an != null) { + treeModel.addNodeInto(an, tn); + // Calling oneway methods from an UNO thread may cause + // deadlocks, so adding the listeners here. + an.setAttached(true); + } + } + }; + SwingUtilities.invokeLater(addNodeRun); + } + } +} diff --git a/accessibility/workben/org/openoffice/accessibility/awb/tree/makefile.common b/accessibility/workben/org/openoffice/accessibility/awb/tree/makefile.common new file mode 100644 index 000000000000..e44be51360e7 --- /dev/null +++ b/accessibility/workben/org/openoffice/accessibility/awb/tree/makefile.common @@ -0,0 +1,35 @@ +#************************************************************************* +# +# 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 +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +JARFILES = jurt.jar unoil.jar ridl.jar +JAVAFILES = \ + AccessibilityModel.java \ + AccessibilityNode.java \ + AccessibilityTree.java \ + DynamicAccessibilityModel.java \ + DynamicAccessibilityNode.java \ + ToolkitNode.java diff --git a/accessibility/workben/org/openoffice/accessibility/awb/tree/makefile.mk b/accessibility/workben/org/openoffice/accessibility/awb/tree/makefile.mk new file mode 100644 index 000000000000..0135ca9d6422 --- /dev/null +++ b/accessibility/workben/org/openoffice/accessibility/awb/tree/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# 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 +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJNAME = awb +PRJ = ..$/..$/..$/..$/..$/.. +TARGET = java_tree +PACKAGE = org$/openoffice$/accessibility$/awb$/tree + +USE_JAVAVER:=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +.IF "$(JAVAVER:s/.//)" >= "140" + +.INCLUDE : makefile.common + +JAVACLASSFILES= $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class) + +.ENDIF + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + |