diff options
Diffstat (limited to 'toolkit/test')
67 files changed, 9620 insertions, 0 deletions
diff --git a/toolkit/test/accessibility/AWB.sxw b/toolkit/test/accessibility/AWB.sxw Binary files differnew file mode 100755 index 000000000000..57931aed1d19 --- /dev/null +++ b/toolkit/test/accessibility/AWB.sxw diff --git a/toolkit/test/accessibility/AccTreeNode.java b/toolkit/test/accessibility/AccTreeNode.java new file mode 100644 index 000000000000..64a5a5a3c4f6 --- /dev/null +++ b/toolkit/test/accessibility/AccTreeNode.java @@ -0,0 +1,350 @@ +import com.sun.star.uno.UnoRuntime; +import com.sun.star.accessibility.*; +import java.util.Vector; + +/** + * 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 +{ + class HandlerDescriptor + { + public HandlerDescriptor (NodeHandler aHandler) + { + maHandler = aHandler; + mnChildCount = -1; + } + public NodeHandler maHandler; + public int mnChildCount; + } + /// NodeHandlers for this node + private Vector maHandlers; + + // The accessible context of this node. + private XAccessible mxAccessible; + private XAccessibleContext mxContext; + private XAccessibleComponent mxComponent; + private XAccessibleText mxText; + private XAccessibleTable mxTable; + + public AccTreeNode (XAccessible xAccessible, XAccessibleContext xContext, AccessibleTreeNode aParent) + { + this (xAccessible, xContext, xContext, aParent); + } + + public AccTreeNode (XAccessible xAccessible, XAccessibleContext xContext, Object aDisplay, AccessibleTreeNode aParent) + { + super (aDisplay, aParent); + + maHandlers = new Vector(5); + mxContext = xContext; + mxAccessible = xAccessible; + } + + /** 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. + */ + public void update () + { + for (int i=0; i<maHandlers.size(); i++) + { + System.out.println ("replacing handler " + i); + HandlerDescriptor aDescriptor = (HandlerDescriptor)maHandlers.get(i); + aDescriptor.maHandler = aDescriptor.maHandler.createHandler (mxContext); + aDescriptor.mnChildCount = + aDescriptor.maHandler.getChildCount (this); + } + } + + public XAccessibleContext getContext () + { + return mxContext; + } + + public XAccessibleComponent getComponent () + { + if (mxComponent == null && mxContext != null) + mxComponent = (XAccessibleComponent)UnoRuntime.queryInterface( + XAccessibleComponent.class, mxContext); + return mxComponent; + } + + public XAccessibleExtendedComponent getExtendedComponent () + { + if (mxComponent == null) + getComponent(); + if (mxComponent != null) + return (XAccessibleExtendedComponent)UnoRuntime.queryInterface( + XAccessibleExtendedComponent.class, mxComponent); + else + return null; + } + + public XAccessibleText getText () + { + if (mxText == null && mxContext != null) + mxText = (XAccessibleText)UnoRuntime.queryInterface( + XAccessibleText.class, mxContext); + return mxText; + } + + public XAccessibleEditableText getEditText () + { + return (XAccessibleEditableText)UnoRuntime.queryInterface( + XAccessibleEditableText.class, mxContext); + } + + public XAccessibleTable getTable () + { + if (mxTable == null && mxContext != null) + mxTable = (XAccessibleTable)UnoRuntime.queryInterface( + XAccessibleTable.class, mxContext); + return mxTable; + } + + + public XAccessible getAccessible() + { + if ((mxAccessible == null) && (mxContext != null)) + mxAccessible = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, mxContext); + return mxAccessible; + } + + public XAccessibleSelection getSelection () + { + return (XAccessibleSelection)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 */ + protected HandlerDescriptor getHandlerDescriptor (int i) + { + HandlerDescriptor aDescriptor = (HandlerDescriptor)maHandlers.get(i); + if (aDescriptor.mnChildCount < 0) + aDescriptor.mnChildCount = + aDescriptor.maHandler.getChildCount (this); + return aDescriptor; + } + + 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 */ + 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; + } + + 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 (this, nIndex); + else + nIndex -= aDescriptor.mnChildCount; + } + } + else + throw new IndexOutOfBoundsException(); + + // nothing found? + return null; + } + + 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 (this, nIndex); + aDescriptor.mnChildCount = aDescriptor.maHandler.getChildCount (this); + break; + } + else + nIndex -= aDescriptor.mnChildCount; + } + } + else + throw new IndexOutOfBoundsException(); + + return bStatus; + } + + + 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 */ + public boolean isLeaf() + { + return (maHandlers.size() == 0);// || (getChildCount() == 0); + } + + public boolean equals (Object aOther) + { + return (this == aOther) || (aOther!=null && aOther.equals(mxContext)); + } + + + /** iterate over handlers until the child is found */ + public void getActions(Vector aActions) + { + for(int i = 0; i < maHandlers.size(); i++) + { + HandlerDescriptor aDescriptor = getHandlerDescriptor (i); + NodeHandler aHandler = aDescriptor.maHandler; + String[] aHandlerActions = aHandler.getActions (this); + for(int j = 0; j < aHandlerActions.length; j++ ) + { + aActions.add( aHandlerActions[j] ); + } + } + } + + 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 (this); + return aNode; + } + } + return null; + } + + /** Update the specified handlers. + @return + The returned array containes the indices of the updated children + and can be used to create a TreeModelEvent. + */ + public Vector updateChildren (java.lang.Class class1) + { + return updateChildren (class1, null); + } + + public Vector updateChildren (java.lang.Class class1, java.lang.Class class2) + { + Vector aChildIndices = new Vector(); + 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 (this); + aDescriptor.mnChildCount = nChildCount; + // Fill in the indices of the updated children. + for (int j=0; j<nChildCount; j++) + aChildIndices.add(new Integer(j+nOffset)); + } + nOffset += aDescriptor.mnChildCount; + } + return aChildIndices; + } +} diff --git a/toolkit/test/accessibility/AccessibilityTree.java b/toolkit/test/accessibility/AccessibilityTree.java new file mode 100755 index 000000000000..819631b41eb8 --- /dev/null +++ b/toolkit/test/accessibility/AccessibilityTree.java @@ -0,0 +1,377 @@ +import com.sun.star.accessibility.*; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.IndexOutOfBoundsException; +import com.sun.star.uno.UnoRuntime; + +import java.util.Vector; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.tree.*; +import javax.swing.event.*; + + + +/** 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); + + maCellRenderer = new AccessibleTreeCellRenderer(); + // setCellRenderer (maCellRenderer); + + // allow editing of XAccessibleText interfaces + // setEditable (true); + // maTreeModel.addTreeModelListener( new TextUpdateListener() ); + + 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) + { + maCanvas = aCanvas; + ((AccessibilityTreeModel)maTree.getModel()).setCanvas (maCanvas); + } + + /** Expand the nodes in the subtree rooted in aNode according to the the + specified expander. The tree is locked during the expansion. + */ + protected 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; + + // System.out.print ("e"); + + try + { + // get 'our' object + Object aObj = aPath.getLastPathComponent(); + + // expand this object, if the Expander tells us so + if( aExpander.expand( aObj ) ) + { + maTree.expandPath (aPath); + if( aFirst == null ) + 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()); + } + public void expandShapes (AccessibleTreeNode aNode) + { + expandTree (aNode, new ShapeExpander()); + } + + /** Expand all nodes */ + public void expandAll () + { + expandAll ((AccessibleTreeNode)maTree.getModel().getRoot()); + } + public void expandAll (AccessibleTreeNode aNode) + { + expandTree (aNode, new AllExpander()); + } + + + + public void disposing (com.sun.star.lang.EventObject e) + { + System.out.println ("disposing " + e); + } + + /* + public Dimension getPreferredSize () + { + Dimension aPreferredSize = super.getPreferredSize(); + Dimension aMinimumSize = super.getMinimumSize(); + if (aPreferredSize.width < aMinimumSize.width) + aPreferredSize.width = aMinimumSize.width; + return aPreferredSize; + } + */ + + class MouseListener extends MouseAdapter + { + public MouseListener (AccessibilityTree aTree) + { + maTree=aTree; + } + public void mousePressed(MouseEvent e) { popupTrigger(e); } + public void mouseClicked(MouseEvent e) { popupTrigger(e); } + public void mouseEntered(MouseEvent e) { popupTrigger(e); } + public void mouseExited(MouseEvent e) { popupTrigger(e); } + public void mouseReleased(MouseEvent e) { popupTrigger(e); } + + public boolean popupTrigger( MouseEvent e ) + { + boolean bIsPopup = e.isPopupTrigger(); + if( bIsPopup ) + { + int selRow = maTree.getComponent().getRowForLocation(e.getX(), e.getY()); + if (selRow != -1) + { + 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; + + Vector aActions = new Vector(); + 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.elementAt(i).toString(), + 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 AccessibilityTree maTree; + } + + class NodeAction extends AbstractAction + { + private int mnIndex; + private AccessibleTreeNode maNode; + + public 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. + class ShapeExpandAction extends AbstractAction + { + private AccessibilityTree maTree; + private 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. + class SubtreeExpandAction extends AbstractAction + { + private AccessibilityTree maTree; + private 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 */ + abstract class Expander + { + abstract public boolean expand (Object aObject); + } + + /** expand all nodes */ + class AllExpander extends Expander + { + public boolean expand(Object aObject) { return true; } + } + + /** expand all nodes with accessibility roles > 100 */ + class ShapeExpander extends Expander + { + public boolean expand (Object aObject) + { + if (aObject instanceof AccTreeNode) + { + AccTreeNode aNode = (AccTreeNode)aObject; + XAccessibleContext xContext = aNode.getContext(); + if (xContext != null) + if (xContext.getAccessibleRole() >= 100) + return true; + } + return false; + } + } + + + + protected AccessibleTreeCellRenderer + maCellRenderer; + + + private JTree + maTree; + private Canvas + maCanvas; + private boolean + mbFirstShapeSeen; + private int + mnExpandLevel; +} diff --git a/toolkit/test/accessibility/AccessibilityTreeModel.java b/toolkit/test/accessibility/AccessibilityTreeModel.java new file mode 100644 index 000000000000..d4981e86b4a0 --- /dev/null +++ b/toolkit/test/accessibility/AccessibilityTreeModel.java @@ -0,0 +1,513 @@ +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.tree.TreePath; + + +import java.util.Vector; +import java.util.HashMap; +import java.util.Enumeration; + +import com.sun.star.accessibility.*; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.Any; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.XServiceName; + +public class AccessibilityTreeModel + extends AccessibilityTreeModelBase +{ + public boolean mbVerbose = false; + + public AccessibilityTreeModel (AccessibleTreeNode aRoot) + { + // create default node (unless we have a 'proper' node) + if( ! (aRoot instanceof AccessibleTreeNode) ) + aRoot = new StringNode ("Root", null); + setRoot (aRoot); + + maNodeMap = new NodeMap(); + + maEventListener = new EventListener (this); + mxListener = new QueuedListener (maEventListener); + } + + 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()))); + } + + + + + /** Inform all listeners (especially the renderer) of a change of the + tree's structure. + @param aNode This node specifies the sub tree in which all changes + take place. + */ + public void FireTreeStructureChanged (AccessibleTreeNode aNode) + { + } + + + + + + public synchronized void setRoot (AccessibleTreeNode aRoot) + { + if (getRoot() == null) + super.setRoot (aRoot); + else + { + lock (); + maNodeMap.ForEach (new NodeMapCallback () { + public void Apply (AccTreeNode aNode) + { + if (maCanvas != null) + maCanvas.removeNode (aNode); + removeAccListener ((AccTreeNode)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. + */ + public 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; + } + + public Object getChildNoCreate (Object aParent, int nIndex) + { + AccessibleTreeNode aChild = (AccessibleTreeNode)super.getChildNoCreate (aParent, nIndex); + + return aChild; + } + + + + + /** Remove a node (and all children) from the tree model. + */ + protected 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 add a new child to a parent. + @return + Returns the new or existing representation of the specified + accessible object. + */ + protected AccessibleTreeNode addChild (AccTreeNode aParentNode, XAccessible xNewChild) + { + AccessibleTreeNode aChildNode = null; + try + { + boolean bRet = false; + + // 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 (createEvent (xParent, xChild)); + 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. + */ + protected 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 + */ + protected Object[] createPath (AccessibleTreeNode aNode) + { + Vector aPath = new Vector(); + 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. + // + + protected void fireTreeNodesChanged(TreeModelEvent e) + { + for(int i = 0; i < maTMListeners.size(); i++) + { + ((TreeModelListener)maTMListeners.get(i)).treeNodesChanged(e); + } + } + + protected void fireTreeNodesInserted(final TreeModelEvent e) + { + for(int i = 0; i < maTMListeners.size(); i++) + { + ((TreeModelListener)maTMListeners.get(i)).treeNodesInserted(e); + } + } + + protected void fireTreeNodesRemoved(final TreeModelEvent e) + { + for(int i = 0; i < maTMListeners.size(); i++) + { + ((TreeModelListener)maTMListeners.get(i)).treeNodesRemoved(e); + } + } + + protected void fireTreeStructureChanged(final TreeModelEvent e) + { + for(int i = 0; i < maTMListeners.size(); i++) + { + ((TreeModelListener)maTMListeners.get(i)).treeStructureChanged(e); + } + } + + protected TreeModelEvent createEvent (XAccessibleContext xParent) + { + AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent); + return new TreeModelEvent (this, createPath (aParentNode)); + } + + /** Create a TreeModelEvent object that informs listeners that one child + has been removed from or inserted into its parent. + */ + public TreeModelEvent createEvent (XAccessibleContext xParent, XAccessible xChild) + { + AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent); + return createEvent (aParentNode, xParent); + } + + public 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. + */ + protected TreeModelEvent createChangeEvent (AccTreeNode aNode, Vector 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 = ((Integer)aChildIndices.elementAt(i)).intValue(); + aChildObjects[i] = aNode.getChild (nIndex); + nChildIndices[i] = nIndex; + } + + return new TreeModelEvent (this, + createPath(aNode), + nChildIndices, + aChildObjects); + } + + + + /** + * broadcast a tree event in a seperate Thread + * must override fire method + */ + class EventRunner implements Runnable + { + public void run() + { + for(int i = 0; i < maTMListeners.size(); i++) + { + fire( (TreeModelListener)maTMListeners.get(i) ); + } + } + + protected void fire( TreeModelListener l) { } + } + + + + protected XAccessibleEventBroadcaster getBroadcaster (Object aObject) + { + if (aObject instanceof AccTreeNode) + return (XAccessibleEventBroadcaster) UnoRuntime.queryInterface ( + XAccessibleEventBroadcaster.class, ((AccTreeNode)aObject).getContext()); + else + return null; + } + + protected void registerAccListener( Object aObject ) + { + // register this as listener for XAccessibleEventBroadcaster + // implementations + XAccessibleEventBroadcaster xBroadcaster = getBroadcaster( aObject ); + if (xBroadcaster != null) + { + xBroadcaster.addEventListener( mxListener ); + } + } + + protected void removeAccListener( Object aObject ) + { + XAccessibleEventBroadcaster xBroadcaster = getBroadcaster( aObject ); + if (xBroadcaster != null) + { + xBroadcaster.removeEventListener( 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 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. + Vector 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 NodeMap maNodeMap; + + // If the lock count is higher then zero, then no events are processed. + private int mnLockCount; + + private Canvas maCanvas; + + private EventListener maEventListener; +} diff --git a/toolkit/test/accessibility/AccessibilityTreeModelBase.java b/toolkit/test/accessibility/AccessibilityTreeModelBase.java new file mode 100644 index 000000000000..e80819bef840 --- /dev/null +++ b/toolkit/test/accessibility/AccessibilityTreeModelBase.java @@ -0,0 +1,122 @@ +import javax.swing.tree.TreeModel; +import javax.swing.event.TreeModelListener; +import javax.swing.tree.TreePath; +import javax.swing.event.TreeModelEvent; +import java.util.Vector; + +public class AccessibilityTreeModelBase + implements TreeModel +{ + public AccessibilityTreeModelBase () + { + setRoot (null); + maTMListeners = new Vector(); + } + + 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 != null && 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 != null && 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 Vector 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 100755 index 000000000000..58ad607fed67 --- /dev/null +++ b/toolkit/test/accessibility/AccessibilityWorkBench.java @@ -0,0 +1,620 @@ +import com.sun.star.awt.XWindow; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.XPropertyChangeListener; +import com.sun.star.beans.PropertyChangeEvent; +import com.sun.star.container.XEnumerationAccess; +import com.sun.star.container.XEnumeration; +import com.sun.star.document.XEventListener; +import com.sun.star.drawing.XDrawPage; +import com.sun.star.drawing.XDrawView; +import com.sun.star.frame.XController; +import com.sun.star.frame.XFrame; +import com.sun.star.frame.XFrameActionListener; +import com.sun.star.frame.FrameActionEvent; +import com.sun.star.frame.FrameAction; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XModel; +import com.sun.star.frame.XTerminateListener; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleComponent; +import com.sun.star.accessibility.XAccessibleExtendedComponent; +import com.sun.star.accessibility.XAccessibleRelationSet; +import com.sun.star.accessibility.XAccessibleStateSet; + +import com.sun.star.awt.XExtendedToolkit; + +import java.util.Vector; +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 java.io.*; + +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 + +{ + public static final String msVersion = "v1.7.2"; + public 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); + info = new InformationWriter (); + + maAccessibilityTree.getComponent().addTreeSelectionListener (this); + + addWindowListener (new WindowAdapter () + { public void windowClosing (WindowEvent e) + { System.exit(0); } + }); + + initialize (); + } + + + + + /** Create and arrange the widgets of the GUI. + */ + public void Layout () + { + setSize (new Dimension (8000,600)); + + JScrollPane aScrollPane; + GridBagConstraints constraints; + + // Create new layout. + GridBagLayout aLayout = new GridBagLayout (); + getContentPane().setLayout (aLayout); + + // Accessible Tree. + maAccessibilityTree = new AccessibilityTree (); + // maAccessibilityTree.getComponent().setMinimumSize (new Dimension (250,300)); + 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 (); + // maObjectViewContainer.setPreferredSize (new Dimension (300,100)); + 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. + maMessageArea = MessageArea.Instance (); + // maMessageArea.setPreferredSize (new Dimension (300,50)); + + // Split pane for the two views and the message area. + JSplitPane aSplitPane = new JSplitPane (JSplitPane.VERTICAL_SPLIT, + aViewSplitPane, maMessageArea); + aSplitPane.setOneTouchExpandable(true); + addGridElement (aViewSplitPane, 0,0, 2,1, 3,3, + GridBagConstraints.CENTER, GridBagConstraints.BOTH); + + // Button bar. + maButtonBar = new JPanel(); + GridBagLayout aButtonLayout = new GridBagLayout (); + 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. + */ + 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. + */ + public 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>. + */ + JMenuBar CreateMenuBar () + { + // Menu bar. + maMenuBar = new JMenuBar (); + + // File menu. + JMenu aFileMenu = new JMenu ("File"); + maMenuBar.add (aFileMenu); + JMenuItem aItem; + aItem = new JMenuItem ("Quit"); + aFileMenu.add (aItem); + aItem.addActionListener (this); + + // View menu. + JMenu aViewMenu = new JMenu ("View"); + maMenuBar.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"); + maMenuBar.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"); + maMenuBar.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 maMenuBar; + } + + + + + /** 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. + */ + protected 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. + */ + protected 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 = (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 ("Notifiy Termination Event : " + aEvent); + } + + + + /// The Singleton Workbench object. + private static AccessibilityWorkBench + saWorkBench = null; + + protected SimpleOffice + office; + protected InformationWriter + info; + + private XModel + mxModel; + private JPanel + maMainPanel, + maButtonBar; + private Canvas + maCanvas; + private AccessibilityTree + maAccessibilityTree; + private ObjectViewContainer + maObjectViewContainer; + private JScrollPane + maScrollPane; + private MessageArea + maMessageArea; + private JButton + aConnectButton, + aQuitButton, + aUpdateButton, + aExpandButton, + aShapesButton; + private JMenuBar + maMenuBar; + private String + msMessage; + 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 000000000000..0aac7158efde --- /dev/null +++ b/toolkit/test/accessibility/AccessibleActionHandler.java @@ -0,0 +1,72 @@ + +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 +{ + public NodeHandler createHandler (XAccessibleContext xContext) + { + XAccessibleAction xEComponent = + (XAccessibleAction) UnoRuntime.queryInterface ( + XAccessibleAction.class, xContext); + if (xEComponent != null) + return new AccessibleActionHandler (xEComponent); + else + return null; + } + + public AccessibleActionHandler () + { + } + + public AccessibleActionHandler (XAccessibleAction xAction) + { + if (xAction != null) + maChildList.setSize (1 + xAction.getAccessibleActionCount()); + } + + protected static XAccessibleAction getAction (AccTreeNode aParent) + { + return (XAccessibleAction) UnoRuntime.queryInterface ( + XAccessibleAction.class, aParent.getContext()); + } + + 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 000000000000..7c72ac69803e --- /dev/null +++ b/toolkit/test/accessibility/AccessibleActionNode.java @@ -0,0 +1,48 @@ +import javax.swing.JOptionPane; +import com.sun.star.accessibility.XAccessibleAction; + +/** + Base class for all tree nodes. + */ +class AccessibleActionNode + extends StringNode +{ + public AccessibleActionNode (String aDisplayObject, + AccessibleTreeNode aParent, + int nActionIndex) + { + super (aDisplayObject, aParent); + mnActionIndex = nActionIndex; + } + + public String[] getActions () + { + return new String[] {"Perform Action"}; + } + + /** perform action */ + 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 int mnActionIndex; +} diff --git a/toolkit/test/accessibility/AccessibleCellHandler.java b/toolkit/test/accessibility/AccessibleCellHandler.java new file mode 100644 index 000000000000..19b4a9df67ad --- /dev/null +++ b/toolkit/test/accessibility/AccessibleCellHandler.java @@ -0,0 +1,156 @@ + +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 +{ + public NodeHandler createHandler (XAccessibleContext xContext) + { + AccessibleCellHandler aCellHandler = null; + if (xContext != null) + { + XAccessible xParent = xContext.getAccessibleParent(); + if (xParent != null) + { + XAccessibleTable xTable = + (XAccessibleTable) UnoRuntime.queryInterface ( + XAccessibleTable.class, xParent.getAccessibleContext()); + if (xTable != null) + aCellHandler = new AccessibleCellHandler (xTable); + } + } + return aCellHandler; + + } + + public AccessibleCellHandler () + { + } + + public AccessibleCellHandler (XAccessibleTable xTable) + { + if (xTable != null) + maChildList.setSize (8); + } + + protected static XAccessibleTable getTable(Object aObject) + { + return (XAccessibleTable) UnoRuntime.queryInterface ( + XAccessibleTable.class, aObject); + } + + 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 000000000000..38e5545d23aa --- /dev/null +++ b/toolkit/test/accessibility/AccessibleComponentHandler.java @@ -0,0 +1,102 @@ + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleComponent; + + +class AccessibleComponentHandler + extends NodeHandler +{ + + public NodeHandler createHandler (XAccessibleContext xContext) + { + XAccessibleComponent xComponent = + (XAccessibleComponent) UnoRuntime.queryInterface ( + XAccessibleComponent.class, xContext); + if (xComponent != null) + return new AccessibleComponentHandler (xComponent); + else + return null; + + } + + public AccessibleComponentHandler () + { + } + + public AccessibleComponentHandler (XAccessibleComponent xComponent) + { + if (xComponent != null) + maChildList.setSize (6); + } + + 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>>0&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>>0&0xff) + + "A" + (nColor>>24&0xff), + aParent); + break; + } + } + } + return aChild; + } + + public void update (AccessibleTreeNode aNode) + { + maChildList.clear(); + if (aNode instanceof AccTreeNode) + if (((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 000000000000..fd22bcd5367f --- /dev/null +++ b/toolkit/test/accessibility/AccessibleContextHandler.java @@ -0,0 +1,91 @@ +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleStateSet; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.container.XIndexAccess; +import java.util.HashMap; + +import tools.NameProvider; + +class AccessibleContextHandler + extends NodeHandler +{ + protected int nChildrenCount; + + public NodeHandler createHandler (XAccessibleContext xContext) + { + if (xContext != null) + return new AccessibleContextHandler (xContext); + else + return null; + } + + public AccessibleContextHandler () + { + super (); + } + + public AccessibleContextHandler (XAccessibleContext xContext) + { + super(); + if (xContext != null) + maChildList.setSize (4); + } + + public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex) + { + XAccessibleContext xContext = null; + if (aParent instanceof AccTreeNode) + xContext = ((AccTreeNode)aParent).getContext(); + + String sChild = new String(); + 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"); + /* if (xParent != ((AccTreeNode)aParent).getAccessible()) + { + sChild += " but that is inconsistent" + + "#" + xParent + " # " + ((AccTreeNode)aParent).getAccessible(); + } + */ + 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; + + /* case 3: + sChild = "Child count: " + xContext.getAccessibleChildCount(); + break;*/ + } + } + return new StringNode (sChild, aParent); + } +} diff --git a/toolkit/test/accessibility/AccessibleEditableTextHandler.java b/toolkit/test/accessibility/AccessibleEditableTextHandler.java new file mode 100644 index 000000000000..a79158c099ba --- /dev/null +++ b/toolkit/test/accessibility/AccessibleEditableTextHandler.java @@ -0,0 +1,40 @@ + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleEditableText; + + +class AccessibleEditableTextHandler extends NodeHandler +{ + public NodeHandler createHandler (XAccessibleContext xContext) + { + XAccessibleEditableText xText = + (XAccessibleEditableText) UnoRuntime.queryInterface ( + XAccessibleEditableText.class, xContext); + if (xText != null) + return new AccessibleEditableTextHandler (xText); + else + return null; + } + + public AccessibleEditableTextHandler () + { + } + + public AccessibleEditableTextHandler (XAccessibleEditableText xText) + { + if (xText != null) + maChildList.setSize (1); + } + + protected static XAccessibleEditableText getEText (AccTreeNode aNode) + { + return (XAccessibleEditableText) UnoRuntime.queryInterface ( + XAccessibleEditableText.class, aNode.getContext()); + } + + 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 000000000000..7f9fc17b23a5 --- /dev/null +++ b/toolkit/test/accessibility/AccessibleExtendedComponentHandler.java @@ -0,0 +1,73 @@ +import com.sun.star.uno.UnoRuntime; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleExtendedComponent; + + +class AccessibleExtendedComponentHandler + extends NodeHandler +{ + public NodeHandler createHandler (XAccessibleContext xContext) + { + XAccessibleExtendedComponent xEComponent = + (XAccessibleExtendedComponent) UnoRuntime.queryInterface ( + XAccessibleExtendedComponent.class, xContext); + if (xEComponent != null) + return new AccessibleExtendedComponentHandler (xEComponent); + else + return null; + } + + public AccessibleExtendedComponentHandler () + { + } + + public AccessibleExtendedComponentHandler (XAccessibleExtendedComponent xEComponent) + { + if (xEComponent != null) + maChildList.setSize (0); + } + + private static XAccessibleExtendedComponent getComponent (AccTreeNode aNode) + { + return (XAccessibleExtendedComponent) UnoRuntime.queryInterface ( + XAccessibleExtendedComponent.class, + aNode.getContext()); + } + + + 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 ("Depricated Foreground color: R" + + (nColor>>16&0xff) + + "G" + (nColor>>8&0xff) + + "B" + (nColor>>0&0xff) + + "A" + (nColor>>24&0xff), + aParent); + break; + case 1: + nColor = xEComponent.getBackground(); + aChild = new StringNode ("Depricated Background color: R" + + (nColor>>16&0xff) + + "G" + (nColor>>8&0xff) + + "B" + (nColor>>0&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 000000000000..674331317f7e --- /dev/null +++ b/toolkit/test/accessibility/AccessibleHyperlinkHandler.java @@ -0,0 +1,42 @@ + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleHyperlink; + + +class AccessibleHyperlinkHandler extends AccessibleTreeHandler +{ + public NodeHandler createHandler (XAccessibleContext xContext) + { + XAccessibleHyperlink xLink = + (XAccessibleHyperlink) UnoRuntime.queryInterface ( + XAccessibleHyperlink.class, xContext); + if (xLink != null) + return new AccessibleHyperlinkHandler (xLink); + else + return null; + } + + public AccessibleHyperlinkHandler () + { + } + + public AccessibleHyperlinkHandler (XAccessibleHyperlink xLink) + { + if (xLink != null) + maChildList.setSize (1); + } + + protected XAccessibleHyperlink getHyperlink(Object aObject) + { + XAccessibleHyperlink xHyperlink = + (XAccessibleHyperlink) UnoRuntime.queryInterface ( + XAccessibleHyperlink.class, aObject); + return xHyperlink; + } + + 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 000000000000..aa703942bc4c --- /dev/null +++ b/toolkit/test/accessibility/AccessibleHypertextHandler.java @@ -0,0 +1,42 @@ + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleHypertext; + + +class AccessibleHypertextHandler extends AccessibleTreeHandler +{ + public NodeHandler createHandler (XAccessibleContext xContext) + { + XAccessibleHypertext xText = + (XAccessibleHypertext) UnoRuntime.queryInterface ( + XAccessibleHypertext.class, xContext); + if (xText != null) + return new AccessibleHypertextHandler (xText); + else + return null; + } + + public AccessibleHypertextHandler () + { + } + + public AccessibleHypertextHandler (XAccessibleHypertext xText) + { + if (xText != null) + maChildList.setSize (1); + } + + protected static XAccessibleHypertext getHypertext (AccTreeNode aNode) + { + XAccessibleHypertext xHypertext = + (XAccessibleHypertext) UnoRuntime.queryInterface ( + XAccessibleHypertext.class, aNode.getContext()); + return xHypertext; + } + + 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 000000000000..92917e1b9740 --- /dev/null +++ b/toolkit/test/accessibility/AccessibleImageHandler.java @@ -0,0 +1,51 @@ + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleImage; + + +class AccessibleImageHandler extends NodeHandler +{ + public NodeHandler createHandler (XAccessibleContext xContext) + { + XAccessibleImage xImage = + (XAccessibleImage) UnoRuntime.queryInterface ( + XAccessibleImage.class, xContext); + if (xImage != null) + return new AccessibleImageHandler (xImage); + else + return null; + } + + public AccessibleImageHandler () + { + } + + public AccessibleImageHandler (XAccessibleImage xImage) + { + if (xImage != null) + maChildList.setSize (1); + } + + protected static XAccessibleImage getImage (AccTreeNode aNode) + { + return (XAccessibleImage) UnoRuntime.queryInterface ( + XAccessibleImage.class, aNode.getContext()); + } + + 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 000000000000..ea3be4c16264 --- /dev/null +++ b/toolkit/test/accessibility/AccessibleRelationHandler.java @@ -0,0 +1,96 @@ +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.accessibility.AccessibleRelationType; +import com.sun.star.lang.IndexOutOfBoundsException; + +import tools.NameProvider; + +class AccessibleRelationHandler + extends NodeHandler +{ + 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() + { + } + + public AccessibleRelationHandler( XAccessibleContext xContext ) + { + XAccessibleRelationSet xRelation = xContext.getAccessibleRelationSet(); + if (xRelation != null) + maChildList.setSize( 1 ); + } + + 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 = + (XAccessible)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 000000000000..f7ab62807332 --- /dev/null +++ b/toolkit/test/accessibility/AccessibleSelectionHandler.java @@ -0,0 +1,130 @@ + +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; + +import javax.swing.*; +import java.awt.*; +import java.util.Vector; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; + + + +class AccessibleSelectionHandler + extends NodeHandler +{ + public NodeHandler createHandler( XAccessibleContext xContext ) + { + XAccessibleSelection xSelection = + (XAccessibleSelection) UnoRuntime.queryInterface( + XAccessibleSelection.class, xContext); + return (xSelection == null) ? null : + new AccessibleSelectionHandler(xSelection); + } + + public AccessibleSelectionHandler() + { + } + + public AccessibleSelectionHandler( XAccessibleSelection xSelection ) + { + if (xSelection != null) + maChildList.setSize( 2 ); + } + + public AccessibleTreeNode createChild( AccessibleTreeNode aParent, + int nIndex ) + { + AccessibleTreeNode aChild = null; + + if( aParent instanceof AccTreeNode ) + { + XAccessibleSelection xSelection = + ((AccTreeNode)aParent).getSelection(); + if( xSelection != 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; + } + + + 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]; + } + + public void performAction (AccessibleTreeNode aNode, int nIndex) + { + new SelectionDialog( (AccTreeNode)aNode ).show(); + } +} diff --git a/toolkit/test/accessibility/AccessibleTableHandler.java b/toolkit/test/accessibility/AccessibleTableHandler.java new file mode 100644 index 000000000000..c3883f649d5e --- /dev/null +++ b/toolkit/test/accessibility/AccessibleTableHandler.java @@ -0,0 +1,90 @@ + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleTable; + + +class AccessibleTableHandler extends NodeHandler +{ + public NodeHandler createHandler (XAccessibleContext xContext) + { + XAccessibleTable xTable = + (XAccessibleTable) UnoRuntime.queryInterface ( + XAccessibleTable.class, xContext); + if (xTable != null) + return new AccessibleTableHandler (xTable); + else + return null; + } + + public AccessibleTableHandler () + { + } + + public AccessibleTableHandler (XAccessibleTable xTable) + { + if (xTable != null) + maChildList.setSize (4); + } + + protected static XAccessibleTable getTable(Object aObject) + { + return (XAccessibleTable) UnoRuntime.queryInterface ( + XAccessibleTable.class, aObject); + } + + 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 000000000000..6fa083b22ea3 --- /dev/null +++ b/toolkit/test/accessibility/AccessibleTextHandler.java @@ -0,0 +1,792 @@ + +import com.sun.star.accessibility.AccessibleTextType; +import com.sun.star.accessibility.TextSegment; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleText; +import com.sun.star.accessibility.XAccessibleEditableText; + +import com.sun.star.awt.Rectangle; +import com.sun.star.awt.Point; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.lang.IndexOutOfBoundsException; +import com.sun.star.beans.PropertyValue; + +import java.util.Vector; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import javax.swing.JDialog; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JLabel; +import javax.swing.Icon; +import javax.swing.JTextArea; +import javax.swing.JOptionPane; +import javax.swing.JCheckBox; +import javax.swing.JColorChooser; +import javax.swing.BoxLayout; +import javax.swing.text.JTextComponent; + + +class AccessibleTextHandler extends NodeHandler +{ + public NodeHandler createHandler (XAccessibleContext xContext) + { + XAccessibleText xText = (XAccessibleText) UnoRuntime.queryInterface ( + XAccessibleText.class, xContext); + if (xText != null) + return new AccessibleTextHandler (xText); + else + return null; + } + + public AccessibleTextHandler () + { + } + + public AccessibleTextHandler (XAccessibleText xText) + { + if (xText != null) + maChildList.setSize (8); + } + + 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 = new String (""); + } + + // 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( IndexOutOfBoundsException e ) + { + aRet = new StringNode( "Exception caught:" + e, aParent ); + } + + return aRet; + } + + + static String[] aTextActions = + new String[] { "select...", "copy..." }; + static String[] aEditableTextActions = + new String[] { "select...", "copy...", + "cut...", "paste...", "edit...", "format..." }; + + public String[] getActions (AccessibleTreeNode aNode) + { + XAccessibleEditableText xEText = null; + if (aNode instanceof AccTreeNode) + xEText = ((AccTreeNode)aNode).getEditText (); + + return (xEText == null) ? aTextActions : aEditableTextActions; + } + + 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" ) + { + 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" ) + { + 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" ) + { + 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" ) + { + 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.show(); + } + +} + +/** + * Display a dialog with a text field and a pair of cancel/do-it buttons + */ +class TextActionDialog extends JDialog + implements ActionListener +{ + AccTreeNode aNode; + JTextArea aText; + String sName; + JCheckBox aIndexToggle; + + public TextActionDialog( AccTreeNode aNd, + String sExplanation, + String sButtonText ) + { + super( AccessibilityWorkBench.Instance() ); + + aNode = aNd; + sName = sButtonText; + init( sExplanation, aNode.getText().getText(), sButtonText ); +// setSize( getPreferredSize() ); + setSize( 350, 225 ); + } + + /** build dialog */ + protected void init( String sExplanation, + String sText, + String sButtonText ) + { + setTitle( sName ); + + // vertical stacking of the elements + Container aContent = getContentPane(); + // aContent.setLayout( new BorderLayout() ); + + // 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 ); + } + + void cancel() + { + hide(); + dispose(); + } + + 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); } + int getSelection(boolean bStart) + { + return ( bStart ^ aIndexToggle.isSelected() ) + ? aText.getSelectionStart() : aText.getSelectionEnd(); + } + + + + /** override this for dialog-specific action */ + boolean action( JTextComponent aText, AccTreeNode aNode ) + throws IndexOutOfBoundsException + { + return false; + } +} + + +class TextEditDialog extends TextActionDialog +{ + public TextEditDialog( AccTreeNode aNode, + String sExplanation, + String sButtonText ) + { + super( aNode, sExplanation, sButtonText ); + } + + protected void init( String sExplanation, + String sText, + String sButtonText ) + { + super.init( sExplanation, sText, sButtonText ); + aText.setEditable( true ); + } + + + /** edit the text */ + 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 */ + 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; + + 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 ); + } + + + class ColorIcon implements Icon + { + boolean bForeground; + static final int nHeight = 16; + 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 */ + 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 = new Integer( aBold.isSelected() ? 150 : 100 ); + aSequence[1] = new PropertyValue(); + aSequence[1].Name = "CharUnderline"; + aSequence[1].Value = new Integer( aUnderline.isSelected() ? 1 : 0 ); + aSequence[2] = new PropertyValue(); + aSequence[2].Name = "CharBackColor"; + aSequence[2].Value = new Integer( aBackground.getRGB() ); + aSequence[3] = new PropertyValue(); + aSequence[3].Name = "CharColor"; + aSequence[3].Value = new Integer( aForeground.getRGB() ); + aSequence[4] = new PropertyValue(); + aSequence[4].Name = "CharPosture"; + aSequence[4].Value = new Integer( aItalics.isSelected() ? 1 : 0 ); + aSequence[5] = new PropertyValue(); + aSequence[5].Name = "CharBackTransparent"; + aSequence[5].Value = new Boolean( false ); + + bSuccess = xEdit.setAttributes( getSelectionStart(), + getSelectionEnd(), + aSequence ); + } + return bSuccess; + } + +} diff --git a/toolkit/test/accessibility/AccessibleTreeCellRenderer.java b/toolkit/test/accessibility/AccessibleTreeCellRenderer.java new file mode 100644 index 000000000000..deb3cb967133 --- /dev/null +++ b/toolkit/test/accessibility/AccessibleTreeCellRenderer.java @@ -0,0 +1,86 @@ +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreePath; +import javax.swing.JTree; +import java.awt.Color; +import java.awt.Component; +import java.util.Vector; + + +public class AccessibleTreeCellRenderer + extends DefaultTreeCellRenderer +{ + public Color + maDefaultColor, + maChangedColor; + protected Vector + maChangedLines; + + + + public AccessibleTreeCellRenderer () + { + maDefaultColor = Color.black; + maChangedColor = Color.red; + maChangedLines = new Vector (); + } + + public Component getTreeCellRendererComponent ( + JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) + { + super.getTreeCellRendererComponent( + tree, value, sel, + expanded, leaf, row, + hasFocus); + + if (maChangedLines.size()<=row || maChangedLines.elementAt (row) == null) + setTextNonSelectionColor (maDefaultColor); + else + setTextNonSelectionColor (maChangedColor); + + return this; + } + + /** Tell the cell renderer that no changes shall be displayed anymore. + */ + public void clearAllChanges () + { + maChangedLines.clear(); + } + + /** Inform the cell renderer of a new changed line which to paint + highlighted when asked to paint it the next time. + */ + public void addChangedLine (int nRow) + { + if (maChangedLines.size() <= nRow) + maChangedLines.setSize (nRow+1); + nRow -= 1; // row index is one to large for some reason. + maChangedLines.set (nRow, new Boolean (true)); + } + + /** Inform the cell renderer of a set of changed line which to paint + highlighted when asked to paint them the next time. + @param aChangedNodes + The set of changed nodes. Each entry is a TreePath. + @param aTree + The JTree that is used to transform the given TreePath objects + into rows. + */ + public void addChangedNodes (Vector aChangedNodes, JTree aTree) + { + for (int i=0; i<aChangedNodes.size(); i++) + { + TreePath aPath = (TreePath)aChangedNodes.elementAt (i); + int nRow = aTree.getRowForPath (aPath); + addChangedLine (nRow); + } + } + +} + diff --git a/toolkit/test/accessibility/AccessibleTreeHandler.java b/toolkit/test/accessibility/AccessibleTreeHandler.java new file mode 100644 index 000000000000..f45db8cb5ab9 --- /dev/null +++ b/toolkit/test/accessibility/AccessibleTreeHandler.java @@ -0,0 +1,110 @@ +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.lang.IndexOutOfBoundsException; + + +/** + * Map the tree of accessibility objects into their + * AccessibilityTreeModel counterparts. + */ +class AccessibleTreeHandler + extends NodeHandler +{ + protected XAccessibleContext mxContext; + + public NodeHandler createHandler (XAccessibleContext xContext) + { + if (xContext != null) + return new AccessibleTreeHandler (xContext); + else + return null; + } + + public AccessibleTreeHandler () + { + super(); + mxContext = null; + } + + public 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()); + } + } + + 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.insertElementAt (aChild, nIndex); + } + } + } + } + return aChild; + } + + + /** Update only the child count node. Trust on other ways to update the + accessible children. + */ + public void update (AccessibleTreeNode aNode) + { + synchronized (maChildList) + { + maChildList.setElementAt (null, 0); + } + } +} diff --git a/toolkit/test/accessibility/AccessibleTreeNode.java b/toolkit/test/accessibility/AccessibleTreeNode.java new file mode 100644 index 000000000000..f9b0799e4423 --- /dev/null +++ b/toolkit/test/accessibility/AccessibleTreeNode.java @@ -0,0 +1,101 @@ +import java.util.Vector; +import com.sun.star.lang.IndexOutOfBoundsException; + +/** + Base class for all tree nodes. + */ +class AccessibleTreeNode +{ + /// The parent node. It is null for the root node. + protected AccessibleTreeNode maParent; + + /// The object to be displayed. + private Object maDisplayObject; + + public AccessibleTreeNode (Object aDisplayObject, AccessibleTreeNode aParent) + { + maDisplayObject = aDisplayObject; + maParent = aParent; + } + + public void update () + { + // Empty + } + + public AccessibleTreeNode getParent () + { + return maParent; + } + + public Object getDisplayObject () + { + return maDisplayObject; + } + + 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 int indexOf (AccessibleTreeNode aNode) + { + return -1; + } + + /** Create a path to this node by first asking the parent for its path + and then appending this object. + */ + public void createPath (java.util.Vector aPath) + { + if (maParent != null) + maParent.createPath (aPath); + aPath.add (this); + } + + public Object[] createPath () + { + Vector aPath = new Vector (1); + createPath (aPath); + return aPath.toArray(); + } + + public boolean isLeaf() + { + return true; + } + + public String toString() + { + return maDisplayObject.toString(); + } + + /** get names of suported 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 000000000000..d52e60cd721f --- /dev/null +++ b/toolkit/test/accessibility/AccessibleUNOHandler.java @@ -0,0 +1,115 @@ +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.accessibility.AccessibleRelationType; +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 +{ + public NodeHandler createHandler (XAccessibleContext xContext) + { + if (xContext == null) + return null; + else + return new AccessibleUNOHandler (xContext); + } + + public AccessibleUNOHandler() + { + } + + public AccessibleUNOHandler (XAccessibleContext xContext) + { + maChildList.setSize (3); + } + + private XServiceInfo GetServiceInfo (AccessibleTreeNode aNode) + { + XServiceInfo xServiceInfo = null; + if (aNode instanceof AccTreeNode) + xServiceInfo = (XServiceInfo)UnoRuntime.queryInterface( + XServiceInfo.class, ((AccTreeNode)aNode).getContext()); + return xServiceInfo; + } + private XTypeProvider GetTypeProvider (AccessibleTreeNode aNode) + { + XTypeProvider xTypeProvider = null; + if (aNode instanceof AccTreeNode) + xTypeProvider = (XTypeProvider)UnoRuntime.queryInterface( + XTypeProvider.class, ((AccTreeNode)aNode).getContext()); + return xTypeProvider; + } + + public AccessibleTreeNode createChild (AccessibleTreeNode aParent, + int nIndex) + { + AccessibleTreeNode aChild = null; + XServiceInfo xServiceInfo; + switch (nIndex) + { + case 0 : // Implemenation 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 100755 index 000000000000..a1d8fb0f7d08 --- /dev/null +++ b/toolkit/test/accessibility/Canvas.java @@ -0,0 +1,448 @@ +import java.util.*; +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 java.awt.geom.Rectangle2D; + +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleComponent; + +/** 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 (); + maNodes = new Vector (); + maObjectList = new Vector (); + maContexts = new Vector (); + 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); + maLastWidgetSize = new Dimension (0,0); + } + + /** 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 = (CanvasShape) maObjects.get (aNode); + if (aObject == null) + { + aObject = new CanvasShape (aNode); + // Update bounding box that includes all objects. + if (maObjects.size() == 0) + 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 ) + { + Object aObject = maObjects.get(aNode); + maObjectList.remove (aObject); + maObjects.remove (aObject); + maNodes.remove (aNode); + repaint (); + } + } + + public void updateNode (AccTreeNode aNode) + { + int i = maNodes.indexOf (aNode); + if (i != -1) + { + CanvasShape aObject = (CanvasShape)maObjects.get(aNode); + if (aObject != null) + aObject.update(); + } + } + + public void updateNodeGeometry (AccTreeNode aNode) + { + CanvasShape aObject = (CanvasShape)maObjects.get(aNode); + if (aObject != null) + aObject.updateGeometry(); + } + + public void clear () + { + while (maNodes.size() > 0) + removeNode ((AccTreeNode)maNodes.elementAt(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"); + } + + public void setShowText (boolean bNewValue) + { + Options.SetBoolean ("ShowText", bNewValue); + repaint (); + } + + public void setZoomMode (int nZoomMode) + { + Options.SetInteger ("ZoomMode", nZoomMode); + repaint (); + } + + public int getZoomMode () + { + return Options.GetInteger ("ZoomMode", WHOLE_SCREEN); + } + + + 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 arround 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 = (CanvasShape)maObjectList.elementAt(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, + mnHOffset, mnVOffset, mnScale); + } + } + + + + + /** 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; + } + } + maLastWidgetSize = aWidgetSize; + } + + + + /** 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)); + } + + protected CanvasShape FindCanvasShapeUnderMouse (MouseEvent e) + { + int nObjects = maObjects.size(); + CanvasShape aObjectUnderMouse = null; + int nCount = maObjectList.size(); + for (int i=nCount-1; i>=0; --i) + { + CanvasShape aObject = (CanvasShape)maObjectList.elementAt(i); + if (aObject != null) + if (aObject.contains (e.getX(),e.getY())) + { + aObjectUnderMouse = aObject; + break; + } + } + return aObjectUnderMouse; + } + + protected 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 = (CanvasShape)maObjects.get ((AccTreeNode)aObject); + if (highlightObject (aCanvasShape)) + repaint(); + } + } + + private int + mnXAnchor, + mnYAnchor, + maResizeFlag; + private double + mnHOffset, + mnVOffset, + mnScale; + private CanvasShape + maActiveObject; + private java.util.HashMap + maObjects; + private Vector + maObjectList, + maContexts, + maNodes; + private Rectangle + maBoundingBox; + private JTree + maTree; + // The size of the widget at the last call of setupTransformation() + private Dimension + maLastWidgetSize; +} diff --git a/toolkit/test/accessibility/CanvasShape.java b/toolkit/test/accessibility/CanvasShape.java new file mode 100644 index 000000000000..57cedebb9e88 --- /dev/null +++ b/toolkit/test/accessibility/CanvasShape.java @@ -0,0 +1,330 @@ +import java.awt.*; +import javax.swing.*; +import javax.swing.tree.*; +import java.awt.geom.Rectangle2D; + +import com.sun.star.beans.XPropertyChangeListener; +import com.sun.star.beans.PropertyChangeEvent; + +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleComponent; +import com.sun.star.accessibility.XAccessibleExtendedComponent; +import com.sun.star.accessibility.XAccessibleText; +import com.sun.star.accessibility.XAccessibleStateSet; +import com.sun.star.accessibility.AccessibleStateType; + +class CanvasShape +{ + public final Color maHighlightColor = Color.red; + public final Color maSelectionColor = Color.green; + public final Color maFocusColor = Color.blue; + + // public AccessibleObject (XAccessibleContext xContext, TreePath aPath) + 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; + mnRole = -1; + 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(); + mnRole = mxContext.getAccessibleRole(); + + // 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. + Point aLocation = new Point(); + 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, + double nXOffset, double nYOffset, double nScaleFactor) + { + 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) + {} + } + } + + + + + /** Callback for disposing events. + */ + public void disposing (com.sun.star.lang.EventObject e) + { + System.out.println ("Disposing"); + } + + + + + /** 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 boolean isHighlighted () + { + return mbHighlighted; + } + + public Rectangle getBBox () + { + return new Rectangle (maPosition, maSize); + } + + public Point getOrigin () + { + return maPosition; + } + + public TreePath getPath () + { + return new TreePath (maNode.createPath()); + } + + public int getRole () + { + return mnRole; + } + + public XAccessibleContext getContext () + { + return mxContext; + } + + public XAccessibleComponent getComponent () + { + return mxComponent; + } + + public String toString () + { + return ">"+msName+", "+msDescription+" +"+maPosition.x+"+"+maPosition.y + +"x"+maSize.width+"x"+maSize.height+"<"; + } + + private AccTreeNode + maNode; + private XAccessibleContext + mxContext; + private XAccessibleComponent + mxComponent; + private String + msDescription, + msName; + private Rectangle2D.Double + maShape; + private Point + maPosition; + private Dimension + maTransformedSize, + 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; + private int + mnRole; +} diff --git a/toolkit/test/accessibility/ChildEventHandler.java b/toolkit/test/accessibility/ChildEventHandler.java new file mode 100644 index 000000000000..b73c90feac6d --- /dev/null +++ b/toolkit/test/accessibility/ChildEventHandler.java @@ -0,0 +1,46 @@ +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 = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, aEvent.OldValue); + mxNewChild = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, aEvent.NewValue); + } + + public void PrintOldAndNew (PrintStream out) + { + if (mxOldChild != null) + out.println (" removing child " + mxOldChild); + if (mxNewChild != null) + out.println (" adding child " + mxNewChild); + } + + 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 XAccessible mxOldChild; + private XAccessible mxNewChild; +} diff --git a/toolkit/test/accessibility/ContextEventHandler.java b/toolkit/test/accessibility/ContextEventHandler.java new file mode 100644 index 000000000000..ab7166fdede1 --- /dev/null +++ b/toolkit/test/accessibility/ContextEventHandler.java @@ -0,0 +1,52 @@ +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.AccessibleEventObject; +import com.sun.star.accessibility.AccessibleEventId; +import com.sun.star.uno.UnoRuntime; +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); + } + + 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); + } + + } + + 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 000000000000..69f7fd2144f0 --- /dev/null +++ b/toolkit/test/accessibility/EventHandler.java @@ -0,0 +1,57 @@ +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 = (XAccessibleContext)UnoRuntime.queryInterface( + XAccessibleContext.class, aEvent.Source); + if (mxEventSource == null) + { + XAccessible 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 000000000000..619c7fdd355e --- /dev/null +++ b/toolkit/test/accessibility/EventListener.java @@ -0,0 +1,124 @@ + +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeModelEvent; + +import java.util.Vector; +import java.util.HashMap; +import java.util.Enumeration; + +import com.sun.star.accessibility.*; +import com.sun.star.uno.*; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.Any; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.XServiceName; + +/** Objects of this class (usually one, singleton?) listen to accessible + events of all objects in all trees. +*/ +public class EventListener +{ + public boolean mbVerbose = false; + + public EventListener (AccessibilityTreeModel aTreeModel) + { + maTreeModel = aTreeModel; + } + + + private static String objectToString(Object aObject) + { + if (aObject == null) + return null; + else + return aObject.toString(); + } + + + + /** 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: + aHandler = new EventHandler (aEvent, maTreeModel); + break; + + case AccessibleEventId.HYPERTEXT_CHANGED: + aHandler = new EventHandler (aEvent, maTreeModel); + break; + + 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 AccessibilityTreeModel maTreeModel; +} diff --git a/toolkit/test/accessibility/EventLogger.java b/toolkit/test/accessibility/EventLogger.java new file mode 100644 index 000000000000..de0b8e6aee9d --- /dev/null +++ b/toolkit/test/accessibility/EventLogger.java @@ -0,0 +1,31 @@ +import javax.swing.JFrame; +import javax.swing.JScrollPane; + +class EventLogger +{ + public static synchronized EventLogger Instance () + { + if (maInstance == null) + maInstance = new EventLogger(); + return maInstance; + } + + private EventLogger () + { + try + { + maFrame = new JFrame (); + maLogger = new TextLogger (); + maFrame.setContentPane (new JScrollPane (maLogger)); + + maFrame.setSize (400,300); + maFrame.setVisible (true); + } + catch (Exception e) + {} + } + + private static EventLogger maInstance = null; + private JFrame maFrame; + private TextLogger maLogger; +} diff --git a/toolkit/test/accessibility/EventQueue.java b/toolkit/test/accessibility/EventQueue.java new file mode 100644 index 000000000000..9c90af9c63b7 --- /dev/null +++ b/toolkit/test/accessibility/EventQueue.java @@ -0,0 +1,126 @@ +import com.sun.star.accessibility.*; +import com.sun.star.lang.EventObject; + +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 syncronization. +*/ +class EventQueue + implements Runnable +{ + public boolean mbVerbose = false; + public 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 ("queing 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 ("queing disposing event " + aEvent); + maDisposingQueue.addLast (aEvent); + maMonitor.notify (); + } + } + + + private EventQueue () + { + maMonitor = new Boolean (true); + maRegularQueue = new LinkedList(); + maDisposingQueue = new LinkedList(); + 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 = (Runnable)maDisposingQueue.removeFirst(); + if (mbVerbose) + System.out.println ("delivering disposing event " + aEvent); + } + else if (maRegularQueue.size() > 0) + { + aEvent = (Runnable)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 Object maMonitor; + private LinkedList maRegularQueue; + private LinkedList maDisposingQueue; +} + + diff --git a/toolkit/test/accessibility/FrameActionListener.java b/toolkit/test/accessibility/FrameActionListener.java new file mode 100644 index 000000000000..30324fb9bc52 --- /dev/null +++ b/toolkit/test/accessibility/FrameActionListener.java @@ -0,0 +1,21 @@ +import com.sun.star.frame.XFrameActionListener; +import com.sun.star.frame.FrameActionEvent; + +import com.sun.star.lang.EventObject; + +public class FrameActionListener + implements XFrameActionListener +{ + public FrameActionListener () + { + } + + public void frameAction (com.sun.star.frame.FrameActionEvent aEvent) + { + System.out.println ("frame action"); + } + + public void disposing (com.sun.star.lang.EventObject aEvent) + { + } +} diff --git a/toolkit/test/accessibility/GeometryEventHandler.java b/toolkit/test/accessibility/GeometryEventHandler.java new file mode 100644 index 000000000000..07236785e862 --- /dev/null +++ b/toolkit/test/accessibility/GeometryEventHandler.java @@ -0,0 +1,54 @@ +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.AccessibleEventObject; +import com.sun.star.uno.UnoRuntime; + +import java.io.PrintStream; +import java.util.LinkedList; + +class GeometryEventHandler + extends EventHandler +{ + public GeometryEventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel) + { + super (aEvent, aTreeModel); + } + + public void PrintOldAndNew (PrintStream out) + { + out.println (" children not relevant"); + } + + 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 aShapeQueue = new LinkedList(); + 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 000000000000..74627ad99761 --- /dev/null +++ b/toolkit/test/accessibility/HelpWindow.java @@ -0,0 +1,185 @@ +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.IOException; +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.toURL()); + } + catch (MalformedURLException e) + { + e.printStackTrace (System.err); + } + } + public void loadURL (String sURL) + { + try + { + loadURL (new URL (sURL)); + } + catch (MalformedURLException e) + { + e.printStackTrace (System.err); + } + } + + + + + public void loadURL (URL aURL) + { + maHistory.addLast (aURL); + selectHistoryPage (maHistory.size()-1); + maFrame.toFront (); + } + + + + + private HelpWindow () + { + try + { + maCurrentHistoryEntry = -1; + maHistory = new LinkedList(); + + maFrame = new JFrame (); + maFrame.addWindowListener (new WindowAdapter () + { + 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 = (URL)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 maHistory; + private int maCurrentHistoryEntry; + private JButton maPrevButton; + private JButton maNextButton; +} diff --git a/toolkit/test/accessibility/InformationWriter.java b/toolkit/test/accessibility/InformationWriter.java new file mode 100755 index 000000000000..e119d2037350 --- /dev/null +++ b/toolkit/test/accessibility/InformationWriter.java @@ -0,0 +1,415 @@ +import java.lang.Thread; + +import com.sun.star.awt.Rectangle; +import com.sun.star.awt.XWindow; + +import com.sun.star.beans.Property; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.XPropertySetInfo; + +import com.sun.star.container.XIndexAccess; +import com.sun.star.container.XChild; +import com.sun.star.container.XEnumerationAccess; +import com.sun.star.container.XEnumeration; + +import com.sun.star.frame.XComponentLoader; +import com.sun.star.frame.XController; +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XFrame; +import com.sun.star.frame.XTasksSupplier; +import com.sun.star.frame.XTask; + +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.XServiceName; +import com.sun.star.lang.XTypeProvider; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.Type; + +import com.sun.star.drawing.XDrawView; +import com.sun.star.drawing.XDrawPage; +import com.sun.star.drawing.XShapes; +import com.sun.star.drawing.XShape; +import com.sun.star.drawing.XShapeDescriptor; + +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleComponent; +import com.sun.star.accessibility.XAccessibleRelationSet; +import com.sun.star.accessibility.XAccessibleStateSet; + +public class InformationWriter +{ + public InformationWriter () + { + } + + public void drawPageTest (XInterface xPage) + { + try + { + printProperty (xPage, "BorderBottom ", "BorderBottom"); + printProperty (xPage, "BorderLeft ", "BorderLeft"); + printProperty (xPage, "BorderRight ", "BorderRight"); + printProperty (xPage, "BorderTop ", "BorderTop"); + printProperty (xPage, "Height ", "Height"); + printProperty (xPage, "Width ", "Width"); + printProperty (xPage, "Number ", "Number"); + } + catch (Exception e) + { + System.out.println ("caught exception while testing draw page:" + e); + } + } + + public void printProperty (XInterface xObject, String prefix, String name) + { + try + { + XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, xObject); + MessageArea.println (prefix + + xPropertySet.getPropertyValue (name)); + } + catch (Exception e) + { + MessageArea.println ("caught exception while getting property " + + name + " : " + e); + } + } + + + + public void showShapes (XDrawPage xPage) + { + try + { + XIndexAccess xShapeList = (XIndexAccess) UnoRuntime.queryInterface( + XIndexAccess.class, xPage); + + MessageArea.println ("There are " + xShapeList.getCount() + + " shapes"); + for (int i=0; i<xShapeList.getCount(); i++) + { + XShape xShape = (XShape) UnoRuntime.queryInterface( + XShape.class, xShapeList.getByIndex (i)); + + XShapeDescriptor xShapeDescriptor = + (XShapeDescriptor) UnoRuntime.queryInterface( + XShapeDescriptor.class, xShape); + String sName = xShapeDescriptor.getShapeType (); + MessageArea.println (" shape " + i + " : " + sName); + + XPropertySet xPropertySet = + (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, xShape); + Integer nZOrder = + (Integer) xPropertySet.getPropertyValue ("ZOrder"); + MessageArea.println (" zorder = " + nZOrder); + } + } + catch (Exception e) + { + MessageArea.println ("caught exception in showShapes: " + e); + } + } + + + + + /** @descr Print all available services of the given object to the + standard output. + */ + public void showServices (XInterface xObject) + { + try + { + MessageArea.println ("Services:"); + XMultiServiceFactory xMSF = (XMultiServiceFactory) UnoRuntime.queryInterface ( + XMultiServiceFactory.class, + xObject + ); + if (xMSF == null) + MessageArea.println (" object does not support interface XMultiServiceFactory"); + else + { + String[] sServiceNames = xMSF.getAvailableServiceNames (); + MessageArea.println (" object can create " + + sServiceNames.length + " services"); + for (int i=0; i<sServiceNames.length; i++) + MessageArea.println (" service " + i + " : " + sServiceNames[i]); + } + } + catch (Exception e) + { + MessageArea.println ("caught exception in showServices : " + e); + } + } + + /** @descr Print the service and implementation name of the given + object. + */ + public void showInfo (XInterface xObject) + { + try + { + System.out.println ("Info:"); + // Use interface XServiceName to retrieve name of (main) service. + XServiceName xSN = (XServiceName) UnoRuntime.queryInterface ( + XServiceName.class, xObject); + if (xSN == null) + MessageArea.println (" interface XServiceName not supported"); + else + { + MessageArea.println (" Service name : " + xSN.getServiceName ()); + } + + // Use interface XServiceInfo to retrieve information about + // supported services. + XServiceInfo xSI = (XServiceInfo) UnoRuntime.queryInterface ( + XServiceInfo.class, xObject); + if (xSI == null) + MessageArea.println (" interface XServiceInfo not supported"); + else + { + MessageArea.println (" Implementation name : " + + xSI.getImplementationName ()); + } + } + catch (Exception e) + { + MessageArea.println ("caught exception in showInfo : " + e); + } + } + + + + + /** @descr Print information about supported interfaces. + */ + public void showInterfaces (XInterface xObject) + { + try + { + MessageArea.println ("Interfaces:"); + // Use interface XTypeProvider to retrieve a list of supported + // interfaces. + XTypeProvider xTP = (XTypeProvider) UnoRuntime.queryInterface ( + XTypeProvider.class, xObject); + if (xTP == null) + MessageArea.println (" interface XTypeProvider not supported"); + else + { + Type[] aTypeList = xTP.getTypes (); + MessageArea.println (" object supports " + aTypeList.length + + " interfaces"); + for (int i=0; i<aTypeList.length; i++) + MessageArea.println (" " + i + " : " + + aTypeList[i].getTypeName()); + } + } + catch (Exception e) + { + MessageArea.println ("caught exception in showInterfaces : " + e); + } + } + + + /** @descr Print information concerning the accessibility of the given + object. + */ + public boolean showAccessibility (XInterface xObject, int depth) + { + try + { + // Create indentation string. + String sIndent = ""; + while (depth-- > 0) + sIndent += " "; + + // Get XAccessibleContext object if given object does not + // already support this interface. + XAccessibleContext xContext + = (XAccessibleContext) UnoRuntime.queryInterface ( + XAccessibleContext.class, xObject); + if (xContext == null) + { + XAccessible xAccessible + = (XAccessible) UnoRuntime.queryInterface ( + XAccessible.class, xObject); + if (xAccessible == null) + { + MessageArea.println (sIndent + "given object " + xObject + + " is not accessible"); + return false; + } + else + xContext = xAccessible.getAccessibleContext(); + } + + // Print information about the accessible context. + if (xContext != null) + { + MessageArea.println (sIndent + "Name : " + + xContext.getAccessibleName()); + MessageArea.println (sIndent + "Description : " + + xContext.getAccessibleDescription()); + MessageArea.println (sIndent + "Role : " + + xContext.getAccessibleRole()); + String sHasParent; + if (xContext.getAccessibleParent() != null) + { + MessageArea.println (sIndent + "Has parent : yes"); + MessageArea.println (sIndent + "Parent index : " + + xContext.getAccessibleIndexInParent()); + } + else + MessageArea.println (sIndent + "Has parent : no"); + MessageArea.println (sIndent + "Child count : " + + xContext.getAccessibleChildCount()); + MessageArea.print (sIndent + "Relation set : "); + XAccessibleRelationSet xRelationSet + = xContext.getAccessibleRelationSet(); + if (xRelationSet != null) + { + MessageArea.print (xRelationSet.getRelationCount() + " ("); + for (int i=0; i<xRelationSet.getRelationCount(); i++) + { + if (i > 0) + MessageArea.print (", "); + MessageArea.print (xRelationSet.getRelation(i).toString()); + } + MessageArea.println (")"); + } + else + MessageArea.println ("no relation set"); + + MessageArea.print (sIndent + "State set : "); + XAccessibleStateSet xStateSet = + xContext.getAccessibleStateSet(); + if (xStateSet != null) + { + XIndexAccess xStates = + (XIndexAccess) UnoRuntime.queryInterface ( + XIndexAccess.class, xStateSet); + MessageArea.print (xStates.getCount() + " ("); + for (int i=0; i<xStates.getCount(); i++) + { + if (i > 0) + MessageArea.print (", "); + MessageArea.print (xStates.getByIndex(i).toString()); + } + MessageArea.println (")"); + } + else + MessageArea.println ("no state set"); + + showAccessibleComponent (xContext, sIndent); + } + else + MessageArea.println ("object has no accessible context."); + + // showInfo (xContext); + // showServices (xContext); + // showInterfaces (xContext); + } + catch (Exception e) + { + System.out.println ("caught exception in showAccessibility :" + e); + } + return true; + } + + + + + /** @descr Print information about the given accessible component. + */ + public void showAccessibleComponent (XInterface xObject, String sIndent) + { + try + { + XAccessibleComponent xComponent = + (XAccessibleComponent) UnoRuntime.queryInterface ( + XAccessibleComponent.class, xObject); + + // Print information about the accessible context. + if (xComponent != null) + { + MessageArea.println (sIndent + "Position : " + + xComponent.getLocation().X+", " + + xComponent.getLocation().Y); + MessageArea.println (sIndent + "Screen position : " + + xComponent.getLocationOnScreen().X+", " + + xComponent.getLocationOnScreen().Y); + MessageArea.println (sIndent + "Size : " + + xComponent.getSize().Width+", " + + xComponent.getSize().Height); + } + } + catch (Exception e) + { + System.out.println ( + "caught exception in showAccessibleComponent : " + e); + } + } + + + /** Show a textual representation of the accessibility subtree rooted in + xRoot. + */ + public boolean showAccessibilityTree (XAccessible xRoot, int depth) + { + try + { + if ( ! showAccessibility (xRoot, depth)) + return false; + + String sIndent = ""; + for (int i=0; i<depth; i++) + sIndent += " "; + + // Iterate over children and show them. + XAccessibleContext xContext = xRoot.getAccessibleContext(); + if (xContext != null) + { + int n = xContext.getAccessibleChildCount(); + for (int i=0; i<n; i++) + { + MessageArea.println (sIndent + "child " + i + " :"); + showAccessibilityTree (xContext.getAccessibleChild(i),depth+1); + } + } + else + MessageArea.println ("Accessible object has no context"); + } + catch (Exception e) + { + System.out.println ( + "caught exception in showAccessibleTree : " + e); + return false; + } + + return true; + } + + public void showProperties (XInterface xObject) + { + XPropertySet xSet = (XPropertySet) UnoRuntime.queryInterface ( + XPropertySet.class, xObject); + if (xSet == null) + MessageArea.println ("object does not support XPropertySet"); + else + { + XPropertySetInfo xInfo = xSet.getPropertySetInfo (); + Property[] aProperties = xInfo.getProperties (); + int n = aProperties.length; + for (int i=0; i<n; i++) + MessageArea.println (i + " : " + aProperties[i].Name +", " + aProperties[i].Type); + } + } +} diff --git a/toolkit/test/accessibility/MessageArea.java b/toolkit/test/accessibility/MessageArea.java new file mode 100644 index 000000000000..c9d95995e066 --- /dev/null +++ b/toolkit/test/accessibility/MessageArea.java @@ -0,0 +1,123 @@ +import java.awt.Font; +import java.awt.Rectangle; +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 instanciated 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. + */ + public static synchronized void print (String aMessage) + { + print (0, aMessage); + } + + + + + /** Show the given string at the end of the message area and scroll to make + it visible. Indent the string as requested. + */ + public 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. + */ + public static void println (int nIndentation, String aMessage) + { + print (nIndentation, aMessage+"\n"); + } + + + + + 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 JTextArea maText; +} diff --git a/toolkit/test/accessibility/MessageInterface.java b/toolkit/test/accessibility/MessageInterface.java new file mode 100755 index 000000000000..ad189bb8214f --- /dev/null +++ b/toolkit/test/accessibility/MessageInterface.java @@ -0,0 +1,5 @@ +interface MessageInterface +{ + void message (String text); +} + diff --git a/toolkit/test/accessibility/NodeFactory.java b/toolkit/test/accessibility/NodeFactory.java new file mode 100644 index 000000000000..403c482e5ea1 --- /dev/null +++ b/toolkit/test/accessibility/NodeFactory.java @@ -0,0 +1,147 @@ +import com.sun.star.accessibility.*; +import java.util.Vector; + +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 () + { + mbVerbose = false; + + maContextHandler = new AccessibleContextHandler(); + maTextHandler = new AccessibleTextHandler(); + maEditableTextHandler = new AccessibleEditableTextHandler(); + maComponentHandler = new AccessibleComponentHandler(); + maExtendedComponentHandler = new AccessibleExtendedComponentHandler(); + maActionHandler = new AccessibleActionHandler(); + maImageHandler = new AccessibleImageHandler(); + maTableHandler = new AccessibleTableHandler(); + maCellHandler = new AccessibleCellHandler(); + maHypertextHandler = new AccessibleHypertextHandler(); + maHyperlinkHandler = new AccessibleHyperlinkHandler(); + maSelectionHandler = new AccessibleSelectionHandler(); + maRelationHandler = new AccessibleRelationHandler(); + maTreeHandler = new AccessibleTreeHandler(); + maUNOHandler = new AccessibleUNOHandler(); + } + + + /** 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 = new String ("not accessible"); + + + // create node, and add default handlers + AccTreeNode aNode = new AccTreeNode (xAccessible, xContext, sDisplay, aParent); + addDefaultHandlers (aNode, xContext); + + if (aNode == null) + System.out.println ("createDefaultNode == null"); + return aNode; + } + + private static NodeFactory maInstance = null; + + private boolean mbVerbose; + + // default handlers + private NodeHandler maContextHandler = new AccessibleContextHandler(); + private NodeHandler maTextHandler = new AccessibleTextHandler(); + private NodeHandler maEditableTextHandler = new AccessibleEditableTextHandler(); + private NodeHandler maComponentHandler = new AccessibleComponentHandler(); + private NodeHandler maExtendedComponentHandler = new AccessibleExtendedComponentHandler(); + private NodeHandler maActionHandler = new AccessibleActionHandler(); + private NodeHandler maImageHandler = new AccessibleImageHandler(); + private NodeHandler maTableHandler = new AccessibleTableHandler(); + private NodeHandler maCellHandler = new AccessibleCellHandler(); + private NodeHandler maHypertextHandler = new AccessibleHypertextHandler(); + private NodeHandler maHyperlinkHandler = new AccessibleHyperlinkHandler(); + private NodeHandler maSelectionHandler = new AccessibleSelectionHandler(); + private NodeHandler maRelationHandler = new AccessibleRelationHandler(); + private NodeHandler maTreeHandler = new AccessibleTreeHandler(); + private NodeHandler maUNOHandler = new AccessibleUNOHandler(); +} diff --git a/toolkit/test/accessibility/NodeHandler.java b/toolkit/test/accessibility/NodeHandler.java new file mode 100644 index 000000000000..b39741b1f398 --- /dev/null +++ b/toolkit/test/accessibility/NodeHandler.java @@ -0,0 +1,140 @@ +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 maChildList; + + + public abstract NodeHandler createHandler ( + com.sun.star.accessibility.XAccessibleContext xContext); + + public NodeHandler () + { + maChildList = new Vector (); + } + + /** Clear the cache of child objects. + */ + public void clear () + { + synchronized (maChildList) + { + maChildList = new Vector (); + } + } + + /** This factory method creates an individual handler for the specified + object that may hold information to accelerate the access to its children. + */ + // public abstract NodeHandler createHandler (Object aObject); + + /** return the number of children this object has */ + public int getChildCount(Object aObject) + { + 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 = (AccessibleTreeNode)maChildList.get(nIndex); + if (aChild == null) + { + aChild = createChild (aParent, nIndex); + if (aChild == null) + aChild = new StringNode ("could not create child", aParent); + maChildList.setElementAt (aChild, nIndex); + } + return aChild; + } + } + + public AccessibleTreeNode getChildNoCreate (AccessibleTreeNode aParent, int nIndex) + { + synchronized (maChildList) + { + return (AccessibleTreeNode)maChildList.get(nIndex); + } + } + + /** Remove the specified child from the list of children. + */ + public boolean removeChild (AccessibleTreeNode aNode, int nIndex) + { + try + { + synchronized (maChildList) + { + System.out.println (" removing child at position " + nIndex + ": " + + maChildList.elementAt (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. + // + + /** May this child be changed? */ + public boolean isChildEditable (AccessibleTreeNode aNode, int nIndex) + { + return false; + } + + /** change this child's value */ + // public void setChild(Object aObject, int nIndex) { } + + + /** get names of suported 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 000000000000..43479278aec4 --- /dev/null +++ b/toolkit/test/accessibility/NodeMap.java @@ -0,0 +1,112 @@ +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 (); + } + + /** Clear the whole map. + */ + public void Clear () + { + maXAccessibleToNode.clear(); + } + + /** @return + whether the new node was different from a previous one + repspectively was the first one set. + */ + public boolean InsertNode (XAccessibleContext xContext, AccessibleTreeNode aNode) + { + AccessibleTreeNode aPreviousNode = (AccessibleTreeNode)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 (AccessibleTreeNode)maXAccessibleToNode.get (xContext); + } + + AccessibleTreeNode GetNode (Object aObject) + { + if (aObject instanceof XAccessibleContext) + return GetNode ((XAccessibleContext)aObject); + else + return null; + } + + XAccessibleContext GetAccessible (AccessibleTreeNode aNode) + { + if ((aNode != null) && (aNode instanceof AccTreeNode)) + return ((AccTreeNode)aNode).getContext(); + else + return null; + } + + boolean IsMember (XAccessibleContext xContext) + { + return maXAccessibleToNode.containsKey(xContext); + } + + boolean ValueIsMember (AccessibleTreeNode aNode) + { + return maXAccessibleToNode.containsValue(aNode); + } + + + + private HashMap maXAccessibleToNode; +} diff --git a/toolkit/test/accessibility/OfficeConnection.java b/toolkit/test/accessibility/OfficeConnection.java new file mode 100755 index 000000000000..4cc5bee1ed78 --- /dev/null +++ b/toolkit/test/accessibility/OfficeConnection.java @@ -0,0 +1,102 @@ +// base classes +import com.sun.star.uno.UnoRuntime; + +// factory for creating components +import com.sun.star.beans.PropertyValue; +import com.sun.star.bridge.XUnoUrlResolver; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XModel; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XInterface; + +// Exceptions +import com.sun.star.uno.RuntimeException; + + +/** @descr This class establishes a connection to a StarOffice application. + */ +public class OfficeConnection +{ + public OfficeConnection (int nPortNumber) + { + mnDefaultPort = nPortNumber; + connect (); + } + + /** @descr Return the service manager that represents the connected + StarOffice application + */ + public XMultiServiceFactory getServiceManager () + { + if ( ! mbInitialized) + connect (); + return maServiceManager; + } + + /** @descr Return a flag that indicates if the constructor has been able to + establish a valid connection. + */ + public boolean connectionIsValid () + { + return getServiceManager() != null; + } + + /** @descr Connect to a already running StarOffice application. + */ + private void connect () + { + connect (msDefaultHost, mnDefaultPort); + } + + private void connect (String hostname) + { + connect (hostname, mnDefaultPort); + } + + /** @descr Connect to a already running StarOffice 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 = (XUnoUrlResolver) UnoRuntime.queryInterface ( + XUnoUrlResolver.class, + aLocalServiceManager.createInstance ("com.sun.star.bridge.UnoUrlResolver") + ); + + maServiceManager = (XMultiServiceFactory) UnoRuntime.queryInterface ( + XMultiServiceFactory.class, + aURLResolver.resolve (sConnectString) + ); + } + + catch (Exception e) + { + MessageArea.println ("Could not connect with " + sConnectString + " : " + e); + MessageArea.println ("Please start OpenOffice/StarOffice with " + + "\"-accept=socket,host=localhost,port=5678;urp;\""); + } + } + + private int mnDefaultPort = 5678; + private 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 that has been successfull. + */ + private boolean mbInitialized = false; +} diff --git a/toolkit/test/accessibility/Options.java b/toolkit/test/accessibility/Options.java new file mode 100644 index 000000000000..9b0f6f01889c --- /dev/null +++ b/toolkit/test/accessibility/Options.java @@ -0,0 +1,88 @@ +import java.io.File; +import java.io.FileReader; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.Properties; + +/** Load from and save options into a file. +*/ +class Options + extends Properties +{ + static public Options Instance () + { + if (saOptions == null) + saOptions = new Options (); + return saOptions; + } + + static public void SetString (String sName, String sValue) + { + Instance().setProperty (sName, sValue); + } + + static public String GetString (String sName) + { + return Instance().getProperty (sName); + } + + static public void SetBoolean (String sName, boolean bValue) + { + Instance().setProperty (sName, Boolean.toString(bValue)); + } + + static public boolean GetBoolean (String sName) + { + return Boolean.getBoolean(Instance().getProperty (sName)); + } + + static public void SetInteger (String sName, int nValue) + { + Instance().setProperty (sName, Integer.toString(nValue)); + } + + static public 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) + { + try + { + load (new FileInputStream (ProvideFile(sBaseName))); + } + catch (java.io.IOException e) + { + // Ignore a non-existing options file. + } + } + + public void Save (String sBaseName) + { + try + { + store (new FileOutputStream (ProvideFile(sBaseName)), null); + } + catch (java.io.IOException e) + { + } + } + + private Options () + { + } + + private File ProvideFile (String sBaseName) + { + return new File ( + System.getProperty ("user.home"), + sBaseName); + } + + static private Options saOptions = null; +} diff --git a/toolkit/test/accessibility/Print.java b/toolkit/test/accessibility/Print.java new file mode 100755 index 000000000000..e4d21dc4e092 --- /dev/null +++ b/toolkit/test/accessibility/Print.java @@ -0,0 +1,5 @@ +interface Print +{ + void print (String text); + void println (String text); +} diff --git a/toolkit/test/accessibility/QueuedListener.java b/toolkit/test/accessibility/QueuedListener.java new file mode 100644 index 000000000000..b92d7ac487e6 --- /dev/null +++ b/toolkit/test/accessibility/QueuedListener.java @@ -0,0 +1,55 @@ +import com.sun.star.accessibility.*; +import com.sun.star.lang.EventObject; +import com.sun.star.uno.*; +import com.sun.star.accessibility.*; + +import java.util.LinkedList; + +class QueuedListener + implements XAccessibleEventListener +{ + public QueuedListener (EventListener aListener) + { + maListener = aListener; + } + + + public void disposing( final EventObject aEvent) + { + XAccessibleContext xContext = (XAccessibleContext)UnoRuntime.queryInterface( + XAccessibleContext.class, aEvent.Source); + if (xContext == null) + { + XAccessible 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 EventListener maListener; +} + + diff --git a/toolkit/test/accessibility/QueuedTopWindowListener.java b/toolkit/test/accessibility/QueuedTopWindowListener.java new file mode 100644 index 000000000000..61b3472d2002 --- /dev/null +++ b/toolkit/test/accessibility/QueuedTopWindowListener.java @@ -0,0 +1,88 @@ +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 actived: " + aEvent); + } + + public void windowDeactivated (final com.sun.star.lang.EventObject aEvent) + throws RuntimeException + { + System.out.println ("QueuedTopWindowListener: Top window deactived: " + 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 TopWindowListener maListener; +} diff --git a/toolkit/test/accessibility/SelectionDialog.java b/toolkit/test/accessibility/SelectionDialog.java new file mode 100644 index 000000000000..a632e9f77a0c --- /dev/null +++ b/toolkit/test/accessibility/SelectionDialog.java @@ -0,0 +1,179 @@ +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; + +import javax.swing.*; +import java.awt.*; +import java.util.Vector; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; + + + + +/** + * 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 */ + protected 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 GetChildrenList () + { + mxSelection = maNode.getSelection(); + + XAccessibleContext xContext = maNode.getContext(); + int nCount = xContext.getAccessibleChildCount(); + Vector aChildVector = new Vector(); + 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; + } + + + void close () + { + hide(); + dispose(); + } + + void select() + { + try + { + mxSelection.selectAccessibleChild (maChildrenSelector.getSelectedIndex()); + } + catch( IndexOutOfBoundsException e ) + { + JOptionPane.showMessageDialog( AccessibilityWorkBench.Instance(), + "Can't select: IndexOutofBounds", + "Error in selectAccessibleChild", + JOptionPane.ERROR_MESSAGE); + } + } + + void deselect() + { + try + { + mxSelection.deselectAccessibleChild( + maChildrenSelector.getSelectedIndex()); + } + catch( IndexOutOfBoundsException e ) + { + JOptionPane.showMessageDialog( AccessibilityWorkBench.Instance(), + "Can't deselect: IndexOutofBounds", + "Error in deselectAccessibleChild", + JOptionPane.ERROR_MESSAGE); + } + } + + void selectAll() + { + mxSelection.selectAllAccessibleChildren(); + } + + 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 AccTreeNode maNode; +} diff --git a/toolkit/test/accessibility/SimpleOffice.java b/toolkit/test/accessibility/SimpleOffice.java new file mode 100755 index 000000000000..4417267675af --- /dev/null +++ b/toolkit/test/accessibility/SimpleOffice.java @@ -0,0 +1,389 @@ +import java.lang.Thread; + +import com.sun.star.awt.Rectangle; +import com.sun.star.awt.XWindow; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; + +import com.sun.star.container.XIndexAccess; +import com.sun.star.container.XChild; +import com.sun.star.container.XEnumerationAccess; +import com.sun.star.container.XEnumeration; + +import com.sun.star.frame.XComponentLoader; +import com.sun.star.frame.XController; +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XFrame; +import com.sun.star.frame.XModel; +import com.sun.star.frame.XTasksSupplier; +import com.sun.star.frame.XTask; + +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.XServiceName; +import com.sun.star.lang.XTypeProvider; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.Type; + +import com.sun.star.drawing.XDrawView; +import com.sun.star.drawing.XDrawPage; +import com.sun.star.drawing.XShapes; +import com.sun.star.drawing.XShape; +import com.sun.star.drawing.XShapeDescriptor; + +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleComponent; +import com.sun.star.accessibility.XAccessibleRelationSet; +import com.sun.star.accessibility.XAccessibleStateSet; + +import com.sun.star.awt.XExtendedToolkit; + + +/** This class tries to simplify some tasks like loading a document or + getting various objects. +*/ +public class SimpleOffice +{ + XDesktop mxDesktop = null; + OfficeConnection aConnection; + int mnPortNumber; + + public SimpleOffice (int nPortNumber) + { + mnPortNumber = nPortNumber; + connect (); + getDesktop (); + } + + public void connect () + { + aConnection = new OfficeConnection (mnPortNumber); + mxDesktop = null; + getDesktop (); + } + + public XModel loadDocument (String URL) + { + XModel xModel = null; + try + { + // Load the document from the specified URL. + XComponentLoader xLoader = + (XComponentLoader)UnoRuntime.queryInterface( + XComponentLoader.class, mxDesktop); + + XComponent xComponent = xLoader.loadComponentFromURL ( + URL, + "_blank", + 0, + new PropertyValue[0] + ); + + xModel = (XModel) UnoRuntime.queryInterface( + XModel.class, xComponent); + } + catch (java.lang.NullPointerException e) + { + MessageArea.println ("caught exception while loading " + + URL + " : " + e); + } + catch (Exception e) + { + MessageArea.println ("caught exception while loading " + + URL + " : " + e); + } + return xModel; + } + + + + + public XModel getModel (String name) + { + XModel xModel = null; + try + { + XTasksSupplier xTasksSupplier = + (XTasksSupplier) UnoRuntime.queryInterface( + XTasksSupplier.class, mxDesktop); + XEnumerationAccess xEA = xTasksSupplier.getTasks(); + XEnumeration xE = xEA.createEnumeration(); + while (xE.hasMoreElements()) + { + XTask xTask = (XTask) UnoRuntime.queryInterface( + XTask.class, xE.nextElement()); + MessageArea.print (xTask.getName()); + } + } + catch (Exception e) + { + MessageArea.println ("caught exception while getting Model " + name + + ": " + e); + } + return xModel; + } + + + public XModel getModel (XDrawView xView) + { + XController xController = (XController) UnoRuntime.queryInterface( + XController.class, xView); + if (xController != null) + return xController.getModel(); + else + { + MessageArea.println ("can't cast view to controller"); + return null; + } + } + + 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 = (XDesktop) 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 = (XExtendedToolkit) 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 = (XAccessible) UnoRuntime.queryInterface( + XAccessible.class, xObject); + } + catch (Exception e) + { + MessageArea.println ( + "caught exception while getting accessible object" + e); + e.printStackTrace(); + } + return xAccessible; + } + + /** Return the root object of the accessibility hierarchy. + */ + public XAccessible getAccessibleRoot (XAccessible xAccessible) + { + try + { + XAccessible xParent = null; + do + { + XAccessibleContext xContext = xAccessible.getAccessibleContext(); + if (xContext != null) + xParent = xContext.getAccessibleParent(); + if (xParent != null) + xAccessible = xParent; + } + while (xParent != null); + } + catch (Exception e) + { + MessageArea.println ( + "caught exception while getting accessible root" + e); + e.printStackTrace(); + } + return xAccessible; + } + + + + + /** @descr Return the current window associated with the given + model. + */ + public XWindow getCurrentWindow () + { + return getCurrentWindow ((XModel) UnoRuntime.queryInterface( + XModel.class, getDesktop())); + } + + + + + + public XWindow getCurrentWindow (XModel xModel) + { + XWindow xWindow = null; + try + { + if (xModel == null) + MessageArea.println ("invalid model (==null)"); + XController xController = xModel.getCurrentController(); + if (xController == null) + MessageArea.println ("can't get controller from model"); + XFrame xFrame = xController.getFrame(); + if (xFrame == null) + MessageArea.println ("can't get frame from controller"); + xWindow = xFrame.getComponentWindow (); + if (xWindow == null) + MessageArea.println ("can't get window from frame"); + } + catch (Exception e) + { + MessageArea.println ("caught exception while getting current window" + e); + } + + return xWindow; + } + + + /** @descr Return the current draw page of the given desktop. + */ + public XDrawPage getCurrentDrawPage () + { + return getCurrentDrawPage ((XDrawView) UnoRuntime.queryInterface( + XDrawView.class, getCurrentView())); + } + + + + + public XDrawPage getCurrentDrawPage (XDrawView xView) + { + XDrawPage xPage = null; + try + { + if (xView == null) + MessageArea.println ("can't get current draw page from null view"); + else + xPage = xView.getCurrentPage(); + } + catch (Exception e) + { + MessageArea.println ("caught exception while getting current draw page : " + e); + } + + return xPage; + } + + + + + /** @descr Return the current view of the given desktop. + */ + public XDrawView getCurrentView () + { + return getCurrentView (getDesktop()); + } + + public XDrawView getCurrentView (XDesktop xDesktop) + { + if (xDesktop == null) + MessageArea.println ("can't get desktop to retrieve current view"); + + XDrawView xView = null; + try + { + XComponent xComponent = xDesktop.getCurrentComponent(); + if (xComponent == null) + MessageArea.println ("can't get component to retrieve current view"); + + XFrame xFrame = xDesktop.getCurrentFrame(); + if (xFrame == null) + MessageArea.println ("can't get frame to retrieve current view"); + + XController xController = xFrame.getController(); + if (xController == null) + MessageArea.println ("can't get controller to retrieve current view"); + + xView = (XDrawView) UnoRuntime.queryInterface( + XDrawView.class, xController); + if (xView == null) + MessageArea.println ("could not cast controller into view"); + } + catch (Exception e) + { + MessageArea.println ("caught exception while getting current view : " + e); + } + + return xView; + } + + + + + // Return the accessible object of the document window. + public static XAccessible getAccessibleDocumentWindow (XDrawPage xPage) + { + XIndexAccess xShapeList = (XIndexAccess) UnoRuntime.queryInterface( + XIndexAccess.class, xPage); + if (xShapeList.getCount() > 0) + { + // All shapes return as accessible object the document window's + // accessible object. This is, of course, a hack and will be + // removed as soon as the missing infrastructure for obtaining + // the object directly is implemented. + XShape xShape = null; + try{ + xShape = (XShape) UnoRuntime.queryInterface( + XShape.class, xShapeList.getByIndex (0)); + } catch (Exception e) + {} + XAccessible xAccessible = (XAccessible) UnoRuntime.queryInterface ( + XAccessible.class, xShape); + return xAccessible; + } + else + return null; + } +} diff --git a/toolkit/test/accessibility/StringNode.java b/toolkit/test/accessibility/StringNode.java new file mode 100644 index 000000000000..11a7286c60f1 --- /dev/null +++ b/toolkit/test/accessibility/StringNode.java @@ -0,0 +1,13 @@ +import com.sun.star.lang.IndexOutOfBoundsException; + +/** + Base class for all tree nodes. + */ +class StringNode + extends AccessibleTreeNode +{ + public StringNode (String aDisplayObject, AccessibleTreeNode aParent) + { + super (aDisplayObject, aParent); + } +} diff --git a/toolkit/test/accessibility/TableEventHandler.java b/toolkit/test/accessibility/TableEventHandler.java new file mode 100644 index 000000000000..7655d3a13599 --- /dev/null +++ b/toolkit/test/accessibility/TableEventHandler.java @@ -0,0 +1,43 @@ +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.AccessibleEventObject; +import com.sun.star.accessibility.AccessibleEventId; +import com.sun.star.accessibility.AccessibleTableModelChange; +import com.sun.star.uno.UnoRuntime; + +import java.io.PrintStream; + +class TableEventHandler + extends EventHandler +{ + public TableEventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel) + { + super (aEvent, aTreeModel); + } + + 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); + } + } + + public void Process () + { + maTreeModel.updateNode (mxEventSource, AccessibleTableHandler.class); + } + + + private XAccessible mxOldChild; + private XAccessible mxNewChild; +} diff --git a/toolkit/test/accessibility/TextLogger.java b/toolkit/test/accessibility/TextLogger.java new file mode 100644 index 000000000000..e0ee56fd691d --- /dev/null +++ b/toolkit/test/accessibility/TextLogger.java @@ -0,0 +1,52 @@ +import javax.swing.JEditorPane; +import javax.swing.event.HyperlinkListener; +import javax.swing.event.HyperlinkEvent; +import javax.swing.text.Document; +import java.net.URL; + +class TextLogger + extends JEditorPane +{ + public TextLogger () + throws java.io.IOException + { +// maDocument = getEditorKit().createDefaultDocument(); + super ("http://localhost"); + try + { + // setPage (new URL ("http://www.spiegel.de")); + } + catch (Exception e) + {} + + setEditable (false); + final JEditorPane finalPane = this; + addHyperlinkListener (new HyperlinkListener() + { + public void hyperlinkUpdate (HyperlinkEvent e) + { + try + { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) + finalPane.setPage (e.getURL()); + } + catch (java.io.IOException ex) + { + ex.printStackTrace(System.err); + } + } + }); + } + + public void appendText (String sText) + { + try + { + maDocument.insertString (maDocument.getLength(), sText, null); + } + catch (javax.swing.text.BadLocationException e) + {} + } + + private Document maDocument; +} diff --git a/toolkit/test/accessibility/TextUpdateListener.java b/toolkit/test/accessibility/TextUpdateListener.java new file mode 100644 index 000000000000..0ce990144c67 --- /dev/null +++ b/toolkit/test/accessibility/TextUpdateListener.java @@ -0,0 +1,170 @@ +import com.sun.star.accessibility.*; +import com.sun.star.uno.UnoRuntime; + +import javax.swing.tree.*; +import javax.swing.event.*; + + + +/** listen to tree model changes in order to update XAccessibleText objects +*/ +class TextUpdateListener implements TreeModelListener +{ + public void treeNodesChanged(TreeModelEvent e) + { + try { + // if the change is to the first child of a DefaultMutableTreeNode + // with an XAccessibleText child, then we call updateText + int[] aIndices = e.getChildIndices(); + if( (aIndices != null) && + (aIndices.length > 0) ) + { + // we have a parent... lets check for XAccessibleText then + DefaultMutableTreeNode aParent = (DefaultMutableTreeNode) + (e.getTreePath().getLastPathComponent()); + DefaultMutableTreeNode aNode = (DefaultMutableTreeNode) + (aParent.getChildAt(aIndices[0])); + if( aParent.getUserObject() instanceof XAccessibleText) + { + // aha! we have an xText. So we can now check for + // the various cases we support + XAccessibleText xText = + (XAccessibleText)aParent.getUserObject(); + + if( aIndices[0] == 0 ) + { + // first child! Then we call updateText + updateText( xText, aNode.toString() ); + } + else + { + // JDK 1.4: + // // check for pattern "Selection:" + // Matcher m = Pattern.compile( + // "selection: \\[(-?[0-9]+),(-?[0-9]+)\\] \".*" ). + // matcher( aNode.toString() ); + // if( m.matches() ) + // { + // try + // { + // // aha! Selection: + // setSelection( xText, + // Integer.parseInt(m.group(1)), + // Integer.parseInt(m.group(2)) ); + // } + // catch( NumberFormatException f ) + // { + // // ignore + // } + // } + } + } + } + } + catch (com.sun.star.lang.IndexOutOfBoundsException aException) + {} + } + + // don't care: + public void treeNodesInserted(TreeModelEvent e) { ; } + public void treeNodesRemoved(TreeModelEvent e) { ; } + public void treeStructureChanged(TreeModelEvent e) { ; } + + /** update the text */ + boolean updateText( XAccessibleText xText, String sNew ) + throws com.sun.star.lang.IndexOutOfBoundsException + { + // is this text editable? if not, fudge you and return + XAccessibleEditableText xEdit = + (XAccessibleEditableText) UnoRuntime.queryInterface ( + XAccessibleEditableText.class, xText); + if (xEdit == null) + return false; + + String sOld = xText.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; + } + + boolean setSelection( XAccessibleText xText, int p1, int p2 ) + { + try + { + return xText.setSelection( p1, p2 ); + } + catch( com.sun.star.lang.IndexOutOfBoundsException f ) + { + return false; + } + } + + // /** replace the given node with a new xText node */ + // void updateNode( XAccessibleText xText, + // DefaultMutableTreeNode aNode ) + // { + // // create a new node + // DefaultMutableTreeNode aNew = newTextTreeNode( xText ); + // + // // get parent (must be DefaultMutableTreeNode) + // DefaultMutableTreeNode aParent = + // (DefaultMutableTreeNode)aNode.getParent(); + // if( aParent != null ) + // { + // // remove old sub-tree, and insert new one + // int nIndex = aParent.getIndex( aNode ); + // aParent.remove( nIndex ); + // aParent.insert( aNew, nIndex ); + // } + // } +} diff --git a/toolkit/test/accessibility/TopWindowListener.java b/toolkit/test/accessibility/TopWindowListener.java new file mode 100644 index 000000000000..c0aea933ece7 --- /dev/null +++ b/toolkit/test/accessibility/TopWindowListener.java @@ -0,0 +1,205 @@ +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.XInterface; +import com.sun.star.uno.UnoRuntime; +import javax.swing.event.TreeModelEvent; + +/** 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 + { + if ( ! FilterTopLevelNode (xContext)) + { + 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)); + } + } + } + } + } + + /** Ignore windows that have no accessible name, i.e. do not represent + document windows. + @return + Returns <true/> when the given object should not be displayed, + i.e. filtered out. + */ + private boolean FilterTopLevelNode (XAccessibleContext xContext) + { + // No filtering at the moment. + return false; + // return xContext.getAccessibleName().length() == 0; + } + + + + + /** 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); + VectorNode aRoot = (VectorNode) aObject; + maModel.removeNode (xTopLevelObject.getAccessibleContext()); + } + } + + + + + + /** This method exists for debugging. It prints a list of all top + level windows. + */ + private void ShowAllTopLevelWindows () + { + XExtendedToolkit xToolkit = maOffice.getExtendedToolkit(); + if (xToolkit != null) + { + int nTopWindowCount = xToolkit.getTopWindowCount(); + for (int i=0; i<nTopWindowCount; i++) + { + try + { + System.out.println (i + " : " + xToolkit.getTopWindow (i)); + } + catch (Exception e) + { + System.out.println ("caught exception; " + e); + } + } + } + } + + + + + // XTopWindowListener + public void windowOpened (final com.sun.star.lang.EventObject aEvent) + throws RuntimeException + { + if (maModel != null) + { + XWindow 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 = (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 AccessibilityTreeModel + maModel; + private SimpleOffice + maOffice; +} diff --git a/toolkit/test/accessibility/VectorNode.java b/toolkit/test/accessibility/VectorNode.java new file mode 100644 index 000000000000..282abb595620 --- /dev/null +++ b/toolkit/test/accessibility/VectorNode.java @@ -0,0 +1,50 @@ +import com.sun.star.lang.IndexOutOfBoundsException; +import java.util.Vector; + +/** The VectorNode class is a simple container whose list of children is + managed entirely by its owner. +*/ +class VectorNode + extends StringNode +{ + private Vector maChildren; + + public VectorNode (String sDisplayObject, AccessibleTreeNode aParent) + { + super (sDisplayObject, aParent); + + maChildren = new Vector (); + } + + public void addChild (AccessibleTreeNode aChild) + { + maChildren.add (aChild); + } + + public int getChildCount () + { + return maChildren.size(); + } + + public AccessibleTreeNode getChild (int nIndex) + throws IndexOutOfBoundsException + { + return (AccessibleTreeNode)maChildren.elementAt (nIndex); + } + + public boolean removeChild (int nIndex) + throws IndexOutOfBoundsException + { + return maChildren.remove (nIndex) != null; + } + + public int indexOf (AccessibleTreeNode aNode) + { + return maChildren.indexOf (aNode); + } + + 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 000000000000..ff24ed058663 --- /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 000000000000..2660013b6733 --- /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 + Descriptons 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>
\ No newline at end of file diff --git a/toolkit/test/accessibility/jawb.mf b/toolkit/test/accessibility/jawb.mf new file mode 100644 index 000000000000..939cbdad22ab --- /dev/null +++ b/toolkit/test/accessibility/jawb.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: AccessibilityWorkBench +Class-Path: classes.jar ridl.jar unoil.jar jurt.jar juh.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 000000000000..9e801723f06a --- /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>Adaption 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 000000000000..4204c5de7bac --- /dev/null +++ b/toolkit/test/accessibility/ov/ContextView.java @@ -0,0 +1,125 @@ +package ov; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridBagLayout; +import java.awt.GridBagConstraints; + +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; + +import javax.swing.JLabel; +import javax.swing.JTextField; + +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 +{ + static public ObjectView Create ( + ObjectViewContainer aContainer, + XAccessibleContext xContext) + { + System.out.println ("ContextView.CreateView"); + if (xContext != null) + return new ContextView (aContainer); + else + return null; + } + + public ContextView (ObjectViewContainer aContainer) + { + super (aContainer); + maNameLabel = new JLabel ("Name: "); + maName = new JLabel (""); + maDescriptionLabel = new JLabel ("Description: "); + maDescription = new 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 (maNameLabel, constraints); + constraints.gridy = 1; + add (maDescriptionLabel, 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); + } + + 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())); + } + } + + public String GetTitle () + { + return ("Context"); + } + + /** Listen for changes regarding displayed values. + */ + public void notifyEvent (AccessibleEventObject aEvent) + { + switch (aEvent.EventId) + { + case AccessibleEventId.NAME_CHANGED : + case AccessibleEventId.DESCRIPTION_CHANGED : + Update (); + } + } + + public void actionPerformed (ActionEvent aEvent) + { + } + + + private JLabel + maNameLabel, + maName, + maDescriptionLabel, + maDescription, + maRoleLabel, + maRole; +} diff --git a/toolkit/test/accessibility/ov/FocusView.java b/toolkit/test/accessibility/ov/FocusView.java new file mode 100644 index 000000000000..665fa260e288 --- /dev/null +++ b/toolkit/test/accessibility/ov/FocusView.java @@ -0,0 +1,119 @@ +package ov; + +import java.awt.Color; +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. + */ + static public ObjectView Create ( + ObjectViewContainer aContainer, + XAccessibleContext xContext) + { + XAccessibleComponent xComponent = (XAccessibleComponent)UnoRuntime.queryInterface( + XAccessibleComponent.class, xContext); + if (xComponent != null) + return new FocusView (aContainer); + else + return null; + } + + public 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. + */ + public void SetObject (XAccessibleContext xObject) + { + mxComponent = (XAccessibleComponent)UnoRuntime.queryInterface( + XAccessibleComponent.class, xObject); + super.SetObject (xObject); + } + + synchronized public void Destroy () + { + super.Destroy(); + maGrabFocus.removeActionListener (this); + } + + 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); + } + } + + public String GetTitle () + { + return ("Focus"); + } + + synchronized public void actionPerformed (ActionEvent aEvent) + { + if (aEvent.getActionCommand().equals("grabFocus")) + { + mxComponent.grabFocus(); + } + } + + public void notifyEvent (AccessibleEventObject aEvent) + { + System.out.println (aEvent); + if (aEvent.EventId == AccessibleEventId.STATE_CHANGED) + Update (); + } + + private JLabel maFocused; + private 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 000000000000..574fa989b20f --- /dev/null +++ b/toolkit/test/accessibility/ov/ListeningObjectView.java @@ -0,0 +1,60 @@ +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 regsiters 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. + */ + public void SetObject (XAccessibleContext xContext) + { + super.SetObject (xContext); + XAccessibleEventBroadcaster xBroadcaster = + (XAccessibleEventBroadcaster)UnoRuntime.queryInterface( + XAccessibleEventBroadcaster.class, xContext); + if (xBroadcaster != null) + xBroadcaster.addEventListener (this); + } + + + /** Remove this object as event listener from the broadcasting + accessible object. + */ + public void Destroy () + { + super.Destroy (); + XAccessibleEventBroadcaster xBroadcaster = + (XAccessibleEventBroadcaster)UnoRuntime.queryInterface( + XAccessibleEventBroadcaster.class, mxContext); + if (xBroadcaster != null) + xBroadcaster.removeEventListener (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 000000000000..0c96969e733b --- /dev/null +++ b/toolkit/test/accessibility/ov/ObjectView.java @@ -0,0 +1,77 @@ +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 +{ + /** This factory method creates a new instance of the (derived) class + when the given accessible object supports all necessary features. + In the ususal case this will be the support of a specific + accessibility interface. + */ + static public ObjectView Create ( + ObjectViewContainer aContainer, + XAccessibleContext xContext) + { + return null; + } + + public ObjectView (ObjectViewContainer aContainer) + { + maContainer = 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 xObject + 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; + + protected ObjectViewContainer maContainer; +} diff --git a/toolkit/test/accessibility/ov/ObjectViewContainer.java b/toolkit/test/accessibility/ov/ObjectViewContainer.java new file mode 100644 index 000000000000..c0bf6a86736b --- /dev/null +++ b/toolkit/test/accessibility/ov/ObjectViewContainer.java @@ -0,0 +1,166 @@ +package ov; + +import java.awt.Color; +import java.awt.Component; +import java.awt.GridBagLayout; +import java.awt.GridBagConstraints; +import java.awt.Insets; + +import java.util.Vector; + +import java.lang.reflect.Method; +import java.lang.NoSuchMethodException; +import java.lang.IllegalAccessException; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.JPanel; +import javax.swing.JTree; +import javax.swing.BorderFactory; +import javax.swing.border.Border; +import javax.swing.border.BevelBorder; + +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleComponent; +import com.sun.star.accessibility.XAccessibleSelection; +import com.sun.star.uno.UnoRuntime; + + +public class ObjectViewContainer + extends JPanel +{ + public ObjectViewContainer () + { + maViewTemplates = new Vector (); + maViewBorder = BorderFactory.createBevelBorder (BevelBorder.RAISED); + setLayout (new GridBagLayout ()); + + System.out.println ("ObjectViewContainer"); + RegisterView (ContextView.class); + // RegisterView (StateSetView.class); + RegisterView (FocusView.class); + RegisterView (TextView.class); + } + + + + /** 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++) + { + try + { + Class aViewClass = (Class)maViewTemplates.elementAt (i); + Method aCreateMethod = aViewClass.getDeclaredMethod ( + "Create", new Class[] { + ObjectViewContainer.class, + XAccessibleContext.class}); + if (aCreateMethod != null) + { + ObjectView aView = (ObjectView) + aCreateMethod.invoke (null, new Object[] {this, xContext}); + Add (aView); + } + } + catch (NoSuchMethodException e) + {System.err.println ("Caught exception while creating view " + i + " : " + e);} + catch (IllegalAccessException e) + {System.err.println ("Caught exception while creating view " + i + " : " + e);} + catch (InvocationTargetException e) + {System.err.println ("Caught exception while creating view " + i + " : " + e);} + } + + 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 the given class to the list of classes which will be + instantiated the next time an accessible object is set. + */ + public void RegisterView (Class aObjectViewClass) + { + System.out.println ("registering " + aObjectViewClass); + maViewTemplates.addElement (aObjectViewClass); + } + + /** Replace one view class with another. + */ + public void ReplaceView (Class aObjectViewClass, Class aSubstitution) + { + int nIndex = maViewTemplates.indexOf (aObjectViewClass); + if (nIndex >= 0) + maViewTemplates.setElementAt (aSubstitution, nIndex); + } + + /** 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 strech 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); + } + } + + /// Observe this tree for selection changes and notify them to all + /// children. + private JTree maTree; + private Border maViewBorder; + /// List of view templates which are instantiated when new object is set. + private Vector maViewTemplates; +} diff --git a/toolkit/test/accessibility/ov/SelectionView.java b/toolkit/test/accessibility/ov/SelectionView.java new file mode 100644 index 000000000000..a71f242420ba --- /dev/null +++ b/toolkit/test/accessibility/ov/SelectionView.java @@ -0,0 +1,230 @@ +package ov; + +import java.util.Vector; + +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridBagLayout; +import java.awt.GridBagConstraints; + +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JOptionPane; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JToggleButton; +import javax.swing.ListSelectionModel; + + +import com.sun.star.accessibility.AccessibleEventId; +import com.sun.star.accessibility.AccessibleEventObject; +import com.sun.star.accessibility.AccessibleStateType; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleSelection; +import com.sun.star.accessibility.XAccessibleStateSet; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.lang.IndexOutOfBoundsException; + + +/** Display a list of children and select/deselect buttons +*/ +class SelectionView + extends ListeningObjectView + implements ActionListener +{ + static public ObjectView Create ( + ObjectViewContainer aContainer, + XAccessibleContext xContext) + { + XAccessibleSelection xSelection = (XAccessibleSelection)UnoRuntime.queryInterface( + XAccessibleSelection.class, xContext); + if (xSelection != null) + return new SelectionView(aContainer); + else + return null; + } + + public SelectionView (ObjectViewContainer aContainer) + { + super (aContainer); + Layout(); + } + + public String GetTitle () + { + return "Selection"; + } + + /** Create and arrange the widgets for this view. + */ + private void Layout () + { + setLayout (new GridBagLayout()); + + GridBagConstraints aConstraints = new GridBagConstraints(); + + // Label that shows wheter the selection is multi selectable. + aConstraints.gridx = 0; + aConstraints.gridy = 0; + aConstraints.anchor = GridBagConstraints.WEST; + maTypeLabel = new JLabel (); + add (maTypeLabel, aConstraints); + + // the JListBox + maChildrenSelector = new JPanel (); + maChildrenSelector.setPreferredSize (new Dimension (100,100)); + maChildrenSelector.setLayout (new BoxLayout (maChildrenSelector, BoxLayout.Y_AXIS)); + + aConstraints.gridx = 0; + aConstraints.gridwidth = 4; + aConstraints.gridy = 1; + aConstraints.fill = GridBagConstraints.HORIZONTAL; + add (new JScrollPane (maChildrenSelector, + JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), + aConstraints); + + JButton aButton; + aButton = new JButton( "Select all" ); + aButton.setActionCommand( "Select all" ); + aButton.addActionListener( this ); + aConstraints.gridx = 0; + aConstraints.gridwidth = 1; + aConstraints.gridy = 2; + aConstraints.fill = GridBagConstraints.NONE; + aConstraints.anchor = GridBagConstraints.WEST; + add (aButton, aConstraints); + + aButton = new JButton( "Clear Selection" ); + aButton.setActionCommand( "Clear Selection" ); + aButton.addActionListener( this ); + aConstraints.gridx = 1; + aConstraints.gridy = 2; + aConstraints.weightx = 1; + add (aButton, aConstraints); + + setSize (getPreferredSize()); + } + + + public void SetObject (XAccessibleContext xContext) + { + mxSelection = (XAccessibleSelection)UnoRuntime.queryInterface( + XAccessibleSelection.class, xContext); + super.SetObject (xContext); + } + + + public void Update () + { + maChildrenSelector.removeAll (); + + // Determine whether multi selection is possible. + XAccessibleStateSet aStateSet = mxContext.getAccessibleStateSet(); + boolean bMultiSelectable = false; + ButtonGroup aButtonGroup = null; + if (aStateSet!=null && aStateSet.contains(AccessibleStateType.MULTI_SELECTABLE)) + { + bMultiSelectable = true; + maTypeLabel.setText ("multi selectable"); + } + else + { + maTypeLabel.setText ("single selectable"); + aButtonGroup = new ButtonGroup (); + } + + int nCount = mxContext.getAccessibleChildCount(); + for (int i=0; i<nCount; i++) + { + try + { + XAccessible xChild = mxContext.getAccessibleChild(i); + XAccessibleContext xChildContext = xChild.getAccessibleContext(); + + String sName = i + " " + xChildContext.getAccessibleName(); + JToggleButton aChild; + if (bMultiSelectable) + aChild = new JCheckBox (sName); + else + { + aChild = new JRadioButton (sName); + aButtonGroup.add (aChild); + } + + XAccessibleStateSet aChildStateSet = mxContext.getAccessibleStateSet(); + aChild.setSelected (aChildStateSet!=null + && aChildStateSet.contains(AccessibleStateType.SELECTED)); + + aChild.addActionListener (this); + maChildrenSelector.add (aChild); + + } + catch (IndexOutOfBoundsException e) + { + } + } + } + + + void SelectAll() + { + mxSelection.selectAllAccessibleChildren(); + } + + void ClearSelection() + { + mxSelection.clearAccessibleSelection(); + } + + + /** Call the function associated with the pressed button. + */ + public void actionPerformed (ActionEvent aEvent) + { + String sCommand = aEvent.getActionCommand(); + + if (sCommand.equals ("Clear Selection")) + ClearSelection(); + else if (sCommand.equals ("Select all")) + SelectAll(); + else + { + // Extract the child index from the widget text. + String[] aWords = sCommand.split (" "); + int nIndex = Integer.parseInt(aWords[0]); + try + { + if (((JToggleButton)aEvent.getSource()).isSelected()) + mxSelection.selectAccessibleChild (nIndex); + else + mxSelection.deselectAccessibleChild (nIndex); + } + catch (IndexOutOfBoundsException e) + { + System.err.println ("caught exception while changing selection: " + e); + } + } + } + + + public void notifyEvent (AccessibleEventObject aEvent) + { + if (aEvent.EventId == AccessibleEventId.SELECTION_CHANGED) + Update (); + } + + private JPanel maChildrenSelector; + private XAccessibleSelection mxSelection; + private JLabel maTypeLabel; +} diff --git a/toolkit/test/accessibility/ov/StateSetView.java b/toolkit/test/accessibility/ov/StateSetView.java new file mode 100644 index 000000000000..e8997ac0c5a0 --- /dev/null +++ b/toolkit/test/accessibility/ov/StateSetView.java @@ -0,0 +1,249 @@ +package ov; + +import java.awt.Color; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Shape; + +import java.awt.event.MouseListener; +import java.awt.event.MouseEvent; + +import java.awt.geom.Rectangle2D; +import java.awt.geom.AffineTransform; + + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.border.Border; + +import com.sun.star.accessibility.AccessibleEventObject; +import com.sun.star.accessibility.AccessibleEventId; +import com.sun.star.accessibility.AccessibleStateType; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleStateSet; + +import tools.NameProvider; + +public class StateSetView + extends ListeningObjectView + implements MouseListener +{ + /** Create a FocusView when the given object supports the + XAccessibleComponent interface. + */ + static public ObjectView Create ( + ObjectViewContainer aContainer, + XAccessibleContext xContext) + { + ObjectView aView = null; + if (xContext != null) + if (mnViewMode == SHOW_ALL_STATES) + aView = StateSetAllView.Create (aContainer, xContext); + else + aView = StateSetSetView.Create (aContainer, xContext); + return aView; + } + + public StateSetView (ObjectViewContainer aContainer) + { + super (aContainer); + + addMouseListener (this); + } + + private void SetViewMode (int nViewMode) + { + mnViewMode = nViewMode; + switch (mnViewMode) + { + case SHOW_SET_STATES : + maContainer.ReplaceView ( + getClass(), + StateSetSetView.class); + break; + case SHOW_ALL_STATES : + maContainer.ReplaceView ( + getClass(), + StateSetAllView.class); + break; + } + aContainer.SetObject (mxContext); + } + + + + public String GetTitle () + { + return ("StateSet"); + } + + public void notifyEvent (AccessibleEventObject aEvent) + { + if (aEvent.EventId == AccessibleEventId.STATE_CHANGED) + Update(); + } + + public void mouseClicked(MouseEvent e) + { + switch (mnViewMode) + { + case SHOW_SET_STATES : + SetViewMode (SHOW_ALL_STATES); + break; + case SHOW_ALL_STATES : + SetViewMode (SHOW_SET_STATES); + break; + } + } + public void mouseEntered (MouseEvent e) {} + public void mouseExited (MouseEvent e) {} + public void mousePressed (MouseEvent e) {} + public void mouseReleased(MouseEvent e) {} + + private static int mnViewMode = SHOW_ALL_STATES; + private final static int SHOW_SET_STATES = 0; + private final static int SHOW_ALL_STATES = 1; + + + +public class StateSetAllView + extends StateSetView +{ + /** Create a FocusView when the given object supports the + XAccessibleComponent interface. + */ + static public ObjectView Create ( + ObjectViewContainer aContainer, + XAccessibleContext xContext) + { + if (xContext != null) + return new StateSetAllView (aContainer); + else + return null; + } + + public StateSetAllView (ObjectViewContainer aContainer) + { + super (aContainer); + + setPreferredSize (new Dimension(300,90)); + setMinimumSize (new Dimension(200,80)); + } + + public void paintChildren (Graphics g) + { + synchronized (g) + { + super.paintChildren (g); + + // Calculcate the are inside the border. + Insets aInsets = getInsets (); + Dimension aSize = getSize(); + Rectangle aWidgetArea = new Rectangle ( + aInsets.left, + aInsets.top, + aSize.width-aInsets.left-aInsets.right, + aSize.height-aInsets.top-aInsets.bottom); + + PaintAllStates ((Graphics2D)g, aWidgetArea); + } + } + + private void PaintAllStates (Graphics2D g, Rectangle aWidgetArea) + { + Color aTextColor = g.getColor(); + + g.setRenderingHint ( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + XAccessibleStateSet xStateSet = mxContext.getAccessibleStateSet(); + if (xStateSet != null) + { + short aStates[] = xStateSet.getStates (); + final int nMaxStateIndex = AccessibleStateType.MANAGES_DESCENDANTS; + int nStateWidth = (aWidgetArea.width-12) / (nMaxStateIndex+1); + AffineTransform aTransform = g.getTransform (); + g.setColor (aTextColor); + int y = aWidgetArea.y+aWidgetArea.height - 12; + double nTextRotation = -0.9;//-java.lang.Math.PI/2; + double nScale = 0.6; + + // Create a shape for the boxes. + int nBoxWidth = nStateWidth-2; + if (nBoxWidth > 8) + nBoxWidth = 8; + Rectangle aCheckBox = new Rectangle (-nBoxWidth/2,0,nBoxWidth,nBoxWidth); + + for (short i=0; i<=nMaxStateIndex; i++) + { + int x = nStateWidth + i * nStateWidth; + String sStateName = NameProvider.getStateName (i); + boolean bStateSet = xStateSet.contains (i); + g.setTransform (aTransform); + g.translate (x,y); + if (bStateSet) + { + g.setColor (Color.GREEN); + g.fill (aCheckBox); + g.setColor (aTextColor); + } + g.draw (aCheckBox); + g.rotate (nTextRotation); + g.scale (nScale, nScale); + g.translate (2,-2); + g.drawString (sStateName, 0,0); + } + } + } +} + + +public class StateSetSetView + extends StateSetView +{ + static public ObjectView Create ( + ObjectViewContainer aContainer, + XAccessibleContext xContext) + { + if (xContext != null) + return new StateSetSetView (aContainer); + else + return null; + } + + public StateSetSetView (ObjectViewContainer aContainer) + { + super (aContainer); + + maStates = null; + setPreferredSize (new Dimension(300,90)); + } + + + synchronized public void Update () + { + XAccessibleStateSet xStateSet = mxContext.getAccessibleStateSet(); + if (xStateSet != null) + { + String sStates = new String (); + short aStates[] = xStateSet.getStates(); + for (int i=0; i<aStates.length; i++) + { + if (i > 0) + sStates = sStates + ", "; + sStates = sStates + NameProvider.getStateName(aStates[i]); + } + maStates.setText (sStates); + } + } + + private JLabel maStates; +} + +} diff --git a/toolkit/test/accessibility/ov/TextView.java b/toolkit/test/accessibility/ov/TextView.java new file mode 100644 index 000000000000..094647986e4f --- /dev/null +++ b/toolkit/test/accessibility/ov/TextView.java @@ -0,0 +1,123 @@ +package ov; + +import java.awt.Color; +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.XAccessibleText; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleStateSet; +import com.sun.star.uno.UnoRuntime; + +public class TextView + extends ListeningObjectView +{ + /** Create a TextView when the given object supports the + XAccessibleText interface. + */ + static public ObjectView Create ( + ObjectViewContainer aContainer, + XAccessibleContext xContext) + { + XAccessibleText xText = (XAccessibleText)UnoRuntime.queryInterface( + XAccessibleText.class, xContext); + if (xText != null) + return new TextView (aContainer); + else + return null; + } + + + public 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. + */ + public void SetObject (XAccessibleContext xObject) + { + mxText = (XAccessibleText)UnoRuntime.queryInterface( + XAccessibleText.class, xObject); + super.SetObject (xObject); + } + + synchronized public void Destroy () + { + super.Destroy(); + } + + 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())); + } + } + + public String GetTitle () + { + return ("Text"); + } + + public void notifyEvent (AccessibleEventObject aEvent) + { + System.out.println (aEvent); + switch (aEvent.EventId) + { + case AccessibleEventId.TEXT_CHANGED : + case AccessibleEventId.CARET_CHANGED : + Update (); + break; + } + } + + private 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 000000000000..d9bcab802cbf --- /dev/null +++ b/toolkit/test/accessibility/tools/NameProvider.java @@ -0,0 +1,259 @@ +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 (String)maStateMap.get (new Integer(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 (String)maEventMap.get (new Integer(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 (String)maRoleMap.get (new Integer(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 (String)maRelationMap.get (new Integer(nRelation)); + } + + + private static HashMap maStateMap = new HashMap(); + private static HashMap maEventMap = new HashMap(); + private static HashMap maRoleMap = new HashMap(); + private static HashMap maRelationMap = new HashMap(); + + static { + maStateMap.put (new Integer (AccessibleStateType.INVALID), "INVALID"); + maStateMap.put (new Integer (AccessibleStateType.ACTIVE), "ACTIVE"); + maStateMap.put (new Integer (AccessibleStateType.ARMED), "ARMED"); + maStateMap.put (new Integer (AccessibleStateType.BUSY), "BUSY"); + maStateMap.put (new Integer (AccessibleStateType.CHECKED), "CHECKED"); + // maStateMap.put (new Integer (AccessibleStateType.COLLAPSED), "COLLAPSED"); + maStateMap.put (new Integer (AccessibleStateType.DEFUNC), "DEFUNC"); + maStateMap.put (new Integer (AccessibleStateType.EDITABLE), "EDITABLE"); + maStateMap.put (new Integer (AccessibleStateType.ENABLED), "ENABLED"); + maStateMap.put (new Integer (AccessibleStateType.EXPANDABLE), "EXPANDABLE"); + maStateMap.put (new Integer (AccessibleStateType.EXPANDED), "EXPANDED"); + maStateMap.put (new Integer (AccessibleStateType.FOCUSABLE), "FOCUSABLE"); + maStateMap.put (new Integer (AccessibleStateType.FOCUSED), "FOCUSED"); + maStateMap.put (new Integer (AccessibleStateType.HORIZONTAL), "HORIZONTAL"); + maStateMap.put (new Integer (AccessibleStateType.ICONIFIED), "ICONIFIED"); + maStateMap.put (new Integer (AccessibleStateType.MODAL), "MODAL"); + maStateMap.put (new Integer (AccessibleStateType.MULTI_LINE), "MULTI_LINE"); + maStateMap.put (new Integer (AccessibleStateType.MULTI_SELECTABLE), "MULTI_SELECTABLE"); + maStateMap.put (new Integer (AccessibleStateType.OPAQUE), "OPAQUE"); + maStateMap.put (new Integer (AccessibleStateType.PRESSED), "PRESSED"); + maStateMap.put (new Integer (AccessibleStateType.RESIZABLE), "RESIZABLE"); + maStateMap.put (new Integer (AccessibleStateType.SELECTABLE), "SELECTABLE"); + maStateMap.put (new Integer (AccessibleStateType.SELECTED), "SELECTED"); + maStateMap.put (new Integer (AccessibleStateType.SENSITIVE), "SENSITIVE"); + maStateMap.put (new Integer (AccessibleStateType.SHOWING), "SHOWING"); + maStateMap.put (new Integer (AccessibleStateType.SINGLE_LINE), "SINGLE_LINE"); + maStateMap.put (new Integer (AccessibleStateType.STALE), "STALE"); + maStateMap.put (new Integer (AccessibleStateType.TRANSIENT), "TRANSIENT"); + maStateMap.put (new Integer (AccessibleStateType.VERTICAL), "VERTICAL"); + maStateMap.put (new Integer (AccessibleStateType.VISIBLE), "VISIBLE"); + maStateMap.put (new Integer (AccessibleStateType.MANAGES_DESCENDANTS), + "MANAGES_DESCENDANTS"); + // maStateMap.put (new Integer (AccessibleStateType.INCONSISTENT),"INCONSISTENT"); + + + maEventMap.put (new Integer (0), + "[UNKNOWN]"); + maEventMap.put (new Integer (AccessibleEventId.NAME_CHANGED), + "NAME_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.DESCRIPTION_CHANGED), + "DESCRIPTION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.ACTION_CHANGED), + "ACTION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.STATE_CHANGED), + "STATE_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.ACTIVE_DESCENDANT_CHANGED), + "ACTIVE_DESCENDANT_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.BOUNDRECT_CHANGED), + "BOUNDRECT_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.CHILD), + "CHILD"); + maEventMap.put (new Integer (AccessibleEventId.INVALIDATE_ALL_CHILDREN), + "INVALIDATE_ALL_CHILDREN"); + maEventMap.put (new Integer (AccessibleEventId.SELECTION_CHANGED), + "SELECTION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.VISIBLE_DATA_CHANGED), + "VISIBLE_DATA_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.VALUE_CHANGED), + "VALUE_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.CONTENT_FLOWS_FROM_RELATION_CHANGED), + "CONTENT_FLOWS_FROM_RELATION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.CONTENT_FLOWS_TO_RELATION_CHANGED), + "CONTENT_FLOWS_TO_RELATION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.CONTROLLED_BY_RELATION_CHANGED), + "CONTROLLED_BY_RELATION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.CONTROLLER_FOR_RELATION_CHANGED), + "CONTROLLER_FOR_RELATION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.LABEL_FOR_RELATION_CHANGED), + "LABEL_FOR_RELATION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.LABELED_BY_RELATION_CHANGED), + "LABELED_BY_RELATION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.MEMBER_OF_RELATION_CHANGED), + "MEMBER_OF_RELATION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.SUB_WINDOW_OF_RELATION_CHANGED), + "SUB_WINDOW_OF_RELATION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.CARET_CHANGED), + "CARET_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.TEXT_SELECTION_CHANGED), + "TEXT_SELECTION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.TEXT_CHANGED), + "TEXT_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.TEXT_ATTRIBUTE_CHANGED), + "TEXT_ATTRIBUTE_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.HYPERTEXT_CHANGED), + "HYPERTEXT_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.TABLE_CAPTION_CHANGED), + "TABLE_CAPTION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.TABLE_COLUMN_DESCRIPTION_CHANGED), + "TABLE_COLUMN_DESCRIPTION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.TABLE_COLUMN_HEADER_CHANGED), + "TABLE_COLUMN_HEADER_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.TABLE_MODEL_CHANGED), + "TABLE_MODEL_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.TABLE_ROW_DESCRIPTION_CHANGED), + "TABLE_ROW_DESCRIPTION_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.TABLE_ROW_HEADER_CHANGED), + "TABLE_ROW_HEADER_CHANGED"); + maEventMap.put (new Integer (AccessibleEventId.TABLE_SUMMARY_CHANGED), + "TABLE_SUMMARY_CHANGED"); + + maRoleMap.put (new Integer(AccessibleRole.UNKNOWN), "UNKNOWN"); + maRoleMap.put (new Integer (AccessibleRole.UNKNOWN), "UNKNOWN"); + maRoleMap.put (new Integer (AccessibleRole.ALERT), "ALERT"); + maRoleMap.put (new Integer (AccessibleRole.COLUMN_HEADER), "COLUMN_HEADER"); + maRoleMap.put (new Integer (AccessibleRole.CANVAS), "CANVAS"); + maRoleMap.put (new Integer (AccessibleRole.CHECK_BOX), "CHECK_BOX"); + maRoleMap.put (new Integer (AccessibleRole.CHECK_MENU_ITEM), "CHECK_MENU_ITEM"); + maRoleMap.put (new Integer (AccessibleRole.COLOR_CHOOSER), "COLOR_CHOOSER"); + maRoleMap.put (new Integer (AccessibleRole.COMBO_BOX), "COMBO_BOX"); + maRoleMap.put (new Integer (AccessibleRole.DESKTOP_ICON), "DESKTOP_ICON"); + maRoleMap.put (new Integer (AccessibleRole.DESKTOP_PANE), "DESKTOP_PANE"); + maRoleMap.put (new Integer (AccessibleRole.DIRECTORY_PANE), "DIRECTORY_PANE"); + maRoleMap.put (new Integer (AccessibleRole.DIALOG), "DIALOG"); + maRoleMap.put (new Integer (AccessibleRole.DOCUMENT), "DOCUMENT"); + maRoleMap.put (new Integer (AccessibleRole.EMBEDDED_OBJECT), "EMBEDDED_OBJECT"); + maRoleMap.put (new Integer (AccessibleRole.END_NOTE), "END_NOTE"); + maRoleMap.put (new Integer (AccessibleRole.FILE_CHOOSER), "FILE_CHOOSER"); + maRoleMap.put (new Integer (AccessibleRole.FILLER), "FILLER"); + maRoleMap.put (new Integer (AccessibleRole.FONT_CHOOSER), "FONT_CHOOSER"); + maRoleMap.put (new Integer (AccessibleRole.FOOTER), "FOOTER"); + maRoleMap.put (new Integer (AccessibleRole.FOOTNOTE), "FOOTNOTE"); + maRoleMap.put (new Integer (AccessibleRole.FRAME), "FRAME"); + maRoleMap.put (new Integer (AccessibleRole.GLASS_PANE), "GLASS_PANE"); + maRoleMap.put (new Integer (AccessibleRole.GRAPHIC), "GRAPHIC"); + maRoleMap.put (new Integer (AccessibleRole.GROUP_BOX), "GROUP_BOX"); + maRoleMap.put (new Integer (AccessibleRole.HEADER), "HEADER"); + maRoleMap.put (new Integer (AccessibleRole.HEADING), "HEADING"); + maRoleMap.put (new Integer (AccessibleRole.HYPER_LINK), "HYPER_LINK"); + maRoleMap.put (new Integer (AccessibleRole.ICON), "ICON"); + maRoleMap.put (new Integer (AccessibleRole.INTERNAL_FRAME), "INTERNAL_FRAME"); + maRoleMap.put (new Integer (AccessibleRole.LABEL), "LABEL"); + maRoleMap.put (new Integer (AccessibleRole.LAYERED_PANE), "LAYERED_PANE"); + maRoleMap.put (new Integer (AccessibleRole.LIST), "LIST"); + maRoleMap.put (new Integer (AccessibleRole.LIST_ITEM), "LIST_ITEM"); + maRoleMap.put (new Integer (AccessibleRole.MENU), "MENU"); + maRoleMap.put (new Integer (AccessibleRole.MENU_BAR), "MENU_BAR"); + maRoleMap.put (new Integer (AccessibleRole.MENU_ITEM), "MENU_ITEM"); + maRoleMap.put (new Integer (AccessibleRole.OPTION_PANE), "OPTION_PANE"); + maRoleMap.put (new Integer (AccessibleRole.PAGE_TAB), "PAGE_TAB"); + maRoleMap.put (new Integer (AccessibleRole.PAGE_TAB_LIST), "PAGE_TAB_LIST"); + maRoleMap.put (new Integer (AccessibleRole.PANEL), "PANEL"); + maRoleMap.put (new Integer (AccessibleRole.PARAGRAPH), "PARAGRAPH"); + maRoleMap.put (new Integer (AccessibleRole.PASSWORD_TEXT), "PASSWORD_TEXT"); + maRoleMap.put (new Integer (AccessibleRole.POPUP_MENU), "POPUP_MENU"); + maRoleMap.put (new Integer (AccessibleRole.PUSH_BUTTON), "PUSH_BUTTON"); + maRoleMap.put (new Integer (AccessibleRole.PROGRESS_BAR), "PROGRESS_BAR"); + maRoleMap.put (new Integer (AccessibleRole.RADIO_BUTTON), "RADIO_BUTTON"); + maRoleMap.put (new Integer (AccessibleRole.RADIO_MENU_ITEM), "RADIO_MENU_ITEM"); + maRoleMap.put (new Integer (AccessibleRole.ROW_HEADER), "ROW_HEADER"); + maRoleMap.put (new Integer (AccessibleRole.ROOT_PANE), "ROOT_PANE"); + maRoleMap.put (new Integer (AccessibleRole.SCROLL_BAR), "SCROLL_BAR"); + maRoleMap.put (new Integer (AccessibleRole.SCROLL_PANE), "SCROLL_PANE"); + maRoleMap.put (new Integer (AccessibleRole.SHAPE), "SHAPE"); + maRoleMap.put (new Integer (AccessibleRole.SEPARATOR), "SEPARATOR"); + maRoleMap.put (new Integer (AccessibleRole.SLIDER), "SLIDER"); + maRoleMap.put (new Integer (AccessibleRole.SPIN_BOX), "SPIN_BOX"); + maRoleMap.put (new Integer (AccessibleRole.SPLIT_PANE), "SPLIT_PANE"); + maRoleMap.put (new Integer (AccessibleRole.STATUS_BAR), "STATUS_BAR"); + maRoleMap.put (new Integer (AccessibleRole.TABLE), "TABLE"); + maRoleMap.put (new Integer (AccessibleRole.TABLE_CELL), "TABLE_CELL"); + maRoleMap.put (new Integer (AccessibleRole.TEXT), "TEXT"); + maRoleMap.put (new Integer (AccessibleRole.TEXT_FRAME), "TEXT_FRAME"); + maRoleMap.put (new Integer (AccessibleRole.TOGGLE_BUTTON), "TOGGLE_BUTTON"); + maRoleMap.put (new Integer (AccessibleRole.TOOL_BAR), "TOOL_BAR"); + maRoleMap.put (new Integer (AccessibleRole.TOOL_TIP), "TOOL_TIP"); + maRoleMap.put (new Integer (AccessibleRole.TREE), "TREE"); + maRoleMap.put (new Integer (AccessibleRole.VIEW_PORT), "VIEW_PORT"); + maRoleMap.put (new Integer (AccessibleRole.WINDOW), "WINDOW"); + + maRelationMap.put (new Integer (AccessibleRelationType.INVALID), "INVALID"); + maRelationMap.put (new Integer (AccessibleRelationType.CONTENT_FLOWS_FROM), "CONTENT_FLOWS_FROM"); + maRelationMap.put (new Integer (AccessibleRelationType.CONTENT_FLOWS_TO), "CONTENT_FLOWS_TO"); + maRelationMap.put (new Integer (AccessibleRelationType.CONTROLLED_BY), "CONTROLLED_BY"); + maRelationMap.put (new Integer (AccessibleRelationType.CONTROLLER_FOR), "CONTROLLER_FOR"); + maRelationMap.put (new Integer (AccessibleRelationType.LABEL_FOR), "LABEL_FOR"); + maRelationMap.put (new Integer (AccessibleRelationType.LABELED_BY), "LABELED_BY"); + maRelationMap.put (new Integer (AccessibleRelationType.MEMBER_OF), "MEMBER_OF"); + maRelationMap.put (new Integer (AccessibleRelationType.SUB_WINDOW_OF), "SUB_WINDOW_OF"); + } +} |