summaryrefslogtreecommitdiffstats
path: root/toolkit/test
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--toolkit/test/accessibility/AWB.sxwbin0 -> 9257 bytes
-rw-r--r--toolkit/test/accessibility/AccTreeNode.java346
-rw-r--r--toolkit/test/accessibility/AccessibilityTree.java379
-rw-r--r--toolkit/test/accessibility/AccessibilityTreeModel.java471
-rw-r--r--toolkit/test/accessibility/AccessibilityTreeModelBase.java140
-rw-r--r--toolkit/test/accessibility/AccessibilityWorkBench.java591
-rw-r--r--toolkit/test/accessibility/AccessibleActionHandler.java91
-rw-r--r--toolkit/test/accessibility/AccessibleActionNode.java67
-rw-r--r--toolkit/test/accessibility/AccessibleCellHandler.java168
-rw-r--r--toolkit/test/accessibility/AccessibleComponentHandler.java121
-rw-r--r--toolkit/test/accessibility/AccessibleContextHandler.java95
-rw-r--r--toolkit/test/accessibility/AccessibleEditableTextHandler.java53
-rw-r--r--toolkit/test/accessibility/AccessibleExtendedComponentHandler.java93
-rw-r--r--toolkit/test/accessibility/AccessibleHyperlinkHandler.java53
-rw-r--r--toolkit/test/accessibility/AccessibleHypertextHandler.java53
-rw-r--r--toolkit/test/accessibility/AccessibleImageHandler.java70
-rw-r--r--toolkit/test/accessibility/AccessibleRelationHandler.java115
-rw-r--r--toolkit/test/accessibility/AccessibleSelectionHandler.java145
-rw-r--r--toolkit/test/accessibility/AccessibleTableHandler.java103
-rw-r--r--toolkit/test/accessibility/AccessibleTextHandler.java821
-rw-r--r--toolkit/test/accessibility/AccessibleTreeHandler.java130
-rw-r--r--toolkit/test/accessibility/AccessibleTreeNode.java113
-rw-r--r--toolkit/test/accessibility/AccessibleUNOHandler.java126
-rw-r--r--toolkit/test/accessibility/Canvas.java463
-rw-r--r--toolkit/test/accessibility/CanvasShape.java290
-rw-r--r--toolkit/test/accessibility/ChildEventHandler.java66
-rw-r--r--toolkit/test/accessibility/ContextEventHandler.java70
-rw-r--r--toolkit/test/accessibility/EventHandler.java75
-rw-r--r--toolkit/test/accessibility/EventListener.java108
-rw-r--r--toolkit/test/accessibility/EventQueue.java140
-rw-r--r--toolkit/test/accessibility/GeometryEventHandler.java71
-rw-r--r--toolkit/test/accessibility/HelpWindow.java189
-rw-r--r--toolkit/test/accessibility/MessageArea.java131
-rw-r--r--toolkit/test/accessibility/NodeFactory.java142
-rw-r--r--toolkit/test/accessibility/NodeHandler.java133
-rw-r--r--toolkit/test/accessibility/NodeMap.java117
-rw-r--r--toolkit/test/accessibility/OfficeConnection.java98
-rw-r--r--toolkit/test/accessibility/Options.java122
-rw-r--r--toolkit/test/accessibility/QueuedListener.java70
-rw-r--r--toolkit/test/accessibility/QueuedTopWindowListener.java97
-rw-r--r--toolkit/test/accessibility/SelectionDialog.java203
-rw-r--r--toolkit/test/accessibility/SimpleOffice.java139
-rw-r--r--toolkit/test/accessibility/StringNode.java36
-rw-r--r--toolkit/test/accessibility/TableEventHandler.java58
-rw-r--r--toolkit/test/accessibility/TopWindowListener.java175
-rw-r--r--toolkit/test/accessibility/VectorNode.java74
-rw-r--r--toolkit/test/accessibility/about.html8
-rw-r--r--toolkit/test/accessibility/help.html91
-rw-r--r--toolkit/test/accessibility/jawb.mf3
-rw-r--r--toolkit/test/accessibility/news.html36
-rw-r--r--toolkit/test/accessibility/ov/ContextView.java140
-rw-r--r--toolkit/test/accessibility/ov/FocusView.java141
-rw-r--r--toolkit/test/accessibility/ov/ListeningObjectView.java80
-rw-r--r--toolkit/test/accessibility/ov/ObjectView.java80
-rw-r--r--toolkit/test/accessibility/ov/ObjectViewContainer.java152
-rw-r--r--toolkit/test/accessibility/ov/TextView.java133
-rw-r--r--toolkit/test/accessibility/tools/NameProvider.java276
57 files changed, 8551 insertions, 0 deletions
diff --git a/toolkit/test/accessibility/AWB.sxw b/toolkit/test/accessibility/AWB.sxw
new file mode 100644
index 000000000..57931aed1
--- /dev/null
+++ b/toolkit/test/accessibility/AWB.sxw
Binary files differ
diff --git a/toolkit/test/accessibility/AccTreeNode.java b/toolkit/test/accessibility/AccTreeNode.java
new file mode 100644
index 000000000..1ce467684
--- /dev/null
+++ b/toolkit/test/accessibility/AccTreeNode.java
@@ -0,0 +1,346 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleComponent;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleEditableText;
+import com.sun.star.accessibility.XAccessibleSelection;
+import com.sun.star.accessibility.XAccessibleTable;
+import com.sun.star.accessibility.XAccessibleText;
+import com.sun.star.uno.UnoRuntime;
+
+/**
+ * The node type for the AccessibleTreeModel.
+ * This implements all the child-handling based on the appropriate
+ * NodeHandlers. Trivial nodes can be implemented by any Object
+ * type.
+ */
+class AccTreeNode
+ extends AccessibleTreeNode
+{
+ private class HandlerDescriptor
+ {
+ private HandlerDescriptor (NodeHandler aHandler)
+ {
+ maHandler = aHandler;
+ mnChildCount = -1;
+ }
+ private NodeHandler maHandler;
+ private int mnChildCount;
+ }
+ /// NodeHandlers for this node
+ private ArrayList<HandlerDescriptor> maHandlers;
+
+ // The accessible context of this node.
+ private XAccessibleContext mxContext;
+ private XAccessibleComponent mxComponent;
+ private XAccessibleText mxText;
+ private XAccessibleTable mxTable;
+
+ public AccTreeNode (XAccessibleContext xContext, Object aDisplay, AccessibleTreeNode aParent)
+ {
+ super (aDisplay, aParent);
+
+ maHandlers = new ArrayList<HandlerDescriptor>(5);
+ mxContext = xContext;
+ }
+
+ /** Update the internal data extracted from the corresponding accessible
+ object. This is done by replacing every handler by a new one. An
+ update method at each handler would be better of course.
+ */
+ @Override
+ public void update ()
+ {
+ for (int i=0; i<maHandlers.size(); i++)
+ {
+ System.out.println ("replacing handler " + i);
+ HandlerDescriptor aDescriptor = maHandlers.get(i);
+ aDescriptor.maHandler = aDescriptor.maHandler.createHandler (mxContext);
+ aDescriptor.mnChildCount =
+ aDescriptor.maHandler.getChildCount ();
+ }
+ }
+
+ public XAccessibleContext getContext ()
+ {
+ return mxContext;
+ }
+
+ public XAccessibleComponent getComponent ()
+ {
+ if (mxComponent == null && mxContext != null)
+ mxComponent = UnoRuntime.queryInterface(
+ XAccessibleComponent.class, mxContext);
+ return mxComponent;
+ }
+
+ public XAccessibleText getText ()
+ {
+ if (mxText == null && mxContext != null)
+ mxText = UnoRuntime.queryInterface(
+ XAccessibleText.class, mxContext);
+ return mxText;
+ }
+
+ public XAccessibleEditableText getEditText ()
+ {
+ return UnoRuntime.queryInterface(
+ XAccessibleEditableText.class, mxContext);
+ }
+
+ public XAccessibleTable getTable ()
+ {
+ if (mxTable == null && mxContext != null)
+ mxTable = UnoRuntime.queryInterface(
+ XAccessibleTable.class, mxContext);
+ return mxTable;
+ }
+
+
+ public XAccessibleSelection getSelection ()
+ {
+ return UnoRuntime.queryInterface(
+ XAccessibleSelection.class, mxContext);
+ }
+
+ public void addHandler( NodeHandler aHandler )
+ {
+ if (aHandler != null)
+ maHandlers.add (new HandlerDescriptor (aHandler));
+ }
+
+
+ /** iterate over handlers and return child sum */
+ private HandlerDescriptor getHandlerDescriptor (int i)
+ {
+ HandlerDescriptor aDescriptor = maHandlers.get(i);
+ if (aDescriptor.mnChildCount < 0)
+ aDescriptor.mnChildCount =
+ aDescriptor.maHandler.getChildCount ();
+ return aDescriptor;
+ }
+
+ @Override
+ public int getChildCount()
+ {
+ int nChildCount = 0;
+ for (int i = 0; i < maHandlers.size(); i++)
+ {
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ nChildCount += aDescriptor.mnChildCount;
+ }
+ return nChildCount;
+ }
+
+ /** iterate over handlers until the child is found */
+ @Override
+ public AccessibleTreeNode getChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ if( nIndex >= 0 )
+ {
+ for(int i = 0; i < maHandlers.size(); i++)
+ {
+ // check if this handler has the child, and if not
+ // search with next handler
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ if (nIndex < aDescriptor.mnChildCount)
+ return aDescriptor.maHandler.getChild (this, nIndex);
+ else
+ nIndex -= aDescriptor.mnChildCount;
+ }
+ }
+ else
+ throw new IndexOutOfBoundsException();
+
+ // nothing found?
+ return null;
+ }
+
+ @Override
+ public AccessibleTreeNode getChildNoCreate (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ if( nIndex >= 0 )
+ {
+ for(int i = 0; i < maHandlers.size(); i++)
+ {
+ // check if this handler has the child, and if not
+ // search with next handler
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ if (nIndex < aDescriptor.mnChildCount)
+ return aDescriptor.maHandler.getChildNoCreate (nIndex);
+ else
+ nIndex -= aDescriptor.mnChildCount;
+ }
+ }
+ else
+ throw new IndexOutOfBoundsException();
+
+ // nothing found?
+ return null;
+ }
+
+ @Override
+ public boolean removeChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ boolean bStatus = false;
+ if (nIndex >= 0)
+ {
+ for (int i=0; i<maHandlers.size(); i++)
+ {
+ // check if this handler has the child, and if not
+ // search with next handler
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ if (nIndex < aDescriptor.mnChildCount)
+ {
+ bStatus = aDescriptor.maHandler.removeChild (nIndex);
+ aDescriptor.mnChildCount = aDescriptor.maHandler.getChildCount ();
+ break;
+ }
+ else
+ nIndex -= aDescriptor.mnChildCount;
+ }
+ }
+ else
+ throw new IndexOutOfBoundsException();
+
+ return bStatus;
+ }
+
+
+ @Override
+ public int indexOf (AccessibleTreeNode aNode)
+ {
+ int nBaseIndex = 0;
+ if (aNode != null)
+ {
+ for (int i=0; i<maHandlers.size(); i++)
+ {
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ int nIndex = aDescriptor.maHandler.indexOf (aNode);
+ if (nIndex >= 0)
+ return nBaseIndex + nIndex;
+ else
+ nBaseIndex += aDescriptor.mnChildCount;
+ }
+ }
+
+ return -1;
+ }
+
+ /** this node is a leaf if have no handlers, or is those
+ handlers show no children */
+ @Override
+ public boolean isLeaf()
+ {
+ return maHandlers.isEmpty();
+ }
+
+ @Override
+ public boolean equals (Object aOther)
+ {
+ return (this == aOther) || (aOther!=null && aOther.equals(mxContext));
+ }
+
+
+ /** iterate over handlers until the child is found */
+ public void getActions(java.util.List<String> aActions)
+ {
+ for(int i = 0; i < maHandlers.size(); i++)
+ {
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ NodeHandler aHandler = aDescriptor.maHandler;
+ String[] aHandlerActions = aHandler.getActions (this);
+ aActions.addAll(Arrays.asList(aHandlerActions));
+ }
+ }
+
+ @Override
+ public void performAction( int nIndex )
+ {
+ if( nIndex >= 0 )
+ {
+ for(int i = 0; i < maHandlers.size(); i++)
+ {
+ // check if this handler has the child, and if not
+ // search with next handler
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ NodeHandler aHandler = aDescriptor.maHandler;
+ int nCount = aHandler.getActions(this).length;
+ if( nCount > nIndex )
+ {
+ aHandler.performAction(this, nIndex );
+ return;
+ }
+ else
+ nIndex -= nCount;
+ }
+ }
+ }
+
+ /** Try to add the specified accessible object as new accessible child of the
+ AccessibleTreeHandler.
+ Note that child is used in another context than
+ it is used in the other methods of this class.
+ */
+ public AccessibleTreeNode addAccessibleChild (XAccessible xChild)
+ {
+ for(int i = 0; i < maHandlers.size(); i++)
+ {
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ if (aDescriptor.maHandler instanceof AccessibleTreeHandler)
+ {
+ AccessibleTreeHandler aHandler = (AccessibleTreeHandler)aDescriptor.maHandler;
+ AccessibleTreeNode aNode = aHandler.addAccessibleChild (this, xChild);
+ aDescriptor.mnChildCount = aHandler.getChildCount ();
+ return aNode;
+ }
+ }
+ return null;
+ }
+
+ public java.util.List<Integer> updateChildren (java.lang.Class class1, java.lang.Class<AccessibleExtendedComponentHandler> class2)
+ {
+ ArrayList<Integer> aChildIndices = new ArrayList<Integer>();
+ int nOffset = 0;
+ for(int i=0; i < maHandlers.size(); i++)
+ {
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ if ((class1.isInstance(aDescriptor.maHandler))
+ || (class2 !=null && class2.isInstance(aDescriptor.maHandler)))
+ {
+ aDescriptor.maHandler.update(this);
+ // Get updated number of children.
+ int nChildCount = aDescriptor.maHandler.getChildCount ();
+ aDescriptor.mnChildCount = nChildCount;
+ // Fill in the indices of the updated children.
+ for (int j=0; j<nChildCount; j++)
+ aChildIndices.add(j+nOffset);
+ }
+ nOffset += aDescriptor.mnChildCount;
+ }
+ return aChildIndices;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibilityTree.java b/toolkit/test/accessibility/AccessibilityTree.java
new file mode 100644
index 000000000..fdf44177a
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibilityTree.java
@@ -0,0 +1,379 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.awt.Cursor;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import javax.swing.AbstractAction;
+import javax.swing.JPopupMenu;
+import javax.swing.JTree;
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeExpansionListener;
+import javax.swing.event.TreeWillExpandListener;
+import javax.swing.tree.TreePath;
+
+import com.sun.star.accessibility.XAccessibleContext;
+
+
+
+/** This is the tree component that is responsible for displaying the
+ contents of the tree model on the screen.
+*/
+public class AccessibilityTree
+ implements TreeExpansionListener, TreeWillExpandListener
+{
+ /** Create a new accessibility tree. Use the specified message display
+ for displaying messages and the specified canvas to draw the
+ graphical representations of accessible objects on.
+ */
+ public AccessibilityTree ()
+ {
+ maTree = new JTree ();
+
+ AccessibilityTreeModel aModel =
+ new AccessibilityTreeModel (
+ new StringNode ("Please press Update button", null));
+ maTree.setModel (aModel);
+
+ maTree.addMouseListener (new MouseListener (this));
+
+ // Listen to expansions and collapses to change the mouse cursor.
+ mnExpandLevel = 0;
+ maTree.addTreeWillExpandListener (this);
+ maTree.addTreeExpansionListener (this);
+ }
+
+ public JTree getComponent ()
+ {
+ return maTree;
+ }
+
+ // Change cursor during expansions to show the user that this is a
+ // lengthy operation.
+ public void treeWillExpand (TreeExpansionEvent e)
+ {
+ if (mnExpandLevel == 0)
+ {
+ maTree.setCursor (new Cursor (Cursor.WAIT_CURSOR));
+ }
+ mnExpandLevel += 1;
+ }
+ public void treeWillCollapse (TreeExpansionEvent e)
+ {
+ if (mnExpandLevel == 0)
+ {
+ maTree.setCursor (new Cursor (Cursor.WAIT_CURSOR));
+ }
+ mnExpandLevel += 1;
+ }
+ public void treeExpanded (TreeExpansionEvent e)
+ {
+ mnExpandLevel -= 1;
+ if (mnExpandLevel == 0)
+ {
+ maTree.setCursor (new Cursor (Cursor.DEFAULT_CURSOR));
+ }
+ }
+ public void treeCollapsed (TreeExpansionEvent e)
+ {
+ mnExpandLevel -= 1;
+ if (mnExpandLevel == 0)
+ {
+ maTree.setCursor (new Cursor (Cursor.DEFAULT_CURSOR));
+ }
+ }
+
+
+
+ public void SetCanvas (Canvas aCanvas)
+ {
+ ((AccessibilityTreeModel)maTree.getModel()).setCanvas(aCanvas);
+ }
+
+ /** Expand the nodes in the subtree rooted in aNode according to the
+ specified expander. The tree is locked during the expansion.
+ */
+ private void expandTree (AccessibleTreeNode aNode, Expander aExpander)
+ {
+ if (mnExpandLevel == 0)
+ {
+ maTree.setEnabled (false);
+ }
+ mnExpandLevel += 1;
+
+ ((AccessibilityTreeModel)maTree.getModel()).lock ();
+
+ try
+ {
+ expandTree (new TreePath (aNode.createPath()), aExpander);
+ }
+ catch (Exception e)
+ {
+ // Ignore
+ }
+
+ mnExpandLevel -= 1;
+ if (mnExpandLevel == 0)
+ {
+ maTree.setEnabled (true);
+ ((AccessibilityTreeModel)maTree.getModel()).unlock (aNode);
+ }
+ }
+
+ private TreePath expandTree( TreePath aPath, Expander aExpander )
+ {
+ // return first expanded object
+ TreePath aFirst = null;
+
+ try
+ {
+ // get 'our' object
+ Object aObj = aPath.getLastPathComponent();
+
+ // expand this object, if the Expander tells us so
+ if( aExpander.expand( aObj ) )
+ {
+ maTree.expandPath (aPath);
+ aFirst = aPath;
+ }
+
+ // visit all children
+ if (aObj instanceof AccessibleTreeNode)
+ {
+ AccessibleTreeNode aNode = (AccessibleTreeNode)aObj;
+ int nLength = aNode.getChildCount();
+ for( int i = 0; i < nLength; i++ )
+ {
+ TreePath aRet = expandTree(
+ aPath.pathByAddingChild( aNode.getChild( i ) ),
+ aExpander );
+ if( aFirst == null )
+ aFirst = aRet;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception while expanding tree path "
+ + aPath + ": " + e);
+ e.printStackTrace ();
+ }
+
+ return aFirst;
+ }
+
+
+ /** Expand all nodes and their subtrees that represent shapes. Call
+ * this method from the outside. */
+ public void expandShapes ()
+ {
+ expandShapes ((AccessibleTreeNode)maTree.getModel().getRoot());
+ }
+ private void expandShapes (AccessibleTreeNode aNode)
+ {
+ expandTree (aNode, new ShapeExpander());
+ }
+
+ /** Expand all nodes */
+ public void expandAll ()
+ {
+ expandAll ((AccessibleTreeNode)maTree.getModel().getRoot());
+ }
+ private void expandAll (AccessibleTreeNode aNode)
+ {
+ expandTree (aNode, new AllExpander());
+ }
+
+
+
+ /*
+ public Dimension getPreferredSize ()
+ {
+ Dimension aPreferredSize = super.getPreferredSize();
+ Dimension aMinimumSize = super.getMinimumSize();
+ if (aPreferredSize.width < aMinimumSize.width)
+ aPreferredSize.width = aMinimumSize.width;
+ return aPreferredSize;
+ }
+ */
+
+ private class MouseListener extends MouseAdapter
+ {
+ public MouseListener (AccessibilityTree aTree)
+ {
+ maTree=aTree;
+ }
+ @Override
+ public void mousePressed(MouseEvent e) { popupTrigger(e); }
+ @Override
+ public void mouseClicked(MouseEvent e) { popupTrigger(e); }
+ @Override
+ public void mouseEntered(MouseEvent e) { popupTrigger(e); }
+ @Override
+ public void mouseExited(MouseEvent e) { popupTrigger(e); }
+ @Override
+ public void mouseReleased(MouseEvent e) { popupTrigger(e); }
+
+ private boolean popupTrigger( MouseEvent e )
+ {
+ boolean bIsPopup = e.isPopupTrigger();
+ if( !bIsPopup )
+ return false;
+
+ int selRow = maTree.getComponent().getRowForLocation(e.getX(), e.getY());
+ if (selRow == -1)
+ return bIsPopup;
+
+ TreePath aPath = maTree.getComponent().getPathForLocation(e.getX(), e.getY());
+
+ // check for actions
+ Object aObject = aPath.getLastPathComponent();
+ JPopupMenu aMenu = new JPopupMenu();
+ if( aObject instanceof AccTreeNode )
+ {
+ AccTreeNode aNode = (AccTreeNode)aObject;
+
+ ArrayList<String> aActions = new ArrayList<String>();
+ aMenu.add (new AccessibilityTree.ShapeExpandAction(maTree, aNode));
+ aMenu.add (new AccessibilityTree.SubtreeExpandAction(maTree, aNode));
+
+ aNode.getActions(aActions);
+ for( int i = 0; i < aActions.size(); i++ )
+ {
+ aMenu.add( new NodeAction(
+ aActions.get(i),
+ aNode, i ) );
+ }
+ }
+ else if (aObject instanceof AccessibleTreeNode)
+ {
+ AccessibleTreeNode aNode = (AccessibleTreeNode)aObject;
+ String[] aActionNames = aNode.getActions();
+ int nCount=aActionNames.length;
+ if (nCount > 0)
+ {
+ for (int i=0; i<nCount; i++)
+ aMenu.add( new NodeAction(
+ aActionNames[i],
+ aNode,
+ i));
+ }
+ else
+ aMenu = null;
+ }
+ if (aMenu != null)
+ aMenu.show (maTree.getComponent(),
+ e.getX(), e.getY());
+
+ return bIsPopup;
+ }
+
+ private final AccessibilityTree maTree;
+ }
+
+ private class NodeAction extends AbstractAction
+ {
+ private final int mnIndex;
+ private final AccessibleTreeNode maNode;
+
+ private NodeAction( String aName, AccessibleTreeNode aNode, int nIndex )
+ {
+ super( aName );
+ maNode = aNode;
+ mnIndex = nIndex;
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ maNode.performAction(mnIndex);
+ }
+ }
+
+ // This action expands all shapes in the subtree rooted in the specified node.
+ private class ShapeExpandAction extends AbstractAction
+ {
+ private final AccessibilityTree maTree;
+ private final AccTreeNode maNode;
+ public ShapeExpandAction (AccessibilityTree aTree, AccTreeNode aNode)
+ {
+ super ("Expand Shapes");
+ maTree = aTree;
+ maNode = aNode;
+ }
+ public void actionPerformed (ActionEvent e)
+ {
+ maTree.expandShapes (maNode);
+ }
+ }
+
+ // This action expands all nodes in the subtree rooted in the specified node.
+ private class SubtreeExpandAction extends AbstractAction
+ {
+ private final AccessibilityTree maTree;
+ private final AccTreeNode maNode;
+ public SubtreeExpandAction (AccessibilityTree aTree, AccTreeNode aNode)
+ {
+ super ("Expand Subtree");
+ maTree = aTree;
+ maNode = aNode;
+ }
+ public void actionPerformed (ActionEvent e)
+ {
+ maTree.expandAll (maNode);
+ }
+ }
+
+ /** Predicate class to determine whether a node should be expanded
+ * For use with expandTree method */
+ private abstract class Expander
+ {
+ abstract public boolean expand (Object aObject);
+ }
+
+ /** expand all nodes */
+ private class AllExpander extends Expander
+ {
+ @Override
+ public boolean expand(Object aObject) { return true; }
+ }
+
+ /** expand all nodes with accessibility roles > 100 */
+ private class ShapeExpander extends Expander
+ {
+ @Override
+ public boolean expand (Object aObject)
+ {
+ if (aObject instanceof AccTreeNode)
+ {
+ AccTreeNode aNode = (AccTreeNode)aObject;
+ XAccessibleContext xContext = aNode.getContext();
+ if (xContext != null && xContext.getAccessibleRole() >= 100)
+ return true;
+ }
+ return false;
+ }
+ }
+
+
+
+ private final JTree maTree;
+ private int mnExpandLevel;
+}
diff --git a/toolkit/test/accessibility/AccessibilityTreeModel.java b/toolkit/test/accessibility/AccessibilityTreeModel.java
new file mode 100644
index 000000000..b021746bc
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibilityTreeModel.java
@@ -0,0 +1,471 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.util.ArrayList;
+
+import javax.swing.event.TreeModelEvent;
+import javax.swing.tree.TreePath;
+
+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;
+
+public class AccessibilityTreeModel
+ extends AccessibilityTreeModelBase
+{
+ private boolean mbVerbose = false;
+
+ public AccessibilityTreeModel (AccessibleTreeNode aRoot)
+ {
+ // create default node (unless we have a 'proper' node)
+ setRoot (aRoot);
+
+ maNodeMap = new NodeMap();
+
+ mxListener = new QueuedListener(new EventListener (this));
+ }
+
+ public void clear ()
+ {
+ maNodeMap.Clear();
+ }
+
+ /** Lock the tree. While the tree is locked, events from the outside are
+ not processed. Lock the tree when you change its internal structure.
+ */
+ public void lock ()
+ {
+ mnLockCount += 1;
+ }
+
+ /** Unlock the tree. After unlocking the tree as many times as locking
+ it, a treeStructureChange event is sent to the event listeners.
+ @param aNodeHint
+ If not null and treeStructureChange events are thrown then this
+ node is used as root of the modified subtree.
+ */
+ public void unlock (AccessibleTreeNode aNodeHint)
+ {
+ mnLockCount -= 1;
+ if (mnLockCount == 0)
+ fireTreeStructureChanged (
+ new TreeModelEvent (this,
+ new TreePath (aNodeHint.createPath())));
+ }
+
+
+ @Override
+ public synchronized void setRoot (AccessibleTreeNode aRoot)
+ {
+ if (getRoot() == null)
+ super.setRoot (aRoot);
+ else
+ {
+ lock ();
+ maNodeMap.ForEach (new NodeMapCallback () {
+ @Override
+ public void Apply (AccTreeNode aNode)
+ {
+ if (maCanvas != null)
+ maCanvas.removeNode (aNode);
+ removeAccListener (aNode);
+ }
+ });
+ maNodeMap.Clear ();
+
+ setRoot (aRoot);
+ unlock (aRoot);
+ }
+ }
+
+
+
+ // child management:
+
+
+
+
+ /** Delegate the request to the parent and then register listeners at
+ the child and add the child to the canvas.
+ */
+ @Override
+ public synchronized Object getChild (Object aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = (AccessibleTreeNode)super.getChild (aParent, nIndex);
+
+ if (aChild == null)
+ System.out.println ("getChild: child not found");
+ else
+ // Keep translation table up-to-date.
+ addNode (aChild);
+
+ return aChild;
+ }
+
+ /** Remove a node (and all children) from the tree model.
+ */
+ private boolean removeChild (AccessibleTreeNode aNode)
+ {
+ try
+ {
+ if( aNode == null )
+ {
+ System.out.println ("can't remove null node");
+ return false;
+ }
+ else
+ {
+ // depth-first removal of children
+ while (aNode.getChildCount() > 0) {
+ if ( ! removeChild (aNode.getChildNoCreate (0)))
+ break;
+ }
+
+ // Remove node from its parent.
+ AccessibleTreeNode aParent = aNode.getParent();
+ if (aParent != null)
+ {
+ int nIndex = aParent.indexOf(aNode);
+ aParent.removeChild (nIndex);
+ }
+
+ maNodeMap.RemoveNode (aNode);
+ }
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception while removing child "
+ + aNode + " : " + e);
+ e.printStackTrace ();
+ return false;
+ }
+ return true;
+ }
+
+ public void removeNode (XAccessibleContext xNode)
+ {
+ if (xNode != null)
+ {
+ AccessibleTreeNode aNode = maNodeMap.GetNode (xNode);
+ AccessibleTreeNode aRootNode = (AccessibleTreeNode)getRoot();
+ TreeModelEvent aEvent = createEvent (aRootNode, aNode);
+ removeChild (aNode);
+ if (mbVerbose)
+ System.out.println (aNode);
+ fireTreeNodesRemoved (aEvent);
+ maCanvas.repaint ();
+ }
+ }
+
+
+ /** Add a new child to a parent.
+ @return
+ Returns the new or existing representation of the specified
+ accessible object.
+ */
+ private AccessibleTreeNode addChild (AccTreeNode aParentNode, XAccessible xNewChild)
+ {
+ AccessibleTreeNode aChildNode = null;
+ try
+ {
+ // First make sure that the accessible object does not already have
+ // a representation.
+ aChildNode = maNodeMap.GetNode(xNewChild);
+ if (aChildNode == null)
+ aChildNode = aParentNode.addAccessibleChild (xNewChild);
+ else
+ System.out.println ("node already present");
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception while adding child "
+ + xNewChild + " to parent " + aParentNode + ": " + e);
+ e.printStackTrace ();
+ }
+ return aChildNode;
+ }
+
+ public void addChild (XAccessibleContext xParent, XAccessible xChild)
+ {
+ AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent);
+ if (aParentNode instanceof AccTreeNode)
+ {
+ AccessibleTreeNode aChild = addChild ((AccTreeNode)aParentNode, xChild);
+ if (addNode (aChild))
+ {
+ if (maCanvas != null)
+ maCanvas.updateNode ((AccTreeNode)aParentNode);
+
+ // A call to fireTreeNodesInserted for xNew
+ // should be sufficient but at least the
+ // StringNode object that contains the number of
+ // children also changes and we do not know its
+ // index relative to its parent. Therefore the
+ // more expensive fireTreeStructureChanged is
+ // necessary.
+ fireTreeNodesInserted (createChildUpdateEvent (xParent));
+ updateNode (xParent, AccessibleTreeHandler.class);
+ }
+ maCanvas.repaint ();
+ }
+ }
+
+
+ /** Add the child node to the internal tree structure.
+ @param aNode
+ The node to insert into the internal tree structure.
+ */
+ private boolean addNode (AccessibleTreeNode aNode)
+ {
+ boolean bRet = false;
+ try
+ {
+ if ( ! maNodeMap.ValueIsMember (aNode))
+ {
+ if (aNode instanceof AccTreeNode)
+ {
+ AccTreeNode aChild = (AccTreeNode)aNode;
+ XAccessibleContext xChild = aChild.getContext();
+ registerAccListener (aChild);
+ if (maCanvas != null)
+ maCanvas.addNode (aChild);
+ maNodeMap.InsertNode (xChild, aChild);
+ }
+ bRet = true;
+ }
+
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception while adding node "
+ + aNode + ": " + e);
+ e.printStackTrace ();
+ }
+ return bRet;
+ }
+
+
+
+
+ /** create path to node, suitable for TreeModelEvent constructor
+ * @see javax.swing.event.TreeModelEvent#TreeModelEvent
+ */
+ private Object[] createPath (AccessibleTreeNode aNode)
+ {
+ ArrayList<AccessibleTreeNode> aPath = new ArrayList<AccessibleTreeNode>();
+ aNode.createPath (aPath);
+ return aPath.toArray();
+ }
+
+
+ // listeners (and helper methods)
+
+ // We are registered with listeners as soon as objects are in the
+ // tree cache, and we should get removed as soon as they are out.
+
+
+ private void fireTreeNodesChanged(TreeModelEvent e)
+ {
+ for(int i = 0; i < maTMListeners.size(); i++)
+ {
+ maTMListeners.get(i).treeNodesChanged(e);
+ }
+ }
+
+ protected void fireTreeNodesInserted(final TreeModelEvent e)
+ {
+ for(int i = 0; i < maTMListeners.size(); i++)
+ {
+ maTMListeners.get(i).treeNodesInserted(e);
+ }
+ }
+
+ private void fireTreeNodesRemoved(final TreeModelEvent e)
+ {
+ for(int i = 0; i < maTMListeners.size(); i++)
+ {
+ maTMListeners.get(i).treeNodesRemoved(e);
+ }
+ }
+
+ private void fireTreeStructureChanged(final TreeModelEvent e)
+ {
+ for(int i = 0; i < maTMListeners.size(); i++)
+ {
+ maTMListeners.get(i).treeStructureChanged(e);
+ }
+ }
+
+ /** Create a TreeModelEvent object that informs listeners that one child
+ has been removed from or inserted into its parent.
+ */
+ private TreeModelEvent createChildUpdateEvent (XAccessibleContext xParent)
+ {
+ AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent);
+ return createEvent (aParentNode, xParent);
+ }
+
+ private TreeModelEvent createEvent (AccessibleTreeNode aParentNode, XAccessibleContext xChild)
+ {
+ AccessibleTreeNode aChildNode = null;
+ if (xChild != null)
+ aChildNode = maNodeMap.GetNode (xChild);
+ return createEvent (aParentNode, aChildNode);
+ }
+
+
+
+ protected TreeModelEvent createEvent (
+ AccessibleTreeNode aParentNode,
+ AccessibleTreeNode aChildNode)
+ {
+ Object[] aPathToParent = createPath (aParentNode);
+
+ int nIndexInParent = -1;
+ if (aChildNode != null)
+ nIndexInParent = aParentNode.indexOf (aChildNode);
+ if (mbVerbose)
+ System.out.println (aChildNode + " " + nIndexInParent);
+
+ if (nIndexInParent == -1)
+ // This event may be passed only to treeStructureChanged of the listeners.
+ return new TreeModelEvent (this,
+ aPathToParent);
+ else
+ // General purpose event for removing or inserting known nodes.
+ return new TreeModelEvent (this,
+ aPathToParent,
+ new int[] {nIndexInParent},
+ new Object[] {aChildNode} );
+ }
+
+
+
+
+ /** Create a TreeModelEvent that indicates changes at those children of
+ the specified node with the specified indices.
+ */
+ private TreeModelEvent createChangeEvent (AccTreeNode aNode, java.util.List<Integer> aChildIndices)
+ {
+ // Build a list of child objects that are indicated by the given indices.
+ int nCount = aChildIndices.size();
+ Object aChildObjects[] = new Object[nCount];
+ int nChildIndices[] = new int[nCount];
+ for (int i=0; i<nCount; i++)
+ {
+ int nIndex = aChildIndices.get(i);
+ aChildObjects[i] = aNode.getChild (nIndex);
+ nChildIndices[i] = nIndex;
+ }
+
+ return new TreeModelEvent (this,
+ createPath(aNode),
+ nChildIndices,
+ aChildObjects);
+ }
+
+
+
+ private XAccessibleEventBroadcaster getBroadcaster (Object aObject)
+ {
+ if (aObject instanceof AccTreeNode)
+ return UnoRuntime.queryInterface (
+ XAccessibleEventBroadcaster.class, ((AccTreeNode)aObject).getContext());
+ else
+ return null;
+ }
+
+ private void registerAccListener( Object aObject )
+ {
+ // register this as listener for XAccessibleEventBroadcaster
+ // implementations
+ XAccessibleEventBroadcaster xBroadcaster = getBroadcaster( aObject );
+ if (xBroadcaster != null)
+ {
+ xBroadcaster.addAccessibleEventListener( mxListener );
+ }
+ }
+
+ private void removeAccListener( Object aObject )
+ {
+ XAccessibleEventBroadcaster xBroadcaster = getBroadcaster( aObject );
+ if (xBroadcaster != null)
+ {
+ xBroadcaster.removeAccessibleEventListener( mxListener );
+ }
+ }
+
+
+
+ public void setCanvas (Canvas aCanvas)
+ {
+ maCanvas = aCanvas;
+ }
+
+ public Canvas getCanvas ()
+ {
+ return maCanvas;
+ }
+
+ public void updateNode (XAccessibleContext xSource, java.lang.Class class1)
+ {
+ updateNode (xSource, class1,null);
+ }
+
+ /** Get a list of children of the node associated with xSource that are
+ affected by the given handlers. Fire events that these children may
+ have changed in the tree view. Update the canvas representation of
+ xSource.
+ */
+ public AccTreeNode updateNode (XAccessibleContext xSource,
+ java.lang.Class class1, java.lang.Class<AccessibleExtendedComponentHandler> class2)
+ {
+ AccessibleTreeNode aTreeNode = maNodeMap.GetNode (xSource);
+ AccTreeNode aNode = null;
+ if (mbVerbose)
+ System.out.println ("updating node " + xSource + " " + aTreeNode);
+ if (aTreeNode instanceof AccTreeNode)
+ {
+ aNode = (AccTreeNode) aTreeNode;
+ // Get list of affected children.
+ java.util.List<Integer> aChildIndices = aNode.updateChildren (
+ class1, class2);
+ // Fire events that these children may have changed.
+ fireTreeNodesChanged (
+ createChangeEvent (aNode, aChildIndices));
+ }
+ return aNode;
+ }
+
+ /** The listener to be registered with the accessible objects.
+ * Could be set to 'this' for same-thread event delivery, or to an
+ * instance of QueuedListener for multi-threaded delivery. May
+ * not be changed, since this would trip the
+ * register/removeAccListener logic. */
+ private final XAccessibleEventListener mxListener;
+
+ // Map to translate from accessible object to corresponding tree node.
+ private final NodeMap maNodeMap;
+
+ // If the lock count is higher then zero, then no events are processed.
+ private int mnLockCount;
+
+ private Canvas maCanvas;
+}
diff --git a/toolkit/test/accessibility/AccessibilityTreeModelBase.java b/toolkit/test/accessibility/AccessibilityTreeModelBase.java
new file mode 100644
index 000000000..5ff2d96c9
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibilityTreeModelBase.java
@@ -0,0 +1,140 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.util.ArrayList;
+
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+
+public class AccessibilityTreeModelBase
+ implements TreeModel
+{
+ public AccessibilityTreeModelBase ()
+ {
+ setRoot (null);
+ maTMListeners = new ArrayList<TreeModelListener>();
+ }
+
+ public synchronized void addTreeModelListener(TreeModelListener l)
+ {
+ maTMListeners.add(l);
+ }
+
+ public synchronized void removeTreeModelListener(TreeModelListener l)
+ {
+ maTMListeners.remove(l);
+ }
+
+ public synchronized int getChildCount(Object aParent)
+ {
+ return (aParent instanceof AccessibleTreeNode) ?
+ ((AccessibleTreeNode)aParent).getChildCount() : 0;
+ }
+
+ public synchronized Object getChild (Object aParent, int nIndex)
+ {
+ Object aChild = null;
+ try
+ {
+ if (aParent instanceof AccessibleTreeNode)
+ aChild = ((AccessibleTreeNode)aParent).getChild(nIndex);
+ else
+ System.out.println ("getChild called for unknown parent node");
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException e)
+ {
+ aChild = ("no child " + nIndex + " from " + aParent + ": " + e);
+ }
+ return aChild;
+ }
+
+ public synchronized Object getChildNoCreate (Object aParent, int nIndex)
+ {
+ Object aChild = null;
+ try
+ {
+ if (aParent instanceof AccessibleTreeNode)
+ aChild = ((AccessibleTreeNode)aParent).getChildNoCreate(nIndex);
+ else
+ System.out.println ("getChild called for unknown parent node");
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException e)
+ { }
+ return aChild;
+ }
+
+ /** iterate over all children and look for child */
+ public synchronized int getIndexOfChild (Object aParent, Object aChild)
+ {
+ int nIndex = -1;
+ try
+ {
+ if ((aParent instanceof AccessibleTreeNode) && (aChild instanceof AccessibleTreeNode))
+ {
+ AccessibleTreeNode aParentNode = (AccessibleTreeNode) aParent;
+ AccessibleTreeNode aChildNode = (AccessibleTreeNode) aChild;
+
+ int nChildCount = aParentNode.getChildCount();
+ for( int i = 0; i < nChildCount; i++ )
+ {
+ if (aChildNode.equals (aParentNode.getChild (i)))
+ {
+ nIndex = i;
+ break;
+ }
+ }
+ }
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException e)
+ {
+ // Return -1 by falling through.
+ }
+
+ // not found?
+ return nIndex;
+ }
+
+ public boolean isLeaf (Object aNode)
+ {
+ return (aNode instanceof AccessibleTreeNode) ?
+ ((AccessibleTreeNode)aNode).isLeaf() : true;
+ }
+
+
+
+ public synchronized Object getRoot()
+ {
+ return maRoot;
+ }
+
+ public void valueForPathChanged(TreePath path, Object newValue)
+ { }
+
+ protected synchronized void setRoot (AccessibleTreeNode aRoot)
+ {
+ maRoot = aRoot;
+ }
+
+
+ // The list of TreeModelListener objects.
+ protected ArrayList<TreeModelListener> maTMListeners;
+
+ // The root node of the tree. Use setRoot to change it.
+ private AccessibleTreeNode maRoot = null;
+}
diff --git a/toolkit/test/accessibility/AccessibilityWorkBench.java b/toolkit/test/accessibility/AccessibilityWorkBench.java
new file mode 100644
index 000000000..918b8cf6d
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibilityWorkBench.java
@@ -0,0 +1,591 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.frame.XFrame;
+import com.sun.star.frame.XTerminateListener;
+import com.sun.star.uno.UnoRuntime;
+
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.awt.XExtendedToolkit;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.event.TreeSelectionEvent;
+import ov.ObjectViewContainer;
+
+/** This class manages the GUI of the work bench.
+ @see AccessibilityTreeModel
+ for the implementation of the tree view on the left side which also
+ manages the registration of accessibility listeners.
+ @see Canvas
+ for the graphical view of the accessible objects.
+*/
+public class AccessibilityWorkBench
+ extends JFrame
+ implements ActionListener, XTerminateListener, TreeSelectionListener
+
+{
+ private static final String msVersion = "v1.7.2";
+ private String msOptionsFileName = ".AWBrc";
+
+ public static void main (String args[])
+ {
+ int nPortNumber = 5678;
+
+ for (int i=0; i<args.length; i++)
+ {
+ if (args[i].equals ("-h") || args[i].equals ("--help") || args[i].equals ("-?"))
+ {
+ System.out.println ("usage: AccessibilityWorkBench <option>*");
+ System.out.println ("options:");
+ System.out.println (" -p <port-number> Port on which to connect to StarOffice.");
+ System.out.println (" Defaults to 5678.");
+ System.exit (0);
+ }
+ else if (args[i].equals ("-p"))
+ {
+ nPortNumber = Integer.parseInt (args[++i]);
+ }
+ }
+
+ saWorkBench = new AccessibilityWorkBench (nPortNumber);
+ }
+
+
+
+
+ /** Return the one instance of the AccessibilityWorkBench
+ @return
+ Returns null when the AccessibilityWorkBench could not be
+ created successfully.
+ */
+ public static AccessibilityWorkBench Instance ()
+ {
+ return saWorkBench;
+ }
+
+
+
+ /** Create an accessibility work bench that listens at the specified
+ port to Office applications.
+ */
+ private AccessibilityWorkBench (int nPortNumber)
+ {
+ mbInitialized = false;
+
+ Layout ();
+
+ MessageArea.println (System.getProperty ("os.name") + " / "
+ + System.getProperty ("os.arch") + " / "
+ + System.getProperty ("os.version"));
+ MessageArea.println ("Using port " + nPortNumber);
+ office = new SimpleOffice (nPortNumber);
+
+ maAccessibilityTree.getComponent().addTreeSelectionListener (this);
+
+ addWindowListener (new WindowAdapter ()
+ { @Override
+ public void windowClosing (WindowEvent e)
+ { System.exit(0); }
+ });
+
+ initialize ();
+ }
+
+
+
+
+ /** Create and arrange the widgets of the GUI.
+ */
+ private void Layout ()
+ {
+ setSize (new Dimension (8000,600));
+
+ // Create new layout.
+ GridBagLayout aLayout = new GridBagLayout ();
+ getContentPane().setLayout (aLayout);
+
+ // Accessible Tree.
+ maAccessibilityTree = new AccessibilityTree ();
+ JScrollPane aTreeScrollPane = new JScrollPane(
+ maAccessibilityTree.getComponent(),
+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ aTreeScrollPane.setPreferredSize (new Dimension (400,300));
+
+ // Object view shows details about the currently selected accessible
+ // object.
+ maObjectViewContainer = new ObjectViewContainer ();
+ JScrollPane aObjectViewContainerScrollPane = new JScrollPane(
+ maObjectViewContainer,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ aObjectViewContainerScrollPane.setPreferredSize (new Dimension (400,300));
+
+ // Split pane for tree view and object view.
+ JSplitPane aLeftViewSplitPane = new JSplitPane (
+ JSplitPane.VERTICAL_SPLIT,
+ aTreeScrollPane,
+ aObjectViewContainerScrollPane
+ );
+ aLeftViewSplitPane.setDividerLocation (300);
+
+ // Canvas.
+ maCanvas = new Canvas ();
+ maCanvas.setTree (maAccessibilityTree.getComponent());
+ maAccessibilityTree.SetCanvas (maCanvas);
+ JScrollPane aScrolledCanvas = new JScrollPane(maCanvas,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ aScrolledCanvas.getViewport().setBackground (Color.RED);
+ aScrolledCanvas.setPreferredSize (new Dimension(600,400));
+
+ // Split pane for tree view and canvas.
+ JSplitPane aViewSplitPane = new JSplitPane (
+ JSplitPane.HORIZONTAL_SPLIT,
+ aLeftViewSplitPane,
+ aScrolledCanvas
+ );
+ aViewSplitPane.setOneTouchExpandable(true);
+ aViewSplitPane.setDividerLocation (400);
+
+ // Text output area.
+ MessageArea aMessageArea = MessageArea.Instance ();
+
+ // Split pane for the two views and the message area.
+ JSplitPane aSplitPane = new JSplitPane (JSplitPane.VERTICAL_SPLIT,
+ aViewSplitPane, aMessageArea);
+ aSplitPane.setOneTouchExpandable(true);
+ addGridElement (aViewSplitPane, 0,0, 2,1, 3,3,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH);
+
+ // Button bar.
+ maButtonBar = new JPanel();
+ maButtonBar.setLayout (new FlowLayout());
+ addGridElement (maButtonBar, 0,3, 2,1, 1,0,
+ GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL);
+
+ // Buttons.
+ aConnectButton = createButton ("Connect", "connect");
+ aUpdateButton = createButton ("Update", "update");
+ aShapesButton = createButton ("Expand Shapes", "shapes");
+ aExpandButton = createButton ("Expand All", "expand");
+ aQuitButton = createButton ("Quit", "quit");
+ UpdateButtonStates ();
+
+ Options.Instance().Load (msOptionsFileName);
+
+ setJMenuBar (CreateMenuBar ());
+
+ setTitle("Accessibility Workbench " + msVersion);
+
+ pack ();
+ setVisible (true);
+ validate ();
+ repaint();
+ }
+
+
+
+
+ /** Shortcut method for adding an object to a GridBagLayout.
+ */
+ private void addGridElement (JComponent object,
+ int x, int y, int width, int height, int weightx, int weighty,
+ int anchor, int fill)
+ {
+ GridBagConstraints constraints = new GridBagConstraints ();
+ constraints.gridx = x;
+ constraints.gridy = y;
+ constraints.gridwidth = width;
+ constraints.gridheight = height;
+ constraints.weightx = weightx;
+ constraints.weighty = weighty;
+ constraints.anchor = anchor;
+ constraints.fill = fill;
+ getContentPane().add (object, constraints);
+ }
+
+
+
+
+ /** Create a new button and place at the right most position into the
+ button bar.
+ */
+ private JButton createButton (String title, String command)
+ {
+ JButton aButton = new JButton (title);
+ aButton.setEnabled (false);
+ aButton.setActionCommand (command);
+ aButton.addActionListener (this);
+
+ maButtonBar.add (aButton);
+ return aButton;
+ }
+
+
+
+
+ /** Create a menu bar for the application.
+ @return
+ Returns the new menu bar. The returned reference is also
+ remembered in the data member <member>maMenuBar</member>.
+ */
+ private JMenuBar CreateMenuBar ()
+ {
+ // Menu bar.
+ JMenuBar aMenuBar = new JMenuBar ();
+
+ // File menu.
+ JMenu aFileMenu = new JMenu ("File");
+ aMenuBar.add (aFileMenu);
+ JMenuItem aItem;
+ aItem = new JMenuItem ("Quit");
+ aFileMenu.add (aItem);
+ aItem.addActionListener (this);
+
+ // View menu.
+ JMenu aViewMenu = new JMenu ("View");
+ aMenuBar.add (aViewMenu);
+ ButtonGroup aGroup = new ButtonGroup ();
+ JRadioButtonMenuItem aRadioButton = new JRadioButtonMenuItem ("Whole Screen");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+ aRadioButton = new JRadioButtonMenuItem ("200%");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+ aRadioButton = new JRadioButtonMenuItem ("100%");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+ aRadioButton = new JRadioButtonMenuItem ("50%");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+ aRadioButton = new JRadioButtonMenuItem ("25%");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+ aRadioButton = new JRadioButtonMenuItem ("10%");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+
+ // Options menu.
+ JMenu aOptionsMenu = new JMenu ("Options");
+ aMenuBar.add (aOptionsMenu);
+ JCheckBoxMenuItem aCBItem;
+ aCBItem = new JCheckBoxMenuItem ("Show Descriptions", maCanvas.getShowDescriptions());
+ aOptionsMenu.add (aCBItem);
+ aCBItem.addActionListener (this);
+
+ aCBItem = new JCheckBoxMenuItem ("Show Names", maCanvas.getShowNames());
+ aOptionsMenu.add (aCBItem);
+ aCBItem.addActionListener (this);
+
+ aCBItem = new JCheckBoxMenuItem ("Show Text", maCanvas.getShowText());
+ aOptionsMenu.add (aCBItem);
+ aCBItem.addActionListener (this);
+
+ aCBItem = new JCheckBoxMenuItem ("Antialiased Rendering", maCanvas.getAntialiasing());
+ aOptionsMenu.add (aCBItem);
+ aCBItem.addActionListener (this);
+
+ // Help menu.
+ JMenu aHelpMenu = new JMenu ("Help");
+ aMenuBar.add (aHelpMenu);
+
+ aItem = new JMenuItem ("Help");
+ aHelpMenu.add (aItem);
+ aItem.addActionListener (this);
+
+ aItem = new JMenuItem ("News");
+ aHelpMenu.add (aItem);
+ aItem.addActionListener (this);
+
+ aItem = new JMenuItem ("About");
+ aHelpMenu.add (aItem);
+ aItem.addActionListener (this);
+
+ return aMenuBar;
+ }
+
+
+
+
+ /** Initialize the AWB. This includes clearing the canvas, add
+ listeners, creation of a new tree model for the tree list box and
+ the update of the button states.
+
+ This method may be called any number of times. Note that all
+ actions will be carried out every time. The main purpose of a
+ second call is that of a re-initialization after a reconnect.
+ */
+ private void initialize ()
+ {
+ maCanvas.clear();
+
+ AccessibilityTreeModel aModel = null;
+ aModel = new AccessibilityTreeModel (createTreeModelRoot());
+
+ aModel.setCanvas (maCanvas);
+ maAccessibilityTree.getComponent().setModel (aModel);
+
+ if (office != null)
+ {
+ // Add terminate listener.
+ if (office.getDesktop() != null)
+ office.getDesktop().addTerminateListener (this);
+
+ XExtendedToolkit xToolkit = office.getExtendedToolkit();
+ // Remove old top window listener.
+ if (maTopWindowListener != null)
+ xToolkit.removeTopWindowListener (maQueuedTopWindowListener);
+ // Add top window listener.
+ if (xToolkit != null)
+ {
+ MessageArea.println ("registering at extended toolkit");
+ maTopWindowListener = new TopWindowListener (aModel, office);
+ maQueuedTopWindowListener = new QueuedTopWindowListener (maTopWindowListener);
+ xToolkit.addTopWindowListener (maQueuedTopWindowListener);
+ maTopWindowListener.Initialize ();
+ }
+ else
+ maTopWindowListener = null;
+ }
+
+ mbInitialized = true;
+ UpdateButtonStates ();
+ }
+
+
+
+
+ /** Update the states of the buttons according to the internal state of
+ the AWB.
+ */
+ private void UpdateButtonStates ()
+ {
+ aConnectButton.setEnabled (mbInitialized);
+ aQuitButton.setEnabled (mbInitialized);
+ aUpdateButton.setEnabled (mbInitialized);
+ aExpandButton.setEnabled (mbInitialized);
+ aShapesButton.setEnabled (mbInitialized);
+ }
+
+
+
+ /** Callback for GUI actions from the buttons.
+ */
+ public void actionPerformed (java.awt.event.ActionEvent e)
+ {
+ if (e.getActionCommand().equals("connect"))
+ {
+ office.connect();
+ initialize ();
+ }
+ else if (e.getActionCommand().equals("quit"))
+ {
+ AccessibilityTreeModel aModel = (AccessibilityTreeModel)maAccessibilityTree.getComponent().getModel();
+ aModel.clear();
+ System.exit (0);
+ }
+ else if (e.getActionCommand().equals("update"))
+ {
+ initialize ();
+ }
+ else if (e.getActionCommand().equals("shapes"))
+ {
+ Cursor aCursor = getCursor();
+ setCursor (new Cursor (Cursor.WAIT_CURSOR));
+ maAccessibilityTree.expandShapes();
+ setCursor (aCursor);
+ }
+ else if (e.getActionCommand().equals("expand"))
+ {
+ Cursor aCursor = getCursor();
+ setCursor (new Cursor (Cursor.WAIT_CURSOR));
+ maAccessibilityTree.expandAll();
+ setCursor (aCursor);
+ }
+ else if (e.getActionCommand().equals ("Quit"))
+ {
+ System.out.println ("exiting");
+ System.exit (0);
+ }
+ else if (e.getActionCommand().equals ("Show Descriptions"))
+ {
+ maCanvas.setShowDescriptions ( ! maCanvas.getShowDescriptions());
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("Show Names"))
+ {
+ maCanvas.setShowNames ( ! maCanvas.getShowNames());
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("Antialiased Rendering"))
+ {
+ maCanvas.setAntialiasing ( ! maCanvas.getAntialiasing());
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("Help"))
+ {
+ HelpWindow.Instance().loadFile ("help.html");
+ }
+ else if (e.getActionCommand().equals ("News"))
+ {
+ try{
+ HelpWindow.Instance().loadFile ("news.html");
+ } catch (Exception ex) {}
+ }
+ else if (e.getActionCommand().equals ("About"))
+ {
+ HelpWindow.Instance().loadFile ("about.html");
+ }
+ else if (e.getActionCommand().equals ("Whole Screen"))
+ {
+ maCanvas.setZoomMode (Canvas.WHOLE_SCREEN);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("200%"))
+ {
+ maCanvas.setZoomMode (200);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("100%"))
+ {
+ maCanvas.setZoomMode (100);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("50%"))
+ {
+ maCanvas.setZoomMode (50);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("25%"))
+ {
+ maCanvas.setZoomMode (25);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("10%"))
+ {
+ maCanvas.setZoomMode (10);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else
+ {
+ System.err.println("unknown command " + e.getActionCommand());
+ }
+ }
+
+
+
+
+ /** Create an AccessibilityTreeModel root which contains the documents
+ (top windows) that are present at the moment.
+ */
+ private AccessibleTreeNode createTreeModelRoot()
+ {
+ // create root node
+ VectorNode aRoot = new VectorNode ("Accessibility Tree", null);
+ if (maTopWindowListener != null)
+ maTopWindowListener.Initialize ();
+ return aRoot;
+ }
+
+
+ // TreeSelectionListener
+ public void valueChanged (TreeSelectionEvent aEvent)
+ {
+ TreePath aPath = aEvent.getPath();
+ Object aObject = aPath.getLastPathComponent();
+ if (aObject instanceof AccTreeNode)
+ {
+ AccTreeNode aNode = (AccTreeNode) aObject;
+ XAccessibleContext xContext = aNode.getContext();
+ maObjectViewContainer.SetObject (xContext);
+ }
+ }
+
+
+
+
+ // XEventListener
+ public void disposing( com.sun.star.lang.EventObject aSourceObj )
+ {
+ XFrame xFrame = UnoRuntime.queryInterface(XFrame.class, aSourceObj.Source);
+
+ if( xFrame != null )
+ System.out.println("frame disposed");
+ else
+ System.out.println("controller disposed");
+ }
+
+
+
+
+ // XTerminateListener
+ public void queryTermination (final com.sun.star.lang.EventObject aEvent) throws RuntimeException
+ {
+ System.out.println ("Terminate Event : " + aEvent);
+ }
+
+
+
+
+ // XTerminateListener
+ public void notifyTermination (final com.sun.star.lang.EventObject aEvent) throws RuntimeException
+ {
+ System.out.println ("Notify Termination Event : " + aEvent);
+ }
+
+
+
+ /// The Singleton Workbench object.
+ private static AccessibilityWorkBench
+ saWorkBench = null;
+
+ private SimpleOffice
+ office;
+
+ private JPanel
+ maButtonBar;
+ private Canvas
+ maCanvas;
+ private AccessibilityTree
+ maAccessibilityTree;
+ private ObjectViewContainer
+ maObjectViewContainer;
+ private JButton
+ aConnectButton,
+ aQuitButton,
+ aUpdateButton,
+ aExpandButton,
+ aShapesButton;
+ private boolean
+ mbInitialized;
+ private TopWindowListener
+ maTopWindowListener;
+ private QueuedTopWindowListener
+ maQueuedTopWindowListener;
+}
diff --git a/toolkit/test/accessibility/AccessibleActionHandler.java b/toolkit/test/accessibility/AccessibleActionHandler.java
new file mode 100644
index 000000000..868ea1105
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleActionHandler.java
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleAction;
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+class AccessibleActionHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleAction xEComponent =
+ UnoRuntime.queryInterface (
+ XAccessibleAction.class, xContext);
+ if (xEComponent != null)
+ return new AccessibleActionHandler (xEComponent);
+ else
+ return null;
+ }
+
+ public AccessibleActionHandler ()
+ {
+ }
+
+ private AccessibleActionHandler (XAccessibleAction xAction)
+ {
+ if (xAction != null)
+ maChildList.setSize (1 + xAction.getAccessibleActionCount());
+ }
+
+ protected static XAccessibleAction getAction (AccTreeNode aParent)
+ {
+ return UnoRuntime.queryInterface (
+ XAccessibleAction.class, aParent.getContext());
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (
+ AccessibleTreeNode aParent,
+ int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+
+ if (aParent instanceof AccTreeNode)
+ {
+ XAccessibleAction xAction = getAction ((AccTreeNode)aParent);
+ if( xAction != null )
+ {
+ if (nIndex == 0)
+ aChild = new StringNode ("Number of actions: " + xAction.getAccessibleActionCount(),
+ aParent);
+ else
+ {
+ nIndex -= 1;
+ try
+ {
+ aChild = new AccessibleActionNode (
+ "Action " + nIndex + " : "
+ + xAction.getAccessibleActionDescription (nIndex),
+ aParent,
+ nIndex);
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChild = new StringNode ("ERROR", aParent);
+ }
+ }
+ }
+ }
+
+ return aChild;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleActionNode.java b/toolkit/test/accessibility/AccessibleActionNode.java
new file mode 100644
index 000000000..c1c927574
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleActionNode.java
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import javax.swing.JOptionPane;
+
+/**
+ Base class for all tree nodes.
+ */
+class AccessibleActionNode
+ extends StringNode
+{
+ public AccessibleActionNode (String aDisplayObject,
+ AccessibleTreeNode aParent,
+ int nActionIndex)
+ {
+ super (aDisplayObject, aParent);
+ mnActionIndex = nActionIndex;
+ }
+
+ @Override
+ public String[] getActions ()
+ {
+ return new String[] {"Perform Action"};
+ }
+
+ /** perform action */
+ @Override
+ public void performAction (int nIndex)
+ {
+ if (nIndex != 0)
+ return;
+ boolean bResult = false;
+ if (getParent() instanceof AccTreeNode)
+ try
+ {
+ bResult = AccessibleActionHandler.getAction(
+ (AccTreeNode)getParent()).doAccessibleAction (
+ mnActionIndex);
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException e)
+ {
+ }
+
+ JOptionPane.showMessageDialog (null,
+ "performed action " + mnActionIndex
+ + (bResult?" with":" without") + " success",
+ "Action " + mnActionIndex,
+ JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ private final int mnActionIndex;
+}
diff --git a/toolkit/test/accessibility/AccessibleCellHandler.java b/toolkit/test/accessibility/AccessibleCellHandler.java
new file mode 100644
index 000000000..c251f6790
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleCellHandler.java
@@ -0,0 +1,168 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleTable;
+import com.sun.star.accessibility.XAccessible;
+
+
+class AccessibleCellHandler extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ if (xContext == null)
+ return null;
+
+ AccessibleCellHandler aCellHandler = null;
+ XAccessible xParent = xContext.getAccessibleParent();
+ if (xParent != null)
+ {
+ XAccessibleTable xTable =
+ UnoRuntime.queryInterface (
+ XAccessibleTable.class, xParent.getAccessibleContext());
+ if (xTable != null)
+ aCellHandler = new AccessibleCellHandler (xTable);
+ }
+ return aCellHandler;
+ }
+
+ public AccessibleCellHandler ()
+ {
+ }
+
+ private AccessibleCellHandler (XAccessibleTable xTable)
+ {
+ if (xTable != null)
+ maChildList.setSize (8);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ XAccessibleTable xTable = null;
+ XAccessibleContext xContext = null;
+ AccessibleTreeNode aGrandParent = aParent.getParent();
+ if (aGrandParent instanceof AccTreeNode)
+ {
+ xTable = ((AccTreeNode)aGrandParent).getTable();
+ xContext = ((AccTreeNode)aGrandParent).getContext();
+ }
+ if (aParent instanceof AccTreeNode)
+ {
+ xContext = ((AccTreeNode)aParent).getContext();
+ }
+ try
+ {
+ if( xTable != null && xContext != null )
+ {
+ switch( nIndex )
+ {
+ case 0:
+ {
+ int nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+
+ aChild = new StringNode ("# table row: " + nRow, aParent);
+ }
+ break;
+ case 1:
+ {
+ int nChild = xContext.getAccessibleIndexInParent();
+ int nCol = xTable.getAccessibleColumn( nChild );
+
+ aChild = new StringNode ("# table column: " + nCol, aParent);
+ }
+ break;
+ case 2:
+ {
+ int nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+ int nCol = xTable.getAccessibleColumn( nChild );
+ int nExt = xTable.getAccessibleRowExtentAt( nRow, nCol );
+
+ aChild = new StringNode ("# table row extend: " + nExt, aParent);
+ }
+ break;
+ case 3:
+ {
+ int nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+ int nCol = xTable.getAccessibleColumn( nChild );
+ int nExt = xTable.getAccessibleColumnExtentAt( nRow, nCol );
+
+ aChild = new StringNode ("# table column extend: " + nExt, aParent);
+ }
+ break;
+ case 4:
+ {
+ int nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+ int nCol = xTable.getAccessibleColumn( nChild );
+ XAccessible xChild =
+ xTable.getAccessibleCellAt( nRow, nCol );
+
+ aChild = new StringNode ("# cell name retrieved from table: " + xChild.getAccessibleContext().getAccessibleName(), aParent);
+ }
+ break;
+ case 5:
+ {
+ int nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+ int nCol = xTable.getAccessibleColumn( nChild );
+ boolean bSelected =
+ xTable.isAccessibleSelected( nRow, nCol );
+
+ aChild = new StringNode ("cell is selected: " + bSelected, aParent);
+ }
+ break;
+ case 6:
+ {
+ int nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+ boolean bSelected =
+ xTable.isAccessibleRowSelected( nRow );
+
+ aChild = new StringNode ("table row is selected: " + bSelected, aParent);
+ }
+ break;
+ case 7:
+ {
+ int nChild = xContext.getAccessibleIndexInParent();
+ int nCol = xTable.getAccessibleColumn( nChild );
+ boolean bSelected =
+ xTable.isAccessibleColumnSelected( nCol );
+
+ aChild = new StringNode ("table column is selected: " + bSelected, aParent);
+ }
+ break;
+ default:
+ aChild = new StringNode ("unknown child index " + nIndex, aParent);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ // Return empty child.
+ }
+
+ return aChild;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleComponentHandler.java b/toolkit/test/accessibility/AccessibleComponentHandler.java
new file mode 100644
index 000000000..229612b8d
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleComponentHandler.java
@@ -0,0 +1,121 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleComponent;
+
+
+class AccessibleComponentHandler
+ extends NodeHandler
+{
+
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleComponent xComponent =
+ UnoRuntime.queryInterface (
+ XAccessibleComponent.class, xContext);
+ if (xComponent != null)
+ return new AccessibleComponentHandler (xComponent);
+ else
+ return null;
+
+ }
+
+ public AccessibleComponentHandler ()
+ {
+ }
+
+ private AccessibleComponentHandler (XAccessibleComponent xComponent)
+ {
+ if (xComponent != null)
+ maChildList.setSize (6);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ if (aParent instanceof AccTreeNode)
+ {
+ XAccessibleComponent xComponent =
+ ((AccTreeNode)aParent).getComponent();
+
+ if (xComponent != null)
+ {
+ int nColor;
+ switch (nIndex)
+ {
+ case 0:
+ com.sun.star.awt.Point aLocation = xComponent.getLocation();
+ aChild = new StringNode (
+ "Location: " + aLocation.X + ", " + aLocation.Y,
+ aParent);
+ break;
+ case 1:
+ com.sun.star.awt.Point aScreenLocation = xComponent.getLocationOnScreen();
+ aChild = new StringNode (
+ "Location on Screen: " + aScreenLocation.X + ", " + aScreenLocation.Y,
+ aParent);
+ break;
+ case 2:
+ com.sun.star.awt.Size aSize = xComponent.getSize();
+ aChild = new StringNode (
+ "Size: "+ aSize.Width + ", " + aSize.Height,
+ aParent);
+ break;
+ case 3:
+ com.sun.star.awt.Rectangle aBBox = xComponent.getBounds();
+ aChild = new StringNode (
+ "Bounding Box: "+ aBBox.X + ", " + aBBox.Y + ","
+ + aBBox.Width + ", " + aBBox.Height,
+ aParent);
+ break;
+ case 4:
+ nColor = xComponent.getForeground();
+ aChild = new StringNode ("Foreground color: R"
+ + (nColor>>16&0xff)
+ + "G" + (nColor>>8&0xff)
+ + "B" + (nColor&0xff)
+ + "A" + (nColor>>24&0xff),
+ aParent);
+ break;
+ case 5:
+ nColor = xComponent.getBackground();
+ aChild = new StringNode ("Background color: R"
+ + (nColor>>16&0xff)
+ + "G" + (nColor>>8&0xff)
+ + "B" + (nColor&0xff)
+ + "A" + (nColor>>24&0xff),
+ aParent);
+ break;
+ }
+ }
+ }
+ return aChild;
+ }
+
+ @Override
+ public void update (AccessibleTreeNode aNode)
+ {
+ maChildList.clear();
+ if (aNode instanceof AccTreeNode && ((AccTreeNode)aNode).getComponent() != null)
+ maChildList.setSize (4);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleContextHandler.java b/toolkit/test/accessibility/AccessibleContextHandler.java
new file mode 100644
index 000000000..3b3d35108
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleContextHandler.java
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleStateSet;
+import tools.NameProvider;
+
+class AccessibleContextHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ if (xContext != null)
+ return new AccessibleContextHandler (xContext);
+ else
+ return null;
+ }
+
+ public AccessibleContextHandler ()
+ {
+ super ();
+ }
+
+ private AccessibleContextHandler (XAccessibleContext xContext)
+ {
+ super();
+ if (xContext != null)
+ maChildList.setSize (4);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ XAccessibleContext xContext = null;
+ if (aParent instanceof AccTreeNode)
+ xContext = ((AccTreeNode)aParent).getContext();
+
+ String sChild = "";
+ if (xContext != null)
+ {
+ switch( nIndex )
+ {
+ case 0:
+ sChild = "Description: " +
+ xContext.getAccessibleDescription();
+ break;
+ case 1:
+ int nRole = xContext.getAccessibleRole();
+ sChild = "Role: " + nRole + " (" + NameProvider.getRoleName(nRole) + ")";
+ break;
+ case 2:
+ XAccessible xParent = xContext.getAccessibleParent();
+ sChild = "Has parent: " + (xParent!=null ? "yes" : "no");
+ break;
+ case 3:
+ sChild = "";
+ XAccessibleStateSet xStateSet =
+ xContext.getAccessibleStateSet();
+ if (xStateSet != null)
+ {
+ for (short i=0; i<=30; i++)
+ {
+ if (xStateSet.contains (i))
+ {
+ if (sChild.compareTo ("") != 0)
+ sChild += ", ";
+ sChild += NameProvider.getStateName(i);
+ }
+ }
+ }
+ else
+ sChild += "no state set";
+ sChild = "State set: " + sChild;
+ }
+ }
+ return new StringNode (sChild, aParent);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleEditableTextHandler.java b/toolkit/test/accessibility/AccessibleEditableTextHandler.java
new file mode 100644
index 000000000..ae5df1461
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleEditableTextHandler.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleEditableText;
+
+
+class AccessibleEditableTextHandler extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleEditableText xText =
+ UnoRuntime.queryInterface (
+ XAccessibleEditableText.class, xContext);
+ if (xText != null)
+ return new AccessibleEditableTextHandler (xText);
+ else
+ return null;
+ }
+
+ public AccessibleEditableTextHandler ()
+ {
+ }
+
+ private AccessibleEditableTextHandler (XAccessibleEditableText xText)
+ {
+ if (xText != null)
+ maChildList.setSize (1);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ return new StringNode ("XAccessibleEditableText is supported", aParent);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleExtendedComponentHandler.java b/toolkit/test/accessibility/AccessibleExtendedComponentHandler.java
new file mode 100644
index 000000000..f34ed1b5f
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleExtendedComponentHandler.java
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleExtendedComponent;
+
+
+class AccessibleExtendedComponentHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleExtendedComponent xEComponent =
+ UnoRuntime.queryInterface (
+ XAccessibleExtendedComponent.class, xContext);
+ if (xEComponent != null)
+ return new AccessibleExtendedComponentHandler (xEComponent);
+ else
+ return null;
+ }
+
+ public AccessibleExtendedComponentHandler ()
+ {
+ }
+
+ private AccessibleExtendedComponentHandler (XAccessibleExtendedComponent xEComponent)
+ {
+ if (xEComponent != null)
+ maChildList.setSize (0);
+ }
+
+ private static XAccessibleExtendedComponent getComponent (AccTreeNode aNode)
+ {
+ return UnoRuntime.queryInterface (
+ XAccessibleExtendedComponent.class,
+ aNode.getContext());
+ }
+
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ if (aParent instanceof AccTreeNode)
+ {
+ XAccessibleExtendedComponent xEComponent = getComponent ((AccTreeNode)aParent);
+
+ if (xEComponent != null)
+ {
+ int nColor;
+ switch( nIndex )
+ {
+ case 0:
+ nColor = xEComponent.getForeground();
+ aChild = new StringNode ("Deprecated Foreground color: R"
+ + (nColor>>16&0xff)
+ + "G" + (nColor>>8&0xff)
+ + "B" + (nColor&0xff)
+ + "A" + (nColor>>24&0xff),
+ aParent);
+ break;
+ case 1:
+ nColor = xEComponent.getBackground();
+ aChild = new StringNode ("Deprecated Background color: R"
+ + (nColor>>16&0xff)
+ + "G" + (nColor>>8&0xff)
+ + "B" + (nColor&0xff)
+ + "A" + (nColor>>24&0xff),
+ aParent);
+ break;
+ }
+ }
+ }
+ return aChild;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleHyperlinkHandler.java b/toolkit/test/accessibility/AccessibleHyperlinkHandler.java
new file mode 100644
index 000000000..41a161ac5
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleHyperlinkHandler.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleHyperlink;
+
+
+class AccessibleHyperlinkHandler extends AccessibleTreeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleHyperlink xLink =
+ UnoRuntime.queryInterface (
+ XAccessibleHyperlink.class, xContext);
+ if (xLink != null)
+ return new AccessibleHyperlinkHandler (xLink);
+ else
+ return null;
+ }
+
+ public AccessibleHyperlinkHandler ()
+ {
+ }
+
+ private AccessibleHyperlinkHandler (XAccessibleHyperlink xLink)
+ {
+ if (xLink != null)
+ maChildList.setSize (1);
+ }
+
+ @Override
+ public AccessibleTreeNode getChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ return new StringNode ("interface XAccessibleHyperlink is supported", aParent);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleHypertextHandler.java b/toolkit/test/accessibility/AccessibleHypertextHandler.java
new file mode 100644
index 000000000..603d68997
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleHypertextHandler.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleHypertext;
+
+
+class AccessibleHypertextHandler extends AccessibleTreeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleHypertext xText =
+ UnoRuntime.queryInterface (
+ XAccessibleHypertext.class, xContext);
+ if (xText != null)
+ return new AccessibleHypertextHandler (xText);
+ else
+ return null;
+ }
+
+ public AccessibleHypertextHandler ()
+ {
+ }
+
+ private AccessibleHypertextHandler (XAccessibleHypertext xText)
+ {
+ if (xText != null)
+ maChildList.setSize (1);
+ }
+
+ @Override
+ public AccessibleTreeNode getChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ return new StringNode ("interface XAccessibleHypertext is supported", aParent);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleImageHandler.java b/toolkit/test/accessibility/AccessibleImageHandler.java
new file mode 100644
index 000000000..a02077b7d
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleImageHandler.java
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleImage;
+
+
+class AccessibleImageHandler extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleImage xImage =
+ UnoRuntime.queryInterface (
+ XAccessibleImage.class, xContext);
+ if (xImage != null)
+ return new AccessibleImageHandler (xImage);
+ else
+ return null;
+ }
+
+ public AccessibleImageHandler ()
+ {
+ }
+
+ private AccessibleImageHandler (XAccessibleImage xImage)
+ {
+ if (xImage != null)
+ maChildList.setSize (1);
+ }
+
+ private static XAccessibleImage getImage (AccTreeNode aNode)
+ {
+ return UnoRuntime.queryInterface (
+ XAccessibleImage.class, aNode.getContext());
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ if (aParent instanceof AccTreeNode)
+ {
+ XAccessibleImage xImage = getImage ((AccTreeNode)aParent);
+ if (xImage != null)
+ return new StringNode (
+ "Image: " +
+ xImage.getAccessibleImageDescription() + " (" +
+ xImage.getAccessibleImageWidth() + "x" +
+ xImage.getAccessibleImageHeight() + ")",
+ aParent);
+ }
+ return null;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleRelationHandler.java b/toolkit/test/accessibility/AccessibleRelationHandler.java
new file mode 100644
index 000000000..1f7eebada
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleRelationHandler.java
@@ -0,0 +1,115 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.AccessibleRelation;
+import com.sun.star.accessibility.XAccessibleRelationSet;
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+import tools.NameProvider;
+
+class AccessibleRelationHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler( XAccessibleContext xContext )
+ {
+ AccessibleRelationHandler aHandler = null;
+ if (xContext != null)
+ {
+ XAccessibleRelationSet xRelation = xContext.getAccessibleRelationSet();
+ if (xRelation != null)
+ aHandler = new AccessibleRelationHandler(xContext);
+ }
+ return aHandler;
+ }
+
+ public AccessibleRelationHandler()
+ {
+ }
+
+ private AccessibleRelationHandler( XAccessibleContext xContext )
+ {
+ XAccessibleRelationSet xRelation = xContext.getAccessibleRelationSet();
+ if (xRelation != null)
+ maChildList.setSize( 1 );
+ }
+
+ @Override
+ public AccessibleTreeNode createChild( AccessibleTreeNode aParent,
+ int nIndex )
+ {
+ XAccessibleRelationSet xRelation = null;
+ AccessibleTreeNode aChild = null;
+
+ if( aParent instanceof AccTreeNode )
+ {
+ xRelation =
+ ((AccTreeNode)aParent).getContext().getAccessibleRelationSet();
+ }
+ if( xRelation == null )
+ return aChild;
+
+
+ VectorNode aVNode = new VectorNode( "RelationSet", aParent);
+ int nCount = xRelation.getRelationCount();
+ try
+ {
+ for( int i = 0; i < nCount; i++ )
+ {
+ AccessibleRelation aRelation = xRelation.getRelation( i );
+
+ StringBuffer aBuffer = new StringBuffer();
+ aBuffer.append (NameProvider.getRelationName (aRelation.RelationType));
+ aBuffer.append( ": " );
+
+ for( int j = 0; j < aRelation.TargetSet.length; j++ )
+ {
+ Object aTarget = aRelation.TargetSet[j];
+ XAccessible xAccTarget =
+ UnoRuntime.queryInterface(
+ XAccessible.class, aTarget );
+ if( xAccTarget == null )
+ {
+ aBuffer.append( aTarget.toString() );
+ }
+ else
+ {
+ aBuffer.append( xAccTarget.getAccessibleContext().
+ getAccessibleName() );
+ }
+ aBuffer.append( ", " );
+ }
+ aBuffer.delete( aBuffer.length() - 2, aBuffer.length() );
+
+ aVNode.addChild( new StringNode( aBuffer.toString(),
+ aParent ) );
+ }
+
+ aChild = aVNode;
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChild = new StringNode( "IndexOutOfBounds", aParent );
+ }
+
+ return aChild;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleSelectionHandler.java b/toolkit/test/accessibility/AccessibleSelectionHandler.java
new file mode 100644
index 000000000..4a8cd24ba
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleSelectionHandler.java
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleSelection;
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+
+
+class AccessibleSelectionHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler( XAccessibleContext xContext )
+ {
+ XAccessibleSelection xSelection =
+ UnoRuntime.queryInterface(
+ XAccessibleSelection.class, xContext);
+ return (xSelection == null) ? null :
+ new AccessibleSelectionHandler(xSelection);
+ }
+
+ public AccessibleSelectionHandler()
+ {
+ }
+
+ private AccessibleSelectionHandler( XAccessibleSelection xSelection )
+ {
+ if (xSelection != null)
+ maChildList.setSize( 2 );
+ }
+
+ @Override
+ public AccessibleTreeNode createChild( AccessibleTreeNode aParent,
+ int nIndex )
+ {
+ if( !(aParent instanceof AccTreeNode) )
+ return null;
+
+ XAccessibleSelection xSelection = ((AccTreeNode)aParent).getSelection();
+ if( xSelection == null )
+ return null;
+
+ AccessibleTreeNode aChild = null;
+
+ switch( nIndex )
+ {
+ case 0:
+ aChild = new StringNode(
+ "getSelectedAccessibleChildCount: " +
+ xSelection.getSelectedAccessibleChildCount(),
+ aParent );
+ break;
+ case 1:
+ {
+ VectorNode aVNode =
+ new VectorNode( "Selected Children", aParent);
+ int nSelected = 0;
+ int nCount = ((AccTreeNode)aParent).getContext().
+ getAccessibleChildCount();
+ try
+ {
+ for( int i = 0; i < nCount; i++ )
+ {
+ try
+ {
+ if( xSelection.isAccessibleChildSelected( i ) )
+ {
+ XAccessible xSelChild = xSelection.
+ getSelectedAccessibleChild(nSelected);
+ XAccessible xNChild =
+ ((AccTreeNode)aParent).
+ getContext().getAccessibleChild( i );
+ aVNode.addChild( new StringNode(
+ i + ": " +
+ xNChild.getAccessibleContext().
+ getAccessibleDescription() + " (" +
+ (xSelChild.equals(xNChild) ? "OK" : "XXX") +
+ ")", aParent ) );
+ }
+ }
+ catch (com.sun.star.lang.DisposedException e)
+ {
+ aVNode.addChild( new StringNode(
+ i + ": caught DisposedException while creating",
+ aParent ));
+ }
+ }
+ aChild = aVNode;
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChild = new StringNode( "IndexOutOfBounds",
+ aParent );
+ }
+ }
+ break;
+ default:
+ aChild = new StringNode( "ERROR", aParent );
+ break;
+ }
+
+ return aChild;
+ }
+
+
+ @Override
+ public String[] getActions (AccessibleTreeNode aNode)
+ {
+ if( aNode instanceof AccTreeNode )
+ {
+ XAccessibleSelection xSelection =
+ ((AccTreeNode)aNode).getSelection();
+ if( xSelection != null )
+ {
+ return new String[] { "Select..." };
+ }
+ }
+ return new String[0];
+ }
+
+ @Override
+ public void performAction (AccessibleTreeNode aNode, int nIndex)
+ {
+ SelectionDialog selectionDialog = new SelectionDialog( (AccTreeNode)aNode );
+ selectionDialog.setVisible(true);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleTableHandler.java b/toolkit/test/accessibility/AccessibleTableHandler.java
new file mode 100644
index 000000000..a72fe61a3
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleTableHandler.java
@@ -0,0 +1,103 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleTable;
+
+
+class AccessibleTableHandler extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleTable xTable =
+ UnoRuntime.queryInterface (
+ XAccessibleTable.class, xContext);
+ if (xTable != null)
+ return new AccessibleTableHandler (xTable);
+ else
+ return null;
+ }
+
+ public AccessibleTableHandler ()
+ {
+ }
+
+ private AccessibleTableHandler (XAccessibleTable xTable)
+ {
+ if (xTable != null)
+ maChildList.setSize (4);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ XAccessibleTable xTable = null;
+ if (aParent instanceof AccTreeNode)
+ xTable = ((AccTreeNode)aParent).getTable();
+ try
+ {
+ if( xTable != null )
+ {
+ switch( nIndex )
+ {
+ case 0:
+ aChild = new StringNode ("# table rows: " + xTable.getAccessibleRowCount(), aParent);
+ break;
+ case 1:
+ aChild = new StringNode ("# table columns: " + xTable.getAccessibleColumnCount(), aParent);
+ break;
+ case 2:
+ {
+ String sText = "selected rows: ";
+ int[] aSelected = xTable.getSelectedAccessibleRows();
+ for( int i=0; i < aSelected.length; i++ )
+ {
+ sText += aSelected[i];
+ sText += " ";
+ }
+ aChild = new StringNode (sText, aParent);
+ }
+ break;
+ case 3:
+ {
+ String sText = "selected columns: ";
+ int[] aSelected = xTable.getSelectedAccessibleColumns();
+ for( int i=0; i < aSelected.length; i++ )
+ {
+ sText += aSelected[i];
+ sText += " ";
+ }
+ aChild = new StringNode (sText, aParent);
+ }
+ break;
+ default:
+ aChild = new StringNode ("unknown child index " + nIndex, aParent);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ // Return empty child.
+ }
+
+ return aChild;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleTextHandler.java b/toolkit/test/accessibility/AccessibleTextHandler.java
new file mode 100644
index 000000000..714bcb591
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleTextHandler.java
@@ -0,0 +1,821 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BoxLayout;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JColorChooser;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.text.JTextComponent;
+
+import com.sun.star.accessibility.AccessibleTextType;
+import com.sun.star.accessibility.TextSegment;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleEditableText;
+import com.sun.star.accessibility.XAccessibleText;
+import com.sun.star.awt.Point;
+import com.sun.star.awt.Rectangle;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.lang.IndexOutOfBoundsException;
+import com.sun.star.uno.UnoRuntime;
+
+
+class AccessibleTextHandler extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleText xText = UnoRuntime.queryInterface (
+ XAccessibleText.class, xContext);
+ if (xText != null)
+ return new AccessibleTextHandler (xText);
+ else
+ return null;
+ }
+
+ public AccessibleTextHandler ()
+ {
+ }
+
+ private AccessibleTextHandler (XAccessibleText xText)
+ {
+ if (xText != null)
+ maChildList.setSize (8);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ XAccessibleText xText = null;
+ if (aParent instanceof AccTreeNode)
+ xText = ((AccTreeNode)aParent).getText();
+
+ try
+ {
+ if( xText != null )
+ {
+ switch( nIndex )
+ {
+ case 0:
+ aChild = new StringNode (xText.getText(), aParent);
+ break;
+ case 1:
+ aChild = new StringNode ("# chars: " + xText.getCharacterCount(), aParent);
+ break;
+ case 2:
+ aChild = new StringNode (characters( xText ), aParent);
+ break;
+ case 3:
+ aChild = new StringNode ("selection: "
+ + "[" + xText.getSelectionStart()
+ + "," + xText.getSelectionEnd()
+ + "] \"" + xText.getSelectedText() + "\"",
+ aParent);
+ break;
+ case 4:
+ aChild = new StringNode ("getCaretPosition: " + xText.getCaretPosition(), aParent);
+ break;
+ case 5:
+ {
+ VectorNode aVec = new VectorNode("portions", aParent);
+ aChild = aVec;
+ aVec.addChild(
+ textAtIndexNode( xText, "Character",
+ AccessibleTextType.CHARACTER,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Word",
+ AccessibleTextType.WORD,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Sentence",
+ AccessibleTextType.SENTENCE,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Paragraph",
+ AccessibleTextType.PARAGRAPH,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Line",
+ AccessibleTextType.LINE,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Attribute",
+ AccessibleTextType.ATTRIBUTE_RUN,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Glyph",
+ AccessibleTextType.GLYPH,
+ aParent ) );
+ }
+ break;
+ case 6:
+ aChild = new StringNode (bounds( xText ), aParent);
+ break;
+ case 7:
+ aChild = getAttributes( xText, aParent );
+ break;
+ default:
+ aChild = new StringNode ("unknown child index " + nIndex, aParent);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ // Return empty child.
+ }
+
+ return aChild;
+ }
+
+
+ private String textAtIndexNodeString(
+ int nStart, int nEnd,
+ String sWord, String sBefore, String sBehind)
+ {
+ return "[" + nStart + "," + nEnd + "] "
+ + "\"" + sWord + "\" \t"
+ + "(" + sBefore + "," + sBehind + ")";
+ }
+
+ /** Create a text node that lists all strings of a particular text type
+ */
+ private AccessibleTreeNode textAtIndexNode(
+ XAccessibleText xText,
+ String sName,
+ short nTextType,
+ AccessibleTreeNode aParent)
+ {
+ VectorNode aNode = new VectorNode (sName, aParent);
+
+ // get word at all positions;
+ // for nicer display, compare current word to previous one and
+ // make a new node for every interval, not for every word
+ int nLength = xText.getCharacterCount();
+ if( nLength > 0 )
+ {
+ try
+ {
+ // sWord + nStart mark the current word
+ // make a node as soon as a new one is found; close the last
+ // one at the end
+ TextSegment sWord = xText.getTextAtIndex(0, nTextType);
+ TextSegment sBefore = xText.getTextBeforeIndex(0, nTextType);
+ TextSegment sBehind = xText.getTextBehindIndex(0, nTextType);
+ int nStart = 0;
+ for(int i = 1; i < nLength; i++)
+ {
+ TextSegment sTmp = xText.getTextAtIndex(i, nTextType);
+ TextSegment sTBef = xText.getTextBeforeIndex(i, nTextType);
+ TextSegment sTBeh = xText.getTextBehindIndex(i, nTextType);
+ if( ! ( sTmp.equals( sWord ) && sTBef.equals( sBefore ) &&
+ sTBeh.equals( sBehind ) ) )
+ {
+ aNode.addChild (new StringNode (textAtIndexNodeString(
+ nStart, i,
+ sWord.SegmentText, sBefore.SegmentText, sBehind.SegmentText), aNode));
+ sWord = sTmp;
+ sBefore = sTBef;
+ sBehind = sTBeh;
+ nStart = i;
+ }
+
+ // don't generate more than 50 children.
+ if (aNode.getChildCount() > 50)
+ {
+ sWord.SegmentText = "...";
+ break;
+ }
+ }
+ aNode.addChild (new StringNode (textAtIndexNodeString(
+ nStart, nLength,
+ sWord.SegmentText, sBefore.SegmentText, sBehind.SegmentText), aNode));
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aNode.addChild (new StringNode (e.toString(), aNode));
+ }
+ catch (com.sun.star.lang.IllegalArgumentException e)
+ {
+ aNode.addChild (new StringNode (e.toString(), aNode));
+ }
+ }
+
+ return aNode;
+ }
+
+
+
+ /** getCharacter (display as array string) */
+ private String characters(XAccessibleText xText)
+ {
+ // get count (max. 30)
+ int nChars = xText.getCharacterCount();
+ if( nChars > 30 )
+ nChars = 30;
+
+ // build up string
+ StringBuffer aChars = new StringBuffer();
+ try
+ {
+ aChars.append( '[' );
+ for( int i = 0; i < nChars; i++)
+ {
+ aChars.append( xText.getCharacter(i) );
+ aChars.append( ',' );
+ }
+ if( nChars > 0)
+ {
+ if( nChars == xText.getCharacterCount() )
+ aChars.deleteCharAt( aChars.length() - 1 );
+ else
+ aChars.append( "..." );
+ }
+ aChars.append( ']' );
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChars.append( " ERROR " );
+ }
+
+ // return result
+ return "getCharacters: " + aChars;
+ }
+
+
+ /** iterate over characters, and translate their positions
+ * back and forth */
+ private String bounds( XAccessibleText xText )
+ {
+ StringBuffer aBuffer = new StringBuffer( "bounds: " );
+ try
+ {
+ // iterate over characters
+ int nCount = xText.getCharacterCount();
+ for(int i = 0; i < nCount; i++ )
+ {
+ // get bounds for this character
+ Rectangle aRect = xText.getCharacterBounds( i );
+
+ // get the character by 'clicking' into the middle of
+ // the bounds
+ Point aMiddle = new Point();
+ aMiddle.X = aRect.X + (aRect.Width / 2) - 1;
+ aMiddle.Y = aRect.Y + (aRect.Height / 2 ) - 1;
+ int nIndex = xText.getIndexAtPoint( aMiddle );
+
+ // get the character, or a '#' for an illegal index
+ if( (nIndex >= 0) && (nIndex < xText.getCharacter(i)) )
+ aBuffer.append( xText.getCharacter(nIndex) );
+ else
+ aBuffer.append( '#' );
+ }
+ }
+ catch( IndexOutOfBoundsException e )
+ { } // ignore errors
+
+ return aBuffer.toString();
+ }
+
+
+ private AccessibleTreeNode getAttributes( XAccessibleText xText,
+ AccessibleTreeNode aParent)
+ {
+ String[] aAttributeList = new String[] {
+ "CharBackColor",
+ "CharColor",
+ "CharEscapement",
+ "CharHeight",
+ "CharPosture",
+ "CharStrikeout",
+ "CharUnderline",
+ "CharWeight",
+ "ParaAdjust",
+ "ParaBottomMargin",
+ "ParaFirstLineIndent",
+ "ParaLeftMargin",
+ "ParaLineSpacing",
+ "ParaRightMargin",
+ "ParaTabStops"};
+
+ AccessibleTreeNode aRet;
+
+ try
+ {
+ VectorNode aPortions = new VectorNode ("getAttributes", aParent);
+
+ int nIndex = 0;
+ int nLength = xText.getCharacterCount();
+ while( nIndex < nLength )
+ {
+ // get attribute run
+ String aPortion = null;
+ try
+ {
+ aPortion = xText.getTextAtIndex(
+ nIndex, AccessibleTextType.ATTRIBUTE_RUN).SegmentText;
+ }
+ catch(com.sun.star.lang.IllegalArgumentException e)
+ {
+ aPortion = "";
+ }
+
+ // get attributes and make node with attribute children
+ PropertyValue[] aValues = xText.getCharacterAttributes(nIndex, aAttributeList);
+ VectorNode aAttrs = new VectorNode (aPortion, aPortions);
+ for( int i = 0; i < aValues.length; i++ )
+ {
+ new StringNode( aValues[i].Name + ": " + aValues[i].Value,
+ aAttrs );
+ }
+
+ // get next portion, but advance at least one
+ nIndex += (aPortion.length() > 0) ? aPortion.length() : 1;
+ }
+
+ aRet = aPortions;
+ }
+ catch( UnknownPropertyException e )
+ {
+ aRet = new StringNode( "Exception caught:" + e, aParent );
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aRet = new StringNode( "Exception caught:" + e, aParent );
+ }
+
+ return aRet;
+ }
+
+
+ private static String[] aTextActions =
+ new String[] { "select...", "copy..." };
+ private static String[] aEditableTextActions =
+ new String[] { "select...", "copy...",
+ "cut...", "paste...", "edit...", "format..." };
+
+ @Override
+ public String[] getActions (AccessibleTreeNode aNode)
+ {
+ XAccessibleEditableText xEText = null;
+ if (aNode instanceof AccTreeNode)
+ xEText = ((AccTreeNode)aNode).getEditText ();
+
+ return (xEText == null) ? aTextActions : aEditableTextActions;
+ }
+
+ @Override
+ public void performAction (AccessibleTreeNode aNode, int nIndex)
+ {
+ if ( ! (aNode instanceof AccTreeNode))
+ return;
+
+ AccTreeNode aATNode = (AccTreeNode)aNode;
+ TextActionDialog aDialog = null;
+
+ // create proper dialog
+ switch( nIndex )
+ {
+ case 0:
+ aDialog = new TextActionDialog( aATNode,
+ "Select range:",
+ "select" )
+ {
+ @Override
+ boolean action(
+ JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException
+ {
+ return aNode.getText().setSelection(
+ getSelectionStart(),
+ getSelectionEnd() );
+ }
+ };
+ break;
+ case 1:
+ aDialog = new TextActionDialog( aATNode,
+ "Select range and copy:",
+ "copy" )
+ {
+ @Override
+ boolean action(
+ JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException
+ {
+ return aNode.getText().copyText(
+ getSelectionStart(),
+ getSelectionEnd() );
+ }
+ };
+ break;
+ case 2:
+ aDialog = new TextActionDialog( aATNode,
+ "Select range and cut:",
+ "cut" )
+ {
+ @Override
+ boolean action(
+ JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException
+ {
+ return aNode.getEditText().cutText(
+ getSelectionStart(),
+ getSelectionEnd() );
+ }
+ };
+ break;
+ case 3:
+ aDialog = new TextActionDialog( aATNode,
+ "Place Caret and paste:",
+ "paste" )
+ {
+ @Override
+ boolean action(
+ JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException
+ {
+ return aNode.getEditText().pasteText(
+ aText.getCaretPosition() );
+ }
+ };
+ break;
+ case 4:
+ aDialog = new TextEditDialog( aATNode, "Edit text:",
+ "edit" );
+ break;
+ case 5:
+ aDialog = new TextAttributeDialog( aATNode );
+ break;
+ }
+
+ if( aDialog != null )
+ aDialog.setVisible(true);
+ }
+
+}
+
+/**
+ * Display a dialog with a text field and a pair of cancel/do-it buttons
+ */
+abstract class TextActionDialog extends JDialog
+ implements ActionListener
+{
+ private AccTreeNode aNode;
+ JTextArea aText;
+ private String sName;
+ private JCheckBox aIndexToggle;
+
+ public TextActionDialog( AccTreeNode aNd,
+ String sExplanation,
+ String sButtonText )
+ {
+ super( AccessibilityWorkBench.Instance() );
+
+ aNode = aNd;
+ sName = sButtonText;
+ init( sExplanation, aNode.getText().getText(), sButtonText );
+ setSize( 350, 225 );
+ }
+
+ /** build dialog */
+ protected void init( String sExplanation,
+ String sText,
+ String sButtonText )
+ {
+ setTitle( sName );
+
+ // vertical stacking of the elements
+ Container aContent = getContentPane();
+
+ // label with explanation
+ if( sExplanation.length() > 0 )
+ aContent.add( new JLabel( sExplanation ), BorderLayout.NORTH );
+
+ // the text field
+ aText = new JTextArea();
+ aText.setText( sText );
+ aText.setColumns( Math.min( Math.max( 40, sText.length() ), 20 ) );
+ aText.setRows( sText.length() / 40 + 1 );
+ aText.setLineWrap( true );
+ aText.setEditable( false );
+ aContent.add( aText, BorderLayout.CENTER );
+
+ JPanel aButtons = new JPanel();
+ aButtons.setLayout( new FlowLayout() );
+ aIndexToggle = new JCheckBox( "reverse selection" );
+ aButtons.add( aIndexToggle );
+ JButton aActionButton = new JButton( sButtonText );
+ aActionButton.setActionCommand( "Action" );
+ aActionButton.addActionListener( this );
+ aButtons.add( aActionButton );
+ JButton aCancelButton = new JButton( "cancel" );
+ aCancelButton.setActionCommand( "Cancel" );
+ aCancelButton.addActionListener( this );
+ aButtons.add( aCancelButton );
+
+ // add Panel with buttons
+ aContent.add( aButtons, BorderLayout.SOUTH );
+ }
+
+ private void cancel()
+ {
+ setVisible(false);
+ dispose();
+ }
+
+ private void action()
+ {
+ String sError = null;
+ try
+ {
+ boolean bSuccess = action( aText, aNode );
+ if( !bSuccess )
+ sError = "Can't execute";
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ sError = "Index out of bounds";
+ }
+
+ if( sError != null )
+ JOptionPane.showMessageDialog( AccessibilityWorkBench.Instance(),
+ sError, sName,
+ JOptionPane.ERROR_MESSAGE);
+
+ cancel();
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ String sCommand = e.getActionCommand();
+
+ if( "Cancel".equals( sCommand ) )
+ cancel();
+ else if( "Action".equals( sCommand ) )
+ action();
+ }
+
+
+ int getSelectionStart() { return getSelection(true); }
+ int getSelectionEnd() { return getSelection(false); }
+ private int getSelection(boolean bStart)
+ {
+ return ( bStart ^ aIndexToggle.isSelected() )
+ ? aText.getSelectionStart() : aText.getSelectionEnd();
+ }
+
+
+
+ /** override this for dialog-specific action */
+ abstract boolean action( JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException;
+}
+
+
+class TextEditDialog extends TextActionDialog
+{
+ public TextEditDialog( AccTreeNode aNode,
+ String sExplanation,
+ String sButtonText )
+ {
+ super( aNode, sExplanation, sButtonText );
+ }
+
+ @Override
+ protected void init( String sExplanation,
+ String sText,
+ String sButtonText )
+ {
+ super.init( sExplanation, sText, sButtonText );
+ aText.setEditable( true );
+ }
+
+
+ /** edit the text */
+ @Override
+ boolean action( JTextComponent aText, AccTreeNode aNode )
+ {
+ // is this text editable? if not, fudge you and return
+ XAccessibleEditableText xEdit = aNode.getEditText();
+ return ( xEdit == null ) ? false :
+ updateText( xEdit, aText.getText() );
+ }
+
+
+ /** update the text */
+ private boolean updateText( XAccessibleEditableText xEdit, String sNew )
+ {
+ String sOld = xEdit.getText();
+
+ // false alarm? Early out if no change was done!
+ if( sOld.equals( sNew ) )
+ return false;
+
+ // get the minimum length of both strings
+ int nMinLength = sOld.length();
+ if( sNew.length() < nMinLength )
+ nMinLength = sNew.length();
+
+ // count equal characters from front and end
+ int nFront = 0;
+ while( (nFront < nMinLength) &&
+ (sNew.charAt(nFront) == sOld.charAt(nFront)) ) {
+ nFront++;
+ }
+ int nBack = 0;
+ while( (nBack < nMinLength) &&
+ ( sNew.charAt(sNew.length()-nBack-1) ==
+ sOld.charAt(sOld.length()-nBack-1) ) ) {
+ nBack++;
+ }
+ if( nFront + nBack > nMinLength )
+ nBack = nMinLength - nFront;
+
+ // so... the first nFront and the last nBack characters
+ // are the same. Change the others!
+ String sDel = sOld.substring( nFront, sOld.length() - nBack );
+ String sIns = sNew.substring( nFront, sNew.length() - nBack );
+
+ System.out.println("edit text: " +
+ sOld.substring(0, nFront) +
+ " [ " + sDel + " -> " + sIns + " ] " +
+ sOld.substring(sOld.length() - nBack) );
+
+ boolean bRet = false;
+ try
+ {
+ // edit the text, and use
+ // (set|insert|delete|replace)Text as needed
+ if( nFront+nBack == 0 )
+ bRet = xEdit.setText( sIns );
+ else if( sDel.length() == 0 )
+ bRet = xEdit.insertText( sIns, nFront );
+ else if( sIns.length() == 0 )
+ bRet = xEdit.deleteText( nFront, sOld.length()-nBack );
+ else
+ bRet = xEdit.replaceText(nFront, sOld.length()-nBack,sIns);
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ bRet = false;
+ }
+
+ return bRet;
+ }
+}
+
+
+class TextAttributeDialog extends TextActionDialog
+{
+ public TextAttributeDialog(
+ AccTreeNode aNode )
+ {
+ super( aNode, "Choose attributes, select text, and press 'Set':",
+ "set" );
+ }
+
+ private JCheckBox aBold, aUnderline, aItalics;
+ private Color aForeground, aBackground;
+
+ @Override
+ protected void init( String sExplanation,
+ String sText,
+ String sButtonText )
+ {
+ super.init( sExplanation, sText, sButtonText );
+
+ aForeground = Color.black;
+ aBackground = Color.white;
+
+ JPanel aAttr = new JPanel();
+ aAttr.setLayout( new BoxLayout( aAttr, BoxLayout.Y_AXIS ) );
+
+ aBold = new JCheckBox( "bold" );
+ aUnderline = new JCheckBox( "underline" );
+ aItalics = new JCheckBox( "italics" );
+
+ JButton aForeButton = new JButton("Foreground", new ColorIcon(true));
+ aForeButton.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ aForeground = JColorChooser.showDialog(
+ TextAttributeDialog.this,
+ "Select Foreground Color",
+ aForeground);
+ }
+ } );
+
+ JButton aBackButton = new JButton("Background", new ColorIcon(false));
+ aBackButton.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ aBackground = JColorChooser.showDialog(
+ TextAttributeDialog.this,
+ "Select Background Color",
+ aBackground);
+ }
+ } );
+
+ aAttr.add( aBold );
+ aAttr.add( aUnderline );
+ aAttr.add( aItalics );
+ aAttr.add( aForeButton );
+ aAttr.add( aBackButton );
+
+ getContentPane().add( aAttr, BorderLayout.WEST );
+ }
+
+
+ private class ColorIcon implements Icon
+ {
+ private boolean bForeground;
+ private static final int nHeight = 16;
+ private static final int nWidth = 16;
+
+ public ColorIcon(boolean bWhich) { bForeground = bWhich; }
+ public int getIconHeight() { return nHeight; }
+ public int getIconWidth() { return nWidth; }
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ g.setColor( getColor() );
+ g.fillRect( x, y, nHeight, nWidth );
+ g.setColor( c.getForeground() );
+ g.drawRect( x, y, nHeight, nWidth );
+ }
+ Color getColor()
+ {
+ return bForeground ? aForeground : aBackground;
+ }
+ }
+
+
+
+ /** edit the text */
+ @Override
+ boolean action( JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException
+ {
+ // is this text editable? if not, fudge you and return
+ XAccessibleEditableText xEdit = aNode.getEditText();
+ boolean bSuccess = false;
+ if( xEdit != null )
+ {
+ PropertyValue[] aSequence = new PropertyValue[6];
+ aSequence[0] = new PropertyValue();
+ aSequence[0].Name = "CharWeight";
+ aSequence[0].Value = Integer.valueOf( aBold.isSelected() ? 150 : 100 );
+ aSequence[1] = new PropertyValue();
+ aSequence[1].Name = "CharUnderline";
+ aSequence[1].Value = Integer.valueOf( aUnderline.isSelected() ? 1 : 0 );
+ aSequence[2] = new PropertyValue();
+ aSequence[2].Name = "CharBackColor";
+ aSequence[2].Value = Integer.valueOf( aBackground.getRGB() );
+ aSequence[3] = new PropertyValue();
+ aSequence[3].Name = "CharColor";
+ aSequence[3].Value = Integer.valueOf( aForeground.getRGB() );
+ aSequence[4] = new PropertyValue();
+ aSequence[4].Name = "CharPosture";
+ aSequence[4].Value = Integer.valueOf( aItalics.isSelected() ? 1 : 0 );
+ aSequence[5] = new PropertyValue();
+ aSequence[5].Name = "CharBackTransparent";
+ aSequence[5].Value = Boolean.FALSE;
+
+ bSuccess = xEdit.setAttributes( getSelectionStart(),
+ getSelectionEnd(),
+ aSequence );
+ }
+ return bSuccess;
+ }
+
+}
diff --git a/toolkit/test/accessibility/AccessibleTreeHandler.java b/toolkit/test/accessibility/AccessibleTreeHandler.java
new file mode 100644
index 000000000..e022dbae8
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleTreeHandler.java
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+
+/**
+ * Map the tree of accessibility objects into their
+ * AccessibilityTreeModel counterparts.
+ */
+class AccessibleTreeHandler
+ extends NodeHandler
+{
+ private XAccessibleContext mxContext;
+
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ if (xContext != null)
+ return new AccessibleTreeHandler (xContext);
+ else
+ return null;
+ }
+
+ public AccessibleTreeHandler ()
+ {
+ super();
+ mxContext = null;
+ }
+
+ private AccessibleTreeHandler (XAccessibleContext xContext)
+ {
+ super();
+ mxContext = xContext;
+ if (mxContext != null)
+ // Add one to the number of children to include the string node
+ // that tells you how many children there are.
+ synchronized (maChildList)
+ {
+ maChildList.setSize (1 + mxContext.getAccessibleChildCount());
+ }
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ if (mxContext != null)
+ {
+ if (nIndex == 0)
+ aChild = new StringNode ("Child count: " + mxContext.getAccessibleChildCount(),
+ aParent);
+ else
+ {
+ // Lower index to skip the string node.
+ nIndex -= 1;
+ try
+ {
+ XAccessible xChild = mxContext.getAccessibleChild (nIndex);
+ aChild = NodeFactory.Instance().createDefaultNode (
+ xChild, aParent);
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChild = new StringNode ("ERROR: no child with index " + nIndex, aParent);
+ }
+ }
+ }
+ else
+ aChild = new StringNode ("XAccessibleContext interface not supported", aParent);
+ return aChild;
+ }
+
+ /** Try to add the specified accessible child into the lists of
+ children. The insertion position is determined from the
+ getIndexInParent method of the child.
+ */
+ public AccessibleTreeNode addAccessibleChild (AccessibleTreeNode aParent, XAccessible xChild)
+ {
+ AccessibleTreeNode aChild = null;
+
+ if (xChild != null)
+ {
+ XAccessibleContext xContext = xChild.getAccessibleContext();
+ if (xContext != null)
+ {
+ int nIndex = xContext.getAccessibleIndexInParent() + 1;
+ synchronized (maChildList)
+ {
+ if ((nIndex >= 0) || (nIndex <= maChildList.size()))
+ {
+ aChild = NodeFactory.Instance().createDefaultNode (xChild, aParent);
+ maChildList.add (nIndex, aChild);
+ }
+ }
+ }
+ }
+ return aChild;
+ }
+
+
+ /** Update only the child count node. Trust on other ways to update the
+ accessible children.
+ */
+ @Override
+ public void update (AccessibleTreeNode aNode)
+ {
+ synchronized (maChildList)
+ {
+ maChildList.set (0, null);
+ }
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleTreeNode.java b/toolkit/test/accessibility/AccessibleTreeNode.java
new file mode 100644
index 000000000..22fa035f9
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleTreeNode.java
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.util.ArrayList;
+
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+/**
+ Base class for all tree nodes.
+ */
+abstract class AccessibleTreeNode
+{
+ /// The parent node. It is null for the root node.
+ private AccessibleTreeNode maParent;
+
+ /// The object to be displayed.
+ private final Object maDisplayObject;
+
+ public AccessibleTreeNode (Object aDisplayObject, AccessibleTreeNode aParent)
+ {
+ maDisplayObject = aDisplayObject;
+ maParent = aParent;
+ }
+
+ public void update ()
+ {
+ // Empty
+ }
+
+ public AccessibleTreeNode getParent ()
+ {
+ return maParent;
+ }
+
+ public int getChildCount ()
+ {
+ return 0;
+ }
+
+ public AccessibleTreeNode getChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ throw new IndexOutOfBoundsException();
+ }
+
+ public AccessibleTreeNode getChildNoCreate (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ throw new IndexOutOfBoundsException();
+ }
+
+ public boolean removeChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ throw new IndexOutOfBoundsException();
+ }
+
+ public abstract int indexOf (AccessibleTreeNode aNode);
+
+ /** Create a path to this node by first asking the parent for its path
+ and then appending this object.
+ */
+ public void createPath (java.util.List<AccessibleTreeNode> aPath)
+ {
+ if (maParent != null)
+ maParent.createPath (aPath);
+ aPath.add (this);
+ }
+
+ public Object[] createPath ()
+ {
+ ArrayList<AccessibleTreeNode> aPath = new ArrayList<AccessibleTreeNode> (1);
+ createPath (aPath);
+ return aPath.toArray();
+ }
+
+ public boolean isLeaf()
+ {
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return maDisplayObject.toString();
+ }
+
+ /** get names of supported actions */
+ public String[] getActions ()
+ {
+ return new String[] {};
+ }
+
+ /** perform action */
+ public void performAction (int nIndex)
+ {
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleUNOHandler.java b/toolkit/test/accessibility/AccessibleUNOHandler.java
new file mode 100644
index 000000000..1ee522b27
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleUNOHandler.java
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.lang.XServiceInfo;
+import com.sun.star.lang.XTypeProvider;
+import com.sun.star.uno.Type;
+
+
+/** This handler displays lower level UNO information. These are the
+ supported services, interfaces, and the implementation name.
+*/
+class AccessibleUNOHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ if (xContext == null)
+ return null;
+ else
+ {
+ AccessibleUNOHandler h = new AccessibleUNOHandler();
+ h.maChildList.setSize (3);
+ return h;
+ }
+ }
+
+ private XServiceInfo GetServiceInfo (AccessibleTreeNode aNode)
+ {
+ XServiceInfo xServiceInfo = null;
+ if (aNode instanceof AccTreeNode)
+ xServiceInfo = UnoRuntime.queryInterface(
+ XServiceInfo.class, ((AccTreeNode)aNode).getContext());
+ return xServiceInfo;
+ }
+ private XTypeProvider GetTypeProvider (AccessibleTreeNode aNode)
+ {
+ XTypeProvider xTypeProvider = null;
+ if (aNode instanceof AccTreeNode)
+ xTypeProvider = UnoRuntime.queryInterface(
+ XTypeProvider.class, ((AccTreeNode)aNode).getContext());
+ return xTypeProvider;
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent,
+ int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ XServiceInfo xServiceInfo;
+ switch (nIndex)
+ {
+ case 0 : // Implementation name.
+ xServiceInfo = GetServiceInfo (aParent);
+ aChild = new StringNode ("Implementation name: " +
+ (xServiceInfo!=null ? xServiceInfo.getImplementationName()
+ : "<XServiceInfo not supported>"),
+ aParent);
+ break;
+ case 1 :
+ xServiceInfo = GetServiceInfo (aParent);
+ if (xServiceInfo == null)
+ aChild = new StringNode (
+ "Supported services: <XServiceInfo not supported>",
+ aParent);
+ else
+ aChild = CreateServiceTree (aParent, xServiceInfo);
+ break;
+ case 2 :
+ XTypeProvider xTypeProvider = GetTypeProvider (aParent);
+ if (xTypeProvider == null)
+ aChild = new StringNode (
+ "Supported interfaces: <XTypeProvider not supported>",
+ aParent);
+ else
+ aChild = CreateInterfaceTree (aParent, xTypeProvider);
+ break;
+ }
+
+ return aChild;
+ }
+
+
+ private AccessibleTreeNode CreateServiceTree (AccessibleTreeNode aParent,
+ XServiceInfo xServiceInfo)
+ {
+ String[] aServiceNames = xServiceInfo.getSupportedServiceNames();
+ VectorNode aNode = new VectorNode ("Supported Services", aParent);
+
+ int nCount = aServiceNames.length;
+ for (int i=0; i<nCount; i++)
+ aNode.addChild (new StringNode (aServiceNames[i], aParent));
+
+ return aNode;
+ }
+
+ private AccessibleTreeNode CreateInterfaceTree (AccessibleTreeNode aParent,
+ XTypeProvider xTypeProvider)
+ {
+ Type[] aTypes = xTypeProvider.getTypes();
+ VectorNode aNode = new VectorNode ("Supported Interfaces", aParent);
+
+ int nCount = aTypes.length;
+ for (int i=0; i<nCount; i++)
+ aNode.addChild (new StringNode (aTypes[i].getTypeName(), aParent));
+
+ return aNode;
+ }
+}
diff --git a/toolkit/test/accessibility/Canvas.java b/toolkit/test/accessibility/Canvas.java
new file mode 100644
index 000000000..e9149ff82
--- /dev/null
+++ b/toolkit/test/accessibility/Canvas.java
@@ -0,0 +1,463 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Toolkit;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.JViewport;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreePath;
+
+/** This canvas displays accessible objects graphically. Each accessible
+ object with graphical representation is represented by an
+ CanvasShape object and has to be added by the
+ <member>addAccessible</member> member function.
+
+ <p>The canvas listens to selection events of the associated JTree and
+ highlights the first selected node of that tree.</p>
+*/
+class Canvas
+ extends JPanel
+ implements MouseListener, MouseMotionListener, TreeSelectionListener//, Scrollable
+{
+ // This constant can be passed to SetZoomMode to always show the whole screen.
+ public static final int WHOLE_SCREEN = -1;
+
+ public Canvas ()
+ {
+ super (true);
+ maObjects = new java.util.HashMap<AccTreeNode, CanvasShape> ();
+ maNodes = new ArrayList<AccTreeNode> ();
+ maObjectList = new ArrayList<CanvasShape> ();
+ addMouseListener (this);
+ addMouseMotionListener (this);
+ maBoundingBox = new Rectangle (0,0,100,100);
+ maTree = null;
+ mnHOffset = 0;
+ mnVOffset = 0;
+ mnScale = 1;
+ setShowText(false);
+ setShowDescriptions (true);
+ setShowNames (true);
+ setAntialiasing (true);
+ }
+
+ /** Tell the canvas which tree view to use to highlight accessible
+ objects.
+ */
+ public void setTree (JTree aTree)
+ {
+ if (maTree != null)
+ maTree.removeTreeSelectionListener (this);
+ maTree = aTree;
+ if (maTree != null)
+ maTree.addTreeSelectionListener (this);
+ }
+
+
+
+
+ public void addNode (AccTreeNode aNode)
+ {
+ if (maNodes.indexOf (aNode) == -1)
+ {
+ maNodes.add (aNode);
+
+ CanvasShape aObject = maObjects.get (aNode);
+ if (aObject == null)
+ {
+ aObject = new CanvasShape (aNode);
+ // Update bounding box that includes all objects.
+ if (maObjects.isEmpty())
+ maBoundingBox = aObject.getBBox();
+ else
+ maBoundingBox = maBoundingBox.union (aObject.getBBox());
+
+ maObjects.put (aNode, aObject);
+ maObjectList.add (aObject);
+
+ }
+ repaint ();
+ }
+ }
+
+ public void removeNode (AccTreeNode aNode)
+ {
+ int i = maNodes.indexOf (aNode);
+ if( i != -1 )
+ {
+ CanvasShape aObject = maObjects.get(aNode);
+ maObjectList.remove (aObject);
+ maObjects.remove (aNode);
+ maNodes.remove (aNode);
+ repaint ();
+ }
+ }
+
+ public void updateNode (AccTreeNode aNode)
+ {
+ int i = maNodes.indexOf (aNode);
+ if (i != -1)
+ {
+ CanvasShape aObject = maObjects.get(aNode);
+ if (aObject != null)
+ aObject.update();
+ }
+ }
+
+ public void updateNodeGeometry (AccTreeNode aNode)
+ {
+ CanvasShape aObject = maObjects.get(aNode);
+ if (aObject != null)
+ aObject.updateGeometry();
+ }
+
+ public void clear ()
+ {
+ while (maNodes.size() > 0) {
+ removeNode (maNodes.get(0));
+ }
+ maNodes.clear();
+ maObjects.clear();
+ maObjectList.clear();
+ }
+
+ public boolean getShowDescriptions ()
+ {
+ return Options.GetBoolean ("ShowDescriptions");
+ }
+
+ public void setShowDescriptions (boolean bNewValue)
+ {
+ Options.SetBoolean ("ShowDescriptions", bNewValue);
+ repaint ();
+ }
+
+ public boolean getShowNames ()
+ {
+ return Options.GetBoolean ("ShowNames");
+ }
+
+ public void setShowNames (boolean bNewValue)
+ {
+ Options.SetBoolean ("ShowNames", bNewValue);
+ repaint ();
+ }
+
+ public boolean getAntialiasing ()
+ {
+ return Options.GetBoolean ("Antialiasing");
+ }
+
+ public void setAntialiasing (boolean bNewValue)
+ {
+ Options.SetBoolean ("Antialiasing", bNewValue);
+ repaint ();
+ }
+
+ public boolean getShowText ()
+ {
+ return Options.GetBoolean ("ShowText");
+ }
+
+ private void setShowText (boolean bNewValue)
+ {
+ Options.SetBoolean ("ShowText", bNewValue);
+ repaint ();
+ }
+
+ public void setZoomMode (int nZoomMode)
+ {
+ Options.SetInteger ("ZoomMode", nZoomMode);
+ repaint ();
+ }
+
+ private int getZoomMode ()
+ {
+ return Options.GetInteger ("ZoomMode", WHOLE_SCREEN);
+ }
+
+
+ @Override
+ public void paintComponent (Graphics g)
+ {
+ synchronized (g)
+ {
+ super.paintComponent (g);
+
+ Graphics2D g2 = (Graphics2D)g;
+ if (getAntialiasing())
+ g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ else
+ g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_OFF);
+
+ setupTransformation ();
+
+ // Draw the screen representation to give a hint of the location of the
+ // accessible object on the screen.
+ Dimension aScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Rectangle2D.Double aScreen = new Rectangle2D.Double (
+ mnHOffset,
+ mnVOffset,
+ mnScale*aScreenSize.getWidth(),
+ mnScale*aScreenSize.getHeight());
+ // Fill the screen rectangle and draw a frame around it to increase its visibility.
+ g2.setColor (new Color (250,240,230));
+ g2.fill (aScreen);
+ g2.setColor (Color.BLACK);
+ g2.draw (aScreen);
+
+ synchronized (maObjectList)
+ {
+ int nCount = maObjectList.size();
+ boolean bShowDescriptions = getShowDescriptions();
+ boolean bShowNames = getShowNames();
+ boolean bShowText = getShowText();
+ for (int i=0; i<nCount; i++)
+ {
+ CanvasShape aCanvasShape = maObjectList.get(i);
+ aCanvasShape.paint (
+ g2,
+ mnHOffset, mnVOffset, mnScale,
+ bShowDescriptions, bShowNames, bShowText);
+ }
+ }
+
+ // Paint highlighted frame around active object as the last thing.
+ if (maActiveObject != null)
+ maActiveObject.paint_highlight (
+ g2);
+ }
+ }
+
+
+
+
+ /** Set up the transformation so that the graphical display can show a
+ centered representation of the whole screen.
+ */
+ private void setupTransformation ()
+ {
+ // Turn off scrollbars when showing the whole screen. Otherwise show them when needed.
+ JViewport aViewport = (JViewport)getParent();
+ JScrollPane aScrollPane = (JScrollPane)aViewport.getParent();
+ int nZoomMode = getZoomMode();
+ if (nZoomMode == WHOLE_SCREEN)
+ {
+ if (aScrollPane.getHorizontalScrollBarPolicy()
+ != JScrollPane.HORIZONTAL_SCROLLBAR_NEVER)
+ aScrollPane.setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ if (aScrollPane.getVerticalScrollBarPolicy()
+ != JScrollPane.VERTICAL_SCROLLBAR_NEVER)
+ aScrollPane.setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_NEVER);
+ }
+ else
+ {
+ if (aScrollPane.getHorizontalScrollBarPolicy()
+ != JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED)
+ aScrollPane.setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ if (aScrollPane.getVerticalScrollBarPolicy()
+ != JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
+ aScrollPane.setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ }
+
+ Dimension aScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension aWidgetSize = aViewport.getSize();
+ {
+ if ((aScreenSize.getWidth() > 0) && (aScreenSize.getHeight() > 0))
+ {
+ if (nZoomMode == WHOLE_SCREEN)
+ {
+ // Calculate the scales that would map the screen onto the
+ // widget in both of the coordinate axes and select the
+ // smaller
+ // of the two: it maps the screen onto the widget in both
+ // axes at the same time.
+ double nHScale = (aWidgetSize.getWidth() - 10) / aScreenSize.getWidth();
+ double nVScale = (aWidgetSize.getHeight() - 10) / aScreenSize.getHeight();
+ if (nHScale < nVScale)
+ mnScale = nHScale;
+ else
+ mnScale = nVScale;
+ }
+ else
+ {
+ mnScale = nZoomMode / 100.0;
+ }
+
+ // Calculate offsets that center the scaled screen inside the widget.
+ mnHOffset = (aWidgetSize.getWidth() - mnScale*aScreenSize.getWidth()) / 2.0;
+ mnVOffset = (aWidgetSize.getHeight() - mnScale*aScreenSize.getHeight()) / 2.0;
+ if (mnHOffset < 0)
+ mnHOffset = 0;
+ if (mnVOffset < 0)
+ mnVOffset = 0;
+
+ setPreferredSize (new Dimension (
+ (int)(2*mnHOffset + mnScale * aScreenSize.getWidth()),
+ (int)(2*mnVOffset + mnScale * aScreenSize.getHeight())));
+ revalidate ();
+ }
+ else
+ {
+ // In case of a degenerate (not yet initialized?) screen size
+ // use some meaningless default values.
+ mnScale = 1;
+ mnHOffset = 0;
+ mnVOffset = 0;
+ }
+ }
+ }
+
+
+
+ /** Call getAccessibleAt to determine accessible object under mouse.
+ */
+ public void mouseClicked (MouseEvent e)
+ {
+ }
+
+ public void mousePressed (MouseEvent e)
+ {
+ CanvasShape aObjectUnderMouse = FindCanvasShapeUnderMouse (e);
+ highlightObject (aObjectUnderMouse);
+ if ((e.getModifiers() & InputEvent.CTRL_MASK) != 0)
+ {
+ maTree.expandPath (aObjectUnderMouse.getPath());
+ }
+ }
+
+ public void mouseReleased (MouseEvent e)
+ {
+ }
+
+ public void mouseEntered (MouseEvent e)
+ {
+ }
+
+ public void mouseExited (MouseEvent e)
+ {
+ // Deselect currently active object.
+ if (maActiveObject != null)
+ {
+ maActiveObject.unhighlight ();
+ maActiveObject = null;
+ repaint ();
+ }
+ }
+
+ public void mouseDragged (MouseEvent e)
+ {
+ }
+
+ public void mouseMoved (MouseEvent e)
+ {
+ if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0)
+ highlightObject (FindCanvasShapeUnderMouse (e));
+ }
+
+ private CanvasShape FindCanvasShapeUnderMouse (MouseEvent e)
+ {
+ CanvasShape aObjectUnderMouse = null;
+ int nCount = maObjectList.size();
+ for (int i=nCount-1; i>=0; --i)
+ {
+ CanvasShape aObject = maObjectList.get(i);
+ if (aObject != null && aObject.contains (e.getX(),e.getY()))
+ {
+ aObjectUnderMouse = aObject;
+ break;
+ }
+ }
+ return aObjectUnderMouse;
+ }
+
+ private boolean highlightObject (CanvasShape aNewActiveObject)
+ {
+ if (aNewActiveObject != maActiveObject)
+ {
+ if (maActiveObject != null)
+ maActiveObject.unhighlight();
+
+ maActiveObject = aNewActiveObject;
+ if (maActiveObject != null)
+ {
+ if (maTree != null)
+ {
+ maTree.scrollPathToVisible (maActiveObject.getPath());
+ maTree.setSelectionPath (maActiveObject.getPath());
+ maTree.repaint ();
+ }
+ maActiveObject.highlight ();
+ repaint ();
+ }
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /** Called when the selection of the tree changes. Highlight the
+ corresponding graphical representation of the first selected object.
+ */
+ public void valueChanged (javax.swing.event.TreeSelectionEvent event)
+ {
+ TreePath aPath = event.getPath();
+ Object aObject = aPath.getLastPathComponent();
+ if (aObject instanceof AccTreeNode)
+ {
+ CanvasShape aCanvasShape = maObjects.get (aObject);
+ if (highlightObject (aCanvasShape))
+ repaint();
+ }
+ }
+
+ private double
+ mnHOffset,
+ mnVOffset,
+ mnScale;
+ private CanvasShape
+ maActiveObject;
+ private final java.util.HashMap<AccTreeNode, CanvasShape>
+ maObjects;
+ private final List<CanvasShape>
+ maObjectList;
+ private final List<AccTreeNode>
+ maNodes;
+ private Rectangle
+ maBoundingBox;
+ private JTree
+ maTree;
+}
diff --git a/toolkit/test/accessibility/CanvasShape.java b/toolkit/test/accessibility/CanvasShape.java
new file mode 100644
index 000000000..19aa983de
--- /dev/null
+++ b/toolkit/test/accessibility/CanvasShape.java
@@ -0,0 +1,290 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.awt.*;
+import javax.swing.tree.*;
+import java.awt.geom.Rectangle2D;
+
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleComponent;
+import com.sun.star.accessibility.XAccessibleText;
+import com.sun.star.accessibility.XAccessibleStateSet;
+import com.sun.star.accessibility.AccessibleStateType;
+
+class CanvasShape
+{
+ private final Color maHighlightColor = Color.red;
+ private final Color maSelectionColor = Color.green;
+ private final Color maFocusColor = Color.blue;
+
+ public CanvasShape (AccTreeNode aNode)
+ {
+ maNode = aNode;
+ mxContext = aNode.getContext();
+ msName = "name unknown";
+ msDescription = "description unknown";
+ maShape = new Rectangle2D.Double (-10,-10,10,10);
+ maPosition = new Point (-10,-10);
+ maSize = new Dimension (10,10);
+ maFgColor = java.awt.Color.black;
+ maBgColor = Color.blue;
+ mbHighlighted = false;
+ mbSelected = false;
+ mbFocused = false;
+ mxComponent = aNode.getComponent();
+
+ update ();
+ }
+
+
+
+ /** Update the data obtained from the xAccessible.
+ */
+ public void update ()
+ {
+ if (mxContext != null)
+ {
+ msName = mxContext.getAccessibleName();
+ msDescription = mxContext.getAccessibleDescription();
+
+ // Extract the selected and focused flag.
+ XAccessibleStateSet xStateSet = mxContext.getAccessibleStateSet ();
+ if (xStateSet != null)
+ {
+ mbSelected = xStateSet.contains (AccessibleStateType.SELECTED);
+ mbFocused = xStateSet.contains (AccessibleStateType.FOCUSED);
+ }
+ }
+
+ updateGeometry ();
+ if (mxComponent != null)
+ {
+ // Note: alpha values in office 0..255 have to be mapped to
+ // 255..0 in Java
+ Color aCol = new Color (mxComponent.getForeground(), true);
+ maFgColor = new Color (aCol.getRed (),
+ aCol.getGreen (),
+ aCol.getBlue (),
+ 0xff - aCol.getAlpha ());
+ aCol = new Color (mxComponent.getBackground(), true);
+ maBgColor = new Color (aCol.getRed (),
+ aCol.getGreen (),
+ aCol.getBlue (),
+ 0xff - aCol.getAlpha ());
+ }
+ }
+
+ public void updateGeometry ()
+ {
+ if (mxComponent != null)
+ {
+ com.sun.star.awt.Point aLocationOnScreen = mxComponent.getLocationOnScreen();
+ com.sun.star.awt.Size aSizeOnScreen = mxComponent.getSize();
+ maPosition = new Point (
+ aLocationOnScreen.X,
+ aLocationOnScreen.Y);
+ maSize = new Dimension (
+ aSizeOnScreen.Width,
+ aSizeOnScreen.Height);
+ }
+ }
+
+
+ /** Paint the object into the specified canvas. It is transformed
+ according to the specified offset and scale.
+ */
+ public void paint (Graphics2D g,
+ double nXOffset, double nYOffset, double nScaleFactor,
+ boolean bShowDescription, boolean bShowName, boolean bShowText)
+ {
+ try{
+ // Transform the object's position and size according to the
+ // specified offset and scale.
+ maShape = new Rectangle2D.Double (
+ maPosition.x * nScaleFactor + nXOffset,
+ maPosition.y * nScaleFactor + nYOffset,
+ maSize.width * nScaleFactor,
+ maSize.height * nScaleFactor);
+
+ // Fill the object's bounding box with its background color if it
+ // has no children.
+ if (mxContext.getAccessibleChildCount() == 0)
+ {
+ g.setColor (maBgColor);
+ g.fill (maShape);
+ }
+
+ // Remove alpha channel from color before drawing the frame.
+ Color color = maFgColor;
+ if (maFgColor.getAlpha()<128)
+ color = new Color (maFgColor.getRed(), maFgColor.getGreen(), maFgColor.getBlue());
+ g.setColor (color);
+ g.draw (maShape);
+
+ if (mbFocused)
+ {
+ g.setColor (maFocusColor);
+ for (int x=0; x<=2; x++)
+ for (int y=0; y<=2; y++)
+ g.fill (
+ new Rectangle2D.Double (
+ maShape.x + x/2.0 * maShape.width-3,
+ maShape.y + y/2.0 * maShape.height-3,
+ 6,
+ 6));
+ }
+ if (mbSelected)
+ {
+ g.setColor (maSelectionColor);
+ for (int x=0; x<=2; x++)
+ for (int y=0; y<=2; y++)
+ g.draw (
+ new Rectangle2D.Double (
+ maShape.x + x/2.0 * maShape.width-2,
+ maShape.y + y/2.0 * maShape.height-2,
+ 4,
+ 4));
+ }
+
+ // Write the object's text OR name and description.
+ g.setColor (maFgColor);
+ if (bShowName)
+ paintName (g);
+ if (bShowDescription)
+ paintDescription (g);
+ if (bShowText)
+ paintText (g);
+ }
+ catch (Exception e)
+ { // don't care
+ }
+ }
+
+ public void paint_highlight (Graphics2D g)
+ {
+ if (mbHighlighted)
+ g.setColor (maHighlightColor);
+ else
+ g.setColor (maFgColor);
+ g.draw (maShape);
+ }
+
+
+
+
+ private void paintName (Graphics2D g)
+ {
+ g.drawString ("Name: " + msName,
+ (float)maShape.x+5,
+ (float)maShape.y+15);
+ }
+
+
+
+ private void paintDescription (Graphics2D g)
+ {
+ g.drawString ("Description: " + msDescription,
+ (float)maShape.x+5,
+ (float)maShape.y+35);
+ }
+
+
+
+
+ private void paintText (Graphics2D g)
+ {
+ XAccessibleText xText = null;
+ // get XAccessibleText
+ xText = maNode.getText();
+
+ // Draw every character in the text string.
+ if (xText != null)
+ {
+ String sText = xText.getText();
+ try
+ {
+ for(int i = 0; i < sText.length(); i++)
+ {
+ com.sun.star.awt.Rectangle aRect =
+ xText.getCharacterBounds(i);
+
+ double x = maShape.x + aRect.X;
+ double y = maShape.y + aRect.Y + aRect.Height;
+
+ g.drawString(sText.substring(i, i+1), (float)x, (float)y);
+ }
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException e)
+ {}
+ }
+ }
+
+
+
+
+ /** Compute whether the specified point lies inside the object's
+ bounding box.
+ */
+ public boolean contains (int x, int y)
+ {
+ return maShape.contains (x,y);
+ }
+
+ public void highlight ()
+ {
+ mbHighlighted = true;
+ }
+
+ public void unhighlight ()
+ {
+ mbHighlighted = false;
+ }
+
+ public Rectangle getBBox ()
+ {
+ return new Rectangle (maPosition, maSize);
+ }
+
+ public TreePath getPath ()
+ {
+ return new TreePath (maNode.createPath());
+ }
+
+ @Override
+ public String toString ()
+ {
+ return ">"+msName+", "+msDescription+" +"+maPosition.x+"+"+maPosition.y
+ +"x"+maSize.width+"x"+maSize.height+"<";
+ }
+
+ private final AccTreeNode maNode;
+ private final XAccessibleContext mxContext;
+ private final XAccessibleComponent mxComponent;
+ private String msDescription, msName;
+ private Rectangle2D.Double maShape;
+ private Point maPosition;
+ private Dimension maSize;
+ private Color maFgColor, maBgColor;
+ private boolean
+ // Highlighting objects is an internal concept. Corresponds to selection in the tree view.
+ mbHighlighted,
+ // Set when the accessible object is selected.
+ mbSelected,
+ // Set when the accessible object is focused.
+ mbFocused;
+}
diff --git a/toolkit/test/accessibility/ChildEventHandler.java b/toolkit/test/accessibility/ChildEventHandler.java
new file mode 100644
index 000000000..e36f3502a
--- /dev/null
+++ b/toolkit/test/accessibility/ChildEventHandler.java
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.uno.UnoRuntime;
+
+import java.io.PrintStream;
+
+class ChildEventHandler
+ extends EventHandler
+{
+ public ChildEventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel)
+ {
+ super (aEvent, aTreeModel);
+ mxOldChild = UnoRuntime.queryInterface(
+ XAccessible.class, aEvent.OldValue);
+ mxNewChild = UnoRuntime.queryInterface(
+ XAccessible.class, aEvent.NewValue);
+ }
+
+ @Override
+ public void PrintOldAndNew (PrintStream out)
+ {
+ if (mxOldChild != null)
+ out.println (" removing child " + mxOldChild);
+ if (mxNewChild != null)
+ out.println (" adding child " + mxNewChild);
+ }
+
+ @Override
+ public void Process ()
+ {
+ // Insertion and removal of children should be mutually exclusive.
+ // But this is a test tool and should take everything into account.
+ if (mxOldChild != null)
+ {
+ maTreeModel.removeNode (mxOldChild.getAccessibleContext());
+ maTreeModel.updateNode (mxEventSource, AccessibleTreeHandler.class);
+ }
+
+ if (mxNewChild != null)
+ {
+ maTreeModel.addChild (mxEventSource, mxNewChild);
+ }
+ }
+
+
+ private final XAccessible mxOldChild;
+ private final XAccessible mxNewChild;
+}
diff --git a/toolkit/test/accessibility/ContextEventHandler.java b/toolkit/test/accessibility/ContextEventHandler.java
new file mode 100644
index 000000000..12ffd0648
--- /dev/null
+++ b/toolkit/test/accessibility/ContextEventHandler.java
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.uno.AnyConverter;
+
+import java.io.PrintStream;
+
+import tools.NameProvider;
+
+class ContextEventHandler
+ extends EventHandler
+{
+ public ContextEventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel)
+ {
+ super (aEvent, aTreeModel);
+ }
+
+ @Override
+ public void PrintOldAndNew (PrintStream out)
+ {
+ switch (mnEventId)
+ {
+ case AccessibleEventId.STATE_CHANGED:
+ try
+ {
+ int nOldValue = AnyConverter.toInt (maEvent.OldValue);
+ out.println (" turning off state " + nOldValue + " ("
+ + NameProvider.getStateName (nOldValue) + ")");
+ }
+ catch (com.sun.star.lang.IllegalArgumentException e)
+ {}
+ try
+ {
+ int nNewValue = AnyConverter.toInt (maEvent.NewValue);
+ out.println (" turning on state " + nNewValue + " ("
+ + NameProvider.getStateName (nNewValue) + ")");
+ }
+ catch (com.sun.star.lang.IllegalArgumentException e)
+ {}
+ break;
+
+ default:
+ super.PrintOldAndNew (out);
+ }
+
+ }
+
+ @Override
+ public void Process ()
+ {
+ maTreeModel.updateNode (mxEventSource, AccessibleContextHandler.class);
+ }
+}
diff --git a/toolkit/test/accessibility/EventHandler.java b/toolkit/test/accessibility/EventHandler.java
new file mode 100644
index 000000000..ed1a7adb4
--- /dev/null
+++ b/toolkit/test/accessibility/EventHandler.java
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.uno.UnoRuntime;
+
+import java.io.PrintStream;
+
+import tools.NameProvider;
+
+/** Base class for handling of accessibility events.
+*/
+class EventHandler
+{
+ public EventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel)
+ {
+ maEvent = aEvent;
+ maTreeModel = aTreeModel;
+
+ mnEventId = aEvent.EventId;
+
+ mxEventSource = UnoRuntime.queryInterface(
+ XAccessibleContext.class, aEvent.Source);
+ if (mxEventSource == null)
+ {
+ XAccessible xAccessible = UnoRuntime.queryInterface(
+ XAccessible.class, aEvent.Source);
+ if (xAccessible != null)
+ mxEventSource = xAccessible.getAccessibleContext();
+ }
+ }
+
+ public void Print (PrintStream out)
+ {
+ out.println ("Event id is " + mnEventId
+ + " (" + NameProvider.getEventName(mnEventId)+")"
+ + " for " + mxEventSource.getAccessibleName() + " / "
+ + NameProvider.getRoleName (mxEventSource.getAccessibleRole()));
+ PrintOldAndNew (out);
+ }
+
+ public void PrintOldAndNew (PrintStream out)
+ {
+ out.println (" old value is " + maEvent.OldValue);
+ out.println (" new value is " + maEvent.NewValue);
+ }
+
+ public void Process ()
+ {
+ System.out.println ("processing of event " + maEvent + " not implemented");
+ }
+
+ protected AccessibleEventObject maEvent;
+ protected AccessibilityTreeModel maTreeModel;
+
+ protected int mnEventId;
+ protected XAccessibleContext mxEventSource;
+}
diff --git a/toolkit/test/accessibility/EventListener.java b/toolkit/test/accessibility/EventListener.java
new file mode 100644
index 000000000..5d9141953
--- /dev/null
+++ b/toolkit/test/accessibility/EventListener.java
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.*;
+
+/** Objects of this class (usually one, singleton?) listen to accessible
+ events of all objects in all trees.
+*/
+public class EventListener
+{
+ private boolean mbVerbose = false;
+
+ public EventListener (AccessibilityTreeModel aTreeModel)
+ {
+ maTreeModel = aTreeModel;
+ }
+
+
+ /** This method handles accessibility objects that are being disposed.
+ */
+ public void disposing (XAccessibleContext xContext)
+ {
+ if (mbVerbose)
+ System.out.println("disposing " + xContext);
+ maTreeModel.removeNode (xContext);
+ }
+
+ /** This method is called from accessible objects that broadcast
+ modifications of themselves or from their children. The event is
+ processed only, except printing some messages, if the tree is not
+ locked. It should be locked during changes to its internal
+ structure like expanding nodes.
+ */
+ public void notifyEvent (AccessibleEventObject aEvent)
+ {
+ EventHandler aHandler;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId.CHILD:
+ aHandler = new ChildEventHandler (aEvent, maTreeModel);
+ break;
+
+ case AccessibleEventId.BOUNDRECT_CHANGED:
+ case AccessibleEventId.VISIBLE_DATA_CHANGED:
+ aHandler = new GeometryEventHandler (aEvent, maTreeModel);
+ break;
+
+
+ case AccessibleEventId.NAME_CHANGED:
+ case AccessibleEventId.DESCRIPTION_CHANGED:
+ case AccessibleEventId.STATE_CHANGED:
+ case AccessibleEventId.SELECTION_CHANGED:
+ aHandler = new ContextEventHandler (aEvent, maTreeModel);
+ break;
+
+ case AccessibleEventId.TABLE_MODEL_CHANGED:
+ case AccessibleEventId.TABLE_CAPTION_CHANGED:
+ case AccessibleEventId.TABLE_COLUMN_DESCRIPTION_CHANGED:
+ case AccessibleEventId.TABLE_COLUMN_HEADER_CHANGED:
+ case AccessibleEventId.TABLE_ROW_DESCRIPTION_CHANGED:
+ case AccessibleEventId.TABLE_ROW_HEADER_CHANGED:
+ case AccessibleEventId.TABLE_SUMMARY_CHANGED:
+ aHandler = new TableEventHandler (aEvent, maTreeModel);
+ break;
+
+ case AccessibleEventId.ACTION_CHANGED:
+ case AccessibleEventId.HYPERTEXT_CHANGED:
+ case AccessibleEventId.ACTIVE_DESCENDANT_CHANGED:
+ case AccessibleEventId.CARET_CHANGED:
+ case AccessibleEventId.TEXT_CHANGED:
+ case AccessibleEventId.VALUE_CHANGED:
+ aHandler = new EventHandler (aEvent, maTreeModel);
+ break;
+
+ default:
+ aHandler = null;
+ break;
+ }
+
+ if (aHandler == null)
+ System.out.println (" unhandled event");
+ else
+ {
+ if (mbVerbose)
+ aHandler.Print (System.out);
+ aHandler.Process ();
+ }
+ }
+
+
+ private final AccessibilityTreeModel maTreeModel;
+}
diff --git a/toolkit/test/accessibility/EventQueue.java b/toolkit/test/accessibility/EventQueue.java
new file mode 100644
index 000000000..b6f6c6415
--- /dev/null
+++ b/toolkit/test/accessibility/EventQueue.java
@@ -0,0 +1,140 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.util.LinkedList;
+
+/** The event queue singleton dispatches events received from OpenOffice.org
+ applications in a thread separate from the AWB main thread.
+
+ The queue of event objects, LinkedList<Runnable> The queue object will
+ also serve as lock for the consumer/producer type synchronization.
+*/
+class EventQueue
+ implements Runnable
+{
+ private boolean mbVerbose = false;
+ private boolean mbHandleDisposingEventsSynchronous = true;
+
+ public synchronized static EventQueue Instance ()
+ {
+ if (maInstance == null)
+ maInstance = new EventQueue ();
+ return maInstance;
+ }
+
+ public void addEvent (Runnable aEvent)
+ {
+ synchronized (maMonitor)
+ {
+ if (mbVerbose)
+ System.out.println ("queueing regular event " + aEvent);
+ maRegularQueue.addLast (aEvent);
+ maMonitor.notify ();
+ }
+ }
+
+
+ public void addDisposingEvent (Runnable aEvent)
+ {
+ if (mbHandleDisposingEventsSynchronous)
+ aEvent.run ();
+ else
+ synchronized (maMonitor)
+ {
+ if (mbVerbose)
+ System.out.println ("queueing disposing event " + aEvent);
+ maDisposingQueue.addLast (aEvent);
+ maMonitor.notify ();
+ }
+ }
+
+
+ private EventQueue ()
+ {
+ maRegularQueue = new LinkedList<Runnable>();
+ maDisposingQueue = new LinkedList<Runnable>();
+ new Thread(this, "AWB.EventQueue").start();
+ }
+
+
+ /// This thread's main method: deliver all events
+ public void run()
+ {
+ // in an infinite loop, check for events to deliver, then
+ // wait on lock (which will be notified when new events arrive)
+ while( true )
+ {
+ Runnable aEvent = null;
+ do
+ {
+ synchronized (maMonitor)
+ {
+ if (maDisposingQueue.size() > 0)
+ {
+ aEvent = maDisposingQueue.removeFirst();
+ if (mbVerbose)
+ System.out.println ("delivering disposing event " + aEvent);
+ }
+ else if (maRegularQueue.size() > 0)
+ {
+ aEvent = maRegularQueue.removeFirst();
+ if (mbVerbose)
+ System.out.println ("delivering regular event " + aEvent);
+ }
+ else
+ aEvent = null;
+ }
+ if (aEvent != null)
+ {
+ try
+ {
+ aEvent.run();
+ }
+ catch( Throwable e )
+ {
+ System.out.println(
+ "caught exception during event delivery: " + e );
+ e.printStackTrace();
+ }
+ }
+ }
+ while( aEvent != null );
+
+ try
+ {
+ synchronized (maMonitor)
+ {
+ maMonitor.wait();
+ }
+ }
+ catch (Exception e)
+ {
+ // can't wait? odd!
+ System.err.println("Can't wait!");
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static EventQueue maInstance = null;
+ private final Object maMonitor = new Object();
+ private final LinkedList<Runnable> maRegularQueue;
+ private final LinkedList<Runnable> maDisposingQueue;
+}
+
+
diff --git a/toolkit/test/accessibility/GeometryEventHandler.java b/toolkit/test/accessibility/GeometryEventHandler.java
new file mode 100644
index 000000000..c55ee3acc
--- /dev/null
+++ b/toolkit/test/accessibility/GeometryEventHandler.java
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.AccessibleEventObject;
+import java.io.PrintStream;
+import java.util.LinkedList;
+
+class GeometryEventHandler
+ extends EventHandler
+{
+ public GeometryEventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel)
+ {
+ super (aEvent, aTreeModel);
+ }
+
+ @Override
+ public void PrintOldAndNew (PrintStream out)
+ {
+ out.println (" children not relevant");
+ }
+
+ @Override
+ public void Process ()
+ {
+ AccTreeNode aNode = maTreeModel.updateNode (mxEventSource,
+ AccessibleComponentHandler.class,
+ AccessibleExtendedComponentHandler.class);
+
+ // Update the graphical representation of aNode in the Canvas.
+ Canvas aCanvas = maTreeModel.getCanvas();
+ if (aCanvas != null)
+ {
+ // Iterate over all nodes in the sub-tree rooted in aNode.
+ LinkedList<Object> aShapeQueue = new LinkedList<Object>();
+ aShapeQueue.addLast (aNode);
+ while (aShapeQueue.size() > 0)
+ {
+ // Remove the first node from the queue and update its
+ // graphical representation.
+ AccTreeNode aShapeNode = (AccTreeNode) aShapeQueue.getFirst();
+ aShapeQueue.removeFirst();
+ aCanvas.updateNodeGeometry (aShapeNode);
+
+ // Add the node's children to the queue.
+ int nChildCount = maTreeModel.getChildCount (aShapeNode);
+ for (int i=0; i<nChildCount; i++)
+ {
+ Object aTreeNode = maTreeModel.getChildNoCreate (aShapeNode, i);
+ if (aTreeNode instanceof AccTreeNode)
+ aShapeQueue.addLast (aTreeNode);
+ }
+ }
+ aCanvas.repaint ();
+ }
+ }
+}
diff --git a/toolkit/test/accessibility/HelpWindow.java b/toolkit/test/accessibility/HelpWindow.java
new file mode 100644
index 000000000..00c934067
--- /dev/null
+++ b/toolkit/test/accessibility/HelpWindow.java
@@ -0,0 +1,189 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JEditorPane;
+import javax.swing.JButton;
+import java.net.URL;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.event.HyperlinkEvent;
+import java.net.MalformedURLException;
+import java.io.File;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import java.awt.event.ActionListener;
+import java.util.LinkedList;
+
+class HelpWindow
+ implements ActionListener
+{
+ public static synchronized HelpWindow Instance ()
+ {
+ if (maInstance == null)
+ maInstance = new HelpWindow();
+ return maInstance;
+ }
+
+ public void loadFile (String sFilename)
+ {
+ File aFile = new File (sFilename);
+ try
+ {
+ loadURL (aFile.toURI().toURL());
+ }
+ catch (MalformedURLException e)
+ {
+ e.printStackTrace (System.err);
+ }
+ }
+
+ private void loadURL (URL aURL)
+ {
+ maHistory.addLast (aURL);
+ selectHistoryPage (maHistory.size()-1);
+ maFrame.toFront ();
+ }
+
+
+
+
+ private HelpWindow ()
+ {
+ try
+ {
+ maCurrentHistoryEntry = -1;
+ maHistory = new LinkedList<URL>();
+
+ maFrame = new JFrame ();
+ maFrame.addWindowListener (new WindowAdapter ()
+ {
+ @Override
+ public void windowClosing (WindowEvent e)
+ {
+ maInstance = null;
+ }
+ });
+ maContent = createContentWidget();
+
+ maFrame.getContentPane().setLayout (new GridBagLayout());
+ GridBagConstraints aConstraints = new GridBagConstraints ();
+ aConstraints.gridx = 0;
+ aConstraints.gridy = 0;
+ aConstraints.gridwidth = 3;
+ aConstraints.weightx = 1;
+ aConstraints.weighty = 1;
+ aConstraints.fill = GridBagConstraints.BOTH;
+ maFrame.getContentPane().add (new JScrollPane (maContent), aConstraints);
+
+ aConstraints = new GridBagConstraints();
+ aConstraints.gridx = 0;
+ aConstraints.gridy = 1;
+ maPrevButton = new JButton ("Prev");
+ maFrame.getContentPane().add (maPrevButton, aConstraints);
+ maPrevButton.addActionListener (this);
+
+ aConstraints = new GridBagConstraints();
+ aConstraints.gridx = 1;
+ aConstraints.gridy = 1;
+ maNextButton = new JButton ("Next");
+ maFrame.getContentPane().add (maNextButton, aConstraints);
+ maNextButton.addActionListener (this);
+
+ aConstraints = new GridBagConstraints();
+ aConstraints.gridx = 2;
+ aConstraints.gridy = 1;
+ aConstraints.anchor = GridBagConstraints.EAST;
+ JButton aButton = new JButton ("Close");
+ maFrame.getContentPane().add (aButton, aConstraints);
+ aButton.addActionListener (this);
+
+ maFrame.setSize (600,400);
+ maFrame.setVisible (true);
+ }
+ catch (Exception e)
+ {}
+ }
+
+ public void actionPerformed (java.awt.event.ActionEvent e)
+ {
+ if (e.getActionCommand().equals("Prev"))
+ {
+ selectHistoryPage (maCurrentHistoryEntry - 1);
+ }
+ else if (e.getActionCommand().equals("Next"))
+ {
+ selectHistoryPage (maCurrentHistoryEntry + 1);
+ }
+ else if (e.getActionCommand().equals("Close"))
+ {
+ maFrame.dispose ();
+ maInstance = null;
+ }
+ }
+
+ private JEditorPane createContentWidget ()
+ {
+ JEditorPane aContent = new JEditorPane ();
+ aContent.setEditable (false);
+ aContent.addHyperlinkListener (new HyperlinkListener()
+ {
+ public void hyperlinkUpdate (HyperlinkEvent e)
+ {
+ if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
+ HelpWindow.Instance().loadURL (e.getURL());
+ }
+ });
+ return aContent;
+ }
+
+ private void selectHistoryPage (int i)
+ {
+ if (i < 0)
+ i = 0;
+ else if (i >= maHistory.size()-1)
+ i = maHistory.size()-1;
+ if (i != maCurrentHistoryEntry)
+ {
+ URL aURL = maHistory.get (i);
+ try
+ {
+ maContent.setPage (aURL);
+ }
+ catch (java.io.IOException ex)
+ {
+ ex.printStackTrace(System.err);
+ }
+
+ maCurrentHistoryEntry = i;
+ }
+
+ maPrevButton.setEnabled (maCurrentHistoryEntry > 0);
+ maNextButton.setEnabled (maCurrentHistoryEntry < maHistory.size()-1);
+ }
+
+ private static HelpWindow maInstance = null;
+ private JFrame maFrame;
+ private JEditorPane maContent;
+ private LinkedList<URL> maHistory;
+ private int maCurrentHistoryEntry;
+ private JButton maPrevButton;
+ private JButton maNextButton;
+}
diff --git a/toolkit/test/accessibility/MessageArea.java b/toolkit/test/accessibility/MessageArea.java
new file mode 100644
index 000000000..512cfaf73
--- /dev/null
+++ b/toolkit/test/accessibility/MessageArea.java
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.awt.Font;
+import java.awt.Color;
+import java.awt.Graphics;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JScrollBar;
+
+
+
+/** A message area displays text in a scrollable text widget. It is a
+ singleton. Other objects can access it directly to display messages.
+*/
+public class MessageArea
+ extends JScrollPane
+{
+ public static synchronized MessageArea Instance ()
+ {
+ if (saInstance == null)
+ saInstance = new MessageArea ();
+ return saInstance;
+ }
+
+
+
+
+ /** Create a new message area. This method is private because the class is
+ a singleton and may therefore not be instantiated from the outside.
+ */
+ private MessageArea ()
+ {
+ maText = new JTextArea();
+ maText.setBackground (new Color (255,250,240));
+ maText.setFont (new Font ("Helvetica", Font.PLAIN, 9));
+ setViewportView (maText);
+ setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+
+ printMessage (
+ "class path is " + System.getProperty ("java.class.path") + "\n");
+ }
+
+
+
+
+ /** Show the given string at the end of the message area and scroll to make
+ it visible. Indent the string as requested.
+ */
+ private static synchronized void print (int nIndentation, String aMessage)
+ {
+ while (nIndentation-- > 0) {
+ aMessage = " " + aMessage;
+ }
+ Instance().printMessage(aMessage);
+ }
+
+
+
+
+ /** Show the given string at the end of the message area and scroll to make
+ it visible.
+ */
+ public static void println (String aMessage)
+ {
+ println (0, aMessage);
+ }
+
+
+
+
+ /** Show the given string at the end of the message area and scroll to make
+ it visible.
+ */
+ private static void println (int nIndentation, String aMessage)
+ {
+ print (nIndentation, aMessage+"\n");
+ }
+
+
+
+
+ @Override
+ public void paintComponent (Graphics g)
+ {
+ synchronized (g)
+ {
+ JScrollBar sb = getVerticalScrollBar();
+ if (sb != null)
+ {
+ int nScrollBarValue = sb.getMaximum() - sb.getVisibleAmount() - 1;
+ sb.setValue (nScrollBarValue);
+ }
+ super.paintComponent (g);
+ }
+ }
+
+
+
+
+ /** Append the given string to the end of the text and scroll so that it
+ becomes visible. This is an internal method. Use one of the static
+ and public ones.
+ */
+ private synchronized void printMessage (String aMessage)
+ {
+ maText.append (aMessage);
+ }
+
+
+
+
+ private static MessageArea saInstance = null;
+ private final JTextArea maText;
+}
diff --git a/toolkit/test/accessibility/NodeFactory.java b/toolkit/test/accessibility/NodeFactory.java
new file mode 100644
index 000000000..7e1d9f585
--- /dev/null
+++ b/toolkit/test/accessibility/NodeFactory.java
@@ -0,0 +1,142 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.*;
+import tools.NameProvider;
+
+/** This singleton class creates nodes for given accessible objects.
+*/
+class NodeFactory
+{
+ public synchronized static NodeFactory Instance ()
+ {
+ if (maInstance == null)
+ {
+ maInstance = new NodeFactory();
+ }
+ return maInstance;
+ }
+
+ private NodeFactory ()
+ {
+ }
+
+
+ /** add default handlers based on the supported interfaces */
+ private void addDefaultHandlers (AccTreeNode aNode, XAccessibleContext xContext)
+ {
+ if (false)
+ {
+ // Slow but complete version: try each handler type separately.
+ aNode.addHandler (maContextHandler.createHandler (xContext));
+ aNode.addHandler (maTextHandler.createHandler (xContext));
+ aNode.addHandler (maEditableTextHandler.createHandler (xContext));
+ aNode.addHandler (maComponentHandler.createHandler (xContext));
+ aNode.addHandler (maExtendedComponentHandler.createHandler (xContext));
+ aNode.addHandler (maActionHandler.createHandler (xContext));
+ aNode.addHandler (maImageHandler.createHandler (xContext));
+ aNode.addHandler (maTableHandler.createHandler (xContext));
+ aNode.addHandler (maCellHandler.createHandler (xContext));
+ aNode.addHandler (maHypertextHandler.createHandler (xContext));
+ aNode.addHandler (maHyperlinkHandler.createHandler (xContext));
+ aNode.addHandler (maSelectionHandler.createHandler (xContext));
+ aNode.addHandler (maRelationHandler.createHandler (xContext));
+ aNode.addHandler (maUNOHandler.createHandler (xContext));
+ aNode.addHandler (maTreeHandler.createHandler (xContext));
+ }
+ else
+ {
+ // Exploit dependencies between interfaces.
+ NodeHandler aHandler;
+ aNode.addHandler (maContextHandler.createHandler (xContext));
+
+ aHandler = maTextHandler.createHandler (xContext);
+ if (aHandler != null)
+ {
+ aNode.addHandler (aHandler);
+ aNode.addHandler (maEditableTextHandler.createHandler (xContext));
+ aNode.addHandler (maHypertextHandler.createHandler (xContext));
+ aNode.addHandler (maHyperlinkHandler.createHandler (xContext));
+ }
+ aHandler = maComponentHandler.createHandler (xContext);
+ if (aHandler != null)
+ {
+ aNode.addHandler (aHandler);
+ aNode.addHandler (maExtendedComponentHandler.createHandler (xContext));
+ }
+ aNode.addHandler (maActionHandler.createHandler (xContext));
+ aNode.addHandler (maImageHandler.createHandler (xContext));
+ aNode.addHandler (maTableHandler.createHandler (xContext));
+ aNode.addHandler (maRelationHandler.createHandler (xContext));
+ aNode.addHandler (maCellHandler.createHandler (xContext));
+ aNode.addHandler (maSelectionHandler.createHandler (xContext));
+ aNode.addHandler (maUNOHandler.createHandler (xContext));
+ aNode.addHandler (maTreeHandler.createHandler (xContext));
+ }
+ }
+
+ /** create a node with the default handlers */
+ public AccTreeNode createDefaultNode (XAccessible xAccessible, AccessibleTreeNode aParent)
+ {
+ // default: aObject + aDisplay
+ String sDisplay;
+
+ // if we are accessible, we use the context + name instead
+ XAccessibleContext xContext = null;
+ if (xAccessible != null)
+ xContext = xAccessible.getAccessibleContext();
+ if (xContext != null)
+ {
+ sDisplay = xContext.getAccessibleName();
+ if (sDisplay.length()==0)
+ {
+ sDisplay = "<no name> Role: "
+ + NameProvider.getRoleName (
+ xContext.getAccessibleRole());
+ }
+ }
+ else
+ sDisplay = "not accessible";
+
+
+ // create node, and add default handlers
+ AccTreeNode aNode = new AccTreeNode (xContext, sDisplay, aParent);
+ addDefaultHandlers (aNode, xContext);
+
+ return aNode;
+ }
+
+ private static NodeFactory maInstance = null;
+
+ // default handlers
+ private final NodeHandler maContextHandler = new AccessibleContextHandler();
+ private final NodeHandler maTextHandler = new AccessibleTextHandler();
+ private final NodeHandler maEditableTextHandler = new AccessibleEditableTextHandler();
+ private final NodeHandler maComponentHandler = new AccessibleComponentHandler();
+ private final NodeHandler maExtendedComponentHandler = new AccessibleExtendedComponentHandler();
+ private final NodeHandler maActionHandler = new AccessibleActionHandler();
+ private final NodeHandler maImageHandler = new AccessibleImageHandler();
+ private final NodeHandler maTableHandler = new AccessibleTableHandler();
+ private final NodeHandler maCellHandler = new AccessibleCellHandler();
+ private final NodeHandler maHypertextHandler = new AccessibleHypertextHandler();
+ private final NodeHandler maHyperlinkHandler = new AccessibleHyperlinkHandler();
+ private final NodeHandler maSelectionHandler = new AccessibleSelectionHandler();
+ private final NodeHandler maRelationHandler = new AccessibleRelationHandler();
+ private final NodeHandler maTreeHandler = new AccessibleTreeHandler();
+ private final NodeHandler maUNOHandler = new AccessibleUNOHandler();
+}
diff --git a/toolkit/test/accessibility/NodeHandler.java b/toolkit/test/accessibility/NodeHandler.java
new file mode 100644
index 000000000..69cff2c13
--- /dev/null
+++ b/toolkit/test/accessibility/NodeHandler.java
@@ -0,0 +1,133 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.util.Vector;
+
+
+/**
+ * Map an arbitrary object into parts of a tree node.
+ */
+abstract class NodeHandler
+{
+ /** This vector is used as cache for the child objects.
+ */
+ protected Vector<AccessibleTreeNode> maChildList;
+
+
+ public abstract NodeHandler createHandler (
+ com.sun.star.accessibility.XAccessibleContext xContext);
+
+ public NodeHandler ()
+ {
+ maChildList = new Vector<AccessibleTreeNode> ();
+ }
+
+ /** return the number of children this object has */
+ public int getChildCount()
+ {
+ synchronized (maChildList)
+ {
+ return maChildList.size();
+ }
+ }
+
+ /**
+ * return a child object. Complex
+ * children have to be AccTreeNode instances.
+ * @see AccTreeNode
+ */
+ public AccessibleTreeNode getChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ synchronized (maChildList)
+ {
+ AccessibleTreeNode aChild = maChildList.get(nIndex);
+ if (aChild == null)
+ {
+ aChild = createChild (aParent, nIndex);
+ if (aChild == null)
+ aChild = new StringNode ("could not create child", aParent);
+ maChildList.set (nIndex, aChild);
+ }
+ return aChild;
+ }
+ }
+
+ public AccessibleTreeNode getChildNoCreate (int nIndex)
+ {
+ synchronized (maChildList)
+ {
+ return maChildList.get(nIndex);
+ }
+ }
+
+ /** Remove the specified child from the list of children.
+ */
+ public boolean removeChild (int nIndex)
+ {
+ try
+ {
+ synchronized (maChildList)
+ {
+ System.out.println (" removing child at position " + nIndex + ": "
+ + maChildList.get (nIndex));
+ maChildList.remove (nIndex);
+ }
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public int indexOf (AccessibleTreeNode aNode)
+ {
+ synchronized (maChildList)
+ {
+ return maChildList.indexOf (aNode);
+ }
+ }
+
+ /** Create a child object for the specified data. This method is called
+ usually from getChild and put there into the cache.
+ */
+ public abstract AccessibleTreeNode createChild (
+ AccessibleTreeNode aParent, int nIndex);
+
+
+ // The following methods support editing of children and actions.
+ // They have default implementations for no actions and read-only.
+
+
+ /** get names of supported actions */
+ public String[] getActions (AccessibleTreeNode aNode)
+ {
+ return new String[] {};
+ }
+
+ /** perform action */
+ public void performAction (AccessibleTreeNode aNode, int nIndex)
+ {
+ }
+
+ /** Update all children.
+ */
+ public void update (AccessibleTreeNode aNode)
+ {
+ }
+}
diff --git a/toolkit/test/accessibility/NodeMap.java b/toolkit/test/accessibility/NodeMap.java
new file mode 100644
index 000000000..045c93371
--- /dev/null
+++ b/toolkit/test/accessibility/NodeMap.java
@@ -0,0 +1,117 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.XAccessibleContext;
+
+import java.util.HashMap;
+
+abstract class NodeMapCallback
+{
+ public abstract void Apply (AccTreeNode aNode);
+}
+
+/** This map translates from XAccessible objects to our internal
+ representations.
+*/
+class NodeMap
+{
+ public NodeMap ()
+ {
+ maXAccessibleToNode = new HashMap<XAccessibleContext, AccessibleTreeNode> ();
+ }
+
+ /** Clear the whole map.
+ */
+ public void Clear ()
+ {
+ maXAccessibleToNode.clear();
+ }
+
+ /** @return
+ whether the new node was different from a previous one
+ respectively was the first one set.
+ */
+ public boolean InsertNode (XAccessibleContext xContext, AccessibleTreeNode aNode)
+ {
+ AccessibleTreeNode aPreviousNode = maXAccessibleToNode.put (
+ xContext,
+ aNode);
+ return aPreviousNode != aNode;
+ }
+
+ protected void RemoveNode (AccessibleTreeNode aNode)
+ {
+ try
+ {
+ if ((aNode != null) && (aNode instanceof AccTreeNode))
+ {
+ maXAccessibleToNode.remove (((AccTreeNode)aNode).getContext());
+ }
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception while removing node "
+ + aNode + " : " + e);
+ e.printStackTrace();
+ }
+ }
+
+
+ public void ForEach (NodeMapCallback aFunctor)
+ {
+ Object[] aNodes = maXAccessibleToNode.values().toArray();
+ for (int i=0; i<aNodes.length; i++)
+ {
+ if (aNodes[i] != null && (aNodes[i] instanceof AccTreeNode))
+ {
+ try
+ {
+ aFunctor.Apply ((AccTreeNode)aNodes[i]);
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception applying functor to "
+ + i + "th node " + aNodes[i] + " : " + e);
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ AccessibleTreeNode GetNode (XAccessibleContext xContext)
+ {
+ return maXAccessibleToNode.get (xContext);
+ }
+
+ AccessibleTreeNode GetNode (Object aObject)
+ {
+ if (aObject instanceof XAccessibleContext)
+ return GetNode ((XAccessibleContext)aObject);
+ else
+ return null;
+ }
+
+ boolean ValueIsMember (AccessibleTreeNode aNode)
+ {
+ return maXAccessibleToNode.containsValue(aNode);
+ }
+
+
+
+ private final HashMap<XAccessibleContext, AccessibleTreeNode> maXAccessibleToNode;
+}
diff --git a/toolkit/test/accessibility/OfficeConnection.java b/toolkit/test/accessibility/OfficeConnection.java
new file mode 100644
index 000000000..357c7c6d1
--- /dev/null
+++ b/toolkit/test/accessibility/OfficeConnection.java
@@ -0,0 +1,98 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+// base classes
+import com.sun.star.uno.UnoRuntime;
+
+import com.sun.star.bridge.XUnoUrlResolver;
+import com.sun.star.lang.XMultiServiceFactory;
+
+
+/** @descr This class establishes a connection to a LibreOffice application.
+ */
+public class OfficeConnection
+{
+ public OfficeConnection (int nPortNumber)
+ {
+ mnDefaultPort = nPortNumber;
+ connect ();
+ }
+
+ /** @descr Return the service manager that represents the connected
+ LibreOffice application
+ */
+ public XMultiServiceFactory getServiceManager ()
+ {
+ if ( ! mbInitialized)
+ connect ();
+ return maServiceManager;
+ }
+
+ /** @descr Connect to an already running LibreOffice application.
+ */
+ private void connect ()
+ {
+ connect (msDefaultHost, mnDefaultPort);
+ }
+
+ /** @descr Connect to an already running LibreOffice application that has
+ been started with a command line argument like
+ "--accept=socket,host=localhost,port=5678;urp;"
+ */
+ private void connect (String hostname, int portnumber)
+ {
+ mbInitialized = true;
+ // Set up connection string.
+ String sConnectString = "uno:socket,host=" + hostname + ",port=" + portnumber
+ + ";urp;StarOffice.ServiceManager";
+
+
+ // connect to a running office and get the ServiceManager
+ try
+ {
+ // Create a URL Resolver.
+ XMultiServiceFactory aLocalServiceManager =
+ com.sun.star.comp.helper.Bootstrap.createSimpleServiceManager();
+ XUnoUrlResolver aURLResolver = UnoRuntime.queryInterface (
+ XUnoUrlResolver.class,
+ aLocalServiceManager.createInstance ("com.sun.star.bridge.UnoUrlResolver")
+ );
+
+ maServiceManager = UnoRuntime.queryInterface (
+ XMultiServiceFactory.class,
+ aURLResolver.resolve (sConnectString)
+ );
+ }
+
+ catch (Exception e)
+ {
+ MessageArea.println ("Could not connect with " + sConnectString + " : " + e);
+ MessageArea.println ("Please start LibreOffice with "
+ + "\"--accept=socket,host=localhost,port=5678;urp;\"");
+ }
+ }
+
+ private final int mnDefaultPort;
+ private static final String msDefaultHost = "localhost";
+ private XMultiServiceFactory maServiceManager = null;
+
+ /** A value of true just indicates that it has been tried to establish a connection,
+ not that has been successful.
+ */
+ private boolean mbInitialized = false;
+}
diff --git a/toolkit/test/accessibility/Options.java b/toolkit/test/accessibility/Options.java
new file mode 100644
index 000000000..6cf6e48f2
--- /dev/null
+++ b/toolkit/test/accessibility/Options.java
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+/** Load from and save options into a file.
+*/
+class Options
+ extends Properties
+{
+ public static Options Instance ()
+ {
+ if (saOptions == null)
+ saOptions = new Options ();
+ return saOptions;
+ }
+
+ public static void SetBoolean (String sName, boolean bValue)
+ {
+ Instance().setProperty (sName, Boolean.toString(bValue));
+ }
+
+ public static boolean GetBoolean (String sName)
+ {
+ return Boolean.getBoolean(Instance().getProperty (sName));
+ }
+
+ public static void SetInteger (String sName, int nValue)
+ {
+ Instance().setProperty (sName, Integer.toString(nValue));
+ }
+
+ public static int GetInteger (String sName, int nDefault)
+ {
+ String sValue = Instance().getProperty (sName);
+ if (sValue == null)
+ return nDefault;
+ else
+ return Integer.parseInt (sValue);
+ }
+
+ public void Load (String sBaseName)
+ {
+ FileInputStream fis = null;
+ try
+ {
+ fis = new FileInputStream (ProvideFile(sBaseName));
+ load (fis);
+ }
+ catch (IOException e)
+ {
+ // Ignore a non-existing options file.
+ }
+ finally
+ {
+ try
+ {
+ if (fis != null)
+ fis.close();
+ }
+ catch (IOException ex)
+ {
+ }
+ }
+ }
+
+ public void Save (String sBaseName)
+ {
+ FileOutputStream fos = null;
+ try
+ {
+ fos = new FileOutputStream (ProvideFile(sBaseName));
+ store (fos, null);
+ }
+ catch (IOException e)
+ {
+ }
+ finally
+ {
+ try
+ {
+ if (fos != null)
+ fos.close();
+ }
+ catch (IOException ex)
+ {
+ }
+ }
+ }
+
+ private Options ()
+ {
+ }
+
+ private File ProvideFile (String sBaseName)
+ {
+ return new File (
+ System.getProperty ("user.home"),
+ sBaseName);
+ }
+
+ private static Options saOptions = null;
+}
diff --git a/toolkit/test/accessibility/QueuedListener.java b/toolkit/test/accessibility/QueuedListener.java
new file mode 100644
index 000000000..a34b33549
--- /dev/null
+++ b/toolkit/test/accessibility/QueuedListener.java
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.*;
+import com.sun.star.lang.EventObject;
+import com.sun.star.uno.*;
+
+class QueuedListener
+ implements XAccessibleEventListener
+{
+ public QueuedListener (EventListener aListener)
+ {
+ maListener = aListener;
+ }
+
+
+ public void disposing( final EventObject aEvent)
+ {
+ XAccessibleContext xContext = UnoRuntime.queryInterface(
+ XAccessibleContext.class, aEvent.Source);
+ if (xContext == null)
+ {
+ XAccessible xAccessible = UnoRuntime.queryInterface(
+ XAccessible.class, aEvent.Source);
+ if (xAccessible != null)
+ xContext = xAccessible.getAccessibleContext();
+ }
+ final XAccessibleContext xSource = xContext;
+ EventQueue.Instance().addDisposingEvent (new Runnable()
+ {
+ public void run()
+ {
+ if (QueuedListener.this.maListener != null)
+ QueuedListener.this.maListener.disposing (xSource);
+ }
+ }
+ );
+ }
+
+ public void notifyEvent( final AccessibleEventObject aEvent )
+ {
+ EventQueue.Instance().addEvent (new Runnable()
+ {
+ public void run()
+ {
+ QueuedListener.this.maListener.notifyEvent( aEvent );
+ }
+ }
+ );
+ }
+
+ private final EventListener maListener;
+}
+
+
diff --git a/toolkit/test/accessibility/QueuedTopWindowListener.java b/toolkit/test/accessibility/QueuedTopWindowListener.java
new file mode 100644
index 000000000..2ac5c7849
--- /dev/null
+++ b/toolkit/test/accessibility/QueuedTopWindowListener.java
@@ -0,0 +1,97 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.awt.XTopWindowListener;
+import com.sun.star.lang.EventObject;
+
+class QueuedTopWindowListener
+ implements XTopWindowListener
+{
+ public QueuedTopWindowListener (TopWindowListener aListener)
+ {
+ maListener = aListener;
+ }
+
+ public void windowOpened (final com.sun.star.lang.EventObject aEvent) throws RuntimeException
+ {
+ EventQueue.Instance().addEvent (new Runnable()
+ {
+ public void run()
+ {
+ QueuedTopWindowListener.this.maListener.windowOpened (aEvent);
+ }
+ }
+ );
+ }
+
+ public void windowClosing (final com.sun.star.lang.EventObject aEvent) throws RuntimeException
+ {
+ // Ignored.
+ }
+
+ public void windowClosed (final com.sun.star.lang.EventObject aEvent) throws RuntimeException
+ {
+ EventQueue.Instance().addEvent (new Runnable()
+ {
+ public void run()
+ {
+ QueuedTopWindowListener.this.maListener.windowClosed (aEvent);
+ }
+ }
+ );
+ }
+
+ public void windowMinimized (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ System.out.println ("QueuedTopWindowListener: Top window minimized: " + aEvent);
+ }
+
+ public void windowNormalized (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ System.out.println ("QueuedTopWindowListener: Top window normalized: " + aEvent);
+ }
+
+ public void windowActivated (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ System.out.println ("QueuedTopWindowListener: Top window activated: " + aEvent);
+ }
+
+ public void windowDeactivated (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ System.out.println ("QueuedTopWindowListener: Top window deactivated: " + aEvent);
+ }
+
+ public void disposing( final EventObject aEvent)
+ {
+ EventQueue.Instance().addDisposingEvent (new Runnable()
+ {
+ public void run()
+ {
+ if (QueuedTopWindowListener.this.maListener != null)
+ QueuedTopWindowListener.this.maListener.disposing (aEvent);
+ }
+ }
+ );
+ }
+
+ private final TopWindowListener maListener;
+}
diff --git a/toolkit/test/accessibility/SelectionDialog.java b/toolkit/test/accessibility/SelectionDialog.java
new file mode 100644
index 000000000..2f0c6d543
--- /dev/null
+++ b/toolkit/test/accessibility/SelectionDialog.java
@@ -0,0 +1,203 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Vector;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.ListSelectionModel;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleSelection;
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+/**
+ * Display a dialog with a list-box of children and select/deselect buttons
+ */
+class SelectionDialog extends JDialog
+ implements ActionListener
+{
+ public SelectionDialog (AccTreeNode aNode)
+ {
+ super (AccessibilityWorkBench.Instance());
+
+ maNode = aNode;
+
+ Layout();
+ }
+
+ /** build dialog */
+ private void Layout ()
+ {
+ setTitle( "Select" );
+
+ // vertical stacking of the elements
+ Container aContent = getContentPane();
+
+ // label with explanation
+ aContent.add( new JLabel( "Select/Deselect child elements" ),
+ BorderLayout.NORTH );
+
+ // the JListBox
+ maChildrenSelector = new JList (GetChildrenList());
+ maChildrenSelector.setPreferredSize (new Dimension (500,300));
+ aContent.add (maChildrenSelector, BorderLayout.CENTER);
+ maChildrenSelector.setSelectionMode (ListSelectionModel.SINGLE_SELECTION);
+
+ JPanel aButtons = new JPanel();
+ aButtons.setLayout( new FlowLayout() );
+
+ JButton aButton;
+
+ aButton = new JButton( "Select" );
+ aButton.setActionCommand( "Select" );
+ aButton.addActionListener( this );
+ aButtons.add( aButton );
+
+ aButton = new JButton( "Deselect" );
+ aButton.setActionCommand( "Deselect" );
+ aButton.addActionListener( this );
+ aButtons.add( aButton );
+
+ aButton = new JButton( "Select all" );
+ aButton.setActionCommand( "Select all" );
+ aButton.addActionListener( this );
+ aButtons.add( aButton );
+
+ aButton = new JButton( "Clear Selection" );
+ aButton.setActionCommand( "Clear Selection" );
+ aButton.addActionListener( this );
+ aButtons.add( aButton );
+
+ aButton = new JButton( "Close" );
+ aButton.setActionCommand( "Close" );
+ aButton.addActionListener( this );
+ aButtons.add( aButton );
+
+ // add Panel with buttons
+ aContent.add( aButtons, BorderLayout.SOUTH );
+
+ setSize( getPreferredSize() );
+ }
+
+ /** Get a list of all children
+ */
+ private Vector<String> GetChildrenList ()
+ {
+ mxSelection = maNode.getSelection();
+
+ XAccessibleContext xContext = maNode.getContext();
+ int nCount = xContext.getAccessibleChildCount();
+ Vector<String> aChildVector = new Vector<String>();
+ for(int i = 0; i < nCount; i++)
+ {
+ try
+ {
+ XAccessible xChild = xContext.getAccessibleChild(i);
+ XAccessibleContext xChildContext = xChild.getAccessibleContext();
+ aChildVector.add( i + " " + xChildContext.getAccessibleName());
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChildVector.add( "ERROR: IndexOutOfBoundsException" );
+ }
+ }
+ return aChildVector;
+ }
+
+
+ private void close ()
+ {
+ setVisible(false);
+ dispose();
+ }
+
+ private void select()
+ {
+ try
+ {
+ mxSelection.selectAccessibleChild (maChildrenSelector.getSelectedIndex());
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ JOptionPane.showMessageDialog( AccessibilityWorkBench.Instance(),
+ "Can't select: IndexOutofBounds",
+ "Error in selectAccessibleChild",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ private void deselect()
+ {
+ try
+ {
+ mxSelection.deselectAccessibleChild(
+ maChildrenSelector.getSelectedIndex());
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ JOptionPane.showMessageDialog( AccessibilityWorkBench.Instance(),
+ "Can't deselect: IndexOutofBounds",
+ "Error in deselectAccessibleChild",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ private void selectAll()
+ {
+ mxSelection.selectAllAccessibleChildren();
+ }
+
+ private void clearSelection()
+ {
+ mxSelection.clearAccessibleSelection();
+ }
+
+
+
+ public void actionPerformed(ActionEvent e)
+ {
+ String sCommand = e.getActionCommand();
+
+ if( "Close".equals( sCommand ) )
+ close();
+ else if ( "Select".equals( sCommand ) )
+ select();
+ else if ( "Deselect".equals( sCommand ) )
+ deselect();
+ else if ( "Clear Selection".equals( sCommand ) )
+ clearSelection();
+ else if ( "Select all".equals( sCommand ) )
+ selectAll();
+ }
+
+ private JList maChildrenSelector;
+ private XAccessibleSelection mxSelection;
+ private final AccTreeNode maNode;
+}
diff --git a/toolkit/test/accessibility/SimpleOffice.java b/toolkit/test/accessibility/SimpleOffice.java
new file mode 100644
index 000000000..ecb16a6e3
--- /dev/null
+++ b/toolkit/test/accessibility/SimpleOffice.java
@@ -0,0 +1,139 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.frame.XDesktop;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.awt.XExtendedToolkit;
+
+
+/** This class tries to simplify some tasks like loading a document or
+ getting various objects.
+*/
+public class SimpleOffice
+{
+ private XDesktop mxDesktop = null;
+ private OfficeConnection aConnection;
+ private int mnPortNumber;
+
+ public SimpleOffice (int nPortNumber)
+ {
+ mnPortNumber = nPortNumber;
+ connect ();
+ getDesktop ();
+ }
+
+ public void connect ()
+ {
+ aConnection = new OfficeConnection (mnPortNumber);
+ mxDesktop = null;
+ getDesktop ();
+ }
+
+
+
+
+
+
+
+
+
+
+
+ public XDesktop getDesktop ()
+ {
+ if (mxDesktop != null)
+ return mxDesktop;
+ try
+ {
+ // Get the factory of the connected office.
+ XMultiServiceFactory xMSF = aConnection.getServiceManager ();
+ if (xMSF == null)
+ {
+ MessageArea.println ("can't connect to office");
+ return null;
+ }
+ else
+ MessageArea.println ("Connected successfully.");
+
+ // Create a new desktop.
+ mxDesktop = UnoRuntime.queryInterface(
+ XDesktop.class,
+ xMSF.createInstance ("com.sun.star.frame.Desktop")
+ );
+ }
+ catch (Exception e)
+ {
+ MessageArea.println ("caught exception while creating desktop: "
+ + e);
+ }
+
+ return mxDesktop;
+ }
+
+
+ /** Return a reference to the extended toolkit which is a broadcaster of
+ top window, key, and focus events.
+ */
+ public XExtendedToolkit getExtendedToolkit ()
+ {
+ XExtendedToolkit xToolkit = null;
+ try
+ {
+ // Get the factory of the connected office.
+ XMultiServiceFactory xMSF = aConnection.getServiceManager ();
+ if (xMSF != null)
+ {
+ xToolkit = UnoRuntime.queryInterface(
+ XExtendedToolkit.class,
+ xMSF.createInstance ("stardiv.Toolkit.VCLXToolkit")
+ );
+ }
+ }
+ catch (Exception e)
+ {
+ MessageArea.println ("caught exception while creating extended toolkit: " + e);
+ }
+
+ return xToolkit;
+ }
+
+
+
+ public XAccessible getAccessibleObject (XInterface xObject)
+ {
+ XAccessible xAccessible = null;
+ try
+ {
+ xAccessible = UnoRuntime.queryInterface(
+ XAccessible.class, xObject);
+ }
+ catch (Exception e)
+ {
+ MessageArea.println (
+ "caught exception while getting accessible object" + e);
+ e.printStackTrace();
+ }
+ return xAccessible;
+ }
+
+
+
+}
diff --git a/toolkit/test/accessibility/StringNode.java b/toolkit/test/accessibility/StringNode.java
new file mode 100644
index 000000000..f6660e44a
--- /dev/null
+++ b/toolkit/test/accessibility/StringNode.java
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+
+/**
+ Base class for all tree nodes.
+ */
+class StringNode
+ extends AccessibleTreeNode
+{
+ public StringNode (String aDisplayObject, AccessibleTreeNode aParent)
+ {
+ super (aDisplayObject, aParent);
+ }
+
+ @Override
+ public int indexOf(AccessibleTreeNode aNode) {
+ return -1;
+ }
+}
diff --git a/toolkit/test/accessibility/TableEventHandler.java b/toolkit/test/accessibility/TableEventHandler.java
new file mode 100644
index 000000000..09a3adbbc
--- /dev/null
+++ b/toolkit/test/accessibility/TableEventHandler.java
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleTableModelChange;
+import java.io.PrintStream;
+
+class TableEventHandler
+ extends EventHandler
+{
+ public TableEventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel)
+ {
+ super (aEvent, aTreeModel);
+ }
+
+ @Override
+ public void PrintOldAndNew (PrintStream out)
+ {
+ switch (mnEventId)
+ {
+ case AccessibleEventId.TABLE_MODEL_CHANGED:
+ AccessibleTableModelChange aModelChange =
+ (AccessibleTableModelChange)maEvent.NewValue;
+ out.println( "Range: StartRow " + aModelChange.FirstRow +
+ " StartColumn " + aModelChange.FirstColumn +
+ " EndRow " + aModelChange.LastRow +
+ " EndColumn " + aModelChange.LastColumn +
+ " Id " + aModelChange.Type);
+ break;
+ default:
+ super.PrintOldAndNew (out);
+ }
+ }
+
+ @Override
+ public void Process ()
+ {
+ maTreeModel.updateNode (mxEventSource, AccessibleTableHandler.class);
+ }
+
+
+}
diff --git a/toolkit/test/accessibility/TopWindowListener.java b/toolkit/test/accessibility/TopWindowListener.java
new file mode 100644
index 000000000..a35b51a5f
--- /dev/null
+++ b/toolkit/test/accessibility/TopWindowListener.java
@@ -0,0 +1,175 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import com.sun.star.awt.XWindow;
+import com.sun.star.awt.XExtendedToolkit;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.uno.UnoRuntime;
+
+/** Listen for top window events and create or delete children of the tree
+ model accordingly.
+*/
+class TopWindowListener
+{
+ TopWindowListener (AccessibilityTreeModel aModel, SimpleOffice aOffice)
+ {
+ maModel = aModel;
+ maOffice = aOffice;
+ }
+
+
+
+
+ /** Use this function to initially fill the accessibility object tree
+ view with nodes for top level windows.
+ */
+ public void Initialize ()
+ {
+ XExtendedToolkit xToolkit = maOffice.getExtendedToolkit();
+ if (xToolkit != null)
+ {
+ maModel.lock ();
+ int nTopWindowCount = xToolkit.getTopWindowCount();
+ MessageArea.println ("There are " + nTopWindowCount + " top windows.");
+ for (int i=0; i<nTopWindowCount; i++)
+ {
+ try
+ {
+ XAccessible xAccessible = maOffice.getAccessibleObject(
+ xToolkit.getTopWindow (i));
+ // Uncomment the following line to get the real root of
+ // the accessible tree that xAccessible belongs to.
+ // xAccessible = maOffice.getAccessibleRoot(xAccessible);
+ AddTopLevelNode (xAccessible);
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception: " + e);
+ e.printStackTrace();
+ }
+ }
+ maModel.unlock ((AccessibleTreeNode)maModel.getRoot());
+ }
+ }
+
+
+
+ /** Add a new top level node which, to be exact, will be placed on the
+ second layer of the tree.
+ @param xNewTopLevelObject
+ The accessible object of the new top level window.
+ */
+ private void AddTopLevelNode (XAccessible xNewTopLevelObject)
+ {
+ System.out.println ("adding top level window");
+ if (xNewTopLevelObject != null)
+ {
+ XAccessibleContext xContext = xNewTopLevelObject.getAccessibleContext();
+ if (xContext == null)
+ System.out.println ("top level window not accessible");
+ else
+ {
+ Object aRootObject = maModel.getRoot();
+ if (aRootObject instanceof VectorNode)
+ {
+ VectorNode aRoot = (VectorNode) aRootObject;
+ AccessibleTreeNode aNode =
+ NodeFactory.Instance().createDefaultNode (xNewTopLevelObject, aRoot);
+ aRoot.addChild (aNode);
+ maModel.fireTreeNodesInserted (maModel.createEvent (aRoot, aNode));
+ }
+ }
+ }
+ }
+
+ /** Remove an existing top level node from the tree.
+ @param xNewTopLevelObject
+ The accessible object to remove.
+ */
+ private void RemoveTopLevelNode (XAccessible xTopLevelObject)
+ {
+ Object aObject = maModel.getRoot();
+ if (aObject instanceof VectorNode && xTopLevelObject != null)
+ {
+ System.out.println ("removing node " + xTopLevelObject);
+ maModel.removeNode (xTopLevelObject.getAccessibleContext());
+ }
+ }
+
+
+
+
+
+ // XTopWindowListener
+ public void windowOpened (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ if (maModel != null)
+ {
+ XWindow xWindow = UnoRuntime.queryInterface(
+ XWindow.class, aEvent.Source);
+ if (xWindow == null)
+ System.out.println ("event source is no XWindow");
+ else
+ {
+ XAccessible xAccessible = maOffice.getAccessibleObject(xWindow);
+ if (xAccessible == null)
+ System.out.println ("event source is no XAccessible");
+ else
+ AddTopLevelNode (xAccessible);
+ }
+ }
+ }
+
+
+
+
+ public void windowClosed (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ if (maModel != null)
+ {
+ XWindow xWindow = UnoRuntime.queryInterface(
+ XWindow.class, aEvent.Source);
+ if (xWindow == null)
+ System.out.println ("event source is no XWindow");
+ else
+ {
+ XAccessible xAccessible = maOffice.getAccessibleObject(xWindow);
+ if (xAccessible == null)
+ System.out.println ("event source is no XAccessible");
+ else
+ RemoveTopLevelNode (xAccessible);
+ }
+ }
+ }
+
+ public void disposing (final com.sun.star.lang.EventObject aEvent)
+ {
+ System.out.println ("Top window disposed: " + aEvent);
+ }
+
+
+
+
+ private final AccessibilityTreeModel
+ maModel;
+ private final SimpleOffice
+ maOffice;
+}
diff --git a/toolkit/test/accessibility/VectorNode.java b/toolkit/test/accessibility/VectorNode.java
new file mode 100644
index 000000000..c1ffcd650
--- /dev/null
+++ b/toolkit/test/accessibility/VectorNode.java
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+import java.util.ArrayList;
+
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+/** The VectorNode class is a simple container whose list of children is
+ managed entirely by its owner.
+*/
+class VectorNode
+ extends StringNode
+{
+ private final ArrayList<AccessibleTreeNode> maChildren;
+
+ public VectorNode (String sDisplayObject, AccessibleTreeNode aParent)
+ {
+ super (sDisplayObject, aParent);
+
+ maChildren = new ArrayList<AccessibleTreeNode> ();
+ }
+
+ public void addChild (AccessibleTreeNode aChild)
+ {
+ maChildren.add (aChild);
+ }
+
+ @Override
+ public int getChildCount ()
+ {
+ return maChildren.size();
+ }
+
+ @Override
+ public AccessibleTreeNode getChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ return maChildren.get(nIndex);
+ }
+
+ @Override
+ public boolean removeChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ return maChildren.remove (nIndex) != null;
+ }
+
+ @Override
+ public int indexOf (AccessibleTreeNode aNode)
+ {
+ return maChildren.indexOf (aNode);
+ }
+
+ @Override
+ public boolean isLeaf()
+ {
+ return maChildren.isEmpty();
+ }
+}
diff --git a/toolkit/test/accessibility/about.html b/toolkit/test/accessibility/about.html
new file mode 100644
index 000000000..ff24ed058
--- /dev/null
+++ b/toolkit/test/accessibility/about.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<center><h1>About AWB</h1>
+<p>AWB, the <em>A</em>ccessibility <em>W</em>ork <em>B</em>ench.</p>
+<p>Version 1.7</p>
+</center>
+</body>
+</html> \ No newline at end of file
diff --git a/toolkit/test/accessibility/help.html b/toolkit/test/accessibility/help.html
new file mode 100644
index 000000000..681fcead4
--- /dev/null
+++ b/toolkit/test/accessibility/help.html
@@ -0,0 +1,91 @@
+<html><body bgcolor="#fffaf0">
+<h1>Help for the AWB v1.7</h1>
+
+<p>The AWB, or <em>A</em>ccessibility <em>W</em>ork <em>B</em>ench, is a tool
+for testing the implementation UNO Accessibility API.</p>
+
+<p>The main window is roughly divided into three areas:
+<ul>
+<li>The <a href="#treeview">tree view</a> on the left shows a part of the
+accessibility tree of one or more StarOffice/OpenOffice applications.</li>
+<li>The <a href="#graphicalview">graphical view</a> on the right side shows
+a graphical representation of the accessibility objects in the tree. To
+make objects missing in the graphical view visible expand the corresponding
+nodes in the tree view.</li>
+
+<li>The text window at the bottom logs important messages.</li>
+</ul>
+</p>
+
+<h2><a name="treeview">Tree View</a></h2>
+<p>The tree view has a top-level node for every open
+ document window of StarOffice/OpenOffice. Expand those nodes to make them
+ visible in the <a href="#graphicalview">graphical view</a>.</p>
+
+<h3>Nodes</h3>
+<p>The nodes in the tree view belong to different classes, some of which
+ have children others do not:
+<ul>
+<li><b>Accessible Object</b><br>
+ The node represents an accessible object and has corresponding shape in
+ the graphical view. Only this kind of node gets highlighted by clicking
+ on those shapes.</li>
+<li><b>Simple Property</b><br>
+ These leaves represent simple properties of their parent nodes. Examples
+ are the position, size, and color of an accessible object.</li>
+<li><b>Complex Properties</b><br>
+ These nodes have children that are not accessible objects. Examples are
+ the lists of interfaces or services supported by an accessible object.</li>
+</ul>
+</p>
+
+<h3>Actions</h3>
+<p>The tree view supports the following actions:
+<ul><li>Left double click expands the node under the mouse pointer.</li>
+<li>Right click shows a context menu. Entries, when supported, are:
+<ul>
+<li><b>Expand Shapes</b><br>
+Expands all nodes in the sub-tree that lie on a path from the root to a shape.</li>
+<li><b>Expand Subtree</b><br>
+Expands all nodes in the sub-tree.</li>
+<li><b>Select...</b><br>
+Show a dialog that gives access to the XAccessibleSelection interface.</li>
+<li><b>select...</b>, <b>copy...</b>, <b>cut...</b>, <b>paste...</b>,
+ <b>edit...</b>, <b>format...</b><br>
+Show dialogs that give access to the XAccessibleText and
+XAccessibleEditableText interfaces.
+</ul></li>
+</ul>
+</p>
+
+
+
+<h2><a name="graphicalview">Graphical View</a></h2>
+<p>The graphical view shows several properties of accessibility objects:
+<ul>
+<li>The bounding box is represented as a rectangle.</li>
+<li>The background color of the accessible object is taken to draw the
+ bounding box rectangle.</li>
+<li>The foreground color is used to fill the bounding box.</li>
+<li>The accessible name is shown when the menu checkbox Options->Show Name
+ is check.</li>
+<li>The accessible description is shown when the menu checkbox Options->Show
+ Descriptions is checked.</li>
+<li>If the XAccessibleText interface is supported and the menu checkbox
+ Options->Show Text is checked then the text of the accessible object is
+ shown.</li>
+</ul>
+</p>
+
+<h3>Actions</h3>
+<p>The graphical view supports three the following actions:
+<ul>
+<li>Left click (no modifiers) highlights the object under the mouse as well
+ as the corresponding node in the tree view.</li>
+<li>Left click with Control modifier expands the object under the
+ mouse.</li>
+<li>Mouse motion with Shift modifier highlights the object under the mouse
+ as well as the corresponding node in the tree view.</li>
+</ul>
+
+</body></html>
diff --git a/toolkit/test/accessibility/jawb.mf b/toolkit/test/accessibility/jawb.mf
new file mode 100644
index 000000000..88aa2cc76
--- /dev/null
+++ b/toolkit/test/accessibility/jawb.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: AccessibilityWorkBench
+Class-Path: classes.jar libreoffice.jar java_uno.jar xt.jar xml-apis.jar
diff --git a/toolkit/test/accessibility/news.html b/toolkit/test/accessibility/news.html
new file mode 100644
index 000000000..7b5336ea4
--- /dev/null
+++ b/toolkit/test/accessibility/news.html
@@ -0,0 +1,36 @@
+<html><body bgcolor="#fffaf0">
+<h1>News for AWB v1.7.2</h1>
+<p>Adaptation to recent UAA changes:
+<ul>
+<li>Introduction of
+com.sun.star.accessibility.TextSegment structure that is returned by some
+functions of the XAccessibleText interface.</li>
+<li>Removal of the COLLAPSED state.</li>
+<li>Renaming of XAccessibleSelectioni::selectAllAccessible to
+selectAllAccessibleChildren.</li>
+</ul>
+
+<h1>News for AWB v1.7</h1>
+
+<ul>
+
+<li>This help window.</li>
+
+<li>Integrated relocation of UAA files from drafts to final.</li>
+<li>Control left click in the graphical view expands the object that has
+ been clicked at.</li>
+
+<li>Introduction of split panes for easily changing the size of the three
+main widgets.</li>
+
+<li>The graphical view visualizes the screen size.</li>
+
+<li>Removed the "Load" button.</li>
+<li>Removed the status line.</li>
+<li>The tree view shows top level nodes only for document windows.</li>
+<li>New "views" menu that allows you to select the zoom scale of the
+ graphical view.</li>
+
+</ul>
+
+</body></html> \ No newline at end of file
diff --git a/toolkit/test/accessibility/ov/ContextView.java b/toolkit/test/accessibility/ov/ContextView.java
new file mode 100644
index 000000000..0dc97a67a
--- /dev/null
+++ b/toolkit/test/accessibility/ov/ContextView.java
@@ -0,0 +1,140 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package ov;
+
+import java.awt.Color;
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import javax.swing.JLabel;
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.XAccessibleContext;
+
+import tools.NameProvider;
+
+public class ContextView
+ extends ListeningObjectView
+ implements ActionListener
+{
+ public static ObjectView Create (
+ ObjectViewContainer aContainer,
+ XAccessibleContext xContext)
+ {
+ System.out.println ("ContextView.CreateView");
+ if (xContext != null)
+ return new ContextView (aContainer);
+ else
+ return null;
+ }
+
+ private ContextView (ObjectViewContainer aContainer)
+ {
+ super (aContainer);
+ JLabel aNameLabel = new JLabel ("Name: ");
+ maName = new JLabel ("");
+ JLabel aDescriptionLabel = new JLabel ("Description: ");
+ maDescription = new JLabel ("");
+ JLabel maRoleLabel = new JLabel ("Role: ");
+ maRole = new JLabel ("");
+
+ // Make the background of name and description white and opaque so
+ // that leading and trailing spaces become visible.
+ maName.setOpaque (true);
+ maName.setBackground (Color.WHITE);
+ maDescription.setOpaque (true);
+ maDescription.setBackground (Color.WHITE);
+ maRole.setOpaque (true);
+ maRole.setBackground (Color.WHITE);
+
+ GridBagLayout aLayout = new GridBagLayout();
+ setLayout (aLayout);
+ GridBagConstraints constraints = new GridBagConstraints ();
+ constraints.gridx = 0;
+ constraints.gridy = 0;
+ constraints.gridwidth = 1;
+ constraints.gridheight = 1;
+ constraints.weightx = 0;
+ constraints.weighty = 1;
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.fill = GridBagConstraints.NONE;
+ add (aNameLabel, constraints);
+ constraints.gridy = 1;
+ add (aDescriptionLabel, constraints);
+ constraints.gridy = 2;
+ add (maRoleLabel, constraints);
+ constraints.gridy = 0;
+ constraints.gridx = 1;
+ constraints.weightx = 2;
+ add (maName, constraints);
+ constraints.gridy = 1;
+ add (maDescription, constraints);
+ constraints.gridy = 2;
+ add (maRole, constraints);
+ }
+
+ @Override
+ public void Update ()
+ {
+ if (mxContext == null)
+ {
+ maName.setText ("<null object>");
+ maDescription.setText ("<null object>");
+ maRole.setText ("<null object>");
+ }
+ else
+ {
+ maName.setText (mxContext.getAccessibleName());
+ maDescription.setText (mxContext.getAccessibleDescription());
+ maRole.setText (NameProvider.getRoleName (mxContext.getAccessibleRole()));
+ }
+ }
+
+ @Override
+ public String GetTitle ()
+ {
+ return "Context";
+ }
+
+ /** Listen for changes regarding displayed values.
+ */
+ @Override
+ public void notifyEvent (AccessibleEventObject aEvent)
+ {
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId.NAME_CHANGED :
+ case AccessibleEventId.DESCRIPTION_CHANGED :
+ Update ();
+ }
+ }
+
+ public void actionPerformed (ActionEvent aEvent)
+ {
+ }
+
+
+ private final JLabel
+ maName,
+ maDescription,
+ maRole;
+}
diff --git a/toolkit/test/accessibility/ov/FocusView.java b/toolkit/test/accessibility/ov/FocusView.java
new file mode 100644
index 000000000..cca1a6a0c
--- /dev/null
+++ b/toolkit/test/accessibility/ov/FocusView.java
@@ -0,0 +1,141 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package ov;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.AccessibleStateType;
+import com.sun.star.accessibility.XAccessibleComponent;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleStateSet;
+import com.sun.star.uno.UnoRuntime;
+
+public class FocusView
+ extends ListeningObjectView
+ implements ActionListener
+{
+ /** Create a FocusView when the given object supports the
+ XAccessibleComponent interface.
+ */
+ public static ObjectView Create (
+ ObjectViewContainer aContainer,
+ XAccessibleContext xContext)
+ {
+ XAccessibleComponent xComponent = UnoRuntime.queryInterface(
+ XAccessibleComponent.class, xContext);
+ if (xComponent != null)
+ return new FocusView (aContainer);
+ else
+ return null;
+ }
+
+ private FocusView (ObjectViewContainer aContainer)
+ {
+ super (aContainer);
+
+ setLayout (new GridBagLayout());
+ GridBagConstraints aConstraints = new GridBagConstraints ();
+
+ maFocused = new JLabel ();
+ aConstraints.gridy = 0;
+ aConstraints.weightx = 1;
+ aConstraints.fill = GridBagConstraints.HORIZONTAL;
+ add (maFocused, aConstraints);
+
+ maGrabFocus = new JButton ("grabFocus");
+ aConstraints.gridy = 1;
+ aConstraints.fill = GridBagConstraints.NONE;
+ aConstraints.anchor = GridBagConstraints.WEST;
+ add (maGrabFocus, aConstraints);
+
+ maGrabFocus.addActionListener (this);
+ }
+
+ /** Additionally to the context store a reference to the
+ XAccessibleComponent interface.
+ */
+ @Override
+ public void SetObject (XAccessibleContext xObject)
+ {
+ mxComponent = UnoRuntime.queryInterface(
+ XAccessibleComponent.class, xObject);
+ super.SetObject (xObject);
+ }
+
+ @Override
+ synchronized public void Destroy ()
+ {
+ super.Destroy();
+ maGrabFocus.removeActionListener (this);
+ }
+
+ @Override
+ synchronized public void Update ()
+ {
+ if (mxContext == null)
+ {
+ maFocused.setText ("<null object>");
+ maGrabFocus.setEnabled (false);
+ }
+ else
+ {
+ XAccessibleStateSet aStateSet = mxContext.getAccessibleStateSet();
+ if (aStateSet.contains(AccessibleStateType.FOCUSED))
+ maFocused.setText ("focused");
+ else
+ maFocused.setText ("not focused");
+ if (maGrabFocus != null)
+ maGrabFocus.setEnabled (true);
+ }
+ }
+
+ @Override
+ public String GetTitle ()
+ {
+ return "Focus";
+ }
+
+ synchronized public void actionPerformed (ActionEvent aEvent)
+ {
+ if (aEvent.getActionCommand().equals("grabFocus"))
+ {
+ mxComponent.grabFocus();
+ }
+ }
+
+ @Override
+ public void notifyEvent (AccessibleEventObject aEvent)
+ {
+ System.out.println (aEvent);
+ if (aEvent.EventId == AccessibleEventId.STATE_CHANGED)
+ Update ();
+ }
+
+ private final JLabel maFocused;
+ private final JButton maGrabFocus;
+ private XAccessibleComponent mxComponent;
+}
diff --git a/toolkit/test/accessibility/ov/ListeningObjectView.java b/toolkit/test/accessibility/ov/ListeningObjectView.java
new file mode 100644
index 000000000..63b5f8ff7
--- /dev/null
+++ b/toolkit/test/accessibility/ov/ListeningObjectView.java
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package ov;
+
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleEventBroadcaster;
+import com.sun.star.accessibility.XAccessibleEventListener;
+import com.sun.star.lang.EventObject;
+import com.sun.star.uno.UnoRuntime;
+
+/** Base class for object views that registers as accessibility event
+ listener.
+*/
+abstract class ListeningObjectView
+ extends ObjectView
+ implements XAccessibleEventListener
+{
+ public ListeningObjectView (ObjectViewContainer aContainer)
+ {
+ super (aContainer);
+ }
+
+ /** Add this object as event listener at the broadcasting
+ accessible object.
+ */
+ @Override
+ public void SetObject (XAccessibleContext xContext)
+ {
+ super.SetObject (xContext);
+ XAccessibleEventBroadcaster xBroadcaster =
+ UnoRuntime.queryInterface(
+ XAccessibleEventBroadcaster.class, xContext);
+ if (xBroadcaster != null)
+ xBroadcaster.addAccessibleEventListener (this);
+ }
+
+
+ /** Remove this object as event listener from the broadcasting
+ accessible object.
+ */
+ @Override
+ public void Destroy ()
+ {
+ super.Destroy ();
+ XAccessibleEventBroadcaster xBroadcaster =
+ UnoRuntime.queryInterface(
+ XAccessibleEventBroadcaster.class, mxContext);
+ if (xBroadcaster != null)
+ xBroadcaster.removeAccessibleEventListener (this);
+ }
+
+ /** Derived classes have to implement this method to handle incoming
+ events.
+ */
+ abstract public void notifyEvent (AccessibleEventObject aEvent);
+
+ /** The disposing event is ignored per default. If a derived class is
+ interested it can overwrite this method.
+ */
+ public void disposing (EventObject aEvent)
+ {
+ }
+}
diff --git a/toolkit/test/accessibility/ov/ObjectView.java b/toolkit/test/accessibility/ov/ObjectView.java
new file mode 100644
index 000000000..7e1570b62
--- /dev/null
+++ b/toolkit/test/accessibility/ov/ObjectView.java
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package ov;
+
+import javax.swing.JPanel;
+
+import com.sun.star.accessibility.XAccessibleContext;
+
+/** This is the base class for all object views that can be placed inside an
+ object view container.
+
+ <p>When provided with a new accessible object the container will call
+ the Create method to create a new instance when certain conditions are
+ met. It then calls SetObject to pass the object to the instance.
+ Finally it calls Update.</p>
+
+ <p>The SetObject and Update methods may be called for a new object
+ without calling Create first. In this way an existing instance is
+ recycled.</p>
+*/
+abstract public class ObjectView
+ extends JPanel
+{
+ public ObjectView (ObjectViewContainer aContainer)
+ {
+ mxContext = null;
+ }
+
+ /** Call this when you want the object to be destroyed. Release all
+ resources when called.
+ */
+ public void Destroy ()
+ {
+ }
+
+ /** Tell the view to display information for a new accessible object.
+ @param xContext
+ The given object may be null. A typical behaviour in this case
+ would be to display a blank area. But is also possible to show
+ information about the last object.
+ */
+ public void SetObject (XAccessibleContext xContext)
+ {
+ mxContext = xContext;
+ Update ();
+ }
+
+
+ /** This is a request of a repaint with the current state of the current
+ object. The current object may or may not be the same as the one
+ when Update() was called the last time.
+ */
+ public void Update ()
+ {
+ }
+
+
+ /** Return a string that is used as a title of an enclosing frame.
+ */
+ abstract public String GetTitle ();
+
+ /// Reference to the current object to display information about.
+ protected XAccessibleContext mxContext;
+}
diff --git a/toolkit/test/accessibility/ov/ObjectViewContainer.java b/toolkit/test/accessibility/ov/ObjectViewContainer.java
new file mode 100644
index 000000000..c7e647d67
--- /dev/null
+++ b/toolkit/test/accessibility/ov/ObjectViewContainer.java
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package ov;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.ArrayList;
+
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+import javax.swing.border.BevelBorder;
+import javax.swing.border.Border;
+
+import com.sun.star.accessibility.XAccessibleContext;
+
+
+public class ObjectViewContainer
+ extends JPanel
+{
+ private static interface IViewFactory {
+ ObjectView Create (
+ ObjectViewContainer aContainer,
+ XAccessibleContext xContext);
+ }
+
+ public ObjectViewContainer ()
+ {
+ maViewTemplates = new ArrayList<IViewFactory>();
+ maViewBorder = BorderFactory.createBevelBorder (BevelBorder.RAISED);
+ setLayout (new GridBagLayout ());
+
+ maViewTemplates.add(new IViewFactory() {
+ public ObjectView Create(ObjectViewContainer aContainer,
+ XAccessibleContext xContext) {
+ return ContextView.Create(aContainer, xContext);
+ }
+ });
+ maViewTemplates.add(new IViewFactory() {
+ public ObjectView Create(ObjectViewContainer aContainer,
+ XAccessibleContext xContext) {
+ return FocusView.Create(aContainer, xContext);
+ }
+ });
+ maViewTemplates.add(new IViewFactory() {
+ public ObjectView Create(ObjectViewContainer aContainer,
+ XAccessibleContext xContext) {
+ return TextView.Create(aContainer, xContext);
+ }
+ });
+ }
+
+ /** Remove all existing views and create new ones according to the
+ interfaces supported by the given object.
+ */
+ public void SetObject (XAccessibleContext xContext)
+ {
+ // Call Destroy at all views to give them a chance to release their
+ // resources.
+ int n = getComponentCount();
+ for (int i=0; i<n; i++)
+ ((ObjectView)getComponent(i)).Destroy();
+ // Remove existing views.
+ removeAll ();
+
+ // Add new views.
+ for (int i=0; i<maViewTemplates.size(); i++)
+ {
+ IViewFactory aViewFactory = maViewTemplates.get(i);
+ ObjectView aView = aViewFactory.Create(this, xContext);
+ Add (aView);
+ }
+
+ UpdateLayoutManager ();
+
+ // Now set the object at all views.
+ n = getComponentCount();
+ for (int i=0; i<n; i++)
+ ((ObjectView)getComponent(i)).SetObject (xContext);
+
+ setPreferredSize (getLayout().preferredLayoutSize (this));
+ }
+
+
+ /** Add an object view and place it below all previously added views.
+ @param aView
+ This argument may be null. In this case nothing happens.
+ */
+ private void Add (ObjectView aView)
+ {
+ if (aView != null)
+ {
+ GridBagConstraints constraints = new GridBagConstraints ();
+ constraints.gridx = 0;
+ constraints.gridy = getComponentCount();
+ constraints.gridwidth = 1;
+ constraints.gridheight = 1;
+ constraints.weightx = 1;
+ constraints.weighty = 0;
+ constraints.ipadx = 2;
+ constraints.ipady = 5;
+ constraints.insets = new Insets (5,5,5,5);
+ constraints.anchor = GridBagConstraints.NORTH;
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+
+ aView.setBorder (
+ BorderFactory.createTitledBorder (
+ maViewBorder, aView.GetTitle()));
+
+ add (aView, constraints);
+ }
+ }
+
+ /** Update the layout manager by setting the vertical weight of the
+ bottom entry to 1 and so make it stretch to over the available
+ space.
+
+ */
+ private void UpdateLayoutManager ()
+ {
+ // Adapt the layout manager.
+ if (getComponentCount() > 0)
+ {
+ Component aComponent = getComponent (getComponentCount()-1);
+ GridBagLayout aLayout = (GridBagLayout)getLayout();
+ GridBagConstraints aConstraints = aLayout.getConstraints (aComponent);
+ aConstraints.weighty = 1;
+ aLayout.setConstraints (aComponent, aConstraints);
+ }
+ }
+
+ private final Border maViewBorder;
+ /// List of view templates which are instantiated when new object is set.
+ private final ArrayList<IViewFactory> maViewTemplates;
+}
diff --git a/toolkit/test/accessibility/ov/TextView.java b/toolkit/test/accessibility/ov/TextView.java
new file mode 100644
index 000000000..518d5ff50
--- /dev/null
+++ b/toolkit/test/accessibility/ov/TextView.java
@@ -0,0 +1,133 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package ov;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import javax.swing.JLabel;
+
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.XAccessibleText;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.uno.UnoRuntime;
+
+public class TextView
+ extends ListeningObjectView
+{
+ /** Create a TextView when the given object supports the
+ XAccessibleText interface.
+ */
+ public static ObjectView Create (
+ ObjectViewContainer aContainer,
+ XAccessibleContext xContext)
+ {
+ XAccessibleText xText = UnoRuntime.queryInterface(
+ XAccessibleText.class, xContext);
+ if (xText != null)
+ return new TextView (aContainer);
+ else
+ return null;
+ }
+
+
+ private TextView (ObjectViewContainer aContainer)
+ {
+ super (aContainer);
+
+ setLayout (new GridBagLayout());
+ GridBagConstraints aConstraints = new GridBagConstraints ();
+
+ JLabel aLabel = new JLabel ("Text:");
+ aConstraints.gridy = 0;
+ aConstraints.weightx = 1;
+ aConstraints.fill = GridBagConstraints.HORIZONTAL;
+ add (aLabel, aConstraints);
+
+ maTextLabel = new JLabel ("");
+ aConstraints.gridx = 1;
+ aConstraints.fill = GridBagConstraints.NONE;
+ aConstraints.anchor = GridBagConstraints.WEST;
+ add (maTextLabel, aConstraints);
+
+ aLabel = new JLabel ("Caret position:");
+ aConstraints.gridx = 0;
+ aConstraints.gridy = 1;
+ aConstraints.weightx = 1;
+ aConstraints.fill = GridBagConstraints.HORIZONTAL;
+ add (aLabel, aConstraints);
+
+ maCaretPositionLabel = new JLabel ("");
+ aConstraints.gridx = 1;
+ aConstraints.fill = GridBagConstraints.NONE;
+ aConstraints.anchor = GridBagConstraints.WEST;
+ add (maCaretPositionLabel, aConstraints);
+ }
+
+
+ /** Additionally to the context store a reference to the
+ XAccessibleText interface.
+ */
+ @Override
+ public void SetObject (XAccessibleContext xObject)
+ {
+ mxText = UnoRuntime.queryInterface(
+ XAccessibleText.class, xObject);
+ super.SetObject (xObject);
+ }
+
+ @Override
+ synchronized public void Update ()
+ {
+ if (mxText == null)
+ {
+ maTextLabel.setText ("<null object>");
+ maCaretPositionLabel.setText ("<null object>");
+ }
+ else
+ {
+ maTextLabel.setText (mxText.getText());
+ maCaretPositionLabel.setText (Integer.toString(mxText.getCaretPosition()));
+ }
+ }
+
+ @Override
+ public String GetTitle ()
+ {
+ return "Text";
+ }
+
+ @Override
+ public void notifyEvent (AccessibleEventObject aEvent)
+ {
+ System.out.println (aEvent);
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId.TEXT_CHANGED :
+ case AccessibleEventId.CARET_CHANGED :
+ Update ();
+ break;
+ }
+ }
+
+ private final JLabel
+ maTextLabel,
+ maCaretPositionLabel;
+ private XAccessibleText mxText;
+}
diff --git a/toolkit/test/accessibility/tools/NameProvider.java b/toolkit/test/accessibility/tools/NameProvider.java
new file mode 100644
index 000000000..cc5ae469e
--- /dev/null
+++ b/toolkit/test/accessibility/tools/NameProvider.java
@@ -0,0 +1,276 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package tools;
+
+import java.util.HashMap;
+import com.sun.star.accessibility.AccessibleStateType;
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleRole;
+import com.sun.star.accessibility.AccessibleRelationType;
+
+
+/** Provide names for several accessibility constants groups.
+*/
+public class NameProvider
+{
+ /** Return the name of the specified state.
+ @param nStateId
+ Id of the state for which to return its name. This is one of
+ the ids listed in the <type>AccessibleStateType</const>
+ constants group.
+ @return
+ Returns the name of the specified state or an empty string if an
+ invalid / unknown state id was given.
+ */
+ public static String getStateName (int nStateId)
+ {
+ return maStateMap.get (Integer.valueOf(nStateId));
+ }
+
+
+ /** Return the name of the specified event.
+ @param nEventId
+ Id of the event type for which to return its name. This is one
+ of the ids listed in the <type>AccessibleEventId</const>
+ constants group.
+ @return
+ Returns the name of the specified event type or an empty string
+ if an invalid / unknown event id was given.
+ */
+ public static String getEventName (int nEventId)
+ {
+ return maEventMap.get (Integer.valueOf(nEventId));
+ }
+
+
+ /** Return the name of the specified role.
+ @param nRole
+ Id of the role for which to return its name. This is one of
+ the ids listed in the <type>AccessibleRole</const>
+ constants group.
+ @return
+ Returns the name of the specified role or an empty string if an
+ invalid / unknown role id was given.
+ */
+ public static String getRoleName (int nRole)
+ {
+ return maRoleMap.get (Integer.valueOf(nRole));
+ }
+
+
+ /** Return the name of the specified relation.
+ @param nRelation
+ Id of the relation for which to return its name. This is one of
+ the ids listed in the <type>AccessibleRelationType</const>
+ constants group.
+ @return
+ Returns the name of the specified relation type or an empty
+ string if an invalid / unknown role id was given.
+ */
+ public static String getRelationName (int nRelation)
+ {
+ return maRelationMap.get (Integer.valueOf(nRelation));
+ }
+
+
+ private static HashMap<Integer, String> maStateMap = new HashMap<Integer, String>();
+ private static HashMap<Integer, String> maEventMap = new HashMap<Integer, String>();
+ private static HashMap<Integer, String> maRoleMap = new HashMap<Integer, String>();
+ private static HashMap<Integer, String> maRelationMap = new HashMap<Integer, String>();
+
+ static {
+ maStateMap.put (Integer.valueOf(AccessibleStateType.INVALID), "INVALID");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.ACTIVE), "ACTIVE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.ARMED), "ARMED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.BUSY), "BUSY");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.CHECKED), "CHECKED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.DEFUNC), "DEFUNC");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.EDITABLE), "EDITABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.ENABLED), "ENABLED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.EXPANDABLE), "EXPANDABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.EXPANDED), "EXPANDED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.FOCUSABLE), "FOCUSABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.FOCUSED), "FOCUSED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.HORIZONTAL), "HORIZONTAL");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.ICONIFIED), "ICONIFIED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.MODAL), "MODAL");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.MULTI_LINE), "MULTI_LINE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.MULTI_SELECTABLE), "MULTI_SELECTABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.OPAQUE), "OPAQUE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.PRESSED), "PRESSED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.RESIZABLE), "RESIZABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.SELECTABLE), "SELECTABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.SELECTED), "SELECTED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.SENSITIVE), "SENSITIVE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.SHOWING), "SHOWING");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.SINGLE_LINE), "SINGLE_LINE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.STALE), "STALE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.TRANSIENT), "TRANSIENT");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.VERTICAL), "VERTICAL");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.VISIBLE), "VISIBLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.MANAGES_DESCENDANTS),
+ "MANAGES_DESCENDANTS");
+
+
+ maEventMap.put (Integer.valueOf(0),
+ "[UNKNOWN]");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.NAME_CHANGED),
+ "NAME_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.DESCRIPTION_CHANGED),
+ "DESCRIPTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.ACTION_CHANGED),
+ "ACTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.STATE_CHANGED),
+ "STATE_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.ACTIVE_DESCENDANT_CHANGED),
+ "ACTIVE_DESCENDANT_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.BOUNDRECT_CHANGED),
+ "BOUNDRECT_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CHILD),
+ "CHILD");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.INVALIDATE_ALL_CHILDREN),
+ "INVALIDATE_ALL_CHILDREN");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.SELECTION_CHANGED),
+ "SELECTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.VISIBLE_DATA_CHANGED),
+ "VISIBLE_DATA_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.VALUE_CHANGED),
+ "VALUE_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CONTENT_FLOWS_FROM_RELATION_CHANGED),
+ "CONTENT_FLOWS_FROM_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CONTENT_FLOWS_TO_RELATION_CHANGED),
+ "CONTENT_FLOWS_TO_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CONTROLLED_BY_RELATION_CHANGED),
+ "CONTROLLED_BY_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CONTROLLER_FOR_RELATION_CHANGED),
+ "CONTROLLER_FOR_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.LABEL_FOR_RELATION_CHANGED),
+ "LABEL_FOR_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.LABELED_BY_RELATION_CHANGED),
+ "LABELED_BY_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.MEMBER_OF_RELATION_CHANGED),
+ "MEMBER_OF_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.SUB_WINDOW_OF_RELATION_CHANGED),
+ "SUB_WINDOW_OF_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CARET_CHANGED),
+ "CARET_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TEXT_SELECTION_CHANGED),
+ "TEXT_SELECTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TEXT_CHANGED),
+ "TEXT_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TEXT_ATTRIBUTE_CHANGED),
+ "TEXT_ATTRIBUTE_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.HYPERTEXT_CHANGED),
+ "HYPERTEXT_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_CAPTION_CHANGED),
+ "TABLE_CAPTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_COLUMN_DESCRIPTION_CHANGED),
+ "TABLE_COLUMN_DESCRIPTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_COLUMN_HEADER_CHANGED),
+ "TABLE_COLUMN_HEADER_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_MODEL_CHANGED),
+ "TABLE_MODEL_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_ROW_DESCRIPTION_CHANGED),
+ "TABLE_ROW_DESCRIPTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_ROW_HEADER_CHANGED),
+ "TABLE_ROW_HEADER_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_SUMMARY_CHANGED),
+ "TABLE_SUMMARY_CHANGED");
+
+ maRoleMap.put (Integer.valueOf(AccessibleRole.UNKNOWN), "UNKNOWN");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.UNKNOWN), "UNKNOWN");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.ALERT), "ALERT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.COLUMN_HEADER), "COLUMN_HEADER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.CANVAS), "CANVAS");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.CHECK_BOX), "CHECK_BOX");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.CHECK_MENU_ITEM), "CHECK_MENU_ITEM");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.COLOR_CHOOSER), "COLOR_CHOOSER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.COMBO_BOX), "COMBO_BOX");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.DESKTOP_ICON), "DESKTOP_ICON");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.DESKTOP_PANE), "DESKTOP_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.DIRECTORY_PANE), "DIRECTORY_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.DIALOG), "DIALOG");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.DOCUMENT), "DOCUMENT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.EMBEDDED_OBJECT), "EMBEDDED_OBJECT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.END_NOTE), "END_NOTE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FILE_CHOOSER), "FILE_CHOOSER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FILLER), "FILLER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FONT_CHOOSER), "FONT_CHOOSER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FOOTER), "FOOTER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FOOTNOTE), "FOOTNOTE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FRAME), "FRAME");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.GLASS_PANE), "GLASS_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.GRAPHIC), "GRAPHIC");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.GROUP_BOX), "GROUP_BOX");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.HEADER), "HEADER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.HEADING), "HEADING");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.HYPER_LINK), "HYPER_LINK");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.ICON), "ICON");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.INTERNAL_FRAME), "INTERNAL_FRAME");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.LABEL), "LABEL");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.LAYERED_PANE), "LAYERED_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.LIST), "LIST");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.LIST_ITEM), "LIST_ITEM");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.MENU), "MENU");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.MENU_BAR), "MENU_BAR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.MENU_ITEM), "MENU_ITEM");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.OPTION_PANE), "OPTION_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PAGE_TAB), "PAGE_TAB");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PAGE_TAB_LIST), "PAGE_TAB_LIST");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PANEL), "PANEL");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PARAGRAPH), "PARAGRAPH");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PASSWORD_TEXT), "PASSWORD_TEXT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.POPUP_MENU), "POPUP_MENU");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PUSH_BUTTON), "PUSH_BUTTON");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PROGRESS_BAR), "PROGRESS_BAR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.RADIO_BUTTON), "RADIO_BUTTON");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.RADIO_MENU_ITEM), "RADIO_MENU_ITEM");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.ROW_HEADER), "ROW_HEADER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.ROOT_PANE), "ROOT_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SCROLL_BAR), "SCROLL_BAR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SCROLL_PANE), "SCROLL_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SHAPE), "SHAPE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SEPARATOR), "SEPARATOR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SLIDER), "SLIDER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SPIN_BOX), "SPIN_BOX");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SPLIT_PANE), "SPLIT_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.STATIC), "STATIC");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.STATUS_BAR), "STATUS_BAR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TABLE), "TABLE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TABLE_CELL), "TABLE_CELL");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TEXT), "TEXT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TEXT_FRAME), "TEXT_FRAME");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TOGGLE_BUTTON), "TOGGLE_BUTTON");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TOOL_BAR), "TOOL_BAR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TOOL_TIP), "TOOL_TIP");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TREE), "TREE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.VIEW_PORT), "VIEW_PORT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.WINDOW), "WINDOW");
+
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.INVALID), "INVALID");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.CONTENT_FLOWS_FROM), "CONTENT_FLOWS_FROM");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.CONTENT_FLOWS_TO), "CONTENT_FLOWS_TO");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.CONTROLLED_BY), "CONTROLLED_BY");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.CONTROLLER_FOR), "CONTROLLER_FOR");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.LABEL_FOR), "LABEL_FOR");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.LABELED_BY), "LABELED_BY");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.MEMBER_OF), "MEMBER_OF");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.SUB_WINDOW_OF), "SUB_WINDOW_OF");
+ }
+}