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