1 /* 2 * This file is part of the LibreOffice project. 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 * 8 * This file incorporates work covered by the following license notice: 9 * 10 * Licensed to the Apache Software Foundation (ASF) under one or more 11 * contributor license agreements. See the NOTICE file distributed 12 * with this work for additional information regarding copyright 13 * ownership. The ASF licenses this file to you under the Apache 14 * License, Version 2.0 (the "License"); you may not use this file 15 * except in compliance with the License. You may obtain a copy of 16 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 17 */ 18 19 import java.util.ArrayList; 20 import java.util.Arrays; 21 22 import com.sun.star.accessibility.XAccessible; 23 import com.sun.star.accessibility.XAccessibleComponent; 24 import com.sun.star.accessibility.XAccessibleContext; 25 import com.sun.star.accessibility.XAccessibleEditableText; 26 import com.sun.star.accessibility.XAccessibleSelection; 27 import com.sun.star.accessibility.XAccessibleTable; 28 import com.sun.star.accessibility.XAccessibleText; 29 import com.sun.star.uno.UnoRuntime; 30 31 /** 32 * The node type for the AccessibleTreeModel. 33 * This implements all the child-handling based on the appropriate 34 * NodeHandlers. Trivial nodes can be implemented by any Object 35 * type. 36 */ 37 class AccTreeNode 38 extends AccessibleTreeNode 39 { 40 private class HandlerDescriptor 41 { HandlerDescriptor(NodeHandler aHandler)42 private HandlerDescriptor (NodeHandler aHandler) 43 { 44 maHandler = aHandler; 45 mnChildCount = -1; 46 } 47 private NodeHandler maHandler; 48 private int mnChildCount; 49 } 50 /// NodeHandlers for this node 51 private ArrayList<HandlerDescriptor> maHandlers; 52 53 // The accessible context of this node. 54 private XAccessibleContext mxContext; 55 private XAccessibleComponent mxComponent; 56 private XAccessibleText mxText; 57 private XAccessibleTable mxTable; 58 AccTreeNode(XAccessibleContext xContext, Object aDisplay, AccessibleTreeNode aParent)59 public AccTreeNode (XAccessibleContext xContext, Object aDisplay, AccessibleTreeNode aParent) 60 { 61 super (aDisplay, aParent); 62 63 maHandlers = new ArrayList<HandlerDescriptor>(5); 64 mxContext = xContext; 65 } 66 67 /** Update the internal data extracted from the corresponding accessible 68 object. This is done by replacing every handler by a new one. An 69 update method at each handler would be better of course. 70 */ 71 @Override update()72 public void update () 73 { 74 for (int i=0; i<maHandlers.size(); i++) 75 { 76 System.out.println ("replacing handler " + i); 77 HandlerDescriptor aDescriptor = maHandlers.get(i); 78 aDescriptor.maHandler = aDescriptor.maHandler.createHandler (mxContext); 79 aDescriptor.mnChildCount = 80 aDescriptor.maHandler.getChildCount (); 81 } 82 } 83 getContext()84 public XAccessibleContext getContext () 85 { 86 return mxContext; 87 } 88 getComponent()89 public XAccessibleComponent getComponent () 90 { 91 if (mxComponent == null && mxContext != null) 92 mxComponent = UnoRuntime.queryInterface( 93 XAccessibleComponent.class, mxContext); 94 return mxComponent; 95 } 96 getText()97 public XAccessibleText getText () 98 { 99 if (mxText == null && mxContext != null) 100 mxText = UnoRuntime.queryInterface( 101 XAccessibleText.class, mxContext); 102 return mxText; 103 } 104 getEditText()105 public XAccessibleEditableText getEditText () 106 { 107 return UnoRuntime.queryInterface( 108 XAccessibleEditableText.class, mxContext); 109 } 110 getTable()111 public XAccessibleTable getTable () 112 { 113 if (mxTable == null && mxContext != null) 114 mxTable = UnoRuntime.queryInterface( 115 XAccessibleTable.class, mxContext); 116 return mxTable; 117 } 118 119 getSelection()120 public XAccessibleSelection getSelection () 121 { 122 return UnoRuntime.queryInterface( 123 XAccessibleSelection.class, mxContext); 124 } 125 addHandler( NodeHandler aHandler )126 public void addHandler( NodeHandler aHandler ) 127 { 128 if (aHandler != null) 129 maHandlers.add (new HandlerDescriptor (aHandler)); 130 } 131 132 133 /** iterate over handlers and return child sum */ getHandlerDescriptor(int i)134 private HandlerDescriptor getHandlerDescriptor (int i) 135 { 136 HandlerDescriptor aDescriptor = maHandlers.get(i); 137 if (aDescriptor.mnChildCount < 0) 138 aDescriptor.mnChildCount = 139 aDescriptor.maHandler.getChildCount (); 140 return aDescriptor; 141 } 142 143 @Override getChildCount()144 public int getChildCount() 145 { 146 int nChildCount = 0; 147 for (int i = 0; i < maHandlers.size(); i++) 148 { 149 HandlerDescriptor aDescriptor = getHandlerDescriptor (i); 150 nChildCount += aDescriptor.mnChildCount; 151 } 152 return nChildCount; 153 } 154 155 /** iterate over handlers until the child is found */ 156 @Override getChild(int nIndex)157 public AccessibleTreeNode getChild (int nIndex) 158 throws IndexOutOfBoundsException 159 { 160 if( nIndex >= 0 ) 161 { 162 for(int i = 0; i < maHandlers.size(); i++) 163 { 164 // check if this handler has the child, and if not 165 // search with next handler 166 HandlerDescriptor aDescriptor = getHandlerDescriptor (i); 167 if (nIndex < aDescriptor.mnChildCount) 168 return aDescriptor.maHandler.getChild (this, nIndex); 169 else 170 nIndex -= aDescriptor.mnChildCount; 171 } 172 } 173 else 174 throw new IndexOutOfBoundsException(); 175 176 // nothing found? 177 return null; 178 } 179 180 @Override getChildNoCreate(int nIndex)181 public AccessibleTreeNode getChildNoCreate (int nIndex) 182 throws IndexOutOfBoundsException 183 { 184 if( nIndex >= 0 ) 185 { 186 for(int i = 0; i < maHandlers.size(); i++) 187 { 188 // check if this handler has the child, and if not 189 // search with next handler 190 HandlerDescriptor aDescriptor = getHandlerDescriptor (i); 191 if (nIndex < aDescriptor.mnChildCount) 192 return aDescriptor.maHandler.getChildNoCreate (nIndex); 193 else 194 nIndex -= aDescriptor.mnChildCount; 195 } 196 } 197 else 198 throw new IndexOutOfBoundsException(); 199 200 // nothing found? 201 return null; 202 } 203 204 @Override removeChild(int nIndex)205 public boolean removeChild (int nIndex) 206 throws IndexOutOfBoundsException 207 { 208 boolean bStatus = false; 209 if (nIndex >= 0) 210 { 211 for (int i=0; i<maHandlers.size(); i++) 212 { 213 // check if this handler has the child, and if not 214 // search with next handler 215 HandlerDescriptor aDescriptor = getHandlerDescriptor (i); 216 if (nIndex < aDescriptor.mnChildCount) 217 { 218 bStatus = aDescriptor.maHandler.removeChild (nIndex); 219 aDescriptor.mnChildCount = aDescriptor.maHandler.getChildCount (); 220 break; 221 } 222 else 223 nIndex -= aDescriptor.mnChildCount; 224 } 225 } 226 else 227 throw new IndexOutOfBoundsException(); 228 229 return bStatus; 230 } 231 232 233 @Override indexOf(AccessibleTreeNode aNode)234 public int indexOf (AccessibleTreeNode aNode) 235 { 236 int nBaseIndex = 0; 237 if (aNode != null) 238 { 239 for (int i=0; i<maHandlers.size(); i++) 240 { 241 HandlerDescriptor aDescriptor = getHandlerDescriptor (i); 242 int nIndex = aDescriptor.maHandler.indexOf (aNode); 243 if (nIndex >= 0) 244 return nBaseIndex + nIndex; 245 else 246 nBaseIndex += aDescriptor.mnChildCount; 247 } 248 } 249 250 return -1; 251 } 252 253 /** this node is a leaf if have no handlers, or is those 254 handlers show no children */ 255 @Override isLeaf()256 public boolean isLeaf() 257 { 258 return maHandlers.isEmpty(); 259 } 260 261 @Override equals(Object aOther)262 public boolean equals (Object aOther) 263 { 264 return (this == aOther) || (aOther!=null && aOther.equals(mxContext)); 265 } 266 267 268 /** iterate over handlers until the child is found */ getActions(java.util.List<String> aActions)269 public void getActions(java.util.List<String> aActions) 270 { 271 for(int i = 0; i < maHandlers.size(); i++) 272 { 273 HandlerDescriptor aDescriptor = getHandlerDescriptor (i); 274 NodeHandler aHandler = aDescriptor.maHandler; 275 String[] aHandlerActions = aHandler.getActions (this); 276 aActions.addAll(Arrays.asList(aHandlerActions)); 277 } 278 } 279 280 @Override performAction( int nIndex )281 public void performAction( int nIndex ) 282 { 283 if( nIndex >= 0 ) 284 { 285 for(int i = 0; i < maHandlers.size(); i++) 286 { 287 // check if this handler has the child, and if not 288 // search with next handler 289 HandlerDescriptor aDescriptor = getHandlerDescriptor (i); 290 NodeHandler aHandler = aDescriptor.maHandler; 291 int nCount = aHandler.getActions(this).length; 292 if( nCount > nIndex ) 293 { 294 aHandler.performAction(this, nIndex ); 295 return; 296 } 297 else 298 nIndex -= nCount; 299 } 300 } 301 } 302 303 /** Try to add the specified accessible object as new accessible child of the 304 AccessibleTreeHandler. 305 Note that child is used in another context than 306 it is used in the other methods of this class. 307 */ addAccessibleChild(XAccessible xChild)308 public AccessibleTreeNode addAccessibleChild (XAccessible xChild) 309 { 310 for(int i = 0; i < maHandlers.size(); i++) 311 { 312 HandlerDescriptor aDescriptor = getHandlerDescriptor (i); 313 if (aDescriptor.maHandler instanceof AccessibleTreeHandler) 314 { 315 AccessibleTreeHandler aHandler = (AccessibleTreeHandler)aDescriptor.maHandler; 316 AccessibleTreeNode aNode = aHandler.addAccessibleChild (this, xChild); 317 aDescriptor.mnChildCount = aHandler.getChildCount (); 318 return aNode; 319 } 320 } 321 return null; 322 } 323 updateChildren(java.lang.Class class1, java.lang.Class<AccessibleExtendedComponentHandler> class2)324 public java.util.List<Integer> updateChildren (java.lang.Class class1, java.lang.Class<AccessibleExtendedComponentHandler> class2) 325 { 326 ArrayList<Integer> aChildIndices = new ArrayList<Integer>(); 327 int nOffset = 0; 328 for(int i=0; i < maHandlers.size(); i++) 329 { 330 HandlerDescriptor aDescriptor = getHandlerDescriptor (i); 331 if ((class1.isInstance(aDescriptor.maHandler)) 332 || (class2 !=null && class2.isInstance(aDescriptor.maHandler))) 333 { 334 aDescriptor.maHandler.update(this); 335 // Get updated number of children. 336 int nChildCount = aDescriptor.maHandler.getChildCount (); 337 aDescriptor.mnChildCount = nChildCount; 338 // Fill in the indices of the updated children. 339 for (int j=0; j<nChildCount; j++) 340 aChildIndices.add(j+nOffset); 341 } 342 nOffset += aDescriptor.mnChildCount; 343 } 344 return aChildIndices; 345 } 346 } 347