blob: 9b74ac838fc0de3bafe2cfa595d7c0b561b18a9c [file] [log] [blame]
/**************************************************************
*
* 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;
}