1*1b0aaa91SAndrew Rist /************************************************************** 2*1b0aaa91SAndrew Rist * 3*1b0aaa91SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*1b0aaa91SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*1b0aaa91SAndrew Rist * distributed with this work for additional information 6*1b0aaa91SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*1b0aaa91SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*1b0aaa91SAndrew Rist * "License"); you may not use this file except in compliance 9*1b0aaa91SAndrew Rist * with the License. You may obtain a copy of the License at 10*1b0aaa91SAndrew Rist * 11*1b0aaa91SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*1b0aaa91SAndrew Rist * 13*1b0aaa91SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*1b0aaa91SAndrew Rist * software distributed under the License is distributed on an 15*1b0aaa91SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*1b0aaa91SAndrew Rist * KIND, either express or implied. See the License for the 17*1b0aaa91SAndrew Rist * specific language governing permissions and limitations 18*1b0aaa91SAndrew Rist * under the License. 19*1b0aaa91SAndrew Rist * 20*1b0aaa91SAndrew Rist *************************************************************/ 21*1b0aaa91SAndrew Rist 22cdf0e10cSrcweir import com.sun.star.accessibility.*; 23cdf0e10cSrcweir import com.sun.star.lang.XServiceInfo; 24cdf0e10cSrcweir import com.sun.star.lang.IndexOutOfBoundsException; 25cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime; 26cdf0e10cSrcweir 27cdf0e10cSrcweir import java.util.Vector; 28cdf0e10cSrcweir import java.awt.*; 29cdf0e10cSrcweir import java.awt.event.*; 30cdf0e10cSrcweir import javax.swing.*; 31cdf0e10cSrcweir import javax.swing.tree.*; 32cdf0e10cSrcweir import javax.swing.event.*; 33cdf0e10cSrcweir 34cdf0e10cSrcweir 35cdf0e10cSrcweir 36cdf0e10cSrcweir /** This is the tree component that is responsible for displaying the 37cdf0e10cSrcweir contents of the tree model on the screen. 38cdf0e10cSrcweir */ 39cdf0e10cSrcweir public class AccessibilityTree 40cdf0e10cSrcweir implements TreeExpansionListener, TreeWillExpandListener 41cdf0e10cSrcweir { 42cdf0e10cSrcweir /** Create a new accessibility tree. Use the specified message display 43cdf0e10cSrcweir for displaying messages and the specified canvas to draw the 44cdf0e10cSrcweir graphical representations of accessible objects on. 45cdf0e10cSrcweir */ 46cdf0e10cSrcweir public AccessibilityTree () 47cdf0e10cSrcweir { 48cdf0e10cSrcweir maTree = new JTree (); 49cdf0e10cSrcweir 50cdf0e10cSrcweir AccessibilityTreeModel aModel = 51cdf0e10cSrcweir new AccessibilityTreeModel ( 52cdf0e10cSrcweir new StringNode ("Please press Update button", null)); 53cdf0e10cSrcweir maTree.setModel (aModel); 54cdf0e10cSrcweir 55cdf0e10cSrcweir maCellRenderer = new AccessibleTreeCellRenderer(); 56cdf0e10cSrcweir // setCellRenderer (maCellRenderer); 57cdf0e10cSrcweir 58cdf0e10cSrcweir // allow editing of XAccessibleText interfaces 59cdf0e10cSrcweir // setEditable (true); 60cdf0e10cSrcweir // maTreeModel.addTreeModelListener( new TextUpdateListener() ); 61cdf0e10cSrcweir 62cdf0e10cSrcweir maTree.addMouseListener (new MouseListener (this)); 63cdf0e10cSrcweir 64cdf0e10cSrcweir // Listen to expansions and collapses to change the mouse cursor. 65cdf0e10cSrcweir mnExpandLevel = 0; 66cdf0e10cSrcweir maTree.addTreeWillExpandListener (this); 67cdf0e10cSrcweir maTree.addTreeExpansionListener (this); 68cdf0e10cSrcweir } 69cdf0e10cSrcweir 70cdf0e10cSrcweir public JTree getComponent () 71cdf0e10cSrcweir { 72cdf0e10cSrcweir return maTree; 73cdf0e10cSrcweir } 74cdf0e10cSrcweir 75cdf0e10cSrcweir // Change cursor during expansions to show the user that this is a 76cdf0e10cSrcweir // lengthy operation. 77cdf0e10cSrcweir public void treeWillExpand (TreeExpansionEvent e) 78cdf0e10cSrcweir { 79cdf0e10cSrcweir if (mnExpandLevel == 0) 80cdf0e10cSrcweir { 81cdf0e10cSrcweir maTree.setCursor (new Cursor (Cursor.WAIT_CURSOR)); 82cdf0e10cSrcweir } 83cdf0e10cSrcweir mnExpandLevel += 1; 84cdf0e10cSrcweir } 85cdf0e10cSrcweir public void treeWillCollapse (TreeExpansionEvent e) 86cdf0e10cSrcweir { 87cdf0e10cSrcweir if (mnExpandLevel == 0) 88cdf0e10cSrcweir { 89cdf0e10cSrcweir maTree.setCursor (new Cursor (Cursor.WAIT_CURSOR)); 90cdf0e10cSrcweir } 91cdf0e10cSrcweir mnExpandLevel += 1; 92cdf0e10cSrcweir } 93cdf0e10cSrcweir public void treeExpanded (TreeExpansionEvent e) 94cdf0e10cSrcweir { 95cdf0e10cSrcweir mnExpandLevel -= 1; 96cdf0e10cSrcweir if (mnExpandLevel == 0) 97cdf0e10cSrcweir { 98cdf0e10cSrcweir maTree.setCursor (new Cursor (Cursor.DEFAULT_CURSOR)); 99cdf0e10cSrcweir } 100cdf0e10cSrcweir } 101cdf0e10cSrcweir public void treeCollapsed (TreeExpansionEvent e) 102cdf0e10cSrcweir { 103cdf0e10cSrcweir mnExpandLevel -= 1; 104cdf0e10cSrcweir if (mnExpandLevel == 0) 105cdf0e10cSrcweir { 106cdf0e10cSrcweir maTree.setCursor (new Cursor (Cursor.DEFAULT_CURSOR)); 107cdf0e10cSrcweir } 108cdf0e10cSrcweir } 109cdf0e10cSrcweir 110cdf0e10cSrcweir 111cdf0e10cSrcweir 112cdf0e10cSrcweir public void SetCanvas (Canvas aCanvas) 113cdf0e10cSrcweir { 114cdf0e10cSrcweir maCanvas = aCanvas; 115cdf0e10cSrcweir ((AccessibilityTreeModel)maTree.getModel()).setCanvas (maCanvas); 116cdf0e10cSrcweir } 117cdf0e10cSrcweir 118cdf0e10cSrcweir /** Expand the nodes in the subtree rooted in aNode according to the the 119cdf0e10cSrcweir specified expander. The tree is locked during the expansion. 120cdf0e10cSrcweir */ 121cdf0e10cSrcweir protected void expandTree (AccessibleTreeNode aNode, Expander aExpander) 122cdf0e10cSrcweir { 123cdf0e10cSrcweir if (mnExpandLevel == 0) 124cdf0e10cSrcweir { 125cdf0e10cSrcweir maTree.setEnabled (false); 126cdf0e10cSrcweir } 127cdf0e10cSrcweir mnExpandLevel += 1; 128cdf0e10cSrcweir 129cdf0e10cSrcweir ((AccessibilityTreeModel)maTree.getModel()).lock (); 130cdf0e10cSrcweir 131cdf0e10cSrcweir try 132cdf0e10cSrcweir { 133cdf0e10cSrcweir expandTree (new TreePath (aNode.createPath()), aExpander); 134cdf0e10cSrcweir } 135cdf0e10cSrcweir catch (Exception e) 136cdf0e10cSrcweir { 137cdf0e10cSrcweir // Ignore 138cdf0e10cSrcweir } 139cdf0e10cSrcweir 140cdf0e10cSrcweir mnExpandLevel -= 1; 141cdf0e10cSrcweir if (mnExpandLevel == 0) 142cdf0e10cSrcweir { 143cdf0e10cSrcweir maTree.setEnabled (true); 144cdf0e10cSrcweir ((AccessibilityTreeModel)maTree.getModel()).unlock (aNode); 145cdf0e10cSrcweir } 146cdf0e10cSrcweir } 147cdf0e10cSrcweir 148cdf0e10cSrcweir private TreePath expandTree( TreePath aPath, Expander aExpander ) 149cdf0e10cSrcweir { 150cdf0e10cSrcweir // return first expanded object 151cdf0e10cSrcweir TreePath aFirst = null; 152cdf0e10cSrcweir 153cdf0e10cSrcweir // System.out.print ("e"); 154cdf0e10cSrcweir 155cdf0e10cSrcweir try 156cdf0e10cSrcweir { 157cdf0e10cSrcweir // get 'our' object 158cdf0e10cSrcweir Object aObj = aPath.getLastPathComponent(); 159cdf0e10cSrcweir 160cdf0e10cSrcweir // expand this object, if the Expander tells us so 161cdf0e10cSrcweir if( aExpander.expand( aObj ) ) 162cdf0e10cSrcweir { 163cdf0e10cSrcweir maTree.expandPath (aPath); 164cdf0e10cSrcweir if( aFirst == null ) 165cdf0e10cSrcweir aFirst = aPath; 166cdf0e10cSrcweir } 167cdf0e10cSrcweir 168cdf0e10cSrcweir // visit all children 169cdf0e10cSrcweir if (aObj instanceof AccessibleTreeNode) 170cdf0e10cSrcweir { 171cdf0e10cSrcweir AccessibleTreeNode aNode = (AccessibleTreeNode)aObj; 172cdf0e10cSrcweir int nLength = aNode.getChildCount(); 173cdf0e10cSrcweir for( int i = 0; i < nLength; i++ ) 174cdf0e10cSrcweir { 175cdf0e10cSrcweir TreePath aRet = expandTree( 176cdf0e10cSrcweir aPath.pathByAddingChild( aNode.getChild( i ) ), 177cdf0e10cSrcweir aExpander ); 178cdf0e10cSrcweir if( aFirst == null ) 179cdf0e10cSrcweir aFirst = aRet; 180cdf0e10cSrcweir } 181cdf0e10cSrcweir } 182cdf0e10cSrcweir } 183cdf0e10cSrcweir catch (Exception e) 184cdf0e10cSrcweir { 185cdf0e10cSrcweir System.out.println ("caught exception while expanding tree path " 186cdf0e10cSrcweir + aPath + ": " + e); 187cdf0e10cSrcweir e.printStackTrace (); 188cdf0e10cSrcweir } 189cdf0e10cSrcweir 190cdf0e10cSrcweir return aFirst; 191cdf0e10cSrcweir } 192cdf0e10cSrcweir 193cdf0e10cSrcweir 194cdf0e10cSrcweir /** Expand all nodes and their subtrees that represent shapes. Call 195cdf0e10cSrcweir * this method from the outside. */ 196cdf0e10cSrcweir public void expandShapes () 197cdf0e10cSrcweir { 198cdf0e10cSrcweir expandShapes ((AccessibleTreeNode)maTree.getModel().getRoot()); 199cdf0e10cSrcweir } 200cdf0e10cSrcweir public void expandShapes (AccessibleTreeNode aNode) 201cdf0e10cSrcweir { 202cdf0e10cSrcweir expandTree (aNode, new ShapeExpander()); 203cdf0e10cSrcweir } 204cdf0e10cSrcweir 205cdf0e10cSrcweir /** Expand all nodes */ 206cdf0e10cSrcweir public void expandAll () 207cdf0e10cSrcweir { 208cdf0e10cSrcweir expandAll ((AccessibleTreeNode)maTree.getModel().getRoot()); 209cdf0e10cSrcweir } 210cdf0e10cSrcweir public void expandAll (AccessibleTreeNode aNode) 211cdf0e10cSrcweir { 212cdf0e10cSrcweir expandTree (aNode, new AllExpander()); 213cdf0e10cSrcweir } 214cdf0e10cSrcweir 215cdf0e10cSrcweir 216cdf0e10cSrcweir 217cdf0e10cSrcweir public void disposing (com.sun.star.lang.EventObject e) 218cdf0e10cSrcweir { 219cdf0e10cSrcweir System.out.println ("disposing " + e); 220cdf0e10cSrcweir } 221cdf0e10cSrcweir 222cdf0e10cSrcweir /* 223cdf0e10cSrcweir public Dimension getPreferredSize () 224cdf0e10cSrcweir { 225cdf0e10cSrcweir Dimension aPreferredSize = super.getPreferredSize(); 226cdf0e10cSrcweir Dimension aMinimumSize = super.getMinimumSize(); 227cdf0e10cSrcweir if (aPreferredSize.width < aMinimumSize.width) 228cdf0e10cSrcweir aPreferredSize.width = aMinimumSize.width; 229cdf0e10cSrcweir return aPreferredSize; 230cdf0e10cSrcweir } 231cdf0e10cSrcweir */ 232cdf0e10cSrcweir 233cdf0e10cSrcweir class MouseListener extends MouseAdapter 234cdf0e10cSrcweir { 235cdf0e10cSrcweir public MouseListener (AccessibilityTree aTree) 236cdf0e10cSrcweir { 237cdf0e10cSrcweir maTree=aTree; 238cdf0e10cSrcweir } 239cdf0e10cSrcweir public void mousePressed(MouseEvent e) { popupTrigger(e); } 240cdf0e10cSrcweir public void mouseClicked(MouseEvent e) { popupTrigger(e); } 241cdf0e10cSrcweir public void mouseEntered(MouseEvent e) { popupTrigger(e); } 242cdf0e10cSrcweir public void mouseExited(MouseEvent e) { popupTrigger(e); } 243cdf0e10cSrcweir public void mouseReleased(MouseEvent e) { popupTrigger(e); } 244cdf0e10cSrcweir 245cdf0e10cSrcweir public boolean popupTrigger( MouseEvent e ) 246cdf0e10cSrcweir { 247cdf0e10cSrcweir boolean bIsPopup = e.isPopupTrigger(); 248cdf0e10cSrcweir if( bIsPopup ) 249cdf0e10cSrcweir { 250cdf0e10cSrcweir int selRow = maTree.getComponent().getRowForLocation(e.getX(), e.getY()); 251cdf0e10cSrcweir if (selRow != -1) 252cdf0e10cSrcweir { 253cdf0e10cSrcweir TreePath aPath = maTree.getComponent().getPathForLocation(e.getX(), e.getY()); 254cdf0e10cSrcweir 255cdf0e10cSrcweir // check for actions 256cdf0e10cSrcweir Object aObject = aPath.getLastPathComponent(); 257cdf0e10cSrcweir JPopupMenu aMenu = new JPopupMenu(); 258cdf0e10cSrcweir if( aObject instanceof AccTreeNode ) 259cdf0e10cSrcweir { 260cdf0e10cSrcweir AccTreeNode aNode = (AccTreeNode)aObject; 261cdf0e10cSrcweir 262cdf0e10cSrcweir Vector aActions = new Vector(); 263cdf0e10cSrcweir aMenu.add (new AccessibilityTree.ShapeExpandAction(maTree, aNode)); 264cdf0e10cSrcweir aMenu.add (new AccessibilityTree.SubtreeExpandAction(maTree, aNode)); 265cdf0e10cSrcweir 266cdf0e10cSrcweir aNode.getActions(aActions); 267cdf0e10cSrcweir for( int i = 0; i < aActions.size(); i++ ) 268cdf0e10cSrcweir { 269cdf0e10cSrcweir aMenu.add( new NodeAction( 270cdf0e10cSrcweir aActions.elementAt(i).toString(), 271cdf0e10cSrcweir aNode, i ) ); 272cdf0e10cSrcweir } 273cdf0e10cSrcweir } 274cdf0e10cSrcweir else if (aObject instanceof AccessibleTreeNode) 275cdf0e10cSrcweir { 276cdf0e10cSrcweir AccessibleTreeNode aNode = (AccessibleTreeNode)aObject; 277cdf0e10cSrcweir String[] aActionNames = aNode.getActions(); 278cdf0e10cSrcweir int nCount=aActionNames.length; 279cdf0e10cSrcweir if (nCount > 0) 280cdf0e10cSrcweir { 281cdf0e10cSrcweir for (int i=0; i<nCount; i++) 282cdf0e10cSrcweir aMenu.add( new NodeAction( 283cdf0e10cSrcweir aActionNames[i], 284cdf0e10cSrcweir aNode, 285cdf0e10cSrcweir i)); 286cdf0e10cSrcweir } 287cdf0e10cSrcweir else 288cdf0e10cSrcweir aMenu = null; 289cdf0e10cSrcweir } 290cdf0e10cSrcweir if (aMenu != null) 291cdf0e10cSrcweir aMenu.show (maTree.getComponent(), 292cdf0e10cSrcweir e.getX(), e.getY()); 293cdf0e10cSrcweir } 294cdf0e10cSrcweir } 295cdf0e10cSrcweir 296cdf0e10cSrcweir return bIsPopup; 297cdf0e10cSrcweir } 298cdf0e10cSrcweir 299cdf0e10cSrcweir private AccessibilityTree maTree; 300cdf0e10cSrcweir } 301cdf0e10cSrcweir 302cdf0e10cSrcweir class NodeAction extends AbstractAction 303cdf0e10cSrcweir { 304cdf0e10cSrcweir private int mnIndex; 305cdf0e10cSrcweir private AccessibleTreeNode maNode; 306cdf0e10cSrcweir 307cdf0e10cSrcweir public NodeAction( String aName, AccessibleTreeNode aNode, int nIndex ) 308cdf0e10cSrcweir { 309cdf0e10cSrcweir super( aName ); 310cdf0e10cSrcweir maNode = aNode; 311cdf0e10cSrcweir mnIndex = nIndex; 312cdf0e10cSrcweir } 313cdf0e10cSrcweir 314cdf0e10cSrcweir public void actionPerformed(ActionEvent e) 315cdf0e10cSrcweir { 316cdf0e10cSrcweir maNode.performAction(mnIndex); 317cdf0e10cSrcweir } 318cdf0e10cSrcweir } 319cdf0e10cSrcweir 320cdf0e10cSrcweir // This action expands all shapes in the subtree rooted in the specified node. 321cdf0e10cSrcweir class ShapeExpandAction extends AbstractAction 322cdf0e10cSrcweir { 323cdf0e10cSrcweir private AccessibilityTree maTree; 324cdf0e10cSrcweir private AccTreeNode maNode; 325cdf0e10cSrcweir public ShapeExpandAction (AccessibilityTree aTree, AccTreeNode aNode) 326cdf0e10cSrcweir { 327cdf0e10cSrcweir super ("Expand Shapes"); 328cdf0e10cSrcweir maTree = aTree; 329cdf0e10cSrcweir maNode = aNode; 330cdf0e10cSrcweir } 331cdf0e10cSrcweir public void actionPerformed (ActionEvent e) 332cdf0e10cSrcweir { 333cdf0e10cSrcweir maTree.expandShapes (maNode); 334cdf0e10cSrcweir } 335cdf0e10cSrcweir } 336cdf0e10cSrcweir 337cdf0e10cSrcweir // This action expands all nodes in the subtree rooted in the specified node. 338cdf0e10cSrcweir class SubtreeExpandAction extends AbstractAction 339cdf0e10cSrcweir { 340cdf0e10cSrcweir private AccessibilityTree maTree; 341cdf0e10cSrcweir private AccTreeNode maNode; 342cdf0e10cSrcweir public SubtreeExpandAction (AccessibilityTree aTree, AccTreeNode aNode) 343cdf0e10cSrcweir { 344cdf0e10cSrcweir super ("Expand Subtree"); 345cdf0e10cSrcweir maTree = aTree; 346cdf0e10cSrcweir maNode = aNode; 347cdf0e10cSrcweir } 348cdf0e10cSrcweir public void actionPerformed (ActionEvent e) 349cdf0e10cSrcweir { 350cdf0e10cSrcweir maTree.expandAll (maNode); 351cdf0e10cSrcweir } 352cdf0e10cSrcweir } 353cdf0e10cSrcweir 354cdf0e10cSrcweir /** Predicate class to determine whether a node should be expanded 355cdf0e10cSrcweir * For use with expandTree method */ 356cdf0e10cSrcweir abstract class Expander 357cdf0e10cSrcweir { 358cdf0e10cSrcweir abstract public boolean expand (Object aObject); 359cdf0e10cSrcweir } 360cdf0e10cSrcweir 361cdf0e10cSrcweir /** expand all nodes */ 362cdf0e10cSrcweir class AllExpander extends Expander 363cdf0e10cSrcweir { 364cdf0e10cSrcweir public boolean expand(Object aObject) { return true; } 365cdf0e10cSrcweir } 366cdf0e10cSrcweir 367cdf0e10cSrcweir /** expand all nodes with accessibility roles > 100 */ 368cdf0e10cSrcweir class ShapeExpander extends Expander 369cdf0e10cSrcweir { 370cdf0e10cSrcweir public boolean expand (Object aObject) 371cdf0e10cSrcweir { 372cdf0e10cSrcweir if (aObject instanceof AccTreeNode) 373cdf0e10cSrcweir { 374cdf0e10cSrcweir AccTreeNode aNode = (AccTreeNode)aObject; 375cdf0e10cSrcweir XAccessibleContext xContext = aNode.getContext(); 376cdf0e10cSrcweir if (xContext != null) 377cdf0e10cSrcweir if (xContext.getAccessibleRole() >= 100) 378cdf0e10cSrcweir return true; 379cdf0e10cSrcweir } 380cdf0e10cSrcweir return false; 381cdf0e10cSrcweir } 382cdf0e10cSrcweir } 383cdf0e10cSrcweir 384cdf0e10cSrcweir 385cdf0e10cSrcweir 386cdf0e10cSrcweir protected AccessibleTreeCellRenderer 387cdf0e10cSrcweir maCellRenderer; 388cdf0e10cSrcweir 389cdf0e10cSrcweir 390cdf0e10cSrcweir private JTree 391cdf0e10cSrcweir maTree; 392cdf0e10cSrcweir private Canvas 393cdf0e10cSrcweir maCanvas; 394cdf0e10cSrcweir private boolean 395cdf0e10cSrcweir mbFirstShapeSeen; 396cdf0e10cSrcweir private int 397cdf0e10cSrcweir mnExpandLevel; 398cdf0e10cSrcweir } 399