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 
23 
24 package org.openoffice.java.accessibility;
25 
26 import javax.accessibility.AccessibleContext;
27 import javax.accessibility.AccessibleState;
28 
29 import com.sun.star.uno.AnyConverter;
30 import com.sun.star.uno.UnoRuntime;
31 import com.sun.star.accessibility.*;
32 
33 public class List extends DescendantManager implements javax.accessibility.Accessible {
34 
List(XAccessible xAccessible, XAccessibleContext xAccessibleContext)35     protected List(XAccessible xAccessible, XAccessibleContext xAccessibleContext) {
36         super(xAccessible, xAccessibleContext);
37     }
38 
setActiveDescendant(javax.accessibility.Accessible descendant)39     protected void setActiveDescendant(javax.accessibility.Accessible descendant) {
40         javax.accessibility.Accessible oldAD = activeDescendant;
41         activeDescendant = descendant;
42         firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY,
43             oldAD, descendant);
44     }
45 
setActiveDescendant(Object any)46     protected void setActiveDescendant(Object any) {
47         javax.accessibility.Accessible descendant = null;
48         try {
49             if (AnyConverter.isObject(any)) {
50                 XAccessible unoAccessible = (XAccessible) AnyConverter.toObject(
51                     AccessibleObjectFactory.XAccessibleType, any);
52                 if (unoAccessible != null) {
53                     // FIXME: have to handle non transient objects here ..
54                     descendant = new ListItem(unoAccessible);
55                     if (Build.DEBUG) {
56                         try {
57                             if (Build.DEBUG) {
58                                 System.err.println("[List] retrieved active descendant event: new descendant is " +
59                                     unoAccessible.getAccessibleContext().getAccessibleName());
60                             }
61                         } catch (java.lang.NullPointerException e) {
62                             System.err.println("*** ERROR *** new active descendant not accessible");
63                         }
64                     }
65                 }
66             }
67             setActiveDescendant(descendant);
68         } catch (com.sun.star.lang.IllegalArgumentException e) {
69         }
70     }
71 
add(XAccessible unoAccessible)72     protected void add(XAccessible unoAccessible) {
73         if (unoAccessible != null) {
74             ListItem item = new ListItem(unoAccessible);
75             // The AccessBridge for Windows expects an instance of AccessibleContext
76             // as parameters
77             firePropertyChange(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
78                 null, item.getAccessibleContext());
79         }
80     }
81 
remove(XAccessible unoAccessible)82     protected void remove(XAccessible unoAccessible) {
83         if (unoAccessible != null) {
84             ListItem item = new ListItem(unoAccessible);
85             // The AccessBridge for Windows expects an instance of AccessibleContext
86             // as parameters
87             firePropertyChange(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
88                 item.getAccessibleContext(), null);
89         }
90     }
91 
add(Object any)92     protected void add(Object any) {
93         try {
94             add((XAccessible) AnyConverter.toObject(AccessibleObjectFactory.XAccessibleType, any));
95         } catch (com.sun.star.lang.IllegalArgumentException e) {
96         }
97     }
98 
remove(Object any)99     protected void remove(Object any) {
100         try {
101             remove((XAccessible) AnyConverter.toObject(AccessibleObjectFactory.XAccessibleType, any));
102         } catch (com.sun.star.lang.IllegalArgumentException e) {
103         }
104     }
105 
106     /**
107     * Update the proxy objects appropriatly on property change events
108     */
109     protected class AccessibleListListener extends AccessibleDescendantManagerListener {
110 
AccessibleListListener()111         protected AccessibleListListener() {
112             super();
113         }
114 
115         /** Called by OpenOffice process to notify property changes */
notifyEvent(AccessibleEventObject event)116         public void notifyEvent(AccessibleEventObject event) {
117             switch (event.EventId) {
118                 case AccessibleEventId.ACTIVE_DESCENDANT_CHANGED:
119                     setActiveDescendant(event.NewValue);
120                     break;
121                 case AccessibleEventId.CHILD:
122                     if (AnyConverter.isObject(event.OldValue)) {
123                         remove(event.OldValue);
124                     }
125                     if (AnyConverter.isObject(event.NewValue)) {
126                         add(event.NewValue);
127                     }
128                     break;
129                 case AccessibleEventId.INVALIDATE_ALL_CHILDREN:
130                     // Since List items a transient a child events are mostly used
131                     // to attach/detach listeners, it is save to ignore it here
132                     break;
133                 default:
134                     super.notifyEvent(event);
135             }
136         }
137     }
138 
createEventListener()139     protected XAccessibleEventListener createEventListener() {
140         return new AccessibleListListener();
141     }
142 
143     /** Creates the AccessibleContext associated with this object */
createAccessibleContext()144     public javax.accessibility.AccessibleContext createAccessibleContext() {
145         return new AccessibleList();
146     }
147 
148     protected class AccessibleList extends AccessibleDescendantManager {
149 
150         /** Gets the role of this object */
getAccessibleRole()151         public javax.accessibility.AccessibleRole getAccessibleRole() {
152             return javax.accessibility.AccessibleRole.LIST;
153         }
154 
155         /** Returns the specified Accessible child of the object */
getAccessibleChild(int i)156         public javax.accessibility.Accessible getAccessibleChild(int i) {
157             javax.accessibility.Accessible child = null;
158             try {
159                 XAccessible xAccessible = unoAccessibleContext.getAccessibleChild(i);
160                 if (xAccessible != null) {
161                     // Re-use the active descandant wrapper if possible
162                     javax.accessibility.Accessible activeDescendant = List.this.activeDescendant;
163                     if ((activeDescendant instanceof ListItem) && xAccessible.equals(((ListItem) activeDescendant).unoAccessible)) {
164                         child = activeDescendant;
165                     } else {
166                         child = new ListItem(xAccessible);
167                     }
168                 }
169             } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
170             } catch (com.sun.star.uno.RuntimeException e) {
171             }
172             return child;
173         }
174 
175         /*
176          * AccessibleComponent
177          */
178 
179         /** Returns the Accessible child, if one exists, contained at the local coordinate Point */
getAccessibleAt(java.awt.Point p)180         public javax.accessibility.Accessible getAccessibleAt(java.awt.Point p) {
181             javax.accessibility.Accessible child = null;
182             try {
183                 XAccessible xAccessible = unoAccessibleComponent.getAccessibleAtPoint(new com.sun.star.awt.Point(p.x, p.y));
184                 if (xAccessible != null) {
185                     // Re-use the active descandant wrapper if possible
186                     javax.accessibility.Accessible activeDescendant = List.this.activeDescendant;
187                     if ((activeDescendant instanceof ListItem) && xAccessible.equals(((ListItem) activeDescendant).unoAccessible)) {
188                         child = activeDescendant;
189                     } else {
190                         child = new ListItem(xAccessible);
191                     }
192                 }
193                 return child;
194             } catch (com.sun.star.uno.RuntimeException e) {
195                 return null;
196             }
197         }
198 
199         /*
200         * AccessibleSelection
201         */
202 
203         /** Returns an Accessible representing the specified selected child of the object */
getAccessibleSelection(int i)204         public javax.accessibility.Accessible getAccessibleSelection(int i) {
205             javax.accessibility.Accessible child = null;
206             try {
207                 XAccessible xAccessible = unoAccessibleSelection.getSelectedAccessibleChild(i);
208                 if (xAccessible != null) {
209                     // Re-use the active descandant wrapper if possible
210                     javax.accessibility.Accessible activeDescendant = List.this.activeDescendant;
211                     if ((activeDescendant instanceof ListItem) && xAccessible.equals(((ListItem) activeDescendant).unoAccessible)) {
212                         child = activeDescendant;
213                     } else {
214                         child = new ListItem(xAccessible);
215                     }
216                 } else if (Build.DEBUG) {
217                     System.out.println(i + "th selected child is not accessible");
218                 }
219             } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
220                 if (Build.DEBUG) {
221                     System.err.println("IndexOutOfBoundsException caught for AccessibleList.getAccessibleSelection(" + i + ")");
222                 }
223             } catch (com.sun.star.uno.RuntimeException e) {
224             }
225             return child;
226         }
227     }
228 
229     class ListItem extends java.awt.Component implements javax.accessibility.Accessible {
230 
231         protected XAccessible unoAccessible;
232 
ListItem(XAccessible xAccessible)233         public ListItem(XAccessible xAccessible) {
234             unoAccessible = xAccessible;
235         }
236 
create(Object[] targetSet)237         public Object[] create(Object[] targetSet) {
238             try {
239                 java.util.ArrayList list = new java.util.ArrayList(targetSet.length);
240                 for (int i=0; i < targetSet.length; i++) {
241                     XAccessible xAccessible = (XAccessible) UnoRuntime.queryInterface(
242                         XAccessible.class, targetSet[i]);
243                     if (xAccessible != null) {
244                         list.add(new ListItem(xAccessible));
245                     }
246                 }
247                 list.trimToSize();
248                 return list.toArray();
249             } catch (com.sun.star.uno.RuntimeException e) {
250                 return null;
251             }
252         }
253 
254         javax.accessibility.AccessibleContext accessibleContext = null;
255 
256         /** Returns the AccessibleContext associated with this object */
getAccessibleContext()257         public javax.accessibility.AccessibleContext getAccessibleContext() {
258             if (accessibleContext == null) {
259                 try {
260                     XAccessibleContext xAccessibleContext = unoAccessible.getAccessibleContext();
261                     if (xAccessibleContext != null) {
262                         javax.accessibility.AccessibleContext ac = new AccessibleListItem(xAccessibleContext);
263                         if (ac != null) {
264                             ac.setAccessibleParent(List.this);
265                             accessibleContext = ac;
266                         }
267                         AccessibleStateAdapter.setComponentState(this, xAccessibleContext.getAccessibleStateSet());
268                     }
269                 } catch (com.sun.star.uno.RuntimeException e) {
270                 }
271             }
272             return accessibleContext;
273         }
274 
275         protected class AccessibleListItem extends javax.accessibility.AccessibleContext {
276 
277             XAccessibleContext unoAccessibleContext;
278 
AccessibleListItem(XAccessibleContext xAccessibleContext)279             public AccessibleListItem(XAccessibleContext xAccessibleContext) {
280                 unoAccessibleContext = xAccessibleContext;
281             }
282 
283             /** Returns the accessible name of this object */
getAccessibleName()284             public String getAccessibleName() {
285                 try {
286                     return unoAccessibleContext.getAccessibleName();
287                 } catch (com.sun.star.uno.RuntimeException e) {
288                     return null;
289                 }
290             }
291 
292             /** Sets the accessible name of this object */
setAccessibleName(String name)293             public void setAccessibleName(String name) {
294                 // Not supported
295             }
296 
297             /** Returns the accessible name of this object */
getAccessibleDescription()298             public String getAccessibleDescription() {
299                 try {
300                     return unoAccessibleContext.getAccessibleDescription();
301                 } catch (com.sun.star.uno.RuntimeException e) {
302                     return null;
303                 }
304             }
305 
306             /** Sets the accessible name of this object */
setAccessibleDescription(String name)307             public void setAccessibleDescription(String name) {
308                 // Not supported
309             }
310 
311             /** Returns the accessible role of this object */
getAccessibleRole()312             public javax.accessibility.AccessibleRole getAccessibleRole() {
313                 try {
314                     javax.accessibility.AccessibleRole role = AccessibleRoleAdapter.getAccessibleRole(
315                         unoAccessibleContext.getAccessibleRole());
316                     return (role != null) ? role : javax.accessibility.AccessibleRole.LABEL;
317                 } catch(com.sun.star.uno.RuntimeException e) {
318                     return null;
319                 }
320             }
321 
322             /** Gets the locale of the component */
getLocale()323             public java.util.Locale getLocale() throws java.awt.IllegalComponentStateException {
324                 try {
325                     com.sun.star.lang.Locale unoLocale = unoAccessibleContext.getLocale();
326                     return new java.util.Locale(unoLocale.Language, unoLocale.Country);
327                 } catch (IllegalAccessibleComponentStateException e) {
328                     throw new java.awt.IllegalComponentStateException(e.getMessage());
329                 } catch (com.sun.star.uno.RuntimeException e) {
330                     return List.this.getLocale();
331                 }
332             }
333 
334             /** Gets the 0-based index of this object in its accessible parent */
getAccessibleIndexInParent()335             public int getAccessibleIndexInParent() {
336                 try {
337                     return unoAccessibleContext.getAccessibleIndexInParent();
338                 } catch (com.sun.star.uno.RuntimeException e) {
339                     return -1;
340                 }
341             }
342 
343             /** Returns the number of accessible children of the object. */
getAccessibleChildrenCount()344             public int getAccessibleChildrenCount() {
345                 try {
346                     return unoAccessibleContext.getAccessibleChildCount();
347                 } catch (com.sun.star.uno.RuntimeException e) {
348                     return 0;
349                 }
350             }
351 
352             /** Returns the specified Accessible child of the object. */
getAccessibleChild(int i)353             public javax.accessibility.Accessible getAccessibleChild(int i) {
354                 javax.accessibility.Accessible child = null;
355                 try {
356                     XAccessible xAccessible = unoAccessibleContext.getAccessibleChild(i);
357                     // Re-use the active descandant wrapper if possible
358                     javax.accessibility.Accessible activeDescendant = List.this.activeDescendant;
359                     if ((activeDescendant instanceof ListItem) && ((ListItem) activeDescendant).unoAccessible.equals(xAccessible)) {
360                         child = activeDescendant;
361                     } else if (xAccessible != null) {
362                         child = new ListItem(xAccessible);
363                     }
364                 } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
365                 } catch (com.sun.star.uno.RuntimeException e) {
366                 }
367                 return child;
368             }
369 
370             /** Returns the state set of this object */
getAccessibleStateSet()371             public javax.accessibility.AccessibleStateSet getAccessibleStateSet() {
372                 try {
373                     return AccessibleStateAdapter.getAccessibleStateSet(ListItem.this,
374                         unoAccessibleContext.getAccessibleStateSet());
375                 } catch (com.sun.star.uno.RuntimeException e) {
376                     return AccessibleStateAdapter.getDefunctStateSet();
377                 }
378             }
379 
380             /** Gets the AccessibleComponent associated with this object that has a graphical representation */
getAccessibleComponent()381             public javax.accessibility.AccessibleComponent getAccessibleComponent() {
382                 try {
383                     XAccessibleComponent unoAccessibleComponent = (XAccessibleComponent)
384                         UnoRuntime.queryInterface(XAccessibleComponent.class, unoAccessibleContext);
385                     return (unoAccessibleComponent != null) ?
386                         new AccessibleComponentImpl(unoAccessibleComponent) : null;
387                 } catch (com.sun.star.uno.RuntimeException e) {
388                     return null;
389                 }
390             }
391 
392             /** Gets the AccessibleAction associated with this object that has a graphical representation */
getAccessibleAction()393             public javax.accessibility.AccessibleAction getAccessibleAction() {
394                 try {
395                     XAccessibleAction unoAccessibleAction = (XAccessibleAction)
396                         UnoRuntime.queryInterface(XAccessibleAction.class, unoAccessibleContext);
397                     return (unoAccessibleAction != null) ?
398                         new AccessibleActionImpl(unoAccessibleAction) : null;
399                 } catch (com.sun.star.uno.RuntimeException e) {
400                     return null;
401                 }
402             }
403 
404             /** Gets the AccessibleText associated with this object that has a graphical representation */
getAccessibleText()405             public javax.accessibility.AccessibleText getAccessibleText() {
406 
407                 if (disposed)
408                     return null;
409 
410                 try {
411                     XAccessibleText unoAccessibleText = (XAccessibleText)
412                         UnoRuntime.queryInterface(XAccessibleText.class, unoAccessibleContext);
413                     return (unoAccessibleText != null) ?
414                         new AccessibleTextImpl(unoAccessibleText) : null;
415                 } catch (com.sun.star.uno.RuntimeException e) {
416                     return null;
417                 }
418             }
419 
420             /** Gets the AccessibleValue associated with this object that has a graphical representation */
getAccessibleValue()421             public javax.accessibility.AccessibleValue getAccessibleValue() {
422                 try {
423                     XAccessibleValue unoAccessibleValue = (XAccessibleValue)
424                         UnoRuntime.queryInterface(XAccessibleValue.class, unoAccessibleContext);
425                     return (unoAccessibleValue != null) ?
426                         new AccessibleValueImpl(unoAccessibleValue) : null;
427                 } catch (com.sun.star.uno.RuntimeException e) {
428                     return null;
429                 }
430             }
431 
432             /** Gets the AccessibleText associated with this object presenting text on the display */
getAccessibleIcon()433             public javax.accessibility.AccessibleIcon[] getAccessibleIcon() {
434                 try {
435                     XAccessibleImage unoAccessibleImage = (XAccessibleImage)
436                         UnoRuntime.queryInterface(XAccessibleImage.class, unoAccessibleContext);
437                     if (unoAccessibleImage != null) {
438                         javax.accessibility.AccessibleIcon[] icons = { new AccessibleIconImpl(unoAccessibleImage) };
439                         return icons;
440                     }
441                 } catch (com.sun.star.uno.RuntimeException e) {
442                 }
443                 return null;
444             }
445         }
446     }
447 }
448 
449