| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| 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; |
| } |