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