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