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