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