xref: /AOO41X/main/toolkit/test/accessibility/AccessibilityTreeModel.java (revision 1b0aaa91df402a6f20c4769a008573eb958e886d)
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 javax.swing.event.TreeModelEvent;
23cdf0e10cSrcweir import javax.swing.event.TreeModelListener;
24cdf0e10cSrcweir import javax.swing.tree.TreePath;
25cdf0e10cSrcweir 
26cdf0e10cSrcweir 
27cdf0e10cSrcweir import java.util.Vector;
28cdf0e10cSrcweir import java.util.HashMap;
29cdf0e10cSrcweir import java.util.Enumeration;
30cdf0e10cSrcweir 
31cdf0e10cSrcweir import com.sun.star.accessibility.*;
32cdf0e10cSrcweir 
33cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime;
34cdf0e10cSrcweir import com.sun.star.uno.XInterface;
35cdf0e10cSrcweir import com.sun.star.uno.Any;
36cdf0e10cSrcweir import com.sun.star.lang.EventObject;
37cdf0e10cSrcweir import com.sun.star.lang.XServiceInfo;
38cdf0e10cSrcweir import com.sun.star.lang.XServiceName;
39cdf0e10cSrcweir 
40cdf0e10cSrcweir public class AccessibilityTreeModel
41cdf0e10cSrcweir     extends AccessibilityTreeModelBase
42cdf0e10cSrcweir {
43cdf0e10cSrcweir     public boolean mbVerbose = false;
44cdf0e10cSrcweir 
AccessibilityTreeModel(AccessibleTreeNode aRoot)45cdf0e10cSrcweir     public AccessibilityTreeModel (AccessibleTreeNode aRoot)
46cdf0e10cSrcweir     {
47cdf0e10cSrcweir         // create default node (unless we have a 'proper' node)
48cdf0e10cSrcweir         if( ! (aRoot instanceof AccessibleTreeNode) )
49cdf0e10cSrcweir             aRoot = new StringNode ("Root", null);
50cdf0e10cSrcweir         setRoot (aRoot);
51cdf0e10cSrcweir 
52cdf0e10cSrcweir         maNodeMap = new NodeMap();
53cdf0e10cSrcweir 
54cdf0e10cSrcweir         maEventListener = new EventListener (this);
55cdf0e10cSrcweir         mxListener = new QueuedListener (maEventListener);
56cdf0e10cSrcweir     }
57cdf0e10cSrcweir 
clear()58cdf0e10cSrcweir     public void clear ()
59cdf0e10cSrcweir     {
60cdf0e10cSrcweir         maNodeMap.Clear();
61cdf0e10cSrcweir     }
62cdf0e10cSrcweir 
63cdf0e10cSrcweir     /** Lock the tree.  While the tree is locked, events from the outside are
64cdf0e10cSrcweir         not processed.  Lock the tree when you change its internal structure.
65cdf0e10cSrcweir     */
lock()66cdf0e10cSrcweir     public void lock ()
67cdf0e10cSrcweir     {
68cdf0e10cSrcweir         mnLockCount += 1;
69cdf0e10cSrcweir     }
70cdf0e10cSrcweir 
71cdf0e10cSrcweir     /** Unlock the tree.  After unlocking the tree as many times as locking
72cdf0e10cSrcweir         it, a treeStructureChange event is sent to the event listeners.
73cdf0e10cSrcweir         @param aNodeHint
74cdf0e10cSrcweir             If not null and treeStructureChange events are thrown then this
75cdf0e10cSrcweir             node is used as root of the modified subtree.
76cdf0e10cSrcweir     */
unlock(AccessibleTreeNode aNodeHint)77cdf0e10cSrcweir     public void unlock (AccessibleTreeNode aNodeHint)
78cdf0e10cSrcweir     {
79cdf0e10cSrcweir         mnLockCount -= 1;
80cdf0e10cSrcweir         if (mnLockCount == 0)
81cdf0e10cSrcweir             fireTreeStructureChanged (
82cdf0e10cSrcweir                 new TreeModelEvent (this,
83cdf0e10cSrcweir                     new TreePath (aNodeHint.createPath())));
84cdf0e10cSrcweir     }
85cdf0e10cSrcweir 
86cdf0e10cSrcweir 
87cdf0e10cSrcweir 
88cdf0e10cSrcweir 
89cdf0e10cSrcweir     /** Inform all listeners (especially the renderer) of a change of the
90cdf0e10cSrcweir         tree's structure.
91cdf0e10cSrcweir         @param aNode This node specifies the sub tree in which all changes
92cdf0e10cSrcweir         take place.
93cdf0e10cSrcweir     */
FireTreeStructureChanged(AccessibleTreeNode aNode)94cdf0e10cSrcweir     public void FireTreeStructureChanged (AccessibleTreeNode aNode)
95cdf0e10cSrcweir     {
96cdf0e10cSrcweir     }
97cdf0e10cSrcweir 
98cdf0e10cSrcweir 
99cdf0e10cSrcweir 
100cdf0e10cSrcweir 
101cdf0e10cSrcweir 
setRoot(AccessibleTreeNode aRoot)102cdf0e10cSrcweir     public synchronized void setRoot (AccessibleTreeNode aRoot)
103cdf0e10cSrcweir     {
104cdf0e10cSrcweir         if (getRoot() == null)
105cdf0e10cSrcweir             super.setRoot (aRoot);
106cdf0e10cSrcweir         else
107cdf0e10cSrcweir         {
108cdf0e10cSrcweir             lock ();
109cdf0e10cSrcweir             maNodeMap.ForEach (new NodeMapCallback () {
110cdf0e10cSrcweir                     public void Apply (AccTreeNode aNode)
111cdf0e10cSrcweir                     {
112cdf0e10cSrcweir                         if (maCanvas != null)
113cdf0e10cSrcweir                             maCanvas.removeNode (aNode);
114cdf0e10cSrcweir                         removeAccListener ((AccTreeNode)aNode);
115cdf0e10cSrcweir                     }
116cdf0e10cSrcweir                 });
117cdf0e10cSrcweir             maNodeMap.Clear ();
118cdf0e10cSrcweir 
119cdf0e10cSrcweir             setRoot (aRoot);
120cdf0e10cSrcweir             unlock (aRoot);
121cdf0e10cSrcweir         }
122cdf0e10cSrcweir     }
123cdf0e10cSrcweir 
124cdf0e10cSrcweir 
125cdf0e10cSrcweir     //
126cdf0e10cSrcweir     // child management:
127cdf0e10cSrcweir     //
128cdf0e10cSrcweir 
129cdf0e10cSrcweir 
130cdf0e10cSrcweir 
131cdf0e10cSrcweir     /** Delegate the request to the parent and then register listeners at
132cdf0e10cSrcweir         the child and add the child to the canvas.
133cdf0e10cSrcweir     */
getChild(Object aParent, int nIndex)134cdf0e10cSrcweir     public Object getChild (Object aParent, int nIndex)
135cdf0e10cSrcweir     {
136cdf0e10cSrcweir         AccessibleTreeNode aChild = (AccessibleTreeNode)super.getChild (aParent, nIndex);
137cdf0e10cSrcweir 
138cdf0e10cSrcweir         if (aChild == null)
139cdf0e10cSrcweir             System.out.println ("getChild: child not found");
140cdf0e10cSrcweir         else
141cdf0e10cSrcweir             // Keep translation table up-to-date.
142cdf0e10cSrcweir             addNode (aChild);
143cdf0e10cSrcweir 
144cdf0e10cSrcweir         return aChild;
145cdf0e10cSrcweir     }
146cdf0e10cSrcweir 
getChildNoCreate(Object aParent, int nIndex)147cdf0e10cSrcweir     public Object getChildNoCreate (Object aParent, int nIndex)
148cdf0e10cSrcweir     {
149cdf0e10cSrcweir         AccessibleTreeNode aChild = (AccessibleTreeNode)super.getChildNoCreate (aParent, nIndex);
150cdf0e10cSrcweir 
151cdf0e10cSrcweir         return aChild;
152cdf0e10cSrcweir     }
153cdf0e10cSrcweir 
154cdf0e10cSrcweir 
155cdf0e10cSrcweir 
156cdf0e10cSrcweir 
157cdf0e10cSrcweir     /** Remove a node (and all children) from the tree model.
158cdf0e10cSrcweir     */
removeChild(AccessibleTreeNode aNode)159cdf0e10cSrcweir     protected boolean removeChild (AccessibleTreeNode aNode)
160cdf0e10cSrcweir     {
161cdf0e10cSrcweir         try
162cdf0e10cSrcweir         {
163cdf0e10cSrcweir             if( aNode == null )
164cdf0e10cSrcweir             {
165cdf0e10cSrcweir                 System.out.println ("can't remove null node");
166cdf0e10cSrcweir                 return false;
167cdf0e10cSrcweir             }
168cdf0e10cSrcweir             else
169cdf0e10cSrcweir             {
170cdf0e10cSrcweir                 // depth-first removal of children
171cdf0e10cSrcweir                 while (aNode.getChildCount() > 0)
172cdf0e10cSrcweir                     if ( ! removeChild (aNode.getChildNoCreate (0)))
173cdf0e10cSrcweir                         break;
174cdf0e10cSrcweir 
175cdf0e10cSrcweir                 // Remove node from its parent.
176cdf0e10cSrcweir                 AccessibleTreeNode aParent = aNode.getParent();
177cdf0e10cSrcweir                 if (aParent != null)
178cdf0e10cSrcweir                 {
179cdf0e10cSrcweir                     int nIndex = aParent.indexOf(aNode);
180cdf0e10cSrcweir                     aParent.removeChild (nIndex);
181cdf0e10cSrcweir                 }
182cdf0e10cSrcweir 
183cdf0e10cSrcweir                 maNodeMap.RemoveNode (aNode);
184cdf0e10cSrcweir             }
185cdf0e10cSrcweir         }
186cdf0e10cSrcweir         catch (Exception e)
187cdf0e10cSrcweir         {
188cdf0e10cSrcweir             System.out.println ("caught exception while removing child "
189cdf0e10cSrcweir                 + aNode + " : " + e);
190cdf0e10cSrcweir             e.printStackTrace ();
191cdf0e10cSrcweir             return false;
192cdf0e10cSrcweir         }
193cdf0e10cSrcweir         return true;
194cdf0e10cSrcweir     }
195cdf0e10cSrcweir 
removeNode(XAccessibleContext xNode)196cdf0e10cSrcweir     public void removeNode (XAccessibleContext xNode)
197cdf0e10cSrcweir     {
198cdf0e10cSrcweir         if (xNode != null)
199cdf0e10cSrcweir         {
200cdf0e10cSrcweir             AccessibleTreeNode aNode = maNodeMap.GetNode (xNode);
201cdf0e10cSrcweir             AccessibleTreeNode aRootNode = (AccessibleTreeNode)getRoot();
202cdf0e10cSrcweir             TreeModelEvent aEvent = createEvent (aRootNode, aNode);
203cdf0e10cSrcweir             removeChild (aNode);
204cdf0e10cSrcweir             if (mbVerbose)
205cdf0e10cSrcweir                 System.out.println (aNode);
206cdf0e10cSrcweir             fireTreeNodesRemoved (aEvent);
207cdf0e10cSrcweir             maCanvas.repaint ();
208cdf0e10cSrcweir         }
209cdf0e10cSrcweir     }
210cdf0e10cSrcweir 
211cdf0e10cSrcweir 
212cdf0e10cSrcweir     /** Add add a new child to a parent.
213cdf0e10cSrcweir         @return
214cdf0e10cSrcweir             Returns the new or existing representation of the specified
215cdf0e10cSrcweir             accessible object.
216cdf0e10cSrcweir     */
addChild(AccTreeNode aParentNode, XAccessible xNewChild)217cdf0e10cSrcweir     protected AccessibleTreeNode addChild (AccTreeNode aParentNode, XAccessible xNewChild)
218cdf0e10cSrcweir     {
219cdf0e10cSrcweir         AccessibleTreeNode aChildNode = null;
220cdf0e10cSrcweir         try
221cdf0e10cSrcweir         {
222cdf0e10cSrcweir             boolean bRet = false;
223cdf0e10cSrcweir 
224cdf0e10cSrcweir             // First make sure that the accessible object does not already have
225cdf0e10cSrcweir             // a representation.
226cdf0e10cSrcweir             aChildNode = maNodeMap.GetNode(xNewChild);
227cdf0e10cSrcweir             if (aChildNode == null)
228cdf0e10cSrcweir                 aChildNode = aParentNode.addAccessibleChild (xNewChild);
229cdf0e10cSrcweir             else
230cdf0e10cSrcweir                 System.out.println ("node already present");
231cdf0e10cSrcweir         }
232cdf0e10cSrcweir         catch (Exception e)
233cdf0e10cSrcweir         {
234cdf0e10cSrcweir             System.out.println ("caught exception while adding child "
235cdf0e10cSrcweir                 + xNewChild + " to parent " + aParentNode + ": " + e);
236cdf0e10cSrcweir             e.printStackTrace ();
237cdf0e10cSrcweir         }
238cdf0e10cSrcweir         return aChildNode;
239cdf0e10cSrcweir     }
240cdf0e10cSrcweir 
addChild(XAccessibleContext xParent, XAccessible xChild)241cdf0e10cSrcweir     public void addChild (XAccessibleContext xParent, XAccessible xChild)
242cdf0e10cSrcweir     {
243cdf0e10cSrcweir         AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent);
244cdf0e10cSrcweir         if (aParentNode instanceof AccTreeNode)
245cdf0e10cSrcweir         {
246cdf0e10cSrcweir             AccessibleTreeNode aChild = addChild ((AccTreeNode)aParentNode, xChild);
247cdf0e10cSrcweir             if (addNode (aChild))
248cdf0e10cSrcweir             {
249cdf0e10cSrcweir                 if (maCanvas != null)
250cdf0e10cSrcweir                     maCanvas.updateNode ((AccTreeNode)aParentNode);
251cdf0e10cSrcweir 
252cdf0e10cSrcweir                 // A call to fireTreeNodesInserted for xNew
253cdf0e10cSrcweir                 // should be sufficient but at least the
254cdf0e10cSrcweir                 // StringNode object that contains the number of
255cdf0e10cSrcweir                 // children also changes and we do not know its
256cdf0e10cSrcweir                 // index relative to its parent.  Therefore the
257cdf0e10cSrcweir                 // more expensive fireTreeStructureChanged is
258cdf0e10cSrcweir                 // necessary.
259cdf0e10cSrcweir                 fireTreeNodesInserted (createEvent (xParent, xChild));
260cdf0e10cSrcweir                 updateNode (xParent, AccessibleTreeHandler.class);
261cdf0e10cSrcweir             }
262cdf0e10cSrcweir             maCanvas.repaint ();
263cdf0e10cSrcweir         }
264cdf0e10cSrcweir     }
265cdf0e10cSrcweir 
266cdf0e10cSrcweir 
267cdf0e10cSrcweir     /** Add the child node to the internal tree structure.
268cdf0e10cSrcweir         @param aNode
269cdf0e10cSrcweir             The node to insert into the internal tree structure.
270cdf0e10cSrcweir     */
addNode(AccessibleTreeNode aNode)271cdf0e10cSrcweir     protected boolean addNode (AccessibleTreeNode aNode)
272cdf0e10cSrcweir     {
273cdf0e10cSrcweir         boolean bRet = false;
274cdf0e10cSrcweir         try
275cdf0e10cSrcweir         {
276cdf0e10cSrcweir             if ( ! maNodeMap.ValueIsMember (aNode))
277cdf0e10cSrcweir             {
278cdf0e10cSrcweir                 if (aNode instanceof AccTreeNode)
279cdf0e10cSrcweir                 {
280cdf0e10cSrcweir                     AccTreeNode aChild = (AccTreeNode)aNode;
281cdf0e10cSrcweir                     XAccessibleContext xChild = aChild.getContext();
282cdf0e10cSrcweir                     registerAccListener (aChild);
283cdf0e10cSrcweir                     if (maCanvas != null)
284cdf0e10cSrcweir                         maCanvas.addNode (aChild);
285cdf0e10cSrcweir                     maNodeMap.InsertNode (xChild, aChild);
286cdf0e10cSrcweir                 }
287cdf0e10cSrcweir                 bRet = true;
288cdf0e10cSrcweir             }
289cdf0e10cSrcweir 
290cdf0e10cSrcweir         }
291cdf0e10cSrcweir         catch (Exception e)
292cdf0e10cSrcweir         {
293cdf0e10cSrcweir             System.out.println ("caught exception while adding node "
294cdf0e10cSrcweir                 + aNode + ": " + e);
295cdf0e10cSrcweir             e.printStackTrace ();
296cdf0e10cSrcweir         }
297cdf0e10cSrcweir         return bRet;
298cdf0e10cSrcweir     }
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 
301cdf0e10cSrcweir 
302cdf0e10cSrcweir 
303cdf0e10cSrcweir     /** create path to node, suitable for TreeModelEvent constructor
304cdf0e10cSrcweir      * @see javax.swing.event.TreeModelEvent#TreeModelEvent
305cdf0e10cSrcweir      */
createPath(AccessibleTreeNode aNode)306cdf0e10cSrcweir     protected Object[] createPath (AccessibleTreeNode aNode)
307cdf0e10cSrcweir     {
308cdf0e10cSrcweir         Vector aPath = new Vector();
309cdf0e10cSrcweir         aNode.createPath (aPath);
310cdf0e10cSrcweir         return aPath.toArray();
311cdf0e10cSrcweir     }
312cdf0e10cSrcweir 
313cdf0e10cSrcweir     //
314cdf0e10cSrcweir     // listeners (and helper methods)
315cdf0e10cSrcweir     //
316cdf0e10cSrcweir     // We are registered with listeners as soon as objects are in the
317cdf0e10cSrcweir     // tree cache, and we should get removed as soon as they are out.
318cdf0e10cSrcweir     //
319cdf0e10cSrcweir 
fireTreeNodesChanged(TreeModelEvent e)320cdf0e10cSrcweir     protected void fireTreeNodesChanged(TreeModelEvent e)
321cdf0e10cSrcweir     {
322cdf0e10cSrcweir         for(int i = 0; i < maTMListeners.size(); i++)
323cdf0e10cSrcweir         {
324cdf0e10cSrcweir             ((TreeModelListener)maTMListeners.get(i)).treeNodesChanged(e);
325cdf0e10cSrcweir         }
326cdf0e10cSrcweir     }
327cdf0e10cSrcweir 
fireTreeNodesInserted(final TreeModelEvent e)328cdf0e10cSrcweir     protected void fireTreeNodesInserted(final TreeModelEvent e)
329cdf0e10cSrcweir     {
330cdf0e10cSrcweir         for(int i = 0; i < maTMListeners.size(); i++)
331cdf0e10cSrcweir         {
332cdf0e10cSrcweir             ((TreeModelListener)maTMListeners.get(i)).treeNodesInserted(e);
333cdf0e10cSrcweir         }
334cdf0e10cSrcweir     }
335cdf0e10cSrcweir 
fireTreeNodesRemoved(final TreeModelEvent e)336cdf0e10cSrcweir     protected void fireTreeNodesRemoved(final TreeModelEvent e)
337cdf0e10cSrcweir     {
338cdf0e10cSrcweir         for(int i = 0; i < maTMListeners.size(); i++)
339cdf0e10cSrcweir         {
340cdf0e10cSrcweir             ((TreeModelListener)maTMListeners.get(i)).treeNodesRemoved(e);
341cdf0e10cSrcweir         }
342cdf0e10cSrcweir     }
343cdf0e10cSrcweir 
fireTreeStructureChanged(final TreeModelEvent e)344cdf0e10cSrcweir     protected void fireTreeStructureChanged(final TreeModelEvent e)
345cdf0e10cSrcweir     {
346cdf0e10cSrcweir         for(int i = 0; i < maTMListeners.size(); i++)
347cdf0e10cSrcweir         {
348cdf0e10cSrcweir             ((TreeModelListener)maTMListeners.get(i)).treeStructureChanged(e);
349cdf0e10cSrcweir         }
350cdf0e10cSrcweir     }
351cdf0e10cSrcweir 
createEvent(XAccessibleContext xParent)352cdf0e10cSrcweir     protected TreeModelEvent createEvent (XAccessibleContext xParent)
353cdf0e10cSrcweir     {
354cdf0e10cSrcweir         AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent);
355cdf0e10cSrcweir         return new TreeModelEvent (this, createPath (aParentNode));
356cdf0e10cSrcweir     }
357cdf0e10cSrcweir 
358cdf0e10cSrcweir     /** Create a TreeModelEvent object that informs listeners that one child
359cdf0e10cSrcweir         has been removed from or inserted into its parent.
360cdf0e10cSrcweir     */
createEvent(XAccessibleContext xParent, XAccessible xChild)361cdf0e10cSrcweir     public TreeModelEvent createEvent (XAccessibleContext xParent, XAccessible xChild)
362cdf0e10cSrcweir     {
363cdf0e10cSrcweir         AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent);
364cdf0e10cSrcweir         return createEvent (aParentNode, xParent);
365cdf0e10cSrcweir     }
366cdf0e10cSrcweir 
createEvent(AccessibleTreeNode aParentNode, XAccessibleContext xChild)367cdf0e10cSrcweir     public TreeModelEvent createEvent (AccessibleTreeNode aParentNode, XAccessibleContext xChild)
368cdf0e10cSrcweir     {
369cdf0e10cSrcweir         AccessibleTreeNode aChildNode = null;
370cdf0e10cSrcweir         if (xChild != null)
371cdf0e10cSrcweir             aChildNode = maNodeMap.GetNode (xChild);
372cdf0e10cSrcweir         return createEvent (aParentNode, aChildNode);
373cdf0e10cSrcweir     }
374cdf0e10cSrcweir 
375cdf0e10cSrcweir 
376cdf0e10cSrcweir 
createEvent( AccessibleTreeNode aParentNode, AccessibleTreeNode aChildNode)377cdf0e10cSrcweir     protected TreeModelEvent createEvent (
378cdf0e10cSrcweir         AccessibleTreeNode aParentNode,
379cdf0e10cSrcweir         AccessibleTreeNode aChildNode)
380cdf0e10cSrcweir     {
381cdf0e10cSrcweir         Object[] aPathToParent = createPath (aParentNode);
382cdf0e10cSrcweir 
383cdf0e10cSrcweir         int nIndexInParent = -1;
384cdf0e10cSrcweir         if (aChildNode != null)
385cdf0e10cSrcweir             nIndexInParent = aParentNode.indexOf (aChildNode);
386cdf0e10cSrcweir         if (mbVerbose)
387cdf0e10cSrcweir             System.out.println (aChildNode + " " + nIndexInParent);
388cdf0e10cSrcweir 
389cdf0e10cSrcweir         if (nIndexInParent == -1)
390cdf0e10cSrcweir             // This event may be passed only to treeStructureChanged of the listeners.
391cdf0e10cSrcweir             return new TreeModelEvent (this,
392cdf0e10cSrcweir                 aPathToParent);
393cdf0e10cSrcweir         else
394cdf0e10cSrcweir             // General purpose event for removing or inserting known nodes.
395cdf0e10cSrcweir             return new TreeModelEvent (this,
396cdf0e10cSrcweir                 aPathToParent,
397cdf0e10cSrcweir                 new int[] {nIndexInParent},
398cdf0e10cSrcweir                 new Object[] {aChildNode} );
399cdf0e10cSrcweir     }
400cdf0e10cSrcweir 
401cdf0e10cSrcweir 
402cdf0e10cSrcweir 
403cdf0e10cSrcweir 
404cdf0e10cSrcweir     /** Create a TreeModelEvent that indicates changes at those children of
405cdf0e10cSrcweir         the specified node with the specified indices.
406cdf0e10cSrcweir     */
createChangeEvent(AccTreeNode aNode, Vector aChildIndices)407cdf0e10cSrcweir     protected TreeModelEvent createChangeEvent (AccTreeNode aNode, Vector aChildIndices)
408cdf0e10cSrcweir     {
409cdf0e10cSrcweir         // Build a list of child objects that are indicated by the given indices.
410cdf0e10cSrcweir         int nCount = aChildIndices.size();
411cdf0e10cSrcweir         Object aChildObjects[] = new Object[nCount];
412cdf0e10cSrcweir         int nChildIndices[] = new int[nCount];
413cdf0e10cSrcweir         for (int i=0; i<nCount; i++)
414cdf0e10cSrcweir         {
415cdf0e10cSrcweir             int nIndex = ((Integer)aChildIndices.elementAt(i)).intValue();
416cdf0e10cSrcweir             aChildObjects[i] = aNode.getChild (nIndex);
417cdf0e10cSrcweir             nChildIndices[i] = nIndex;
418cdf0e10cSrcweir         }
419cdf0e10cSrcweir 
420cdf0e10cSrcweir         return new TreeModelEvent (this,
421cdf0e10cSrcweir             createPath(aNode),
422cdf0e10cSrcweir             nChildIndices,
423cdf0e10cSrcweir             aChildObjects);
424cdf0e10cSrcweir     }
425cdf0e10cSrcweir 
426cdf0e10cSrcweir 
427cdf0e10cSrcweir 
428cdf0e10cSrcweir     /**
429cdf0e10cSrcweir      * broadcast a tree event in a seperate Thread
430cdf0e10cSrcweir      * must override fire method
431cdf0e10cSrcweir      */
432cdf0e10cSrcweir     class EventRunner implements Runnable
433cdf0e10cSrcweir     {
run()434cdf0e10cSrcweir         public void run()
435cdf0e10cSrcweir         {
436cdf0e10cSrcweir             for(int i = 0; i < maTMListeners.size(); i++)
437cdf0e10cSrcweir             {
438cdf0e10cSrcweir                 fire( (TreeModelListener)maTMListeners.get(i) );
439cdf0e10cSrcweir             }
440cdf0e10cSrcweir         }
441cdf0e10cSrcweir 
fire( TreeModelListener l)442cdf0e10cSrcweir         protected void fire( TreeModelListener l) { }
443cdf0e10cSrcweir     }
444cdf0e10cSrcweir 
445cdf0e10cSrcweir 
446cdf0e10cSrcweir 
getBroadcaster(Object aObject)447cdf0e10cSrcweir     protected XAccessibleEventBroadcaster getBroadcaster (Object aObject)
448cdf0e10cSrcweir     {
449cdf0e10cSrcweir         if (aObject instanceof AccTreeNode)
450cdf0e10cSrcweir             return (XAccessibleEventBroadcaster) UnoRuntime.queryInterface (
451cdf0e10cSrcweir                 XAccessibleEventBroadcaster.class, ((AccTreeNode)aObject).getContext());
452cdf0e10cSrcweir         else
453cdf0e10cSrcweir             return null;
454cdf0e10cSrcweir     }
455cdf0e10cSrcweir 
registerAccListener( Object aObject )456cdf0e10cSrcweir     protected void registerAccListener( Object aObject )
457cdf0e10cSrcweir     {
458cdf0e10cSrcweir         // register this as listener for XAccessibleEventBroadcaster
459cdf0e10cSrcweir         // implementations
460cdf0e10cSrcweir         XAccessibleEventBroadcaster xBroadcaster = getBroadcaster( aObject );
461cdf0e10cSrcweir         if (xBroadcaster != null)
462cdf0e10cSrcweir         {
463cdf0e10cSrcweir             xBroadcaster.addEventListener( mxListener );
464cdf0e10cSrcweir         }
465cdf0e10cSrcweir     }
466cdf0e10cSrcweir 
removeAccListener( Object aObject )467cdf0e10cSrcweir     protected void removeAccListener( Object aObject )
468cdf0e10cSrcweir     {
469cdf0e10cSrcweir         XAccessibleEventBroadcaster xBroadcaster = getBroadcaster( aObject );
470cdf0e10cSrcweir         if (xBroadcaster != null)
471cdf0e10cSrcweir         {
472cdf0e10cSrcweir             xBroadcaster.removeEventListener( mxListener );
473cdf0e10cSrcweir         }
474cdf0e10cSrcweir     }
475cdf0e10cSrcweir 
476cdf0e10cSrcweir 
477cdf0e10cSrcweir 
setCanvas(Canvas aCanvas)478cdf0e10cSrcweir     public void setCanvas (Canvas aCanvas)
479cdf0e10cSrcweir     {
480cdf0e10cSrcweir         maCanvas = aCanvas;
481cdf0e10cSrcweir     }
482cdf0e10cSrcweir 
getCanvas()483cdf0e10cSrcweir     public Canvas getCanvas ()
484cdf0e10cSrcweir     {
485cdf0e10cSrcweir         return maCanvas;
486cdf0e10cSrcweir     }
487cdf0e10cSrcweir 
updateNode(XAccessibleContext xSource, java.lang.Class class1)488cdf0e10cSrcweir     public void updateNode (XAccessibleContext xSource, java.lang.Class class1)
489cdf0e10cSrcweir     {
490cdf0e10cSrcweir         updateNode (xSource, class1,null);
491cdf0e10cSrcweir     }
492cdf0e10cSrcweir 
493cdf0e10cSrcweir     /** Get a list of children of the node associated with xSource that are
494cdf0e10cSrcweir         affected by the given handlers.  Fire events that these children may
495cdf0e10cSrcweir         have changed in the tree view.  Update the canvas representation of
496cdf0e10cSrcweir         xSource.
497cdf0e10cSrcweir     */
updateNode(XAccessibleContext xSource, java.lang.Class class1, java.lang.Class class2)498cdf0e10cSrcweir     public AccTreeNode updateNode (XAccessibleContext xSource,
499cdf0e10cSrcweir         java.lang.Class class1, java.lang.Class class2)
500cdf0e10cSrcweir     {
501cdf0e10cSrcweir         AccessibleTreeNode aTreeNode = maNodeMap.GetNode (xSource);
502cdf0e10cSrcweir         AccTreeNode aNode = null;
503cdf0e10cSrcweir         if (mbVerbose)
504cdf0e10cSrcweir             System.out.println ("updating node " + xSource + "  " + aTreeNode);
505cdf0e10cSrcweir         if (aTreeNode instanceof AccTreeNode)
506cdf0e10cSrcweir         {
507cdf0e10cSrcweir             aNode = (AccTreeNode) aTreeNode;
508cdf0e10cSrcweir             // Get list of affected children.
509cdf0e10cSrcweir             Vector aChildIndices = (aNode).updateChildren (
510cdf0e10cSrcweir                 class1, class2);
511cdf0e10cSrcweir             // Fire events that these children may have changed.
512cdf0e10cSrcweir             fireTreeNodesChanged (
513cdf0e10cSrcweir                 createChangeEvent (aNode, aChildIndices));
514cdf0e10cSrcweir         }
515cdf0e10cSrcweir         return aNode;
516cdf0e10cSrcweir     }
517cdf0e10cSrcweir 
518cdf0e10cSrcweir     /** The listener to be registered with the accessible objects.
519cdf0e10cSrcweir      * Could be set to 'this' for same-thread event delivery, or to an
520cdf0e10cSrcweir      * instance of QueuedListener for multi-threaded delivery.  May
521cdf0e10cSrcweir      * not be changed, since this would trip the
522cdf0e10cSrcweir      * register/removeAccListener logic. */
523cdf0e10cSrcweir     private final XAccessibleEventListener mxListener;
524cdf0e10cSrcweir 
525cdf0e10cSrcweir     // Map to translate from accessible object to corresponding tree node.
526cdf0e10cSrcweir     private NodeMap maNodeMap;
527cdf0e10cSrcweir 
528cdf0e10cSrcweir     // If the lock count is higher then zero, then no events are processed.
529cdf0e10cSrcweir     private int mnLockCount;
530cdf0e10cSrcweir 
531cdf0e10cSrcweir     private Canvas maCanvas;
532cdf0e10cSrcweir 
533cdf0e10cSrcweir     private EventListener maEventListener;
534cdf0e10cSrcweir }
535